Source code for m4opt.constraints._atnight
from typing import override
from astropy import units as u
from astropy.coordinates import AltAz, get_sun
from ._core import Constraint
[docs]
class AtNightConstraint(Constraint):
"""
Constrain observations to specific twilight phases or a user-defined solar altitude limit.
Parameters
----------
max_solar_altitude : `~astropy.units.Quantity`
A user-defined maximum solar altitude threshold. This parameter is required
when not using specific twilight methods (`twilight_civil`, `twilight_nautical`, `twilight_astronomical`).
It sets the maximum altitude of the Sun for which observations are allowed.
Notes
-----
- The pressure is set to zero when calculating the Sun's altitude.
This avoids errors due to atmospheric refraction at very low altitudes.
Examples
--------
>>> from astropy.coordinates import EarthLocation, SkyCoord
>>> from astropy.time import Time
>>> from astropy import units as u
>>> from m4opt.constraints import AtNightConstraint
>>> time = Time("2017-08-17T00:41:04Z")
>>> target = SkyCoord.from_name("NGC 4993")
>>> location = EarthLocation.of_site("Rubin Observatory")
>>> constraint = AtNightConstraint.twilight_civil()
>>> constraint(observer_location=location, target_coord=target, obstime=time)
np.True_
>>> constraint = AtNightConstraint.twilight_nautical()
>>> constraint(observer_location=location, target_coord=target, obstime=time)
np.True_
>>> constraint = AtNightConstraint.twilight_astronomical()
>>> constraint(observer_location=location, target_coord=target, obstime=time)
np.True_
"""
def __init__(self, max_solar_altitude: u.Quantity[u.physical.angle] = 0 * u.deg):
self.max_solar_altitude = max_solar_altitude
[docs]
@classmethod
def twilight_civil(cls):
"""
Create an :class:`~m4opt.constraints.AtNightConstraint` for civil twilight (-6°).
"""
return cls(-6 * u.deg)
[docs]
@classmethod
def twilight_nautical(cls):
"""
Create an :class:`~m4opt.constraints.AtNightConstraint` for nautical twilight (-12°).
"""
return cls(-12 * u.deg)
[docs]
@classmethod
def twilight_astronomical(cls):
"""
Create an :class:`~m4opt.constraints.AtNightConstraint` for astronomical twilight (-18°).
"""
return cls(-18 * u.deg)
[docs]
@override
def __call__(self, observer_location, target_coord, obstime):
altaz_frame = AltAz(obstime=obstime, location=observer_location)
sun_altitude = get_sun(obstime).transform_to(altaz_frame).alt
return sun_altitude <= self.max_solar_altitude