Coverage for python/lsst/obs/rubinGenericCamera/translator.py: 74%
87 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-05-01 13:05 +0000
« prev ^ index » next coverage.py v7.5.0, created at 2024-05-01 13:05 +0000
1import os
3import numpy as np
4import astropy.units as u
5from astropy.time import Time
7from astro_metadata_translator import cache_translation
8from lsst.obs.lsst.translators.lsst import LsstBaseTranslator
10from lsst.utils import getPackageDir
12__all__ = ["StarTrackerNarrowTranslator", "StarTrackerWideTranslator", "StarTrackerFastTranslator",]
15class RubinGenericCameraTranslator(LsstBaseTranslator):
16 """Metadata translator for Rubin Generic Camera FITS headers"""
18 name = None # you must specialise this class
19 """Name of this translation class"""
21 supported_instrument = None # you must specialise this class
22 """Supports the LSST Generic Camera instrument."""
24 default_search_path = os.path.join(getPackageDir("obs_rubinGenericCamera"), "corrections")
25 """Default search path to use to locate header correction files."""
27 default_resource_root = os.path.join(getPackageDir("obs_rubinGenericCamera"), "corrections")
28 """Default resource path root to use to locate header correction files."""
30 DETECTOR_MAX = 1
32 _const_map = {"detector_num": 0,
33 "boresight_rotation_coord": "sky",
34 "physical_filter": "empty",
35 "detector_group": "None",
36 "relative_humidity": None,
37 "pressure": None,
38 "temperature": None,
39 "focus_z": None,
40 }
41 """Constant mappings"""
43 _trivial_map = {
44 "boresight_rotation_angle": (["ROTPA", "ROTANGLE"], dict(default=np.NaN, unit=u.deg)),
45 "detector_name": "CCD0",
46 "object": ("OBJECT", dict(default="UNKNOWN")),
47 "observation_id": "OBSID",
48 "observation_type": "IMGTYPE",
49 "science_program": ("PROGRAM", dict(default="unknown")),
50 "telescope": "TELESCOP",
51 }
52 """One-to-one mappings"""
54 extensions = dict(
55 )
57 @classmethod
58 def can_translate(cls, header, filename=None):
59 """Indicate whether this translation class can translate the
60 supplied header.
62 Parameters
63 ----------
64 header : `dict`-like
65 Header to convert to standardized form.
66 filename : `str`, optional
67 Name of file being translated.
69 Returns
70 -------
71 can : `bool`
72 `True` if the header is recognized by this class. `False`
73 otherwise.
74 """
76 return False # you must specialise this class
78 @cache_translation
79 def to_datetime_begin(self):
80 self._used_these_cards("MJD-BEG")
81 return Time(self._header["MJD-BEG"], scale="tai", format="mjd")
83 @cache_translation
84 def to_instrument(self):
85 return None # you must specialise this class
87 @cache_translation
88 def to_exposure_time(self):
89 # Docstring will be inherited. Property defined in properties.py
90 # Some data is missing a value for EXPTIME.
91 # Have to be careful we do not have circular logic when trying to
92 # guess
93 if self.is_key_ok("EXPTIME"):
94 return self.quantity_from_card("EXPTIME", u.s)
96 # A missing or undefined EXPTIME is problematic. Set to -1
97 # to indicate that none was found.
98 self.log.warning("%s: Insufficient information to derive exposure time. Setting to -1.0s",
99 self._log_prefix)
100 return -1.0 * u.s
102 @cache_translation
103 def to_dark_time(self): # N.b. defining this suppresses a warning re setting from exptime
104 if "DARKTIME" in self._header:
105 darkTime = self._header["DARKTIME"]
106 self._used_these_cards("DARKTIME")
107 return (darkTime, dict(unit=u.s))
108 return self.to_exposure_time()
111class StarTrackerTranslator(RubinGenericCameraTranslator):
112 name = None # must be specialised
113 """Name of this translation class"""
115 supported_instrument = None # must be specialised
116 """Supports the Rubin Star Tracker instrument."""
118 @classmethod
119 def _is_startracker(cls, header, filename=None):
120 """Indicate whether the supplied header comes from a starTracker
122 Parameters
123 ----------
124 header : `dict`-like
125 Header to convert to standardized form.
126 filename : `str`, optional
127 Name of file being translated.
129 Returns
130 -------
131 (isStarTracker, camId) : (`True`, `int`) or (`False`, `None`)
132 isStarTracker is `True` iff header comes from a starTracker
133 camId is the cameraID, e.g. 101 for the wide-field startracker,
134 102 for the narrow-field startracker
135 """
136 if "INSTRUME" not in header or header["INSTRUME"] != "StarTracker" or "OBSID" not in header:
137 return (False, None)
139 camId = int(header["OBSID"][2:5])
141 return (True, camId)
144class StarTrackerNarrowTranslator(StarTrackerTranslator):
145 name = "StarTrackerNarrow"
146 """Name of this translation class"""
148 supported_instrument = "StarTrackerNarrow"
149 """Supports the Rubin Star Tracker narrow-field instrument."""
151 _const_map = {"instrument": "StarTrackerNarrow",
152 "detector_serial": "00:0f:31:03:ae:60", # MAC address
153 }
155 @classmethod
156 def can_translate(cls, header, filename=None):
157 """Indicate whether this translation class can translate the
158 supplied header.
160 Parameters
161 ----------
162 header : `dict`-like
163 Header to convert to standardized form.
164 filename : `str`, optional
165 Name of file being translated.
167 Returns
168 -------
169 can : `bool`
170 `True` if the header is recognized by this class. `False`
171 otherwise.
172 """
174 isStarTracker, camId = cls._is_startracker(header, filename=None)
176 return isStarTracker and camId == 102
179class StarTrackerWideTranslator(StarTrackerTranslator):
180 name = "StarTrackerWide"
181 """Name of this translation class"""
183 supported_instrument = "StarTrackerWide"
184 """Supports the Rubin Star Tracker wide-field instrument."""
186 _const_map = {"instrument": "StarTrackerWide",
187 "detector_serial": "00:0f:31:03:60:c2", # MAC address
188 }
190 @classmethod
191 def can_translate(cls, header, filename=None):
192 """Indicate whether this translation class can translate the
193 supplied header.
195 Parameters
196 ----------
197 header : `dict`-like
198 Header to convert to standardized form.
199 filename : `str`, optional
200 Name of file being translated.
202 Returns
203 -------
204 can : `bool`
205 `True` if the header is recognized by this class. `False`
206 otherwise.
207 """
208 isStarTracker, camId = cls._is_startracker(header, filename=None)
210 return isStarTracker and camId == 101
213class StarTrackerFastTranslator(StarTrackerTranslator):
214 name = "StarTrackerFast"
215 """Name of this translation class"""
217 supported_instrument = "starTrackerFast"
218 """Supports the STARTRACKERFAST dome-seeing instrument."""
220 _const_map = {"instrument": "StarTrackerFast",
221 "detector_serial": "00:0F:31:03:3F:BA", # MAC address
222 }
224 @classmethod
225 def can_translate(cls, header, filename=None):
226 """Indicate whether this translation class can translate the
227 supplied header.
229 Parameters
230 ----------
231 header : `dict`-like
232 Header to convert to standardized form.
233 filename : `str`, optional
234 Name of file being translated.
236 Returns
237 -------
238 can : `bool`
239 `True` if the header is recognized by this class. `False`
240 otherwise.
241 """
242 isStarTracker, camId = cls._is_startracker(header, filename=None)
244 return isStarTracker and camId == 103