Hide keyboard shortcuts

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

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 "boresight_rotation_coord": "unknown", 

48 "boresight_rotation_angle": None, 

49 "boresight_airmass": None, 

50 "tracking_radec": None, 

51 } 

52 

53 # Use the comCam raft definition 

54 cameraPolicyFile = "policy/comCam.yaml" 

55 

56 @classmethod 

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

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

59 supplied header. 

60 

61 Looks for "COMCAM" instrument in case-insensitive manner but 

62 must be on LSST telescope. This avoids confusion with other 

63 telescopes using commissioning cameras. 

64 

65 Parameters 

66 ---------- 

67 header : `dict`-like 

68 Header to convert to standardized form. 

69 filename : `str`, optional 

70 Name of file being translated. 

71 

72 Returns 

73 ------- 

74 can : `bool` 

75 `True` if the header is recognized by this class. `False` 

76 otherwise. 

77 """ 

78 if "INSTRUME" in header and "TELESCOP" in header: 

79 telescope = header["TELESCOP"] 

80 instrument = header["INSTRUME"].lower() 

81 if instrument == "comcam" and telescope in (SIMONYI_TELESCOPE, "LSST"): 

82 return True 

83 telcode = header.get("TELCODE", None) 

84 # Some lab data reports that it is LSST_CAMERA 

85 if telcode == "CC" and telescope in (SIMONYI_TELESCOPE, "LSST"): 

86 return True 

87 

88 return False 

89 

90 @classmethod 

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

92 """Fix ComCam headers. 

93 

94 Notes 

95 ----- 

96 Fixes the following issues: 

97 

98 * If LSST_NUM is missing it is filled in by looking at the CCDSLOT 

99 value and assuming that the ComCam detectors are fixed. 

100 

101 Corrections are reported as debug level log messages. 

102 

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

104 process. 

105 """ 

106 modified = False 

107 

108 # Calculate the standard label to use for log messages 

109 log_label = cls._construct_log_prefix(obsid, filename) 

110 

111 physical_filter = header.get("FILTER") 

112 if physical_filter in (None, "r", ""): 

113 # Create a translator since we need the date 

114 translator = cls(header) 

115 if physical_filter is None: 

116 header["FILTER"] = "unknown" 

117 physical_filter_str = "None" 

118 else: 

119 date = translator.to_datetime_begin() 

120 if date > COMCAM_TO_CHILE_DATE: 

121 header["FILTER"] = "empty" 

122 else: 

123 header["FILTER"] = "r_03" # it's currently 'r', which is a band not a physical_filter 

124 

125 physical_filter_str = f'"{physical_filter}"' 

126 

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

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

129 modified = True 

130 

131 if "LSST_NUM" not in header: 

132 slot = header.get("CCDSLOT", None) 

133 if slot in DETECTOR_SERIALS: 

134 header["LSST_NUM"] = DETECTOR_SERIALS[slot] 

135 modified = True 

136 log.debug("%s: Set LSST_NUM to %s", log_label, header["LSST_NUM"]) 

137 

138 return modified