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

66 statements  

« prev     ^ index     » next       coverage.py v6.4.1, created at 2022-06-25 01:46 -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 

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 instrument = pexConfig.Field( 

70 doc="Instrument.", 

71 dtype=str, 

72 default='hsc', 

73 ) 

74 

75 

76class PatchTableMeasurementTask(CatalogMeasurementBaseTask): 

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

78 

79 ConfigClass = PatchTableMeasurementConfig 

80 _DefaultName = "patchTableMeasurementTask" 

81 

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

83 inputs = butlerQC.get(inputRefs) 

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

85 

86 columns = list(self.config.measure.columns.values()) 

87 columns.append("patch") 

88 

89 for column in self.config.measure.columnsBand.values(): 

90 columns.append(kwargs["currentBands"] + "_" + column) 

91 columnsWithSelectors = self._getTableColumnsSelectors(columns, kwargs["currentBands"]) 

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

93 

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

95 kwargs["catalog"] = catalog[selection] 

96 

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

98 refCats = inputs.pop("refCat") 

99 filter_map = FilterMap() 

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

101 [kwargs["currentBands"]]) 

102 

103 # TODO: add capability to select the reference epoch 

104 epoch = None 

105 refCat = self._getReferenceCatalog( 

106 butlerQC, 

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

108 refCats, 

109 filterList, 

110 epoch, 

111 ) 

112 kwargs["refCat"] = refCat 

113 

114 outputs = self.run(**kwargs) 

115 if outputs.measurement is not None: 

116 butlerQC.put(outputs, outputRefs) 

117 else: 

118 self.log.debugf( 

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

120 self, 

121 inputRefs, 

122 ) 

123 

124 

125class PatchMultiBandTableMeasurementConnections( 

126 PatchTableMeasurementConnections, 

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

128): 

129 

130 catalog = pipeBase.connectionTypes.Input( 

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

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

133 storageClass="DataFrame", 

134 name="objectTable_tract", 

135 deferLoad=True, 

136 ) 

137 

138 measurement = pipeBase.connectionTypes.Output( 

139 doc="Per-tract measurement.", 

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

141 storageClass="MetricValue", 

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

143 ) 

144 

145 

146class PatchMultiBandTableMeasurementConfig( 

147 PatchTableMeasurementConfig, 

148 pipelineConnections=PatchMultiBandTableMeasurementConnections, 

149): 

150 """Configuration for PatchMultiBandTableMeasurementTask.""" 

151 

152 bands = pexConfig.ListField( 

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

154 dtype=str, 

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

156 ) 

157 

158 

159class PatchMultiBandTableMeasurementTask(PatchTableMeasurementTask): 

160 

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

162 

163 ConfigClass = PatchMultiBandTableMeasurementConfig 

164 _DefaultName = "patchMultiBandTableMeasurementTask" 

165 

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

167 inputs = butlerQC.get(inputRefs) 

168 

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

170 

171 columns = list(self.config.measure.columns.values()) 

172 columns.append("patch") 

173 

174 for band in self.config.bands: 

175 for column in self.config.measure.columnsBand.values(): 

176 columns.append(band + "_" + column) 

177 columnsWithSelectors = self._getTableColumnsSelectors(columns, kwargs["currentBands"]) 

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

179 

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

181 kwargs["catalog"] = catalog[selection] 

182 

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

184 refCats = inputs.pop("refCat") 

185 filter_map = FilterMap() 

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

187 self.config.bands) 

188 

189 # TODO: add capability to select the reference epoch 

190 epoch = None 

191 refCat = self._getReferenceCatalog( 

192 butlerQC, 

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

194 refCats, 

195 filterList, 

196 epoch, 

197 ) 

198 kwargs["refCat"] = refCat 

199 

200 outputs = self.run(**kwargs) 

201 if outputs.measurement is not None: 

202 butlerQC.put(outputs, outputRefs) 

203 else: 

204 self.log.debugf( 

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

206 self, 

207 inputRefs, 

208 )