Coverage for python/lsst/pipe/tasks/deblendCoaddSourcesPipeline.py : 46%

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 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/>.
22from lsst.pipe.base import (Struct, PipelineTask, PipelineTaskConfig, PipelineTaskConnections)
23import lsst.pipe.base.connectionTypes as cT
25from lsst.pex.config import ConfigurableField
26from lsst.meas.deblender import SourceDeblendTask
27from lsst.meas.extensions.scarlet import ScarletDeblendTask
29import lsst.afw.image as afwImage
30import lsst.afw.table as afwTable
32__all__ = ("DeblendCoaddSourcesSingleConfig", "DeblendCoaddSourcesSingleTask",
33 "DeblendCoaddSourcesMultiConfig", "DeblendCoaddSourcesMultiTask")
36deblendBaseTemplates = {"inputCoaddName": "deep", "outputCoaddName": "deep"}
39class DeblendCoaddSourceSingleConnections(PipelineTaskConnections,
40 dimensions=("tract", "patch", "abstract_filter", "skymap"),
41 defaultTemplates=deblendBaseTemplates):
42 inputSchema = cT.InitInput(
43 doc="Input schema to use in the deblend catalog",
44 name="{inputCoaddName}Coadd_mergeDet_schema",
45 storageClass="SourceCatalog"
46 )
47 peakSchema = cT.InitInput(
48 doc="Schema of the footprint peak catalogs",
49 name="{inputCoaddName}Coadd_peak_schema",
50 storageClass="PeakCatalog"
51 )
52 mergedDetections = cT.Input(
53 doc="Detection catalog merged across bands",
54 name="{inputCoaddName}Coadd_mergeDet",
55 storageClass="SourceCatalog",
56 dimensions=("tract", "patch", "skymap")
57 )
58 coadd = cT.Input(
59 doc="Exposure on which to run deblending",
60 name="{inputCoaddName}Coadd_calexp",
61 storageClass="ExposureF",
62 dimensions=("tract", "patch", "abstract_filter", "skymap")
63 )
64 measureCatalog = cT.Output(
65 doc="The output measurement catalog of deblended sources",
66 name="{outputCoaddName}Coadd_deblendedFlux",
67 storageClass="SourceCatalog",
68 dimensions=("tract", "patch", "abstract_filter", "skymap")
69 )
70 outputSchema = cT.InitOutput(
71 doc="Output of the schema used in deblending task",
72 name="{outputCoaddName}Coadd_deblendedFlux_schema",
73 storageClass="SourceCatalog"
74 )
76 def setDefaults(self):
77 super().setDefaults()
78 self.singleBandDeblend.propagateAllPeaks = True
81class DeblendCoaddSourcesSingleConfig(PipelineTaskConfig,
82 pipelineConnections=DeblendCoaddSourceSingleConnections):
83 singleBandDeblend = ConfigurableField(
84 target=SourceDeblendTask,
85 doc="Task to deblend an image in one band"
86 )
89class DeblendCoaddSourcesMultiConnections(PipelineTaskConnections,
90 dimensions=("tract", "patch", "skymap"),
91 defaultTemplates=deblendBaseTemplates):
92 inputSchema = cT.InitInput(
93 doc="Input schema to use in the deblend catalog",
94 name="{inputCoaddName}Coadd_mergeDet_schema",
95 storageClass="SourceCatalog"
96 )
97 peakSchema = cT.InitInput(
98 doc="Schema of the footprint peak catalogs",
99 name="{inputCoaddName}Coadd_peak_schema",
100 storageClass="PeakCatalog"
101 )
102 mergedDetections = cT.Input(
103 doc="Detection catalog merged across bands",
104 name="{inputCoaddName}Coadd_mergeDet",
105 storageClass="SourceCatalog",
106 dimensions=("tract", "patch", "skymap")
107 )
108 coadds = cT.Input(
109 doc="Exposure on which to run deblending",
110 name="{inputCoaddName}Coadd_calexp",
111 storageClass="ExposureF",
112 multiple=True,
113 dimensions=("tract", "patch", "abstract_filter", "skymap")
114 )
115 outputSchema = cT.InitOutput(
116 doc="Output of the schema used in deblending task",
117 name="{outputCoaddName}Coadd_deblendedModel_schema",
118 storageClass="SourceCatalog"
119 )
120 fluxCatalogs = cT.Output(
121 doc="Flux catalogs produced by multiband deblending, not written "
122 "if conserve flux is turned off",
123 name="{outputCoaddName}Coadd_deblendedFlux",
124 storageClass="SourceCatalog",
125 dimensions=("tract", "patch", "abstract_filter", "skymap")
126 )
127 templateCatalogs = cT.Output(
128 doc="Template catalogs produced by multiband deblending",
129 name="{outputCoaddName}Coadd_deblendedModel",
130 storageClass="SourceCatalog",
131 dimensions=("tract", "patch", "abstract_filter", "skymap")
132 )
134 def __init__(self, *, config=None):
135 super().__init__(config=config)
136 if not config.multibandDeblend.conserveFlux:
137 self.outputs -= set(("fluxCatalogs",))
140class DeblendCoaddSourcesMultiConfig(PipelineTaskConfig,
141 pipelineConnections=DeblendCoaddSourcesMultiConnections):
142 multibandDeblend = ConfigurableField(
143 target=ScarletDeblendTask,
144 doc="Task to deblend an images in multiple bands"
145 )
148class DeblendCoaddSourcesBaseTask(PipelineTask):
149 def __init__(self, initInputs, **kwargs):
150 super().__init__(initInputs=initInputs, **kwargs)
151 schema = initInputs["inputSchema"].schema
152 self.peakSchema = initInputs["peakSchema"].schema
153 self.schemaMapper = afwTable.SchemaMapper(schema)
154 self.schemaMapper.addMinimalSchema(schema)
155 self.schema = self.schemaMapper.getOutputSchema()
157 def runQuantum(self, butlerQC, inputRefs, outputRefs):
158 inputs = butlerQC.get(inputRefs)
159 packedId, maxBits = butlerQC.quantum.dataId.pack("tract_patch", returnMaxBits=True)
160 inputs["idFactory"] = afwTable.IdFactory.makeSource(packedId, 64 - maxBits)
161 outputs = self.run(**inputs)
162 butlerQC.put(outputs, outputRefs)
164 def _makeSourceCatalog(self, mergedDetections, idFactory):
165 table = afwTable.SourceTable.make(self.schema, idFactory)
166 sources = afwTable.SourceCatalog(table)
167 sources.extend(mergedDetections, self.schemaMapper)
168 return sources
171class DeblendCoaddSourcesSingleTask(DeblendCoaddSourcesBaseTask):
172 ConfigClass = DeblendCoaddSourcesSingleConfig
173 _DefaultName = "deblendCoaddSourcesSingle"
175 def __init__(self, initInputs, **kwargs):
176 super().__init__(initInputs=initInputs, **kwargs)
177 self.makeSubtask("singleBandDeblend", schema=self.schema, peakSchema=self.peakSchema)
178 self.outputSchema = afwTable.SourceCatalog(self.schema)
180 def run(self, coadd, mergedDetections, idFactory):
181 sources = self._makeSourceCatalog(mergedDetections, idFactory)
182 self.singleBandDeblend.run(coadd, sources)
183 if not sources.isContiguous():
184 sources = sources.copy(deep=True)
185 return Struct(measureCatalog=sources)
188class DeblendCoaddSourcesMultiTask(DeblendCoaddSourcesBaseTask):
189 ConfigClass = DeblendCoaddSourcesMultiConfig
190 _DefaultName = "deblendCoaddSourcesMulti"
192 def __init__(self, initInputs, **kwargs):
193 super().__init__(initInputs=initInputs, **kwargs)
194 self.makeSubtask("multibandDeblend", schema=self.schema, peakSchema=self.peakSchema)
195 self.outputSchema = afwTable.SourceCatalog(self.schema)
197 def runQuantum(self, butlerQC, inputRefs, outputRefs):
198 inputs = butlerQC.get(inputRefs)
199 packedId, maxBits = butlerQC.quantum.dataId.pack("tract_patch", returnMaxBits=True)
200 inputs["idFactory"] = afwTable.IdFactory.makeSource(packedId, 64 - maxBits)
201 inputs["filters"] = [dRef.dataId["abstract_filter"] for dRef in inputRefs.coadds]
202 outputs = self.run(**inputs)
203 butlerQC.put(outputs, outputRefs)
205 def run(self, coadds, filters, mergedDetections, idFactory):
206 sources = self._makeSourceCatalog(mergedDetections, idFactory)
207 multiExposure = afwImage.MultibandExposure.fromExposures(filters, coadds)
208 fluxCatalogs, templateCatalogs = self.multibandDeblend.run(multiExposure, sources)
209 retStruct = Struct(templateCatalogs)
210 if self.config.multibandDeblend.conserveFlux:
211 retStruct.fluxCatalogs = fluxCatalogs
212 return retStruct