LSSTApplications  10.0+286,10.0+36,10.0+46,10.0-2-g4f67435,10.1+152,10.1+37,11.0,11.0+1,11.0-1-g47edd16,11.0-1-g60db491,11.0-1-g7418c06,11.0-2-g04d2804,11.0-2-g68503cd,11.0-2-g818369d,11.0-2-gb8b8ce7
LSSTDataManagementBasePackage
coadd.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 math
23 
24 import lsst.pex.config as pexConfig
25 from lsst.pex.logging import Log
26 import lsst.afw.image as afwImage
27 import lsst.afw.math as afwMath
28 from .utilsLib import addToCoadd, setCoaddEdgeBits
29 
30 __all__ = ["Coadd"]
31 
32 class CoaddConfig(pexConfig.Config):
33  """Config for Coadd
34  """
35  badMaskPlanes = pexConfig.ListField(
36  dtype = str,
37  doc = "mask planes that, if set, the associated pixel should not be included in the coadd",
38  default = ("NO_DATA", "SAT"),
39  )
40 
41 
42 class Coadd(object):
43  """Coadd by weighted addition
44 
45  This class may be subclassed to implement other coadd techniques.
46  Typically this is done by overriding addExposure.
47  """
48  ConfigClass = CoaddConfig
49 
50  def __init__(self, bbox, wcs, badMaskPlanes, logName="coadd.utils.Coadd"):
51  """Create a coadd
52 
53  @param[in] bbox: bounding box of coadd Exposure with respect to parent (lsst.afw.geom.Box2I):
54  coadd dimensions = bbox.getDimensions(); xy0 = bbox.getMin()
55  @param[in] wcs: WCS of coadd exposure (lsst.afw.math.Wcs)
56  @param[in] badMaskPlanes: mask planes to pay attention to when rejecting masked pixels.
57  Specify as a collection of names.
58  badMaskPlanes should always include "NO_DATA".
59  @param[in] logName: name by which messages are logged
60  """
61  self._log = Log(Log.getDefaultLog(), logName)
62  self._bbox = bbox
63  self._wcs = wcs
64  self._badPixelMask = afwImage.MaskU.getPlaneBitMask(badMaskPlanes)
65  self._coadd = afwImage.ExposureF(bbox, wcs)
66  self._weightMap = afwImage.ImageF(bbox)
67  self._filterDict = dict() # dict of filter name: filter object for all filters seen so far
68 
70  self._statsControl.setNumSigmaClip(3.0)
71  self._statsControl.setNumIter(2)
72  self._statsControl.setAndMask(self._badPixelMask)
73 
74  @classmethod
75  def fromConfig(cls, bbox, wcs, config, logName="coadd.utils.Coadd"):
76  """Create a coadd
77 
78  @param[in] bbox: bounding box of coadd Exposure with respect to parent (lsst.afw.geom.Box2I):
79  coadd dimensions = bbox.getDimensions(); xy0 = bbox.getMin()
80  @param[in] wcs: WCS of coadd exposure (lsst.afw.math.Wcs)
81  @param[in] config: coadd config; an instance of CoaddConfig
82  @param[in] logName: name by which messages are logged
83  """
84  return cls(
85  bbox = bbox,
86  wcs = wcs,
87  badMaskPlanes = config.badMaskPlanes,
88  logName = logName,
89  )
90 
91  def addExposure(self, exposure, weightFactor=1.0):
92  """Add an Exposure to the coadd
93 
94  @param[in] exposure: Exposure to add to coadd; this should be:
95  - background-subtracted or background-matched to the other images being coadded
96  - psf-matched to the desired PSF model (optional)
97  - warped to match the coadd
98  - photometrically scaled to the desired flux magnitude
99  @param[in] weightFactor: extra weight factor for this exposure
100 
101  @return
102  - overlapBBox: region of overlap between exposure and coadd in parent coordinates (afwGeom.Box2I)
103  - weight: weight with which exposure was added to coadd; weight = weightFactor / clipped mean variance
104 
105  Subclasses may override to preprocess the exposure or change the way it is added to the coadd.
106  """
107  maskedImage = exposure.getMaskedImage()
108 
109  # compute the weight
110  statObj = afwMath.makeStatistics(maskedImage.getVariance(), maskedImage.getMask(),
111  afwMath.MEANCLIP, self._statsControl)
112  meanVar = statObj.getResult(afwMath.MEANCLIP)[0]
113  weight = weightFactor / float(meanVar)
114  if math.isnan(weight):
115  raise RuntimeError("Weight is NaN (weightFactor=%s; mean variance=%s)" % (weightFactor, meanVar))
116 
117  # save filter info
118  filter = exposure.getFilter()
119  self._filterDict.setdefault(filter.getName(), filter)
120 
121  self._log.log(Log.INFO, "Add exposure to coadd with weight=%0.3g" % (weight,))
122 
123  overlapBBox = addToCoadd(self._coadd.getMaskedImage(), self._weightMap,
124  maskedImage, self._badPixelMask, weight)
125 
126  return overlapBBox, weight
127 
128  def getCoadd(self):
129  """Get the coadd exposure for all exposures you have coadded so far
130 
131  If all exposures in this coadd have the same-named filter then that filter is set in the coadd.
132  Otherwise the coadd will have the default unknown filter.
133 
134  @warning: the Calib is not be set.
135  """
136  # make a deep copy so I can scale it
137  coaddMaskedImage = self._coadd.getMaskedImage()
138  scaledMaskedImage = coaddMaskedImage.Factory(coaddMaskedImage, True)
139 
140  # set the edge pixels
141  setCoaddEdgeBits(scaledMaskedImage.getMask(), self._weightMap)
142 
143  # scale non-edge pixels by weight map
144  scaledMaskedImage /= self._weightMap
145 
146  scaledExposure = afwImage.makeExposure(scaledMaskedImage, self._wcs)
147  if len(self._filterDict) == 1:
148  scaledExposure.setFilter(self._filterDict.values()[0])
149  return scaledExposure
150 
151  def getFilters(self):
152  """Return a collection of all the filters seen so far in in addExposure
153  """
154  return self._filterDict.values()
155 
156  def getBadPixelMask(self):
157  """Return the bad pixel mask
158  """
159  return self._badPixelMask
160 
161  def getBBox(self):
162  """Return the bounding box of the coadd
163  """
164  return self._bbox
165 
166  def getWcs(self):
167  """Return the wcs of the coadd
168  """
169  return self._wcs
170 
171  def getWeightMap(self):
172  """Return the weight map for all exposures you have coadded so far
173 
174  The weight map is a float Image of the same dimensions as the coadd; the value of each pixel
175  is the sum of the weights of all exposures that contributed to that pixel.
176  """
177  return self._weightMap
void setCoaddEdgeBits(lsst::afw::image::Mask< lsst::afw::image::MaskPixel > &coaddMask, lsst::afw::image::Image< WeightPixelT > const &weightMap)
set edge bits of coadd mask based on weight map
a place to record messages and descriptions of the state of processing.
Definition: Log.h:154
Pass parameters to a Statistics objectA class to pass parameters which control how the stats are calc...
Definition: Statistics.h:92
Statistics makeStatistics(afwImage::Mask< afwImage::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl)
Specialization to handle Masks.
Definition: Statistics.cc:1082
lsst::afw::geom::Box2I addToCoadd(lsst::afw::image::Image< CoaddPixelT > &coadd, lsst::afw::image::Image< WeightPixelT > &weightMap, lsst::afw::image::Image< CoaddPixelT > const &image, WeightPixelT weight)
add good pixels from an image to a coadd and associated weight map
Definition: addToCoadd.cc:126
Exposure< ImagePixelT, MaskPixelT, VariancePixelT >::Ptr makeExposure(MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > &mimage, boost::shared_ptr< Wcs const > wcs=boost::shared_ptr< Wcs const >())
Definition: Exposure.h:308