Coverage for python/lsst/faro/measurement/DetectorMeasurement.py : 32%

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 product includes software developed by the LSST Project
2# (https://www.lsst.org).
3# See the COPYRIGHT file at the top-level directory of this distribution
4# for details of code ownership.
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program. If not, see <https://www.gnu.org/licenses/>.
19import lsst.pipe.base as pipeBase
20from lsst.verify.tasks import MetricConnections
21import lsst.pex.config as pexConfig
23from lsst.faro.base.CatalogMeasurementBase import CatalogMeasurementBaseConfig, CatalogMeasurementBaseTask
25__all__ = ("DetectorMeasurementConfig", "DetectorMeasurementTask")
28class DetectorMeasurementConnections(MetricConnections,
29 dimensions=("instrument", "visit", "detector", "band"),
30 defaultTemplates={"photoCalibName": "calexp.photoCalib",
31 "externalPhotoCalibName": "fgcm",
32 "wcsName": "calexp.wcs",
33 "externalWcsName": "jointcal"}):
35 catalog = pipeBase.connectionTypes.Input(
36 doc="Source catalog.",
37 dimensions=("instrument", "visit", "detector", "band"),
38 storageClass="SourceCatalog",
39 name="src"
40 )
41 skyWcs = pipeBase.connectionTypes.Input(
42 doc="WCS for the catalog.",
43 dimensions=("instrument", "visit", "detector", "band"),
44 storageClass="Wcs",
45 name="{wcsName}"
46 )
47 photoCalib = pipeBase.connectionTypes.Input(
48 doc="Photometric calibration object.",
49 dimensions=("instrument", "visit", "detector", "band"),
50 storageClass="PhotoCalib",
51 name="{photoCalibName}"
52 )
53 externalSkyWcsTractCatalog = pipeBase.connectionTypes.Input(
54 doc=("Per-tract, per-visit wcs calibrations. These catalogs use the detector "
55 "id for the catalog id, sorted on id for fast lookup."),
56 name="{externalWcsName}SkyWcsCatalog",
57 storageClass="ExposureCatalog",
58 dimensions=("instrument", "visit", "tract"),
59 )
60 externalSkyWcsGlobalCatalog = pipeBase.connectionTypes.Input(
61 doc=("Per-visit wcs calibrations computed globally (with no tract information). "
62 "These catalogs use the detector id for the catalog id, sorted on id for "
63 "fast lookup."),
64 name="{externalWcsName}SkyWcsCatalog",
65 storageClass="ExposureCatalog",
66 dimensions=("instrument", "visit"),
67 )
68 externalPhotoCalibTractCatalog = pipeBase.connectionTypes.Input(
69 doc=("Per-tract, per-visit photometric calibrations. These catalogs use the "
70 "detector id for the catalog id, sorted on id for fast lookup."),
71 name="{externalPhotoCalibName}PhotoCalibCatalog",
72 storageClass="ExposureCatalog",
73 dimensions=("instrument", "visit", "tract"),
74 )
75 externalPhotoCalibGlobalCatalog = pipeBase.connectionTypes.Input(
76 doc=("Per-visit photometric calibrations computed globally (with no tract "
77 "information). These catalogs use the detector id for the catalog id, "
78 "sorted on id for fast lookup."),
79 name="{externalPhotoCalibName}PhotoCalibCatalog",
80 storageClass="ExposureCatalog",
81 dimensions=("instrument", "visit"),
82 )
83 measurement = pipeBase.connectionTypes.Output(
84 doc="Per-detector measurement.",
85 dimensions=("instrument", "visit", "detector", "band"),
86 storageClass="MetricValue",
87 name="metricvalue_{package}_{metric}"
88 )
90 def __init__(self, *, config=None):
91 super().__init__(config=config)
92 if config.doApplyExternalSkyWcs:
93 if config.useGlobalExternalSkyWcs:
94 self.inputs.remove("externalSkyWcsTractCatalog")
95 else:
96 self.inputs.remove("externalSkyWcsGlobalCatalog")
97 else:
98 self.inputs.remove("externalSkyWcsTractCatalog")
99 self.inputs.remove("externalSkyWcsGlobalCatalog")
100 if config.doApplyExternalPhotoCalib:
101 if config.useGlobalExternalPhotoCalib:
102 self.inputs.remove("externalPhotoCalibTractCatalog")
103 else:
104 self.inputs.remove("externalPhotoCalibGlobalCatalog")
105 else:
106 self.inputs.remove("externalPhotoCalibTractCatalog")
107 self.inputs.remove("externalPhotoCalibGlobalCatalog")
110class DetectorMeasurementConfig(CatalogMeasurementBaseConfig,
111 pipelineConnections=DetectorMeasurementConnections):
112 doApplyExternalSkyWcs = pexConfig.Field(doc="Whether or not to use the external wcs.",
113 dtype=bool, default=False)
114 useGlobalExternalSkyWcs = pexConfig.Field(doc="Whether or not to use the global external wcs.",
115 dtype=bool, default=False)
116 doApplyExternalPhotoCalib = pexConfig.Field(doc="Whether or not to use the external photoCalib.",
117 dtype=bool, default=False)
118 useGlobalExternalPhotoCalib = pexConfig.Field(doc="Whether or not to use the global external photoCalib.",
119 dtype=bool, default=False)
122class DetectorMeasurementTask(CatalogMeasurementBaseTask):
123 ConfigClass = DetectorMeasurementConfig
124 _DefaultName = "detectorMeasurementTask"
126 def runQuantum(self, butlerQC, inputRefs, outputRefs):
127 inputs = butlerQC.get(inputRefs)
128 if self.config.doApplyExternalPhotoCalib:
129 detector = inputRefs.catalog.dataId['detector']
130 if self.config.useGlobalExternalPhotoCalib:
131 externalPhotoCalibCatalog = inputs.pop('externalPhotoCalibGlobalCatalog')
132 else:
133 externalPhotoCalibCatalog = inputs.pop('externalPhotoCalibTractCatalog')
134 row = externalPhotoCalibCatalog.find(detector)
135 externalPhotoCalib = row.getPhotoCalib()
136 inputs['photoCalib'] = externalPhotoCalib
137 if self.config.doApplyExternalSkyWcs:
138 detector = inputRefs.catalog.dataId['detector']
139 if self.config.useGlobalExternalSkyWcs:
140 externalSkyWcsCatalog = inputs.pop('externalSkyWcsGlobalCatalog')
141 else:
142 externalSkyWcsCatalog = inputs.pop('externalSkyWcsTractCatalog')
143 row = externalSkyWcsCatalog.find(detector)
144 externalSkyWcs = row.getWcs()
145 inputs['skyWcs'] = externalSkyWcs
147 outputs = self.run(**inputs)
148 if outputs.measurement is not None:
149 butlerQC.put(outputs, outputRefs)
150 else:
151 self.log.debug("Skipping measurement of {!r} on {} "
152 "as not applicable.", self, inputRefs)