Coverage for python/lsst/faro/measurement/TractMeasurement.py: 55%
48 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-14 11:26 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-14 11:26 +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"] = [cat.dataId for cat in inputRefs.catalogs]
131 outputs = self.run(**inputs)
132 if outputs.measurement is not None:
133 butlerQC.put(outputs, outputRefs)
134 else:
135 self.log.debug(
136 "Skipping measurement of {!r} on {} " "as not applicable.",
137 self,
138 inputRefs,
139 )
142class TractMultiBandMeasurementConnections(
143 TractMeasurementConnections,
144 dimensions=("tract", "skymap"),
145 defaultTemplates={
146 "coaddName": "deepCoadd",
147 "photoCalibName": "deepCoadd_calexp.photoCalib",
148 },
149):
151 catalogs = pipeBase.connectionTypes.Input(
152 doc="Object catalog.",
153 dimensions=("tract", "skymap", "patch", "band"),
154 storageClass="SourceCatalog",
155 name="deepCoadd_forced_src",
156 multiple=True,
157 )
159 photoCalibs = pipeBase.connectionTypes.Input(
160 doc="Photometric calibration object.",
161 dimensions=("tract", "skymap", "patch", "band"),
162 storageClass="PhotoCalib",
163 name="{photoCalibName}",
164 multiple=True,
165 )
167 measurement = pipeBase.connectionTypes.Output(
168 doc="Per-tract measurement.",
169 dimensions=("tract", "skymap"),
170 storageClass="MetricValue",
171 name="metricvalue_{package}_{metric}",
172 )
175class TractMultiBandMeasurementConfig(
176 CatalogMeasurementBaseConfig,
177 pipelineConnections=TractMultiBandMeasurementConnections,
178):
179 pass
182class TractMultiBandMeasurementTask(TractMeasurementTask):
184 ConfigClass = TractMultiBandMeasurementConfig
185 _DefaultName = "tractMultiBandMeasurementTask"