Coverage for python/lsst/obs/lsst/translators/comCam.py: 26%
55 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-17 02:55 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-17 02:55 -0800
1# This file is currently part of obs_lsst but is written to allow it
2# to be migrated to the astro_metadata_translator package at a later date.
3#
4# This product includes software developed by the LSST Project
5# (http://www.lsst.org).
6# See the LICENSE file in this directory for details of code ownership.
7#
8# Use of this source code is governed by a 3-clause BSD-style
9# license that can be found in the LICENSE file.
11"""Metadata translation code for the LSST Commissioning Camera"""
13__all__ = ("LsstComCamTranslator", )
15import logging
17from astropy.time import Time
18from .lsstCam import LsstCamTranslator
19from .lsst import SIMONYI_TELESCOPE
21log = logging.getLogger(__name__)
23DETECTOR_SERIALS = {
24 "S00": "ITL-3800C-229",
25 "S01": "ITL-3800C-251",
26 "S02": "ITL-3800C-215",
27 "S10": "ITL-3800C-326",
28 "S11": "ITL-3800C-283",
29 "S12": "ITL-3800C-243",
30 "S20": "ITL-3800C-319",
31 "S21": "ITL-3800C-209",
32 "S22": "ITL-3800C-206",
33}
35# Date ComCam left Tucson bound for Chile
36COMCAM_TO_CHILE_DATE = Time("2020-03-13T00:00", format="isot", scale="utc")
39class LsstComCamTranslator(LsstCamTranslator):
40 """Metadata translation for the LSST Commissioning Camera."""
42 name = "LSSTComCam"
43 """Name of this translation class"""
45 _const_map = {
46 "instrument": "LSSTComCam",
47 }
49 # Use the comCam raft definition
50 cameraPolicyFile = "policy/comCam.yaml"
52 @classmethod
53 def can_translate(cls, header, filename=None):
54 """Indicate whether this translation class can translate the
55 supplied header.
57 Looks for "COMCAM" instrument in case-insensitive manner but
58 must be on LSST telescope. This avoids confusion with other
59 telescopes using commissioning cameras.
61 Parameters
62 ----------
63 header : `dict`-like
64 Header to convert to standardized form.
65 filename : `str`, optional
66 Name of file being translated.
68 Returns
69 -------
70 can : `bool`
71 `True` if the header is recognized by this class. `False`
72 otherwise.
73 """
74 if "INSTRUME" in header and "TELESCOP" in header:
75 telescope = header["TELESCOP"]
76 instrument = header["INSTRUME"].lower()
77 if instrument == "comcam" and telescope in (SIMONYI_TELESCOPE, "LSST"):
78 return True
79 telcode = header.get("TELCODE", None)
80 # Some lab data reports that it is LSST_CAMERA
81 if telcode == "CC" and telescope in (SIMONYI_TELESCOPE, "LSST"):
82 return True
84 return False
86 @classmethod
87 def fix_header(cls, header, instrument, obsid, filename=None):
88 """Fix ComCam headers.
90 Notes
91 -----
92 Fixes the following issues:
94 * If LSST_NUM is missing it is filled in by looking at the CCDSLOT
95 value and assuming that the ComCam detectors are fixed.
97 Corrections are reported as debug level log messages.
99 See `~astro_metadata_translator.fix_header` for details of the general
100 process.
101 """
102 modified = False
104 # Calculate the standard label to use for log messages
105 log_label = cls._construct_log_prefix(obsid, filename)
107 physical_filter = header.get("FILTER")
108 if physical_filter in (None, "r", ""):
109 # Create a translator since we need the date
110 translator = cls(header)
111 if physical_filter is None:
112 header["FILTER"] = "unknown"
113 physical_filter_str = "None"
114 else:
115 date = translator.to_datetime_begin()
116 if date > COMCAM_TO_CHILE_DATE:
117 header["FILTER"] = "empty"
118 else:
119 header["FILTER"] = "r_03" # it's currently 'r', which is a band not a physical_filter
121 physical_filter_str = f'"{physical_filter}"'
123 log.warning("%s: replaced FILTER %s with \"%s\"",
124 log_label, physical_filter_str, header["FILTER"])
125 modified = True
127 if "LSST_NUM" not in header:
128 slot = header.get("CCDSLOT", None)
129 if slot in DETECTOR_SERIALS:
130 header["LSST_NUM"] = DETECTOR_SERIALS[slot]
131 modified = True
132 log.debug("%s: Set LSST_NUM to %s", log_label, header["LSST_NUM"])
134 if "ROTPA" not in header:
135 header["ROTPA"] = 0.0
136 log.warning("Missing ROTPA in header - replacing with 0.0")
137 modified = True
139 return modified
141 def _is_on_mountain(self):
142 """Indicate whether these data are coming from the instrument
143 installed on the mountain.
144 Returns
145 -------
146 is : `bool`
147 `True` if instrument is on the mountain.
149 Notes
150 -----
151 TODO: DM-33387 This is currently a terrible hack and MUST be removed
152 once CAP-807 and CAP-808 are done.
153 Until then, ALL non-calib ComCam data will look like it is on sky.
154 """
155 return True