LSST Applications g063fba187b+cac8b7c890,g0f08755f38+6aee506743,g1653933729+a8ce1bb630,g168dd56ebc+a8ce1bb630,g1a2382251a+b4475c5878,g1dcb35cd9c+8f9bc1652e,g20f6ffc8e0+6aee506743,g217e2c1bcf+73dee94bd0,g28da252d5a+1f19c529b9,g2bbee38e9b+3f2625acfc,g2bc492864f+3f2625acfc,g3156d2b45e+6e55a43351,g32e5bea42b+1bb94961c2,g347aa1857d+3f2625acfc,g35bb328faa+a8ce1bb630,g3a166c0a6a+3f2625acfc,g3e281a1b8c+c5dd892a6c,g3e8969e208+a8ce1bb630,g414038480c+5927e1bc1e,g41af890bb2+8a9e676b2a,g7af13505b9+809c143d88,g80478fca09+6ef8b1810f,g82479be7b0+f568feb641,g858d7b2824+6aee506743,g89c8672015+f4add4ffd5,g9125e01d80+a8ce1bb630,ga5288a1d22+2903d499ea,gb58c049af0+d64f4d3760,gc28159a63d+3f2625acfc,gcab2d0539d+b12535109e,gcf0d15dbbd+46a3f46ba9,gda6a2b7d83+46a3f46ba9,gdaeeff99f8+1711a396fd,ge79ae78c31+3f2625acfc,gef2f8181fd+0a71e47438,gf0baf85859+c1f95f4921,gfa517265be+6aee506743,gfa999e8aa5+17cd334064,w.2024.51
LSST Data Management Base Package
Loading...
Searching...
No Matches
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
22__all__ = ["DeblendCoaddSourcesSingleConfig", "DeblendCoaddSourcesSingleTask",
23 "DeblendCoaddSourcesMultiConfig", "DeblendCoaddSourcesMultiTask"]
24
25import numpy as np
26
27from deprecated.sphinx import deprecated
28
29from lsst.pipe.base import (Struct, PipelineTask, PipelineTaskConfig, PipelineTaskConnections)
30import lsst.pipe.base.connectionTypes as cT
31
32from lsst.pex.config import ConfigurableField
33from lsst.meas.base import SkyMapIdGeneratorConfig
34from lsst.meas.deblender import SourceDeblendTask
35from lsst.meas.extensions.scarlet import ScarletDeblendTask
36
37import lsst.afw.image as afwImage
38import lsst.afw.table as afwTable
39
40from .makeWarp import reorderRefs
41
42
43deblendBaseTemplates = {"inputCoaddName": "deep", "outputCoaddName": "deep"}
44
45
46class DeblendCoaddSourceSingleConnections(PipelineTaskConnections,
47 dimensions=("tract", "patch", "band", "skymap"),
48 defaultTemplates=deblendBaseTemplates):
49 inputSchema = cT.InitInput(
50 doc="Input schema to use in the deblend catalog",
51 name="{inputCoaddName}Coadd_mergeDet_schema",
52 storageClass="SourceCatalog"
53 )
54 peakSchema = cT.InitInput(
55 doc="Schema of the footprint peak catalogs",
56 name="{inputCoaddName}Coadd_peak_schema",
57 storageClass="PeakCatalog"
58 )
59 mergedDetections = cT.Input(
60 doc="Detection catalog merged across bands",
61 name="{inputCoaddName}Coadd_mergeDet",
62 storageClass="SourceCatalog",
63 dimensions=("tract", "patch", "skymap")
64 )
65 coadd = cT.Input(
66 doc="Exposure on which to run deblending",
67 name="{inputCoaddName}Coadd_calexp",
68 storageClass="ExposureF",
69 dimensions=("tract", "patch", "band", "skymap")
70 )
71 measureCatalog = cT.Output(
72 doc="The output measurement catalog of deblended sources",
73 name="{outputCoaddName}Coadd_deblendedFlux",
74 storageClass="SourceCatalog",
75 dimensions=("tract", "patch", "band", "skymap")
76 )
77 outputSchema = cT.InitOutput(
78 doc="Output of the schema used in deblending task",
79 name="{outputCoaddName}Coadd_deblendedFlux_schema",
80 storageClass="SourceCatalog"
81 )
82
83
84class DeblendCoaddSourcesSingleConfig(PipelineTaskConfig,
85 pipelineConnections=DeblendCoaddSourceSingleConnections):
86 singleBandDeblend = ConfigurableField(
87 target=SourceDeblendTask,
88 doc="Task to deblend an image in one band"
89 )
90 idGenerator = SkyMapIdGeneratorConfig.make_field()
91
92 def setDefaults(self):
93 super().setDefaults()
94 self.singleBandDeblend.propagateAllPeaks = True
95
96
97class DeblendCoaddSourcesMultiConnections(PipelineTaskConnections,
98 dimensions=("tract", "patch", "skymap"),
99 defaultTemplates=deblendBaseTemplates):
100 inputSchema = cT.InitInput(
101 doc="Input schema to use in the deblend catalog",
102 name="{inputCoaddName}Coadd_mergeDet_schema",
103 storageClass="SourceCatalog"
104 )
105 peakSchema = cT.InitInput(
106 doc="Schema of the footprint peak catalogs",
107 name="{inputCoaddName}Coadd_peak_schema",
108 storageClass="PeakCatalog"
109 )
110 mergedDetections = cT.Input(
111 doc="Detection catalog merged across bands",
112 name="{inputCoaddName}Coadd_mergeDet",
113 storageClass="SourceCatalog",
114 dimensions=("tract", "patch", "skymap")
115 )
116 coadds = cT.Input(
117 doc="Exposure on which to run deblending",
118 name="{inputCoaddName}Coadd_calexp",
119 storageClass="ExposureF",
120 multiple=True,
121 dimensions=("tract", "patch", "band", "skymap")
122 )
123 outputSchema = cT.InitOutput(
124 doc="Output of the schema used in deblending task",
125 name="{outputCoaddName}Coadd_deblendedFlux_schema",
126 storageClass="SourceCatalog"
127 )
128 # TODO[DM-47405]: remove this deprecated connection.
129 fluxCatalogs = cT.Output(
130 doc="Flux weighted catalogs produced by multiband deblending",
131 name="{outputCoaddName}Coadd_deblendedFlux",
132 storageClass="SourceCatalog",
133 dimensions=("tract", "patch", "band", "skymap"),
134 multiple=True,
135 deprecated="Deprecated and unused; will be removed after v29."
136 )
137 # TODO[DM-47405]: remove this deprecated connection.
138 templateCatalogs = cT.Output(
139 doc="Template catalogs produced by multiband deblending",
140 name="{outputCoaddName}Coadd_deblendedModel",
141 storageClass="SourceCatalog",
142 dimensions=("tract", "patch", "band", "skymap"),
143 multiple=True,
144 deprecated="Deprecated and unused; will be removed after v29."
145 )
146 deblendedCatalog = cT.Output(
147 doc="Catalogs produced by multiband deblending",
148 name="{outputCoaddName}Coadd_deblendedCatalog",
149 storageClass="SourceCatalog",
150 dimensions=("tract", "patch", "skymap"),
151 )
152 scarletModelData = cT.Output(
153 doc="Multiband scarlet models produced by the deblender",
154 name="{outputCoaddName}Coadd_scarletModelData",
155 storageClass="ScarletModelData",
156 dimensions=("tract", "patch", "skymap"),
157 )
158
159 def __init__(self, *, config=None):
160 super().__init__(config=config)
161 del self.fluxCatalogs
162 del self.templateCatalogs
163
164
165class DeblendCoaddSourcesMultiConfig(PipelineTaskConfig,
166 pipelineConnections=DeblendCoaddSourcesMultiConnections):
167 multibandDeblend = ConfigurableField(
168 target=ScarletDeblendTask,
169 doc="Task to deblend an images in multiple bands"
170 )
171 idGenerator = SkyMapIdGeneratorConfig.make_field()
172
173
174# TODO[DM-47797] Remove this task.
175@deprecated(
176 "Support for the old single-band deblender on coadds will be removed "
177 "after v29.",
178 version="v29",
179 category=FutureWarning
180)
181class DeblendCoaddSourcesBaseTask(PipelineTask):
182 def __init__(self, initInputs, **kwargs):
183 super().__init__(initInputs=initInputs, **kwargs)
184 schema = initInputs["inputSchema"].schema
185 self.peakSchema = initInputs["peakSchema"].schema
187 self.schemaMapper.addMinimalSchema(schema)
188 self.schema = self.schemaMapper.getOutputSchema()
189
190 def runQuantum(self, butlerQC, inputRefs, outputRefs):
191 inputs = butlerQC.get(inputRefs)
192 inputs["idFactory"] = self.config.idGenerator.apply(butlerQC.quantum.dataId).make_table_id_factory()
193 outputs = self.run(**inputs)
194 butlerQC.put(outputs, outputRefs)
195
196 def _makeSourceCatalog(self, mergedDetections, idFactory):
197 # There may be gaps in the mergeDet catalog, which will cause the
198 # source ids to be inconsistent. So we update the id factory
199 # with the largest id already in the catalog.
200 maxId = np.max(mergedDetections["id"])
201 idFactory.notify(maxId)
202 table = afwTable.SourceTable.make(self.schema, idFactory)
203 sources = afwTable.SourceCatalog(table)
204 sources.extend(mergedDetections, self.schemaMapper)
205 return sources
206
207
208# TODO[DM-47797] Remove this task, its connections, and its config.
209@deprecated(
210 "Support for the old single-band deblender on coadds will be removed "
211 "after v29.",
212 version="v29",
213 category=FutureWarning
214)
216 ConfigClass = DeblendCoaddSourcesSingleConfig
217 _DefaultName = "deblendCoaddSourcesSingle"
218
219 def __init__(self, initInputs, **kwargs):
220 super().__init__(initInputs=initInputs, **kwargs)
221 self.makeSubtask("singleBandDeblend", schema=self.schema, peakSchema=self.peakSchema)
223
224 def run(self, coadd, mergedDetections, idFactory):
225 sources = self._makeSourceCatalog(mergedDetections, idFactory)
226 self.singleBandDeblend.run(coadd, sources)
227 if not sources.isContiguous():
228 sources = sources.copy(deep=True)
229 return Struct(measureCatalog=sources)
230
231
233 ConfigClass = DeblendCoaddSourcesMultiConfig
234 _DefaultName = "deblendCoaddSourcesMulti"
235
236 def __init__(self, initInputs, **kwargs):
237 super().__init__(initInputs=initInputs, **kwargs)
238 schema = initInputs["inputSchema"].schema
239 self.peakSchema = initInputs["peakSchema"].schema
241 self.schemaMapper.addMinimalSchema(schema)
242 self.schema = self.schemaMapper.getOutputSchema()
243 self.makeSubtask("multibandDeblend", schema=self.schema, peakSchema=self.peakSchema)
245
246 def runQuantum(self, butlerQC, inputRefs, outputRefs):
247 # Obtain the list of bands, sort them (alphabetically), then reorder
248 # all input lists to match this band order.
249 bandOrder = [dRef.dataId["band"] for dRef in inputRefs.coadds]
250 bandOrder.sort()
251 inputRefs = reorderRefs(inputRefs, bandOrder, dataIdKey="band")
252 inputs = butlerQC.get(inputRefs)
253 inputs["idFactory"] = self.config.idGenerator.apply(butlerQC.quantum.dataId).make_table_id_factory()
254 inputs["filters"] = [dRef.dataId["band"] for dRef in inputRefs.coadds]
255 outputs = self.run(**inputs)
256 butlerQC.put(outputs, outputRefs)
257
258 def run(self, coadds, filters, mergedDetections, idFactory):
259 sources = self._makeSourceCatalog(mergedDetections, idFactory)
260 multiExposure = afwImage.MultibandExposure.fromExposures(filters, coadds)
261 catalog, modelData = self.multibandDeblend.run(multiExposure, sources)
262 retStruct = Struct(deblendedCatalog=catalog, scarletModelData=modelData)
263 return retStruct
264
265 def _makeSourceCatalog(self, mergedDetections, idFactory):
266 # There may be gaps in the mergeDet catalog, which will cause the
267 # source ids to be inconsistent. So we update the id factory
268 # with the largest id already in the catalog.
269 maxId = np.max(mergedDetections["id"])
270 idFactory.notify(maxId)
271 table = afwTable.SourceTable.make(self.schema, idFactory)
272 sources = afwTable.SourceCatalog(table)
273 sources.extend(mergedDetections, self.schemaMapper)
274 return sources
A mapping between the keys of two Schemas, used to copy data between them.