LSSTApplications  11.0-13-gbb96280,12.1+18,12.1+7,12.1-1-g14f38d3+72,12.1-1-g16c0db7+5,12.1-1-g5961e7a+84,12.1-1-ge22e12b+23,12.1-11-g06625e2+4,12.1-11-g0d7f63b+4,12.1-19-gd507bfc,12.1-2-g7dda0ab+38,12.1-2-gc0bc6ab+81,12.1-21-g6ffe579+2,12.1-21-gbdb6c2a+4,12.1-24-g941c398+5,12.1-3-g57f6835+7,12.1-3-gf0736f3,12.1-37-g3ddd237,12.1-4-gf46015e+5,12.1-5-g06c326c+20,12.1-5-g648ee80+3,12.1-5-gc2189d7+4,12.1-6-ga608fc0+1,12.1-7-g3349e2a+5,12.1-7-gfd75620+9,12.1-9-g577b946+5,12.1-9-gc4df26a+10
LSSTDataManagementBasePackage
warpAndPsfMatch.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008, 2009, 2010, 2011, 2012 LSST Corporation.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 import lsst.pex.config as pexConfig
23 import lsst.afw.math as afwMath
24 import lsst.afw.image as afwImage
25 import lsst.afw.geom as afwGeom
26 import lsst.pipe.base as pipeBase
27 from lsst.ip.diffim import ModelPsfMatchTask
28 from lsst.meas.algorithms import WarpedPsf
29 
30 __all__ = ["WarpAndPsfMatchTask"]
31 
32 
33 class WarpAndPsfMatchConfig(pexConfig.Config):
34  """Config for WarpAndPsfMatchTask
35  """
36  psfMatch = pexConfig.ConfigurableField(
37  target=ModelPsfMatchTask,
38  doc="PSF matching model to model task",
39  )
40  warp = pexConfig.ConfigField(
41  dtype=afwMath.Warper.ConfigClass,
42  doc="warper configuration",
43  )
44  matchThenWarp = pexConfig.Field(
45  dtype=bool,
46  doc="Reverse order of warp and match operations to replicate legacy coadd temporary exposures",
47  default=False,
48  )
49 
50 
51 class WarpAndPsfMatchTask(pipeBase.Task):
52  """A task to warp and PSF-match an exposure
53  """
54  ConfigClass = WarpAndPsfMatchConfig
55 
56  def __init__(self, *args, **kwargs):
57  pipeBase.Task.__init__(self, *args, **kwargs)
58  self.makeSubtask("psfMatch")
59  self.warper = afwMath.Warper.fromConfig(self.config.warp)
60 
61  def run(self, exposure, wcs, modelPsf=None, maxBBox=None, destBBox=None):
62  """Warp and PSF-match exposure (if modelPsf is not None)
63 
64  Parameters
65  ----------
66  exposure : :cpp:class: `lsst::afw::image::Exposure`
67  Exposure to preprocess. PSF matching is done in place.
68  wcs : :cpp:class:`lsst::afw::image::Wcs`
69  Desired WCS of temporary images.
70  modelPsf : :cpp:class: `lsst::meas::algorithms::KernelPsf` or None
71  Target PSF to which to match.
72  If None then exposures are not PSF matched.
73  maxBBox : :cpp:class:`lsst::afw::geom::Box2I` or None
74  Maximum allowed parent bbox of warped exposure.
75  If None then the warped exposure will be just big enough to contain all warped pixels;
76  if provided then the warped exposure may be smaller, and so missing some warped pixels;
77  ignored if destBBox is not None.
78  destBBox: :cpp:class: `lsst::afw::geom::Box2I` or None
79  Exact parent bbox of warped exposure.
80  If None then maxBBox is used to determine the bbox, otherwise maxBBox is ignored.
81 
82 
83  Returns
84  -------
85  An lsst.pipe.base.Struct with the following fields:
86 
87  exposure : :cpp:class:`lsst::afw::image::Exposure`
88  processed exposure
89  """
90  if self.config.matchThenWarp:
91  # Legacy order of operations:
92  # PSF-matching is performed before warping, which is incorrect.
93  # a position-dependent warping (as is used in the general case) will
94  # re-introduce a position-dependent PSF.
95  if modelPsf is not None:
96  exposure = self.psfMatch.run(exposure, modelPsf).psfMatchedExposure
97  with self.timer("warp"):
98  exposure = self.warper.warpExposure(wcs, exposure, maxBBox=maxBBox, destBBox=destBBox)
99  else:
100  if modelPsf is not None:
101  # Warp PSF before overwriting exposure
102  xyTransform = afwImage.XYTransformFromWcsPair(wcs, exposure.getWcs())
103  psfWarped = WarpedPsf(exposure.getPsf(), xyTransform)
104 
105  if maxBBox is not None:
106  # grow warped region to provide sufficient area for PSF-matching
107  pixToGrow = 2 * max(self.config.psfMatch.kernel.active.sizeCellX,
108  self.config.psfMatch.kernel.active.sizeCellY)
109  # replace with copy
110  maxBBox = afwGeom.Box2I(maxBBox)
111  maxBBox.grow(pixToGrow)
112 
113  with self.timer("warp"):
114  exposure = self.warper.warpExposure(wcs, exposure, maxBBox=maxBBox, destBBox=destBBox)
115 
116  if modelPsf is not None:
117  exposure.setPsf(psfWarped)
118  exposure = self.psfMatch.run(exposure, modelPsf).psfMatchedExposure
119 
120  return pipeBase.Struct(
121  exposure=exposure,
122  )
XYTransformFromWcsPair: An XYTransform obtained by putting two Wcs objects &quot;back to back&quot;...
Definition: Wcs.h:449
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations...
An integer coordinate rectangle.
Definition: Box.h:53
A Psf class that maps an arbitrary Psf through a coordinate transformation.
Definition: WarpedPsf.h:49