LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
metrics.py
Go to the documentation of this file.
1 # This file is part of pipe_tasks.
2 #
3 # Developed for the LSST Data Management System.
4 # This product includes software developed by the LSST Project
5 # (https://www.lsst.org).
6 # See the COPYRIGHT file at the top-level directory of this distribution
7 # for details of code ownership.
8 #
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <https://www.gnu.org/licenses/>.
21 
22 __all__ = [
23  "NumberDeblendedSourcesMetricTask", "NumberDeblendedSourcesMetricConfig",
24  "NumberDeblendChildSourcesMetricTask", "NumberDeblendChildSourcesMetricConfig",
25 ]
26 
27 
28 import numpy as np
29 import astropy.units as u
30 
31 from lsst.pipe.base import Struct, connectionTypes
32 from lsst.verify import Measurement
33 from lsst.verify.gen2tasks import register
34 from lsst.verify.tasks import MetricTask, MetricConfig, MetricConnections, MetricComputationError
35 
36 
38  MetricConnections,
39  defaultTemplates={"package": "pipe_tasks",
40  "metric": "numDeblendedSciSources"},
41  dimensions={"instrument", "visit", "detector"},
42 ):
43  sources = connectionTypes.Input(
44  doc="The catalog of science sources.",
45  name="src",
46  storageClass="SourceCatalog",
47  dimensions={"instrument", "visit", "detector"},
48  )
49 
50 
51 class NumberDeblendedSourcesMetricConfig(
52  MetricConfig,
53  pipelineConnections=NumberDeblendedSourcesMetricConnections):
54  pass
55 
56 
57 @register("numDeblendedSciSources")
58 class NumberDeblendedSourcesMetricTask(MetricTask):
59  """Task that computes the number of science sources that have
60  been deblended.
61 
62  This task only counts sources that existed prior to any deblending;
63  i.e., if deblending was run more than once or with multiple iterations,
64  only the "top-level" deblended sources are counted, and not any
65  intermediate ones. If sky source information is present, sky sources
66  are excluded.
67 
68  Notes
69  -----
70  The task excludes any non-sky sources in the catalog, but it does
71  not require that the catalog include a ``sky_sources`` column.
72  """
73  _DefaultName = "numDeblendedSciSources"
74  ConfigClass = NumberDeblendedSourcesMetricConfig
75 
76  def run(self, sources):
77  """Count the number of deblended science sources.
78 
79  Parameters
80  ----------
81  sources : `lsst.afw.table.SourceCatalog` or `None`
82  A science source catalog, which may be empty or `None`.
83 
84  Returns
85  -------
86  result : `lsst.pipe.base.Struct`
87  A `~lsst.pipe.base.Struct` containing the following component:
88 
89  ``measurement``
90  the total number of deblended science sources
91  (`lsst.verify.Measurement`). If no deblending information is
92  available in ``sources``, this is `None`.
93 
94  Raises
95  ------
96  MetricComputationError
97  Raised if ``sources`` is missing mandatory keys for
98  source catalogs.
99  """
100  if sources is None:
101  self.log.info("Nothing to do: no catalogs found.")
102  meas = None
103  elif "deblend_nChild" not in sources.schema:
104  self.log.info("Nothing to do: no deblending performed.")
105  meas = None
106  else:
107  try:
108  deblended = ((sources["parent"] == 0) # top-level source
109  & (sources["deblend_nChild"] > 0) # deblended
110  )
111  deblended = _filterSkySources(sources, deblended)
112  except LookupError as e:
113  # Probably "parent"; all other columns already checked
114  raise MetricComputationError("Invalid input catalog") from e
115  else:
116  nDeblended = np.count_nonzero(deblended)
117  meas = Measurement(self.config.metricName, nDeblended * u.dimensionless_unscaled)
118 
119  return Struct(measurement=meas)
120 
121 
122 class NumberDeblendChildSourcesMetricConnections(
123  MetricConnections,
124  defaultTemplates={"package": "pipe_tasks",
125  "metric": "numDeblendChildSciSources"},
126  dimensions={"instrument", "visit", "detector"},
127 ):
128  sources = connectionTypes.Input(
129  doc="The catalog of science sources.",
130  name="src",
131  storageClass="SourceCatalog",
132  dimensions={"instrument", "visit", "detector"},
133  )
134 
135 
136 class NumberDeblendChildSourcesMetricConfig(
137  MetricConfig,
138  pipelineConnections=NumberDeblendChildSourcesMetricConnections):
139  pass
140 
141 
142 @register("numDeblendChildSciSources")
143 class NumberDeblendChildSourcesMetricTask(MetricTask):
144  """Task that computes the number of science sources created
145  through deblending.
146 
147  This task only counts final deblending products; i.e., if deblending was
148  run more than once or with multiple iterations, only the final set of
149  deblended sources are counted, and not any intermediate ones.
150  If sky source information is present, sky sources are excluded.
151 
152  Notes
153  -----
154  The task excludes any non-sky sources in the catalog, but it does
155  not require that the catalog include a ``sky_sources`` column.
156  """
157  _DefaultName = "numDeblendChildSciSources"
158  ConfigClass = NumberDeblendChildSourcesMetricConfig
159 
160  def run(self, sources):
161  """Count the number of science sources created by deblending.
162 
163  Parameters
164  ----------
165  sources : `lsst.afw.table.SourceCatalog` or `None`
166  A science source catalog, which may be empty or `None`.
167 
168  Returns
169  -------
170  result : `lsst.pipe.base.Struct`
171  A `~lsst.pipe.base.Struct` containing the following component:
172 
173  ``measurement``
174  the total number of science sources from deblending
175  (`lsst.verify.Measurement`). If no deblending information is
176  available in ``sources``, this is `None`.
177 
178  Raises
179  ------
180  MetricComputationError
181  Raised if ``sources`` is missing mandatory keys for
182  source catalogs.
183  """
184  if sources is None:
185  self.log.info("Nothing to do: no catalogs found.")
186  meas = None
187  # Use deblend_parentNChild rather than detect_fromBlend because the
188  # latter need not be defined in post-deblending catalogs.
189  elif "deblend_parentNChild" not in sources.schema or "deblend_nChild" not in sources.schema:
190  self.log.info("Nothing to do: no deblending performed.")
191  meas = None
192  else:
193  try:
194  children = ((sources["deblend_parentNChild"] > 1) # deblend child
195  & (sources["deblend_nChild"] == 0) # not deblended
196  )
197  children = _filterSkySources(sources, children)
198  except LookupError as e:
199  # Probably "parent"; all other columns already checked
200  raise MetricComputationError("Invalid input catalog") from e
201  else:
202  nChildren = np.count_nonzero(children)
203  meas = Measurement(self.config.metricName, nChildren * u.dimensionless_unscaled)
204 
205  return Struct(measurement=meas)
206 
207 
208 def _filterSkySources(catalog, selection):
209  """Filter out any sky sources from a vector of selected sources.
210 
211  If no sky source information is available, all sources are assumed to
212  be non-sky.
213 
214  Parameters
215  ----------
216  catalog : `lsst.afw.table.SourceCatalog`
217  The catalog to filter.
218  selection : `numpy.ndarray` [`bool`], (N,)
219  A vector of existing source selections, of the same length as
220  ``catalog``, where selected sources are marked `True`.
221 
222  Returns
223  -------
224  filtered : `numpy.ndarray` [`bool`], (N,)
225  A version of ``selection`` with any sky sources filtered out
226  (set to `False`). May be the same vector as ``selection`` if
227  no changes were made.
228  """
229  if "sky_source" in catalog.schema:
230  # E712 is not applicable, because afw.table.SourceRecord.ColumnView
231  # is not a bool.
232  return selection & (catalog["sky_source"] == False) # noqa: E712
233  else:
234  return selection
def run(self, coaddExposures, bbox, wcs)
Definition: getTemplate.py:603