Coverage for python/lsst/obs/lsst/translators/comCam.py: 28%

55 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2022-08-19 13:15 -0700

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. 

10 

11"""Metadata translation code for the LSST Commissioning Camera""" 

12 

13__all__ = ("LsstComCamTranslator", ) 

14 

15import logging 

16 

17from astropy.time import Time 

18from .lsstCam import LsstCamTranslator 

19from .lsst import SIMONYI_TELESCOPE 

20 

21log = logging.getLogger(__name__) 

22 

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} 

34 

35# Date ComCam left Tucson bound for Chile 

36COMCAM_TO_CHILE_DATE = Time("2020-03-13T00:00", format="isot", scale="utc") 

37 

38 

39class LsstComCamTranslator(LsstCamTranslator): 

40 """Metadata translation for the LSST Commissioning Camera.""" 

41 

42 name = "LSSTComCam" 

43 """Name of this translation class""" 

44 

45 _const_map = { 

46 "instrument": "LSSTComCam", 

47 } 

48 

49 # Use the comCam raft definition 

50 cameraPolicyFile = "policy/comCam.yaml" 

51 

52 @classmethod 

53 def can_translate(cls, header, filename=None): 

54 """Indicate whether this translation class can translate the 

55 supplied header. 

56 

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. 

60 

61 Parameters 

62 ---------- 

63 header : `dict`-like 

64 Header to convert to standardized form. 

65 filename : `str`, optional 

66 Name of file being translated. 

67 

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 

83 

84 return False 

85 

86 @classmethod 

87 def fix_header(cls, header, instrument, obsid, filename=None): 

88 """Fix ComCam headers. 

89 

90 Notes 

91 ----- 

92 Fixes the following issues: 

93 

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. 

96 

97 Corrections are reported as debug level log messages. 

98 

99 See `~astro_metadata_translator.fix_header` for details of the general 

100 process. 

101 """ 

102 modified = False 

103 

104 # Calculate the standard label to use for log messages 

105 log_label = cls._construct_log_prefix(obsid, filename) 

106 

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 

120 

121 physical_filter_str = f'"{physical_filter}"' 

122 

123 log.warning("%s: replaced FILTER %s with \"%s\"", 

124 log_label, physical_filter_str, header["FILTER"]) 

125 modified = True 

126 

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"]) 

133 

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 

138 

139 return modified 

140 

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. 

148 

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