Skip to content

Commit 4465070

Browse files
Merge pull request #1121 from lsst/tickets/DM-49008
DM-49008: Add options to use cell-based coadds
2 parents 9386764 + 57f2a4f commit 4465070

File tree

5 files changed

+221
-31
lines changed

5 files changed

+221
-31
lines changed

python/lsst/pipe/tasks/deblendCoaddSourcesPipeline.py

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from lsst.pipe.base import (Struct, PipelineTask, PipelineTaskConfig, PipelineTaskConnections)
3030
import lsst.pipe.base.connectionTypes as cT
3131

32-
from lsst.pex.config import ConfigurableField
32+
from lsst.pex.config import ConfigurableField, Field
3333
from lsst.meas.base import SkyMapIdGeneratorConfig
3434
from lsst.meas.deblender import SourceDeblendTask
3535
from lsst.meas.extensions.scarlet import ScarletDeblendTask
@@ -120,6 +120,20 @@ class DeblendCoaddSourcesMultiConnections(PipelineTaskConnections,
120120
multiple=True,
121121
dimensions=("tract", "patch", "band", "skymap")
122122
)
123+
coadds_cell = cT.Input(
124+
doc="Exposure on which to run deblending",
125+
name="{inputCoaddName}CoaddCell",
126+
storageClass="MultipleCellCoadd",
127+
multiple=True,
128+
dimensions=("tract", "patch", "band", "skymap")
129+
)
130+
backgrounds = cT.Input(
131+
doc="Background model to subtract from the cell-based coadd",
132+
name="{inputCoaddName}Coadd_calexp_background",
133+
storageClass="Background",
134+
multiple=True,
135+
dimensions=("tract", "patch", "band", "skymap")
136+
)
123137
outputSchema = cT.InitOutput(
124138
doc="Output of the schema used in deblending task",
125139
name="{outputCoaddName}Coadd_deblendedFlux_schema",
@@ -161,9 +175,20 @@ def __init__(self, *, config=None):
161175
del self.fluxCatalogs
162176
del self.templateCatalogs
163177

178+
if config:
179+
if config.useCellCoadds:
180+
del self.coadds
181+
else:
182+
del self.coadds_cell
183+
del self.backgrounds
184+
164185

165186
class DeblendCoaddSourcesMultiConfig(PipelineTaskConfig,
166187
pipelineConnections=DeblendCoaddSourcesMultiConnections):
188+
useCellCoadds = Field[bool](
189+
doc="Use cell-based coadds instead of regular coadds?",
190+
default=False,
191+
)
167192
multibandDeblend = ConfigurableField(
168193
target=ScarletDeblendTask,
169194
doc="Task to deblend an images in multiple bands"
@@ -246,13 +271,28 @@ def __init__(self, initInputs, **kwargs):
246271
def runQuantum(self, butlerQC, inputRefs, outputRefs):
247272
# Obtain the list of bands, sort them (alphabetically), then reorder
248273
# all input lists to match this band order.
249-
bandOrder = [dRef.dataId["band"] for dRef in inputRefs.coadds]
274+
coaddRefs = inputRefs.coadds_cell if self.config.useCellCoadds else inputRefs.coadds
275+
bandOrder = [dRef.dataId["band"] for dRef in coaddRefs]
250276
bandOrder.sort()
251277
inputRefs = reorderRefs(inputRefs, bandOrder, dataIdKey="band")
252278
inputs = butlerQC.get(inputRefs)
253-
inputs["idFactory"] = self.config.idGenerator.apply(butlerQC.quantum.dataId).make_table_id_factory()
254-
inputs["bands"] = [dRef.dataId["band"] for dRef in inputRefs.coadds]
255-
outputs = self.run(**inputs)
279+
bands = [dRef.dataId["band"] for dRef in coaddRefs]
280+
mergedDetections = inputs.pop("mergedDetections")
281+
if self.config.useCellCoadds:
282+
exposures = [mcc.stitch().asExposure() for mcc in inputs.pop("coadds_cell")]
283+
backgrounds = inputs.pop("backgrounds")
284+
for exposure, background in zip(exposures, backgrounds):
285+
exposure.image -= background.getImage()
286+
coadds = exposures
287+
else:
288+
coadds = inputs.pop("coadds")
289+
assert not inputs, "runQuantum got extra inputs"
290+
outputs = self.run(
291+
coadds=coadds,
292+
bands=bands,
293+
mergedDetections=mergedDetections,
294+
idFactory=self.config.idGenerator.apply(butlerQC.quantum.dataId).make_table_id_factory(),
295+
)
256296
butlerQC.put(outputs, outputRefs)
257297

258298
def run(self, coadds, bands, mergedDetections, idFactory):

python/lsst/pipe/tasks/fit_coadd_multiband.py

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,20 @@ class CoaddMultibandFitInputConnections(
7979
dimensions=("tract", "patch", "band", "skymap"),
8080
multiple=True,
8181
)
82+
coadds_cell = cT.Input(
83+
doc="Cell-coadd exposures on which to run fits",
84+
name="{name_coadd}CoaddCell",
85+
storageClass="MultipleCellCoadd",
86+
dimensions=("tract", "patch", "band", "skymap"),
87+
multiple=True,
88+
)
89+
backgrounds = cT.Input(
90+
doc="Background models to subtract from the coadds_cell",
91+
name="{name_coadd}Coadd_calexp_background",
92+
storageClass="Background",
93+
dimensions=("tract", "patch", "band", "skymap"),
94+
multiple=True,
95+
)
8296
models_psf = cT.Input(
8397
doc="Input PSF model parameter catalog",
8498
# Consider allowing independent psf fit method
@@ -198,9 +212,18 @@ def adjustQuantum(self, inputs, outputs, label, data_id):
198212
return adjusted_inputs, {}
199213

200214
def __init__(self, *, config=None):
215+
super().__init__(config=config)
216+
assert isinstance(config, CoaddMultibandFitBaseConfig)
217+
201218
if config.drop_psf_connection:
202219
del self.models_psf
203220

221+
if config.use_cell_coadds:
222+
del self.coadds
223+
else:
224+
del self.coadds_cell
225+
del self.backgrounds
226+
204227

205228
class CoaddMultibandFitConnections(CoaddMultibandFitInputConnections):
206229
cat_output = cT.Output(
@@ -295,6 +318,10 @@ class CoaddMultibandFitBaseConfig(
295318
target=CoaddMultibandFitSubTask,
296319
doc="Task to fit sources using multiple bands",
297320
)
321+
use_cell_coadds = pexConfig.Field[bool](
322+
doc="Use cell coadd images for object fitting?",
323+
default=False,
324+
)
298325
idGenerator = SkyMapIdGeneratorConfig.make_field()
299326

300327
def get_band_sets(self):
@@ -332,18 +359,30 @@ class CoaddMultibandFitBase:
332359
def build_catexps(self, butlerQC, inputRefs, inputs) -> list[CatalogExposureInputs]:
333360
id_tp = self.config.idGenerator.apply(butlerQC.quantum.dataId).catalog_id
334361
# This is a roundabout way of ensuring all inputs get sorted and matched
335-
keys = ["cats_meas", "coadds"]
362+
if self.config.use_cell_coadds:
363+
keys = ["cats_meas", "coadds_cell", "backgrounds"]
364+
else:
365+
keys = ["cats_meas", "coadds"]
336366
has_psf_models = "models_psf" in inputs
337367
if has_psf_models:
338368
keys.append("models_psf")
339-
input_refs_objs = ((getattr(inputRefs, key), inputs[key]) for key in keys)
340-
inputs_sorted = tuple(
341-
{dRef.dataId: obj for dRef, obj in zip(refs, objs)}
342-
for refs, objs in input_refs_objs
343-
)
344-
cats = inputs_sorted[0]
345-
exps = inputs_sorted[1]
346-
models_psf = inputs_sorted[2] if has_psf_models else None
369+
input_refs_objs = {key: (getattr(inputRefs, key), inputs[key]) for key in keys}
370+
inputs_sorted = {
371+
key: {dRef.dataId: obj for dRef, obj in zip(refs, objs, strict=True)}
372+
for key, (refs, objs) in input_refs_objs.items()
373+
}
374+
cats = inputs_sorted["cats_meas"]
375+
if self.config.use_cell_coadds:
376+
exps = {}
377+
for data_id, background in inputs_sorted["backgrounds"].items():
378+
mcc = inputs_sorted["coadds_cell"][data_id]
379+
stitched_coadd = mcc.stitch()
380+
exposure = stitched_coadd.asExposure()
381+
exposure.image -= background.getImage()
382+
exps[data_id] = exposure
383+
else:
384+
exps = inputs_sorted["coadds"]
385+
models_psf = inputs_sorted["models_psf"] if has_psf_models else None
347386
dataIds = set(cats).union(set(exps))
348387
models_scarlet = inputs["models_scarlet"]
349388
catexp_dict = {}

python/lsst/pipe/tasks/fit_coadd_psf.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,18 @@ class CoaddPsfFitConnections(
6363
storageClass="ExposureF",
6464
dimensions=("tract", "patch", "band", "skymap"),
6565
)
66+
coadd_cell = cT.Input(
67+
doc="Cell-coadd image to fit a PSF model to",
68+
name="{name_coadd}CoaddCell",
69+
storageClass="MultipleCellCoadd",
70+
dimensions=("tract", "patch", "band", "skymap"),
71+
)
72+
background = cT.Input(
73+
doc="Background model to subtract from the coadd_cell",
74+
name="{name_coadd}Coadd_calexp_background",
75+
storageClass="Background",
76+
dimensions=("tract", "patch", "band", "skymap"),
77+
)
6678
cat_meas = cT.Input(
6779
doc="Deblended single-band source catalog",
6880
name="{name_coadd}Coadd_meas",
@@ -76,6 +88,17 @@ class CoaddPsfFitConnections(
7688
dimensions=("tract", "patch", "band", "skymap"),
7789
)
7890

91+
def __init__(self, *, config=None):
92+
super().__init__(config=config)
93+
if config is None:
94+
return
95+
96+
if config.use_cell_coadds:
97+
del self.coadd
98+
else:
99+
del self.coadd_cell
100+
del self.background
101+
79102

80103
class CoaddPsfFitSubConfig(pexConfig.Config):
81104
"""Base config class for the CoaddPsfFitTask.
@@ -135,6 +158,11 @@ class CoaddPsfFitConfig(
135158
):
136159
"""Configure a CoaddPsfFitTask, including a configurable fitting subtask.
137160
"""
161+
use_cell_coadds = pexConfig.Field(
162+
dtype=bool,
163+
default=False,
164+
doc="Use cell coadd images for PSF fitting",
165+
)
138166
fit_coadd_psf = pexConfig.ConfigurableField(
139167
target=CoaddPsfFitSubTask,
140168
doc="Task to fit PSF models for a single coadd",
@@ -162,13 +190,26 @@ def runQuantum(self, butlerQC, inputRefs, outputRefs):
162190
inputs = butlerQC.get(inputRefs)
163191
id_tp = self.config.idGenerator.apply(butlerQC.quantum.dataId).catalog_id
164192
dataId = inputRefs.cat_meas.dataId
165-
for dataRef in (inputRefs.coadd,):
193+
194+
if self.config.use_cell_coadds:
195+
coaddDataRef = inputRefs.coadd_cell
196+
multiple_cell_coadd = inputs.pop('coadd_cell')
197+
background = inputs.pop('background')
198+
exposure = multiple_cell_coadd.stitch().asExposure()
199+
exposure.image -= background.getImage()
200+
else:
201+
coaddDataRef = inputRefs.coadd
202+
exposure = inputs.pop('coadd')
203+
204+
for dataRef in (coaddDataRef,):
166205
if dataRef.dataId != dataId:
167206
raise RuntimeError(f'{dataRef=}.dataId != {inputRefs.cat_meas.dataId=}')
168207

208+
catalog = inputs.pop('cat_meas')
169209
catexp = CatalogExposurePsf(
170-
catalog=inputs['cat_meas'], exposure=inputs['coadd'], dataId=dataId, id_tract_patch=id_tp,
210+
catalog=catalog, exposure=exposure, dataId=dataId, id_tract_patch=id_tp,
171211
)
212+
assert not inputs, "runQuantum got more inputs than expected"
172213
outputs = self.run(catexp=catexp)
173214
butlerQC.put(outputs, outputRefs)
174215

0 commit comments

Comments
 (0)