LSSTApplications  18.1.0
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 
25 /*
26  * Implementation of SpatialCell class
27  */
28 #include <algorithm>
29 
31 #include "lsst/afw/image/Utils.h"
32 
34 #include "lsst/log/Log.h"
36 
37 namespace image = lsst::afw::image;
38 
39 namespace lsst {
40 namespace afw {
41 namespace math {
42 
43 namespace {
44 struct CandidatePtrMore : public std::binary_function<std::shared_ptr<SpatialCellCandidate>,
45  std::shared_ptr<SpatialCellCandidate>, bool> {
47  return a->getCandidateRating() > b->getCandidateRating();
48  }
49 };
50 } // namespace
51 
52 int SpatialCellCandidate::_CandidateId = 0;
53 
55  switch (status) {
56  case GOOD:
57  case UNKNOWN:
58  _status = status;
59  return;
60  case BAD:
61  _status = status;
62  return;
63  }
64 
66  (boost::format("Saw unknown status %d") % status).str());
67 }
68 
69 int SpatialCellImageCandidate::_width = 0;
70 
71 int SpatialCellImageCandidate::_height = 0;
72 
74  CandidateList const &candidateList)
75  : _label(label), _bbox(bbox), _candidateList(candidateList), _ignoreBad(true) {
76  LOGL_DEBUG("afw.math.SpatialCell", "Cell %s : created with %d candidates", this->_label.c_str(),
77  this->_candidateList.size());
79 }
80 
81 void SpatialCell::sortCandidates() { sort(_candidateList.begin(), _candidateList.end(), CandidatePtrMore()); }
82 
84  CandidateList::iterator pos =
85  std::lower_bound(_candidateList.begin(), _candidateList.end(), candidate, CandidatePtrMore());
86  _candidateList.insert(pos, candidate);
87 }
88 
90  CandidateList::iterator pos = std::find(_candidateList.begin(), _candidateList.end(), candidate);
91  if (pos == _candidateList.end()) {
92  throw LSST_EXCEPT(
94  (boost::format("Unable to find candidate with ID == %d") % candidate->getId()).str());
95  }
96  _candidateList.erase(pos);
97 }
98 
99 bool SpatialCell::empty() const {
100  // Cast away const; end is only non-const as it provides access to the Candidates
101  // and we don't (yet) have SpatialCellCandidateConstIterator
102  SpatialCell *mthis = const_cast<SpatialCell *>(this);
103 
104  for (SpatialCellCandidateIterator ptr = mthis->begin(), end = mthis->end(); ptr != end; ++ptr) {
105  if (!(_ignoreBad && (*ptr)->isBad())) { // found a good candidate, or don't care
106  return false;
107  }
108  }
109 
110  return true;
111 }
112 
113 size_t SpatialCell::size() const {
114  // Cast away const; begin/end is only non-const as they provide access to the Candidates
115  // and we don't (yet) have SpatialCellCandidateConstIterator
116  SpatialCell *mthis = const_cast<SpatialCell *>(this);
117 
118  return mthis->end() - mthis->begin();
119 }
120 
122  for (SpatialCellCandidateIterator ptr = begin(), end = this->end(); ptr != end; ++ptr) {
123  if ((*ptr)->getId() == id) {
124  return *ptr;
125  }
126  }
127 
128  if (noThrow) {
130  } else {
132  (boost::format("Unable to find object with ID == %d") % id).str());
133  }
134 }
135 
136 void SpatialCell::visitCandidates(CandidateVisitor *visitor, int const nMaxPerCell,
137 
138  bool const ignoreExceptions, bool const reset) {
139  if (reset) {
140  visitor->reset();
141  }
142 
143  int i = 0;
144  for (SpatialCell::iterator candidate = begin(), candidateEnd = end(); candidate != candidateEnd;
145  ++candidate, ++i) {
146  if (nMaxPerCell > 0 && i == nMaxPerCell) { // we've processed all the candidates we want
147  return;
148  }
149 
150  try {
151  visitor->processCandidate((*candidate).get());
152  } catch (lsst::pex::exceptions::Exception &e) {
153  if (ignoreExceptions) {
154  ;
155  } else {
156  LSST_EXCEPT_ADD(e, "Visiting candidate");
157  throw e;
158  }
159  }
160  }
161 }
162 
163 void SpatialCell::visitCandidates(CandidateVisitor *visitor, int const nMaxPerCell,
164  bool const ignoreExceptions, bool const reset) const {
165 #if 1
166  //
167  // This const_cast must go!
168  //
169  SpatialCell *mthis = const_cast<SpatialCell *>(this);
170  mthis->visitCandidates(visitor, nMaxPerCell, ignoreExceptions, reset);
171 #else
172  int i = 0;
173  for (SpatialCell::const_iterator candidate = (*cell)->begin(), candidateEnd = (*cell)->end();
174  candidate != candidateEnd; ++candidate, ++i) {
175  if (i == nMaxPerCell) { // we've processed all the candidates we want
176  return;
177  }
178 
179  try {
180  visitor->processCandidate((*candidate).get());
182  if (ignoreExceptions) {
183  ;
184  } else {
185  LSST_EXCEPT_ADD(e, "Visiting candidate");
186  throw e;
187  }
188  }
189  }
190 #endif
191 }
192 
193 void SpatialCell::visitAllCandidates(CandidateVisitor *visitor, bool const ignoreExceptions,
194  bool const reset) {
195  if (reset) {
196  visitor->reset();
197  }
198 
199  int i = 0;
200  for (SpatialCell::iterator candidate = begin(false), candidateEnd = end(false); candidate != candidateEnd;
201  ++candidate, ++i) {
202  try {
203  visitor->processCandidate((*candidate).get());
205  if (ignoreExceptions) {
206  ;
207  } else {
208  LSST_EXCEPT_ADD(e, "Visiting candidate");
209  throw e;
210  }
211  }
212  }
213 }
214 
215 void SpatialCell::visitAllCandidates(CandidateVisitor *visitor, bool const ignoreExceptions,
216  bool const reset) const {
217 #if 1
218  //
219  // This const_cast must go!
220  //
221  SpatialCell *mthis = const_cast<SpatialCell *>(this);
222  mthis->visitAllCandidates(visitor, ignoreExceptions, reset);
223 #else
224  int i = 0;
225  for (SpatialCell::const_iterator candidate = (*cell)->begin(false), candidateEnd = (*cell)->end(false);
226  candidate != candidateEnd; ++candidate, ++i) {
227  try {
228  visitor->processCandidate((*candidate).get());
230  if (ignoreExceptions) {
231  ;
232  } else {
233  LSST_EXCEPT_ADD(e, "Visiting candidate");
234  throw e;
235  }
236  }
237  }
238 #endif
239 }
240 
242  CandidateList::iterator end, bool ignoreBad)
243  : _iterator(iterator), _end(end), _ignoreBad(ignoreBad) {
244  for (; _iterator != _end; ++_iterator) {
245  (*_iterator)->instantiate();
246 
247  if (!(_ignoreBad && (*_iterator)->isBad())) { // found a good candidate, or don't care
248  return;
249  }
250  }
251 }
252 
254  CandidateList::iterator end, bool ignoreBad, bool)
255  : _iterator(end), _end(end), _ignoreBad(ignoreBad) {
256  if (ignoreBad) {
257  // We could decrement end if there are bad Candidates at the end of the list, but it's probably
258  // not worth the trouble
259  }
260 }
261 
263  if (_iterator != _end) {
264  ++_iterator;
265  }
266 
267  for (; _iterator != _end; ++_iterator) {
268  (*_iterator)->instantiate();
269 
270  if (!(_ignoreBad && (*_iterator)->isBad())) { // found a good candidate, or don't care
271  return;
272  }
273  }
274 }
275 
277  size_t n = 0;
278  for (SpatialCellCandidateIterator ptr = rhs; ptr != *this; ++ptr) {
279  if (!(_ignoreBad && (*ptr)->isBad())) { // found a good candidate, or don't care
280  ++n;
281  }
282  }
283 
284  return n;
285 }
286 
288  if (_iterator == _end) {
289  throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError, "Iterator points to end");
290  }
291 
292  return *_iterator;
293 }
294 
296  if (_iterator == _end) {
297  throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError, "Iterator points to end");
298  }
299 
300  return *_iterator;
301 }
302 
304  : _region(region), _cellList(CellList()) {
305  if (ySize == 0) {
306  ySize = xSize;
307  }
308 
309  if (xSize <= 0 || ySize <= 0) {
310  throw LSST_EXCEPT(
312  (boost::format("Please specify cells that contain pixels, not %dx%d") % xSize % ySize).str());
313  }
314 
315  int nx = region.getWidth() / xSize;
316  if (nx * xSize != region.getWidth()) {
317  nx++;
318  }
319 
320  int ny = region.getHeight() / ySize;
321  if (ny * ySize != region.getHeight()) {
322  ny++;
323  }
324  //
325  // N.b. the SpatialCells will be sorted in y at the end of this
326  //
327  int y0 = region.getMinY();
328  for (int y = 0; y < ny; ++y) {
329  // ny may not be a factor of height
330  int const y1 = (y == ny - 1) ? region.getMaxY() : y0 + ySize - 1;
331  int x0 = region.getMinX();
332  for (int x = 0; x < nx; ++x) {
333  // nx may not be a factor of width
334  int const x1 = (x == nx - 1) ? region.getMaxX() : x0 + xSize - 1;
336  std::string label = (boost::format("Cell %dx%d") % x % y).str();
337 
338  _cellList.push_back(std::shared_ptr<SpatialCell>(new SpatialCell(label, bbox)));
339 
340  x0 = x1 + 1;
341  }
342  y0 = y1 + 1;
343  }
344 }
345 
346 namespace {
347 struct CellContains : public std::unary_function<std::shared_ptr<SpatialCell>, bool> {
348  CellContains(std::shared_ptr<SpatialCellCandidate> candidate) : _candidate(candidate) {}
349 
350  bool operator()(std::shared_ptr<SpatialCell> cell) {
351  return cell->getBBox().contains(
352  lsst::geom::Point2I(image::positionToIndex(_candidate->getXCenter()),
353  image::positionToIndex(_candidate->getYCenter())));
354  }
355 
356 private:
358 };
359 } // namespace
360 
362  CellList::iterator pos = std::find_if(_cellList.begin(), _cellList.end(), CellContains(candidate));
363 
364  if (pos == _cellList.end()) {
366  (boost::format("Unable to insert a candidate at (%.2f, %.2f)") %
367  candidate->getXCenter() % candidate->getYCenter())
368  .str());
369  }
370 
371  (*pos)->insertCandidate(candidate);
372 }
373 
375  for (CellList::iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) {
376  (*cell)->sortCandidates();
377  }
378 }
379 
380 void SpatialCellSet::visitCandidates(CandidateVisitor *visitor, int const nMaxPerCell,
381  bool const ignoreExceptions) {
382  visitor->reset();
383 
384  for (CellList::iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) {
385  (*cell)->visitCandidates(visitor, nMaxPerCell, ignoreExceptions, false);
386  }
387 }
388 
389 void SpatialCellSet::visitCandidates(CandidateVisitor *visitor, int const nMaxPerCell,
390  bool const ignoreExceptions) const {
391  visitor->reset();
392 
393  for (CellList::const_iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) {
394  SpatialCell const *ccell = cell->get(); // the SpatialCellSet's SpatialCells should be const too
395  ccell->visitCandidates(visitor, nMaxPerCell, ignoreExceptions, false);
396  }
397 }
398 
399 void SpatialCellSet::visitAllCandidates(CandidateVisitor *visitor, bool const ignoreExceptions) {
400  visitor->reset();
401 
402  for (CellList::iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) {
403  (*cell)->visitAllCandidates(visitor, ignoreExceptions, false);
404  }
405 }
406 
407 void SpatialCellSet::visitAllCandidates(CandidateVisitor *visitor, bool const ignoreExceptions) const {
408  visitor->reset();
409 
410  for (CellList::const_iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) {
411  SpatialCell const *ccell = cell->get(); // the SpatialCellSet's SpatialCells should be const too
412  ccell->visitAllCandidates(visitor, ignoreExceptions, false);
413  }
414 }
415 
417  for (CellList::iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) {
418  std::shared_ptr<SpatialCellCandidate> cand = (*cell)->getCandidateById(id, true);
419 
420  if (cand) {
421  return cand;
422  }
423  }
424 
425  if (noThrow) {
427  } else {
429  (boost::format("Unable to find object with ID == %d") % id).str());
430  }
431 }
432 
433 void SpatialCellSet::setIgnoreBad(bool ignoreBad) {
434  for (CellList::iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) {
435  (*cell)->setIgnoreBad(ignoreBad);
436  }
437 }
438 } // namespace math
439 } // namespace afw
440 } // namespace lsst
bool empty() const
Determine if cell has no usable candidates.
Definition: SpatialCell.cc:99
void setStatus(Status status)
Set the candidate&#39;s status.
Definition: SpatialCell.cc:54
uint64_t * ptr
Definition: RangeSet.cc:88
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:193
int getHeight() const noexcept
Definition: Box.h:175
SpatialCellCandidateIterator end()
Return an iterator to (one after) the end of the Candidates.
Definition: SpatialCell.h:277
int positionToIndex(double pos)
Convert image position to nearest integer index.
Definition: ImageUtils.h:69
table::Key< int > b
Reports attempts to exceed implementation-defined length limits for some classes. ...
Definition: Runtime.h:76
int y
Definition: SpanSet.cc:49
table::Key< int > a
void sortCandidates()
Rearrange the candidates to reflect their current ratings.
Definition: SpatialCell.cc:81
void setIgnoreBad(bool ignoreBad)
Set whether we should omit BAD candidates from candidate list when traversing.
Definition: SpatialCell.cc:433
T end(T... args)
SpatialCellCandidateIterator(CandidateList::iterator iterator, CandidateList::iterator end, bool ignoreBad)
ctor; designed to be used to pass begin to SpatialCellCandidateIterator
Definition: SpatialCell.cc:241
Provides consistent interface for LSST exceptions.
Definition: Exception.h:107
virtual void processCandidate(SpatialCellCandidate *)
Definition: SpatialCell.h:64
table::Key< int > id
Definition: Detector.cc:166
T lower_bound(T... args)
void insertCandidate(std::shared_ptr< SpatialCellCandidate > candidate)
Add a candidate to the list, preserving ranking.
Definition: SpatialCell.cc:83
#define LOGL_DEBUG(logger, message...)
Log a debug-level message using a varargs/printf style interface.
Definition: Log.h:489
STL class.
void operator++()
Advance the iterator, maybe skipping over candidates labelled BAD.
Definition: SpatialCell.cc:262
LSST DM logging module built on log4cxx.
Reports attempts to access elements using an invalid key.
Definition: Runtime.h:151
T push_back(T... args)
SpatialCell(std::string const &label, lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), CandidateList const &candidateList=CandidateList())
Constructor.
Definition: SpatialCell.cc:73
A base class for image defects.
int getMaxY() const noexcept
Definition: Box.h:149
SpatialCellSet(lsst::geom::Box2I const &region, int xSize, int ySize=0)
Constructor.
Definition: SpatialCell.cc:303
T erase(T... args)
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
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:136
int getWidth() const noexcept
Definition: Box.h:174
void removeCandidate(std::shared_ptr< SpatialCellCandidate > candidate)
Remove a candidate from the list.
Definition: SpatialCell.cc:89
std::shared_ptr< SpatialCellCandidate const > operator*() const
Dereference the iterator to return the Candidate (if there is one)
Definition: SpatialCell.cc:287
SpatialCellCandidateIterator iterator
Definition: SpatialCell.h:230
size_t operator-(SpatialCellCandidateIterator const &rhs) const
Return the number of candidate between this and rhs.
Definition: SpatialCell.cc:276
table::Box2IKey bbox
Definition: Detector.cc:169
int getMaxX() const noexcept
Definition: Box.h:148
double x
void sortCandidates()
Rearrange the Candidates in all SpatialCells to reflect their current ratings.
Definition: SpatialCell.cc:374
T insert(T... args)
int getMinX() const noexcept
Definition: Box.h:144
T find(T... args)
T size(T... args)
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
Reports attempts to access elements outside a valid range of indices.
Definition: Runtime.h:89
void insertCandidate(std::shared_ptr< SpatialCellCandidate > candidate)
Insert a candidate into the correct cell.
Definition: SpatialCell.cc:361
T begin(T... args)
Class to ensure constraints for spatial modeling.
Definition: SpatialCell.h:227
T c_str(T... args)
afw::table::Key< afw::table::Array< ImagePixelT > > image
std::shared_ptr< SpatialCellCandidate > getCandidateById(int id, bool noThrow=false)
Return the SpatialCellCandidate with the specified id.
Definition: SpatialCell.cc:121
Reports invalid arguments.
Definition: Runtime.h:66
void visitAllCandidates(CandidateVisitor *visitor, bool const ignoreExceptions=false)
Call the visitor&#39;s processCandidate method for every Candidate in the SpatialCellSet.
Definition: SpatialCell.cc:399
std::shared_ptr< SpatialCellCandidate > getCandidateById(int id, bool noThrow=false)
Return the SpatialCellCandidate with the specified id.
Definition: SpatialCell.cc:416
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects...
#define LSST_EXCEPT_ADD(e, m)
Add the current location and a message to an existing exception before rethrowing it...
Definition: Exception.h:54
An integer coordinate rectangle.
Definition: Box.h:54
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:380
SpatialCellCandidateIterator begin()
Return an iterator to the beginning of the Candidates.
Definition: SpatialCell.h:267
size_t size() const
Return number of usable candidates in Cell.
Definition: SpatialCell.cc:113
An iterator that only returns usable members of the SpatialCell.
Definition: SpatialCell.h:163
int end
int getMinY() const noexcept
Definition: Box.h:145