LSSTApplications  1.1.2+25,10.0+13,10.0+132,10.0+133,10.0+224,10.0+41,10.0+8,10.0-1-g0f53050+14,10.0-1-g4b7b172+19,10.0-1-g61a5bae+98,10.0-1-g7408a83+3,10.0-1-gc1e0f5a+19,10.0-1-gdb4482e+14,10.0-11-g3947115+2,10.0-12-g8719d8b+2,10.0-15-ga3f480f+1,10.0-2-g4f67435,10.0-2-gcb4bc6c+26,10.0-28-gf7f57a9+1,10.0-3-g1bbe32c+14,10.0-3-g5b46d21,10.0-4-g027f45f+5,10.0-4-g86f66b5+2,10.0-4-gc4fccf3+24,10.0-40-g4349866+2,10.0-5-g766159b,10.0-5-gca2295e+25,10.0-6-g462a451+1
LSSTDataManagementBasePackage
matchOptimisticB.cc
Go to the documentation of this file.
1 #include <algorithm>
2 #include <cmath>
3 #include <fstream>
4 #include <iostream>
5 #include <vector>
6 
7 #include "boost/scoped_array.hpp"
8 #include "boost/shared_array.hpp"
9 #include "gsl/gsl_linalg.h"
10 
11 #include "lsst/utils/ieee.h"
12 #include "lsst/pex/exceptions.h"
13 #include "lsst/afw/image/Wcs.h"
15 
16 namespace pexExcept = lsst::pex::exceptions;
17 namespace afwTable = lsst::afw::table;
18 
19 namespace {
20  using namespace lsst::meas::astrom;
21 
22  // Algorithm is based on V.Tabur 2007, PASA, 24, 189-198
23  // "Fast Algorithms for Matching CCD Images to a Stellar Catalogue"
24 
31  inline double deltaAngle(double ang1, double ang2) {
32  return std::fmod(std::fabs(ang1 - ang2), M_PI*2);
33  }
34 
35  bool cmpPair(ProxyPair const &a, ProxyPair const &b) {
36  return a.distance > b.distance;
37  }
38 
39  // Compare source based on its PsfFlux
40  // Ordering is bright to faint
41  struct CompareProxyFlux {
42 
43  bool operator()(RecordProxy const & a, RecordProxy const & b) const {
44  double aFlux = a.record->get(key);
45  double bFlux = b.record->get(key);
46  if (lsst::utils::isnan(aFlux)) {
47  aFlux = 0.0;
48  }
49  if (lsst::utils::isnan(bFlux)) {
50  bFlux = 0.0;
51  }
52  return aFlux > bFlux;
53  }
54 
56  };
57 
58  ProxyVector selectPoint(
59  ProxyVector const &a,
60  afwTable::Key<double> const & key,
61  std::size_t num,
62  std::size_t start=0
63  ) {
64  // copy and sort array of pointers on apFlux
65  CompareProxyFlux cmp = {key};
66  ProxyVector b(a);
67  std::sort(b.begin(), b.end(), cmp);
68  std::size_t end = std::min(start + num, b.size());
69  return ProxyVector(b.begin() + start, b.begin() + end);
70  }
71 
72  std::vector<ProxyPair> searchPair(
73  std::vector<ProxyPair> const &a,
74  ProxyPair const &p,
75  double e,
76  double e_dpa
77  ) {
78  std::vector<ProxyPair> v;
79 
80  for (size_t i = 0; i < a.size(); i++) {
81  double dd = std::fabs(a[i].distance - p.distance);
82  double dpa = deltaAngle(a[i].pa, p.pa);
83  if (dd < e && dpa < e_dpa) {
84  v.push_back(a[i]);
85  }
86  }
87 
88  return v;
89  }
90 
91  std::vector<ProxyPair>::iterator searchPair3(
92  std::vector<ProxyPair> &a,
93  ProxyPair const &p,
94  ProxyPair const &q,
95  double e,
96  double dpa,
97  double e_dpa = 0.02
98  ) {
99  std::vector<ProxyPair>::iterator idx = a.end();
100  double dd_min = 1.E+10;
101  //double dpa_min = e_dpa;
102 
103  for (auto i = a.begin(); i != a.end(); ++i) {
104  double dd = std::fabs(i->distance - p.distance);
105  #if 1
106  if (dd < e &&
107  deltaAngle(p.pa, i->pa - dpa) < e_dpa &&
108  dd < dd_min &&
109  (i->first == q.first)) {
110  dd_min = dd;
111  idx = i;
112  }
113  #else
114  if (dd < e &&
115  deltaAngle(p.pa, i->pa - dpa) < dpa_min) {
116  dpa_min = std::fabs(p.pa - i->pa - dpa);
117  idx = i;
118  }
119  #endif
120  }
121 
122  return idx;
123  }
124 
125  void transform(
126  int order,
127  boost::shared_array<double> const & coeff,
128  double x,
129  double y,
130  double *xn,
131  double *yn
132  ) {
133  int ncoeff = (order + 1) * (order + 2) / 2;
134  *xn = 0.0;
135  *yn = 0.0;
136  int n = 0;
137  for (int i = 0; i <= order; i++) {
138  for (int k = 0; k <= i; k++) {
139  int j = i - k;
140  *xn += coeff[n] * pow(x, j) * pow(y, k);
141  *yn += coeff[n+ncoeff] * pow(x, j) * pow(y, k);
142  n++;
143  }
144  }
145  }
146 
147  boost::shared_array<double> polyfit(
148  int order,
149  ProxyVector const &img,
150  ProxyVector const &posRefCat
151  ) {
152  int ncoeff = (order + 1) * (order + 2) / 2;
153  boost::scoped_array<int> xorder(new int[ncoeff]);
154  boost::scoped_array<int> yorder(new int[ncoeff]);
155 
156  int n = 0;
157  for (int i = 0; i <= order; i++) {
158  for (int k = 0; k <= i; k++) {
159  int j = i - k;
160  xorder[n] = j;
161  yorder[n] = k;
162  n++;
163  }
164  }
165 
166  boost::scoped_array<int> flag(new int[img.size()]);
167  for (size_t k = 0; k < img.size(); k++) {
168  flag[k] = 1;
169  }
170 
171  boost::scoped_array<double> a_data(new double[ncoeff*ncoeff]);
172  boost::scoped_array<double> b_data(new double[ncoeff]);
173  boost::scoped_array<double> c_data(new double[ncoeff]);
174 
175  boost::shared_array<double> coeff(new double[ncoeff*2]);
176 
177  for (int loop = 0; loop < 1; loop++) {
178  for (int i = 0; i < ncoeff; i++) {
179  for (int j = 0; j < ncoeff; j++) {
180  a_data[i*ncoeff+j] = 0.0;
181  for (size_t k = 0; k < img.size(); k++) {
182  if (flag[k] == 1) {
183  a_data[i*ncoeff+j] += pow(img[k].getX(), xorder[i]) *
184  pow(img[k].getY(), yorder[i]) *
185  pow(img[k].getX(), xorder[j]) *
186  pow(img[k].getY(), yorder[j]);
187  }
188  }
189  }
190  b_data[i] = c_data[i] = 0.0;
191  for (unsigned int k = 0; k < img.size(); k++) {
192  if (flag[k] == 1) {
193  b_data[i] += pow(img[k].getX(), xorder[i]) *
194  pow(img[k].getY(), yorder[i]) *
195  posRefCat[k].getX();
196  c_data[i] += pow(img[k].getX(), xorder[i]) *
197  pow(img[k].getY(), yorder[i]) *
198  posRefCat[k].getY();
199  }
200  }
201  }
202 
203  gsl_matrix_view a = gsl_matrix_view_array(a_data.get(), ncoeff, ncoeff);
204  gsl_vector_view b = gsl_vector_view_array(b_data.get(), ncoeff);
205  gsl_vector_view c = gsl_vector_view_array(c_data.get(), ncoeff);
206 
207  boost::shared_ptr<gsl_vector> x(gsl_vector_alloc(ncoeff), gsl_vector_free);
208  boost::shared_ptr<gsl_vector> y(gsl_vector_alloc(ncoeff), gsl_vector_free);
209 
210  int s;
211 
212  boost::shared_ptr<gsl_permutation> p(gsl_permutation_alloc(ncoeff), gsl_permutation_free);
213 
214  gsl_linalg_LU_decomp(&a.matrix, p.get(), &s);
215  gsl_linalg_LU_solve(&a.matrix, p.get(), &b.vector, x.get());
216  gsl_linalg_LU_solve(&a.matrix, p.get(), &c.vector, y.get());
217 
218  for (int i = 0; i < ncoeff; i++) {
219  coeff[i] = x->data[i];
220  coeff[i+ncoeff] = y->data[i];
221  }
222 
223  double S, Sx, Sy, Sxx, Syy;
224  S = Sx = Sy = Sxx = Syy = 0.0;
225  for (size_t k = 0; k < img.size(); k++) {
226  if (flag[k] == 1) {
227  double x0 = img[k].getX();
228  double y0 = img[k].getY();
229  double x1, y1;
230  transform(order, coeff, x0, y0, &x1, &y1);
231  S += 1.;
232  Sx += (x1 - posRefCat[k].getX());
233  Sxx += (x1 - posRefCat[k].getX()) * (x1 - posRefCat[k].getX());
234  Sy += (y1 - posRefCat[k].getY());
235  Syy += (y1 - posRefCat[k].getY()) * (y1 - posRefCat[k].getY());
236  }
237  }
238  double x_sig = std::sqrt((Sxx - Sx * Sx / S) / S);
239  double y_sig = std::sqrt((Syy - Sy * Sy / S) / S);
240  //std::cout << x_sig << " " << y_sig << std::endl;
241 
242  for (size_t k = 0; k < img.size(); k++) {
243  double x0 = img[k].getX();
244  double y0 = img[k].getY();
245  double x1, y1;
246  transform(order, coeff, x0, y0, &x1, &y1);
247  if (std::fabs(x1-posRefCat[k].getX()) > 2. * x_sig ||
248  std::fabs(y1-posRefCat[k].getY()) > 2. * y_sig) {
249  flag[k] = 0;
250  }
251  }
252 
253  }
254 
255  return coeff;
256  }
257 
258  ProxyVector::const_iterator searchNearestPoint(
259  ProxyVector const &posRefCat,
260  double x,
261  double y,
262  double e
263  ) {
264  ProxyVector::const_iterator foundPtr = posRefCat.end();
265  double d_min, d;
266 
267  d_min = e;
268 
269  for (ProxyVector::const_iterator posRefPtr = posRefCat.begin();
270  posRefPtr != posRefCat.end(); ++posRefPtr) {
271  d = std::hypot(posRefPtr->getX()-x, posRefPtr->getY()-y);
272  if (d < d_min) {
273  foundPtr = posRefPtr;
274  d_min = d;
275  break;
276  }
277  }
278 
279  return foundPtr;
280  }
281 
282  afwTable::ReferenceMatchVector FinalVerify(
283  boost::shared_array<double> coeff,
284  ProxyVector const & posRefCat,
285  ProxyVector const & sourceCat,
286  double matchingAllowancePix,
287  bool verbose
288  ) {
289  ProxyVector srcMat;
290  ProxyVector catMat;
292 
293  double x0, y0, x1, y1;
294  int num = 0, num_prev = -1;
295  for (ProxyVector::const_iterator sourcePtr = sourceCat.begin(); sourcePtr != sourceCat.end();
296  ++sourcePtr) {
297  x0 = sourcePtr->getX();
298  y0 = sourcePtr->getY();
299  transform(1, coeff, x0, y0, &x1, &y1);
300  auto p = searchNearestPoint(posRefCat, x1, y1, matchingAllowancePix);
301  if (p != posRefCat.end()) {
302  num++;
303  srcMat.push_back(*sourcePtr);
304  catMat.push_back(*p);
305  }
306  }
307 
308  //std::cout << num << std::endl;
309  int order = 1;
310  if (num > 5) {
311  coeff = polyfit(order, srcMat, catMat);
312 
313  for (int j = 0; j < 100; j++) {
314  srcMat.clear();
315  catMat.clear();
316  matPair.clear();
317  num = 0;
318  for (ProxyVector::const_iterator sourcePtr = sourceCat.begin();
319  sourcePtr != sourceCat.end(); ++sourcePtr) {
320  x0 = sourcePtr->getX();
321  y0 = sourcePtr->getY();
322  transform(order, coeff, x0, y0, &x1, &y1);
323  auto p = searchNearestPoint(posRefCat, x1, y1, matchingAllowancePix);
324  if (p != posRefCat.end()) {
325  num++;
326  srcMat.push_back(*sourcePtr);
327  catMat.push_back(*p);
328  matPair.push_back(afwTable::ReferenceMatch(
329  *p, boost::static_pointer_cast<afwTable::SourceRecord>(sourcePtr->record), 0.0));
330  }
331  }
332  //std::cout << "# of objects matched: " << num << " " << num_prev << std::endl;
333  if (num == num_prev) break;
334  //if (num > 50) order = 3;
335  coeff = polyfit(order, srcMat, catMat);
336  num_prev = num;
337  }
338  if (verbose) {
339  //std::cout << "# of objects matched: " << num << std::endl;
340  //for (int i = 0; i < 10; i++) {
341  //printf("%2d %12.5e %12.5e\n", i, coeff[i], coeff[10+i]);
342  //}
343  //printf("\n");
344  }
345  } else {
346  for (unsigned int i = 0; i < srcMat.size(); i++) {
347  matPair.push_back(
349  catMat[i], boost::static_pointer_cast<afwTable::SourceRecord>(srcMat[i].record), 0.0)
350  );
351  }
352  }
353 
354  return matPair;
355  }
356 
357 } // anonymous namespace
358 
359 namespace lsst {
360 namespace meas {
361 namespace astrom {
362 
363  void MatchOptimisticBControl::validate() const {
364  if (refFluxField.empty()) {
365  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "refFluxField must be specified");
366  }
367  if (sourceFluxField.empty()) {
368  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "sourceFluxField must be specified");
369  }
370  if (numBrightStars <= 0) {
371  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "numBrightStars must be positive");
372  }
373  if (minMatchedPairs < 0) {
374  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "minMatchedPairs must not be negative");
375  }
376  if (matchingAllowancePix <= 0) {
377  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "matchingAllowancePix must be positive");
378  }
379  if (maxOffsetPix <= 0) {
380  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "maxOffsetPix must be positive");
381  }
382  if (maxRotationRad <= 0) {
383  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "maxRotationRad must be positive");
384  }
385  if (angleDiffFrom90 <= 0) {
386  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "angleDiffFrom90 must be positive");
387  }
388  if (numPointsForShape <= 0) {
389  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "numPointsForShape must be positive");
390  }
391  if (maxDeterminant <= 0) {
392  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "maxDeterminant must be positive");
393  }
394  }
395 
397  ProxyVector r;
398  r.reserve(sourceCat.size());
399  for (afwTable::SourceCatalog::const_iterator sourcePtr = sourceCat.begin();
400  sourcePtr != sourceCat.end(); ++sourcePtr) {
401  r.push_back(RecordProxy(sourcePtr, sourcePtr->getCentroid()));
402  }
403  return r;
404  }
405 
407  auto centroidKey = posRefCat.getSchema().find<afwTable::Point<double>>("centroid").key;
408  auto hasCentroidKey = posRefCat.getSchema().find<afwTable::Flag>("hasCentroid").key;
409  ProxyVector r;
410  r.reserve(posRefCat.size());
411  for (afwTable::SimpleCatalog::const_iterator posRefPtr = posRefCat.begin();
412  posRefPtr != posRefCat.end(); ++posRefPtr) {
413  if (!posRefPtr->get(hasCentroidKey)) {
414  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "unknown centroid");
415  }
416  r.push_back(RecordProxy(posRefPtr, posRefPtr->get(centroidKey)));
417  }
418  return r;
419  }
420 
422  afwTable::SimpleCatalog const &posRefCat,
423  afwTable::SourceCatalog const &sourceCat,
424  MatchOptimisticBControl const &control,
425  int posRefBegInd,
426  bool verbose
427  ) {
428  control.validate();
429 
430  // Select brightest Nsub stars from list of objects
431  // Process both detected from image and external catalog
432  int Nsub = control.numBrightStars;
433  ProxyVector posRefProxyCat = makeProxies(posRefCat);
434  ProxyVector sourceProxyCat = makeProxies(sourceCat);
435  ProxyVector sourceSubCat = selectPoint(
436  sourceProxyCat,
437  sourceCat.getSchema().find<double>(control.sourceFluxField).key,
438  Nsub);
439  ProxyVector posRefSubCat = selectPoint(
440  posRefProxyCat,
441  posRefCat.getSchema().find<double>(control.refFluxField).key,
442  sourceSubCat.size()+25,
443  posRefBegInd);
444  if (verbose) {
445  std::cout << "Catalog sizes: " << sourceSubCat.size() << " " << posRefSubCat.size() << std::endl;
446  }
447 
448  // Construct a list of pairs of position reference stars sorted by increasing separation
449  std::vector<ProxyPair> posRefPairList;
450  size_t const posRefCatSubSize = posRefSubCat.size();
451  for (size_t i = 0; i < posRefCatSubSize-1; i++) {
452  for (size_t j = i+1; j < posRefCatSubSize; j++) {
453  posRefPairList.push_back(ProxyPair(posRefSubCat[i], posRefSubCat[j]));
454  }
455  }
456 
457  // Sort posRefPairList on distance
458  std::sort(posRefPairList.begin(), posRefPairList.end(), cmpPair);
459 
460  // Construct a list of pairs of sources sorted by increasing separation
461  std::vector<ProxyPair> sourcePairList;
462  size_t const sourceSubCatSize = sourceSubCat.size();
463  for (size_t i = 0; i < sourceSubCatSize-1; i++) {
464  for (size_t j = i+1; j < sourceSubCatSize; j++) {
465  sourcePairList.push_back(ProxyPair(sourceSubCat[i], sourceSubCat[j]));
466  }
467  }
468  std::sort(sourcePairList.begin(), sourcePairList.end(), cmpPair);
469 
471  afwTable::ReferenceMatchVector matPairSave;
472  std::vector<afwTable::ReferenceMatchVector> matPairCand;
473 
474  size_t const fullShapeSize = control.numPointsForShape - 1; // Max size of shape array
475  for (size_t ii = 0; ii < sourcePairList.size(); ii++) {
476  ProxyPair p = sourcePairList[ii];
477 
478  std::vector<ProxyPair> q = searchPair(posRefPairList, p,
479  control.matchingAllowancePix, control.maxRotationRad);
480 
481  // If candidate pairs are found
482  if (q.size() != 0) {
483 
484  std::vector<ProxyPair> srcMatPair;
485  std::vector<ProxyPair> catMatPair;
486 
487  // Go through candidate pairs
488  for (size_t l = 0; l < q.size(); l++) {
489 
490  double dpa = p.pa - q[l].pa;
491 
492  srcMatPair.clear();
493  catMatPair.clear();
494 
495  srcMatPair.push_back(p);
496  catMatPair.push_back(q[l]);
497 
498  if (verbose) {
499  std::cout << "p dist: " << p.distance << " pa: " << p.pa << std::endl;
500  std::cout << "q dist: " << q[l].distance << " pa: " << q[l].pa << std::endl;
501  }
502 
503  for (size_t k = 0; k < sourceSubCat.size(); k++) {
504  if (p.first == sourceSubCat[k] || p.second == sourceSubCat[k]) continue;
505 
506  ProxyPair pp(p.first, sourceSubCat[k]);
507 
508  std::vector<ProxyPair>::iterator r = searchPair3(posRefPairList, pp, q[l],
509  control.matchingAllowancePix, dpa, control.maxRotationRad);
510  if (r != posRefPairList.end()) {
511  srcMatPair.push_back(pp);
512  catMatPair.push_back(*r);
513  if (verbose) {
514  std::cout << " p dist: " << pp.distance << " pa: " << pp.pa << std::endl;
515  std::cout << " r dist: " << (*r).distance << " pa: " << (*r).pa << std::endl;
516  }
517  if (srcMatPair.size() == fullShapeSize) {
518  break;
519  }
520  }
521  }
522 
523  bool goodMatch = false;
524  if (srcMatPair.size() == fullShapeSize) {
525  goodMatch = true;
526  for (size_t k = 1; k < catMatPair.size(); k++) {
527  if (catMatPair[0].first != catMatPair[k].first) {
528  goodMatch = false;
529  }
530  }
531  }
532 
533  if (goodMatch && srcMatPair.size() == fullShapeSize) {
534 
535  ProxyVector srcMat;
536  ProxyVector catMat;
537 
538  srcMat.push_back(srcMatPair[0].first);
539  catMat.push_back(catMatPair[0].first);
540  for (size_t k = 0; k < srcMatPair.size(); k++) {
541  srcMat.push_back(srcMatPair[k].second);
542  catMat.push_back(catMatPair[k].second);
543  }
544 
545  boost::shared_array<double> coeff = polyfit(1, srcMat, catMat);
546 
547  if (verbose) {
548  for (size_t k = 0; k < srcMat.size(); k++) {
549  std::cout << "circle(" << srcMat[k].getX() << ","
550  << srcMat[k].getY() << ",10) # color=green" << std::endl;
551  std::cout << "circle(" << catMat[k].getX() << ","
552  << catMat[k].getY() << ",10) # color=red" << std::endl;
553  std::cout << "line(" << srcMat[0].getX() << "," << srcMat[0].getY() << ","
554  << srcMat[k].getX() << "," << srcMat[k].getY()
555  << ") # line=0 0 color=green" << std::endl;
556  std::cout << "line(" << catMat[0].getX() << "," << catMat[0].getY() << ","
557  << catMat[k].getX() << "," << catMat[k].getY()
558  << ") # line=0 0 color=red" << std::endl;
559  }
560  }
561 
562  double a = coeff[1];
563  double b = coeff[2];
564  double c = coeff[4];
565  double d = coeff[5];
566  double theta = std::acos((a*b+c*d)/(std::sqrt(a*a+c*c)*std::sqrt(b*b+d*d))) /
567  M_PI * 180.0;
568  if (verbose) {
569  std::cout << "Linear fit from match:" << std::endl;
570  std::cout << coeff[0] << " " << coeff[1] << " " << coeff[2] << std::endl;
571  std::cout << coeff[3] << " " << coeff[4] << " " << coeff[5] << std::endl;
572  std::cout << coeff[1] * coeff[5] - coeff[2] * coeff[4] - 1. << std::endl;
573  std::cout << theta << std::endl;
574  }
575  if (std::fabs(coeff[1] * coeff[5] - coeff[2] * coeff[4] - 1.) > control.maxDeterminant ||
576  std::fabs(theta - 90.) > control.angleDiffFrom90 ||
577  std::fabs(coeff[0]) > control.maxOffsetPix ||
578  std::fabs(coeff[3]) > control.maxOffsetPix) {
579  if (verbose) {
580  std::cout << "Bad; continuing" << std::endl;
581  }
582  continue;
583  } else {
584  double x0, y0, x1, y1;
585  int num = 0;
586  srcMat.clear();
587  catMat.clear();
588  for (size_t i = 0; i < sourceSubCat.size(); i++) {
589  x0 = sourceSubCat[i].getX();
590  y0 = sourceSubCat[i].getY();
591  transform(1, coeff, x0, y0, &x1, &y1);
592  auto p = searchNearestPoint(posRefSubCat, x1, y1,
593  control.matchingAllowancePix);
594  if (p != posRefSubCat.end()) {
595  num++;
596  srcMat.push_back(sourceSubCat[i]);
597  catMat.push_back(*p);
598  if (verbose) {
599  std::cout << "Match: " << x0 << "," << y0 << " --> "
600  << x1 << "," << y1 <<
601  " <==> " << p->getX() << "," << p->getY() << std::endl;
602  }
603  }
604  }
605  if (num <= control.numPointsForShape) {
606  // Can get matrix = 0,0,0,0; everything matches a single catalog object
607  if (verbose) {
608  std::cout << "Insufficient initial matches; continuing" << std::endl;
609  }
610  continue;
611  }
612  coeff = polyfit(1, srcMat, catMat);
613  if (verbose) {
614  std::cout << "Coefficients from initial matching:" << std::endl;
615  for (size_t i = 0; i < 6; ++i) {
616  std::cout << coeff[i] << " ";
617  }
618  std::cout << std::endl;
619  }
620 
621  matPair = FinalVerify(coeff, posRefProxyCat, sourceProxyCat,
622  control.matchingAllowancePix, verbose);
623  if (verbose) {
624  std::cout << "Number of matches: " << matPair.size() << " vs " <<
625  control.minMatchedPairs << std::endl;
626  }
627  if (matPair.size() <= control.minMatchedPairs) {
628  if (verbose) {
629  std::cout << "Insufficient final matches; continuing" << std::endl;
630  }
631  if (matPair.size() > matPairSave.size()) {
632  matPairSave = matPair;
633  }
634  continue;
635  } else {
636  if (verbose) {
637  std::cout << "Finish" << std::endl;
638  }
639  matPairCand.push_back(matPair);
640  if (matPairCand.size() == 3) {
641  goto END;
642  }
643  }
644  }
645  }
646  }
647  }
648  }
649 
650  END:
651  if (matPairCand.size() == 0) {
652  return matPairSave;
653  } else {
654  size_t nmatch = matPairCand[0].size();
655  afwTable::ReferenceMatchVector matPairRet = matPairCand[0];
656  for (size_t i = 1; i < matPairCand.size(); i++) {
657  if (matPairCand[i].size() > nmatch) {
658  nmatch = matPairCand[i].size();
659  matPairRet = matPairCand[i];
660  }
661  }
662  return matPairRet;
663  }
664  }
665 
666 }}} // namespace lsst::afw::astrom
int y
int numPointsForShape
&quot;number of points in a matching shape&quot; ;
double angleDiffFrom90
&quot;? (deg)&quot; ;
std::vector< ReferenceMatch > ReferenceMatchVector
Definition: fwd.h:97
int isnan(T t)
Definition: ieee.h:110
int const x0
Definition: saturated.cc:45
std::vector< RecordProxy > ProxyVector
double min
Definition: attributes.cc:216
int d
Definition: KDTree.cc:89
afwTable::ReferenceMatchVector matchOptimisticB(afwTable::SimpleCatalog const &posRefCat, afwTable::SourceCatalog const &sourceCat, MatchOptimisticBControl const &control, int posRefBegInd, bool verbose)
Custom catalog class for record/table subclasses that are guaranteed to have an ID, and should generally be sorted by that ID.
Definition: fwd.h:55
ProxyVector makeProxies(afwTable::SourceCatalog const &sourceCat)
Schema getSchema() const
Return the schema associated with the catalog&#39;s table.
Definition: Catalog.h:114
Lightweight representation of a geometric match between two records.
Definition: fwd.h:90
SchemaItem< T > find(std::string const &name) const
Find a SchemaItem in the Schema by name.
double maxOffsetPix
&quot;maximum translation allowed (pixels)&quot; ;
int x
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
int numBrightStars
&quot;maximum number of bright reference stars to use&quot; ;
std::string refFluxField
&quot;name of flux field in reference catalog&quot; ;
afw::table::Key< double > b
double maxRotationRad
&quot;maximum allowed rotation (rad)&quot; ;
std::string sourceFluxField
&quot;name of flux field in source catalog&quot; ;
Base::const_iterator const_iterator
Definition: SortedCatalog.h:49
int const y0
Definition: saturated.cc:45
Tag types used to declare specialized field types.
Definition: misc.h:35
Include files required for standard LSST Exception handling.
int minMatchedPairs
&quot;minimum number of matches&quot; ;
boost::shared_ptr< lsst::afw::table::SimpleRecord > record
size_type size() const
Return the number of elements in the catalog.
Definition: Catalog.h:401