Source code for rubin_scheduler.utils.approx_coord_transforms

__all__ = (
    "_approx_alt_az2_ra_dec",
    "_approx_ra_dec2_alt_az",
    "approx_alt_az2_ra_dec",
    "approx_ra_dec2_alt_az",
    "_approx_altaz2pa",
    "approx_altaz2pa",
)

import numpy as np

from .coordinate_transformations import calc_lmst


def _approx_altaz2pa(alt_rad, az_rad, latitude_rad):
    """A fast calculation of parallactic angle.

    Parameters
    ----------
    alt_rad : `float`
        Altitude (radians)
    az_rad : `float`
        Azimuth (radians)
    latitude_rad : `float`
        The latitude of the observatory (radians)

    Returns
    -------
    pa : `float`
        Parallactic angle (radians)
    """

    y = np.sin(-az_rad) * np.cos(latitude_rad)
    x = np.cos(alt_rad) * np.sin(latitude_rad) - np.sin(alt_rad) * np.cos(latitude_rad) * np.cos(-az_rad)
    pa = np.arctan2(y, x)
    # Make it run from 0-360 deg instead of of -180 to 180
    pa = pa % (2.0 * np.pi)
    return pa


[docs] def approx_altaz2pa(alt_deg, az_deg, latitude_deg): """A fast calculation of parallactic angle. Parameters ---------- alt_rad : `float` Altitude (degrees) az_rad : `float` Azimuth (degrees) latitude_rad : `float` The latitude of the observatory (degrees) Returns ------- pa : `float` Parallactic angle (degrees) """ pa = _approx_altaz2pa(np.radians(alt_deg), np.radians(az_deg), np.radians(latitude_deg)) return np.degrees(pa)
[docs] def approx_alt_az2_ra_dec(alt, az, lat, lon, mjd, lmst=None): """Convert alt, az to RA, Dec without taking into account aberration, precession, diffraction, etc. Parameters ---------- alt : numpy.array Altitude, same length as `ra` and `dec`. Degrees. az : numpy.array Azimuth, same length as `ra` and `dec`. Must be same length as `alt`. Degrees. lat : float Latitude of the observatory in degrees. lon : float Longitude of the observatory in degrees. mjd : float Modified Julian Date. lmst : float (None) The local mean sidereal time (computed if not given). (hours) Returns ------- ra : array_like RA, in degrees. dec : array_like Dec, in degrees. """ ra, dec = _approx_alt_az2_ra_dec( np.radians(alt), np.radians(az), np.radians(lat), np.radians(lon), mjd, lmst=lmst, ) return np.degrees(ra), np.degrees(dec)
def _approx_alt_az2_ra_dec(alt, az, lat, lon, mjd, lmst=None): """Convert alt, az to RA, Dec without taking into account aberration, precession, diffraction, etc. Parameters ---------- alt : numpy.array Altitude, same length as `ra` and `dec`. Radians. az : numpy.array Azimuth, same length as `ra` and `dec`. Must be same length as `alt`. Radians. lat : float Latitude of the observatory in radians. lon : float Longitude of the observatory in radians. mjd : float Modified Julian Date. lmst : float (None) The local mean sidereal time (computed if not given). (hours) Returns ------- ra : array_like RA, in radians. dec : array_like Dec, in radians. """ if lmst is None: lmst = calc_lmst(mjd, lon) lmst = lmst / 12.0 * np.pi # convert to rad sindec = np.sin(lat) * np.sin(alt) + np.cos(lat) * np.cos(alt) * np.cos(az) sindec = np.clip(sindec, -1, 1) dec = np.arcsin(sindec) ha = np.arctan2( -np.sin(az) * np.cos(alt), -np.cos(az) * np.sin(lat) * np.cos(alt) + np.sin(alt) * np.cos(lat), ) ra = lmst - ha raneg = np.where(ra < 0) ra[raneg] = ra[raneg] + 2.0 * np.pi raover = np.where(ra > 2.0 * np.pi) ra[raover] -= 2.0 * np.pi return ra, dec
[docs] def approx_ra_dec2_alt_az(ra, dec, lat, lon, mjd, lmst=None): """Convert Ra,Dec to Altitude and Azimuth. Coordinate transformation is killing performance. Just use simple equations to speed it up and ignore aberration, precession, nutation, nutrition, etc. Parameters ---------- ra : array_like RA, in degrees. dec : array_like Dec, in degrees. Must be same length as `ra`. lat : float Latitude of the observatory in degrees. lon : float Longitude of the observatory in degrees. mjd : float Modified Julian Date. lmst : float (None) The local mean sidereal time (computed if not given). (hours) Returns ------- alt : numpy.array Altitude, same length as `ra` and `dec`. degrees. az : numpy.array Azimuth, same length as `ra` and `dec`. degrees. """ alt, az = _approx_ra_dec2_alt_az( np.radians(ra), np.radians(dec), np.radians(lat), np.radians(lon), mjd, lmst=lmst, ) return np.degrees(alt), np.degrees(az)
def _approx_ra_dec2_alt_az(ra, dec, lat, lon, mjd, lmst=None, return_pa=False): """Convert Ra,Dec to Altitude and Azimuth. Coordinate transformation is killing performance. Just use simple equations to speed it up and ignore aberration, precession, nutation, nutrition, etc. Parameters ---------- ra : array_like RA, in radians. dec : array_like Dec, in radians. Must be same length as `ra`. lat : float Latitude of the observatory in radians. lon : float Longitude of the observatory in radians. mjd : float Modified Julian Date. lmst : float (None) The local mean sidereal time (computed if not given). (hours) Returns ------- alt : numpy.array Altitude, same length as `ra` and `dec`. Radians. az : numpy.array Azimuth, same length as `ra` and `dec`. Radians. """ if lmst is None: lmst = calc_lmst(mjd, lon) lmst = lmst / 12.0 * np.pi # convert to rad ha = lmst - ra sindec = np.sin(dec) sinlat = np.sin(lat) coslat = np.cos(lat) sinalt = sindec * sinlat + np.cos(dec) * coslat * np.cos(ha) sinalt = np.clip(sinalt, -1, 1) alt = np.arcsin(sinalt) cosaz = (sindec - np.sin(alt) * sinlat) / (np.cos(alt) * coslat) cosaz = np.clip(cosaz, -1, 1) az = np.arccos(cosaz) if np.size(ha) < 2: if np.sin(ha) > 0: az = 2.0 * np.pi - az else: signflip = np.where(np.sin(ha) > 0) az[signflip] = 2.0 * np.pi - az[signflip] if return_pa: pa = _approx_altaz2pa(alt, az, lat) return alt, az, pa return alt, az