lsst.pipe.tasks  21.0.0-34-g778a6a5a+74dfa3b817
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 from lsst.pipe.base import (Struct, PipelineTask, PipelineTaskConfig, PipelineTaskConnections)
24 
25 from lsst.pex.config import ConfigurableField
26 from lsst.meas.deblender import SourceDeblendTask
27 from lsst.meas.extensions.scarlet import ScarletDeblendTask
28 
29 import lsst.afw.image as afwImage
30 import lsst.afw.table as afwTable
31 
32 __all__ = ("DeblendCoaddSourcesSingleConfig", "DeblendCoaddSourcesSingleTask",
33  "DeblendCoaddSourcesMultiConfig", "DeblendCoaddSourcesMultiTask")
34 
35 
36 deblendBaseTemplates = {"inputCoaddName": "deep", "outputCoaddName": "deep"}
37 
38 
39 class DeblendCoaddSourceSingleConnections(PipelineTaskConnections,
40  dimensions=("tract", "patch", "band", "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", "band", "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", "band", "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  )
75 
76  def setDefaults(self):
77  super().setDefaults()
78  self.singleBandDeblend.propagateAllPeaks = True
79 
80 
81 class DeblendCoaddSourcesSingleConfig(PipelineTaskConfig,
82  pipelineConnections=DeblendCoaddSourceSingleConnections):
83  singleBandDeblend = ConfigurableField(
84  target=SourceDeblendTask,
85  doc="Task to deblend an image in one band"
86  )
87 
88 
89 class 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", "band", "skymap")
114  )
115  outputSchema = cT.InitOutput(
116  doc="Output of the schema used in deblending task",
117  name="{outputCoaddName}Coadd_deblendedFlux_schema",
118  storageClass="SourceCatalog"
119  )
120  templateCatalogs = cT.Output(
121  doc="Template catalogs produced by multiband deblending",
122  name="{outputCoaddName}Coadd_deblendedFlux",
123  storageClass="SourceCatalog",
124  dimensions=("tract", "patch", "band", "skymap"),
125  multiple=True
126  )
127 
128 
129 class DeblendCoaddSourcesMultiConfig(PipelineTaskConfig,
130  pipelineConnections=DeblendCoaddSourcesMultiConnections):
131  multibandDeblend = ConfigurableField(
132  target=ScarletDeblendTask,
133  doc="Task to deblend an images in multiple bands"
134  )
135 
136 
137 class DeblendCoaddSourcesBaseTask(PipelineTask):
138  def __init__(self, initInputs, **kwargs):
139  super().__init__(initInputs=initInputs, **kwargs)
140  schema = initInputs["inputSchema"].schema
141  self.peakSchemapeakSchema = initInputs["peakSchema"].schema
142  self.schemaMapperschemaMapper = afwTable.SchemaMapper(schema)
143  self.schemaMapperschemaMapper.addMinimalSchema(schema)
144  self.schemaschema = self.schemaMapperschemaMapper.getOutputSchema()
145 
146  def runQuantum(self, butlerQC, inputRefs, outputRefs):
147  inputs = butlerQC.get(inputRefs)
148  packedId, maxBits = butlerQC.quantum.dataId.pack("tract_patch", returnMaxBits=True)
149  inputs["idFactory"] = afwTable.IdFactory.makeSource(packedId, 64 - maxBits)
150  outputs = self.run(**inputs)
151  butlerQC.put(outputs, outputRefs)
152 
153  def _makeSourceCatalog(self, mergedDetections, idFactory):
154  table = afwTable.SourceTable.make(self.schemaschema, idFactory)
155  sources = afwTable.SourceCatalog(table)
156  sources.extend(mergedDetections, self.schemaMapperschemaMapper)
157  return sources
158 
159 
161  ConfigClass = DeblendCoaddSourcesSingleConfig
162  _DefaultName = "deblendCoaddSourcesSingle"
163 
164  def __init__(self, initInputs, **kwargs):
165  super().__init__(initInputs=initInputs, **kwargs)
166  self.makeSubtask("singleBandDeblend", schema=self.schemaschema, peakSchema=self.peakSchemapeakSchema)
167  self.outputSchemaoutputSchema = afwTable.SourceCatalog(self.schemaschema)
168 
169  def run(self, coadd, mergedDetections, idFactory):
170  sources = self._makeSourceCatalog_makeSourceCatalog(mergedDetections, idFactory)
171  self.singleBandDeblend.run(coadd, sources)
172  if not sources.isContiguous():
173  sources = sources.copy(deep=True)
174  return Struct(measureCatalog=sources)
175 
176 
178  ConfigClass = DeblendCoaddSourcesMultiConfig
179  _DefaultName = "deblendCoaddSourcesMulti"
180 
181  def __init__(self, initInputs, **kwargs):
182  super().__init__(initInputs=initInputs, **kwargs)
183  self.makeSubtask("multibandDeblend", schema=self.schemaschema, peakSchema=self.peakSchemapeakSchema)
184  self.outputSchemaoutputSchema = afwTable.SourceCatalog(self.schemaschema)
185 
186  def runQuantum(self, butlerQC, inputRefs, outputRefs):
187  inputs = butlerQC.get(inputRefs)
188  packedId, maxBits = butlerQC.quantum.dataId.pack("tract_patch", returnMaxBits=True)
189  inputs["idFactory"] = afwTable.IdFactory.makeSource(packedId, 64 - maxBits)
190  inputs["filters"] = [dRef.dataId["band"] for dRef in inputRefs.coadds]
191  outputs = self.runrun(**inputs)
192  sortedTemplateCatalogs = []
193  for outRef in outputRefs.templateCatalogs:
194  band = outRef.dataId['band']
195  sortedTemplateCatalogs.append(outputs.templateCatalogs[band])
196  outputs.templateCatalogs = sortedTemplateCatalogs
197  butlerQC.put(outputs, outputRefs)
198 
199  def run(self, coadds, filters, mergedDetections, idFactory):
200  sources = self._makeSourceCatalog_makeSourceCatalog(mergedDetections, idFactory)
201  multiExposure = afwImage.MultibandExposure.fromExposures(filters, coadds)
202  templateCatalogs = self.multibandDeblend.run(multiExposure, sources)
203  retStruct = Struct(templateCatalogs=templateCatalogs)
204  return retStruct