Coverage for python/lsst/faro/measurement/TractTableMeasurement.py: 29%

60 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-04-12 03:02 -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 "TractTableMeasurementConnections", 

35 "TractTableMeasurementConfig", 

36 "TractTableMeasurementTask", 

37 "TractMultiBandTableMeasurementConnections", 

38 "TractMultiBandTableMeasurementConfig", 

39 "TractMultiBandTableMeasurementTask", 

40) 

41 

42 

43class TractTableMeasurementConnections( 

44 CatalogMeasurementBaseConnections, 

45 dimensions=("tract", "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", "skymap", "band"), 

59 storageClass="MetricValue", 

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

61 ) 

62 

63 

64class TractTableMeasurementConfig( 

65 CatalogMeasurementBaseConfig, pipelineConnections=TractTableMeasurementConnections 

66): 

67 """Configuration for TractTableMeasurementTask.""" 

68 

69 instrument = pexConfig.Field( 

70 doc="Instrument.", 

71 dtype=str, 

72 default='hsc', 

73 ) 

74 

75 

76class TractTableMeasurementTask(CatalogMeasurementBaseTask): 

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

78 

79 ConfigClass = TractTableMeasurementConfig 

80 _DefaultName = "tractTableMeasurementTask" 

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 for column in self.config.measure.columnsBand.values(): 

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

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

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

91 

92 # maybe include an if statement to check whether any selectors have been requested 

93 

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

95 refCats = inputs.pop("refCat") 

96 filter_map = FilterMap() 

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

98 [kwargs["currentBands"]]) 

99 

100 # TODO: add capability to select the reference epoch 

101 epoch = None 

102 refCatFrame = self._getReferenceCatalog( 

103 butlerQC, 

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

105 refCats, 

106 filterList, 

107 epoch, 

108 ) 

109 kwargs["refCatFrame"] = refCatFrame 

110 

111 outputs = self.run(**kwargs) 

112 if outputs.measurement is not None: 

113 butlerQC.put(outputs, outputRefs) 

114 else: 

115 self.log.debug( 

116 "Skipping measurement of %r on %s as not applicable.", 

117 self, 

118 inputRefs, 

119 ) 

120 

121 

122class TractMultiBandTableMeasurementConnections( 

123 TractTableMeasurementConnections, 

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

125): 

126 

127 catalog = pipeBase.connectionTypes.Input( 

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

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

130 storageClass="DataFrame", 

131 name="objectTable_tract", 

132 deferLoad=True, 

133 ) 

134 

135 measurement = pipeBase.connectionTypes.Output( 

136 doc="Per-tract measurement.", 

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

138 storageClass="MetricValue", 

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

140 ) 

141 

142 

143class TractMultiBandTableMeasurementConfig( 

144 TractTableMeasurementConfig, 

145 pipelineConnections=TractMultiBandTableMeasurementConnections, 

146): 

147 """Configuration for TractMultiBandTableMeasurementTask.""" 

148 

149 bands = pexConfig.ListField( 

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

151 dtype=str, 

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

153 ) 

154 

155 

156class TractMultiBandTableMeasurementTask(TractTableMeasurementTask): 

157 

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

159 

160 ConfigClass = TractMultiBandTableMeasurementConfig 

161 _DefaultName = "tractMultiBandTableMeasurementTask" 

162 

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

164 inputs = butlerQC.get(inputRefs) 

165 

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

167 

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

169 for band in self.config.bands: 

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

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

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

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

174 

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

176 refCats = inputs.pop("refCat") 

177 filter_map = FilterMap() 

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

179 self.config.bands) 

180 

181 # TODO: add capability to select the reference epoch 

182 epoch = None 

183 refCat = self._getReferenceCatalog( 

184 butlerQC, 

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

186 refCats, 

187 filterList, 

188 epoch, 

189 ) 

190 kwargs["refCat"] = refCat 

191 

192 outputs = self.run(**kwargs) 

193 if outputs.measurement is not None: 

194 butlerQC.put(outputs, outputRefs) 

195 else: 

196 self.log.debug( 

197 "Skipping measurement of %r on %s as not applicable.", 

198 self, 

199 inputRefs, 

200 )