Source code for pyobs.robotic.scheduler.constraints.solarelevationconstraint

from __future__ import annotations
from typing import TYPE_CHECKING, Literal
import astroplan
import astropy.units as u
import logging
from astropy.coordinates import get_sun
from pydantic import Field
from astropy.time import Time

from .constraint import Constraint

if TYPE_CHECKING:
    from ..dataprovider import DataProvider
    from pyobs.robotic import Task


log = logging.getLogger(__name__)


[docs] class SolarElevationConstraint(Constraint): """Solar elevation constraint.""" min_elevation: float = Field(ge=-90, le=90, default=-90.0) max_elevation: float = Field(ge=-90, le=90, default=-18.0) direction: Literal["rising", "setting", "both"] = "both" def to_astroplan(self) -> astroplan.AtNightConstraint: if self.min_elevation > -90.0: log.warning("Minimum solar elevation constraint not supported by astroplan.") return astroplan.AtNightConstraint(max_solar_altitude=self.max_elevation * u.deg) async def __call__(self, time: Time, task: Task, data: DataProvider) -> bool: sun = data.observer.sun_altaz(time) in_range = self.min_elevation <= float(sun.alt.degree) <= self.max_elevation if self.direction == "both": return in_range else: sun_coord = get_sun(time) transit = data.observer.target_meridian_transit_time(time, sun_coord, which="nearest") midnight = data.observer.midnight(time, which="nearest") if self.direction == "rising": return in_range and bool(midnight < time < transit) else: return in_range and not bool(midnight < time < transit)
__all__ = ["SolarElevationConstraint"]