LSST Applications g0f08755f38+f106ab12ff,g12f32b3c4e+379379c50c,g1653933729+a8ce1bb630,g168dd56ebc+a8ce1bb630,g1a0ca8cf93+eaabd3c39c,g28da252d5a+0daa941822,g2bbee38e9b+c076ca1133,g2bc492864f+c076ca1133,g3156d2b45e+41e33cbcdc,g347aa1857d+c076ca1133,g35bb328faa+a8ce1bb630,g3a166c0a6a+c076ca1133,g3e281a1b8c+b162652f75,g414038480c+6cfc39b08c,g41af890bb2+c487125eda,g5fbc88fb19+17cd334064,g6b1c1869cb+eff3e9fdae,g781aacb6e4+a8ce1bb630,g80478fca09+a0d7f63753,g82479be7b0+052d678814,g858d7b2824+f106ab12ff,g89c8672015+ff349045bf,g9125e01d80+a8ce1bb630,g9726552aa6+3a8748fa0c,ga5288a1d22+d836312400,gb58c049af0+d64f4d3760,gc28159a63d+c076ca1133,gcf0d15dbbd+3012552f84,gd7358e8bfb+8e90b07072,gda3e153d99+f106ab12ff,gda6a2b7d83+3012552f84,gdaeeff99f8+1711a396fd,ge2409df99d+e4ed96189f,ge79ae78c31+c076ca1133,gf0baf85859+50e8a91c63,gf3967379c6+f3639e9197,gfb92a5be7c+f106ab12ff,gfec2e1e490+bdc87d04ab,w.2024.47
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 cat_meas = cT.Input(
67 doc="Deblended single-band source catalog",
68 name="{name_coadd}Coadd_meas",
69 storageClass="SourceCatalog",
70 dimensions=("tract", "patch", "band", "skymap"),
71 )
72 cat_output = cT.Output(
73 doc="Output PSF fit parameter catalog",
74 name="{name_coadd}Coadd_psfs_{name_output_method}",
75 storageClass="ArrowTable",
76 dimensions=("tract", "patch", "band", "skymap"),
77 )
78
79
80class CoaddPsfFitSubConfig(pexConfig.Config):
81 """Base config class for the CoaddPsfFitTask.
82
83 Implementing classes may add any necessary attributes.
84 """
85
86
87class CoaddPsfFitSubTask(pipeBase.Task, ABC):
88 """Interface for CoaddPsfFitTask subtasks to fit PSFs.
89
90 Parameters
91 ----------
92 **kwargs
93 Additional arguments to be passed to the `lsst.pipe.base.Task`
94 constructor.
95 """
96 ConfigClass = CoaddPsfFitSubConfig
97
98 def __init__(self, **kwargs):
99 super().__init__(**kwargs)
100
101 @abstractmethod
102 def run(
103 self, catexp: CatalogExposurePsf
104 ) -> pipeBase.Struct:
105 """Fit PSF images at locations of sources in a single exposure.
106
107 Parameters
108 ----------
109 catexp : `CatalogExposurePsf`
110 An exposure to fit a model PSF at the position of all
111 sources in the corresponding catalog.
112
113 Returns
114 -------
115 retStruct : `lsst.pipe.base.Struct`
116 A struct with a cat_output attribute containing the output
117 measurement catalog.
118
119 Notes
120 -----
121 Subclasses may have further requirements on the input parameters,
122 including:
123 - Passing only one catexp per band;
124 - Catalogs containing HeavyFootprints with deblended images;
125 - Fitting only a subset of the sources.
126 If any requirements are not met, the subtask should fail as soon as
127 possible.
128 """
129 raise NotImplementedError()
130
131
133 pipeBase.PipelineTaskConfig,
134 pipelineConnections=CoaddPsfFitConnections,
135):
136 """Configure a CoaddPsfFitTask, including a configurable fitting subtask.
137 """
138 fit_coadd_psf = pexConfig.ConfigurableField(
139 target=CoaddPsfFitSubTask,
140 doc="Task to fit PSF models for a single coadd",
141 )
142 idGenerator = SkyMapIdGeneratorConfig.make_field()
143
144
145class CoaddPsfFitTask(pipeBase.PipelineTask):
146 """Fit a PSF model at the location of sources in a coadd.
147
148 This task is intended to fit only a single PSF model at the
149 centroid of all of the sources in a single coadd exposure.
150 Subtasks may choose to filter which sources they fit,
151 and may output whatever columns they desire in addition to
152 the minimum of 'id'.
153 """
154 ConfigClass = CoaddPsfFitConfig
155 _DefaultName = "CoaddPsfFit"
156
157 def __init__(self, initInputs, **kwargs):
158 super().__init__(initInputs=initInputs, **kwargs)
159 self.makeSubtask("fit_coadd_psf")
160
161 def runQuantum(self, butlerQC, inputRefs, outputRefs):
162 inputs = butlerQC.get(inputRefs)
163 id_tp = self.config.idGenerator.apply(butlerQC.quantum.dataId).catalog_id
164 dataId = inputRefs.cat_meas.dataId
165 for dataRef in (inputRefs.coadd,):
166 if dataRef.dataId != dataId:
167 raise RuntimeError(f'{dataRef=}.dataId != {inputRefs.cat_meas.dataId=}')
168
169 catexp = CatalogExposurePsf(
170 catalog=inputs['cat_meas'], exposure=inputs['coadd'], dataId=dataId, id_tract_patch=id_tp,
171 )
172 outputs = self.run(catexp=catexp)
173 butlerQC.put(outputs, outputRefs)
174
175 def run(self, catexp: CatalogExposurePsf) -> pipeBase.Struct:
176 """Fit a PSF model at the location of sources in a coadd.
177
178 Parameters
179 ----------
180 catexp : `typing.List [CatalogExposurePsf]`
181 A list of catalog-exposure pairs in a given band.
182
183 Returns
184 -------
185 retStruct : `lsst.pipe.base.Struct`
186 A struct with a cat_output attribute containing the output
187 measurement catalog.
188
189 Notes
190 -----
191 Subtasks may have further requirements; see `CoaddPsfFitSubTask.run`.
192 """
193 cat_output = self.fit_coadd_psf.run(catexp).output
194 retStruct = pipeBase.Struct(cat_output=cat_output)
195 return retStruct
pipeBase.Struct run(self, CatalogExposurePsf catexp)
pipeBase.Struct run(self, CatalogExposurePsf catexp)
runQuantum(self, butlerQC, inputRefs, outputRefs)