Coverage for python/lsst/faro/measurement/DetectorMeasurement.py: 36%

57 statements  

« prev     ^ index     » next       coverage.py v6.4.1, created at 2022-06-09 03:41 -0700

1# This file is part of faro. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (https://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 <https://www.gnu.org/licenses/>. 

21 

22import lsst.pipe.base as pipeBase 

23import lsst.pex.config as pexConfig 

24 

25from lsst.faro.base.CatalogMeasurementBase import ( 

26 CatalogMeasurementBaseConnections, 

27 CatalogMeasurementBaseConfig, 

28 CatalogMeasurementBaseTask, 

29) 

30 

31__all__ = ("DetectorMeasurementConfig", "DetectorMeasurementTask") 

32 

33 

34class DetectorMeasurementConnections( 

35 CatalogMeasurementBaseConnections, 

36 dimensions=("instrument", "visit", "detector", "band"), 

37 defaultTemplates={ 

38 "photoCalibName": "calexp.photoCalib", 

39 "externalPhotoCalibName": "fgcm", 

40 "wcsName": "calexp.wcs", 

41 "externalWcsName": "jointcal", 

42 }, 

43): 

44 

45 catalog = pipeBase.connectionTypes.Input( 

46 doc="Source catalog.", 

47 dimensions=("instrument", "visit", "detector", "band"), 

48 storageClass="SourceCatalog", 

49 name="src", 

50 ) 

51 skyWcs = pipeBase.connectionTypes.Input( 

52 doc="WCS for the catalog.", 

53 dimensions=("instrument", "visit", "detector", "band"), 

54 storageClass="Wcs", 

55 name="{wcsName}", 

56 ) 

57 photoCalib = pipeBase.connectionTypes.Input( 

58 doc="Photometric calibration object.", 

59 dimensions=("instrument", "visit", "detector", "band"), 

60 storageClass="PhotoCalib", 

61 name="{photoCalibName}", 

62 ) 

63 externalSkyWcsTractCatalog = pipeBase.connectionTypes.Input( 

64 doc=( 

65 "Per-tract, per-visit wcs calibrations. These catalogs use the detector " 

66 "id for the catalog id, sorted on id for fast lookup." 

67 ), 

68 name="{externalWcsName}SkyWcsCatalog", 

69 storageClass="ExposureCatalog", 

70 dimensions=("instrument", "visit", "tract"), 

71 ) 

72 externalSkyWcsGlobalCatalog = pipeBase.connectionTypes.Input( 

73 doc=( 

74 "Per-visit wcs calibrations computed globally (with no tract information). " 

75 "These catalogs use the detector id for the catalog id, sorted on id for " 

76 "fast lookup." 

77 ), 

78 name="{externalWcsName}SkyWcsCatalog", 

79 storageClass="ExposureCatalog", 

80 dimensions=("instrument", "visit"), 

81 ) 

82 externalPhotoCalibTractCatalog = pipeBase.connectionTypes.Input( 

83 doc=( 

84 "Per-tract, per-visit photometric calibrations. These catalogs use the " 

85 "detector id for the catalog id, sorted on id for fast lookup." 

86 ), 

87 name="{externalPhotoCalibName}PhotoCalibCatalog", 

88 storageClass="ExposureCatalog", 

89 dimensions=("instrument", "visit", "tract"), 

90 ) 

91 externalPhotoCalibGlobalCatalog = pipeBase.connectionTypes.Input( 

92 doc=( 

93 "Per-visit photometric calibrations computed globally (with no tract " 

94 "information). These catalogs use the detector id for the catalog id, " 

95 "sorted on id for fast lookup." 

96 ), 

97 name="{externalPhotoCalibName}PhotoCalibCatalog", 

98 storageClass="ExposureCatalog", 

99 dimensions=("instrument", "visit"), 

100 ) 

101 measurement = pipeBase.connectionTypes.Output( 

102 doc="Per-detector measurement.", 

103 dimensions=("instrument", "visit", "detector", "band"), 

104 storageClass="MetricValue", 

105 name="metricvalue_{package}_{metric}", 

106 ) 

107 

108 def __init__(self, *, config=None): 

109 super().__init__(config=config) 

110 if config.doApplyExternalSkyWcs: 

111 if config.useGlobalExternalSkyWcs: 

112 self.inputs.remove("externalSkyWcsTractCatalog") 

113 else: 

114 self.inputs.remove("externalSkyWcsGlobalCatalog") 

115 else: 

116 self.inputs.remove("externalSkyWcsTractCatalog") 

117 self.inputs.remove("externalSkyWcsGlobalCatalog") 

118 if config.doApplyExternalPhotoCalib: 

119 if config.useGlobalExternalPhotoCalib: 

120 self.inputs.remove("externalPhotoCalibTractCatalog") 

121 else: 

122 self.inputs.remove("externalPhotoCalibGlobalCatalog") 

123 else: 

124 self.inputs.remove("externalPhotoCalibTractCatalog") 

125 self.inputs.remove("externalPhotoCalibGlobalCatalog") 

126 

127 

128class DetectorMeasurementConfig( 

129 CatalogMeasurementBaseConfig, pipelineConnections=DetectorMeasurementConnections 

130): 

131 doApplyExternalSkyWcs = pexConfig.Field( 

132 doc="Whether or not to use the external wcs.", dtype=bool, default=False 

133 ) 

134 useGlobalExternalSkyWcs = pexConfig.Field( 

135 doc="Whether or not to use the global external wcs.", dtype=bool, default=False 

136 ) 

137 doApplyExternalPhotoCalib = pexConfig.Field( 

138 doc="Whether or not to use the external photoCalib.", dtype=bool, default=False 

139 ) 

140 useGlobalExternalPhotoCalib = pexConfig.Field( 

141 doc="Whether or not to use the global external photoCalib.", 

142 dtype=bool, 

143 default=False, 

144 ) 

145 

146 

147class DetectorMeasurementTask(CatalogMeasurementBaseTask): 

148 ConfigClass = DetectorMeasurementConfig 

149 _DefaultName = "detectorMeasurementTask" 

150 

151 def runQuantum(self, butlerQC, inputRefs, outputRefs): 

152 inputs = butlerQC.get(inputRefs) 

153 if self.config.doApplyExternalPhotoCalib: 

154 detector = inputRefs.catalog.dataId["detector"] 

155 if self.config.useGlobalExternalPhotoCalib: 

156 externalPhotoCalibCatalog = inputs.pop( 

157 "externalPhotoCalibGlobalCatalog" 

158 ) 

159 else: 

160 externalPhotoCalibCatalog = inputs.pop("externalPhotoCalibTractCatalog") 

161 row = externalPhotoCalibCatalog.find(detector) 

162 externalPhotoCalib = row.getPhotoCalib() 

163 inputs["photoCalib"] = externalPhotoCalib 

164 if self.config.doApplyExternalSkyWcs: 

165 detector = inputRefs.catalog.dataId["detector"] 

166 if self.config.useGlobalExternalSkyWcs: 

167 externalSkyWcsCatalog = inputs.pop("externalSkyWcsGlobalCatalog") 

168 else: 

169 externalSkyWcsCatalog = inputs.pop("externalSkyWcsTractCatalog") 

170 row = externalSkyWcsCatalog.find(detector) 

171 externalSkyWcs = row.getWcs() 

172 inputs["skyWcs"] = externalSkyWcs 

173 

174 outputs = self.run(**inputs) 

175 if outputs.measurement is not None: 

176 butlerQC.put(outputs, outputRefs) 

177 else: 

178 self.log.debug( 

179 "Skipping measurement of {!r} on {} " "as not applicable.", 

180 self, 

181 inputRefs, 

182 )