Source code for edges_analysis.coordinates
"""Functions for working with earth/sky coordinates."""
from __future__ import annotations
import datetime as dt
import numpy as np
from astropy import coordinates as apc
from astropy import time as apt
from astropy import units as apu
from . import const
[docs]
def utc2lst(utc_time_array, longitude):
"""
Convert an array representing UTC date/time to a 1D array of LST date/time.
Parameters
----------
utc_time_array : array-like
Nx6 array of floats or integers, where each row is of the form
[yyyy, mm, dd,HH, MM, SS]. It can also be a 6-element 1D array.
longitude : float
Terrestrial longitude of observatory (float) in degrees.
Returns
-------
LST : 1D array of LST dates/times
Examples
--------
>>> LST = utc2lst(utc_time_array, -27.5)
"""
# convert input array to "int"
if not isinstance(utc_time_array[0], dt.datetime):
utc_time_array = [
dt.datetime(*utc) for utc in np.atleast_2d(utc_time_array).astype(int)
]
# python "datetime" to astropy "Time" format
t = apt.Time(utc_time_array, format="datetime", scale="utc")
# necessary approximation to compute sidereal time
t.delta_ut1_utc = 0
return t.sidereal_time("apparent", str(longitude) + "d", model="IAU2006A").value
[docs]
def moon_azel(times: apt.Time, obs_location: apc.EarthLocation) -> np.ndarray:
"""Get local coordinates of the Sun using Astropy."""
moon = apc.get_moon(times).transform_to(apc.AltAz(location=obs_location))
return moon.az.deg, moon.alt.deg
[docs]
def sun_azel(times: apt.Time, obs_location: apc.EarthLocation) -> np.ndarray:
"""Get local coordinates of the Sun using Astropy."""
sun = apc.get_moon(times).transform_to(apc.AltAz(location=obs_location))
return sun.az.deg, sun.alt.deg
[docs]
def f2z(fe: float | np.ndarray) -> float | np.ndarray:
"""Convert observed 21cm frequency to redshift."""
# Constants and definitions
c = 299792458 # wikipedia, m/s
f21 = 1420.40575177e6 # wikipedia,
lambda21 = c / f21 # frequency to wavelength, as emitted
# frequency to wavelength, observed. fe comes in MHz but it
# has to be converted to Hertz
lmbda = c / (fe * 1e6)
return (lmbda - lambda21) / lambda21
[docs]
def z2f(z: float | np.ndarray) -> float | np.ndarray:
"""Convert observed redshift to 21cm frequency."""
# Constants and definitions
c = 299792458 # wikipedia, m/s
f21 = 1420.40575177e6 # wikipedia,
l21 = c / f21 # frequency to wavelength, as emitted
lmbda = l21 * (1 + z)
return c / (lmbda * 1e6)
[docs]
def lst2gha(lst: float | np.ndarray) -> float | np.ndarray:
"""Convert LST to GHA."""
gha = lst - const.galactic_centre_lst
return gha % 24
[docs]
def gha2lst(gha: float | np.ndarray) -> float | np.ndarray:
"""Convert GHA to LST."""
lst = gha + const.galactic_centre_lst
return lst % 24
[docs]
def get_jd(d: dt.datetime) -> int:
"""Get the day of the year from a datetime object."""
dt0 = dt.datetime(d.year, 1, 1)
return (d - dt0).days + 1
[docs]
def dt_from_jd(y: int, d: int, *args) -> dt.datetime:
"""Get a datetime object from a julian date."""
begin = dt.datetime(y, 1, 1, *args)
return begin + dt.timedelta(days=d - 1)
[docs]
def lst_to_earth_time(time: apt.Time) -> float:
"""Return a factor to convert one second of earth-measured time to an LST."""
time2 = time + dt.timedelta(seconds=1)
lst = time.sidereal_time("apparent")
lst2 = time2.sidereal_time("apparent")
return (lst2.arcsecond - lst.arcsecond) / 15
[docs]
def lsts_to_times(
lsts: np.typing.ArrayLike,
ref_time: apt.Time,
location: apc.EarthLocation = const.edges_location,
) -> list[apt.Time]:
"""Convert a list of LSTs to local times at a particular location.
The times are generated close to (surrounding) a particular time.
Recall that any particular LST maps to some time on an infinite number of days.
Pass `ref_time` to set the time around which the LSTs will map.
Parameters
----------
lsts
A list/array of LSTs in hours.
ref_time
An astropy time (in UTC) giving the time around which to find the LSTs.
location
The location at which the LSTs are defined.
"""
ref_time.location = location
ref_lst = ref_time.sidereal_time("apparent")
lst_per_sec = lst_to_earth_time(ref_time)
times = []
for this_lst in lsts:
lst_diff = apc.Longitude(this_lst * apu.hour) - ref_lst
sec_diff = apt.TimeDelta(lst_diff.arcsecond / 15 / lst_per_sec, format="sec")
times.append(ref_time + sec_diff)
return times