24 "NumberSciSourcesMetricTask",
"NumberSciSourcesMetricConfig",
25 "FractionDiaSourcesToSciSourcesMetricTask",
"FractionDiaSourcesToSciSourcesMetricConfig",
30 import astropy.units
as u
32 from lsst.pipe.base
import Struct, connectionTypes
33 from lsst.verify
import Measurement
34 from lsst.verify.gen2tasks
import register
35 from lsst.verify.tasks
import MetricTask, MetricConfig, MetricConnections, \
36 MetricComputationError
41 defaultTemplates={
"package":
"ip_diffim",
42 "metric":
"numSciSources"},
43 dimensions={
"Instrument",
"Exposure",
"Detector"},
45 sources = connectionTypes.Input(
46 doc=
"The catalog of science sources.",
48 storageClass=
"SourceCatalog",
49 dimensions={
"Instrument",
"Exposure",
"Detector"},
53 class NumberSciSourcesMetricConfig(
55 pipelineConnections=NumberSciSourcesMetricConnections):
60 class NumberSciSourcesMetricTask(MetricTask):
61 """Task that computes the number of cataloged non-sky science sources.
65 The task excludes any sky sources in the catalog, but it does not require
66 that the catalog include a ``sky_sources`` column.
68 _DefaultName =
"numSciSources"
69 ConfigClass = NumberSciSourcesMetricConfig
71 def run(self, sources):
72 """Count the number of non-sky science sources.
76 sources : `lsst.afw.table.SourceCatalog` or `None`
77 A science source catalog, which may be empty or `None`.
81 result : `lsst.pipe.base.Struct`
82 A `~lsst.pipe.base.Struct` containing the following component:
85 the total number of non-sky science sources (`lsst.verify.Measurement`
88 if sources
is not None:
89 nSciSources = _countRealSources(sources)
90 meas = Measurement(self.config.metricName, nSciSources * u.count)
92 self.log.info(
"Nothing to do: no catalogs found.")
94 return Struct(measurement=meas)
97 class FractionDiaSourcesToSciSourcesMetricConnections(
98 MetricTask.ConfigClass.ConnectionsClass,
99 dimensions={
"Instrument",
"Exposure",
"Detector"},
100 defaultTemplates={
"coaddName":
"deep",
101 "package":
"ip_diffim",
102 "metric":
"fracDiaSourcesToSciSources"}):
103 sciSources = connectionTypes.Input(
104 doc=
"The catalog of science sources.",
106 storageClass=
"SourceCatalog",
107 dimensions={
"Instrument",
"Exposure",
"Detector"},
109 diaSources = connectionTypes.Input(
110 doc=
"The catalog of DIASources.",
111 name=
"{coaddName}Diff_diaSrc",
112 storageClass=
"SourceCatalog",
113 dimensions={
"Instrument",
"Exposure",
"Detector"},
117 class FractionDiaSourcesToSciSourcesMetricConfig(
118 MetricTask.ConfigClass,
119 pipelineConnections=FractionDiaSourcesToSciSourcesMetricConnections):
123 @
register(
"fracDiaSourcesToSciSources")
124 class FractionDiaSourcesToSciSourcesMetricTask(MetricTask):
125 """Task that computes the ratio of difference image sources to science
126 sources in an image, visit, etc.
130 The task excludes any sky sources in the direct source catalog, but it
131 does not require that either catalog include a ``sky_sources`` column.
133 _DefaultName =
"fracDiaSourcesToSciSources"
134 ConfigClass = FractionDiaSourcesToSciSourcesMetricConfig
136 def run(self, sciSources, diaSources):
137 """Compute the ratio of DIASources to non-sky science sources.
141 sciSources : `lsst.afw.table.SourceCatalog` or `None`
142 A science source catalog, which may be empty or `None`.
143 diaSources : `lsst.afw.table.SourceCatalog` or `None`
144 A DIASource catalog for the same unit of processing
149 result : `lsst.pipe.base.Struct`
150 A `~lsst.pipe.base.Struct` containing the following component:
153 the ratio (`lsst.verify.Measurement` or `None`)
155 if diaSources
is not None and sciSources
is not None:
156 nSciSources = _countRealSources(sciSources)
157 nDiaSources = _countRealSources(diaSources)
158 metricName = self.config.metricName
159 if nSciSources <= 0.0:
160 raise MetricComputationError(
161 "No science sources found; ratio of DIASources to science sources ill-defined.")
163 meas = Measurement(metricName, nDiaSources / nSciSources * u.dimensionless_unscaled)
165 self.log.info(
"Nothing to do: no catalogs found.")
167 return Struct(measurement=meas)
170 def _countRealSources(catalog):
171 """Return the number of valid sources in a catalog.
173 At present, this definition excludes sky sources. If a catalog does not
174 have a ``sky_source`` flag, all sources are assumed to be non-sky.
178 `catalog` : `lsst.afw.table.SourceCatalog`
179 The catalog of sources to count.
184 The number of sources that satisfy the criteria.
186 if "sky_source" in catalog.schema:
187 return np.count_nonzero(catalog[
"sky_source"] ==
False)