Coverage for python/lsst/ap/pipe/metrics.py: 58%

44 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-10-30 02:59 -0700

1# This file is part of ap_pipe. 

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 

23"""Metrics for ap_pipe tasks. 

24""" 

25 

26__all__ = [ 

27 "ApFakesCompletenessMetricTask", "ApFakesCompletenessMetricConfig", 

28 "ApFakesCountMetricTask", "ApFakesCountMetricConfig" 

29] 

30 

31import astropy.units as u 

32import numpy as np 

33 

34import lsst.pex.config as pexConfig 

35from lsst.pipe.base import Struct 

36import lsst.pipe.base.connectionTypes as connTypes 

37from lsst.pipe.tasks.insertFakes import InsertFakesConfig 

38from lsst.verify import Measurement 

39from lsst.verify.tasks import MetricTask, MetricComputationError 

40 

41 

42class ApFakesCompletenessMetricConnections( 

43 MetricTask.ConfigClass.ConnectionsClass, 

44 dimensions={"instrument", "visit", "detector", "band"}, 

45 defaultTemplates={"coaddName": "deep", 

46 "fakesType": "fakes_", 

47 "package": "ap_pipe", 

48 "metric": "apFakesCompleteness"}): 

49 """ApFakesCompleteness connections. 

50 """ 

51 matchedFakes = connTypes.Input( 

52 doc="Fakes matched to their detections in the difference image.", 

53 name="{fakesType}{coaddName}Diff_matchDiaSrc", 

54 storageClass="DataFrame", 

55 dimensions=("instrument", "visit", "detector"), 

56 ) 

57 

58 

59# Inherits from InsertFakesConfig to preserve column names in the fakes 

60# catalog. 

61class ApFakesCompletenessMetricConfig( 

62 MetricTask.ConfigClass, 

63 InsertFakesConfig, 

64 pipelineConnections=ApFakesCompletenessMetricConnections): 

65 """ApFakesCompleteness config. 

66 """ 

67 magMin = pexConfig.RangeField( 

68 doc="Minimum of cut on magnitude range used to compute completeness " 

69 "in.", 

70 dtype=float, 

71 default=20, 

72 min=1, 

73 max=40, 

74 ) 

75 magMax = pexConfig.RangeField( 

76 doc="Maximum of cut on magnitude range used to compute completeness " 

77 "in.", 

78 dtype=int, 

79 default=30, 

80 min=1, 

81 max=40, 

82 ) 

83 

84 

85class ApFakesCompletenessMetricTask(MetricTask): 

86 """Metric task for summarizing the completeness of fakes inserted into the 

87 AP pipeline. 

88 """ 

89 _DefaultName = "apFakesCompleteness" 

90 ConfigClass = ApFakesCompletenessMetricConfig 

91 

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

93 """Do Butler I/O to provide in-memory objects for run. 

94 

95 This specialization of runQuantum passes the band ID to `run`. 

96 """ 

97 inputs = butlerQC.get(inputRefs) 

98 inputs["band"] = butlerQC.quantum.dataId["band"] 

99 outputs = self.run(**inputs) 

100 if outputs.measurement is not None: 

101 butlerQC.put(outputs, outputRefs) 

102 else: 

103 self.log.debug("Skipping measurement of %r on %s " 

104 "as not applicable.", self, inputRefs) 

105 

106 def run(self, matchedFakes, band): 

107 """Compute the completeness of recovered fakes within a magnitude 

108 range. 

109 

110 Parameters 

111 ---------- 

112 matchedFakes : `lsst.afw.table.SourceCatalog` 

113 Catalog of fakes that were inserted into the ccdExposure matched 

114 to their detected counterparts. 

115 band : `str` 

116 Name of the band whose magnitudes are to be analyzed. 

117 

118 Returns 

119 ------- 

120 result : `lsst.pipe.base.Struct` 

121 A `~lsst.pipe.base.Struct` containing the following component: 

122 ``measurement`` 

123 the ratio (`lsst.verify.Measurement` or `None`) 

124 """ 

125 magnitudes = np.fabs(matchedFakes[f"{self.config.mag_col}" % band]) 

126 magCutFakes = matchedFakes[np.logical_and(magnitudes > self.config.magMin, 

127 magnitudes < self.config.magMax)] 

128 if len(magCutFakes) <= 0.0: 

129 raise MetricComputationError( 

130 "No matched fakes catalog sources found; Completeness is " 

131 "ill defined.") 

132 else: 

133 meas = Measurement( 

134 self.config.metricName, 

135 ((magCutFakes["diaSourceId"] > 0).sum() / len(magCutFakes)) 

136 * u.dimensionless_unscaled) 

137 return Struct(measurement=meas) 

138 

139 

140class ApFakesCountMetricConnections( 

141 ApFakesCompletenessMetricConnections, 

142 dimensions={"instrument", "visit", "detector", "band"}, 

143 defaultTemplates={"coaddName": "deep", 

144 "fakesType": "fakes_", 

145 "package": "ap_pipe", 

146 "metric": "apFakesCompleteness"}): 

147 pass 

148 

149 

150class ApFakesCountMetricConfig( 

151 ApFakesCompletenessMetricConfig, 

152 pipelineConnections=ApFakesCountMetricConnections): 

153 """ApFakesCompleteness config. 

154 """ 

155 pass 

156 

157 

158class ApFakesCountMetricTask(ApFakesCompletenessMetricTask): 

159 """Metric task for summarizing the completeness of fakes inserted into the 

160 AP pipeline. 

161 """ 

162 _DefaultName = "apFakesCount" 

163 ConfigClass = ApFakesCountMetricConfig 

164 

165 def run(self, matchedFakes, band): 

166 """Compute the number of fakes inserted within a magnitude 

167 range. 

168 

169 Parameters 

170 ---------- 

171 matchedFakes : `lsst.afw.table.SourceCatalog` 

172 Catalog of fakes that were inserted into the ccdExposure matched 

173 to their detected counterparts. 

174 band : `str` 

175 Single character name of the observed band for this quanta. 

176 

177 Returns 

178 ------- 

179 result : `lsst.pipe.base.Struct` 

180 A `~lsst.pipe.base.Struct` containing the following component: 

181 ``measurement`` 

182 the ratio (`lsst.verify.Measurement` or `None`) 

183 """ 

184 magnitudes = np.fabs(matchedFakes[f"{self.config.mag_col}" % band]) 

185 magCutFakes = matchedFakes[np.logical_and(magnitudes > self.config.magMin, 

186 magnitudes < self.config.magMax)] 

187 meas = Measurement(self.config.metricName, 

188 len(magCutFakes) * u.count) 

189 return Struct(measurement=meas)