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
SpatialCell.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008, 2009, 2010 LSST Corporation.
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 <algorithm>
33 
35 #include "lsst/afw/image/Utils.h"
36 
38 #include "lsst/log/Log.h"
40 
41 namespace image = lsst::afw::image;
42 
43 namespace lsst {
44 namespace afw {
45 namespace math {
46 
47 namespace {
48  struct CandidatePtrMore : public std::binary_function<SpatialCellCandidate::Ptr,
49  SpatialCellCandidate::Ptr,
50  bool> {
52  return a->getCandidateRating() > b->getCandidateRating();
53  }
54  };
55 }
56 
59 
62  switch (status) {
63  case GOOD:
64  case UNKNOWN:
65  _status = status;
66  return;
67  case BAD:
68  _status = status;
69  return;
70  }
71 
72  throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
73  (boost::format("Saw unknown status %d") % status).str());
74 }
75 
77 
79 
80 /************************************************************************************************************/
84 SpatialCell::SpatialCell(std::string const& label,
85  geom::Box2I const& bbox,
86  CandidateList const& candidateList
87  ) :
88  _label(label),
89  _bbox(bbox),
90  _candidateList(candidateList),
91  _ignoreBad(true)
92 {
93  LOGL_DEBUG("afw.math.SpatialCell", "Cell %s : created with %d candidates",
94  this->_label.c_str(), this->_candidateList.size());
96 }
97 
98 /************************************************************************************************************/
103 {
104  sort(_candidateList.begin(), _candidateList.end(), CandidatePtrMore());
105 }
106 
107 /************************************************************************************************************/
112  CandidateList::iterator pos = std::lower_bound(_candidateList.begin(), _candidateList.end(),
113  candidate, CandidatePtrMore());
114  _candidateList.insert(pos, candidate);
115 }
116 
118 {
119  CandidateList::iterator pos = std::find(_candidateList.begin(), _candidateList.end(), candidate);
120  if (pos == _candidateList.end()) {
121  throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError,
122  (boost::format("Unable to find candidate with ID == %d") %
123  candidate->getId()).str());
124  }
125  _candidateList.erase(pos);
126 }
127 
131 bool SpatialCell::empty() const {
132  // Cast away const; end is only non-const as it provides access to the Candidates
133  // and we don't (yet) have SpatialCellCandidateConstIterator
134  SpatialCell *mthis = const_cast<SpatialCell *>(this);
135 
136  for (SpatialCellCandidateIterator ptr = mthis->begin(), end = mthis->end(); ptr != end; ++ptr) {
137  if (!(_ignoreBad && (*ptr)->isBad())) { // found a good candidate, or don't care
138  return false;
139  }
140  }
141 
142  return true;
143 }
144 
148 size_t SpatialCell::size() const {
149  // Cast away const; begin/end is only non-const as they provide access to the Candidates
150  // and we don't (yet) have SpatialCellCandidateConstIterator
151  SpatialCell *mthis = const_cast<SpatialCell *>(this);
152 
153  return mthis->end() - mthis->begin();
154 }
155 
156 /************************************************************************************************************/
163  bool noThrow
164  ) {
165  for (SpatialCellCandidateIterator ptr = begin(), end = this->end(); ptr != end; ++ptr) {
166  if ((*ptr)->getId() == id) {
167  return *ptr;
168  }
169  }
170 
171  if (noThrow) {
172  return SpatialCellCandidate::Ptr();
173  } else {
174  throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError,
175  (boost::format("Unable to find object with ID == %d") % id).str());
176  }
177 }
178 
187  int const nMaxPerCell,
188  bool const ignoreExceptions,
190  bool const reset
192  ) {
193  if (reset) {
194  visitor->reset();
195  }
196 
197  int i = 0;
198  for (SpatialCell::iterator candidate = begin(), candidateEnd = end();
199  candidate != candidateEnd; ++candidate, ++i) {
200  if (nMaxPerCell > 0 && i == nMaxPerCell) { // we've processed all the candidates we want
201  return;
202  }
203 
204  try {
205  visitor->processCandidate((*candidate).get());
207  if (ignoreExceptions) {
208  ;
209  } else {
210  LSST_EXCEPT_ADD(e, "Visiting candidate");
211  throw e;
212  }
213  }
214  }
215 }
216 
226  CandidateVisitor * visitor,
227  int const nMaxPerCell,
228  bool const ignoreExceptions,
229  bool const reset
230  ) const {
231 #if 1
232  //
233  // This const_cast must go!
234  //
235  SpatialCell *mthis = const_cast<SpatialCell *>(this);
236  mthis->visitCandidates(visitor, nMaxPerCell, ignoreExceptions, reset);
237 #else
238  int i = 0;
239  for (SpatialCell::const_iterator candidate = (*cell)->begin(), candidateEnd = (*cell)->end();
240  candidate != candidateEnd; ++candidate, ++i) {
241  if (i == nMaxPerCell) { // we've processed all the candidates we want
242  return;
243  }
244 
245  try {
246  visitor->processCandidate((*candidate).get());
247  } catch(lsst::pex::exceptions::LengthError &e) {
248  if (ignoreExceptions) {
249  ;
250  } else {
251  LSST_EXCEPT_ADD(e, "Visiting candidate");
252  throw e;
253  }
254  }
255  }
256 #endif
257 }
258 
265  bool const ignoreExceptions,
266  bool const reset
267  ) {
268  if (reset) {
269  visitor->reset();
270  }
271 
272  int i = 0;
273  for (SpatialCell::iterator candidate = begin(false), candidateEnd = end(false);
274  candidate != candidateEnd; ++candidate, ++i) {
275  try {
276  visitor->processCandidate((*candidate).get());
277  } catch(lsst::pex::exceptions::LengthError &e) {
278  if (ignoreExceptions) {
279  ;
280  } else {
281  LSST_EXCEPT_ADD(e, "Visiting candidate");
282  throw e;
283  }
284  }
285  }
286 }
287 
297  CandidateVisitor * visitor,
298  bool const ignoreExceptions,
299  bool const reset
300  ) const {
301 #if 1
302  //
303  // This const_cast must go!
304  //
305  SpatialCell *mthis = const_cast<SpatialCell *>(this);
306  mthis->visitAllCandidates(visitor, ignoreExceptions, reset);
307 #else
308  int i = 0;
309  for (SpatialCell::const_iterator candidate = (*cell)->begin(false), candidateEnd = (*cell)->end(false);
310  candidate != candidateEnd; ++candidate, ++i) {
311  try {
312  visitor->processCandidate((*candidate).get());
313  } catch(lsst::pex::exceptions::LengthError &e) {
314  if (ignoreExceptions) {
315  ;
316  } else {
317  LSST_EXCEPT_ADD(e, "Visiting candidate");
318  throw e;
319  }
320  }
321  }
322 #endif
323 }
324 
325 /************************************************************************************************************/
328  CandidateList::iterator iterator,
329  CandidateList::iterator end,
330  bool ignoreBad
331  )
332  : _iterator(iterator), _end(end), _ignoreBad(ignoreBad) {
333  for (; _iterator != _end; ++_iterator) {
334  (*_iterator)->instantiate();
335 
336  if (!(_ignoreBad && (*_iterator)->isBad())) { // found a good candidate, or don't care
337  return;
338  }
339  }
340 }
341 
344  CandidateList::iterator,
345  CandidateList::iterator end,
346  bool ignoreBad,
347  bool
348  )
349  : _iterator(end), _end(end), _ignoreBad(ignoreBad) {
350  if (ignoreBad) {
351  // We could decrement end if there are bad Candidates at the end of the list, but it's probably
352  // not worth the trouble
353  }
354 }
355 
360  if (_iterator != _end) {
361  ++_iterator;
362  }
363 
364  for (; _iterator != _end; ++_iterator) {
365  (*_iterator)->instantiate();
366 
367  if (!(_ignoreBad && (*_iterator)->isBad())) { // found a good candidate, or don't care
368  return;
369  }
370  }
371 }
372 
377  size_t n = 0;
378  for (SpatialCellCandidateIterator ptr = rhs; ptr != *this; ++ptr) {
379  if (!(_ignoreBad && (*ptr)->isBad())) { // found a good candidate, or don't care
380  ++n;
381  }
382  }
383 
384  return n;
385 }
386 
393  if (_iterator == _end) {
394  throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError, "Iterator points to end");
395  }
396 
397  return *_iterator;
398 }
399 
402  if (_iterator == _end) {
403  throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError, "Iterator points to end");
404  }
405 
406  return *_iterator;
407 }
408 
409 /************************************************************************************************************/
410 
417  int xSize,
418  int ySize
419  ) :
420  _region(region), _cellList(CellList()) {
421  if (ySize == 0) {
422  ySize = xSize;
423  }
424 
425  if (xSize <= 0 || ySize <= 0) {
426  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
427  (boost::format("Please specify cells that contain pixels, not %dx%d") %
428  xSize % ySize).str());
429  }
430 
431  int nx = region.getWidth()/xSize;
432  if (nx*xSize != region.getWidth()) {
433  nx++;
434  }
435 
436  int ny = region.getHeight()/ySize;
437  if (ny*ySize != region.getHeight()) {
438  ny++;
439  }
440  //
441  // N.b. the SpatialCells will be sorted in y at the end of this
442  //
443  int y0 = region.getMinY();
444  for (int y = 0; y < ny; ++y) {
445  // ny may not be a factor of height
446  int const y1 = (y == ny - 1) ? region.getMaxY() : y0 + ySize - 1;
447  int x0 = region.getMinX();
448  for (int x = 0; x < nx; ++x) {
449  // nx may not be a factor of width
450  int const x1 = (x == nx - 1) ? region.getMaxX() : x0 + xSize - 1;
451  geom::Box2I bbox(geom::Point2I(x0, y0), geom::Point2I(x1, y1));
452  std::string label = (boost::format("Cell %dx%d") % x % y).str();
453 
454  _cellList.push_back(SpatialCell::Ptr(new SpatialCell(label, bbox)));
455 
456  x0 = x1 + 1;
457  }
458  y0 = y1 + 1;
459  }
460 }
461 
462 /************************************************************************************************************/
463 
464 namespace {
465  struct CellContains : public std::unary_function<SpatialCell::Ptr,
466  bool> {
467  CellContains(SpatialCellCandidate::Ptr candidate) : _candidate(candidate) {}
468 
469  bool operator()(SpatialCell::Ptr cell) {
470  return cell->getBBox().contains(geom::Point2I(image::positionToIndex(_candidate->getXCenter()),
471  image::positionToIndex(_candidate->getYCenter())));
472  }
473  private:
475  };
476 }
477 
482  CellList::iterator pos = std::find_if(_cellList.begin(), _cellList.end(), CellContains(candidate));
483 
484  if (pos == _cellList.end()) {
485  throw LSST_EXCEPT(lsst::pex::exceptions::OutOfRangeError,
486  (boost::format("Unable to insert a candidate at (%.2f, %.2f)") %
487  candidate->getXCenter() % candidate->getYCenter()).str());
488  }
489 
490  (*pos)->insertCandidate(candidate);
491 }
492 
493 
494 /************************************************************************************************************/
499 {
500  for (CellList::iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) {
501  (*cell)->sortCandidates();
502  }
503 }
504 
505 /************************************************************************************************************/
514  CandidateVisitor *visitor,
515  int const nMaxPerCell,
516  bool const ignoreExceptions
517  ) {
518  visitor->reset();
519 
520  for (CellList::iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) {
521  (*cell)->visitCandidates(visitor, nMaxPerCell, ignoreExceptions, false);
522  }
523 }
524 
531  CandidateVisitor *visitor,
532  int const nMaxPerCell,
533  bool const ignoreExceptions
534  ) const {
535  visitor->reset();
536 
537  for (CellList::const_iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) {
538  SpatialCell const *ccell = cell->get(); // the SpatialCellSet's SpatialCells should be const too
539  ccell->visitCandidates(visitor, nMaxPerCell, ignoreExceptions, false);
540  }
541 }
542 
543 /************************************************************************************************************/
550  CandidateVisitor *visitor,
551  bool const ignoreExceptions
552  ) {
553  visitor->reset();
554 
555  for (CellList::iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) {
556  (*cell)->visitAllCandidates(visitor, ignoreExceptions, false);
557  }
558 }
559 
566  CandidateVisitor *visitor,
567  bool const ignoreExceptions
568  ) const {
569  visitor->reset();
570 
571  for (CellList::const_iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) {
572  SpatialCell const *ccell = cell->get(); // the SpatialCellSet's SpatialCells should be const too
573  ccell->visitAllCandidates(visitor, ignoreExceptions, false);
574  }
575 }
576 
577 /************************************************************************************************************/
585  bool noThrow
586  ) {
587  for (CellList::iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) {
588  SpatialCellCandidate::Ptr cand = (*cell)->getCandidateById(id, true);
589 
590  if (cand) {
591  return cand;
592  }
593  }
594 
595  if (noThrow) {
596  return SpatialCellCandidate::Ptr();
597  } else {
598  throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError,
599  (boost::format("Unable to find object with ID == %d") % id).str());
600  }
601 }
602 
604 void SpatialCellSet::setIgnoreBad(bool ignoreBad) {
605  for (CellList::iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) {
606  (*cell)->setIgnoreBad(ignoreBad);
607  }
608 }
609 
610 }}}
int y
void setStatus(Status status)
Set the candidate&#39;s status.
Definition: SpatialCell.cc:61
void visitAllCandidates(CandidateVisitor *visitor, bool const ignoreExceptions=false, bool const reset=true)
Call the visitor&#39;s processCandidate method for every Candidate in the SpatialCell.
Definition: SpatialCell.cc:264
void insertCandidate(boost::shared_ptr< SpatialCellCandidate > candidate)
Insert a candidate into the correct cell.
Definition: SpatialCell.cc:481
int getMinY() const
Definition: Box.h:125
bool empty() const
Determine if cell has no usable candidates.
Definition: SpatialCell.cc:131
SpatialCellCandidateIterator end()
Return an iterator to (one after) the end of the Candidates.
Definition: SpatialCell.h:251
int positionToIndex(double pos)
Convert image position to nearest integer index.
Definition: ImageUtils.h:69
SpatialCellSet(lsst::afw::geom::Box2I const &region, int xSize, int ySize=0)
Constructor.
Definition: SpatialCell.cc:416
std::shared_ptr< const SpatialCellCandidate > ConstPtr
Definition: SpatialCell.h:77
std::vector< boost::shared_ptr< SpatialCell > > CellList
Definition: SpatialCell.h:309
size_t operator-(SpatialCellCandidateIterator const &rhs) const
Return the number of candidate between this and rhs.
Definition: SpatialCell.cc:376
static int _CandidateId
Unique identifier for candidates; useful for preserving current candidate following insertion...
Definition: SpatialCell.h:123
std::shared_ptr< SpatialCellCandidate > Ptr
Definition: SpatialCell.h:76
void sortCandidates()
Rearrange the candidates to reflect their current ratings.
Definition: SpatialCell.cc:102
void setIgnoreBad(bool ignoreBad)
Set whether we should omit BAD candidates from candidate list when traversing.
Definition: SpatialCell.cc:604
A set of classes of general utility in connection with images.
SpatialCellCandidateIterator(CandidateList::iterator iterator, CandidateList::iterator end, bool ignoreBad)
ctor; designed to be used to pass begin to SpatialCellCandidateIterator
Definition: SpatialCell.cc:327
virtual void processCandidate(SpatialCellCandidate *)
Definition: SpatialCell.h:67
SpatialCellCandidate::Ptr _candidate
Definition: SpatialCell.cc:474
#define LOGL_DEBUG(logger, message...)
Log a debug-level message using a varargs/printf style interface.
Definition: Log.h:513
int const x0
Definition: saturated.cc:45
Image utility functions.
An integer coordinate rectangle.
Definition: Box.h:53
int getMinX() const
Definition: Box.h:124
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
boost::shared_ptr< SpatialCellCandidate > getCandidateById(int id, bool noThrow=false)
Return the SpatialCellCandidate with the specified id.
Definition: SpatialCell.cc:162
void operator++()
Advance the iterator, maybe skipping over candidates labelled BAD.
Definition: SpatialCell.cc:359
LSST DM logging module built on log4cxx.
boost::shared_ptr< SpatialCellCandidate > getCandidateById(int id, bool noThrow=false)
Return the SpatialCellCandidate with the specified id.
Definition: SpatialCell.cc:584
metadata import lsst afw display as afwDisplay n
int getMaxX() const
Definition: Box.h:128
std::vector< boost::shared_ptr< SpatialCellCandidate > > CandidateList
Definition: SpatialCell.h:220
int getWidth() const
Definition: Box.h:154
void removeCandidate(boost::shared_ptr< SpatialCellCandidate > candidate)
Remove a candidate from the list.
Definition: SpatialCell.cc:117
SpatialCell(std::string const &label, lsst::afw::geom::Box2I const &bbox=lsst::afw::geom::Box2I(), CandidateList const &candidateList=CandidateList())
Constructor.
Definition: SpatialCell.cc:84
geom::Box2I const & _bbox
Definition: fits_io_mpl.h:80
boost::shared_ptr< SpatialCellCandidate const > operator*() const
Dereference the iterator to return the Candidate (if there is one)
Definition: SpatialCell.cc:392
void visitCandidates(CandidateVisitor *visitor, int const nMaxPerCell=-1, bool const ignoreExceptions=false, bool const reset=true)
Call the visitor&#39;s processCandidate method for each Candidate in the SpatialCell. ...
Definition: SpatialCell.cc:186
double x
size_t size() const
Return number of usable candidates in Cell.
Definition: SpatialCell.cc:148
void sortCandidates()
Rearrange the Candidates in all SpatialCells to reflect their current ratings.
Definition: SpatialCell.cc:498
#define LSST_EXCEPT(type,...)
Create an exception with a given type and message and optionally other arguments (dependent on the ty...
Definition: Exception.h:46
std::shared_ptr< SpatialCell > Ptr
Definition: SpatialCell.h:218
int status
int getHeight() const
Definition: Box.h:155
Class to ensure constraints for spatial modeling.
Definition: SpatialCell.h:216
int id
Definition: CR.cc:156
Class to ensure constraints for spatial modeling.
afw::table::Key< double > b
void visitAllCandidates(CandidateVisitor *visitor, bool const ignoreExceptions=false)
Call the visitor&#39;s processCandidate method for every Candidate in the SpatialCellSet.
Definition: SpatialCell.cc:549
int getMaxY() const
Definition: Box.h:129
int const y0
Definition: saturated.cc:45
#define LSST_EXCEPT_ADD(e, m)
Add the current location and a message to an existing exception before rethrowing it...
Definition: Exception.h:51
void visitCandidates(CandidateVisitor *visitor, int const nMaxPerCell=-1, bool const ignoreExceptions=false)
Call the visitor&#39;s processCandidate method for each Candidate in the SpatialCellSet.
Definition: SpatialCell.cc:513
void insertCandidate(boost::shared_ptr< SpatialCellCandidate > candidate)
Add a candidate to the list, preserving ranking.
Definition: SpatialCell.cc:111
SpatialCellCandidateIterator begin()
Return an iterator to the beginning of the Candidates.
Definition: SpatialCell.h:241
An iterator that only returns usable members of the SpatialCell.
Definition: SpatialCell.h:173