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",
"visit",
"detector"},
45 sources = connectionTypes.Input(
46 doc=
"The catalog of science sources.",
48 storageClass=
"SourceCatalog",
49 dimensions={
"instrument",
"visit",
"detector"},
53 class NumberSciSourcesMetricConfig(
55 pipelineConnections=NumberSciSourcesMetricConnections):
59 @register("numSciSources")
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",
"visit",
"detector"},
100 defaultTemplates={
"coaddName":
"deep",
102 "package":
"ip_diffim",
103 "metric":
"fracDiaSourcesToSciSources"}):
104 sciSources = connectionTypes.Input(
105 doc=
"The catalog of science sources.",
107 storageClass=
"SourceCatalog",
108 dimensions={
"instrument",
"visit",
"detector"},
110 diaSources = connectionTypes.Input(
111 doc=
"The catalog of DIASources.",
112 name=
"{fakesType}{coaddName}Diff_diaSrc",
113 storageClass=
"SourceCatalog",
114 dimensions={
"instrument",
"visit",
"detector"},
118 class FractionDiaSourcesToSciSourcesMetricConfig(
119 MetricTask.ConfigClass,
120 pipelineConnections=FractionDiaSourcesToSciSourcesMetricConnections):
124 @register("fracDiaSourcesToSciSources")
125 class FractionDiaSourcesToSciSourcesMetricTask(MetricTask):
126 """Task that computes the ratio of difference image sources to science
127 sources in an image, visit, etc.
131 The task excludes any sky sources in the direct source catalog, but it
132 does not require that either catalog include a ``sky_sources`` column.
134 _DefaultName =
"fracDiaSourcesToSciSources"
135 ConfigClass = FractionDiaSourcesToSciSourcesMetricConfig
137 def run(self, sciSources, diaSources):
138 """Compute the ratio of DIASources to non-sky science sources.
142 sciSources : `lsst.afw.table.SourceCatalog` or `None`
143 A science source catalog, which may be empty or `None`.
144 diaSources : `lsst.afw.table.SourceCatalog` or `None`
145 A DIASource catalog for the same unit of processing
150 result : `lsst.pipe.base.Struct`
151 A `~lsst.pipe.base.Struct` containing the following component:
154 the ratio (`lsst.verify.Measurement` or `None`)
156 if diaSources
is not None and sciSources
is not None:
157 nSciSources = _countRealSources(sciSources)
158 nDiaSources = _countRealSources(diaSources)
159 metricName = self.config.metricName
160 if nSciSources <= 0.0:
161 raise MetricComputationError(
162 "No science sources found; ratio of DIASources to science sources ill-defined.")
164 meas = Measurement(metricName, nDiaSources / nSciSources * u.dimensionless_unscaled)
166 self.log.info(
"Nothing to do: no catalogs found.")
168 return Struct(measurement=meas)
171 def _countRealSources(catalog):
172 """Return the number of valid sources in a catalog.
174 At present, this definition excludes sky sources. If a catalog does not
175 have a ``sky_source`` flag, all sources are assumed to be non-sky.
179 `catalog` : `lsst.afw.table.SourceCatalog`
180 The catalog of sources to count.
185 The number of sources that satisfy the criteria.
187 if "sky_source" in catalog.schema:
188 return np.count_nonzero(catalog[
"sky_source"] ==
False)