lsst.pipe.tasks  16.0-65-g12857137
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", "AbstractFilter", "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", "AbstractFilter", "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", "AbstractFilter", "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 
87  multibandDeblend = ConfigurableField(
88  target=MultibandDeblendTask,
89  doc="Task to deblend an images in multiple bands"
90  )
91  coadds = InputDatasetField(
92  doc="Exposure on which to run deblending",
93  nameTemplate="{inputCoaddName}Coadd_calexp",
94  storageClass="ExposureF",
95  dimensions=("Tract", "Patch", "AbstractFilter", "SkyMap")
96  )
97  outputSchema = InitOutputDatasetField(
98  doc="Output of the schema used in deblending task",
99  nameTemplate="{outputCoaddName}Coadd_deblendedModel_schema",
100  storageClass="SourceCatalog"
101  )
102  fluxCatalogs = OutputDatasetField(
103  doc="Flux catalogs produced by multiband deblending, not written "
104  "if conserve flux is turned off",
105  nameTemplate="{outputCoaddName}Coadd_deblendedFlux",
106  storageClass="SourceCatalog",
107  dimensions=("Tract", "Patch", "AbstractFilter", "SkyMap")
108  )
109  templateCatalogs = OutputDatasetField(
110  doc="Template catalogs produced by multiband deblending",
111  nameTemplate="{outputCoaddName}Coadd_deblendedModel",
112  storageClass="SourceCatalog",
113  dimensions=("Tract", "Patch", "AbstractFilter", "SkyMap")
114  )
115 
116  def setDefaults(self):
117  super().setDefaults()
118  self.quantum.dimensions = ("Tract", "Patch", "SkyMap")
119 
120 
121 class DeblendCoaddSourcesBaseTask(PipelineTask):
122  def __init__(self, initInputs, **kwargs):
123  super().__init__(initInputs=initInputs, **kwargs)
124  schema = initInputs["inputSchema"].schema
125  self.peakSchema = initInputs["peakSchema"].schema
126  self.schemaMapper = afwTable.SchemaMapper(schema)
127  self.schemaMapper.addMinimalSchema(schema)
128  self.schema = self.schemaMapper.getOutputSchema()
129 
131  return {"outputSchema": afwTable.SourceCatalog(self.schema)}
132 
133  def adaptArgsAndRun(self, inputData, inputDataIds, outputDataIds, butler):
134  # FINDME: DM-15843 needs to come back and address final solution
135  inputData["idFactory"] = afwTable.IdFactory.makeSimple()
136  return self.run(**inputData)
137 
138  def _makeSourceCatalog(self, mergedDetections, idFactory):
139  # Need to do something more clever once we have a real Idfactory here
140  # see command line task version. FINDME DM-15843
141  table = afwTable.SourceTable.make(self.schema, idFactory)
142  sources = afwTable.SourceCatalog(table)
143  sources.extend(mergedDetections, self.schemaMapper)
144  return sources
145 
146 
148  ConfigClass = DeblendCoaddSourcesSingleConfig
149  _DefaultName = "deblendCoaddSourcesSingle"
150 
151  def __init__(self, initInputs, **kwargs):
152  super().__init__(initInputs=initInputs, **kwargs)
153  self.makeSubtask("singleBandDeblend", schema=self.schema, peakSchema=self.peakSchema)
154 
155  def run(self, coadd, mergedDetections, idFactory):
156  sources = self._makeSourceCatalog(mergedDetections, idFactory)
157  self.singleBandDeblend.run(coadd, sources)
158  return Struct(measureCatalog=sources)
159 
160 
162  ConfigClass = DeblendCoaddSourcesMultiConfig
163  _DefaultName = "deblendCoaddSourcesMulti"
164 
165  def __init__(self, initInputs, **kwargs):
166  super().__init__(initInputs=initInputs, **kwargs)
167  self.makeSubtask("multibandDeblend", schema=self.schema, peakSchema=self.peakSchema)
168 
169  @classmethod
170  def getOutputDatasetTypes(cls, config):
171  outputTypeDict = super().getOutputDatasetTypes(config)
172  # If Conserve flux is set to false, remove that catalog as a possible output
173  if not config.multibandDeblend.conserveFlux:
174  outputTypeDict.pop("fluxCatalogs", None)
175  return outputTypeDict
176 
177  def adaptArgsAndRun(self, inputData, inputDataIds, outputDataIds, butler):
178  inputData["filters"] = [dId["abstract_filter"] for dId in inputDataIds["coadds"]]
179  return super().adaptArgsAndRun(inputData, inputDataIds, outputDataIds, butler)
180 
181  def run(self, coadds, filters, mergedDetections, idFactory):
182  sources = self._makeSourceCatalog(mergedDetections, idFactory)
183  multiExposure = afwImage.MultibandExposure.fromExposures(filters, coadds)
184  fluxCatalogs, templateCatalogs = self.multibandDeblend.run(multiExposure, sources)
185  retStruct = Struct(templateCatalogs)
186  if self.config.multibandDeblend.conserveFlux:
187  retStruct.fluxCatalogs = fluxCatalogs
188  return retStruct
def adaptArgsAndRun(self, inputData, inputDataIds, outputDataIds, butler)
def adaptArgsAndRun(self, inputData, inputDataIds, outputDataIds, butler)