LSST Applications g04e9c324dd+8c5ae1fdc5,g134cb467dc+1b3060144d,g18429d2f64+f642bf4753,g199a45376c+0ba108daf9,g1fd858c14a+2dcf163641,g262e1987ae+7b8c96d2ca,g29ae962dfc+3bd6ecb08a,g2cef7863aa+aef1011c0b,g35bb328faa+8c5ae1fdc5,g3fd5ace14f+53e1a9e7c5,g4595892280+fef73a337f,g47891489e3+2efcf17695,g4d44eb3520+642b70b07e,g53246c7159+8c5ae1fdc5,g67b6fd64d1+2efcf17695,g67fd3c3899+b70e05ef52,g74acd417e5+317eb4c7d4,g786e29fd12+668abc6043,g87389fa792+8856018cbb,g89139ef638+2efcf17695,g8d7436a09f+3be3c13596,g8ea07a8fe4+9f5ccc88ac,g90f42f885a+a4e7b16d9b,g97be763408+ad77d7208f,g9dd6db0277+b70e05ef52,ga681d05dcb+a3f46e7fff,gabf8522325+735880ea63,gac2eed3f23+2efcf17695,gb89ab40317+2efcf17695,gbf99507273+8c5ae1fdc5,gd8ff7fe66e+b70e05ef52,gdab6d2f7ff+317eb4c7d4,gdc713202bf+b70e05ef52,gdfd2d52018+b10e285e0f,ge365c994fd+310e8507c4,ge410e46f29+2efcf17695,geaed405ab2+562b3308c0,gffca2db377+8c5ae1fdc5,w.2025.35
LSST Data Management Base Package
Loading...
Searching...
No Matches
fit_coadd_psf.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__all__ = [
23 "CatalogExposurePsf", "CoaddPsfFitConfig", "CoaddPsfFitConnections",
24 "CoaddPsfFitSubConfig", "CoaddPsfFitSubTask", "CoaddPsfFitTask",
25]
26
27from .fit_multiband import CatalogExposure, CatalogExposureConfig
28from lsst.meas.base import SkyMapIdGeneratorConfig
29import lsst.pex.config as pexConfig
30import lsst.pipe.base as pipeBase
31import lsst.pipe.base.connectionTypes as cT
32
33from abc import ABC, abstractmethod
34from pydantic.dataclasses import dataclass
35
36
37@dataclass(frozen=True, kw_only=True, config=CatalogExposureConfig)
39 def get_catalog(self):
40 return self.catalog
41
42 def get_psf_image(self, source):
43 """Return the PSF image for this object."""
44 bbox = source.getFootprint().getBBox()
45 center = bbox.getCenter()
46 return self.exposure.getPsf().computeKernelImage(center).array
47
48
49CoaddPsfFitBaseTemplates = {
50 "name_coadd": "deep",
51 "name_output_method": "multiprofit",
52}
53
54
56 pipeBase.PipelineTaskConnections,
57 dimensions=("tract", "patch", "band", "skymap"),
58 defaultTemplates=CoaddPsfFitBaseTemplates,
59):
60 coadd = cT.Input(
61 doc="Coadd image to fit a PSF model to",
62 name="{name_coadd}Coadd_calexp",
63 storageClass="ExposureF",
64 dimensions=("tract", "patch", "band", "skymap"),
65 )
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 )
78 cat_meas = cT.Input(
79 doc="Deblended single-band source catalog",
80 name="{name_coadd}Coadd_meas",
81 storageClass="SourceCatalog",
82 dimensions=("tract", "patch", "band", "skymap"),
83 )
84 cat_output = cT.Output(
85 doc="Output PSF fit parameter catalog",
86 name="{name_coadd}Coadd_psfs_{name_output_method}",
87 storageClass="ArrowTable",
88 dimensions=("tract", "patch", "band", "skymap"),
89 )
90
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
102
103class CoaddPsfFitSubConfig(pexConfig.Config):
104 """Base config class for the CoaddPsfFitTask.
105
106 Implementing classes may add any necessary attributes.
107 """
108
109
110class CoaddPsfFitSubTask(pipeBase.Task, ABC):
111 """Interface for CoaddPsfFitTask subtasks to fit PSFs.
112
113 Parameters
114 ----------
115 **kwargs
116 Additional arguments to be passed to the `lsst.pipe.base.Task`
117 constructor.
118 """
119 ConfigClass = CoaddPsfFitSubConfig
120
121 def __init__(self, **kwargs):
122 super().__init__(**kwargs)
123
124 @abstractmethod
125 def run(
126 self, catexp: CatalogExposurePsf
127 ) -> pipeBase.Struct:
128 """Fit PSF images at locations of sources in a single exposure.
129
130 Parameters
131 ----------
132 catexp : `CatalogExposurePsf`
133 An exposure to fit a model PSF at the position of all
134 sources in the corresponding catalog.
135
136 Returns
137 -------
138 retStruct : `lsst.pipe.base.Struct`
139 A struct with a cat_output attribute containing the output
140 measurement catalog.
141
142 Notes
143 -----
144 Subclasses may have further requirements on the input parameters,
145 including:
146 - Passing only one catexp per band;
147 - Catalogs containing HeavyFootprints with deblended images;
148 - Fitting only a subset of the sources.
149 If any requirements are not met, the subtask should fail as soon as
150 possible.
151 """
152 raise NotImplementedError()
153
154
156 pipeBase.PipelineTaskConfig,
157 pipelineConnections=CoaddPsfFitConnections,
158):
159 """Configure a CoaddPsfFitTask, including a configurable fitting subtask.
160 """
161 use_cell_coadds = pexConfig.Field(
162 dtype=bool,
163 default=False,
164 doc="Use cell coadd images for PSF fitting",
165 )
166 fit_coadd_psf = pexConfig.ConfigurableField(
167 target=CoaddPsfFitSubTask,
168 doc="Task to fit PSF models for a single coadd",
169 )
170 idGenerator = SkyMapIdGeneratorConfig.make_field()
171
172
173class CoaddPsfFitTask(pipeBase.PipelineTask):
174 """Fit a PSF model at the location of sources in a coadd.
175
176 This task is intended to fit only a single PSF model at the
177 centroid of all of the sources in a single coadd exposure.
178 Subtasks may choose to filter which sources they fit,
179 and may output whatever columns they desire in addition to
180 the minimum of 'id'.
181 """
182 ConfigClass = CoaddPsfFitConfig
183 _DefaultName = "CoaddPsfFit"
184
185 def __init__(self, initInputs, **kwargs):
186 super().__init__(initInputs=initInputs, **kwargs)
187 self.makeSubtask("fit_coadd_psf")
188
189 def runQuantum(self, butlerQC, inputRefs, outputRefs):
190 inputs = butlerQC.get(inputRefs)
191 id_tp = self.config.idGenerator.apply(butlerQC.quantum.dataId).catalog_id
192 dataId = inputRefs.cat_meas.dataId
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,):
205 if dataRef.dataId != dataId:
206 raise RuntimeError(f'{dataRef=}.dataId != {inputRefs.cat_meas.dataId=}')
207
208 catalog = inputs.pop('cat_meas')
209 catexp = CatalogExposurePsf(
210 catalog=catalog, exposure=exposure, dataId=dataId, id_tract_patch=id_tp,
211 )
212 assert not inputs, "runQuantum got more inputs than expected"
213 outputs = self.run(catexp=catexp)
214 butlerQC.put(outputs, outputRefs)
215
216 def run(self, catexp: CatalogExposurePsf) -> pipeBase.Struct:
217 """Fit a PSF model at the location of sources in a coadd.
218
219 Parameters
220 ----------
221 catexp : `typing.List [CatalogExposurePsf]`
222 A list of catalog-exposure pairs in a given band.
223
224 Returns
225 -------
226 retStruct : `lsst.pipe.base.Struct`
227 A struct with a cat_output attribute containing the output
228 measurement catalog.
229
230 Notes
231 -----
232 Subtasks may have further requirements; see `CoaddPsfFitSubTask.run`.
233 """
234 cat_output = self.fit_coadd_psf.run(catexp).output
235 retStruct = pipeBase.Struct(cat_output=cat_output)
236 return retStruct
pipeBase.Struct run(self, CatalogExposurePsf catexp)
pipeBase.Struct run(self, CatalogExposurePsf catexp)
runQuantum(self, butlerQC, inputRefs, outputRefs)