Source code for adam_core.observations.exposures
from __future__ import annotations
from typing import Iterator, Literal
import pyarrow as pa
import pyarrow.compute as pc
import quivr as qv
from quivr.validators import and_, ge, le
from ..coordinates.origin import OriginCodes
from ..observers import observers, state
from ..time import Timestamp
[docs]
class Exposures(qv.Table):
"""
Exposures is a table of data about exposures that provide point source observations.
"""
id = qv.LargeStringColumn()
start_time = Timestamp.as_column()
duration = qv.Float64Column(validator=and_(ge(0), le(3600)))
filter = qv.LargeStringColumn()
observatory_code = qv.LargeStringColumn()
seeing = qv.Float64Column(nullable=True)
depth_5sigma = qv.Float64Column(nullable=True)
[docs]
def group_by_observatory_code(self) -> Iterator[tuple[str, Exposures]]:
"""
Groups the exposures by observatory code.
"""
unique_codes = self.observatory_code.unique()
for code in unique_codes:
mask = pc.equal(self.observatory_code, code)
yield code, self.apply_mask(mask)
[docs]
def observers(
self,
frame: Literal["ecliptic", "equatorial", "itrf93"] = "ecliptic",
origin: OriginCodes = OriginCodes.SUN,
) -> observers.Observers:
"""
Return the observer location at each exposure midpoint.
"""
# bunch of bookkeeping here to return states with the same
# indexing as self
coords = []
indices = []
codes = []
unique_codes = self.observatory_code.unique().to_pylist()
for code in unique_codes:
mask = pc.equal(self.observatory_code, code)
exposures_for_code = self.apply_mask(mask)
indices_for_code = pc.indices_nonzero(mask)
times_for_code = exposures_for_code.midpoint()
coords_for_code = state.get_observer_state(
code, times_for_code, frame=frame, origin=origin
)
coords.append(coords_for_code)
indices.append(indices_for_code)
codes.append(pa.array([code] * len(coords_for_code)))
observers_table = observers.Observers.from_kwargs(
code=pa.concat_arrays(codes),
coordinates=qv.concatenate(coords),
)
indices = pa.concat_arrays(indices)
original_ordering = pc.array_sort_indices(indices)
return observers_table.take(original_ordering)
[docs]
def midpoint(self) -> Timestamp:
"""
Returns the midpoint of the exposure.
"""
return self.start_time.add_seconds(pc.divide(self.duration, 2.0))