Coverage for python/lsst/obs/lsst/translators/auxTel.py : 23%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# This file is currently part of obs_lsst but is written to allow it # to be migrated to the astro_metadata_translator package at a later date. # # This product includes software developed by the LSST Project # (http://www.lsst.org). # See the LICENSE file in this directory for details of code ownership. # # Use of this source code is governed by a 3-clause BSD-style # license that can be found in the LICENSE file.
# AuxTel is not the same place as LSST # These coordinates read from Apple Maps
# Date instrument is taking data at telescope # Prior to this date many parameters are automatically nulled out # since the headers have not historically been reliable
# Define the sensor and group name for AuxTel globally so that it can be used # in multiple places. There is no raft but for consistency with other LSST # cameras we define one.
"""Pseudo method to determine whether this is a lab or non-science header.
Raises ------ KeyError If this is a science observation and on the mountain. """ if is_non_science(self): return if not self._is_on_mountain(): return raise KeyError("Required key is missing and this is a mountain science observation")
"""Metadata translator for LSST AuxTel data.
For lab measurements many values are masked out. """
"""Name of this translation class"""
"""Supports the LATISS instrument."""
# AuxTel is not yet attached to a telescope so many translations # are null. "instrument": "LATISS", "telescope": "LSSTAuxTel", "detector_group": _DETECTOR_GROUP_NAME, "detector_num": 0, "detector_name": _DETECTOR_NAME, # Single sensor "boresight_rotation_coord": "unknown", "science_program": "unknown", "relative_humidity": None, "pressure": None, "temperature": None, "altaz_begin": None, "tracking_radec": None, }
"observation_id": ("OBSID", dict(default=None, checker=is_non_science)), "exposure_time": ("EXPTIME", dict(unit=u.s)), "dark_time": (["DARKTIME", "EXPTIME"], dict(unit=u.s)), "detector_serial": ["LSST_NUM", "DETSER"], "boresight_airmass": ("AMSTART", dict(checker=is_non_science_or_lab)), "object": ("OBJECT", dict(checker=is_non_science_or_lab, default="UNKNOWN")), "boresight_rotation_angle": ("ROTANGLE", dict(checker=is_non_science_or_lab, default=float("nan"), unit=u.deg)), }
"""Fixed name of detector group."""
"""Fixed name of single sensor."""
"""Indicate whether this translation class can translate the supplied header.
Parameters ---------- header : `dict`-like Header to convert to standardized form. filename : `str`, optional Name of file being translated.
Returns ------- can : `bool` `True` if the header is recognized by this class. `False` otherwise. """ # INSTRUME keyword might be of two types if "INSTRUME" in header: instrume = header["INSTRUME"] for v in ("LSST_ATISS", "LATISS"): if instrume == v: return True # Calibration files strip important headers at the moment so guess if "DETNAME" in header and header["DETNAME"] == "RXX_S00": return True return False
date = self.to_datetime_begin() if date > TSTART: return True return False
def compute_detector_exposure_id(exposure_id, detector_num): """Compute the detector exposure ID from detector number and exposure ID.
This is a helper method to allow code working outside the translator infrastructure to use the same algorithm.
Parameters ---------- exposure_id : `int` Unique exposure ID. detector_num : `int` Detector number.
Returns ------- detector_exposure_id : `int` The calculated ID. """ if detector_num != 0: log.warning("Unexpected non-zero detector number for AuxTel") return exposure_id
def compute_exposure_id(dayobs, seqnum): """Helper method to calculate the AuxTel exposure_id.
Parameters ---------- dayobs : `str` Day of observation in either YYYYMMDD or YYYY-MM-DD format. seqnum : `int` or `str` Sequence number.
Returns ------- exposure_id : `int` Exposure ID in form YYYYMMDDnnnnn form. """ dayobs = dayobs.replace("-", "")
if len(dayobs) != 8: raise ValueError(f"Malformed dayobs: {dayobs}")
# Expect no more than 99,999 exposures in a day maxdigits = 5 if seqnum >= 10**maxdigits: raise ValueError(f"Sequence number ({seqnum}) exceeds limit")
# Form the number as a string zero padding the sequence number idstr = f"{dayobs}{seqnum:0{maxdigits}d}" return int(idstr)
def to_location(self): # Docstring will be inherited. Property defined in properties.py if self._is_on_mountain(): return AUXTEL_LOCATION return None
def to_datetime_begin(self): # Docstring will be inherited. Property defined in properties.py if "MJD-OBS" in self._header: self._used_these_cards("MJD-OBS") return Time(self._header["MJD-OBS"], scale="utc", format="mjd") if "CALIB_ID" in self._header: # Calibration files hide the date information calib_id = self._header["CALIB_ID"] self._used_these_cards("CALIB_ID") parts = calib_id.split() for p in parts: if p.startswith("calibDate"): ymd = p[10:] return Time(ymd, scale="utc", format="isot") return None
def to_datetime_end(self): # Docstring will be inherited. Property defined in properties.py return self.to_datetime_begin() + self.to_exposure_time()
def to_detector_exposure_id(self): # Docstring will be inherited. Property defined in properties.py exposure_id = self.to_exposure_id() detector_num = self.to_detector_num() return self.compute_detector_exposure_id(exposure_id, detector_num)
def to_exposure_id(self): """Generate a unique exposure ID number
This is a combination of DAYOBS and SEQNUM.
Returns ------- exposure_id : `int` Unique exposure number. """ if "CALIB_ID" in self._header: self._used_these_cards("CALIB_ID") return None
dayobs = self._header["DAYOBS"] seqnum = self._header["SEQNUM"] self._used_these_cards("DAYOBS", "SEQNUM")
return self.compute_exposure_id(dayobs, seqnum)
# For now "visits" are defined to be identical to exposures.
def to_observation_type(self): """Determine the observation type.
In the absence of an ``IMGTYPE`` header, assumes lab data is always a dark if exposure time is non-zero, else bias.
Returns ------- obstype : `str` Observation type. """ if self._is_on_mountain(): obstype = self._header["IMGTYPE"] self._used_these_cards("IMGTYPE") return obstype.lower()
exptime = self.to_exposure_time() if exptime == 0.0: obstype = "bias" else: obstype = "unknown" log.warning("Unable to determine observation type. Guessing '%s'", obstype) return obstype
def to_physical_filter(self): # Docstring will be inherited. Property defined in properties.py filters = [] for k in ("FILTER1", "FILTER2"): if k in self._header: filters.append(self._header[k]) self._used_these_cards(k)
if filters: filterName = "|".join(filters) else: filterName = "NONE"
return filterName |