Match sources to stars in a position reference catalog using optimistic pattern matching B.
Optimistic Pattern Matching is described in V. Tabur 2007, PASA, 24, 189-198 "Fast Algorithms for Matching CCD Images to a Stellar Catalogue"
529 if (posRefCat.empty()) {
530 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"no entries in posRefCat");
532 if (sourceCat.empty()) {
533 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"no entries in sourceCat");
535 if (posRefBegInd < 0) {
536 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"posRefBegInd < 0");
538 if (static_cast<size_t>(posRefBegInd) >= posRefCat.size()) {
539 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"posRefBegInd too big");
544 if (
wcs.hasDistortion()) {
548 for (
auto iter = sourceCat.begin();
iter != sourceCat.end(); ++
iter) {
551 srcCenter /= sourceCat.size();
554 for (
auto iter = posRefCat.begin();
iter != posRefCat.end(); ++
iter) {
557 refCenter /= posRefCat.size();
559 tanWcs = std::make_shared<afw::image::Wcs>(
572 sourceCat.getSchema().find<
double>(control.sourceFluxField).key,
573 control.numBrightStars);
579 posRefCat.getSchema().find<
double>(control.refFluxField).key,
580 sourceSubCat.size()+25,
583 std::cout <<
"Catalog sizes: " << sourceSubCat.size() <<
" " << posRefSubCat.size() << std::endl;
587 std::vector<ProxyPair> posRefPairList;
588 size_t const posRefCatSubSize = posRefSubCat.size();
589 for (
size_t i = 0; i < posRefCatSubSize-1; i++) {
590 for (
size_t j = i+1; j < posRefCatSubSize; j++) {
591 posRefPairList.push_back(
ProxyPair(posRefSubCat[i], posRefSubCat[j]));
594 std::sort(posRefPairList.begin(), posRefPairList.end(), cmpPair);
597 std::vector<ProxyPair> sourcePairList;
598 size_t const sourceSubCatSize = sourceSubCat.size();
599 for (
size_t i = 0; i < sourceSubCatSize-1; i++) {
600 for (
size_t j = i+1; j < sourceSubCatSize; j++) {
601 sourcePairList.push_back(
ProxyPair(sourceSubCat[i], sourceSubCat[j]));
604 std::sort(sourcePairList.begin(), sourcePairList.end(), cmpPair);
608 std::vector<afwTable::ReferenceMatchVector> matPairCand;
610 size_t const fullShapeSize = control.numPointsForShape - 1;
611 for (
size_t ii = 0; ii < sourcePairList.size(); ii++) {
614 std::vector<ProxyPair> q = searchPair(posRefPairList, p,
615 control.matchingAllowancePix, maxRotationRad);
620 std::vector<ProxyPair> srcMatPair;
621 std::vector<ProxyPair> catMatPair;
624 for (
size_t l = 0; l < q.size(); l++) {
627 double dpa = p.
pa - q[l].pa;
632 srcMatPair.push_back(p);
633 catMatPair.push_back(q[l]);
636 std::cout <<
"p dist: " << p.
distance <<
" pa: " << p.
pa << std::endl;
637 std::cout <<
"q dist: " << q[l].distance <<
" pa: " << q[l].pa << std::endl;
640 for (
size_t k = 0; k < sourceSubCat.size(); k++) {
641 if (p.
first == sourceSubCat[k] || p.
second == sourceSubCat[k])
continue;
645 std::vector<ProxyPair>::iterator r = searchPair3(posRefPairList, pp, q[l],
646 control.matchingAllowancePix, dpa, maxRotationRad);
647 if (r != posRefPairList.end()) {
648 srcMatPair.push_back(pp);
649 catMatPair.push_back(*r);
651 std::cout <<
" p dist: " << pp.distance <<
" pa: " << pp.pa << std::endl;
652 std::cout <<
" r dist: " << (*r).distance <<
" pa: " << (*r).pa << std::endl;
654 if (srcMatPair.size() == fullShapeSize) {
660 bool goodMatch =
false;
661 if (srcMatPair.size() == fullShapeSize) {
663 for (
size_t k = 1; k < catMatPair.size(); k++) {
664 if (catMatPair[0].first != catMatPair[k].first) {
671 if (goodMatch && srcMatPair.size() == fullShapeSize) {
676 srcMat.push_back(srcMatPair[0].first);
677 catMat.push_back(catMatPair[0].first);
678 for (
size_t k = 0; k < srcMatPair.size(); k++) {
679 srcMat.push_back(srcMatPair[k].second);
680 catMat.push_back(catMatPair[k].second);
683 boost::shared_array<double> coeff = polyfit(1, srcMat, catMat);
686 for (
size_t k = 0; k < srcMat.size(); k++) {
687 std::cout <<
"circle(" << srcMat[k].getX() <<
","
688 << srcMat[k].getY() <<
",10) # color=green" << std::endl;
689 std::cout <<
"circle(" << catMat[k].getX() <<
","
690 << catMat[k].getY() <<
",10) # color=red" << std::endl;
691 std::cout <<
"line(" << srcMat[0].getX() <<
"," << srcMat[0].getY() <<
","
692 << srcMat[k].getX() <<
"," << srcMat[k].getY()
693 <<
") # line=0 0 color=green" << std::endl;
694 std::cout <<
"line(" << catMat[0].getX() <<
"," << catMat[0].getY() <<
","
695 << catMat[k].getX() <<
"," << catMat[k].getY()
696 <<
") # line=0 0 color=red" << std::endl;
705 (std::sqrt(a*a+c*c)*std::sqrt(b*b+d*d))),
708 std::cout <<
"Linear fit from match:" << std::endl;
709 std::cout << coeff[0] <<
" " << coeff[1] <<
" " << coeff[2] << std::endl;
710 std::cout << coeff[3] <<
" " << coeff[4] <<
" " << coeff[5] << std::endl;
711 std::cout <<
"Determinant (max " << control.maxDeterminant <<
"): ";
712 std::cout << coeff[1] * coeff[5] - coeff[2] * coeff[4] - 1. << std::endl;
713 std::cout <<
"Angle between axes (deg; allowed 90 +/- ";
714 std::cout << control.allowedNonperpDeg <<
"): ";
715 std::cout << theta.asDegrees() << std::endl;
717 if (std::fabs(coeff[1] * coeff[5] - coeff[2] * coeff[4] - 1.)
718 > control.maxDeterminant ||
719 std::fabs(theta.asDegrees() - 90) > control.allowedNonperpDeg ||
720 std::fabs(coeff[0]) > control.maxOffsetPix ||
721 std::fabs(coeff[3]) > control.maxOffsetPix) {
723 std::cout <<
"Bad; continuing" << std::endl;
727 double x0,
y0, x1, y1;
731 for (
size_t i = 0; i < sourceSubCat.size(); i++) {
732 x0 = sourceSubCat[i].getX();
733 y0 = sourceSubCat[i].getY();
734 transform(1, coeff, x0, y0, &x1, &y1);
735 auto refObjDist = searchNearestPoint(posRefSubCat, x1, y1,
736 control.matchingAllowancePix);
737 if (refObjDist.first != posRefSubCat.end()) {
739 srcMat.push_back(sourceSubCat[i]);
740 catMat.push_back(*refObjDist.first);
742 std::cout <<
"Match: " << x0 <<
"," << y0 <<
" --> "
743 << x1 <<
"," << y1 <<
" <==> "
744 << refObjDist.first->getX() <<
"," << refObjDist.first->getY()
749 if (num <= control.numPointsForShape) {
752 std::cout <<
"Insufficient initial matches; continuing" << std::endl;
756 coeff = polyfit(1, srcMat, catMat);
758 std::cout <<
"Coefficients from initial matching:" << std::endl;
759 for (
size_t i = 0; i < 6; ++i) {
760 std::cout << coeff[i] <<
" ";
762 std::cout << std::endl;
765 matPair = FinalVerify(coeff, posRefProxyCat, sourceProxyCat,
766 control.matchingAllowancePix, verbose);
768 std::cout <<
"Number of matches: " << matPair.size() <<
" vs " <<
769 control.minMatchedPairs << std::endl;
771 if (matPair.size() <=
static_cast<std::size_t
>(control.minMatchedPairs)) {
773 std::cout <<
"Insufficient final matches; continuing" << std::endl;
775 if (matPair.size() > matPairSave.size()) {
776 matPairSave = matPair;
781 std::cout <<
"Finish" << std::endl;
783 matPairCand.push_back(matPair);
784 if (matPairCand.size() == 3) {
795 if (matPairCand.size() == 0) {
798 size_t nmatch = matPairCand[0].size();
800 for (
size_t i = 1; i < matPairCand.size(); i++) {
801 if (matPairCand[i].size() > nmatch) {
802 nmatch = matPairCand[i].size();
803 matPairRet = matPairCand[i];
lsst::afw::geom::Point2D getPosition(lsst::afw::geom::AngleUnit unit=lsst::afw::geom::degrees) const
Return our contents in a Point2D object.
AngleUnit const radians
constant with units of radians
Extent< double, 2 > Extent2D
std::vector< ReferenceMatch > ReferenceMatchVector
lsst::afw::coord::IcrsCoord IcrsCoord
Extent< double, 3 > Extent3D
if(width!=gim.getWidth()||height!=gim.getHeight()||x0!=gim.getX0()||y0!=gim.getY0())
Point< double, 3 > Point3D
lsst::afw::image::Wcs Wcs
double degToRad(long double angleInDegrees)
#define LSST_EXCEPT(type,...)
Create an exception with a given type and message and optionally other arguments (dependent on the ty...
std::vector< RecordProxy > ProxyVector
lsst::afw::geom::Angle Angle
afw::table::Key< double > b
Point< double, 2 > Point2D
ProxyVector makeProxies(lsst::afw::table::SourceCatalog const &sourceCat, afw::image::Wcs const &distortedWcs, afw::image::Wcs const &tanWcs)
#define CONST_PTR(...)
A shared pointer to a const object.