Coverage for python/lsst/faro/base/BaseSubTasks.py : 43%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# This file is part of faro.
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/>.
22import astropy.units as u
23import numpy as np
24from lsst.pipe.base import Struct, Task
25from lsst.pex.config import Config, Field
26from lsst.verify import Measurement
28from lsst.faro.utils.matcher import mergeCatalogs
30__all__ = (
31 "NumSourcesTask",
32 "NumSourcesMergeTask",
33 "NumpySummaryConfig",
34 "NumpySummaryTask",
35)
38class NumSourcesConfig(Config):
39 doPrimary = Field(
40 doc="Only count sources where detect_isPrimary is True.",
41 dtype=bool,
42 default=False,
43 )
46class NumSourcesTask(Task):
47 r"""Simple default task count the number of sources/objects in catalog."""
49 ConfigClass = NumSourcesConfig
50 _DefaultName = "numSourcesTask"
52 def run(self, metricName, catalog, **kwargs):
53 """Run NumSourcesTask
55 Parameters
56 ----------
57 metricName : `str`
58 The name of the metric to measure.
59 catalog : `dict`
60 `lsst.afw.table` Catalog type
61 kwargs
62 Extra keyword arguments used to construct the task.
64 Returns
65 -------
66 measurement : `Struct`
67 The measured value of the metric.
68 """
69 self.log.info("Measuring %s", metricName)
70 if self.config.doPrimary:
71 nSources = np.sum(catalog["detect_isPrimary"] is True)
72 else:
73 nSources = len(catalog)
74 self.log.info("Number of sources (nSources) = %i" % nSources)
75 meas = Measurement("nsrcMeas", nSources * u.count)
76 return Struct(measurement=meas)
79class NumSourcesMergeTask(Task):
81 ConfigClass = Config
82 _DefaultName = "numSourcesMergeTask"
84 def run(self, metricName, catalogs, photoCalibs, astromCalibs, **kwargs):
85 self.log.info("Measuring %s", metricName)
86 catalog = mergeCatalogs(catalogs, photoCalibs, astromCalibs)
87 nSources = len(catalog)
88 meas = Measurement("nsrcMeas", nSources * u.count)
89 return Struct(measurement=meas)
92class NumpySummaryConfig(Config):
93 summary = Field(
94 dtype=str, default="median", doc="Aggregation to use for summary metrics"
95 )
98class NumpySummaryTask(Task):
100 ConfigClass = NumpySummaryConfig
101 _DefaultName = "numpySummaryTask"
103 def run(self, measurements, agg_name, package, metric):
104 agg = agg_name.lower()
105 if agg == "summary":
106 agg = self.config.summary
107 self.log.info("Computing the %s of %s_%s values", agg, package, metric)
109 if len(measurements) == 0:
110 self.log.info("Received zero length measurements list. Returning NaN.")
111 # In the case of an empty list, there is nothing we can do other than
112 # to return a NaN
113 value = u.Quantity(np.nan)
114 else:
115 unit = measurements[0].quantity.unit
116 value = getattr(np, agg)(
117 u.Quantity(
118 [x.quantity for x in measurements if np.isfinite(x.quantity)]
119 )
120 )
121 # Make sure return has same unit as inputs
122 # In some cases numpy can return a NaN and the unit gets dropped
123 value = value.value * unit
124 return Struct(
125 measurement=Measurement(
126 f"metricvalue_{agg_name.lower()}_{package}_{metric}", value
127 )
128 )