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 part of obs_lsst. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# This program is free software: you can redistribute it and/or modify 

10# it under the terms of the GNU General Public License as published by 

11# the Free Software Foundation, either version 3 of the License, or 

12# (at your option) any later version. 

13# 

14# This program is distributed in the hope that it will be useful, 

15# but WITHOUT ANY WARRANTY; without even the implied warranty of 

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the GNU General Public License 

20# along with this program. If not, see <http://www.gnu.org/licenses/>. 

21 

22__all__ = ("LsstCam", "LsstImSim", "LsstPhoSim", "LsstTS8", 

23 "Latiss", "LsstTS3", "LsstUCDCam", "LsstComCam") 

24 

25import os.path 

26 

27import lsst.obs.base.yamlCamera as yamlCamera 

28from lsst.daf.butler.core.utils import getFullTypeName 

29from lsst.utils import getPackageDir 

30from lsst.obs.base import Instrument 

31from lsst.obs.base.gen2to3 import TranslatorFactory 

32from .filters import LSSTCAM_FILTER_DEFINITIONS, LATISS_FILTER_DEFINITIONS 

33 

34from .translators import LatissTranslator, LsstCamTranslator, \ 

35 LsstUCDCamTranslator, LsstTS3Translator, LsstComCamTranslator, \ 

36 LsstPhoSimTranslator, LsstTS8Translator, LsstImSimTranslator 

37 

38PACKAGE_DIR = getPackageDir("obs_lsst") 

39 

40 

41class LsstCam(Instrument): 

42 """Gen3 Butler specialization for the LSST Main Camera. 

43 

44 Parameters 

45 ---------- 

46 camera : `lsst.cameraGeom.Camera` 

47 Camera object from which to extract detector information. 

48 filters : `list` of `FilterDefinition` 

49 An ordered list of filters to define the set of PhysicalFilters 

50 associated with this instrument in the registry. 

51 

52 While both the camera geometry and the set of filters associated with a 

53 camera are expected to change with time in general, their Butler Registry 

54 representations defined by an Instrument do not. Instead: 

55 

56 - We only extract names, IDs, and purposes from the detectors in the 

57 camera, which should be static information that actually reflects 

58 detector "slots" rather than the physical sensors themselves. Because 

59 the distinction between physical sensors and slots is unimportant in 

60 the vast majority of Butler use cases, we just use "detector" even 

61 though the concept really maps better to "detector slot". Ideally in 

62 the future this distinction between static and time-dependent 

63 information would be encoded in cameraGeom itself (e.g. by making the 

64 time-dependent Detector class inherit from a related class that only 

65 carries static content). 

66 

67 - The Butler Registry is expected to contain physical_filter entries for 

68 all filters an instrument has ever had, because we really only care 

69 about which filters were used for particular observations, not which 

70 filters were *available* at some point in the past. And changes in 

71 individual filters over time will be captured as changes in their 

72 TransmissionCurve datasets, not changes in the registry content (which 

73 is really just a label). While at present Instrument and Registry 

74 do not provide a way to add new physical_filters, they will in the 

75 future. 

76 """ 

77 filterDefinitions = LSSTCAM_FILTER_DEFINITIONS 

78 instrument = "LSSTCam" 

79 policyName = "lsstCam" 

80 translatorClass = LsstCamTranslator 

81 obsDataPackage = "obs_lsst_data" 

82 

83 @property 

84 def configPaths(self): 

85 return [os.path.join(PACKAGE_DIR, "config"), 

86 os.path.join(PACKAGE_DIR, "config", self.policyName)] 

87 

88 @classmethod 

89 def getName(cls): 

90 # Docstring inherited from Instrument.getName 

91 return cls.instrument 

92 

93 @classmethod 

94 def getCamera(cls): 

95 # Constructing a YAML camera takes a long time but we rely on 

96 # yamlCamera to cache for us. 

97 cameraYamlFile = os.path.join(PACKAGE_DIR, "policy", f"{cls.policyName}.yaml") 

98 camera = yamlCamera.makeCamera(cameraYamlFile) 

99 if camera.getName() != cls.getName(): 

100 raise RuntimeError(f"Expected to read camera geometry for {cls.instrument}" 

101 f" but instead got geometry for {cls._camera.getName()}") 

102 return camera 

103 

104 def getRawFormatter(self, dataId): 

105 # Docstring inherited from Instrument.getRawFormatter 

106 # local import to prevent circular dependency 

107 from .rawFormatter import LsstCamRawFormatter 

108 return LsstCamRawFormatter 

109 

110 def register(self, registry): 

111 # Docstring inherited from Instrument.register 

112 # The maximum values below make Gen3's ObservationDataIdPacker produce 

113 # outputs that match Gen2's ccdExposureId. 

114 obsMax = self.translatorClass.max_detector_exposure_id() 

115 registry.insertDimensionData("instrument", 

116 {"name": self.getName(), 

117 "detector_max": self.translatorClass.DETECTOR_MAX, 

118 "visit_max": obsMax, 

119 "exposure_max": obsMax, 

120 "class_name": getFullTypeName(self), 

121 }) 

122 

123 records = [self.extractDetectorRecord(detector) for detector in self.getCamera()] 

124 registry.insertDimensionData("detector", *records) 

125 

126 self._registerFilters(registry) 

127 

128 def extractDetectorRecord(self, camGeomDetector): 

129 """Create a Gen3 Detector entry dict from a cameraGeom.Detector. 

130 """ 

131 # All of the LSST instruments have detector names like R??_S??; we'll 

132 # split them up here, and instruments with only one raft can override 

133 # to change the group to something else if desired. 

134 # Long-term, we should get these fields into cameraGeom separately 

135 # so there's no need to specialize at this stage. 

136 # They are separate in ObservationInfo 

137 group, name = camGeomDetector.getName().split("_") 

138 

139 # getType() returns a pybind11-wrapped enum, which unfortunately 

140 # has no way to extract the name of just the value (it's always 

141 # prefixed by the enum type name). 

142 purpose = str(camGeomDetector.getType()).split(".")[-1] 

143 

144 return dict( 

145 instrument=self.getName(), 

146 id=camGeomDetector.getId(), 

147 full_name=camGeomDetector.getName(), 

148 name_in_raft=name, 

149 purpose=purpose, 

150 raft=group, 

151 ) 

152 

153 def makeDataIdTranslatorFactory(self) -> TranslatorFactory: 

154 # Docstring inherited from lsst.obs.base.Instrument. 

155 factory = TranslatorFactory() 

156 factory.addGenericInstrumentRules(self.getName(), detectorKey="detector", exposureKey="expId") 

157 return factory 

158 

159 

160class LsstComCam(LsstCam): 

161 """Gen3 Butler specialization for ComCam data. 

162 """ 

163 

164 instrument = "LSSTComCam" 

165 policyName = "comCam" 

166 translatorClass = LsstComCamTranslator 

167 

168 def getRawFormatter(self, dataId): 

169 # local import to prevent circular dependency 

170 from .rawFormatter import LsstComCamRawFormatter 

171 return LsstComCamRawFormatter 

172 

173 

174class LsstImSim(LsstCam): 

175 """Gen3 Butler specialization for ImSim simulations. 

176 """ 

177 

178 instrument = "LSST-ImSim" 

179 policyName = "imsim" 

180 translatorClass = LsstImSimTranslator 

181 

182 def getRawFormatter(self, dataId): 

183 # local import to prevent circular dependency 

184 from .rawFormatter import LsstImSimRawFormatter 

185 return LsstImSimRawFormatter 

186 

187 

188class LsstPhoSim(LsstCam): 

189 """Gen3 Butler specialization for Phosim simulations. 

190 """ 

191 

192 instrument = "LSST-PhoSim" 

193 policyName = "phosim" 

194 translatorClass = LsstPhoSimTranslator 

195 

196 def getRawFormatter(self, dataId): 

197 # local import to prevent circular dependency 

198 from .rawFormatter import LsstPhoSimRawFormatter 

199 return LsstPhoSimRawFormatter 

200 

201 

202class LsstTS8(LsstCam): 

203 """Gen3 Butler specialization for raft test stand data. 

204 """ 

205 

206 instrument = "LSST-TS8" 

207 policyName = "ts8" 

208 translatorClass = LsstTS8Translator 

209 

210 def getRawFormatter(self, dataId): 

211 # local import to prevent circular dependency 

212 from .rawFormatter import LsstTS8RawFormatter 

213 return LsstTS8RawFormatter 

214 

215 

216class LsstUCDCam(LsstCam): 

217 """Gen3 Butler specialization for UCDCam test stand data. 

218 """ 

219 

220 instrument = "LSST-UCDCam" 

221 policyName = "ucd" 

222 translatorClass = LsstUCDCamTranslator 

223 

224 def getRawFormatter(self, dataId): 

225 # local import to prevent circular dependency 

226 from .rawFormatter import LsstUCDCamRawFormatter 

227 return LsstUCDCamRawFormatter 

228 

229 

230class LsstTS3(LsstCam): 

231 """Gen3 Butler specialization for TS3 test stand data. 

232 """ 

233 

234 instrument = "LSST-TS3" 

235 policyName = "ts3" 

236 translatorClass = LsstTS3Translator 

237 

238 def getRawFormatter(self, dataId): 

239 # local import to prevent circular dependency 

240 from .rawFormatter import LsstTS3RawFormatter 

241 return LsstTS3RawFormatter 

242 

243 

244class Latiss(LsstCam): 

245 """Gen3 Butler specialization for AuxTel LATISS data. 

246 """ 

247 filterDefinitions = LATISS_FILTER_DEFINITIONS 

248 instrument = "LATISS" 

249 policyName = "latiss" 

250 translatorClass = LatissTranslator 

251 

252 def extractDetectorRecord(self, camGeomDetector): 

253 # Override to remove group (raft) name, because LATISS only has one 

254 # detector. 

255 record = super().extractDetectorRecord(camGeomDetector) 

256 record["raft"] = None 

257 record["name_in_raft"] = record["full_name"] 

258 return record 

259 

260 def getRawFormatter(self, dataId): 

261 # local import to prevent circular dependency 

262 from .rawFormatter import LatissRawFormatter 

263 return LatissRawFormatter