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