Coverage for python/lsst/faro/measurement/PatchTableMeasurement.py: 39%

Shortcuts 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

66 statements  

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 

22 

23import lsst.pipe.base as pipeBase 

24import lsst.pex.config as pexConfig 

25 

26from lsst.faro.base.CatalogMeasurementBase import ( 

27 CatalogMeasurementBaseConnections, 

28 CatalogMeasurementBaseConfig, 

29 CatalogMeasurementBaseTask, 

30) 

31from lsst.faro.utils.filter_map import FilterMap 

32 

33__all__ = ( 

34 "PatchTableMeasurementConnections", 

35 "PatchTableMeasurementConfig", 

36 "PatchTableMeasurementTask", 

37 "PatchMultiBandTableMeasurementConnections", 

38 "PatchMultiBandTableMeasurementConfig", 

39 "PatchMultiBandTableMeasurementTask", 

40) 

41 

42 

43class PatchTableMeasurementConnections( 

44 CatalogMeasurementBaseConnections, 

45 dimensions=("tract", "patch", "skymap", "band"), 

46): 

47 

48 catalog = pipeBase.connectionTypes.Input( 

49 doc="Object table in parquet format, per tract.", 

50 dimensions=("tract", "skymap"), 

51 storageClass="DataFrame", 

52 name="objectTable_tract", 

53 deferLoad=True, 

54 ) 

55 

56 measurement = pipeBase.connectionTypes.Output( 

57 doc="Per-tract measurement.", 

58 dimensions=("tract", "patch", "skymap", "band"), 

59 storageClass="MetricValue", 

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

61 ) 

62 

63 

64class PatchTableMeasurementConfig( 

65 CatalogMeasurementBaseConfig, pipelineConnections=PatchTableMeasurementConnections 

66): 

67 """Configuration for PatchTableMeasurementTask.""" 

68 

69 columns = pexConfig.ListField( 

70 doc="Band-independent columns from objectTable_tract to load.", 

71 dtype=str, 

72 default=["coord_ra", "coord_dec", "detect_isPrimary", "patch"], 

73 ) 

74 

75 columnsBand = pexConfig.ListField( 

76 doc="Band-specific columns from objectTable_tract to load.", 

77 dtype=str, 

78 default=["psfFlux", "psfFluxErr"], 

79 ) 

80 

81 instrument = pexConfig.Field( 

82 doc="Instrument.", 

83 dtype=str, 

84 default='hsc', 

85 ) 

86 

87 

88class PatchTableMeasurementTask(CatalogMeasurementBaseTask): 

89 """Base class for per-band science performance metrics measured on single-tract object catalogs.""" 

90 

91 ConfigClass = PatchTableMeasurementConfig 

92 _DefaultName = "tractTableMeasurementTask" 

93 

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

95 inputs = butlerQC.get(inputRefs) 

96 kwargs = {"band": butlerQC.quantum.dataId['band']} 

97 

98 columns = self.config.columns.list() 

99 for column in self.config.columnsBand: 

100 columns.append(kwargs["band"] + column) 

101 catalog = inputs["catalog"].get(parameters={"columns": columns}) 

102 selection = (catalog["patch"] == butlerQC.quantum.dataId["patch"]) 

103 kwargs["catalog"] = catalog[selection] 

104 

105 if self.config.connections.refDataset != "": 

106 refCats = inputs.pop("refCat") 

107 filter_map = FilterMap() 

108 filterList = filter_map.getFilters(self.config.instrument, 

109 [kwargs["band"]]) 

110 

111 # TODO: add capability to select the reference epoch 

112 epoch = None 

113 refCat, refCatCorrected = self._getReferenceCatalog( 

114 butlerQC, 

115 [ref.datasetRef.dataId for ref in inputRefs.refCat], 

116 refCats, 

117 filterList, 

118 epoch, 

119 ) 

120 kwargs["refCat"] = refCat 

121 kwargs["refCatCorrected"] = refCatCorrected 

122 

123 outputs = self.run(**kwargs) 

124 if outputs.measurement is not None: 

125 butlerQC.put(outputs, outputRefs) 

126 else: 

127 self.log.debugf( 

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

129 self, 

130 inputRefs, 

131 ) 

132 

133 

134class PatchMultiBandTableMeasurementConnections( 

135 PatchTableMeasurementConnections, 

136 dimensions=("tract", "patch", "skymap"), 

137): 

138 

139 catalog = pipeBase.connectionTypes.Input( 

140 doc="Object table in parquet format, per tract.", 

141 dimensions=("tract", "skymap"), 

142 storageClass="DataFrame", 

143 name="objectTable_tract", 

144 deferLoad=True, 

145 ) 

146 

147 measurement = pipeBase.connectionTypes.Output( 

148 doc="Per-tract measurement.", 

149 dimensions=("tract", "patch", "skymap"), 

150 storageClass="MetricValue", 

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

152 ) 

153 

154 

155class PatchMultiBandTableMeasurementConfig( 

156 PatchTableMeasurementConfig, 

157 pipelineConnections=PatchMultiBandTableMeasurementConnections, 

158): 

159 """Configuration for PatchMultiBandTableMeasurementTask.""" 

160 

161 bands = pexConfig.ListField( 

162 doc="Bands for band-specific column loading from objectTable_tract.", 

163 dtype=str, 

164 default=["g", "r", "i", "z", "y"], 

165 ) 

166 

167 

168class PatchMultiBandTableMeasurementTask(PatchTableMeasurementTask): 

169 

170 """Base class for science performance metrics measured on single-tract source catalogs, multi-band.""" 

171 

172 ConfigClass = PatchMultiBandTableMeasurementConfig 

173 _DefaultName = "tractMultiBandTableMeasurementTask" 

174 

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

176 inputs = butlerQC.get(inputRefs) 

177 

178 kwargs = {"bands": self.config.bands.list()} 

179 

180 columns = self.config.columns.list() 

181 for band in self.config.bands: 

182 for column in self.config.columnsBand: 

183 columns.append(band + column) 

184 catalog = inputs["catalog"].get(parameters={"columns": columns}) 

185 selection = (catalog["patch"] == butlerQC.quantum.dataId["patch"]) 

186 kwargs["catalog"] = catalog[selection] 

187 

188 if self.config.connections.refDataset != "": 

189 refCats = inputs.pop("refCat") 

190 filter_map = FilterMap() 

191 filterList = filter_map.getFilters(self.config.instrument, 

192 self.config.bands) 

193 

194 # TODO: add capability to select the reference epoch 

195 epoch = None 

196 refCat, refCatCorrected = self._getReferenceCatalog( 

197 butlerQC, 

198 [ref.datasetRef.dataId for ref in inputRefs.refCat], 

199 refCats, 

200 filterList, 

201 epoch, 

202 ) 

203 kwargs["refCat"] = refCat 

204 kwargs["refCatCorrected"] = refCatCorrected 

205 

206 outputs = self.run(**kwargs) 

207 if outputs.measurement is not None: 

208 butlerQC.put(outputs, outputRefs) 

209 else: 

210 self.log.debugf( 

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

212 self, 

213 inputRefs, 

214 )