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