===================== Observing Constraints ===================== Overview ======== The Observation Scheduling Tool (OST) validates observing constraints to ensure that scheduled observations are feasible and meet operational requirements. All constraints are evaluated simultaneously at the observation start time, and violations are reported with detailed metadata. Constraint Evaluation ===================== The constraint validation system evaluates all constraints in a single pass and returns: - **OST-000**: All constraints passed (success) - **OST-001 to OST-008**: Specific constraint violations (failure) Constraints are categorized as: - **Mandatory**: Must pass for observation to proceed (OST-001, OST-005, OST-006) - **Non-Mandatory**: Warnings that can be overridden by user confirmation (OST-002, OST-003, OST-004, OST-007) Constraint Codes ================ OST-000: All Constraints Passed ------------------------------- **Status**: Success **Description**: All observing constraints are satisfied at the observation start time. **Metadata Returned**: - ``sun_separation``: Angular separation from Sun in degrees - ``moon_separation``: Angular separation from Moon in degrees - ``jupiter_separation``: Angular separation from Jupiter in degrees - ``current_elevation``: Target elevation at observation time in degrees - ``current_lst``: Local Sidereal Time at observation time in hours - ``observation_time``: ISO 8601 formatted observation start time - ``telescope``: Telescope identifier (``mid`` or ``low``) **Example Response**: .. code-block:: json { "success": true, "violations": [], "observing_constraints": { "sun_separation": 45.2, "moon_separation": 62.1, "jupiter_separation": 78.5, "current_elevation": 35.4, "current_lst": 14.5, "observation_time": "2024-06-01T12:00:00", "telescope": "mid" } } OST-001: Target Not Visible (Dish Elevation Limit) --------------------------------------------------- **Status**: Mandatory violation **Description**: Target elevation is below the dish elevation limit. This is a blocking constraint that prevents observation. **Constraint Type**: Dish Elevation Limit **Default Limit**: 5.0 degrees (configurable per subarray definition via telemodel) **Applies To**: Both telescopes i.e. SKA-MID and SKA-LOW **Violation Metadata**: - ``current_elevation``: Actual target elevation in degrees - ``dish_limit``: Minimum required elevation in degrees - ``telescope``: Telescope identifier - ``observation_time``: ISO 8601 formatted observation start time **Example Violation**: .. code-block:: json { "code": "OST-001", "message": "Target not visible: elevation -15.0° is below the dish elevation limit of 5.0°", "values": { "current_elevation": "-15.0°", "dish_limit": "5.0°", "telescope": "ska_mid", "observation_time": "2024-06-01T12:00:00" } } **Window Period Support**: If a ``window_period_sec`` is specified in the queue item, the system will automatically retry at ``observation_start_time + window_period_sec`` if OST-001 fails at the original time. OST-002: Sun Separation Constraint ---------------------------------- **Status**: Non-Mandatory Constraint **Description**: Target is too close to the Sun. This constraint protects sensitive receiver equipment from solar radiation. **Constraint Type**: Separation Constraint **Default Minimum Separation**: 30 degrees (configurable via SBD) **Applies To**: Both SKA-MID and SKA-LOW **Violation Metadata**: - ``current_degrees``: Actual angular separation from Sun in degrees - ``min_required``: Minimum required separation in degrees **Example Violation**: .. code-block:: json { "code": "OST-002", "message": "Sun separation not met. Required ≥ 30.0°, current 15.5°", "values": { "min_required": 30.0, "current_degrees": 15.5 } } **Configuration**: Specified in SBD under ``observing_constraints.sun_separation.min`` OST-003: Moon Separation Constraint ----------------------------------- **Status**: Non-Mandatory Constraint **Description**: Target is too close to the Moon. This constraint reduces radio frequency interference from lunar reflections. **Constraint Type**: Separation Constraint **Default Minimum Separation**: 20 degrees (configurable via SBD) **Applies To**: Both SKA-MID and SKA-LOW **Violation Metadata**: - ``current_degrees``: Actual angular separation from Moon in degrees - ``min_required``: Minimum required separation in degrees **Example Violation**: .. code-block:: json { "code": "OST-003", "message": "Moon separation not met. Required ≥ 20.0°, current 12.3°", "values": { "min_required": 20.0, "current_degrees": 12.3 } } **Configuration**: Specified in SBD under ``observing_constraints.moon_separation.min`` OST-004: Jupiter Separation Constraint -------------------------------------- **Status**: Non-Mandatory Constraint **Description**: Target is too close to Jupiter. This constraint reduces radio frequency interference from Jupiter's strong emissions. **Constraint Type**: Separation Constraint **Default Minimum Separation**: 15 degrees (configurable via SBD) **Applies To**: Both SKA-MID and SKA-LOW **Violation Metadata**: - ``current_degrees``: Actual angular separation from Jupiter in degrees - ``min_required``: Minimum required separation in degrees **Example Violation**: .. code-block:: json { "code": "OST-004", "message": "Jupiter separation not met. Required ≥ 15.0°, current 8.7°", "values": { "min_required": 15.0, "current_degrees": 8.7 } } **Configuration**: Specified in SBD under ``observing_constraints.jupiter_separation.min`` OST-005: Minimum Elevation Constraint ------------------------------------- **Status**: Mandatory Constraint **Description**: Target elevation is below the specified minimum elevation window. This is a blocking constraint — the telescope cannot physically point below the science-defined minimum elevation. **Constraint Type**: Altitude Window Constraint **Default Minimum**: 0 degrees (configurable via SBD) **Applies To**: Both SKA-MID and SKA-LOW **Violation Metadata**: - ``current_elevation``: Actual target elevation in degrees - ``min_required``: Minimum required elevation in degrees **Example Violation**: .. code-block:: json { "code": "OST-005", "message": "Elevation constraint not met. Required ≥ 30.0°, current 15.0°", "values": { "current_elevation": "15.0°", "min_required": "30.0°" } } **Configuration**: Specified in SBD under ``observing_constraints.altitude.min`` **Note**: When multiple altitude violations exist, the stricter (higher) minimum is reported. OST-006: Maximum Elevation Constraint ------------------------------------- **Status**: Mandatory Constraint **Description**: Target elevation exceeds the specified maximum elevation window. This is a blocking constraint — observing at too high an elevation risks cable wrap and atmospheric path issues. **Constraint Type**: Altitude Window Constraint **Default Maximum**: 90 degrees (configurable via SBD) **Applies To**: Both SKA-MID and SKA-LOW **Violation Metadata**: - ``current_elevation``: Actual target elevation in degrees - ``max_allowed``: Maximum allowed elevation in degrees **Example Violation**: .. code-block:: json { "code": "OST-006", "message": "Maximum elevation exceeded. Allowed ≤ 80.0°, current 85.0°", "values": { "current_elevation": "85.0°", "max_allowed": "80.0°" } } **Configuration**: Specified in SBD under ``observing_constraints.altitude.max`` **Note**: When multiple altitude violations exist, the stricter (lower) maximum is reported. OST-007: LST Window Constraint ------------------------------ **Status**: Non-Mandatory Constraint **Description**: Observation time falls outside the specified Local Sidereal Time (LST) window. **Constraint Type**: LST Window Constraint **Default Window**: No restriction (configurable via SBD) **Applies To**: Both SKA-MID and SKA-LOW **Violation Metadata**: - ``current_lst``: Actual LST at observation time in hours (0-24) - ``window_start``: LST window start in hours - ``window_end``: LST window end in hours **Example Violation**: .. code-block:: json { "code": "OST-007", "message": "LST constraint not met. Allowed window [8.00h, 16.00h], current LST 20.50h", "values": { "window_start": "8.00h", "window_end": "16.00h", "current_lst": "20.50h" } } **Configuration**: Specified in SBD under ``observing_constraints.lst`` **Wrapping Windows**: LST windows can wrap around midnight (e.g., 22h to 2h). Constraint Configuration in SBD =============================== Constraints are specified in the Scheduling Block Definition (SBD) under the ``observing_constraints`` section: .. code-block:: json { "observing_constraints": { "sun_separation": { "min": { "value": 30.0, "unit": "deg" } }, "moon_separation": { "min": { "value": 20.0, "unit": "deg" } }, "jupiter_separation": { "min": { "value": 15.0, "unit": "deg" } }, "altitude": { "min": { "value": 30.0, "unit": "deg" }, "max": { "value": 80.0, "unit": "deg" } }, "lst": { "start": { "value": 8.0, "unit": "hourangle" }, "end": { "value": 16.0, "unit": "hourangle" } }, "a_team_separation": { "min": { "value": 20.0, "unit": "deg" } } } } Window Period Support ===================== Queue items can specify a ``window_period_sec`` to allow the system to retry observations if OST-001 (target not visible) fails at the original observation start time. **Behavior**: 1. Check all constraints at ``observation_start_time`` 2. If OST-001 fails and ``window_period_sec > 0``: - Retry at ``observation_start_time + window_period_sec`` - If OST-001 passes at extended time, update ``observation_start_time`` to extended time - Continue with non-mandatory constraint checks at extended time 3. If OST-001 still fails at extended time, return failure **Example Queue Item**: .. code-block:: json { "id": "item_1", "sbd_fk": "sbd_123", "observation_start_time": "2024-06-01T12:00:00Z", "window_period_sec": 3600 } **Response with Extended Time**: .. code-block:: json { "success": true, "violations": [], "observing_constraints": { "used_extended_time": true, "sun_separation": 45.2, "moon_separation": 62.1, "jupiter_separation": 78.5, "current_elevation": 35.4, "current_lst": 14.5, "observation_time": "2024-06-01T13:00:00", "telescope": "mid" } } Non-Mandatory Constraint Override ================================= Users can override non-mandatory constraint violations by setting ``user_confirmed_non_mandatory: true`` when updating a queue item. **Behavior**: 1. If only non-mandatory constraints fail (OST-002, OST-003, OST-004, OST-007) and ``user_confirmed_non_mandatory: true``: - Queue item is persisted - Response includes violation details - Observation can proceed 2. If mandatory constraints fail (OST-001, OST-005, OST-006): - Queue item is NOT persisted - Response includes violation details - User must resolve the issue before scheduling **Example Request**: .. code-block:: json { "id": "item_1", "sbd_fk": "sbd_123", "observation_start_time": "2024-06-01T12:00:00Z", "user_confirmed_non_mandatory": true } Constraint Evaluation Details ============================= Coordinate Systems ------------------ All angular separations are computed in the observer's Altitude-Azimuth (AltAz) frame at the observation time. This accounts for: - Observer location (SKA-MID or SKA-LOW) - Observation time - Target coordinates (RA/DEC) - Solar system body positions Elevation Calculation --------------------- Target elevation is calculated as the altitude angle in the AltAz frame: - **Positive elevation**: Target is above the horizon - **Negative elevation**: Target is below the horizon - **0° elevation**: Target is on the horizon Dish Elevation Limit -------------------- The dish elevation limit is retrieved from the telemodel based on: 1. Telescope type (SKA-MID or SKA-LOW) 2. Subarray definition (e.g., AA0.5, AA1, AA2) Default: 5.0 degrees (if telemodel lookup fails) LST Calculation --------------- Local Sidereal Time is calculated as: .. code-block:: text LST = observation_time.sidereal_time(observer_longitude) % 24 hours LST windows can wrap around midnight (e.g., 22h to 2h). API Integration =============== Constraint Validation Endpoint ------------------------------ **Endpoint**: ``PUT /observing_queue_items/{item_id}/queue/{queue_id}`` **Request**: .. code-block:: json { "id": "item_1", "sbd_fk": "sbd_123", "observation_start_time": "2024-06-01T12:00:00Z", "user_confirmed_non_mandatory": false } **Success Response (HTTP 200)**: .. code-block:: json { "result_status": "success", "result_data": [ { "id": "item_1", "sbd_fk": "sbd_123", "observation_start_time": "2024-06-01T12:00:00Z", "observing_constraints": { "sun_separation": 45.2, "moon_separation": 62.1, "jupiter_separation": 78.5, "current_elevation": 35.4, "current_lst": 14.5, "observation_time": "2024-06-01T12:00:00", "telescope": "mid" } } ] } **Failure Response (HTTP 200)**: .. code-block:: json { "result_status": "failed", "result_data": [ { "id": "item_1", "sbd_fk": "sbd_123", "observation_start_time": "2024-06-01T12:00:00Z", "observing_constraints": { "violations": [ { "code": "OST-001", "message": "Target not visible: elevation -15.0° is below the dish elevation limit of 5.0°", "values": { "current_elevation": "-15.0°", "dish_limit": "5.0°", "telescope": "ska_mid", "observation_time": "2024-06-01T12:00:00" } } ] } } ] }