LSSTApplications  11.0-13-gbb96280,12.1+18,12.1+7,12.1-1-g14f38d3+72,12.1-1-g16c0db7+5,12.1-1-g5961e7a+84,12.1-1-ge22e12b+23,12.1-11-g06625e2+4,12.1-11-g0d7f63b+4,12.1-19-gd507bfc,12.1-2-g7dda0ab+38,12.1-2-gc0bc6ab+81,12.1-21-g6ffe579+2,12.1-21-gbdb6c2a+4,12.1-24-g941c398+5,12.1-3-g57f6835+7,12.1-3-gf0736f3,12.1-37-g3ddd237,12.1-4-gf46015e+5,12.1-5-g06c326c+20,12.1-5-g648ee80+3,12.1-5-gc2189d7+4,12.1-6-ga608fc0+1,12.1-7-g3349e2a+5,12.1-7-gfd75620+9,12.1-9-g577b946+5,12.1-9-gc4df26a+10
LSSTDataManagementBasePackage
Namespaces | Classes | Typedefs | Functions
lsst.meas.astrom Namespace Reference

Namespaces

 anetAstrometry
 
 anetBasicAstrometry
 
 approximateWcs
 
 astrometry
 
 astrometryNetDataConfig
 
 catalogStarSelector
 
 
 detail
 
 directMatch
 
 display
 
 fitSipDistortion
 
 fitTanSipWcs
 
 loadAstrometryNetObjects
 
 matchOptimisticB
 
 multiindex
 
 ref_match
 
 setMatchDistance
 
 sip
 
 verifyWcs
 
 version
 

Classes

struct  RecordProxy
 A wrapper around a SimpleRecord or SourceRecord that allows us to record a pixel position in a way that is independent of the record type. More...
 
struct  ProxyPair
 
struct  MatchOptimisticBControl
 
class  PolynomialTransform
 A 2-d coordinate transform represented by a pair of standard polynomials (one for each coordinate). More...
 
class  ScaledPolynomialTransform
 A 2-d coordinate transform represented by a lazy composition of an AffineTransform, a PolynomialTransform, and another AffineTransform. More...
 
class  OutlierRejectionControl
 Control object for outlier rejection in ScaledPolynomialTransformFitter. More...
 
class  ScaledPolynomialTransformFitter
 A fitter class for scaled polynomial transforms. More...
 
class  SipTransformBase
 Base class for SIP transform objects. More...
 
class  SipForwardTransform
 A transform that maps pixel coordinates to intermediate world coordinates according to the SIP convention. More...
 
class  SipReverseTransform
 A transform that maps intermediate world coordinates to pixel coordinates according to the SIP convention. More...
 

Typedefs

typedef std::vector< RecordProxyProxyVector
 

Functions

template<typename MatchT >
afw::math::Statistics makeMatchStatistics (std::vector< MatchT > const &matchList, int const flags, afw::math::StatisticsControl const &sctrl=afw::math::StatisticsControl())
 Compute statistics of the distance field of a match list. More...
 
template<typename MatchT >
afw::math::Statistics makeMatchStatisticsInPixels (afw::image::Wcs const &wcs, std::vector< MatchT > const &matchList, int const flags, afw::math::StatisticsControl const &sctrl=afw::math::StatisticsControl())
 Compute statistics of on-detector radial separation for a match list, in pixels. More...
 
template<typename MatchT >
afw::math::Statistics makeMatchStatisticsInRadians (afw::image::Wcs const &wcs, std::vector< MatchT > const &matchList, int const flags, afw::math::StatisticsControl const &sctrl=afw::math::StatisticsControl())
 Compute statistics of on-sky radial separation for a match list, in radians. More...
 
ProxyVector makeProxies (lsst::afw::table::SourceCatalog const &sourceCat, afw::image::Wcs const &distortedWcs, afw::image::Wcs const &tanWcs)
 
ProxyVector makeProxies (lsst::afw::table::SimpleCatalog const &posRefCat, afw::image::Wcs const &tanWcs)
 
lsst::afw::table::ReferenceMatchVector matchOptimisticB (lsst::afw::table::SimpleCatalog const &posRefCat, lsst::afw::table::SourceCatalog const &sourceCat, MatchOptimisticBControl const &control, afw::image::Wcs const &wcs, int posRefBegInd=0, bool verbose=false)
 Match sources to stars in a position reference catalog using optimistic pattern matching B. More...
 
PolynomialTransform compose (afw::geom::AffineTransform const &t1, PolynomialTransform const &t2)
 Return a PolynomialTransform that is equivalent to the composition t1(t2()) More...
 
PolynomialTransform compose (PolynomialTransform const &t1, afw::geom::AffineTransform const &t2)
 Return a PolynomialTransform that is equivalent to the composition t1(t2()) More...
 
std::shared_ptr
< afw::image::TanWcs
makeWcs (SipForwardTransform const &sipForward, SipReverseTransform const &sipReverse, afw::coord::Coord const &skyOrigin)
 Create a new TAN SIP Wcs from a pair of SIP transforms and the sky origin. More...
 
template afw::math::Statistics makeMatchStatistics< afw::table::ReferenceMatch > (std::vector< afw::table::ReferenceMatch > const &matchList, int const flags, afw::math::StatisticsControl const &sctrl)
 
template afw::math::Statistics makeMatchStatisticsInPixels< afw::table::ReferenceMatch > (afw::image::Wcs const &wcs, std::vector< afw::table::ReferenceMatch > const &matchList, int const flags, afw::math::StatisticsControl const &sctrl)
 
template afw::math::Statistics makeMatchStatisticsInRadians< afw::table::ReferenceMatch > (afw::image::Wcs const &wcs, std::vector< afw::table::ReferenceMatch > const &matchList, int const flags, afw::math::StatisticsControl const &sctrl)
 
template afw::math::Statistics makeMatchStatistics< afw::table::SourceMatch > (std::vector< afw::table::SourceMatch > const &matchList, int const flags, afw::math::StatisticsControl const &sctrl)
 
template afw::math::Statistics makeMatchStatisticsInPixels< afw::table::SourceMatch > (afw::image::Wcs const &wcs, std::vector< afw::table::SourceMatch > const &matchList, int const flags, afw::math::StatisticsControl const &sctrl)
 
template afw::math::Statistics makeMatchStatisticsInRadians< afw::table::SourceMatch > (afw::image::Wcs const &wcs, std::vector< afw::table::SourceMatch > const &matchList, int const flags, afw::math::StatisticsControl const &sctrl)
 

Typedef Documentation

Definition at line 53 of file matchOptimisticB.h.

Function Documentation

PolynomialTransform lsst::meas::astrom::compose ( afw::geom::AffineTransform const &  t1,
PolynomialTransform const &  t2 
)

Return a PolynomialTransform that is equivalent to the composition t1(t2())

The returned composition would be exact in ideal arithmetic, but may suffer from significant round-off error for high-order polynomials.

Definition at line 254 of file PolynomialTransform.cc.

254  {
255  typedef afw::geom::AffineTransform AT;
256  PolynomialTransform result(t2.getOrder());
257  result._xCoeffs = t2._xCoeffs*t1[AT::XX] + t2._yCoeffs*t1[AT::XY];
258  result._yCoeffs = t2._xCoeffs*t1[AT::YX] + t2._yCoeffs*t1[AT::YY];
259  result._xCoeffs(0, 0) += t1[AT::X];
260  result._yCoeffs(0, 0) += t1[AT::Y];
261  return result;
262 }
PolynomialTransform lsst::meas::astrom::compose ( PolynomialTransform const &  t1,
afw::geom::AffineTransform const &  t2 
)

Return a PolynomialTransform that is equivalent to the composition t1(t2())

The returned composition would be exact in ideal arithmetic, but may suffer from significant round-off error for high-order polynomials.

Definition at line 264 of file PolynomialTransform.cc.

264  {
265  typedef afw::geom::AffineTransform AT;
266  int const order = t1.getOrder();
267  if (order < 1) {
268  PolynomialTransform t1a(1);
269  t1a._xCoeffs(0, 0) = t1._xCoeffs(0, 0);
270  t1a._yCoeffs(0, 0) = t1._yCoeffs(0, 0);
271  return compose(t1a, t2);
272  }
273  detail::BinomialMatrix binomial(order);
274  // For each of these, (e.g.) a[n] == pow(a, n)
275  auto const t2u = detail::computePowers(t2[AT::X], order);
276  auto const t2v = detail::computePowers(t2[AT::Y], order);
277  auto const t2uu = detail::computePowers(t2[AT::XX], order);
278  auto const t2uv = detail::computePowers(t2[AT::XY], order);
279  auto const t2vu = detail::computePowers(t2[AT::YX], order);
280  auto const t2vv = detail::computePowers(t2[AT::YY], order);
281  PolynomialTransform result(order);
282  for (int p = 0; p <= order; ++p) {
283  for (int m = 0; m <= p; ++m) {
284  for (int j = 0; j <= m; ++j) {
285  for (int q = 0; p + q <= order; ++q) {
286  for (int n = 0; n <= q; ++n) {
287  for (int k = 0; k <= n; ++k) {
288  double z = binomial(p,m) * t2u[p-m] * binomial(m,j) * t2uu[j] * t2uv[m-j] *
289  binomial(q,n) * t2v[q-n] * binomial(n,k) * t2vu[k] * t2vv[n-k];
290  result._xCoeffs(j + k, m + n - j - k) += t1._xCoeffs(p, q) * z;
291  result._yCoeffs(j + k, m + n - j - k) += t1._yCoeffs(p, q) * z;
292  } // k
293  } // n
294  } // q
295  } // j
296  } // m
297  } // p
298  return result;
299 }
PolynomialTransform compose(afw::geom::AffineTransform const &t1, PolynomialTransform const &t2)
Return a PolynomialTransform that is equivalent to the composition t1(t2())
metadata import lsst afw display as afwDisplay n
tuple m
Definition: lsstimport.py:48
void computePowers(Eigen::VectorXd &r, double x)
Fill an array with integer powers of x, so .
template<typename MatchT >
afw::math::Statistics lsst::meas::astrom::makeMatchStatistics ( std::vector< MatchT > const &  matchList,
int const  flags,
afw::math::StatisticsControl const &  sctrl = afw::math::StatisticsControl() 
)

Compute statistics of the distance field of a match list.

Parameters
[in]matchListlist of matchList between reference objects and sources; fields read:
  • distance: distance between source and reference object, in arbitrary units; the resulting statistics have the same units as distance
[in]flagswhat to calculate; OR constants such as lsst::afw::math::MEAN, MEANCLIP, STDDEV, MEDIAN, defined in lsst/afw/math/Statitics.h's Property enum
[in]sctrlstatistics configuration

Definition at line 33 of file makeMatchStatistics.cc.

37  {
38  if (matchList.empty()) {
39  throw LSST_EXCEPT(pexExcept::RuntimeError, "matchList is empty");
40  }
41  std::vector<double> val;
42  val.reserve(matchList.size());
43 
44  for (auto const & match: matchList) {
45  val.push_back(match.distance);
46  }
47  return afw::math::makeStatistics(val, flags, sctrl);
48 }
#define LSST_EXCEPT(type,...)
Create an exception with a given type and message and optionally other arguments (dependent on the ty...
Definition: Exception.h:46
Statistics makeStatistics(afwImage::Mask< afwImage::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl)
Specialization to handle Masks.
Definition: Statistics.cc:1107
ImageT val
Definition: CR.cc:159
template afw::math::Statistics lsst::meas::astrom::makeMatchStatistics< afw::table::ReferenceMatch > ( std::vector< afw::table::ReferenceMatch > const &  matchList,
int const  flags,
afw::math::StatisticsControl const &  sctrl 
)
template afw::math::Statistics lsst::meas::astrom::makeMatchStatistics< afw::table::SourceMatch > ( std::vector< afw::table::SourceMatch > const &  matchList,
int const  flags,
afw::math::StatisticsControl const &  sctrl 
)
template<typename MatchT >
afw::math::Statistics lsst::meas::astrom::makeMatchStatisticsInPixels ( afw::image::Wcs const &  wcs,
std::vector< MatchT > const &  matchList,
int const  flags,
afw::math::StatisticsControl const &  sctrl = afw::math::StatisticsControl() 
)

Compute statistics of on-detector radial separation for a match list, in pixels.

Parameters
[in]wcsWCS describing pixel to sky transformation
[in]matchListlist of matchList between reference objects and sources; fields read:
  • first: reference object; only the coord is read
  • second: source; only the centroid is read
[in]flagswhat to calculate; OR constants such as lsst::afw::math::MEAN, MEANCLIP, STDDEV, MEDIAN, defined in lsst/afw/math/Statitics.h's Property enum
[in]sctrlstatistics configuration

Definition at line 51 of file makeMatchStatistics.cc.

56  {
57  if (matchList.empty()) {
58  throw LSST_EXCEPT(pexExcept::RuntimeError, "matchList is empty");
59  }
60  std::vector<double> val;
61  val.reserve(matchList.size());
62 
63  for (auto const & match: matchList) {
64  auto refPtr = match.first;
65  auto srcPtr = match.second;
66  auto srcX = srcPtr->getX();
67  auto srcY = srcPtr->getY();
68  auto refPos = wcs.skyToPixel(refPtr->getCoord());
69  auto refX = refPos[0];
70  auto refY = refPos[1];
71  val.push_back(::hypot(srcX - refX, srcY - refY));
72  }
73  return afw::math::makeStatistics(val, flags, sctrl);
74 }
tbl::Key< int > wcs
#define LSST_EXCEPT(type,...)
Create an exception with a given type and message and optionally other arguments (dependent on the ty...
Definition: Exception.h:46
Statistics makeStatistics(afwImage::Mask< afwImage::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl)
Specialization to handle Masks.
Definition: Statistics.cc:1107
ImageT val
Definition: CR.cc:159
template afw::math::Statistics lsst::meas::astrom::makeMatchStatisticsInPixels< afw::table::ReferenceMatch > ( afw::image::Wcs const &  wcs,
std::vector< afw::table::ReferenceMatch > const &  matchList,
int const  flags,
afw::math::StatisticsControl const &  sctrl 
)
template afw::math::Statistics lsst::meas::astrom::makeMatchStatisticsInPixels< afw::table::SourceMatch > ( afw::image::Wcs const &  wcs,
std::vector< afw::table::SourceMatch > const &  matchList,
int const  flags,
afw::math::StatisticsControl const &  sctrl 
)
template<typename MatchT >
afw::math::Statistics lsst::meas::astrom::makeMatchStatisticsInRadians ( afw::image::Wcs const &  wcs,
std::vector< MatchT > const &  matchList,
int const  flags,
afw::math::StatisticsControl const &  sctrl = afw::math::StatisticsControl() 
)

Compute statistics of on-sky radial separation for a match list, in radians.

Parameters
[in]wcsWCS describing pixel to sky transformation
[in]matchListlist of matchList between reference objects and sources; fields read:
  • first: reference object; only the coord is read
  • second: source; only the centroid is read
[in]flagswhat to calculate; OR constants such as lsst::afw::math::MEAN, MEANCLIP, STDDEV, MEDIAN, defined in lsst/afw/math/Statitics.h's Property enum
[in]sctrlstatistics configuration

Definition at line 77 of file makeMatchStatistics.cc.

82  {
83  if (matchList.empty()) {
84  throw LSST_EXCEPT(pexExcept::RuntimeError, "matchList is empty");
85  }
86  std::vector<double> val;
87  val.reserve(matchList.size());
88 
89  for (auto const & match: matchList) {
90  auto refPtr = match.first;
91  auto srcPtr = match.second;
92  auto refCoord = refPtr->getCoord();
93  auto srcCoord = wcs.pixelToSky(srcPtr->getCentroid());
94  auto angSep = refCoord.angularSeparation(*srcCoord);
95  val.push_back(angSep.asRadians());
96  }
97  return afw::math::makeStatistics(val, flags, sctrl);
98 }
tbl::Key< int > wcs
#define LSST_EXCEPT(type,...)
Create an exception with a given type and message and optionally other arguments (dependent on the ty...
Definition: Exception.h:46
Statistics makeStatistics(afwImage::Mask< afwImage::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl)
Specialization to handle Masks.
Definition: Statistics.cc:1107
ImageT val
Definition: CR.cc:159
template afw::math::Statistics lsst::meas::astrom::makeMatchStatisticsInRadians< afw::table::ReferenceMatch > ( afw::image::Wcs const &  wcs,
std::vector< afw::table::ReferenceMatch > const &  matchList,
int const  flags,
afw::math::StatisticsControl const &  sctrl 
)
template afw::math::Statistics lsst::meas::astrom::makeMatchStatisticsInRadians< afw::table::SourceMatch > ( afw::image::Wcs const &  wcs,
std::vector< afw::table::SourceMatch > const &  matchList,
int const  flags,
afw::math::StatisticsControl const &  sctrl 
)
ProxyVector lsst::meas::astrom::makeProxies ( lsst::afw::table::SourceCatalog const &  sourceCat,
afw::image::Wcs const &  distortedWcs,
afw::image::Wcs const &  tanWcs 
)

Definition at line 491 of file matchOptimisticB.cc.

495  {
496  ProxyVector r;
497  r.reserve(sourceCat.size());
498  for (afwTable::SourceCatalog::const_iterator sourcePtr = sourceCat.begin();
499  sourcePtr != sourceCat.end(); ++sourcePtr) {
500  r.push_back(RecordProxy(sourcePtr,
501  tanWcs.skyToPixel(*distortedWcs.pixelToSky(sourcePtr->getCentroid()))));
502  }
503  return r;
504  }
Base::const_iterator const_iterator
Definition: SortedCatalog.h:49
std::vector< RecordProxy > ProxyVector
A wrapper around a SimpleRecord or SourceRecord that allows us to record a pixel position in a way th...
ProxyVector lsst::meas::astrom::makeProxies ( lsst::afw::table::SimpleCatalog const &  posRefCat,
afw::image::Wcs const &  tanWcs 
)

Definition at line 506 of file matchOptimisticB.cc.

509  {
510  auto coordKey = afwTable::CoordKey(posRefCat.getSchema()["coord"]);
511  ProxyVector r;
512  r.reserve(posRefCat.size());
513  for (afwTable::SimpleCatalog::const_iterator posRefPtr = posRefCat.begin();
514  posRefPtr != posRefCat.end(); ++posRefPtr) {
515  r.push_back(RecordProxy(posRefPtr, tanWcs.skyToPixel(posRefPtr->get(coordKey))));
516  }
517  return r;
518  }
Base::const_iterator const_iterator
Definition: SortedCatalog.h:49
std::vector< RecordProxy > ProxyVector
A wrapper around a SimpleRecord or SourceRecord that allows us to record a pixel position in a way th...
A FunctorKey used to get or set celestial coordinates from a pair of Angle keys.
Definition: aggregates.h:119
boost::shared_ptr< afw::image::TanWcs > lsst::meas::astrom::makeWcs ( SipForwardTransform const &  sipForward,
SipReverseTransform const &  sipReverse,
afw::coord::Coord const &  skyOrigin 
)

Create a new TAN SIP Wcs from a pair of SIP transforms and the sky origin.

Parameters
[in]sipForwardMapping from pixel coordinates to intermediate world coordinates.
[in]sipReverseMapping from intermediate world coordinates to pixel coordinates.
[in]skyOriginPosition of the gnomonic projection that maps sky coordinates to intermediate world coordinates (CRVAL).
Exceptions
pex::exceptions::InvalidParameterErrorif the forward and reverse SIP transforms have different CRPIX values or CD matrices.

Definition at line 149 of file SipTransform.cc.

153  {
154  if (!sipForward.getPixelOrigin().asEigen().isApprox(sipReverse.getPixelOrigin().asEigen())) {
155  std::ostringstream oss;
156  oss << "SIP forward and reverse transforms have inconsistent CRPIX: "
157  << sipForward.getPixelOrigin() << " != " << sipReverse.getPixelOrigin();
158  throw LSST_EXCEPT(
159  pex::exceptions::InvalidParameterError,
160  oss.str()
161  );
162  }
163  if (!sipForward.getCDMatrix().getMatrix().isApprox(sipReverse.getCDMatrix().getMatrix())) {
164  std::ostringstream oss;
165  oss << "SIP forward and reverse transforms have inconsistent CD matrix: "
166  << sipForward.getCDMatrix() << "\n!=\n" << sipReverse.getCDMatrix();
167  throw LSST_EXCEPT(
168  pex::exceptions::InvalidParameterError,
169  oss.str()
170  );
171  }
172  Eigen::MatrixXd sipA(sipForward.getPoly().getXCoeffs().asEigen());
173  Eigen::MatrixXd sipB(sipForward.getPoly().getYCoeffs().asEigen());
174  Eigen::MatrixXd sipAP(sipReverse.getPoly().getXCoeffs().asEigen());
175  Eigen::MatrixXd sipBP(sipReverse.getPoly().getYCoeffs().asEigen());
176  // TanWcs uses strings for coordinate systems, while Coord uses an enum.
177  // Frustratingly, there's no way to convert from the enum to the string.
178  std::string coordSys;
179  switch (skyOrigin.getCoordSystem()) {
180  case afw::coord::ICRS:
181  coordSys = "ICRS";
182  break;
183  case afw::coord::FK5:
184  coordSys = "FK5";
185  break;
186  default:
187  throw LSST_EXCEPT(
188  pex::exceptions::InvalidParameterError,
189  "Coordinate system not supported"
190  );
191  }
192  return std::make_shared<afw::image::TanWcs>(
193  skyOrigin.getPosition(afw::geom::degrees),
194  sipForward.getPixelOrigin(),
195  sipForward.getCDMatrix().getMatrix(),
196  sipA, sipB, sipAP, sipBP,
197  skyOrigin.getEpoch(),
198  coordSys
199  );
200 }
AngleUnit const degrees
Definition: Angle.h:91
#define LSST_EXCEPT(type,...)
Create an exception with a given type and message and optionally other arguments (dependent on the ty...
Definition: Exception.h:46
afwTable::ReferenceMatchVector lsst::meas::astrom::matchOptimisticB ( lsst::afw::table::SimpleCatalog const &  posRefCat,
lsst::afw::table::SourceCatalog const &  sourceCat,
MatchOptimisticBControl const &  control,
afw::image::Wcs const &  wcs,
int  posRefBegInd = 0,
bool  verbose = false 
)

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"

Parameters
[in]posRefCatcatalog of position reference stars; fields read:
  • "coord"
  • control.refFluxField
[in]sourceCatcatalog of detected sources; fields read:
  • "Centroid_x"
  • "Centroid_y"
  • control.refFluxField
[in]wcsestimated WCS
[in]controlcontrol object
[in]posRefBegIndindex of first start to use in posRefCat
[in]verbosetrue to print diagnostic information to std::cout
Returns
a list of matches; the d field may be set, but you should not rely on it

Definition at line 520 of file matchOptimisticB.cc.

527  {
528  control.validate();
529  if (posRefCat.empty()) {
530  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "no entries in posRefCat");
531  }
532  if (sourceCat.empty()) {
533  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "no entries in sourceCat");
534  }
535  if (posRefBegInd < 0) {
536  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "posRefBegInd < 0");
537  }
538  if (static_cast<size_t>(posRefBegInd) >= posRefCat.size()) {
539  throw LSST_EXCEPT(pexExcept::InvalidParameterError, "posRefBegInd too big");
540  }
541  double const maxRotationRad = afw::geom::degToRad(control.maxRotationDeg);
542 
543  CONST_PTR(afw::image::Wcs) tanWcs; // Undistorted Wcs, providing tangent plane
544  if (wcs.hasDistortion()) {
545  // Create an undistorted Wcs to project everything with
546  // We'll anchor it at the center of the area.
547  afw::geom::Extent2D srcCenter(0, 0);
548  for (auto iter = sourceCat.begin(); iter != sourceCat.end(); ++iter) {
549  srcCenter += afw::geom::Extent2D(iter->getCentroid());
550  }
551  srcCenter /= sourceCat.size();
552 
553  afw::geom::Extent3D refCenter(0, 0, 0);
554  for (auto iter = posRefCat.begin(); iter != posRefCat.end(); ++iter) {
555  refCenter += afw::geom::Extent3D(iter->getCoord().toIcrs().getVector());
556  }
557  refCenter /= posRefCat.size();
558 
559  tanWcs = std::make_shared<afw::image::Wcs>(
561  afw::geom::Point2D(srcCenter),
562  wcs.getCDMatrix()
563  );
564  }
565 
566  ProxyVector posRefProxyCat = makeProxies(posRefCat, tanWcs ? *tanWcs : wcs);
567  ProxyVector sourceProxyCat = makeProxies(sourceCat, wcs, tanWcs ? *tanWcs : wcs);
568 
569  // sourceSubCat contains at most the numBrightStars brightest sources, sorted by decreasing flux
570  ProxyVector sourceSubCat = selectPoint(
571  sourceProxyCat,
572  sourceCat.getSchema().find<double>(control.sourceFluxField).key,
573  control.numBrightStars);
574 
575  // posRefSubCat skips the initial posRefBegInd brightest reference objects and contains
576  // at most the next len(sourceSubCat) + 25 brightest reference objects, sorted by decreasing flux
577  ProxyVector posRefSubCat = selectPoint(
578  posRefProxyCat,
579  posRefCat.getSchema().find<double>(control.refFluxField).key,
580  sourceSubCat.size()+25,
581  posRefBegInd);
582  if (verbose) {
583  std::cout << "Catalog sizes: " << sourceSubCat.size() << " " << posRefSubCat.size() << std::endl;
584  }
585 
586  // Construct a list of pairs of position reference stars sorted by increasing separation
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]));
592  }
593  }
594  std::sort(posRefPairList.begin(), posRefPairList.end(), cmpPair);
595 
596  // Construct a list of pairs of sources sorted by increasing separation
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]));
602  }
603  }
604  std::sort(sourcePairList.begin(), sourcePairList.end(), cmpPair);
605 
607  afwTable::ReferenceMatchVector matPairSave;
608  std::vector<afwTable::ReferenceMatchVector> matPairCand;
609 
610  size_t const fullShapeSize = control.numPointsForShape - 1; // Max size of shape array
611  for (size_t ii = 0; ii < sourcePairList.size(); ii++) {
612  ProxyPair p = sourcePairList[ii];
613 
614  std::vector<ProxyPair> q = searchPair(posRefPairList, p,
615  control.matchingAllowancePix, maxRotationRad);
616 
617  // If candidate pairs are found
618  if (q.size() != 0) {
619 
620  std::vector<ProxyPair> srcMatPair;
621  std::vector<ProxyPair> catMatPair;
622 
623  // Go through candidate pairs
624  for (size_t l = 0; l < q.size(); l++) {
625  // sign matters, so don't use deltaAng; no need to wrap because
626  // the result is used with deltaAng later
627  double dpa = p.pa - q[l].pa;
628 
629  srcMatPair.clear();
630  catMatPair.clear();
631 
632  srcMatPair.push_back(p);
633  catMatPair.push_back(q[l]);
634 
635  if (verbose) {
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;
638  }
639 
640  for (size_t k = 0; k < sourceSubCat.size(); k++) {
641  if (p.first == sourceSubCat[k] || p.second == sourceSubCat[k]) continue;
642 
643  ProxyPair pp(p.first, sourceSubCat[k]);
644 
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);
650  if (verbose) {
651  std::cout << " p dist: " << pp.distance << " pa: " << pp.pa << std::endl;
652  std::cout << " r dist: " << (*r).distance << " pa: " << (*r).pa << std::endl;
653  }
654  if (srcMatPair.size() == fullShapeSize) {
655  break;
656  }
657  }
658  }
659 
660  bool goodMatch = false;
661  if (srcMatPair.size() == fullShapeSize) {
662  goodMatch = true;
663  for (size_t k = 1; k < catMatPair.size(); k++) {
664  if (catMatPair[0].first != catMatPair[k].first) {
665  goodMatch = false;
666  break;
667  }
668  }
669  }
670 
671  if (goodMatch && srcMatPair.size() == fullShapeSize) {
672 
673  ProxyVector srcMat;
674  ProxyVector catMat;
675 
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);
681  }
682 
683  boost::shared_array<double> coeff = polyfit(1, srcMat, catMat);
684 
685  if (verbose) {
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;
697  }
698  }
699 
700  double a = coeff[1];
701  double b = coeff[2];
702  double c = coeff[4];
703  double d = coeff[5];
704  afw::geom::Angle const theta(std::acos((a*b+c*d)/
705  (std::sqrt(a*a+c*c)*std::sqrt(b*b+d*d))),
707  if (verbose) {
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;
716  }
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) {
722  if (verbose) {
723  std::cout << "Bad; continuing" << std::endl;
724  }
725  continue;
726  } else {
727  double x0, y0, x1, y1;
728  int num = 0;
729  srcMat.clear();
730  catMat.clear();
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()) {
738  num++;
739  srcMat.push_back(sourceSubCat[i]);
740  catMat.push_back(*refObjDist.first);
741  if (verbose) {
742  std::cout << "Match: " << x0 << "," << y0 << " --> "
743  << x1 << "," << y1 << " <==> "
744  << refObjDist.first->getX() << "," << refObjDist.first->getY()
745  << std::endl;
746  }
747  }
748  }
749  if (num <= control.numPointsForShape) {
750  // Can get matrix = 0,0,0,0; everything matches a single catalog object
751  if (verbose) {
752  std::cout << "Insufficient initial matches; continuing" << std::endl;
753  }
754  continue;
755  }
756  coeff = polyfit(1, srcMat, catMat);
757  if (verbose) {
758  std::cout << "Coefficients from initial matching:" << std::endl;
759  for (size_t i = 0; i < 6; ++i) {
760  std::cout << coeff[i] << " ";
761  }
762  std::cout << std::endl;
763  }
764 
765  matPair = FinalVerify(coeff, posRefProxyCat, sourceProxyCat,
766  control.matchingAllowancePix, verbose);
767  if (verbose) {
768  std::cout << "Number of matches: " << matPair.size() << " vs " <<
769  control.minMatchedPairs << std::endl;
770  }
771  if (matPair.size() <= static_cast<std::size_t>(control.minMatchedPairs)) {
772  if (verbose) {
773  std::cout << "Insufficient final matches; continuing" << std::endl;
774  }
775  if (matPair.size() > matPairSave.size()) {
776  matPairSave = matPair;
777  }
778  continue;
779  } else {
780  if (verbose) {
781  std::cout << "Finish" << std::endl;
782  }
783  matPairCand.push_back(matPair);
784  if (matPairCand.size() == 3) {
785  goto END;
786  }
787  }
788  }
789  }
790  }
791  }
792  }
793 
794  END:
795  if (matPairCand.size() == 0) {
796  return matPairSave;
797  } else {
798  size_t nmatch = matPairCand[0].size();
799  afwTable::ReferenceMatchVector matPairRet = matPairCand[0];
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];
804  }
805  }
806  return matPairRet;
807  }
808  }
int iter
lsst::afw::geom::Point2D getPosition(lsst::afw::geom::AngleUnit unit=lsst::afw::geom::degrees) const
Return our contents in a Point2D object.
Definition: Coord.cc:477
AngleUnit const radians
constant with units of radians
Definition: Angle.h:90
Extent< double, 2 > Extent2D
Definition: Extent.h:361
tbl::Key< int > wcs
std::vector< ReferenceMatch > ReferenceMatchVector
Definition: fwd.h:97
lsst::afw::coord::IcrsCoord IcrsCoord
Definition: misc.h:37
int const x0
Definition: saturated.cc:45
Extent< double, 3 > Extent3D
Definition: Extent.h:362
if(width!=gim.getWidth()||height!=gim.getHeight()||x0!=gim.getX0()||y0!=gim.getY0())
Definition: saturated.cc:47
Point< double, 3 > Point3D
Definition: Point.h:289
lsst::afw::image::Wcs Wcs
Definition: Wcs.cc:61
double degToRad(long double angleInDegrees)
Definition: RaDecStr.cc:66
#define LSST_EXCEPT(type,...)
Create an exception with a given type and message and optionally other arguments (dependent on the ty...
Definition: Exception.h:46
std::vector< RecordProxy > ProxyVector
lsst::afw::geom::Angle Angle
Definition: misc.h:38
afw::table::Key< double > b
Point< double, 2 > Point2D
Definition: Point.h:288
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.
Definition: base.h:47
int const y0
Definition: saturated.cc:45