lsst.meas.algorithms  13.0-12-gfeff4b0+9
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PsfCandidate.cc
Go to the documentation of this file.
1 // -*- LSST-C++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008-2015 AURA/LSST.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <http://www.lsstcorp.org/LegalNotices/>.
23  */
24 
32 #include "lsst/afw/detection/Footprint.h"
33 #include "lsst/afw/geom/Point.h"
34 #include "lsst/afw/geom/Extent.h"
35 #include "lsst/afw/geom/Box.h"
36 #include "lsst/afw/image/ImageAlgorithm.h"
37 #include "lsst/afw/image/Image.h"
38 #include "lsst/afw/math/offsetImage.h"
40 
41 namespace afwDetection = lsst::afw::detection;
42 namespace afwGeom = lsst::afw::geom;
43 namespace afwImage = lsst::afw::image;
44 namespace afwMath = lsst::afw::math;
45 namespace measAlg = lsst::meas::algorithms;
46 
47 /************************************************************************************************************/
48 /*
49  * PsfCandidate's members
50  */
51 template <typename PixelT>
53 template <typename PixelT>
55 template <typename PixelT>
57 template <typename PixelT>
59 
60 /************************************************************************************************************/
61 namespace {
62  template<typename T> // functor used by makeImageFromMask to return inputMask
63  struct noop : public afwImage::pixelOp1<T> {
64  T operator()(T x) const { return x; }
65  };
66 
67  template<typename T> // functor used by makeImageFromMask to return (inputMask & mask)
68  struct andMask : public afwImage::pixelOp1<T> {
69  andMask(T mask) : _mask(mask) {}
70  T operator()(T x) const { return (x & _mask); }
71  private:
72  T _mask;
73  };
74 
75  template<typename T>
76  andMask<T> makeAndMask(T val) {
77  return andMask<T>(val);
78  }
79 
80  /*
81  * Return an Image initialized from a Mask (possibly modified by func)
82  */
83  template<typename LhsT, typename RhsT>
84  std::shared_ptr<afwImage::Image<LhsT>>
85  makeImageFromMask(afwImage::Mask<RhsT> const& rhs,
86  afwImage::pixelOp1<RhsT> const& func=noop<RhsT>()
87  )
88  {
89  std::shared_ptr<afwImage::Image<LhsT>> lhs =
90  std::make_shared<afwImage::Image<LhsT> >(rhs.getDimensions());
91  lhs->setXY0(rhs.getXY0());
92 
93  for (int y = 0; y != lhs->getHeight(); ++y) {
94  typename afwImage::Image<RhsT>::const_x_iterator rhsPtr = rhs.row_begin(y);
95 
96  for (typename afwImage::Image<LhsT>::x_iterator lhsPtr = lhs->row_begin(y),
97  lhsEnd = lhs->row_end(y); lhsPtr != lhsEnd; ++rhsPtr, ++lhsPtr) {
98  *lhsPtr = func(*rhsPtr);
99  }
100  }
101 
102  return lhs;
103  }
104 
106  double distanceSquared(double x, double y, afwDetection::PeakRecord const& peak) {
107  return std::pow(peak.getIx() - x, 2) + std::pow(peak.getIy() - y, 2);
108  }
109 
114  template <typename MaskT>
115  class BlendedFunctor {
116  public:
117  BlendedFunctor(
118  afwDetection::PeakRecord const& central,
119  afwDetection::PeakCatalog const& peaks,
120  afwImage::MaskPixel turnOff,
121  afwImage::MaskPixel turnOn
122  ) :
123  _central(central),
124  _peaks(peaks),
125  _turnOff(~turnOff),
126  _turnOn(turnOn)
127  {}
128 
130  void operator()(afwGeom::Point2I const & point, MaskT & val) {
131  int x = point.getX();
132  int y = point.getY();
133  double const central = distanceSquared(x, y, _central);
134  for (afwDetection::PeakCatalog::const_iterator iter = _peaks.begin(), end = _peaks.end();
135  iter != end; ++iter) {
136  double const dist2 = distanceSquared(x, y, *iter);
137  if (dist2 < central) {
138  val &= _turnOff;
139  val |= _turnOn;
140  }
141  }
142  }
143 
144 
145  private:
146  afwDetection::PeakRecord const& _central;
147  afwDetection::PeakCatalog const& _peaks;
148  afwImage::MaskPixel const _turnOff;
149  afwImage::MaskPixel const _turnOn;
150  };
151 
152 } // anonymous namespace
153 
172 template <typename PixelT>
173 PTR(afwImage::MaskedImage<PixelT>)
174 measAlg::PsfCandidate<PixelT>::extractImage(
175  unsigned int width, // Width of image
176  unsigned int height // Height of image
177 ) const {
178  afwGeom::Point2I const cen(afwImage::positionToIndex(getXCenter()),
179  afwImage::positionToIndex(getYCenter()));
180  afwGeom::Point2I const llc(cen[0] - width/2 - _parentExposure->getX0(),
181  cen[1] - height/2 - _parentExposure->getY0());
182 
183  afwGeom::BoxI bbox(llc, afwGeom::ExtentI(width, height));
184 
185  PTR(MaskedImageT) image;
186  try {
187  MaskedImageT mimg = _parentExposure->getMaskedImage();
188  image.reset(new MaskedImageT(mimg, bbox, afwImage::LOCAL, true)); // a deep copy
189  } catch(lsst::pex::exceptions::LengthError &e) {
190  LSST_EXCEPT_ADD(e, "Extracting image of PSF candidate");
191  throw e;
192  }
193 
194  //
195  // Set INTRP and unset DETECTED for any pixels we don't want to deal with.
196  //
197  afwImage::MaskPixel const intrp = MaskedImageT::Mask::getPlaneBitMask("INTRP"); // mask bit for bad pixels
198  afwImage::MaskPixel const detected = MaskedImageT::Mask::getPlaneBitMask("DETECTED"); // object pixels
199 
200  // Mask out blended objects
201  if (getMaskBlends()) {
202  CONST_PTR(afwDetection::Footprint) foot = getSource()->getFootprint();
203  typedef afwDetection::PeakCatalog PeakCatalog;
204  PeakCatalog const& peaks = foot->getPeaks();
205  if (peaks.size() > 1) {
206  // Mask all pixels in the footprint except for those closest to the central peak
207  double best = std::numeric_limits<double>::infinity();
208  PTR(afwDetection::PeakRecord) central;
209  for (PeakCatalog::const_iterator iter = peaks.begin(), end = peaks.end(); iter != end; ++iter) {
210  double const dist2 = distanceSquared(getXCenter(), getYCenter(), *iter);
211  if (dist2 < best) {
212  best = dist2;
213  central = iter;
214  }
215  }
216  assert(central); // We must have found something
217 
218  PeakCatalog others(peaks.getTable());
219  others.reserve(peaks.size() - 1);
220  for (PeakCatalog::const_iterator iter = peaks.begin(), end = peaks.end(); iter != end; ++iter) {
221  PTR(afwDetection::PeakRecord) ptr(iter);
222  if (central != ptr) {
223  others.push_back(ptr);
224  }
225  }
226 
227  BlendedFunctor<typename MaskedImageT::Mask::Pixel> functor(*central, others, detected, intrp);
228  foot->getSpans()->clippedTo(image->getBBox())->applyFunctor(functor, *image->getMask());
229  }
230  }
231 
232  /*
233  * Mask any DETECTED pixels other than the one in the center of the object;
234  * we grow the Footprint a bit first
235  */
236  typedef afwDetection::FootprintSet::FootprintList FootprintList;
237 
238  PTR(afwImage::Image<int>) mim = makeImageFromMask<int>(*image->getMask(), makeAndMask(detected));
239  PTR(afwDetection::FootprintSet) fs =
240  std::make_shared<afwDetection::FootprintSet>(*mim, afwDetection::Threshold(1));
241  CONST_PTR(FootprintList) feet = fs->getFootprints();
242 
243  if (feet->size() > 1) {
244  int const ngrow = 3; // number of pixels to grow bad Footprints
245  //
246  // Go through Footprints looking for ones that don't contain cen
247  //
248  for (FootprintList::const_iterator fiter = feet->begin(); fiter != feet->end(); ++fiter) {
249  PTR(afwDetection::Footprint) foot = *fiter;
250  if (foot->contains(cen)) {
251  continue;
252  }
253 
254  // Dilate and clip to the image bounding box, incase the span grows outside the image
255  auto bigSpan = foot->getSpans()->dilated(ngrow)->clippedTo(image->getBBox());
256  bigSpan->clearMask(*image->getMask(), detected);
257  bigSpan->setMask(*image->getMask(), intrp);
258  }
259  }
260 
261  // Mask high pixels unconnected to the center
262  if (_pixelThreshold > 0.0) {
263  CONST_PTR(afwDetection::FootprintSet) fpSet =
264  std::make_shared<afwDetection::FootprintSet>(*image,
265  afwDetection::Threshold(_pixelThreshold, afwDetection::Threshold::PIXEL_STDEV));
266  for (FootprintList::const_iterator fpIter = fpSet->getFootprints()->begin();
267  fpIter != fpSet->getFootprints()->end(); ++fpIter) {
268  CONST_PTR(afwDetection::Footprint) fp = *fpIter;
269  if (!fp->contains(cen)) {
270  fp->getSpans()->clearMask(*image->getMask(), detected);
271  fp->getSpans()->setMask(*image->getMask(), intrp);
272  }
273  }
274  }
275 
276  return image;
277 }
278 
279 
285 template <typename PixelT>
286 CONST_PTR(afwImage::MaskedImage<PixelT>)
287 measAlg::PsfCandidate<PixelT>::getMaskedImage(int width, int height) const {
288  if (!_image || (width != _image->getWidth() || height != _image->getHeight())) {
289  _image = extractImage(width, height);
290  }
291  return _image;
292 }
293 
299 template <typename PixelT>
300 CONST_PTR(afwImage::MaskedImage<PixelT>) measAlg::PsfCandidate<PixelT>::getMaskedImage() const {
301  int const width = getWidth() == 0 ? _defaultWidth : getWidth();
302  int const height = getHeight() == 0 ? _defaultWidth : getHeight();
303  return getMaskedImage(width, height);
304 }
305 
311 template <typename PixelT>
312 PTR(afwImage::MaskedImage<PixelT>)
313 measAlg::PsfCandidate<PixelT>::getOffsetImage(
314  std::string const algorithm, // Warping algorithm to use
315  unsigned int buffer // Buffer for warping
316 ) const {
317  unsigned int const width = getWidth() == 0 ? _defaultWidth : getWidth();
318  unsigned int const height = getHeight() == 0 ? _defaultWidth : getHeight();
319  if (_offsetImage && static_cast<unsigned int>(_offsetImage->getWidth()) == width + 2*buffer &&
320  static_cast<unsigned int>(_offsetImage->getHeight()) == height + 2*buffer) {
321  return _offsetImage;
322  }
323 
324  PTR(MaskedImageT) image = extractImage(width + 2*buffer, height + 2*buffer);
325 
326  double const xcen = getXCenter(), ycen = getYCenter();
327  double const dx = afwImage::positionToIndex(xcen, true).second;
328  double const dy = afwImage::positionToIndex(ycen, true).second;
329 
330  PTR(MaskedImageT) offset = afwMath::offsetImage(*image, -dx, -dy, algorithm);
331  afwGeom::Point2I llc(buffer, buffer);
332  afwGeom::Extent2I dims(width, height);
333  afwGeom::Box2I box(llc, dims);
334  _offsetImage.reset(new MaskedImageT(*offset, box, afwImage::LOCAL, true)); // Deep copy
335 
336  return _offsetImage;
337 }
338 
339 
340 /************************************************************************************************************/
341 //
342 // Explicit instantiations
343 //
345 typedef float Pixel;
346 //template class measAlg::PsfCandidate<afwImage::MaskedImage<Pixel> >;
347 template class measAlg::PsfCandidate<Pixel>;
MaskedImageT const & _image
Definition: CR.cc:967
Class used by SpatialCell for spatial PSF fittig.
ImageT val
Definition: CR.cc:158
Class stored in SpatialCells for spatial Psf fitting.
Definition: PsfCandidate.h:56
lsst::afw::image::MaskedImage< PixelT > MaskedImageT
Definition: PsfCandidate.h:63