LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
LSST Data Management Base Package
_warper.py
Go to the documentation of this file.
1# This file is part of afw.
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__ = ["Warper", "WarperConfig"]
23
24import lsst.pex.config as pexConfig
25import lsst.geom
26import lsst.afw.image as afwImage
27from ._math import warpImage
28from ._math import WarpingControl
29from ._math import warpExposure
30
31
32def computeWarpedBBox(destWcs, srcBBox, srcWcs):
33 """Compute the bounding box of a warped image.
34
35 The bounding box includes all warped pixels and it may be a bit oversize.
36
37 Parameters
38 ----------
39 destWcs : `lsst.afw.geom.SkyWcs`
40 WCS of warped exposure
41 srcBBox : `lsst.geom.Box2I`
42 parent bounding box of unwarped image
43 srcWcs : `lsst.afw.geom.SkyWcs`
44 WCS of unwarped image
45
46 Returns
47 -------
48 destBBox: `lsst.geom.Box2I`
49 bounding box of warped exposure
50 """
51 srcPosBox = lsst.geom.Box2D(srcBBox)
52 destPosBox = lsst.geom.Box2D()
53 for inX in (srcPosBox.getMinX(), srcPosBox.getMaxX()):
54 for inY in (srcPosBox.getMinY(), srcPosBox.getMaxY()):
55 destPos = destWcs.skyToPixel(srcWcs.pixelToSky(inX, inY))
56 destPosBox.include(destPos)
57 destBBox = lsst.geom.Box2I(destPosBox, lsst.geom.Box2I.EXPAND)
58 return destBBox
59
60
61_DefaultInterpLength = 10
62_DefaultCacheSize = 1000000
63
64
65class WarperConfig(pexConfig.Config):
66 warpingKernelName = pexConfig.ChoiceField(
67 dtype=str,
68 doc="Warping kernel",
69 default="lanczos3",
70 allowed={
71 "bilinear": "bilinear interpolation",
72 "lanczos3": "Lanczos kernel of order 3",
73 "lanczos4": "Lanczos kernel of order 4",
74 "lanczos5": "Lanczos kernel of order 5",
75 }
76 )
77 maskWarpingKernelName = pexConfig.ChoiceField(
78 dtype=str,
79 doc="Warping kernel for mask (use ``warpingKernelName`` if '')",
80 default="bilinear",
81 allowed={
82 "": "use the regular warping kernel for the mask plane, as well as the image and variance planes",
83 "bilinear": "bilinear interpolation",
84 "lanczos3": "Lanczos kernel of order 3",
85 "lanczos4": "Lanczos kernel of order 4",
86 "lanczos5": "Lanczos kernel of order 5",
87 }
88 )
89 interpLength = pexConfig.Field(
90 dtype=int,
91 doc="``interpLength`` argument to `lsst.afw.math.warpExposure`",
92 default=_DefaultInterpLength,
93 )
94 cacheSize = pexConfig.Field(
95 dtype=int,
96 doc="``cacheSize`` argument to `lsst.afw.math.SeparableKernel.computeCache`",
97 default=_DefaultCacheSize,
98 )
99 growFullMask = pexConfig.Field(
100 dtype=int,
101 doc="mask bits to grow to full width of image/variance kernel,",
102 default=afwImage.Mask.getPlaneBitMask("EDGE"),
103 )
104
105
106class Warper:
107 """Warp images.
108
109 Parameters
110 ----------
111 warpingKernelName : `str`
112 see `WarperConfig.warpingKernelName`
113 interpLength : `int`, optional
114 ``interpLength`` argument to `lsst.afw.math.warpExposure`
115 cacheSize : `int`, optional
116 size of computeCache
117 maskWarpingKernelName : `str`, optional
118 name of mask warping kernel (if ``""`` then use ``warpingKernelName``);
119 see `WarperConfig.maskWarpingKernelName`
120 growFullMask : `int`, optional
121 mask bits to grow to full width of image/variance kernel
122 """
123 ConfigClass = WarperConfig
124
125 def __init__(self,
126 warpingKernelName,
127 interpLength=_DefaultInterpLength,
128 cacheSize=_DefaultCacheSize,
129 maskWarpingKernelName="",
130 growFullMask=afwImage.Mask.getPlaneBitMask("EDGE"),):
131 self._warpingControl_warpingControl = WarpingControl(
132 warpingKernelName, maskWarpingKernelName, cacheSize, interpLength, growFullMask)
133
134 @classmethod
135 def fromConfig(cls, config):
136 """Create a Warper from a config.
137
138 Parameters
139 ----------
140 config : `WarperConfig`
141 The config to initialize the Warper with.
142 """
143 return cls(
144 warpingKernelName=config.warpingKernelName,
145 maskWarpingKernelName=config.maskWarpingKernelName,
146 interpLength=config.interpLength,
147 cacheSize=config.cacheSize,
148 growFullMask=config.growFullMask,
149 )
150
152 """Get the warping kernel.
153 """
154 return self._warpingControl_warpingControl.getWarpingKernel()
155
157 """Get the mask warping kernel.
158 """
159 return self._warpingControl_warpingControl.getMaskWarpingKernel()
160
161 def warpExposure(self, destWcs, srcExposure, border=0, maxBBox=None, destBBox=None):
162 """Warp an exposure.
163
164 Parameters
165 -----------
166 destWcs : `lsst.afw.geom.SkyWcs`
167 WCS of warped exposure
168 srcExposure
169 exposure to warp
170 border : `int`, optional
171 grow bbox of warped exposure by this amount in all directions
172 (in pixels); if negative then the bbox is shrunk; border is applied
173 before ``maxBBox``; ignored if ``destBBox`` is not `None`
174 maxBBox : `lsst.geom.Box2I`, optional
175 maximum allowed parent bbox of warped exposure; if `None` then the
176 warped exposure will be just big enough to contain all warped pixels;
177 if provided then the warped exposure may be smaller, and so
178 missing some warped pixels; ignored if ``destBBox`` is not `None`
179 destBBox : `lsst.geom.Box2I`, optional
180 exact parent bbox of warped exposure; if `None` then ``border`` and
181 ``maxBBox`` are used to determine the bbox, otherwise ``border``
182 and ``maxBBox`` are ignored
183
184 Returns
185 -------
186 destExposure : same type as ``srcExposure``
187 warped exposure
188
189 Notes
190 -----
191 calls `lsst.afw.math.warpExposure` insted of `~Warper.warpImage` because the former
192 copies attributes such as ``Calib``, and that should be done in one place
193
194 The PSF is not warped. To warp the PSF, use `lsst.meas.algorithms.WarpedPsf`
195 """
196 destBBox = self._computeDestBBox_computeDestBBox(
197 destWcs=destWcs,
198 srcImage=srcExposure.getMaskedImage(),
199 srcWcs=srcExposure.getWcs(),
200 border=border,
201 maxBBox=maxBBox,
202 destBBox=destBBox,
203 )
204 destExposure = srcExposure.Factory(destBBox, destWcs)
205 warpExposure(destExposure, srcExposure, self._warpingControl_warpingControl)
206 return destExposure
207
208 def warpImage(self, destWcs, srcImage, srcWcs, border=0, maxBBox=None, destBBox=None):
209 """Warp an image or masked image.
210
211 Parameters
212 ----------
213 destWcs : `lsst.afw.geom.SkyWcs`
214 WCS of warped image
215 srcImage
216 image or masked image to warp
217 srcWcs : `lsst.afw.geom.SkyWcs`
218 WCS of image
219 border : `int`, optional
220 grow bbox of warped image by this amount in all directions
221 (in pixels); if negative then the bbox is shrunk; border is applied
222 before ``maxBBox``; ignored if ``destBBox`` is not `None`
223 maxBBox : `lsst.geom.Box2I`, optional
224 maximum allowed parent bbox of warped image; if `None` then the
225 warped image will be just big enough to contain all warped pixels;
226 if provided then the warped image may be smaller, and so
227 missing some warped pixels; ignored if ``destBBox`` is not `None`
228 destBBox : `lsst.geom.Box2I`, optional
229 exact parent bbox of warped image; if `None` then ``border`` and
230 ``maxBBox`` are used to determine the bbox, otherwise ``border``
231 and ``maxBBox`` are ignored
232
233 Returns
234 -------
235 destImage : same type as ``srcExposure``
236 warped image or masked image
237 """
238 destBBox = self._computeDestBBox_computeDestBBox(
239 destWcs=destWcs,
240 srcImage=srcImage,
241 srcWcs=srcWcs,
242 border=border,
243 maxBBox=maxBBox,
244 destBBox=destBBox,
245 )
246 destImage = srcImage.Factory(destBBox)
247 warpImage(destImage, destWcs, srcImage,
248 srcWcs, self._warpingControl_warpingControl)
249 return destImage
250
251 def _computeDestBBox(self, destWcs, srcImage, srcWcs, border, maxBBox, destBBox):
252 """Process destBBox argument for warpImage and warpExposure.
253
254 Parameters
255 ----------
256 destWcs : `lsst.afw.geom.SkyWcs`
257 WCS of warped image
258 srcImage
259 image or masked image to warp
260 srcWcs : `lsst.afw.geom.SkyWcs`
261 WCS of image
262 border : `int`, optional
263 grow bbox of warped image by this amount in all directions
264 (in pixels); if negative then the bbox is shrunk; border is applied
265 before ``maxBBox``; ignored if ``destBBox`` is not `None`
266 maxBBox : `lsst.geom.Box2I`, optional
267 maximum allowed parent bbox of warped image; if `None` then the
268 warped image will be just big enough to contain all warped pixels;
269 if provided then the warped image may be smaller, and so
270 missing some warped pixels; ignored if ``destBBox`` is not `None`
271 destBBox : `lsst.geom.Box2I`, optional
272 exact parent bbox of warped image; if `None` then ``border`` and
273 ``maxBBox`` are used to determine the bbox, otherwise ``border``
274 and ``maxBBox`` are ignored
275 """
276 if destBBox is None: # warning: == None fails due to Box2I.__eq__
277 destBBox = computeWarpedBBox(
278 destWcs, srcImage.getBBox(afwImage.PARENT), srcWcs)
279 if border:
280 destBBox.grow(border)
281 if maxBBox is not None:
282 destBBox.clip(maxBBox)
283 return destBBox
A 2-dimensional celestial WCS that transform pixels to ICRS RA/Dec, using the LSST standard for pixel...
Definition: SkyWcs.h:117
def warpImage(self, destWcs, srcImage, srcWcs, border=0, maxBBox=None, destBBox=None)
Definition: _warper.py:208
def _computeDestBBox(self, destWcs, srcImage, srcWcs, border, maxBBox, destBBox)
Definition: _warper.py:251
def fromConfig(cls, config)
Definition: _warper.py:135
def warpExposure(self, destWcs, srcExposure, border=0, maxBBox=None, destBBox=None)
Definition: _warper.py:161
def __init__(self, warpingKernelName, interpLength=_DefaultInterpLength, cacheSize=_DefaultCacheSize, maskWarpingKernelName="", growFullMask=afwImage.Mask.getPlaneBitMask("EDGE"))
Definition: _warper.py:130
A floating-point coordinate rectangle geometry.
Definition: Box.h:413
An integer coordinate rectangle.
Definition: Box.h:55
A Psf class that maps an arbitrary Psf through a coordinate transformation.
Definition: WarpedPsf.h:52
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
def computeWarpedBBox(destWcs, srcBBox, srcWcs)
Definition: _warper.py:32