lsst.ip.diffim  18.0.0-3-g6f60df3+3
KernelCandidateDetection.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
12 #include "lsst/afw/geom.h"
13 #include "lsst/afw/image.h"
14 #include "lsst/afw/detection.h"
15 #include "lsst/log/Log.h"
17 #include "lsst/pex/policy/Policy.h"
18 
21 
22 namespace afwGeom = lsst::afw::geom;
23 namespace afwImage = lsst::afw::image;
26 
27 namespace lsst {
28 namespace ip {
29 namespace diffim {
30 
31 
32  template <typename PixelT>
34  lsst::pex::policy::Policy const& policy
35  ) :
36  _policy(policy),
37  _badBitMask(0),
38  _footprints(std::vector<std::shared_ptr<lsst::afw::detection::Footprint>>()) {
39 
40  std::vector<std::string> detBadMaskPlanes = _policy.getStringArray("badMaskPlanes");
41  for (std::vector<std::string>::iterator mi = detBadMaskPlanes.begin();
42  mi != detBadMaskPlanes.end(); ++mi){
43  try {
45  } catch (pexExcept::Exception& e) {
46  LOGL_DEBUG("TRACE3.ip.diffim.KernelCandidateDetection",
47  "Cannot update bad bit mask with %s", (*mi).c_str());
48  LOGL_DEBUG("TRACE4.ip.diffim.KernelCandidateDetection",
49  e.what());
50  }
51  }
52  LOGL_DEBUG("TRACE2.ip.diffim.KernelCandidateDetection",
53  "Using bad bit mask %d", _badBitMask);
54  }
55 
56 
57 
76  template <typename PixelT>
78  MaskedImagePtr const& templateMaskedImage,
79  MaskedImagePtr const& scienceMaskedImage
80  ) {
81 
82  // Parse the Policy
83  int fpNpixMin = _policy.getInt("fpNpixMin");
84  int fpGrowPix = _policy.getInt("fpGrowPix");
85 
86  bool detOnTemplate = _policy.getBool("detOnTemplate");
87  double detThreshold = _policy.getDouble("detThreshold");
88  std::string detThresholdType = _policy.getString("detThresholdType");
89 
90  /* reset private variables */
91  _footprints.clear();
92 
93  // List of Footprints
95 
96  // Find detections
97  afwDetect::Threshold threshold =
98  afwDetect::createThreshold(detThreshold, detThresholdType);
99 
100  if (detOnTemplate == true) {
101  afwDetect::FootprintSet footprintSet(
102  *(templateMaskedImage),
103  threshold,
104  "",
105  fpNpixMin);
106  // Get the associated footprints
107 
108  footprintListInPtr = footprintSet.getFootprints();
109  LOGL_DEBUG("TRACE2.ip.diffim.KernelCandidateDetection.apply",
110  "Found %d total footprints in template above %.3f %s",
111  footprintListInPtr->size(), detThreshold, detThresholdType.c_str());
112  }
113  else {
114  afwDetect::FootprintSet footprintSet(
115  *(scienceMaskedImage),
116  threshold,
117  "",
118  fpNpixMin);
119 
120  footprintListInPtr = footprintSet.getFootprints();
121  LOGL_DEBUG("TRACE2.ip.diffim.KernelCandidateDetection.apply",
122  "Found %d total footprints in science image above %.3f %s",
123  footprintListInPtr->size(), detThreshold, detThresholdType.c_str());
124  }
125 
126  // Iterate over footprints, look for "good" ones
127  for (std::vector<std::shared_ptr<afwDetect::Footprint>>::iterator i = footprintListInPtr->begin();
128  i != footprintListInPtr->end(); ++i) {
129 
130  growCandidate((*i), fpGrowPix, templateMaskedImage, scienceMaskedImage);
131  }
132 
133  if (_footprints.size() == 0) {
135  "Unable to find any footprints for Psf matching");
136  }
137 
138  LOGL_DEBUG("TRACE1.ip.diffim.KernelCandidateDetection.apply",
139  "Found %d clean footprints above threshold %.3f",
140  _footprints.size(), detThreshold);
141 
142  }
143 
144  template <typename PixelT>
147  int fpGrowPix,
148  MaskedImagePtr const& templateMaskedImage,
149  MaskedImagePtr const& scienceMaskedImage
150  ) {
151  int fpNpixMax = _policy.getInt("fpNpixMax");
152 
153  /* Functor to search through the images for masked pixels within *
154  * candidate footprints. Might want to consider changing the default
155  * mask planes it looks through.
156  */
158 
159  afwGeom::Box2I fpBBox = fp->getBBox();
160  /* Failure Condition 1)
161  *
162  * Footprint has too many pixels off the bat. We don't want to throw
163  * away these guys, they have alot of signal! Lets just use the core of
164  * it.
165  *
166  */
167  if (fp->getArea() > static_cast<std::size_t>(fpNpixMax)) {
168  LOGL_DEBUG("TRACE3.ip.diffim.KernelCandidateDetection.apply",
169  "Footprint has too many pix: %d (max =%d)",
170  fp->getArea(), fpNpixMax);
171 
172  int xc = int(0.5 * (fpBBox.getMinX() + fpBBox.getMaxX()));
173  int yc = int(0.5 * (fpBBox.getMinY() + fpBBox.getMaxY()));
176  std::make_shared<afwGeom::SpanSet>(afwGeom::Box2I(afwGeom::Point2I(xc, yc),
177  afwGeom::Extent2I(1,1))))
178  );
179  return growCandidate(fpCore, fpGrowPix, templateMaskedImage, scienceMaskedImage);
180  }
181 
182  LOGL_DEBUG("TRACE5.ip.diffim.KernelCandidateDetection.apply",
183  "Original footprint in parent : %d,%d -> %d,%d -> %d,%d",
184  fpBBox.getMinX(), fpBBox.getMinY(),
185  int(0.5 * (fpBBox.getMinX() + fpBBox.getMaxX())),
186  int(0.5 * (fpBBox.getMinY() + fpBBox.getMaxY())),
187  fpBBox.getMaxX(), fpBBox.getMaxY());
188 
189  /* Grow the footprint
190  * flag true = isotropic grow = slow
191  * flag false = 'manhattan grow' = fast
192  *
193  * The manhattan masks are rotated 45 degree w.r.t. the coordinate
194  * system. They intersect the vertices of the rectangle that would
195  * connect pixels (X0,Y0) (X1,Y0), (X0,Y1), (X1,Y1).
196  *
197  * The isotropic masks do take considerably longer to grow and are
198  * basically elliptical. X0, X1, Y0, Y1 delimit the extent of the
199  * ellipse.
200  *
201  * In both cases, since the masks aren't rectangles oriented with
202  * the image coordinate system, when we DO extract such rectangles
203  * as subimages for kernel fitting, some corner pixels can be found
204  * in multiple subimages.
205  *
206  */
207  std::shared_ptr<afwDetect::Footprint> fpGrow = std::make_shared<afwDetect::Footprint>(
208  fp->getSpans()->dilated(fpGrowPix, afwGeom::Stencil::MANHATTAN)
209  );
210 
211  /* Next we look at the image within this Footprint.
212  */
213  afwGeom::Box2I fpGrowBBox = fpGrow->getBBox();
214  LOGL_DEBUG("TRACE5.ip.diffim.KernelCandidateDetection.apply",
215  "Grown footprint in parent : %d,%d -> %d,%d -> %d,%d",
216  fpGrowBBox.getMinX(), fpGrowBBox.getMinY(),
217  int(0.5 * (fpGrowBBox.getMinX() + fpGrowBBox.getMaxX())),
218  int(0.5 * (fpGrowBBox.getMinY() + fpGrowBBox.getMaxY())),
219  fpGrowBBox.getMaxX(), fpGrowBBox.getMaxY());
220 
221  /* Failure Condition 2)
222  * Grown off the image
223  */
224  if (!(templateMaskedImage->getBBox().contains(fpGrowBBox))) {
225  LOGL_DEBUG("TRACE3.ip.diffim.KernelCandidateDetection.apply",
226  "Footprint grown off image");
227  return false;
228  }
229 
230  /* Grab subimages; report any exception */
231  bool subimageHasFailed = false;
232  try {
233  afwImage::MaskedImage<PixelT> templateSubimage(*templateMaskedImage, fpGrowBBox);
234  afwImage::MaskedImage<PixelT> scienceSubimage(*scienceMaskedImage, fpGrowBBox);
235 
236  // Search for any masked pixels within the footprint
237  fsb.apply(*(templateSubimage.getMask()));
238  if (fsb.getBits() & _badBitMask) {
239  LOGL_DEBUG("TRACE3.ip.diffim.KernelCandidateDetection.apply",
240  "Footprint has masked pix (vals=%d) in image to convolve",
241  fsb.getBits());
242  subimageHasFailed = true;
243  }
244 
245  fsb.apply(*(scienceSubimage.getMask()));
246  if (fsb.getBits() & _badBitMask) {
247  LOGL_DEBUG("TRACE3.ip.diffim.KernelCandidateDetection.apply",
248  "Footprint has masked pix (vals=%d) in image not to convolve",
249  fsb.getBits());
250  subimageHasFailed = true;
251  }
252 
253  } catch (pexExcept::Exception& e) {
254  LOGL_DEBUG("TRACE3.ip.diffim.KernelCandidateDetection.apply",
255  "Exception caught extracting Footprint");
256  LOGL_DEBUG("TRACE4.ip.diffim.KernelCandidateDetection.apply",
257  e.what());
258  subimageHasFailed = true;
259  }
260  if (subimageHasFailed) {
261  return false;
262  } else {
263  /* We have a good candidate */
264  _footprints.push_back(fpGrow);
265  return true;
266  }
267  }
268 
269 /***********************************************************************************************************/
270 //
271 // Explicit instantiations
272 //
273  typedef float PixelT;
274  template class KernelCandidateDetection<PixelT>;
275 
276 }}} // end of namespace lsst::ip::diffim
Image Subtraction helper functions.
virtual char const * what(void) const noexcept
void apply(MaskT const &mask)
Definition: FindSetBits.h:68
STL namespace.
void apply(MaskedImagePtr const &templateMaskedImage, MaskedImagePtr const &scienceMaskedImage)
Runs Detection on a single image for significant peaks, and checks returned Footprints for Masked pix...
T end(T... args)
Detect candidates for kernels within 2 images.
KernelCandidateDetection(lsst::pex::policy::Policy const &policy)
#define LOGL_DEBUG(logger, message...)
Class to accumulate Mask bits.
Definition: FindSetBits.h:53
STL class.
StringArray getStringArray(const std::string &name) const
bool getBool(const std::string &name) const
T push_back(T... args)
Search through images for Footprints with no masked pixels.
int getInt(const std::string &name) const
static MaskPixelT getPlaneBitMask(const std::vector< std::string > &names)
T clear(T... args)
const std::string getString(const std::string &name) const
double getDouble(const std::string &name) const
T size(T... args)
#define LSST_EXCEPT(type,...)
T begin(T... args)
T c_str(T... args)
bool growCandidate(std::shared_ptr< lsst::afw::detection::Footprint > fp, int fpGrowPix, MaskedImagePtr const &templateMaskedImage, MaskedImagePtr const &scienceMaskedImage)
std::shared_ptr< FootprintList > getFootprints()
MaskT::Pixel getBits() const
Definition: FindSetBits.h:65