LSST Applications g180d380827+770a9040cc,g2079a07aa2+86d27d4dc4,g2305ad1205+09cfdadad9,g2bbee38e9b+c6a8a0fb72,g337abbeb29+c6a8a0fb72,g33d1c0ed96+c6a8a0fb72,g3a166c0a6a+c6a8a0fb72,g3ddfee87b4+1ea5e09c42,g48712c4677+7e2ea9cd42,g487adcacf7+301d09421d,g50ff169b8f+96c6868917,g52b1c1532d+585e252eca,g591dd9f2cf+96fcb956a6,g64a986408d+23540ee355,g858d7b2824+23540ee355,g864b0138d7+aa38e45daa,g95921f966b+d83dc58ecd,g991b906543+23540ee355,g99cad8db69+7f13b58a93,g9c22b2923f+e2510deafe,g9ddcbc5298+9a081db1e4,ga1e77700b3+03d07e1c1f,gb0e22166c9+60f28cb32d,gb23b769143+23540ee355,gba4ed39666+c2a2e4ac27,gbb8dafda3b+49e7449578,gbd998247f1+585e252eca,gc120e1dc64+1bbfa184e1,gc28159a63d+c6a8a0fb72,gc3e9b769f7+385ea95214,gcf0d15dbbd+1ea5e09c42,gdaeeff99f8+f9a426f77a,ge6526c86ff+1bccc98490,ge79ae78c31+c6a8a0fb72,gee10cc3b42+585e252eca,w.2024.18
LSST Data Management Base Package
Loading...
Searching...
No Matches
coaddBase.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__ = ["CoaddBaseTask", "makeSkyInfo"]
23
24import lsst.pex.config as pexConfig
25import lsst.afw.image as afwImage
26import lsst.pipe.base as pipeBase
27import lsst.geom as geom
28
29from lsst.meas.algorithms import ScaleVarianceTask
30from .selectImages import PsfWcsSelectImagesTask
31from .coaddInputRecorder import CoaddInputRecorderTask
32
33
34class CoaddBaseConfig(pexConfig.Config):
35 """Configuration parameters for CoaddBaseTask
36
37 Configuration parameters shared between MakeCoaddTempExp and AssembleCoadd
38 """
39
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 includeCalibVar = pexConfig.Field(
59 dtype=bool,
60 doc="Add photometric calibration variance to warp variance plane.",
61 default=False
62 )
63 matchingKernelSize = pexConfig.Field(
64 dtype=int,
65 doc="Size in pixels of matching kernel. Must be odd.",
66 default=21,
67 check=lambda x: x % 2 == 1
68 )
69
70
71class CoaddBaseTask(pipeBase.PipelineTask):
72 """Base class for coaddition.
73
74 Subclasses must specify _DefaultName
75 """
76
77 ConfigClass = CoaddBaseConfig
78
79 def __init__(self, **kwargs):
80 super().__init__(**kwargs)
81 self.makeSubtask("select")
82 self.makeSubtask("inputRecorder")
83
84 def getTempExpDatasetName(self, warpType="direct"):
85 """Return warp name for given warpType and task config
86
87 Parameters
88 ----------
89 warpType : `str`
90 Either 'direct' or 'psfMatched'.
91
92 Returns
93 -------
94 WarpDatasetName : `str`
95 """
96 return self.config.coaddName + "Coadd_" + warpType + "Warp"
97
98 def getBadPixelMask(self):
99 """Convenience method to provide the bitmask from the mask plane names
100 """
101 return afwImage.Mask.getPlaneBitMask(self.config.badMaskPlanes)
102
103
104def makeSkyInfo(skyMap, tractId, patchId):
105 """Constructs SkyInfo used by coaddition tasks for multiple
106 patchId formats.
107
108 Parameters
109 ----------
110 skyMap : `lsst.skyMap.SkyMap`
111 Sky map.
112 tractId : `int`
113 The ID of the tract.
114 patchId : `str` or `int` or `tuple` of `int`
115 Either Gen2-style comma delimited string (e.g. '4,5'),
116 tuple of integers (e.g (4, 5), Gen3-style integer.
117
118 Returns
119 -------
120 makeSkyInfo : `lsst.pipe.base.Struct`
121 pipe_base Struct with attributes:
122
123 ``skyMap``
124 Sky map (`lsst.skyMap.SkyMap`).
125 ``tractInfo``
126 Information for chosen tract of sky map (`lsst.skyMap.TractInfo`).
127 ``patchInfo``
128 Information about chosen patch of tract (`lsst.skyMap.PatchInfo`).
129 ``wcs``
130 WCS of tract (`lsst.afw.image.SkyWcs`).
131 ``bbox``
132 Outer bbox of patch, as an geom Box2I (`lsst.afw.geom.Box2I`).
133 """
134 tractInfo = skyMap[tractId]
135
136 if isinstance(patchId, str) and ',' in patchId:
137 # patch format is "xIndex,yIndex"
138 patchIndex = tuple(int(i) for i in patchId.split(","))
139 else:
140 patchIndex = patchId
141
142 patchInfo = tractInfo.getPatchInfo(patchIndex)
143
144 return pipeBase.Struct(
145 skyMap=skyMap,
146 tractInfo=tractInfo,
147 patchInfo=patchInfo,
148 wcs=tractInfo.getWcs(),
149 bbox=patchInfo.getOuterBBox(),
150 )
151
152
153def scaleVariance(maskedImage, maskPlanes, log=None):
154 """Scale the variance in a maskedImage
155
156 This is deprecated. Use the ScaleVarianceTask instead.
157
158 Parameters
159 ----------
160 maskedImage : `lsst.afw.image.MaskedImage`
161 MaskedImage to operate on; variance will be scaled.
162 maskPlanes : `list`
163 List of mask planes for pixels to reject.
164 log : `Unknown`
165 Log for reporting the renormalization factor; or None.
166
167 Returns
168 -------
169 task.run : `Unknown`
170 Renormalization factor.
171
172 Notes
173 -----
174 The variance plane in a convolved or warped image (or a coadd derived
175 from warped images) does not accurately reflect the noise properties of
176 the image because variance has been lost to covariance. This function
177 attempts to correct for this by scaling the variance plane to match
178 the observed variance in the image. This is not perfect (because we're
179 not tracking the covariance) but it's simple and is often good enough.
180 """
181 config = ScaleVarianceTask.ConfigClass()
182 config.maskPlanes = maskPlanes
183 task = ScaleVarianceTask(config=config, name="scaleVariance", log=log)
184 return task.run(maskedImage)
185
186
187def reorderAndPadList(inputList, inputKeys, outputKeys, padWith=None):
188 """Match the order of one list to another, padding if necessary
189
190 Parameters
191 ----------
192 inputList : `list`
193 List to be reordered and padded. Elements can be any type.
194 inputKeys : `iterable`
195 Iterable of values to be compared with outputKeys. Length must match `inputList`.
196 outputKeys : `iterable`
197 Iterable of values to be compared with inputKeys.
198 padWith : `Unknown`
199 Any value to be inserted where inputKey not in outputKeys.
200
201 Returns
202 -------
203 outputList : `list`
204 Copy of inputList reordered per outputKeys and padded with `padWith`
205 so that the length matches length of outputKeys.
206 """
207 outputList = []
208 for d in outputKeys:
209 if d in inputKeys:
210 outputList.append(inputList[inputKeys.index(d)])
211 else:
212 outputList.append(padWith)
213 return outputList
214
215
216def subBBoxIter(bbox, subregionSize):
217 """Iterate over subregions of a bbox.
218
219 Parameters
220 ----------
221 bbox : `lsst.geom.Box2I`
222 Bounding box over which to iterate.
223 subregionSize : `lsst.geom.Extent2I`
224 Size of sub-bboxes.
225
226 Yields
227 ------
228 subBBox : `lsst.geom.Box2I`
229 Next sub-bounding box of size ``subregionSize`` or smaller; each ``subBBox``
230 is contained within ``bbox``, so it may be smaller than ``subregionSize`` at
231 the edges of ``bbox``, but it will never be empty.
232
233 Raises
234 ------
235 RuntimeError
236 Raised if any of the following occur:
237 - The given bbox is empty.
238 - The subregionSize is 0.
239 """
240 if bbox.isEmpty():
241 raise RuntimeError("bbox %s is empty" % (bbox,))
242 if subregionSize[0] < 1 or subregionSize[1] < 1:
243 raise RuntimeError("subregionSize %s must be nonzero" % (subregionSize,))
244
245 for rowShift in range(0, bbox.getHeight(), subregionSize[1]):
246 for colShift in range(0, bbox.getWidth(), subregionSize[0]):
247 subBBox = geom.Box2I(bbox.getMin() + geom.Extent2I(colShift, rowShift), subregionSize)
248 subBBox.clip(bbox)
249 if subBBox.isEmpty():
250 raise RuntimeError("Bug: empty bbox! bbox=%s, subregionSize=%s, "
251 "colShift=%s, rowShift=%s" %
252 (bbox, subregionSize, colShift, rowShift))
253 yield subBBox
An integer coordinate rectangle.
Definition Box.h:55
getTempExpDatasetName(self, warpType="direct")
Definition coaddBase.py:84
reorderAndPadList(inputList, inputKeys, outputKeys, padWith=None)
Definition coaddBase.py:187
makeSkyInfo(skyMap, tractId, patchId)
Definition coaddBase.py:104
subBBoxIter(bbox, subregionSize)
Definition coaddBase.py:216