Source code for ctapipe.coordinates.utils

import astropy.units as u
import numpy as np
from astropy.coordinates import AltAz
from erfa.ufunc import p2s as cartesian_to_spherical
from erfa.ufunc import s2p as spherical_to_cartesian

from .ground_frames import _get_xyz

__all__ = [
    "altaz_to_righthanded_cartesian",
    "get_point_on_shower_axis",
]


_zero_m = u.Quantity(0, u.m)


[docs] def altaz_to_righthanded_cartesian(alt, az, distance=1.0): """Turns an alt/az coordinate into a 3d direction in a right-handed coordinate system. This is because azimuths are in a left-handed system. See e.g: https://github.com/astropy/astropy/issues/5300 Parameters ---------- alt: u.Quantity altitude az: u.Quantity azimuth """ # this is an optimization, shaves of ca. 50 % compared to handing over units # to the erfa function if hasattr(az, "unit"): az = az.to_value(u.rad) alt = alt.to_value(u.rad) unit = None if hasattr(distance, "unit"): unit = distance.unit distance = distance.value result = spherical_to_cartesian(-az, alt, distance) if unit is not None: return u.Quantity(result, unit=unit, copy=False) return result
[docs] @u.quantity_input(core_x=u.m, core_y=u.m, alt=u.rad, az=u.rad, distance=u.km) def get_point_on_shower_axis(core_x, core_y, alt, az, telescope_position, distance): """ Get a point on the shower axis in AltAz frame as seen by a telescope at the given position. Parameters ---------- core_x : u.Quantity[length] Impact x-coordinate core_y : u.Quantity[length] Impact y-coordinate alt : u.Quantity[angle] Altitude of primary az : u.Quantity[angle] Azimuth of primary telescope_position : GroundFrame Telescope position distance : u.Quantity[length] Distance along the shower axis from the ground of the point returned. Returns ------- coord : AltAz The AltAz coordinate of a point on the shower axis at the given distance from the impact point. """ impact = u.Quantity([core_x, core_y, _zero_m], unit=u.m) # move up the shower axis by slant_distance point = impact + altaz_to_righthanded_cartesian(alt=alt, az=az, distance=distance) # offset by telescope positions and convert to sperical # to get local AltAz for each telescope cartesian = point[np.newaxis, :] - _get_xyz(telescope_position).T lon, lat, _ = cartesian_to_spherical(cartesian) return AltAz(alt=lat, az=-lon, copy=False)