24 "NumberSciSourcesMetricTask",
"NumberSciSourcesMetricConfig",
25 "FractionDiaSourcesToSciSourcesMetricTask",
"FractionDiaSourcesToSciSourcesMetricConfig",
30import astropy.units
as u
33from lsst.verify
import Measurement
34from lsst.verify.tasks
import MetricTask, MetricConfig, MetricConnections, \
35 MetricComputationError
40 defaultTemplates={
"package":
"ip_diffim",
41 "metric":
"numSciSources"},
42 dimensions={
"instrument",
"visit",
"detector"},
44 sources = connectionTypes.Input(
45 doc=
"The catalog of science sources.",
47 storageClass=
"SourceCatalog",
48 dimensions={
"instrument",
"visit",
"detector"},
52class NumberSciSourcesMetricConfig(
54 pipelineConnections=NumberSciSourcesMetricConnections):
58class NumberSciSourcesMetricTask(MetricTask):
59 """Task that computes the number of cataloged non-primary science sources.
63 The task excludes any non-primary sources in the catalog, but it does
64 not require that the catalog include a ``detect_isPrimary``
or
65 ``sky_sources`` column.
67 _DefaultName = "numSciSources"
68 ConfigClass = NumberSciSourcesMetricConfig
70 def run(self, sources):
71 """Count the number of non-primary science sources.
76 A science source catalog, which may be empty
or `
None`.
80 result : `lsst.pipe.base.Struct`
81 A `~lsst.pipe.base.Struct` containing the following component:
84 the total number of non-primary science sources
85 (`lsst.verify.Measurement`
or `
None`)
87 if sources
is not None:
88 nSciSources = _countRealSources(sources)
89 meas = Measurement(self.config.metricName, nSciSources * u.count)
91 self.log.info(
"Nothing to do: no catalogs found.")
93 return Struct(measurement=meas)
96class FractionDiaSourcesToSciSourcesMetricConnections(
97 MetricTask.ConfigClass.ConnectionsClass,
98 dimensions={
"instrument",
"visit",
"detector"},
99 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",
"visit",
"detector"},
109 diaSources = connectionTypes.Input(
110 doc=
"The catalog of DIASources.",
111 name=
"{fakesType}{coaddName}Diff_diaSrc",
112 storageClass=
"SourceCatalog",
113 dimensions={
"instrument",
"visit",
"detector"},
117class FractionDiaSourcesToSciSourcesMetricConfig(
118 MetricTask.ConfigClass,
119 pipelineConnections=FractionDiaSourcesToSciSourcesMetricConnections):
123class FractionDiaSourcesToSciSourcesMetricTask(MetricTask):
124 """Task that computes the ratio of difference image sources to science
125 sources in an image, visit, etc.
129 The task excludes any non-primary sources
in the catalog, but it does
130 not require that the catalog include a ``detect_isPrimary``
or
131 ``sky_sources`` column.
133 _DefaultName = "fracDiaSourcesToSciSources"
134 ConfigClass = FractionDiaSourcesToSciSourcesMetricConfig
136 def run(self, sciSources, diaSources):
137 """Compute the ratio of DIASources to non-primary science sources.
142 A science source catalog, which may be empty
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
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)
170def _countRealSources(catalog):
171 """Return the number of valid sources in a catalog.
173 At present, this definition includes only primary sources. If a catalog
174 does not have a ``detect_isPrimary`` flag, this function counts non-sky
175 sources. If it does
not have a ``sky_source`` flag, either, all sources
181 The catalog of sources to count.
186 The number of sources that satisfy the criteria.
190 if "detect_isPrimary" in catalog.schema:
191 return np.count_nonzero(catalog[
"detect_isPrimary"] ==
True)
192 elif "sky_source" in catalog.schema:
193 return np.count_nonzero(catalog[
"sky_source"] ==
False)
def run(self, coaddExposures, bbox, wcs, dataIds, **kwargs)