Coverage for python/lsst/pipe/tasks/coaddBase.py: 52%
52 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-11 02:44 -0700
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-11 02:44 -0700
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/>.
22__all__ = ["CoaddBaseTask", "makeSkyInfo"]
24import lsst.pex.config as pexConfig
25import lsst.afw.image as afwImage
26import lsst.pipe.base as pipeBase
27import lsst.meas.algorithms as measAlg
29from lsst.meas.algorithms import ScaleVarianceTask
30from .selectImages import PsfWcsSelectImagesTask
31from .coaddInputRecorder import CoaddInputRecorderTask
34class CoaddBaseConfig(pexConfig.Config):
35 """Configuration parameters for CoaddBaseTask
37 Configuration parameters shared between MakeCoaddTempExp and AssembleCoadd
38 """
40 coaddName = pexConfig.Field(
41 doc="Coadd name: typically one of deep or goodSeeing.",
42 dtype=str,
43 default="deep",
44 )
45 select = pexConfig.ConfigurableField(
46 doc="Image selection subtask.",
47 target=PsfWcsSelectImagesTask,
48 )
49 badMaskPlanes = pexConfig.ListField(
50 dtype=str,
51 doc="Mask planes that, if set, the associated pixel should not be included in the coaddTempExp.",
52 default=("NO_DATA",),
53 )
54 inputRecorder = pexConfig.ConfigurableField(
55 doc="Subtask that helps fill CoaddInputs catalogs added to the final Exposure",
56 target=CoaddInputRecorderTask
57 )
58 doPsfMatch = pexConfig.Field(
59 dtype=bool,
60 doc="Match to modelPsf? Deprecated. Sets makePsfMatched=True, makeDirect=False",
61 default=False
62 )
63 modelPsf = measAlg.GaussianPsfFactory.makeField(doc="Model Psf factory")
64 doApplyExternalPhotoCalib = pexConfig.Field(
65 dtype=bool,
66 default=False,
67 doc=("Whether to apply external photometric calibration via an "
68 "`lsst.afw.image.PhotoCalib` object. Uses the "
69 "`externalPhotoCalibName` field to determine which calibration "
70 "to load.")
71 )
72 useGlobalExternalPhotoCalib = pexConfig.Field(
73 dtype=bool,
74 default=True,
75 doc=("When using doApplyExternalPhotoCalib, use 'global' calibrations "
76 "that are not run per-tract. When False, use per-tract photometric "
77 "calibration files.")
78 )
79 externalPhotoCalibName = pexConfig.ChoiceField(
80 # TODO: Remove this config with the removal of Gen2 in DM-20572.
81 dtype=str,
82 doc=("Type of external PhotoCalib if `doApplyExternalPhotoCalib` is True. "
83 "This field is only used for Gen2 middleware."),
84 default="jointcal",
85 allowed={
86 "jointcal": "Use jointcal_photoCalib",
87 "fgcm": "Use fgcm_photoCalib",
88 "fgcm_tract": "Use fgcm_tract_photoCalib"
89 },
90 deprecated="This configuration is no longer used, and will be removed after v25.0",
91 )
92 doApplyExternalSkyWcs = pexConfig.Field(
93 dtype=bool,
94 default=False,
95 doc=("Whether to apply external astrometric calibration via an "
96 "`lsst.afw.geom.SkyWcs` object. Uses `externalSkyWcsName` "
97 "field to determine which calibration to load.")
98 )
99 useGlobalExternalSkyWcs = pexConfig.Field(
100 dtype=bool,
101 default=True,
102 doc=("When using doApplyExternalSkyWcs, use 'global' calibrations "
103 "that are not run per-tract. When False, use per-tract wcs "
104 "files.")
105 )
106 externalSkyWcsName = pexConfig.ChoiceField(
107 # TODO: Remove this config with the removal of Gen2 in DM-20572.
108 dtype=str,
109 doc=("Type of external SkyWcs if `doApplyExternalSkyWcs` is True. "
110 "This field is only used for Gen2 middleware."),
111 default="jointcal",
112 allowed={
113 "jointcal": "Use jointcal_wcs"
114 },
115 deprecated="This configuration is no longer used, and will be removed after v25.0",
116 )
117 includeCalibVar = pexConfig.Field(
118 dtype=bool,
119 doc="Add photometric calibration variance to warp variance plane.",
120 default=False
121 )
122 matchingKernelSize = pexConfig.Field( 122 ↛ exitline 122 didn't jump to the function exit
123 dtype=int,
124 doc="Size in pixels of matching kernel. Must be odd.",
125 default=21,
126 check=lambda x: x % 2 == 1
127 )
130class CoaddBaseTask(pipeBase.PipelineTask):
131 """Base class for coaddition.
133 Subclasses must specify _DefaultName
134 """
136 ConfigClass = CoaddBaseConfig
138 def __init__(self, **kwargs):
139 super().__init__(**kwargs)
140 self.makeSubtask("select")
141 self.makeSubtask("inputRecorder")
143 def getTempExpDatasetName(self, warpType="direct"):
144 """Return warp name for given warpType and task config
146 Parameters
147 ----------
148 warpType : `str`
149 Either 'direct' or 'psfMatched'.
151 Returns
152 -------
153 WarpDatasetName : `str`
154 """
155 return self.config.coaddName + "Coadd_" + warpType + "Warp"
157 def getBadPixelMask(self):
158 """Convenience method to provide the bitmask from the mask plane names
159 """
160 return afwImage.Mask.getPlaneBitMask(self.config.badMaskPlanes)
163def makeSkyInfo(skyMap, tractId, patchId):
164 """Constructs SkyInfo used by coaddition tasks for multiple
165 patchId formats.
167 Parameters
168 ----------
169 skyMap : `lsst.skyMap.SkyMap`
170 Sky map.
171 tractId : `int`
172 The ID of the tract.
173 patchId : `str` or `int` or `tuple` of `int`
174 Either Gen2-style comma delimited string (e.g. '4,5'),
175 tuple of integers (e.g (4, 5), Gen3-style integer.
177 Returns
178 -------
179 makeSkyInfo : `lsst.pipe.base.Struct`
180 pipe_base Struct with attributes:
182 ``skyMap``
183 Sky map (`lsst.skyMap.SkyMap`).
184 ``tractInfo``
185 Information for chosen tract of sky map (`lsst.skyMap.TractInfo`).
186 ``patchInfo``
187 Information about chosen patch of tract (`lsst.skyMap.PatchInfo`).
188 ``wcs``
189 WCS of tract (`lsst.afw.image.SkyWcs`).
190 ``bbox``
191 Outer bbox of patch, as an geom Box2I (`lsst.afw.geom.Box2I`).
192 """
193 tractInfo = skyMap[tractId]
195 if isinstance(patchId, str) and ',' in patchId:
196 # patch format is "xIndex,yIndex"
197 patchIndex = tuple(int(i) for i in patchId.split(","))
198 else:
199 patchIndex = patchId
201 patchInfo = tractInfo.getPatchInfo(patchIndex)
203 return pipeBase.Struct(
204 skyMap=skyMap,
205 tractInfo=tractInfo,
206 patchInfo=patchInfo,
207 wcs=tractInfo.getWcs(),
208 bbox=patchInfo.getOuterBBox(),
209 )
212def scaleVariance(maskedImage, maskPlanes, log=None):
213 """Scale the variance in a maskedImage
215 This is deprecated. Use the ScaleVarianceTask instead.
217 Parameters
218 ----------
219 maskedImage : `lsst.afw.image.MaskedImage`
220 MaskedImage to operate on; variance will be scaled.
221 maskPlanes : `list`
222 List of mask planes for pixels to reject.
223 log : `Unknown`
224 Log for reporting the renormalization factor; or None.
226 Returns
227 -------
228 task.run : `Unknown`
229 Renormalization factor.
231 Notes
232 -----
233 The variance plane in a convolved or warped image (or a coadd derived
234 from warped images) does not accurately reflect the noise properties of
235 the image because variance has been lost to covariance. This function
236 attempts to correct for this by scaling the variance plane to match
237 the observed variance in the image. This is not perfect (because we're
238 not tracking the covariance) but it's simple and is often good enough.
239 """
240 config = ScaleVarianceTask.ConfigClass()
241 config.maskPlanes = maskPlanes
242 task = ScaleVarianceTask(config=config, name="scaleVariance", log=log)
243 return task.run(maskedImage)
246def reorderAndPadList(inputList, inputKeys, outputKeys, padWith=None):
247 """Match the order of one list to another, padding if necessary
249 Parameters
250 ----------
251 inputList : `list`
252 List to be reordered and padded. Elements can be any type.
253 inputKeys : `iterable`
254 Iterable of values to be compared with outputKeys. Length must match `inputList`.
255 outputKeys : `iterable`
256 Iterable of values to be compared with inputKeys.
257 padWith : `Unknown`
258 Any value to be inserted where inputKey not in outputKeys.
260 Returns
261 -------
262 outputList : `list`
263 Copy of inputList reordered per outputKeys and padded with `padWith`
264 so that the length matches length of outputKeys.
265 """
266 outputList = []
267 for d in outputKeys:
268 if d in inputKeys:
269 outputList.append(inputList[inputKeys.index(d)])
270 else:
271 outputList.append(padWith)
272 return outputList