24 "NumberSciSourcesMetricTask",
"NumberSciSourcesMetricConfig",
25 "FractionDiaSourcesToSciSourcesMetricTask",
"FractionDiaSourcesToSciSourcesMetricConfig",
30import astropy.units
as u
32from lsst.pipe.base
import Struct, connectionTypes
33from lsst.verify
import Measurement
34from lsst.verify.gen2tasks
import register
35from 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"},
53class NumberSciSourcesMetricConfig(
55 pipelineConnections=NumberSciSourcesMetricConnections):
59@register("numSciSources")
60class 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.
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)
98class 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"},
119class FractionDiaSourcesToSciSourcesMetricConfig(
120 MetricTask.ConfigClass,
121 pipelineConnections=FractionDiaSourcesToSciSourcesMetricConnections):
125@register("fracDiaSourcesToSciSources")
126class 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.
145 A science source catalog, which may be empty
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)
173def _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
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)