Coverage for python/lsst/ap/pipe/metrics.py: 58%
44 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-04 23:14 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-04 23:14 +0000
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#
23"""Metrics for ap_pipe tasks.
24"""
26__all__ = [
27 "ApFakesCompletenessMetricTask", "ApFakesCompletenessMetricConfig",
28 "ApFakesCountMetricTask", "ApFakesCountMetricConfig"
29]
31import astropy.units as u
32import numpy as np
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
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 )
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 )
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
92 def runQuantum(self, butlerQC, inputRefs, outputRefs):
93 """Do Butler I/O to provide in-memory objects for run.
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)
106 def run(self, matchedFakes, band):
107 """Compute the completeness of recovered fakes within a magnitude
108 range.
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.
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)
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
150class ApFakesCountMetricConfig(
151 ApFakesCompletenessMetricConfig,
152 pipelineConnections=ApFakesCountMetricConnections):
153 """ApFakesCompleteness config.
154 """
155 pass
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
165 def run(self, matchedFakes, band):
166 """Compute the number of fakes inserted within a magnitude
167 range.
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.
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)