lsst.pipe.tasks  18.0.0-10-g73b8679e+3
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, InitInputDatasetField, InitOutputDatasetField,
23  InputDatasetField, OutputDatasetField, PipelineTaskConfig)
24 
25 from lsst.pex.config import ConfigurableField
26 from lsst.meas.deblender import SourceDeblendTask, MultibandDeblendTask
27 
28 import lsst.afw.image as afwImage
29 import lsst.afw.table as afwTable
30 
31 __all__ = ("DeblendCoaddSourcesSingleConfig", "DeblendCoaddSourcesSingleTask",
32  "DeblendCoaddSourcesMultiConfig", "DeblendCoaddSourcesMultiTask")
33 
34 
35 class DeblendCoaddSourcesBaseConfig(PipelineTaskConfig):
36  inputSchema = InitInputDatasetField(
37  doc="Input schema to use in the deblend catalog",
38  nameTemplate="{inputCoaddName}Coadd_mergeDet_schema",
39  storageClass="SourceCatalog"
40  )
41  peakSchema = InitInputDatasetField(
42  doc="Schema of the footprint peak catalogs",
43  nameTemplate="{inputCoaddName}Coadd_peak_schema",
44  storageClass="PeakCatalog"
45  )
46  mergedDetections = InputDatasetField(
47  doc="Detection catalog merged across bands",
48  nameTemplate="{inputCoaddName}Coadd_mergeDet",
49  storageClass="SourceCatalog",
50  scalar=True,
51  dimensions=("tract", "patch", "skymap")
52  )
53 
54  def setDefaults(self):
55  super().setDefaults()
56  self.quantum.dimensions = ("tract", "patch", "abstract_filter", "skymap")
57  self.formatTemplateNames({"inputCoaddName": "deep", "outputCoaddName": "deep"})
58 
59 
61  singleBandDeblend = ConfigurableField(
62  target=SourceDeblendTask,
63  doc="Task to deblend an image in one band"
64  )
65  coadd = InputDatasetField(
66  doc="Exposure on which to run deblending",
67  nameTemplate="{inputCoaddName}Coadd_calexp",
68  storageClass="ExposureF",
69  scalar=True,
70  dimensions=("tract", "patch", "abstract_filter", "skymap")
71  )
72  measureCatalog = OutputDatasetField(
73  doc="The output measurement catalog of deblended sources",
74  nameTemplate="{outputCoaddName}Coadd_deblendedFlux",
75  scalar=True,
76  storageClass="SourceCatalog",
77  dimensions=("tract", "patch", "abstract_filter", "skymap")
78  )
79  outputSchema = InitOutputDatasetField(
80  doc="Output of the schema used in deblending task",
81  nameTemplate="{outputCoaddName}Coadd_deblendedFlux_schema",
82  storageClass="SourceCatalog"
83  )
84 
85  def setDefaults(self):
86  super().setDefaults()
87  self.singleBandDeblend.propagateAllPeaks = True
88 
89 
91  multibandDeblend = ConfigurableField(
92  target=MultibandDeblendTask,
93  doc="Task to deblend an images in multiple bands"
94  )
95  coadds = InputDatasetField(
96  doc="Exposure on which to run deblending",
97  nameTemplate="{inputCoaddName}Coadd_calexp",
98  storageClass="ExposureF",
99  dimensions=("tract", "patch", "abstract_filter", "skymap")
100  )
101  outputSchema = InitOutputDatasetField(
102  doc="Output of the schema used in deblending task",
103  nameTemplate="{outputCoaddName}Coadd_deblendedModel_schema",
104  storageClass="SourceCatalog"
105  )
106  fluxCatalogs = OutputDatasetField(
107  doc="Flux catalogs produced by multiband deblending, not written "
108  "if conserve flux is turned off",
109  nameTemplate="{outputCoaddName}Coadd_deblendedFlux",
110  storageClass="SourceCatalog",
111  dimensions=("tract", "patch", "abstract_filter", "skymap")
112  )
113  templateCatalogs = OutputDatasetField(
114  doc="Template catalogs produced by multiband deblending",
115  nameTemplate="{outputCoaddName}Coadd_deblendedModel",
116  storageClass="SourceCatalog",
117  dimensions=("tract", "patch", "abstract_filter", "skymap")
118  )
119 
120  def setDefaults(self):
121  super().setDefaults()
122  self.quantum.dimensions = ("tract", "patch", "skymap")
123 
124 
125 class DeblendCoaddSourcesBaseTask(PipelineTask):
126  def __init__(self, initInputs, **kwargs):
127  super().__init__(initInputs=initInputs, **kwargs)
128  schema = initInputs["inputSchema"].schema
129  self.peakSchema = initInputs["peakSchema"].schema
130  self.schemaMapper = afwTable.SchemaMapper(schema)
131  self.schemaMapper.addMinimalSchema(schema)
132  self.schema = self.schemaMapper.getOutputSchema()
133 
135  return {"outputSchema": afwTable.SourceCatalog(self.schema)}
136 
137  def adaptArgsAndRun(self, inputData, inputDataIds, outputDataIds, butler):
138  packedId, maxBits = butler.registry.packDataId("tract_patch", inputDataIds["mergedDetections"],
139  returnMaxBits=True)
140  inputData["idFactory"] = afwTable.IdFactory.makeSource(packedId, 64 - maxBits)
141  return self.run(**inputData)
142 
143  def _makeSourceCatalog(self, mergedDetections, idFactory):
144  table = afwTable.SourceTable.make(self.schema, idFactory)
145  sources = afwTable.SourceCatalog(table)
146  sources.extend(mergedDetections, self.schemaMapper)
147  return sources
148 
149 
151  ConfigClass = DeblendCoaddSourcesSingleConfig
152  _DefaultName = "deblendCoaddSourcesSingle"
153 
154  def __init__(self, initInputs, **kwargs):
155  super().__init__(initInputs=initInputs, **kwargs)
156  self.makeSubtask("singleBandDeblend", schema=self.schema, peakSchema=self.peakSchema)
157 
158  def run(self, coadd, mergedDetections, idFactory):
159  sources = self._makeSourceCatalog(mergedDetections, idFactory)
160  self.singleBandDeblend.run(coadd, sources)
161  return Struct(measureCatalog=sources)
162 
163 
165  ConfigClass = DeblendCoaddSourcesMultiConfig
166  _DefaultName = "deblendCoaddSourcesMulti"
167 
168  def __init__(self, initInputs, **kwargs):
169  super().__init__(initInputs=initInputs, **kwargs)
170  self.makeSubtask("multibandDeblend", schema=self.schema, peakSchema=self.peakSchema)
171 
172  @classmethod
173  def getOutputDatasetTypes(cls, config):
174  outputTypeDict = super().getOutputDatasetTypes(config)
175  # If Conserve flux is set to false, remove that catalog as a possible output
176  if not config.multibandDeblend.conserveFlux:
177  outputTypeDict.pop("fluxCatalogs", None)
178  return outputTypeDict
179 
180  def adaptArgsAndRun(self, inputData, inputDataIds, outputDataIds, butler):
181  inputData["filters"] = [dId["abstract_filter"] for dId in inputDataIds["coadds"]]
182  return super().adaptArgsAndRun(inputData, inputDataIds, outputDataIds, butler)
183 
184  def run(self, coadds, filters, mergedDetections, idFactory):
185  sources = self._makeSourceCatalog(mergedDetections, idFactory)
186  multiExposure = afwImage.MultibandExposure.fromExposures(filters, coadds)
187  fluxCatalogs, templateCatalogs = self.multibandDeblend.run(multiExposure, sources)
188  retStruct = Struct(templateCatalogs)
189  if self.config.multibandDeblend.conserveFlux:
190  retStruct.fluxCatalogs = fluxCatalogs
191  return retStruct
def adaptArgsAndRun(self, inputData, inputDataIds, outputDataIds, butler)
def adaptArgsAndRun(self, inputData, inputDataIds, outputDataIds, butler)