Source code for sasktran2.solar
from __future__ import annotations
import abc
import pandas as pd
from .model import SolarModel
__all__ = ["SolarModel"]
class SolarGeometryHandlerBase:
def __init__(self):
"""
Interface class for the solar handler. A solar handler is used to calculate the
solar angles for a give time and location.
"""
@abc.abstractmethod
def target_solar_angles(
self, latitude: float, longitude: float, altitude: float, time: pd.Timestamp
) -> tuple[float, float]:
"""
Calculates the solar zenith and solar azimuth angles for a given location and time.
Parameters
----------
latitude : float
Latitude in [degrees north]
longitude : float
Longitude in [degrees east]
altitude : float
Altius in [m]
time : pd.Timestamp
Time of interest
Returns
-------
tuple[float, float]
Solar zenith and solar azimuth angles in [degrees]. Solar azimuth is relative to true north, not
to the observer. And is defined clockwise from north, such that the east is 90 degrees, south is 180 degrees, etc.
The azimuthal direction points towards the sun.
"""
[docs]
class SolarGeometryHandlerForced(SolarGeometryHandlerBase):
[docs]
def __init__(self, solar_zenith: float, solar_azimuth: float):
"""
A solar handler where the solar angles are forced to be the same for all locations and times.
Parameters
----------
solar_zenith : float
Solar zenith angle in [degrees]
solar_azimuth : float
Solar azimuth angle in [degrees]. Here 0 degrees corresponds to pointing true north, 90 degrees to east, etc.
Note that this is NOT relative to the observer. Note this is also pointing towards the sun, not away from the sun.
"""
self.solar_zenith = solar_zenith
self.solar_azimuth = solar_azimuth
[docs]
def target_solar_angles(
self,
latitude: float, # noqa: ARG002
longitude: float, # noqa: ARG002
altitude: float, # noqa: ARG002
time: pd.Timestamp, # noqa: ARG002
) -> tuple[float, float]:
return self.solar_zenith, self.solar_azimuth
[docs]
class SolarGeometryHandlerAstropy(SolarGeometryHandlerBase):
"""
Solar handler where the astropy package is used to calculate the solar angles.
Must have astropy installed in the Python environment in order to use this solar handler.
"""
[docs]
def target_solar_angles(
self, latitude: float, longitude: float, altitude: float, time: pd.Timestamp
) -> tuple[float, float]:
try:
from astropy.coordinates import AltAz, EarthLocation, get_sun
from astropy.time import Time
except ImportError:
msg = "Astropy is required to use the astropy solar hanlder"
raise ImportError(msg) # noqa: B904
# Location object
loc = EarthLocation(lat=latitude, lon=longitude, height=altitude)
sun = get_sun(Time(time))
altaz = sun.transform_to(AltAz(obstime=time, location=loc))
return 90.0 - altaz.alt.deg, altaz.az.deg