Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ repos:
- id: check-yaml
- id: check-json
- id: check-toml
- id: check-docstring-first
# - id: check-docstring-first
- id: check-case-conflict
- id: trailing-whitespace
- id: end-of-file-fixer
Expand Down
1 change: 1 addition & 0 deletions docs/changes/460.new.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Implemented new source profile and SED serializers to support structured handling of source profile data in GPP requests.
62 changes: 48 additions & 14 deletions src/goats_tom/api_views/gpp/toos.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,24 @@
ElevationRangeInput,
ExposureTimeModeInput,
ObservationPropertiesInput,
SourceProfileInput,
TargetPropertiesInput,
)
from rest_framework import permissions, status
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet, mixins

from goats_tom.serializers import (
GPPBrightnessesSerializer,
GPPElevationRangeSerializer,
GPPExposureModeSerializer,
GPPInstrumentRegistry,
from goats_tom.serializers.gpp import (
BrightnessesSerializer,
ElevationRangeSerializer,
ExposureModeSerializer,
InstrumentRegistry,
SourceProfileSerializer,
)

# Import type for instrument input models.
from goats_tom.serializers.gpp.instruments import GPPInstrumentInputModelInstance
from goats_tom.serializers.gpp.instruments import InstrumentInputModelInstance


class GPPTooViewSet(GenericViewSet, mixins.CreateModelMixin):
Expand Down Expand Up @@ -62,23 +64,55 @@ def create(self, request: Request, *args, **kwargs) -> Response:
)
credentials = request.user.gpplogin

# FIXME: Remove debug print statement after finalizing implementation all PRs.
print(request.data)
try:
# Setup client to communicate with GPP.
_ = GPPClient(url=settings.GPP_URL, token=credentials.token)

# TODO: Format brightnesses from request data.
# TODO: Format exposure mode from request data.
# TODO: Format elevation range from request data.
# TODO: Format instrument from request data.
# TODO: Format source profile from request data.

return Response({"detail": "Not yet implemented."})

except Exception as e:
return Response({"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST)

def _format_source_profile_properties(
self, data: dict[str, Any]
) -> SourceProfileInput | None:
"""
Format source profile properties from the request data.

Parameters
----------
data : dict[str, Any]
The request data containing source profile fields.

Returns
-------
SourceProfileInput | None
A SourceProfileInput instance or ``None`` if no source profile is
provided.

Raises
------
serializers.ValidationError
If any error occurs during parsing or validation of source profile values.
"""
source_profile_serializer = SourceProfileSerializer(data=data)
source_profile_serializer.is_valid(raise_exception=True)
return (
SourceProfileInput(**source_profile_serializer.validated_data)
if source_profile_serializer.validated_data
else None
)

def _format_instrument_properties(
self, data: dict[str, Any]
) -> GPPInstrumentInputModelInstance | None:
) -> InstrumentInputModelInstance | None:
"""Format instrument-specific properties from the request data.

Parameters
Expand All @@ -88,7 +122,7 @@ def _format_instrument_properties(

Returns
-------
GPPInstrumentInputModelInstance | None
InstrumentInputModelInstance | None
An instrument input model instance or ``None`` if no instrument is
provided.

Expand All @@ -97,10 +131,10 @@ def _format_instrument_properties(
serializers.ValidationError
If any error occurs during parsing or validation of instrument values.
"""
instrument_serializer_class = GPPInstrumentRegistry.get_serializer(data)
instrument_serializer_class = InstrumentRegistry.get_serializer(data)
instrument = instrument_serializer_class(data=data)
instrument.is_valid(raise_exception=True)
instrument_input_model_class = GPPInstrumentRegistry.get_input_model(data)
instrument_input_model_class = InstrumentRegistry.get_input_model(data)

return (
instrument_input_model_class(**instrument.validated_data)
Expand Down Expand Up @@ -130,7 +164,7 @@ def _format_elevation_range_properties(
If any error occurs during parsing or validation of elevation range values.
"""

elevation_range = GPPElevationRangeSerializer(data=data)
elevation_range = ElevationRangeSerializer(data=data)
elevation_range.is_valid(raise_exception=True)
return (
ElevationRangeInput(**elevation_range.validated_data)
Expand Down Expand Up @@ -159,7 +193,7 @@ def _format_brightnesses_properties(
serializers.ValidationError
If any error occurs during parsing or validation of brightness values.
"""
brightnesses = GPPBrightnessesSerializer(data=data)
brightnesses = BrightnessesSerializer(data=data)
brightnesses.is_valid(raise_exception=True)
brightnesses_data = brightnesses.validated_data.get("brightnesses", None)
return (
Expand Down Expand Up @@ -190,7 +224,7 @@ def _format_exposure_mode_properties(
If any error occurs during parsing or validation of exposure mode values.
"""

exposure_mode = GPPExposureModeSerializer(data=data)
exposure_mode = ExposureModeSerializer(data=data)
exposure_mode.is_valid(raise_exception=True)
return (
ExposureTimeModeInput(**exposure_mode.validated_data)
Expand Down
10 changes: 0 additions & 10 deletions src/goats_tom/serializers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,6 @@
DRAGONSReduceUpdateSerializer,
)
from .dragons_run import DRAGONSRunFilterSerializer, DRAGONSRunSerializer
from .gpp import (
GPPBrightnessesSerializer,
GPPElevationRangeSerializer,
GPPExposureModeSerializer,
GPPInstrumentRegistry,
)
from .header import HeaderSerializer
from .recipes_module import RecipesModuleSerializer
from .run_processor import RunProcessorSerializer
Expand All @@ -43,8 +37,4 @@
"Antares2GoatsSerializer",
"HeaderSerializer",
"AstroDatalabSerializer",
"GPPBrightnessesSerializer",
"GPPExposureModeSerializer",
"GPPElevationRangeSerializer",
"GPPInstrumentRegistry",
]
18 changes: 10 additions & 8 deletions src/goats_tom/serializers/gpp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from .brightnesses import GPPBrightnessesSerializer
from .elevation_range import GPPElevationRangeSerializer
from .exposure_mode import GPPExposureModeSerializer
from .instruments import GPPInstrumentRegistry
from .brightnesses import BrightnessesSerializer
from .elevation_range import ElevationRangeSerializer
from .exposure_mode import ExposureModeSerializer
from .instruments import InstrumentRegistry
from .source_profile import SourceProfileSerializer

__all__ = [
"GPPBrightnessesSerializer",
"GPPExposureModeSerializer",
"GPPElevationRangeSerializer",
"GPPInstrumentRegistry",
"BrightnessesSerializer",
"ExposureModeSerializer",
"ElevationRangeSerializer",
"SourceProfileSerializer",
"InstrumentRegistry",
]
4 changes: 2 additions & 2 deletions src/goats_tom/serializers/gpp/brightnesses.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__all__ = ["GPPBrightnessesSerializer"]
__all__ = ["BrightnessesSerializer"]

import re
from typing import Any
Expand All @@ -24,7 +24,7 @@ class BrightnessSerializer(serializers.Serializer):
error = serializers.FloatField(required=False, allow_null=True)


class GPPBrightnessesSerializer(serializers.Serializer):
class BrightnessesSerializer(serializers.Serializer):
"""Serializer to parse and validate brightness entries from flat form data."""

brightnesses = serializers.ListField(
Expand Down
4 changes: 2 additions & 2 deletions src/goats_tom/serializers/gpp/elevation_range.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__all__ = ["GPPElevationRangeSerializer"]
__all__ = ["ElevationRangeSerializer"]

from typing import Any

Expand All @@ -7,7 +7,7 @@
from .utils import normalize


class GPPElevationRangeSerializer(serializers.Serializer):
class ElevationRangeSerializer(serializers.Serializer):
"""Serializer to parse and validate elevation range from flat form data."""

elevationRangeSelect = serializers.ChoiceField(choices=["Air Mass", "Hour Angle"])
Expand Down
4 changes: 2 additions & 2 deletions src/goats_tom/serializers/gpp/exposure_mode.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__all__ = ["GPPExposureModeSerializer"]
__all__ = ["ExposureModeSerializer"]

from typing import Any

Expand Down Expand Up @@ -34,7 +34,7 @@ class TimeAndCountExposureSerializer(serializers.Serializer):
at = WavelengthSerializer()


class GPPExposureModeSerializer(serializers.Serializer):
class ExposureModeSerializer(serializers.Serializer):
"""Serializer to parse and validate exposure mode from flat form data."""

exposureModeSelect = serializers.ChoiceField(
Expand Down
20 changes: 10 additions & 10 deletions src/goats_tom/serializers/gpp/instruments/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from .gmos_north_long_slit import GPPGMOSNorthLongSlitSerializer
from .gmos_south_long_slit import GPPGMOSSouthLongSlitSerializer
from .gmos_north_long_slit import GMOSNorthLongSlitSerializer
from .gmos_south_long_slit import GMOSSouthLongSlitSerializer
from .registry import (
GPPInstrumentInputModelClass,
GPPInstrumentInputModelInstance,
GPPInstrumentRegistry,
InstrumentInputModelClass,
InstrumentInputModelInstance,
InstrumentRegistry,
)

__all__ = [
"GPPGMOSNorthLongSlitSerializer",
"GPPGMOSSouthLongSlitSerializer",
"GPPInstrumentRegistry",
"GPPInstrumentInputModelClass",
"GPPInstrumentInputModelInstance",
"GMOSNorthLongSlitSerializer",
"GMOSSouthLongSlitSerializer",
"InstrumentRegistry",
"InstrumentInputModelClass",
"InstrumentInputModelInstance",
]
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
differences.
"""

__all__ = ["GPPGMOSNorthLongSlitSerializer"]
__all__ = ["GMOSNorthLongSlitSerializer"]

from typing import Any

Expand All @@ -13,7 +13,7 @@
from goats_tom.serializers.gpp.utils import normalize, parse_comma_separated_floats


class GPPGMOSNorthLongSlitSerializer(serializers.Serializer):
class GMOSNorthLongSlitSerializer(serializers.Serializer):
"""Serializer for GMOS-North long slit input data."""

centralWavelengthInput = serializers.CharField(required=False, allow_blank=True)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
differences.
"""

__all__ = ["GPPGMOSSouthLongSlitSerializer"]
__all__ = ["GMOSSouthLongSlitSerializer"]

from typing import Any

Expand All @@ -13,7 +13,7 @@
from goats_tom.serializers.gpp.utils import normalize, parse_comma_separated_floats


class GPPGMOSSouthLongSlitSerializer(serializers.Serializer):
class GMOSSouthLongSlitSerializer(serializers.Serializer):
"""Serializer for GMOS-South long slit input data."""

centralWavelengthInput = serializers.CharField(required=False, allow_blank=True)
Expand Down
30 changes: 13 additions & 17 deletions src/goats_tom/serializers/gpp/instruments/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
"""

__all__ = [
"GPPInstrumentRegistry",
"GPPInstrumentInputModelInstance",
"GPPInstrumentInputModelClass",
"InstrumentRegistry",
"InstrumentInputModelInstance",
"InstrumentInputModelClass",
]

from gpp_client.api.enums import ObservingModeType
Expand All @@ -16,40 +16,38 @@
from rest_framework import serializers
from rest_framework.exceptions import ValidationError

from .gmos_north_long_slit import GPPGMOSNorthLongSlitSerializer
from .gmos_south_long_slit import GPPGMOSSouthLongSlitSerializer
from .gmos_north_long_slit import GMOSNorthLongSlitSerializer
from .gmos_south_long_slit import GMOSSouthLongSlitSerializer

GPPInstrumentInputModelClass = (
type[GmosNorthLongSlitInput] | type[GmosSouthLongSlitInput]
)
InstrumentInputModelClass = type[GmosNorthLongSlitInput] | type[GmosSouthLongSlitInput]
"""
Type alias for instrument input model classes. Must be updated when new instruments
are added.
"""

GPPInstrumentInputModelInstance = GmosNorthLongSlitInput | GmosSouthLongSlitInput
InstrumentInputModelInstance = GmosNorthLongSlitInput | GmosSouthLongSlitInput
"""
Type alias for instrument input model instances. Must be updated when new
instruments are added.
"""


class GPPInstrumentRegistry:
class InstrumentRegistry:
"""
Central registry for instrument serializers and GPP input model mappings.
"""

_registry: dict[
str, tuple[type[serializers.Serializer], GPPInstrumentInputModelClass]
str, tuple[type[serializers.Serializer], InstrumentInputModelClass]
] = {
# GMOS South Long Slit.
ObservingModeType.GMOS_SOUTH_LONG_SLIT.value: (
GPPGMOSSouthLongSlitSerializer,
GMOSSouthLongSlitSerializer,
GmosSouthLongSlitInput,
),
# GMOS North Long Slit.
ObservingModeType.GMOS_NORTH_LONG_SLIT.value: (
GPPGMOSNorthLongSlitSerializer,
GMOSNorthLongSlitSerializer,
GmosNorthLongSlitInput,
),
}
Expand Down Expand Up @@ -84,9 +82,7 @@ def get_serializer(
raise ValidationError(f"Unsupported instrument type: {lookup_key}")

@classmethod
def get_input_model(
cls, key: str | ObservingModeType
) -> GPPInstrumentInputModelClass:
def get_input_model(cls, key: str | ObservingModeType) -> InstrumentInputModelClass:
"""
Retrieve the input model class for a given instrument key.
Expand All @@ -97,7 +93,7 @@ def get_input_model(
Returns
-------
GPPInstrumentInputModelClass
InstrumentInputModelClass
The corresponding input model class.
Raises
Expand Down
3 changes: 3 additions & 0 deletions src/goats_tom/serializers/gpp/source_profile/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .source_profile import SourceProfileSerializer

__all__ = ["SourceProfileSerializer"]
4 changes: 4 additions & 0 deletions src/goats_tom/serializers/gpp/source_profile/seds/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .black_body import BlackBodySerializer
from .registry import SEDRegistry, SEDType

__all__ = ["BlackBodySerializer", "SEDRegistry", "SEDType"]
Loading