LSST Applications  21.0.0-147-g0e635eb1+1acddb5be5,22.0.0+052faf71bd,22.0.0+1ea9a8b2b2,22.0.0+6312710a6c,22.0.0+729191ecac,22.0.0+7589c3a021,22.0.0+9f079a9461,22.0.1-1-g7d6de66+b8044ec9de,22.0.1-1-g87000a6+536b1ee016,22.0.1-1-g8e32f31+6312710a6c,22.0.1-10-gd060f87+016f7cdc03,22.0.1-12-g9c3108e+df145f6f68,22.0.1-16-g314fa6d+c825727ab8,22.0.1-19-g93a5c75+d23f2fb6d8,22.0.1-19-gb93eaa13+aab3ef7709,22.0.1-2-g8ef0a89+b8044ec9de,22.0.1-2-g92698f7+9f079a9461,22.0.1-2-ga9b0f51+052faf71bd,22.0.1-2-gac51dbf+052faf71bd,22.0.1-2-gb66926d+6312710a6c,22.0.1-2-gcb770ba+09e3807989,22.0.1-20-g32debb5+b8044ec9de,22.0.1-23-gc2439a9a+fb0756638e,22.0.1-3-g496fd5d+09117f784f,22.0.1-3-g59f966b+1e6ba2c031,22.0.1-3-g849a1b8+f8b568069f,22.0.1-3-gaaec9c0+c5c846a8b1,22.0.1-32-g5ddfab5d3+60ce4897b0,22.0.1-4-g037fbe1+64e601228d,22.0.1-4-g8623105+b8044ec9de,22.0.1-5-g096abc9+d18c45d440,22.0.1-5-g15c806e+57f5c03693,22.0.1-7-gba73697+57f5c03693,master-g6e05de7fdc+c1283a92b8,master-g72cdda8301+729191ecac,w.2021.39
LSST Data Management Base Package
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 import numpy as np
23 
24 from lsst.pipe.base import (Struct, PipelineTask, PipelineTaskConfig, PipelineTaskConnections)
25 import lsst.pipe.base.connectionTypes as cT
26 
27 from lsst.pex.config import ConfigurableField
28 from lsst.meas.deblender import SourceDeblendTask
29 from lsst.meas.extensions.scarlet import ScarletDeblendTask
30 from lsst.obs.base import ExposureIdInfo
31 
32 import lsst.afw.image as afwImage
33 import lsst.afw.table as afwTable
34 
35 __all__ = ("DeblendCoaddSourcesSingleConfig", "DeblendCoaddSourcesSingleTask",
36  "DeblendCoaddSourcesMultiConfig", "DeblendCoaddSourcesMultiTask")
37 
38 
39 deblendBaseTemplates = {"inputCoaddName": "deep", "outputCoaddName": "deep"}
40 
41 
42 class DeblendCoaddSourceSingleConnections(PipelineTaskConnections,
43  dimensions=("tract", "patch", "band", "skymap"),
44  defaultTemplates=deblendBaseTemplates):
45  inputSchema = cT.InitInput(
46  doc="Input schema to use in the deblend catalog",
47  name="{inputCoaddName}Coadd_mergeDet_schema",
48  storageClass="SourceCatalog"
49  )
50  peakSchema = cT.InitInput(
51  doc="Schema of the footprint peak catalogs",
52  name="{inputCoaddName}Coadd_peak_schema",
53  storageClass="PeakCatalog"
54  )
55  mergedDetections = cT.Input(
56  doc="Detection catalog merged across bands",
57  name="{inputCoaddName}Coadd_mergeDet",
58  storageClass="SourceCatalog",
59  dimensions=("tract", "patch", "skymap")
60  )
61  coadd = cT.Input(
62  doc="Exposure on which to run deblending",
63  name="{inputCoaddName}Coadd_calexp",
64  storageClass="ExposureF",
65  dimensions=("tract", "patch", "band", "skymap")
66  )
67  measureCatalog = cT.Output(
68  doc="The output measurement catalog of deblended sources",
69  name="{outputCoaddName}Coadd_deblendedFlux",
70  storageClass="SourceCatalog",
71  dimensions=("tract", "patch", "band", "skymap")
72  )
73  outputSchema = cT.InitOutput(
74  doc="Output of the schema used in deblending task",
75  name="{outputCoaddName}Coadd_deblendedFlux_schema",
76  storageClass="SourceCatalog"
77  )
78 
79  def setDefaults(self):
80  super().setDefaults()
81  self.singleBandDeblend.propagateAllPeaks = True
82 
83 
84 class DeblendCoaddSourcesSingleConfig(PipelineTaskConfig,
85  pipelineConnections=DeblendCoaddSourceSingleConnections):
86  singleBandDeblend = ConfigurableField(
87  target=SourceDeblendTask,
88  doc="Task to deblend an image in one band"
89  )
90 
91 
92 class DeblendCoaddSourcesMultiConnections(PipelineTaskConnections,
93  dimensions=("tract", "patch", "skymap"),
94  defaultTemplates=deblendBaseTemplates):
95  inputSchema = cT.InitInput(
96  doc="Input schema to use in the deblend catalog",
97  name="{inputCoaddName}Coadd_mergeDet_schema",
98  storageClass="SourceCatalog"
99  )
100  peakSchema = cT.InitInput(
101  doc="Schema of the footprint peak catalogs",
102  name="{inputCoaddName}Coadd_peak_schema",
103  storageClass="PeakCatalog"
104  )
105  mergedDetections = cT.Input(
106  doc="Detection catalog merged across bands",
107  name="{inputCoaddName}Coadd_mergeDet",
108  storageClass="SourceCatalog",
109  dimensions=("tract", "patch", "skymap")
110  )
111  coadds = cT.Input(
112  doc="Exposure on which to run deblending",
113  name="{inputCoaddName}Coadd_calexp",
114  storageClass="ExposureF",
115  multiple=True,
116  dimensions=("tract", "patch", "band", "skymap")
117  )
118  outputSchema = cT.InitOutput(
119  doc="Output of the schema used in deblending task",
120  name="{outputCoaddName}Coadd_deblendedFlux_schema",
121  storageClass="SourceCatalog"
122  )
123  templateCatalogs = cT.Output(
124  doc="Template catalogs produced by multiband deblending",
125  name="{outputCoaddName}Coadd_deblendedFlux",
126  storageClass="SourceCatalog",
127  dimensions=("tract", "patch", "band", "skymap"),
128  multiple=True
129  )
130 
131 
132 class DeblendCoaddSourcesMultiConfig(PipelineTaskConfig,
133  pipelineConnections=DeblendCoaddSourcesMultiConnections):
134  multibandDeblend = ConfigurableField(
135  target=ScarletDeblendTask,
136  doc="Task to deblend an images in multiple bands"
137  )
138 
139 
140 class DeblendCoaddSourcesBaseTask(PipelineTask):
141  def __init__(self, initInputs, **kwargs):
142  super().__init__(initInputs=initInputs, **kwargs)
143  schema = initInputs["inputSchema"].schema
144  self.peakSchemapeakSchema = initInputs["peakSchema"].schema
145  self.schemaMapperschemaMapper = afwTable.SchemaMapper(schema)
146  self.schemaMapperschemaMapper.addMinimalSchema(schema)
147  self.schemaschema = self.schemaMapperschemaMapper.getOutputSchema()
148 
149  def runQuantum(self, butlerQC, inputRefs, outputRefs):
150  inputs = butlerQC.get(inputRefs)
151  inputs["idFactory"] = ExposureIdInfo.fromDataId(
152  butlerQC.quantum.dataId,
153  "tract_patch"
154  ).makeSourceIdFactory()
155  outputs = self.run(**inputs)
156  butlerQC.put(outputs, outputRefs)
157 
158  def _makeSourceCatalog(self, mergedDetections, idFactory):
159  # There may be gaps in the mergeDet catalog, which will cause the
160  # source ids to be inconsistent. So we update the id factory
161  # with the largest id already in the catalog.
162  maxId = np.max(mergedDetections["id"])
163  idFactory.notify(maxId)
164  table = afwTable.SourceTable.make(self.schemaschema, idFactory)
165  sources = afwTable.SourceCatalog(table)
166  sources.extend(mergedDetections, self.schemaMapperschemaMapper)
167  return sources
168 
169 
171  ConfigClass = DeblendCoaddSourcesSingleConfig
172  _DefaultName = "deblendCoaddSourcesSingle"
173 
174  def __init__(self, initInputs, **kwargs):
175  super().__init__(initInputs=initInputs, **kwargs)
176  self.makeSubtask("singleBandDeblend", schema=self.schemaschema, peakSchema=self.peakSchemapeakSchema)
177  self.outputSchemaoutputSchema = afwTable.SourceCatalog(self.schemaschema)
178 
179  def run(self, coadd, mergedDetections, idFactory):
180  sources = self._makeSourceCatalog_makeSourceCatalog(mergedDetections, idFactory)
181  self.singleBandDeblend.run(coadd, sources)
182  if not sources.isContiguous():
183  sources = sources.copy(deep=True)
184  return Struct(measureCatalog=sources)
185 
186 
188  ConfigClass = DeblendCoaddSourcesMultiConfig
189  _DefaultName = "deblendCoaddSourcesMulti"
190 
191  def __init__(self, initInputs, **kwargs):
192  super().__init__(initInputs=initInputs, **kwargs)
193  self.makeSubtask("multibandDeblend", schema=self.schemaschema, peakSchema=self.peakSchemapeakSchema)
194  self.outputSchemaoutputSchema = afwTable.SourceCatalog(self.schemaschema)
195 
196  def runQuantum(self, butlerQC, inputRefs, outputRefs):
197  inputs = butlerQC.get(inputRefs)
198  exposureIdInfo = ExposureIdInfo.fromDataId(butlerQC.quantum.dataId, "tract_patch")
199  inputs["idFactory"] = exposureIdInfo.makeSourceIdFactory()
200  inputs["filters"] = [dRef.dataId["band"] for dRef in inputRefs.coadds]
201  outputs = self.runrun(**inputs)
202  for outRef in outputRefs.templateCatalogs:
203  band = outRef.dataId['band']
204  if (catalog := outputs.templateCatalogs.get(band)) is not None:
205  butlerQC.put(catalog, outRef)
206 
207  def run(self, coadds, filters, mergedDetections, idFactory):
208  sources = self._makeSourceCatalog_makeSourceCatalog(mergedDetections, idFactory)
209  multiExposure = afwImage.MultibandExposure.fromExposures(filters, coadds)
210  templateCatalogs = self.multibandDeblend.run(multiExposure, sources)
211  retStruct = Struct(templateCatalogs=templateCatalogs)
212  return retStruct
A mapping between the keys of two Schemas, used to copy data between them.
Definition: SchemaMapper.h:21
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.