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-primary science sources.
65 The task excludes any non-primary sources in the catalog, but it does
66 not require that the catalog include a ``detect_isPrimary`` or
67 ``sky_sources`` column.
69 _DefaultName =
"numSciSources"
70 ConfigClass = NumberSciSourcesMetricConfig
72 def run(self, sources):
73 """Count the number of non-primary science sources.
77 sources : `lsst.afw.table.SourceCatalog` or `None`
78 A science source catalog, which may be empty or `None`.
82 result : `lsst.pipe.base.Struct`
83 A `~lsst.pipe.base.Struct` containing the following component:
86 the total number of non-primary science sources
87 (`lsst.verify.Measurement` or `None`)
89 if sources
is not None:
90 nSciSources = _countRealSources(sources)
91 meas = Measurement(self.config.metricName, nSciSources * u.count)
93 self.log.info(
"Nothing to do: no catalogs found.")
95 return Struct(measurement=meas)
98 class FractionDiaSourcesToSciSourcesMetricConnections(
99 MetricTask.ConfigClass.ConnectionsClass,
100 dimensions={
"instrument",
"visit",
"detector"},
101 defaultTemplates={
"coaddName":
"deep",
103 "package":
"ip_diffim",
104 "metric":
"fracDiaSourcesToSciSources"}):
105 sciSources = connectionTypes.Input(
106 doc=
"The catalog of science sources.",
108 storageClass=
"SourceCatalog",
109 dimensions={
"instrument",
"visit",
"detector"},
111 diaSources = connectionTypes.Input(
112 doc=
"The catalog of DIASources.",
113 name=
"{fakesType}{coaddName}Diff_diaSrc",
114 storageClass=
"SourceCatalog",
115 dimensions={
"instrument",
"visit",
"detector"},
119 class FractionDiaSourcesToSciSourcesMetricConfig(
120 MetricTask.ConfigClass,
121 pipelineConnections=FractionDiaSourcesToSciSourcesMetricConnections):
125 @register("fracDiaSourcesToSciSources")
126 class FractionDiaSourcesToSciSourcesMetricTask(MetricTask):
127 """Task that computes the ratio of difference image sources to science
128 sources in an image, visit, etc.
132 The task excludes any non-primary sources in the catalog, but it does
133 not require that the catalog include a ``detect_isPrimary`` or
134 ``sky_sources`` column.
136 _DefaultName =
"fracDiaSourcesToSciSources"
137 ConfigClass = FractionDiaSourcesToSciSourcesMetricConfig
139 def run(self, sciSources, diaSources):
140 """Compute the ratio of DIASources to non-primary science sources.
144 sciSources : `lsst.afw.table.SourceCatalog` or `None`
145 A science source catalog, which may be empty or `None`.
146 diaSources : `lsst.afw.table.SourceCatalog` or `None`
147 A DIASource catalog for the same unit of processing
152 result : `lsst.pipe.base.Struct`
153 A `~lsst.pipe.base.Struct` containing the following component:
156 the ratio (`lsst.verify.Measurement` or `None`)
158 if diaSources
is not None and sciSources
is not None:
159 nSciSources = _countRealSources(sciSources)
160 nDiaSources = _countRealSources(diaSources)
161 metricName = self.config.metricName
163 raise MetricComputationError(
164 "No science sources found; ratio of DIASources to science sources ill-defined.")
166 meas = Measurement(metricName, nDiaSources / nSciSources * u.dimensionless_unscaled)
168 self.log.info(
"Nothing to do: no catalogs found.")
170 return Struct(measurement=meas)
173 def _countRealSources(catalog):
174 """Return the number of valid sources in a catalog.
176 At present, this definition includes only primary sources. If a catalog
177 does not have a ``detect_isPrimary`` flag, this function counts non-sky
178 sources. If it does not have a ``sky_source`` flag, either, all sources
183 `catalog` : `lsst.afw.table.SourceCatalog`
184 The catalog of sources to count.
189 The number of sources that satisfy the criteria.
193 if "detect_isPrimary" in catalog.schema:
194 return np.count_nonzero(catalog[
"detect_isPrimary"] ==
True)
195 elif "sky_source" in catalog.schema:
196 return np.count_nonzero(catalog[
"sky_source"] ==
False)
def run(self, coaddExposures, bbox, wcs)