Coverage for python/lsst/obs/lsst/translators/comCamSim.py: 28%
66 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-26 11:36 +0000
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-26 11:36 +0000
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 Simulated LSST Commissioning Camera"""
13__all__ = ("LsstComCamSimTranslator", )
15import logging
16import warnings
18import astropy.utils.exceptions
19from astropy.coordinates import AltAz
20from astro_metadata_translator import cache_translation
22from .lsstCam import LsstCamTranslator
23from .lsst import SIMONYI_TELESCOPE
25log = logging.getLogger(__name__)
28class LsstComCamSimTranslator(LsstCamTranslator):
29 """Metadata translation for the LSST Commissioning Camera."""
31 name = "LSSTComCamSim"
32 """Name of this translation class"""
34 _const_map = {
35 "instrument": "LSSTComCamSim",
36 }
38 cameraPolicyFile = 'policy/comCamSim.yaml'
40 @classmethod
41 def can_translate(cls, header, filename=None):
42 """Indicate whether this translation class can translate the
43 supplied header.
45 Looks for "COMCAMSIM" instrument in case-insensitive manner but
46 must be on LSST telescope. This avoids confusion with other
47 telescopes using commissioning cameras.
49 Parameters
50 ----------
51 header : `dict`-like
52 Header to convert to standardized form.
53 filename : `str`, optional
54 Name of file being translated.
56 Returns
57 -------
58 can : `bool`
59 `True` if the header is recognized by this class. `False`
60 otherwise.
61 """
62 if "INSTRUME" in header and "TELESCOP" in header:
63 telescope = header["TELESCOP"]
64 instrument = header["INSTRUME"].lower()
65 if instrument == "comcamsim" and telescope in (SIMONYI_TELESCOPE, "LSST"):
66 return True
68 return False
70 @classmethod
71 def fix_header(cls, header, instrument, obsid, filename=None):
72 """Fix Simulated ComCam headers.
74 Notes
75 -----
76 Content will be added as needed.
78 Corrections are reported as debug level log messages.
80 See `~astro_metadata_translator.fix_header` for details of the general
81 process.
82 """
83 modified = False
85 # Calculate the standard label to use for log messages
86 log_label = cls._construct_log_prefix(obsid, filename)
88 # Some simulated files lack RASTART/DECSTART etc headers. Since these
89 # are simulated they can be populated directly from the RA/DEC headers.
90 synced_radec = False
91 for key in ("RA", "DEC"):
92 for time in ("START", "END"):
93 time_key = f"{key}{time}"
94 if not header.get(time_key):
95 if (value := header.get(key)):
96 header[time_key] = value
97 synced_radec = True
98 if synced_radec:
99 modified = True
100 log.debug("%s: Synced RASTART/RAEND/DECSTART/DECEND headers with RA/DEC headers", log_label)
102 if not header.get("RADESYS") and header.get("RA") and header.get("DEC"):
103 header["RADESYS"] = "ICRS"
104 log.debug("%s: Forcing undefined RADESYS to '%s'", log_label, header["RADESYS"])
105 modified = True
107 if not header.get("TELCODE"):
108 if camcode := header.get("CAMCODE"):
109 header["TELCODE"] = camcode
110 modified = True
111 log.debug("%s: Setting TELCODE header from CAMCODE header", log_label)
112 else:
113 # Get the code from the OBSID.
114 code, _ = obsid.split("_", 1)
115 header["TELCODE"] = code
116 modified = True
117 log.debug("%s: Determining telescope code of %s from OBSID", log_label, code)
119 return modified
121 def _is_on_mountain(self):
122 """Indicate whether these data are coming from the instrument
123 installed on the mountain.
124 Returns
125 -------
126 is : `bool`
127 `True` if instrument is on the mountain.
129 Notes
130 -----
131 TODO: DM-33387 This is currently a terrible hack and MUST be removed
132 once CAP-807 and CAP-808 are done.
133 Until then, ALL non-calib ComCam data will look like it is on sky.
134 """
135 return True
137 @cache_translation
138 def to_altaz_begin(self):
139 # Tries to calculate the value. Simulated files for ops-rehearsal 3
140 # did not have the AZ/EL headers defined.
141 if self.are_keys_ok(["ELSTART", "AZSTART"]):
142 return super().to_altaz_begin()
144 # Calculate it from the RA/Dec and time.
145 # The time is not consistent with the HASTART/AMSTART values.
146 # This means that the elevation may well come out negative.
147 if self.are_keys_ok(["RA", "DEC"]):
148 # Derive from RADec in absence of any other information
149 radec = self.to_tracking_radec()
150 if radec is not None:
151 # This can trigger warnings because of the future dates
152 with warnings.catch_warnings():
153 warnings.simplefilter("ignore", category=astropy.utils.exceptions.AstropyWarning)
154 altaz = radec.transform_to(AltAz())
155 return altaz
157 return None