LSST Applications g070148d5b3+33e5256705,g0d53e28543+25c8b88941,g0da5cf3356+2dd1178308,g1081da9e2a+62d12e78cb,g17e5ecfddb+7e422d6136,g1c76d35bf8+ede3a706f7,g295839609d+225697d880,g2e2c1a68ba+cc1f6f037e,g2ffcdf413f+853cd4dcde,g38293774b4+62d12e78cb,g3b44f30a73+d953f1ac34,g48ccf36440+885b902d19,g4b2f1765b6+7dedbde6d2,g5320a0a9f6+0c5d6105b6,g56b687f8c9+ede3a706f7,g5c4744a4d9+ef6ac23297,g5ffd174ac0+0c5d6105b6,g6075d09f38+66af417445,g667d525e37+2ced63db88,g670421136f+2ced63db88,g71f27ac40c+2ced63db88,g774830318a+463cbe8d1f,g7876bc68e5+1d137996f1,g7985c39107+62d12e78cb,g7fdac2220c+0fd8241c05,g96f01af41f+368e6903a7,g9ca82378b8+2ced63db88,g9d27549199+ef6ac23297,gabe93b2c52+e3573e3735,gb065e2a02a+3dfbe639da,gbc3249ced9+0c5d6105b6,gbec6a3398f+0c5d6105b6,gc9534b9d65+35b9f25267,gd01420fc67+0c5d6105b6,geee7ff78d7+a14128c129,gf63283c776+ede3a706f7,gfed783d017+0c5d6105b6,w.2022.47
LSST Data Management Base Package
Loading...
Searching...
No Matches
_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(
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 """
155
157 """Get the mask warping kernel.
158 """
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(
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)
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(
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)
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 _computeDestBBox(self, destWcs, srcImage, srcWcs, border, maxBBox, destBBox)
Definition: _warper.py:251
def fromConfig(cls, config)
Definition: _warper.py:135
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
def computeWarpedBBox(destWcs, srcBBox, srcWcs)
Definition: _warper.py:32