LSSTApplications  10.0-2-g4f67435,11.0.rc2+1,11.0.rc2+12,11.0.rc2+3,11.0.rc2+4,11.0.rc2+5,11.0.rc2+6,11.0.rc2+7,11.0.rc2+8
LSSTDataManagementBasePackage
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 
34 #include "lsst/afw/geom/Point.h"
35 #include "lsst/afw/geom/Extent.h"
36 #include "lsst/afw/geom/Box.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>
85  makeImageFromMask(afwImage::Mask<RhsT> const& rhs,
86  afwImage::pixelOp1<RhsT> const& func=noop<RhsT>()
87  )
88  {
89  typename afwImage::Image<LhsT>::Ptr lhs =
90  boost::make_shared<afwImage::Image<LhsT> >(rhs.getDimensions());
91  lhs->setXY0(rhs.getXY0());
92 
93  for (int y = 0; y != lhs->getHeight(); ++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 PixelT>
115  class BlendedFunctor : public afwDetection::FootprintFunctor<afwImage::MaskedImage<PixelT> > {
116  public:
117  typedef typename afwImage::MaskedImage<PixelT> Image;
118  typedef typename Image::Mask Mask;
119  typedef typename afwDetection::FootprintFunctor<Image> Super;
120  BlendedFunctor(
121  Image const& image,
122  Mask & mask,
123  afwDetection::PeakRecord const& central,
124  afwDetection::PeakCatalog const& peaks,
125  afwImage::MaskPixel turnOff,
126  afwImage::MaskPixel turnOn
127  ) :
128  Super(image),
129  _central(central),
130  _peaks(peaks),
131  _mask(mask),
132  _turnOff(~turnOff),
133  _turnOn(turnOn)
134  {}
135 
137  virtual void operator()(typename Image::xy_locator loc, int x, int y) {
138  double const central = distanceSquared(x, y, _central);
139  int const xImage = x - getImage().getX0();
140  int const yImage = y - getImage().getY0();
141  for (afwDetection::PeakCatalog::const_iterator iter = _peaks.begin(), end = _peaks.end();
142  iter != end; ++iter) {
143  double const dist2 = distanceSquared(x, y, *iter);
144  if (dist2 < central) {
145  (_mask)(xImage, yImage) &= _turnOff;
146  (_mask)(xImage, yImage) |= _turnOn;
147  return;
148  }
149  }
150  }
151 
152  using Super::getImage;
153 
154  private:
155  afwDetection::PeakRecord const& _central;
156  afwDetection::PeakCatalog const& _peaks;
157  Mask & _mask;
158  afwImage::MaskPixel const _turnOff;
159  afwImage::MaskPixel const _turnOn;
160  };
161 
162 } // anonymous namespace
163 
182 template <typename PixelT>
184 measAlg::PsfCandidate<PixelT>::extractImage(
185  unsigned int width, // Width of image
186  unsigned int height // Height of image
187 ) const {
188  afwGeom::Point2I const cen(afwImage::positionToIndex(getXCenter()),
189  afwImage::positionToIndex(getYCenter()));
190  afwGeom::Point2I const llc(cen[0] - width/2 - _parentExposure->getX0(),
191  cen[1] - height/2 - _parentExposure->getY0());
192 
193  afwGeom::BoxI bbox(llc, afwGeom::ExtentI(width, height));
194 
196  try {
197  MaskedImageT mimg = _parentExposure->getMaskedImage();
198  image.reset(new MaskedImageT(mimg, bbox, afwImage::LOCAL, true)); // a deep copy
199  } catch(lsst::pex::exceptions::LengthError &e) {
200  LSST_EXCEPT_ADD(e, "Extracting image of PSF candidate");
201  throw e;
202  }
203 
204  //
205  // Set INTRP and unset DETECTED for any pixels we don't want to deal with.
206  //
207  afwImage::MaskPixel const intrp = MaskedImageT::Mask::getPlaneBitMask("INTRP"); // mask bit for bad pixels
208  afwImage::MaskPixel const detected = MaskedImageT::Mask::getPlaneBitMask("DETECTED"); // object pixels
209 
210  // Mask out blended objects
211  if (getMaskBlends()) {
212  CONST_PTR(afwDetection::Footprint) foot = getSource()->getFootprint();
214  PeakCatalog const& peaks = foot->getPeaks();
215  if (peaks.size() > 1) {
216  // Mask all pixels in the footprint except for those closest to the central peak
217  double best = std::numeric_limits<double>::infinity();
218  PTR(afwDetection::PeakRecord) central;
219  for (PeakCatalog::const_iterator iter = peaks.begin(), end = peaks.end(); iter != end; ++iter) {
220  double const dist2 = distanceSquared(getXCenter(), getYCenter(), *iter);
221  if (dist2 < best) {
222  best = dist2;
223  central = iter;
224  }
225  }
226  assert(central); // We must have found something
227 
228  PeakCatalog others(peaks.getTable());
229  others.reserve(peaks.size() - 1);
230  for (PeakCatalog::const_iterator iter = peaks.begin(), end = peaks.end(); iter != end; ++iter) {
232  if (central != ptr) {
233  others.push_back(ptr);
234  }
235  }
236 
237  BlendedFunctor<PixelT> functor(*image, *image->getMask(), *central, others, detected, intrp);
238  functor.apply(*foot);
239  }
240  }
241 
242  /*
243  * Mask any DETECTED pixels other than the one in the center of the object;
244  * we grow the Footprint a bit first
245  */
247 
248  PTR(afwImage::Image<int>) mim = makeImageFromMask<int>(*image->getMask(), makeAndMask(detected));
250  boost::make_shared<afwDetection::FootprintSet>(*mim, afwDetection::Threshold(1));
251  CONST_PTR(FootprintList) feet = fs->getFootprints();
252 
253  if (feet->size() > 1) {
254  int const ngrow = 3; // number of pixels to grow bad Footprints
255  //
256  // Go through Footprints looking for ones that don't contain cen
257  //
258  for (FootprintList::const_iterator fiter = feet->begin(); fiter != feet->end(); ++fiter) {
259  PTR(afwDetection::Footprint) foot = *fiter;
260  if (foot->contains(cen)) {
261  continue;
262  }
263 
265  afwDetection::clearMaskFromFootprint(image->getMask().get(), *bigfoot, detected);
266  afwDetection::setMaskFromFootprint(image->getMask().get(), *bigfoot, intrp);
267  }
268  }
269 
270  // Mask high pixels unconnected to the center
271  if (_pixelThreshold > 0.0) {
273  boost::make_shared<afwDetection::FootprintSet>(*image,
275  for (FootprintList::const_iterator fpIter = fpSet->getFootprints()->begin();
276  fpIter != fpSet->getFootprints()->end(); ++fpIter) {
277  CONST_PTR(afwDetection::Footprint) fp = *fpIter;
278  if (!fp->contains(cen)) {
279  afwDetection::clearMaskFromFootprint(image->getMask().get(), *fp, detected);
280  afwDetection::setMaskFromFootprint(image->getMask().get(), *fp, intrp);
281  }
282  }
283  }
284 
285  return image;
286 }
287 
288 
294 template <typename PixelT>
296 measAlg::PsfCandidate<PixelT>::getMaskedImage(int width, int height) const {
297 
298 
299  if (_haveImage && (width != _image->getWidth() || height != _image->getHeight())) {
300  _haveImage = false;
301  }
302 
303  if (!_haveImage) {
304  _image = extractImage(width, height);
305  _haveImage = true;
306  }
307 
308  return _image;
309 }
310 
316 template <typename PixelT>
317 CONST_PTR(afwImage::MaskedImage<PixelT>) measAlg::PsfCandidate<PixelT>::getMaskedImage() const {
318 
319  int const width = getWidth() == 0 ? _defaultWidth : getWidth();
320  int const height = getHeight() == 0 ? _defaultWidth : getHeight();
321 
322  return getMaskedImage(width, height);
323 
324 }
325 
331 template <typename PixelT>
333 measAlg::PsfCandidate<PixelT>::getOffsetImage(
334  std::string const algorithm, // Warping algorithm to use
335  unsigned int buffer // Buffer for warping
336 ) const {
337  unsigned int const width = getWidth() == 0 ? _defaultWidth : getWidth();
338  unsigned int const height = getHeight() == 0 ? _defaultWidth : getHeight();
339  if (_offsetImage && static_cast<unsigned int>(_offsetImage->getWidth()) == width + 2*buffer &&
340  static_cast<unsigned int>(_offsetImage->getHeight()) == height + 2*buffer) {
341  return _offsetImage;
342  }
343 
344  PTR(MaskedImageT) image = extractImage(width + 2*buffer, height + 2*buffer);
345 
346  double const xcen = getXCenter(), ycen = getYCenter();
347  double const dx = afwImage::positionToIndex(xcen, true).second;
348  double const dy = afwImage::positionToIndex(ycen, true).second;
349 
350  PTR(MaskedImageT) offset = afwMath::offsetImage(*image, -dx, -dy, algorithm);
351  afwGeom::Point2I llc(buffer, buffer);
352  afwGeom::Extent2I dims(width, height);
353  afwGeom::Box2I box(llc, dims);
354  _offsetImage.reset(new MaskedImageT(*offset, box, afwImage::LOCAL, true)); // Deep copy
355 
356  return _offsetImage;
357 }
358 
359 
360 /************************************************************************************************************/
361 //
362 // Explicit instantiations
363 //
365 typedef float Pixel;
366 //template class measAlg::PsfCandidate<afwImage::MaskedImage<Pixel> >;
367 template class measAlg::PsfCandidate<Pixel>;
int y
int iter
boost::uint16_t MaskPixel
A coordinate class intended to represent absolute positions.
#define PTR(...)
Definition: base.h:41
Represent a set of pixels of an arbitrary shape and size.
x_iterator row_begin(int y) const
Definition: Image.h:319
x_iterator row_end(int y) const
Return an x_iterator to the end of the y&#39;th row.
Definition: Image.h:324
int positionToIndex(double pos)
Convert image position to nearest integer index.
Definition: ImageUtils.h:69
boost::shared_ptr< FootprintList > feet
Definition: saturated.cc:81
#define CONST_PTR(...)
Definition: base.h:47
Use number of sigma given per-pixel s.d.
Definition: Threshold.h:52
std::vector< Footprint::Ptr > FootprintList
The FootprintSet&#39;s set of Footprints.
Definition: FootprintSet.h:57
A Threshold is used to pass a threshold value to detection algorithms.
Definition: Threshold.h:44
afw::table::CatalogT< PeakRecord > PeakCatalog
Definition: Peak.h:225
int getIy() const
Convenience accessors for the keys in the minimal schema.
Definition: Peak.h:210
An integer coordinate rectangle.
Definition: Box.h:53
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
boost::shared_ptr< Footprint > growFootprint(Footprint const &foot, int nGrow, bool isotropic=true)
CatalogIterator< typename Internal::const_iterator > const_iterator
Definition: Catalog.h:108
Class used by SpatialCell for spatial PSF fittig.
Represent a 2-dimensional array of bitmask pixels.
Definition: Mask.h:93
A class to manipulate images, masks, and variance as a single object.
Definition: MaskedImage.h:77
detection::FootprintSet::FootprintList FootprintList
Definition: saturated.cc:80
A set of pixels in an Image.
Definition: Footprint.h:62
Support for functors over Image&#39;s pixels.
MaskT clearMaskFromFootprint(lsst::afw::image::Mask< MaskT > *mask, Footprint const &footprint, MaskT const bitmask)
(AND ~bitmask) all the Mask&#39;s pixels that are in the Footprint; that is, set to zero in the Mask-inte...
int x
void setXY0(geom::Point2I const origin)
Definition: Image.h:362
ImageT::Ptr offsetImage(ImageT const &image, float dx, float dy, std::string const &algorithmName="lanczos5", unsigned int buffer=0)
Return an image offset by (dx, dy) using the specified algorithm.
Definition: offsetImage.cc:55
A set of Footprints, associated with a MaskedImage.
Definition: FootprintSet.h:53
MaskT setMaskFromFootprint(lsst::afw::image::Mask< MaskT > *mask, Footprint const &footprint, MaskT const bitmask)
OR bitmask into all the Mask&#39;s pixels that are in the Footprint.
geom::Point2I getXY0() const
Definition: Image.h:264
int getHeight() const
Return the number of rows in the image.
Definition: Image.h:239
Record class that represents a peak in a Footprint.
Definition: Peak.h:40
A coordinate class intended to represent offsets and dimensions.
#define LSST_EXCEPT_ADD(e, m)
Definition: Exception.h:51
A functor class to allow users to process all the pixels in a Footprint.
ImageT val
Definition: CR.cc:154
geom::Extent2I getDimensions() const
Return the image&#39;s size; useful for passing to constructors.
Definition: Image.h:298
A class to represent a 2-dimensional array of pixels.
Definition: PSF.h:43
Class stored in SpatialCells for spatial Psf fitting.
Definition: PsfCandidate.h:57
int getIx() const
Convenience accessors for the keys in the minimal schema.
Definition: Peak.h:209