Coverage for python/lsst/faro/measurement/TractMeasurement.py: 55%
48 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-26 10:14 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-26 10:14 +0000
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/>.
22from lsst.afw.geom import SkyWcs
23from lsst.afw.image import PhotoCalib
24from lsst.afw.table import SourceCatalog
25import lsst.pex.config as pexConfig
26import lsst.pipe.base as pipeBase
28from lsst.faro.base.BaseSubTasks import NumSourcesMergeTask
29from lsst.faro.base.CatalogMeasurementBase import (
30 CatalogMeasurementBaseConnections,
31 CatalogMeasurementBaseConfig,
32 CatalogMeasurementBaseTask,
33)
34from lsst.faro.utils.calibrated_catalog import CalibratedCatalog
36from collections import defaultdict
37from typing import List
39__all__ = (
40 "TractMeasurementConnections",
41 "TractMeasurementConfig",
42 "TractMeasurementTask",
43 "TractMultiBandMeasurementConnections",
44 "TractMultiBandMeasurementConfig",
45 "TractMultiBandMeasurementTask",
46)
49class TractMeasurementConnections(
50 CatalogMeasurementBaseConnections,
51 dimensions=("tract", "skymap", "band"),
52 defaultTemplates={
53 "coaddName": "deepCoadd",
54 "photoCalibName": "deepCoadd_calexp.photoCalib",
55 "wcsName": "deepCoadd_calexp.wcs",
56 },
57):
59 catalogs = pipeBase.connectionTypes.Input(
60 doc="Object catalog.",
61 dimensions=("tract", "patch", "skymap", "band"),
62 storageClass="SourceCatalog",
63 name="deepCoadd_meas",
64 multiple=True,
65 )
67 photoCalibs = pipeBase.connectionTypes.Input(
68 doc="Photometric calibration object.",
69 dimensions=("tract", "patch", "skymap", "band"),
70 storageClass="PhotoCalib",
71 name="{photoCalibName}",
72 multiple=True,
73 )
75 astromCalibs = pipeBase.connectionTypes.Input(
76 doc="WCS for the catalog.",
77 dimensions=("tract", "patch", "skymap", "band"),
78 storageClass="Wcs",
79 name="{wcsName}",
80 multiple=True,
81 )
83 measurement = pipeBase.connectionTypes.Output(
84 doc="Per-tract measurement.",
85 dimensions=("tract", "skymap", "band"),
86 storageClass="MetricValue",
87 name="metricvalue_{package}_{metric}",
88 )
91class TractMeasurementConfig(
92 CatalogMeasurementBaseConfig, pipelineConnections=TractMeasurementConnections
93):
94 measure = pexConfig.ConfigurableField(
95 # The (plain old) Task that actually measures the desired metric
96 # Should be overridden in pipelines
97 target=NumSourcesMergeTask,
98 doc="Measure task",
99 )
102class TractMeasurementTask(CatalogMeasurementBaseTask):
104 ConfigClass = TractMeasurementConfig
105 _DefaultName = "tractMeasurementTask"
107 def run(
108 self,
109 catalogs: List[SourceCatalog],
110 photoCalibs: List[PhotoCalib],
111 astromCalibs: List[SkyWcs],
112 dataIds,
113 ):
114 data = defaultdict(list)
115 for catalog, photoCalib, astromCalib, dataId in zip(catalogs, photoCalibs, astromCalibs, dataIds):
116 if self.config.requireAstrometry and astromCalib is None:
117 self.log.info("requireAstrometry is True but astromCalib is None for %s. Skipping...",
118 dataId)
119 continue
120 if self.config.requirePhotometry and photoCalib is None:
121 self.log.info("requirePhotometry is True but photoCalib is None for %s. Skipping...",
122 dataId)
123 continue
124 data[dataId['band']].append(CalibratedCatalog(catalog, photoCalib, astromCalib))
126 return self.measure.run(self.config.connections.metric, data)
128 def runQuantum(self, butlerQC, inputRefs, outputRefs):
129 inputs = butlerQC.get(inputRefs)
130 inputs["dataIds"] = [
131 butlerQC.registry.expandDataId(cat.dataId) for cat in inputRefs.catalogs
132 ]
133 outputs = self.run(**inputs)
134 if outputs.measurement is not None:
135 butlerQC.put(outputs, outputRefs)
136 else:
137 self.log.debug(
138 "Skipping measurement of {!r} on {} " "as not applicable.",
139 self,
140 inputRefs,
141 )
144class TractMultiBandMeasurementConnections(
145 TractMeasurementConnections,
146 dimensions=("tract", "skymap"),
147 defaultTemplates={
148 "coaddName": "deepCoadd",
149 "photoCalibName": "deepCoadd_calexp.photoCalib",
150 },
151):
153 catalogs = pipeBase.connectionTypes.Input(
154 doc="Object catalog.",
155 dimensions=("tract", "skymap", "patch", "band"),
156 storageClass="SourceCatalog",
157 name="deepCoadd_forced_src",
158 multiple=True,
159 )
161 photoCalibs = pipeBase.connectionTypes.Input(
162 doc="Photometric calibration object.",
163 dimensions=("tract", "skymap", "patch", "band"),
164 storageClass="PhotoCalib",
165 name="{photoCalibName}",
166 multiple=True,
167 )
169 measurement = pipeBase.connectionTypes.Output(
170 doc="Per-tract measurement.",
171 dimensions=("tract", "skymap"),
172 storageClass="MetricValue",
173 name="metricvalue_{package}_{metric}",
174 )
177class TractMultiBandMeasurementConfig(
178 CatalogMeasurementBaseConfig,
179 pipelineConnections=TractMultiBandMeasurementConnections,
180):
181 pass
184class TractMultiBandMeasurementTask(TractMeasurementTask):
186 ConfigClass = TractMultiBandMeasurementConfig
187 _DefaultName = "tractMultiBandMeasurementTask"