lsst.jointcal  master-gc5b79683b0+1
FastFinder.cc
Go to the documentation of this file.
1 #include <algorithm>
2 
3 #include "lsst/log/Log.h"
6 
7 namespace {
8 LOG_LOGGER _log = LOG_GET("jointcal.FastFinder");
9 }
10 
11 namespace lsst {
12 namespace jointcal {
13 
14 FastFinder::FastFinder(const BaseStarList &list, const unsigned nXSlice)
15  : baselist(list), count(list.size()), stars(count), nslice(nXSlice), index(nslice + 1) {
16  if (count == 0) return;
17 
18  // fill "stars"
19  unsigned j = 0;
20  for (auto const &ci : list) {
21  stars[j] = ci;
22  ++j;
23  }
24 
25  sort(stars.begin(), stars.end(),
26  [](const stars_element &E1, const stars_element &E2) { return (E1->x < E2->x); });
27 
28  xmin = stars[0]->x;
29  xmax = stars[count - 1]->x;
30  nslice = std::min(nslice, count);
31  if (xmin == xmax) nslice = 1;
32 
33  // the x size of each slice:
34  xstep = (xmax - xmin) / nslice;
35 
36  // fill the index array with the first star beyond the slice limit.
37  index[0] = 0; // first
38  unsigned istar = 0;
39  for (unsigned islice = 1; islice < nslice; ++islice) {
40  double xend = xmin + (islice)*xstep;
41  while (istar < count && stars[istar]->x < xend) ++istar;
42  index[islice] = istar;
43  }
44  index[nslice] = count; // last
45  for (unsigned islice = 0; islice < nslice; ++islice) {
46  sort(stars.begin() + index[islice], stars.begin() + index[islice + 1],
47  [](const stars_element &E1, const stars_element &E2) {
48  return (E1->y < E2->y);
49  }); // sort each slice in y.
50  }
51  // dump();
52 }
53 
54 void FastFinder::dump() const {
55  for (unsigned i = 0; i < count; ++i) {
56  stars[i]->dump();
57  }
58 }
59 
60 std::shared_ptr<const BaseStar> FastFinder::findClosest(const Point &where, const double maxDist,
61  bool (*SkipIt)(const BaseStar &)) const {
62  if (count == 0) return nullptr;
63  FastFinder::Iterator it = beginScan(where, maxDist);
64  if (*it == nullptr) return nullptr;
65  std::shared_ptr<const BaseStar> pbest;
66  double minDist2 = maxDist * maxDist;
67  for (; *it != nullptr; ++it) {
68  if (SkipIt && SkipIt(**it)) continue;
69  double dist2 = where.computeDist2(**it);
70  if (dist2 < minDist2) {
71  pbest = *it;
72  minDist2 = dist2;
73  }
74  }
75  return pbest;
76 }
77 
78 std::shared_ptr<const BaseStar> FastFinder::secondClosest(const Point &where, const double maxDist,
79  std::shared_ptr<const BaseStar> &closest,
80  bool (*SkipIt)(const BaseStar &)) const {
81  closest = nullptr;
82  if (count == 0) return nullptr;
83  FastFinder::Iterator it = beginScan(where, maxDist);
84  if (*it == nullptr) return nullptr;
85  std::shared_ptr<const BaseStar> pbest1; // closest
86  std::shared_ptr<const BaseStar> pbest2; // second closest
87  double minDist1_2 = maxDist * maxDist;
88  double minDist2_2 = maxDist * maxDist;
89  for (; *it != nullptr; ++it) {
90  if (SkipIt && SkipIt(**it)) continue;
91  double dist2 = where.computeDist2(**it);
92  if (dist2 < minDist1_2) {
93  pbest2 = pbest1;
94  minDist2_2 = minDist1_2;
95  pbest1 = *it;
96  minDist1_2 = dist2;
97  } else if (dist2 < minDist2_2) {
98  pbest2 = *it;
99  minDist2_2 = dist2;
100  }
101  }
102  closest = pbest1;
103  return pbest2;
104 }
105 
106 /* It is by no means clear the the 2 following routines are actually needed.
107  It is nor clear to me (P.A) why they are different... but they really are.
108 */
109 /* Locate the last position (in the sorted array) between begin and
110  end that lies before yVal.*/
111 FastFinder::pstar FastFinder::locateYStart(pstar begin, pstar end, double yVal) const {
112  if (begin == stars.end() || begin == end) return stars.end();
113  int span = end - begin - 1;
114  while (span > 1) {
115  int half_span = span / 2;
116  pstar middle = begin + half_span;
117  if ((*middle)->y < yVal) {
118  begin += half_span;
119  span -= half_span;
120  } else {
121  span -= (span - half_span);
122  }
123  }
124  return begin;
125 }
126 
127 /* Locate the first position (in the sorted array) between begin and
128  end that lies beyond yVal.*/
129 FastFinder::pstar FastFinder::locateYEnd(pstar begin, pstar end, double yVal) const {
130  if (begin == stars.end()) return stars.end();
131  int span = end - begin - 1;
132  while (span > 1) {
133  int half_span = span / 2;
134  pstar middle = end - half_span;
135  if ((*middle)->y > yVal) {
136  end -= half_span;
137  span -= half_span;
138  } else {
139  span -= (span - half_span);
140  }
141  }
142  return end - 1;
143 }
144 
145 void FastFinder::findRangeInSlice(const int iSlice, const double yStart, const double yEnd, pstar &start,
146  pstar &end) const {
147  start = locateYStart(stars.begin() + index[iSlice], stars.begin() + index[iSlice + 1], yStart);
148  end = locateYEnd(start, stars.begin() + index[iSlice + 1], yEnd);
149 }
150 
151 FastFinder::Iterator FastFinder::beginScan(const Point &where, double maxDist) const {
152  return FastFinder::Iterator(*this, where, maxDist);
153 }
154 
156 
157 Iterator::Iterator(const FastFinder &F, const Point &where, double maxDist)
158  : finder(F), null_value(F.stars.end()) {
159  current = pend = null_value; // does not iterate
160  int startSlice = 0;
161  if (finder.xstep != 0) // means we have several slices
162  {
163  startSlice = std::max(0, int((where.x - maxDist - finder.xmin) / finder.xstep));
164  /* obviously, endSlice (and starSlice) can be negative.
165  This is why slice indices are "int" rather than "unsigned". */
166  endSlice = std::min(int(finder.nslice), int((where.x + maxDist - finder.xmin) / finder.xstep) + 1);
167  } else {
168  startSlice = 0;
169  endSlice = 1;
170  }
171  // beyond limits:
172  if (startSlice >= int(finder.nslice) || endSlice < 0) return;
173  // we are inside in x, so, we setup the y range:
174  yStart = where.y - maxDist;
175  yEnd = where.y + maxDist;
176  /* rather than initializing here, we step back one
177  slice and let "++" do its job */
178  currentSlice = startSlice - 1; // again, this requires "int" slices
179  ++(*this);
180 }
181 
183  if (current != null_value) return *current;
184  return nullptr;
185 }
186 
188  if (current != pend) {
189  current++;
190  } else
191  do {
192  currentSlice++;
193  if (currentSlice >= endSlice) {
195  return;
196  }
198  } while (current == null_value);
199  check();
200 }
201 
203  if (current != null_value &&
204  (current < finder.stars.begin() || current >= finder.stars.begin() + finder.count)) {
205  LOGLS_ERROR(_log, "Error in FastFinder " << *current << " " << *(finder.stars.begin()) << ' '
206  << *(finder.stars.begin() + finder.count));
207  }
208 }
209 } // namespace jointcal
210 } // namespace lsst
A point in a plane.
Definition: Point.h:13
decltype(stars) typedef ::const_iterator pstar
Definition: FastFinder.h:48
std::vector< std::shared_ptr< const BaseStar > > stars
Definition: FastFinder.h:42
Iterator(const FastFinder &f, const Point &where, double maxDist)
Definition: FastFinder.cc:157
void dump() const
mostly for debugging
Definition: FastFinder.cc:54
pstar locateYEnd(pstar begin, pstar end, double yVal) const
Definition: FastFinder.cc:129
double x
coordinate
Definition: Point.h:18
The base class for handling stars. Used by all matching routines.
Definition: BaseStar.h:22
std::shared_ptr< const BaseStar > findClosest(const Point &where, const double maxDist, bool(*SkipIt)(const BaseStar &)=nullptr) const
Find the closest with some rejection capability.
Definition: FastFinder.cc:60
FastFinder::Iterator Iterator
Definition: FastFinder.cc:155
std::lists of Stars.
Definition: StarList.h:35
Class for a simple mapping implementing a generic Gtransfo.
Definition: Associations.h:24
Iterator beginScan(const Point &where, double maxDist) const
Definition: FastFinder.cc:151
Iterator meant to traverse objects within some limiting distance.
Definition: FastFinder.h:69
FastFinder(const BaseStarList &list, const unsigned nXSlice=100)
Constructor.
Definition: FastFinder.cc:14
pstar locateYStart(pstar begin, pstar end, double yVal) const
Definition: FastFinder.cc:111
void findRangeInSlice(const int iSlice, const double yStart, const double yEnd, pstar &start, pstar &end) const
Definition: FastFinder.cc:145
This is an auxillary class for matching objects from starlists.
Definition: FastFinder.h:31
std::vector< unsigned > index
Definition: FastFinder.h:44
decltype(stars) typedef ::value_type stars_element
Definition: FastFinder.h:47
double x
std::shared_ptr< const BaseStar > secondClosest(const Point &where, const double maxDist, std::shared_ptr< const BaseStar > &closest, bool(*SkipIt)(const BaseStar &)=nullptr) const
Definition: FastFinder.cc:78
double computeDist2(const Point &other) const
distance squared to other
Definition: Point.h:32
stars_element operator*() const
Definition: FastFinder.cc:182
Fast locator in starlists.