LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
LSST Data Management Base Package
deblendCoaddSourcesPipeline.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
22import numpy as np
23
24from lsst.pipe.base import (Struct, PipelineTask, PipelineTaskConfig, PipelineTaskConnections)
25import lsst.pipe.base.connectionTypes as cT
26
27from lsst.pex.config import ConfigurableField
28from lsst.meas.deblender import SourceDeblendTask
29from lsst.meas.extensions.scarlet import ScarletDeblendTask
30from lsst.obs.base import ExposureIdInfo
31
32import lsst.afw.image as afwImage
33import lsst.afw.table as afwTable
34
35from .makeCoaddTempExp import reorderRefs
36
37__all__ = ("DeblendCoaddSourcesSingleConfig", "DeblendCoaddSourcesSingleTask",
38 "DeblendCoaddSourcesMultiConfig", "DeblendCoaddSourcesMultiTask")
39
40
41deblendBaseTemplates = {"inputCoaddName": "deep", "outputCoaddName": "deep"}
42
43
44class DeblendCoaddSourceSingleConnections(PipelineTaskConnections,
45 dimensions=("tract", "patch", "band", "skymap"),
46 defaultTemplates=deblendBaseTemplates):
47 inputSchema = cT.InitInput(
48 doc="Input schema to use in the deblend catalog",
49 name="{inputCoaddName}Coadd_mergeDet_schema",
50 storageClass="SourceCatalog"
51 )
52 peakSchema = cT.InitInput(
53 doc="Schema of the footprint peak catalogs",
54 name="{inputCoaddName}Coadd_peak_schema",
55 storageClass="PeakCatalog"
56 )
57 mergedDetections = cT.Input(
58 doc="Detection catalog merged across bands",
59 name="{inputCoaddName}Coadd_mergeDet",
60 storageClass="SourceCatalog",
61 dimensions=("tract", "patch", "skymap")
62 )
63 coadd = cT.Input(
64 doc="Exposure on which to run deblending",
65 name="{inputCoaddName}Coadd_calexp",
66 storageClass="ExposureF",
67 dimensions=("tract", "patch", "band", "skymap")
68 )
69 measureCatalog = cT.Output(
70 doc="The output measurement catalog of deblended sources",
71 name="{outputCoaddName}Coadd_deblendedFlux",
72 storageClass="SourceCatalog",
73 dimensions=("tract", "patch", "band", "skymap")
74 )
75 outputSchema = cT.InitOutput(
76 doc="Output of the schema used in deblending task",
77 name="{outputCoaddName}Coadd_deblendedFlux_schema",
78 storageClass="SourceCatalog"
79 )
80
81 def setDefaults(self):
82 super().setDefaults()
83 self.singleBandDeblend.propagateAllPeaks = True
84
85
86class DeblendCoaddSourcesSingleConfig(PipelineTaskConfig,
87 pipelineConnections=DeblendCoaddSourceSingleConnections):
88 singleBandDeblend = ConfigurableField(
89 target=SourceDeblendTask,
90 doc="Task to deblend an image in one band"
91 )
92
93
94class DeblendCoaddSourcesMultiConnections(PipelineTaskConnections,
95 dimensions=("tract", "patch", "skymap"),
96 defaultTemplates=deblendBaseTemplates):
97 inputSchema = cT.InitInput(
98 doc="Input schema to use in the deblend catalog",
99 name="{inputCoaddName}Coadd_mergeDet_schema",
100 storageClass="SourceCatalog"
101 )
102 peakSchema = cT.InitInput(
103 doc="Schema of the footprint peak catalogs",
104 name="{inputCoaddName}Coadd_peak_schema",
105 storageClass="PeakCatalog"
106 )
107 mergedDetections = cT.Input(
108 doc="Detection catalog merged across bands",
109 name="{inputCoaddName}Coadd_mergeDet",
110 storageClass="SourceCatalog",
111 dimensions=("tract", "patch", "skymap")
112 )
113 coadds = cT.Input(
114 doc="Exposure on which to run deblending",
115 name="{inputCoaddName}Coadd_calexp",
116 storageClass="ExposureF",
117 multiple=True,
118 dimensions=("tract", "patch", "band", "skymap")
119 )
120 outputSchema = cT.InitOutput(
121 doc="Output of the schema used in deblending task",
122 name="{outputCoaddName}Coadd_deblendedFlux_schema",
123 storageClass="SourceCatalog"
124 )
125 fluxCatalogs = cT.Output(
126 doc="Flux weighted catalogs produced by multiband deblending",
127 name="{outputCoaddName}Coadd_deblendedFlux",
128 storageClass="SourceCatalog",
129 dimensions=("tract", "patch", "band", "skymap"),
130 multiple=True
131 )
132 templateCatalogs = cT.Output(
133 doc="Template catalogs produced by multiband deblending",
134 name="{outputCoaddName}Coadd_deblendedModel",
135 storageClass="SourceCatalog",
136 dimensions=("tract", "patch", "band", "skymap"),
137 multiple=True
138 )
139 deblendedCatalog = cT.Output(
140 doc="Catalogs produced by multiband deblending",
141 name="{outputCoaddName}Coadd_deblendedCatalog",
142 storageClass="SourceCatalog",
143 dimensions=("tract", "patch", "skymap"),
144 )
145 scarletModelData = cT.Output(
146 doc="Multiband scarlet models produced by the deblender",
147 name="{outputCoaddName}Coadd_scarletModelData",
148 storageClass="ScarletModelData",
149 dimensions=("tract", "patch", "skymap"),
150 )
151
152 def __init__(self, *, config=None):
153 super().__init__(config=config)
154 # Remove unused connections.
155 # TODO: deprecate once RFC-860 passes.
156 self.outputs -= set(("fluxCatalogs", "templateCatalogs"))
157
158
159class DeblendCoaddSourcesMultiConfig(PipelineTaskConfig,
160 pipelineConnections=DeblendCoaddSourcesMultiConnections):
161 multibandDeblend = ConfigurableField(
162 target=ScarletDeblendTask,
163 doc="Task to deblend an images in multiple bands"
164 )
165
166
167class DeblendCoaddSourcesBaseTask(PipelineTask):
168 def __init__(self, initInputs, **kwargs):
169 super().__init__(initInputs=initInputs, **kwargs)
170 schema = initInputs["inputSchema"].schema
171 self.peakSchemapeakSchema = initInputs["peakSchema"].schema
172 self.schemaMapperschemaMapper = afwTable.SchemaMapper(schema)
173 self.schemaMapperschemaMapper.addMinimalSchema(schema)
174 self.schemaschema = self.schemaMapperschemaMapper.getOutputSchema()
175
176 def runQuantum(self, butlerQC, inputRefs, outputRefs):
177 inputs = butlerQC.get(inputRefs)
178 inputs["idFactory"] = ExposureIdInfo.fromDataId(
179 butlerQC.quantum.dataId,
180 "tract_patch"
181 ).makeSourceIdFactory()
182 outputs = self.run(**inputs)
183 butlerQC.put(outputs, outputRefs)
184
185 def _makeSourceCatalog(self, mergedDetections, idFactory):
186 # There may be gaps in the mergeDet catalog, which will cause the
187 # source ids to be inconsistent. So we update the id factory
188 # with the largest id already in the catalog.
189 maxId = np.max(mergedDetections["id"])
190 idFactory.notify(maxId)
191 table = afwTable.SourceTable.make(self.schemaschema, idFactory)
192 sources = afwTable.SourceCatalog(table)
193 sources.extend(mergedDetections, self.schemaMapperschemaMapper)
194 return sources
195
196
198 ConfigClass = DeblendCoaddSourcesSingleConfig
199 _DefaultName = "deblendCoaddSourcesSingle"
200
201 def __init__(self, initInputs, **kwargs):
202 super().__init__(initInputs=initInputs, **kwargs)
203 self.makeSubtask("singleBandDeblend", schema=self.schemaschema, peakSchema=self.peakSchemapeakSchema)
204 self.outputSchemaoutputSchema = afwTable.SourceCatalog(self.schemaschema)
205
206 def run(self, coadd, mergedDetections, idFactory):
207 sources = self._makeSourceCatalog_makeSourceCatalog(mergedDetections, idFactory)
208 self.singleBandDeblend.run(coadd, sources)
209 if not sources.isContiguous():
210 sources = sources.copy(deep=True)
211 return Struct(measureCatalog=sources)
212
213
215 ConfigClass = DeblendCoaddSourcesMultiConfig
216 _DefaultName = "deblendCoaddSourcesMulti"
217
218 def __init__(self, initInputs, **kwargs):
219 super().__init__(initInputs=initInputs, **kwargs)
220 self.makeSubtask("multibandDeblend", schema=self.schemaschema, peakSchema=self.peakSchemapeakSchema)
221 self.outputSchemaoutputSchema = afwTable.SourceCatalog(self.schemaschema)
222
223 def runQuantum(self, butlerQC, inputRefs, outputRefs):
224 # Obtain the list of bands, sort them (alphabetically), then reorder
225 # all input lists to match this band order.
226 bandOrder = [dRef.dataId["band"] for dRef in inputRefs.coadds]
227 bandOrder.sort()
228 inputRefs = reorderRefs(inputRefs, bandOrder, dataIdKey="band")
229 inputs = butlerQC.get(inputRefs)
230 exposureIdInfo = ExposureIdInfo.fromDataId(butlerQC.quantum.dataId, "tract_patch")
231 inputs["idFactory"] = exposureIdInfo.makeSourceIdFactory()
232 inputs["filters"] = [dRef.dataId["band"] for dRef in inputRefs.coadds]
233 outputs = self.runrun(**inputs)
234 butlerQC.put(outputs, outputRefs)
235
236 def run(self, coadds, filters, mergedDetections, idFactory):
237 sources = self._makeSourceCatalog_makeSourceCatalog(mergedDetections, idFactory)
238 multiExposure = afwImage.MultibandExposure.fromExposures(filters, coadds)
239 catalog, modelData = self.multibandDeblend.run(multiExposure, sources)
240 retStruct = Struct(deblendedCatalog=catalog, scarletModelData=modelData)
241 return retStruct
A mapping between the keys of two Schemas, used to copy data between them.
Definition: SchemaMapper.h:21
daf::base::PropertySet * set
Definition: fits.cc:912
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.