49 #ifndef LSST_AP_MATCH_H
50 #define LSST_AP_MATCH_H
52 #if LSST_AP_HAVE_OPEN_MP
65 namespace lsst {
namespace ap {
83 _distance(2.0*std::asin(0.5*std::sqrt(d2)))
110 template <
typename F,
typename M>
121 template <
typename F,
typename S>
147 typename FirstEntryT,
148 typename SecondEntryT,
149 typename FirstFilterT,
150 typename SecondFilterT,
151 typename MatchListProcessorT
157 FirstFilterT & firstFilter,
158 SecondFilterT & secondFilter,
159 MatchListProcessorT & matchListProcessor
163 typedef typename MatchListProcessorT::Match Match;
166 throw LSST_EXCEPT(lsst::pex::exceptions::RangeError,
167 "match radius must be greater than or equal to zero degrees");
170 double const shr = std::sin(
radians(radius*0.5));
171 double const d2Limit = 4.0*shr*shr;
176 std::size_t numMatchPairs = 0;
181 #if LSST_AP_HAVE_OPEN_MP
182 # pragma omp parallel default(shared)
186 SecondZone * zones[2048];
188 std::vector<Match> matches;
193 #if LSST_AP_HAVE_OPEN_MP
195 reduction(+:numMatchPairs) \
198 for (
int fzi = minZone; fzi <= maxZone; ++fzi) {
200 FirstZone *
const __restrict fz = first.
getZone(fzi);
201 FirstEntryT *
const __restrict fze = fz->_entries;
202 int const nfze = fz->_size;
215 assert(maxz - minz + 1 <= 2048 &&
"match radius too large");
217 SecondZone * __restrict sz = second.
firstZone(minz, maxz);
218 SecondZone *
const __restrict szend = second.
endZone(minz, maxz);
220 for ( ; sz < szend; ++sz) {
221 int const nsze = sz->_size;
224 if ((nsze >> 4) > nfze) {
229 limits[nsz] = sz->findGte(fze[0]._ra - sz->_deltaRa);
242 for (
int fe = 0; fe < nfze; ++fe) {
244 if (!firstFilter(fze[fe])) {
250 boost::uint32_t
const ra = fze[fe]._ra;
251 boost::int32_t
const dec = fze[fe]._dec;
252 double const fx = fze[fe]._x;
253 double const fy = fze[fe]._y;
254 double const fz = fze[fe]._z;
257 for (
int szi = 0; szi < nsz; ++szi) {
259 SecondZone *
const __restrict sz = zones[szi];
260 SecondEntryT *
const __restrict sze = sz->_entries;
262 int const seWrap = sz->_size;
263 boost::uint32_t
const deltaRa = sz->_deltaRa;
264 boost::uint32_t
const deltaRaWrap = -deltaRa;
266 int start = limits[szi];
275 dra = ra - sze[se]._ra;
276 if (dra > deltaRa && dra < deltaRaWrap) {
288 dra = ra - sze[se]._ra;
289 }
while (dra > deltaRa && dra < deltaRaWrap);
302 start = sz->findGte(ra - deltaRa);
304 dra = ra - sze[se]._ra;
305 if (dra > deltaRa && dra < deltaRaWrap) {
316 if (abs(dec - sze[se]._dec) <= deltaDec) {
318 double xd = (fx - sze[se]._x);
319 double yd = (fy - sze[se]._y);
320 double zd = (fz - sze[se]._z);
321 double d2 = xd*xd + yd*yd + zd*zd;
324 if (secondFilter(sze[se])) {
326 matches.push_back(Match(&sze[se], d2));
337 dra = ra - sze[se]._ra;
339 }
while (dra <= deltaRa || dra >= deltaRaWrap);
344 std::size_t nm = matches.size();
347 numMatchPairs = numMatchPairs + nm;
348 matchListProcessor(fze[fe], matches.begin(), matches.end());
356 return numMatchPairs;
380 typename FirstEntryT,
381 typename SecondEntryT,
382 typename FirstFilterT,
383 typename SecondFilterT,
384 typename MatchPairProcessorT
389 FirstFilterT & firstFilter,
390 SecondFilterT & secondFilter,
391 MatchPairProcessorT & matchPairProcessor
397 std::size_t numMatchPairs = 0;
407 while (searchHead < end && searchHead->_minZone <= minZone) {
408 if (searchHead->
_maxZone >= minZone) {
409 if (firstFilter(*searchHead)) {
410 if (activeTail == 0) {
411 activeHead = searchHead;
413 activeTail->
_next = searchHead;
415 activeTail = searchHead;
425 SecondZone *
const __restrict sz = second.
getZone(szi);
426 SecondEntryT *
const __restrict sze = sz->_entries;
427 int const seWrap = sz->_size;
435 while (active != 0) {
437 #if defined(__GNUC__)
438 __builtin_prefetch(active->
_next, 0, 3);
442 boost::uint32_t
const ra = active->
_ra;
443 boost::uint32_t
const deltaRa = active->
_deltaRa;
444 boost::uint32_t
const deltaRaWrap = -deltaRa;
445 int const start = sz->findGte(ra - deltaRa);
448 boost::uint32_t dra = ra - sze[se]._ra;
449 while (dra <= deltaRa || dra >= deltaRaWrap) {
452 boost::int32_t
const dec = sze[se]._dec;
453 if (dec >= active->
_minDec && dec <= active->_maxDec) {
455 if (active->
contains(sze[se]._x, sze[se]._y, sze[se]._z)) {
456 if (secondFilter(sze[se])) {
458 matchPairProcessor(*active, sze[se]);
470 dra = ra - sze[se]._ra;
476 active = active->
_next;
480 prev->
_next = active;
485 active = active->
_next;
496 while (searchHead < end && searchHead->_minZone <= szi) {
497 if (firstFilter(*searchHead)) {
499 activeHead = searchHead;
501 prev->
_next = searchHead;
510 return numMatchPairs;
529 typename FirstEntryT,
530 typename SecondEntryT,
531 typename FirstFilterT,
532 typename SecondFilterT,
533 typename MatchListProcessorT
538 FirstFilterT & firstFilter,
539 SecondFilterT & secondFilter,
540 MatchListProcessorT & matchListProcessor
543 typedef typename MatchListProcessorT::Match Match;
545 std::size_t
const numEllipses = first.size();
546 std::size_t numMatchPairs = 0;
550 #if LSST_AP_HAVE_OPEN_MP
551 # pragma omp parallel default(shared)
555 std::vector<Match> matches;
556 matches.reserve(2048);
559 #if LSST_AP_HAVE_OPEN_MP
561 reduction(+:numMatchPairs) \
564 for (std::size_t i = 0; i < numEllipses; ++i) {
566 if (!firstFilter(first[i])) {
574 boost::uint32_t
const ra = ell->
_ra;
575 boost::uint32_t
const deltaRa = ell->
_deltaRa;
576 boost::uint32_t
const deltaRaWrap = -deltaRa;
581 for ( ; sz < szend; ++sz) {
583 int const seWrap = sz->_size;
589 SecondEntryT *
const __restrict sze = sz->_entries;
590 int const start = sz->findGte(ra - deltaRa);
592 boost::uint32_t dra = ra - sze[se]._ra;
594 while (dra <= deltaRa || dra >= deltaRaWrap) {
597 boost::int32_t
const dec = sze[se]._dec;
598 if (dec >= ell->
_minDec && dec <= ell->_maxDec) {
600 if (ell->
contains(sze[se]._x, sze[se]._y, sze[se]._z)) {
601 if (secondFilter(sze[se])) {
603 matches.push_back(Match(&sze[se]));
614 dra = ra - sze[se]._ra;
619 std::size_t nm = matches.size();
622 numMatchPairs = numMatchPairs + nm;
623 matchListProcessor(*ell, matches.begin(), matches.end());
629 return numMatchPairs;
635 #endif // LSST_AP_MATCH_H
void operator()(F &entity, MatchIterator begin, MatchIterator end)
boost::int32_t deltaDecToScaledInteger(double const delta)
A default "do nothing" match pair processing implementation.
double getZoneDecMax(int const zone) const
int decToZone(double const dec) const
void computeMatchParams(double const radius)
Prepares for distance based matches of the given maximum radius.
boost::uint32_t _deltaRa
width (in right ascension) of ellipse
std::size_t ellipseMatch(EllipseList< FirstEntryT > &first, ZoneIndex< SecondEntryT > &second, FirstFilterT &firstFilter, SecondFilterT &secondFilter, MatchPairProcessorT &matchPairProcessor)
boost::int32_t _minDec
minimum declination of ellipse bounding-box
void operator()(F &first, S &second)
std::size_t distanceMatch(ZoneIndex< FirstEntryT > &first, ZoneIndex< SecondEntryT > &second, double const radius, FirstFilterT &firstFilter, SecondFilterT &secondFilter, MatchListProcessorT &matchListProcessor)
A default "let everything through" filter implementation.
Contains spatial information for a single ellipse on the unit sphere (sky).
A list of ellipses, implemented using std::vector.
Contains a pointer to a match.
ZoneStripeChunkDecomposition const & getDecomposition() const
Container for a sequence of adjacent zones.
boost::uint32_t _ra
right ascension of ellipse center
Stores entries inside a single zone (a narrow declination stripe) in a sorted array.
AngleUnit const radians
constant with units of radians
Ellipse * _next
pointer to next active ellipse in search
void prepareForMatch(ZoneStripeChunkDecomposition const &zsc)
int _minZone
minimum zone of ellipse bounding-box
double getZoneDecMin(int const zone) const
Contains a pointer to a match and an associated distance.
Zone * firstZone(int const minZone, int const maxZone)
int _maxZone
maximum zone of ellipse bounding-box
bool operator()(T const &)
Master header file for the association pipeline.
#define LSST_EXCEPT(type,...)
bool contains(double const x, double const y, double const z) const
Returns true if the ellipse contains the given unit vector.
MatchWithDistance(T *const match, double const d2)
MatchWithoutDistance(T *const match, double const)
Classes for zone entries, zones, and zone indexes.
A default "do nothing" match list processing implementation.
std::size_t ellipseGroupedMatch(EllipseList< FirstEntryT > &first, ZoneIndex< SecondEntryT > &second, FirstFilterT &firstFilter, SecondFilterT &secondFilter, MatchListProcessorT &matchListProcessor)
Zone * getZone(int const zone)
Types involved in algorithms for matching points inside ellipses.
Zone * endZone(int const minZone, int const maxZone)
Class and helper functions related to spatial partitioning.
std::vector< M >::const_iterator MatchIterator