42 #include "Eigen/Cholesky" 58 if (shift ==
nullptr)
return false;
60 static const double eps = 1e-5;
62 double dx = shift->
coeff(0, 0, 0);
63 double dy = shift->
coeff(0, 0, 1);
65 static Point dumb(4000, 4000);
67 fabs(dumb.
x + dx - shift->
apply(dumb).x) < eps &&
fabs(dumb.
y + dy - shift->
apply(dumb).y) < eps)
75 Frame AstrometryTransform::apply(
Frame const &inputframe,
bool inscribed)
const {
77 double xtmin1, xtmax1, ytmin1, ytmax1;
78 apply(inputframe.
xMin, inputframe.
yMin, xtmin1, ytmin1);
79 apply(inputframe.
xMax, inputframe.
yMax, xtmax1, ytmax1);
83 double xtmin2, xtmax2, ytmin2, ytmax2;
84 apply(inputframe.
xMin, inputframe.
yMax, xtmin2, ytmax2);
85 apply(inputframe.
xMax, inputframe.
yMin, xtmax2, ytmin2);
89 if (inscribed)
return fr1 * fr2;
100 double eps = x * 0.01;
101 if (eps == 0) eps = 0.01;
104 apply(x + eps, y, dxdx, dydx);
108 apply(x, y + eps, dxdy, dydy);
111 return ((dxdx * dydy - dxdy * dydx) / (eps * eps));
118 const double step)
const {
122 apply(x, y, xp0, yp0);
125 apply(x + step, y, xp, yp);
126 derivative.
a11() = (xp - xp0) / step;
127 derivative.
a21() = (yp - yp0) / step;
128 apply(x, y + step, xp, yp);
129 derivative.
a12() = (xp - xp0) / step;
130 derivative.
a22() = (yp - yp0) / step;
136 const double step)
const {
137 Point outwhere = apply(where);
139 computeDerivative(where, der, step);
150 computeDerivative(in, der, 0.01);
151 double a11 = der.
A11();
152 double a22 = der.
A22();
153 double a21 = der.
A21();
154 double a12 = der.
A12();
155 res.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
156 res.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
157 res.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
161 void AstrometryTransform::transformErrors(
Point const &where,
const double *vIn,
double *vOut)
const {
163 computeDerivative(where, der, 0.01);
164 double a11 = der.
A11();
165 double a22 = der.
A22();
166 double a21 = der.
A21();
167 double a12 = der.
A12();
182 double b11 = a11 * vIn[xx] + a12 * vIn[xy];
183 double b22 = a21 * vIn[xy] + a22 * vIn[yy];
184 double b12 = a11 * vIn[xy] + a12 * vIn[yy];
185 double b21 = a21 * vIn[xx] + a22 * vIn[xy];
189 vOut[xx] = b11 * a11 + b12 * a12;
190 vOut[xy] = b11 * a21 + b12 * a22;
191 vOut[yy] = b21 * a21 + b22 * a22;
197 Point centerIn = apply(centerOut);
217 for (
std::size_t i = 0; i < npar; ++i) params[i] = paramRef(i);
220 void AstrometryTransform::offsetParams(Eigen::VectorXd
const &delta) {
222 for (
std::size_t i = 0; i < npar; ++i) paramRef(i) += delta[i];
225 double AstrometryTransform::paramRef(Eigen::Index
const)
const {
227 std::string(
"AstrometryTransform::paramRef should never be called "));
230 double &AstrometryTransform::paramRef(Eigen::Index
const) {
232 "AstrometryTransform::paramRef should never be called ");
235 void AstrometryTransform::paramDerivatives(
Point const &,
double *,
double *)
const {
237 "AstrometryTransform::paramDerivatives() should never be called ");
241 transform.
dump(stream);
252 "AstrometryTransform::write, something went wrong for file " + fileName);
258 "AstrometryTransform::write(ostream), should never be called. MEans that it is missing in some " 278 void apply(
const double xIn,
const double yIn,
double &xOut,
double &yOut)
const;
293 return _direct->clone();
309 _direct = direct->
clone();
310 _roughInverse = _direct->roughInverse(region);
311 precision2 = precision * precision;
316 _direct = model._direct->clone();
317 _roughInverse = model._roughInverse->clone();
318 precision2 = model.precision2;
324 _direct = model._direct->clone();
325 _roughInverse = model._roughInverse->clone();
326 precision2 = model.precision2;
331 Point outGuess = _roughInverse->apply(in);
338 Point inGuess = _direct->apply(outGuess);
339 _direct->computeDerivative(outGuess, directDer);
341 double xShift, yShift;
342 reverseDer.
apply(xIn - inGuess.
x, yIn - inGuess.
y, xShift, yShift);
343 outGuess.
x += xShift;
344 outGuess.
y += yShift;
345 move2 = xShift * xShift + yShift * yShift;
346 }
while ((move2 > precision2) && (loop < maxloop));
347 if (loop == maxloop)
LOGLS_WARN(_log,
"Problems applying AstrometryTransformInverse at " << in);
353 stream <<
" AstrometryTransformInverse of :" <<
endl << *_direct <<
endl;
358 "Cannot fit a AstrometryTransformInverse. Use StarMatchList::inverseTransform instead.");
380 void apply(
const double xIn,
const double yIn,
double &xOut,
double &yOut)
const;
392 _first = first.
clone();
393 _second = second.
clone();
397 double &yOut)
const {
399 _first->apply(xIn, yIn, xout, yout);
400 _second->apply(xout, yout, xOut, yOut);
404 _first->dump(stream);
405 _second->dump(stream);
410 return _first->fit(starMatchList);
414 return std::make_unique<AstrometryTransformComposition>(*_second, *_first);
430 if (composition ==
nullptr)
431 return std::make_unique<AstrometryTransformComposition>(left, right);
438 const double)
const {
443 const double)
const {
449 return std::make_shared<ast::UnitMap>(2);
453 stream <<
"AstrometryTransformIdentity 1" <<
endl;
461 " AstrometryTransformIdentity::read : format is not 1 ");
469 _nterms = (order + 1) * (order + 2) / 2;
472 _coeffs.
resize(2 * _nterms, 0.);
487 for (
double x = frame.
xMin + step / 2;
x <= frame.
xMax;
x += step)
488 for (
double y = frame.
yMin + step / 2;
y <= frame.
yMax;
y += step) {
489 auto pix = std::make_shared<BaseStar>(
x,
y, 0, 0);
491 transform->
apply(x, y, xtr, ytr);
492 auto tp = std::make_shared<BaseStar>(xtr, ytr, 0, 0);
507 double xStart = domain.
xMin;
508 double yStart = domain.
yMin;
509 double xStep = domain.
getWidth() / (nSteps + 1);
510 double yStep = domain.
getHeight() / (nSteps + 1);
522 poly.
fit(starMatchList);
526 void AstrometryTransformPolynomial::computeMonomials(
double xIn,
double yIn,
double *monomial)
const {
540 for (
std::size_t iy = 0; iy <= _order - ix; ++iy) {
541 monomial[k] = xx * yy;
552 _nterms = (_order + 1) * (_order + 2) / 2;
557 _coeffs.
resize(2 * _nterms);
560 for (
std::size_t k = 0; k < _nterms; ++k) _coeffs[k] = 0;
564 _coeffs[k] = old_coeffs[k];
565 _coeffs[k + _nterms] = old_coeffs[k + old_nterms];
571 double &yOut)
const {
581 double monomials[_nterms];
582 computeMonomials(xIn, yIn, monomials);
586 const double *c = &_coeffs[0];
587 const double *pm = &monomials[0];
589 for (
int k = _nterms; k--;) xOut += (*(pm++)) * (*(c++));
591 for (
int k = _nterms; k--;) yOut += (*(pm++)) * (*(c++));
600 derivative.
dx() = derivative.
dy() = 0;
604 double dermx[2 * _nterms];
605 double *dermy = dermx + _nterms;
606 double xin = where.
x;
607 double yin = where.
y;
614 dermx[k] = ix * xxm1;
618 for (
std::size_t iy = 1; iy <= _order - ix; ++iy) {
619 dermx[k] = ix * xxm1 * yym1 * yin;
620 dermy[k] = iy * xx * yym1;
625 if (ix >= 1) xxm1 *= xin;
631 const double *mx = &dermx[0];
632 const double *my = &dermy[0];
633 const double *c = &_coeffs[0];
635 double a11 = 0, a12 = 0;
636 for (
int k = _nterms; k--;) {
637 a11 += (*(mx++)) * (*c);
638 a12 += (*(my++)) * (*(c++));
640 derivative.
a11() = a11;
641 derivative.
a12() = a12;
643 double a21 = 0, a22 = 0;
646 for (
int k = _nterms; k--;) {
647 a21 += (*(mx++)) * (*c);
648 a22 += (*(my++)) * (*(c++));
650 derivative.
a21() = a21;
651 derivative.
a22() = a22;
667 double monomials[_nterms];
671 double dermx[2 * _nterms];
672 double *dermy = dermx + _nterms;
681 dermx[k] = ix * xxm1;
687 for (
std::size_t iy = 1; iy <= _order - ix; ++iy) {
688 monomials[k] = xx * yy;
689 dermx[k] = ix * xxm1 * yy;
690 dermy[k] = iy * xx * yym1;
696 if (ix >= 1) xxm1 *= xin;
700 double xout = 0, yout = 0;
701 const double *c = &_coeffs[0];
702 const double *pm = &monomials[0];
703 for (
int k = _nterms; k--;) xout += (*(pm++)) * (*(c++));
705 for (
int k = _nterms; k--;) yout += (*(pm++)) * (*(c++));
711 const double *mx = &dermx[0];
712 const double *my = &dermy[0];
713 double a11 = 0, a12 = 0;
714 for (
int k = _nterms; k--;) {
715 a11 += (*(mx++)) * (*c);
716 a12 += (*(my++)) * (*(c++));
719 double a21 = 0, a22 = 0;
722 for (
int k = _nterms; k--;) {
723 a21 += (*(mx++)) * (*c);
724 a22 += (*(my++)) * (*(c++));
728 res.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
729 res.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
730 res.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
740 assert((degX + degY <= _order) && whichCoord < 2);
744 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
749 assert((degX + degY <= _order) && whichCoord < 2);
750 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
756 assert(whichCoord < 2);
757 if (degX + degY <= _order)
758 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
764 assert(i < 2 * Eigen::Index(_nterms));
769 assert(i < 2 * Eigen::Index(_nterms));
775 computeMonomials(where.
x, where.
y, dx);
777 dy[_nterms + k] = dx[k];
778 dx[_nterms + k] = dy[k] = 0;
785 if (powX + powY) ss <<
"*";
786 if (powX > 0) ss <<
"x";
787 if (powX > 1) ss <<
"^" << powX;
788 if (powY > 0) ss <<
"y";
789 if (powY > 1) ss <<
"^" << powY;
803 if (p +
py != 0) stream <<
" + ";
804 stream <<
coeff(p -
py,
py, ic) << monomialString(p -
py,
py);
808 if (_order > 0) stream <<
" Linear determinant = " <<
determinant() <<
endl;
831 for (
auto it = starMatchList.
begin(); it != starMatchList.
end(); ++it) {
850 static double sq(
double x) {
return x *
x; }
852 double AstrometryTransformPolynomial::computeFit(
StarMatchList const &starMatchList,
854 const bool useErrors) {
855 Eigen::MatrixXd A(2 * _nterms, 2 * _nterms);
857 Eigen::VectorXd B(2 * _nterms);
860 double monomials[_nterms];
861 for (
auto it = starMatchList.
begin(); it != starMatchList.
end(); ++it) {
866 double wxx, wyy, wxy;
868 computeMonomials(point1.
x, point1.
y, monomials);
871 double vxx = (tr1.
vx + point2.
vx);
872 double vyy = (tr1.
vy + point2.
vy);
873 double vxy = (tr1.
vxy + point2.
vxy);
874 double det = vxx * vyy - vxy * vxy;
883 double resx = point2.
x - tr1.
x;
884 double resy = point2.
y - tr1.
y;
885 sumr2 += wxx * sq(resx) + wyy * sq(resy) + 2 * wxy * resx * resy;
887 double bxcoeff = wxx * resx + wxy * resy;
888 double bycoeff = wyy * resy + wxy * resx;
891 A(i, j) += wxx * monomials[i] * monomials[j];
892 A(i + _nterms, j + _nterms) += wyy * monomials[i] * monomials[j];
893 A(j, i + _nterms) = A(i, j + _nterms) += wxy * monomials[i] * monomials[j];
895 B(j) += bxcoeff * monomials[j];
896 B(j + _nterms) += bycoeff * monomials[j];
899 Eigen::LDLT<Eigen::MatrixXd, Eigen::Lower> factor(A);
901 if (factor.info() != Eigen::Success) {
902 LOGL_ERROR(_log,
"AstrometryTransformPolynomial::fit could not factorize");
906 Eigen::VectorXd sol = factor.solve(B);
907 for (
std::size_t k = 0; k < 2 * _nterms; ++k) _coeffs[k] += sol(k);
908 if (starMatchList.
size() == _nterms)
return 0;
909 return (sumr2 - B.dot(sol));
913 if (starMatchList.
size() < _nterms) {
914 LOGLS_FATAL(_log,
"AstrometryTransformPolynomial::fit trying to fit a polynomial transform of order " 915 << _order <<
" with only " << starMatchList.
size() <<
" matches.");
921 computeFit(starMatchList, conditionner,
false);
922 computeFit(starMatchList, conditionner,
true);
923 double chi2 = computeFit(starMatchList, conditionner,
true);
925 (*this) = (*this) * conditionner;
926 if (starMatchList.
size() == _nterms)
return 0;
933 return std::make_unique<AstrometryTransformLinear>((*
this) * (right));
935 return std::make_unique<AstrometryTransformPolynomial>((*this) * (right));
953 PolyXY(
const int order) : order(order), nterms((order + 1) * (order + 2) / 2) {
961 : order(transform.
getOrder()), nterms((order + 1) * (order + 2) / 2), coeffs(nterms, 0L) {
967 assert(powX + powY <= order);
968 return coeffs.
at((powX + powY) * (powX + powY + 1) / 2 + powY);
972 assert(powX + powY <= order);
973 return coeffs.
at((powX + powY) * (powX + powY + 1) / 2 + powY);
1005 result.
coeff(i1 + i2, j1 + j2) += p1.
coeff(i1, j1) * p2.
coeff(i2, j2);
1013 powers[0].coeff(0, 0) = 1L;
1023 computePowers(polyX, pdeg, pXPowers);
1024 computePowers(polyY, pdeg, pYPowers);
1027 result += polyXY.
coeff(px,
py) * product(pXPowers.
at(px), pYPowers.
at(
py));
1044 PolyXY rx(composition(plx, prx, pry));
1045 PolyXY ry(composition(ply, prx, pry));
1049 for (
std::size_t px = 0; px <= result._order; ++px)
1059 if (_order >= right._order) {
1062 for (
std::size_t j = 0; j <= right._order - i; ++j) {
1068 return (right + (*
this));
1075 for (
std::size_t j = 0; j <= res._order - i; ++j) {
1084 return std::make_shared<ast::PolyMap>(toAstPolyMapCoefficients(), inverse->toAstPolyMapCoefficients());
1088 s <<
" AstrometryTransformPolynomial 1" <<
endl;
1089 s <<
"order " << _order << endl;
1092 for (
std::size_t k = 0; k < 2 * _nterms; ++k) s << _coeffs[k] <<
' ';
1094 s << setprecision(oldprec);
1102 " AstrometryTransformPolynomial::read : format is not 1 ");
1105 s >> order >> _order;
1106 if (order !=
"order")
1108 " AstrometryTransformPolynomial::read : expecting \"order\" and found " + order);
1110 for (
std::size_t k = 0; k < 2 * _nterms; ++k) s >> _coeffs[k];
1113 ndarray::Array<double, 2, 2> AstrometryTransformPolynomial::toAstPolyMapCoefficients()
const {
1115 ndarray::Array<double, 2, 2>
result = ndarray::allocate(ndarray::makeVector(nCoeffs,
std::size_t(4)));
1117 ndarray::Size k = 0;
1118 for (
std::size_t iCoord = 0; iCoord < 2; ++iCoord) {
1121 result[k][0] =
coeff(p -
py,
py, iCoord);
1122 result[k][1] = iCoord + 1;
1123 result[k][2] = p -
py;
1133 Frame const &domain,
1134 double const precision,
1138 double xStart = domain.
xMin;
1139 double yStart = domain.
yMin;
1140 double xStep = domain.
getWidth() / (nSteps - 1);
1141 double yStep = domain.
getHeight() / (nSteps - 1);
1144 Point in(xStart + i * xStep, yStart + j * yStep);
1155 for (order = 1; order <= maxOrder; ++order) {
1157 auto success = poly->fit(sm);
1158 if (success == -1) {
1160 errMsg <<
"Cannot fit a polynomial of order " << order <<
" with " << nSteps <<
"^2 points";
1165 for (
auto const &i : sm) chi2 += i.point2.computeDist2(poly->apply((i.point1)));
1166 LOGLS_TRACE(_log,
"inversePoly order " << order <<
": " << chi2 <<
" / " << npairs <<
" = " 1167 << chi2 / npairs <<
" < " << precision * precision);
1169 if (chi2 / npairs < precision * precision)
break;
1172 if (chi2 > oldChi2) {
1173 LOGLS_WARN(_log,
"inversePolyTransform: chi2 increases (" 1174 << chi2 <<
" > " << oldChi2 <<
"); ending fit with order: " << order);
1175 LOGLS_WARN(_log,
"inversePolyTransform: requested precision not reached: " 1176 << chi2 <<
" / " << npairs <<
" = " << chi2 / npairs <<
" < " 1177 << precision * precision);
1188 if (order > maxOrder)
1189 LOGLS_WARN(_log,
"inversePolyTransform: Reached max order without reaching requested precision: " 1190 << chi2 <<
" / " << npairs <<
" = " << chi2 / npairs <<
" < " 1191 << precision * precision);
1201 const double A12,
const double A21,
const double A22)
1215 "Trying to build a AstrometryTransformLinear from a higher order transform. Aborting. ");
1235 const double)
const {
1237 derivative.
coeff(0, 0, 0) = 0;
1238 derivative.
coeff(0, 0, 1) = 0;
1256 double d = (a11 * a22 - a12 *
a21);
1259 "AstrometryTransformLinear::invert singular transformation: transform contents will be " 1260 "dumped to stderr.");
1273 const Frame &)
const {
1284 LOGLS_FATAL(_log,
"AstrometryTransformLinearShift::fit trying to fit a linear transform with only " 1285 << npairs <<
" matches.");
1291 Eigen::VectorXd B(2);
1293 Eigen::MatrixXd A(2, 2);
1296 for (
auto const &it : starMatchList) {
1297 FatPoint const &point1 = it.point1;
1298 FatPoint const &point2 = it.point2;
1299 double deltax = point2.
x - point1.
x;
1300 double deltay = point2.
y - point1.
y;
1301 double vxx = point1.
vx + point2.
vx;
1302 double vyy = point1.
vy + point2.
vy;
1303 double vxy = point1.
vxy + point2.
vxy;
1304 double det = vxx * vyy - vxy * vxy;
1305 double wxx = vyy / det;
1306 double wyy = vxx / det;
1307 double wxy = -vxy / det;
1308 B(0) += deltax * wxx + wxy * deltay;
1309 B(1) += deltay * wyy + wxy * deltax;
1313 sumr2 += deltax * deltax * wxx + deltay * deltay * wyy + 2. * wxy * deltax * deltay;
1315 double det = A(0, 0) * A(1, 1) - A(0, 1) * A(1, 0);
1316 if (det <= 0)
return -1;
1317 double tmp = A(0, 0);
1318 A(0, 0) = A(1, 1) / det;
1319 A(1, 1) = tmp / det;
1320 A(0, 1) = A(1, 0) = -A(0, 1) / det;
1321 Eigen::VectorXd sol = A * B;
1323 return (sumr2 - sol.dot(B));
1327 const double scaleFactor) {
1328 double c = scaleFactor *
std::cos(angleRad);
1329 double s = scaleFactor *
std::sin(angleRad);
1335 Point a_point(0., 0.);
1336 if (center) a_point = *center;
1340 dx() = a_point.
x -
Dx();
1341 dy() = a_point.
y -
dy();
1344 static double deg2rad(
double degree) {
return degree *
M_PI / 180.; }
1346 static double rad2deg(
double rad) {
return rad * 180. /
M_PI; }
1369 linPixelToTan = pixToTan;
1370 ra0 = deg2rad(tangentPoint.
x);
1371 dec0 = deg2rad(tangentPoint.
y);
1408 LOGL_WARN(_log,
"No sidereal coordinates at pole!");
1417 if (rat < 0.0) rat += (2. *
M_PI);
1419 xOut = rad2deg(rat);
1420 yOut = rad2deg(dect);
1440 return Point(inverse.
Dx(), inverse.
Dy());
1446 : _skyWcs(skyWcs) {}
1449 auto const outCoord = _skyWcs->pixelToSky(
geom::Point2D(xIn, yIn));
1450 xOut = outCoord[0].asDegrees();
1451 yOut = outCoord[1].asDegrees();
1455 stream <<
"AstrometryTransformSkyWcs(" << *_skyWcs <<
")";
1470 :
BaseTanWcs(pixToTan, tangentPoint, corrections) {}
1478 return std::make_unique<TanPixelToRaDec>((*this) * (right));
1491 if (
corr !=
nullptr) {
1492 LOGL_WARN(_log,
"You are inverting a TanPixelToRaDec with corrections.");
1493 LOGL_WARN(_log,
"The inverse you get ignores the corrections!");
1520 double &yTangentPlane)
const {
1524 double xtmp = xTangentPlane;
1525 double ytmp = yTangentPlane;
1526 corr->apply(xtmp, ytmp, xTangentPlane, yTangentPlane);
1538 stream <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1540 stream <<
" crpix " << crpix.
x <<
' ' << crpix.
y <<
endl;
1541 if (
corr) stream <<
"PV correction: " <<
endl << *
corr;
1554 "TanPixelToRaDec::fit is NOT implemented (although it is doable)) ");
1562 :
BaseTanWcs(pixToTan, tangentPoint, corrections) {}
1578 const Frame ®ion)
1591 double &yTangentPlane)
const {
1595 corr->apply(xPixel, yPixel, xtmp, ytmp);
1609 stream <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1611 stream <<
" crpix " << crpix.
x <<
' ' << crpix.
y <<
endl;
1612 if (
corr) stream <<
"PV correction: " <<
endl << *
corr;
1625 "TanSipPixelToRaDec::fit is NOT implemented (although it is doable)) ");
1632 : linTan2Pix(tan2Pix) {
1639 ra0 = deg2rad(tangentPoint.
x);
1640 dec0 = deg2rad(tangentPoint.
y);
1672 double ra = deg2rad(in.
x);
1673 double dec = deg2rad(in.
y);
1674 if (ra - ra0 >
M_PI) ra -= (2. *
M_PI);
1675 if (ra - ra0 < -
M_PI) ra += (2. *
M_PI);
1683 double l = sinda * coss;
1684 double m = sins * sin0 + coss * cos0 * cosda;
1686 m = (sins * cos0 - coss * sin0 * cosda) / m;
1690 sq(sin0) - sq(coss) + sq(coss * cos0) * (1 + sq(cosda)) + 2 * sins * sin0 * coss * cos0 * cosda;
1691 double a11 = coss * (cosda * sins * sin0 + coss * cos0) / deno;
1692 double a12 = -sinda * sin0 / deno;
1693 double a21 = coss * sinda * sins / deno;
1694 double a22 = cosda / deno;
1697 tmp.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
1698 tmp.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
1699 tmp.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
1709 double ra = deg2rad(xIn);
1710 double dec = deg2rad(yIn);
1711 if (ra - ra0 >
M_PI) ra -= (2. *
M_PI);
1712 if (ra - ra0 < -
M_PI) ra += (2. *
M_PI);
1717 double l =
std::sin(ra - ra0) * coss;
1718 double m = sins * sin0 + coss * cos0 *
std::cos(ra - ra0);
1720 m = (sins * cos0 - coss * sin0 *
std::cos(ra - ra0)) / m;
1724 linTan2Pix.
apply(l, m, xOut, yOut);
1733 stream <<
" tan2pix " << linTan2Pix <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1752 "TanRaDecToPixel::fit is NOT implemented (although it is doable)) ");
1759 : _userFun(userFun), _userData(userData) {}
1762 _userFun(xIn, yIn, xOut, yOut, _userData);
1766 stream <<
"UserTransform with user function @ " << _userFun <<
"and userData@ " << _userData <<
endl;
1771 "UserTransform::fit is NOT implemented (and will never be)) ");
1785 " astrometryTransformRead : cannot open " + fileName);
1801 "astrometryTransformRead : could not find a AstrometryTransformtype");
1802 if (type ==
"AstrometryTransformIdentity") {
1806 }
else if (type ==
"AstrometryTransformPolynomial") {
1812 " astrometryTransformRead : No reader for AstrometryTransform type " + type);
#define LOGLS_WARN(logger, message)
Log a warn-level message using an iostream-based interface.
std::unique_ptr< AstrometryTransform > inverseTransform(const double precision, const Frame ®ion) const
Inverse transform: returns a TanRaDecToPixel if there are no corrections, or the iterative solver if ...
def write(self, patchRef, catalog)
Write the output.
std::unique_ptr< AstrometryTransform > inverseTransform(const double precision, const Frame ®ion) const
Inverse transform: returns a TanRaDecToPixel if there are no corrections, or the iterative solver if ...
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
void() AstrometryTransformFun(const double, const double, double &, double &, const void *)
signature of the user-provided routine that actually does the coordinate transform for UserTransform...
The transformation that handles pixels to sideral transformations (Gnomonic, possibly with polynomial...
A hanger for star associations.
AstrometryTransformLinear linPixelToTan
Low-level polynomials (including special polynomials) in C++.
std::unique_ptr< AstrometryTransform > composeAndReduce(AstrometryTransformLinear const &right) const
Return a reduced composition of newTransform = this(right()), or nullptr if it cannot be reduced...
std::unique_ptr< AstrometryTransform > clone() const
returns a copy (allocated by new) of the transformation.
bool isIntegerShift(const AstrometryTransform *transform)
Shorthand test to tell if a transform is a simple integer shift.
double fit(StarMatchList const &starMatchList)
fits a transform to a std::list of Point pairs (p1,p2, the Point fields in StarMatch).
table::PointKey< double > crpix
AstrometryTransformPolynomial getPixelToTangentPlane() const
the transformation from pixels to tangent plane (degrees)
double fit(StarMatchList const &starMatchList)
Not implemented yet, because we do it otherwise.
virtual void pixToTangentPlane(double xPixel, double yPixel, double &xTangentPlane, double &yTangentPlane) const =0
Transform from pixels to tangent plane (degrees)
void apply(const double xIn, const double yIn, double &xOut, double &yOut) const
Transform pixels to ICRS RA, Dec in degrees.
double xMin
coordinate of boundary.
TanPixelToRaDec operator*(AstrometryTransformLinear const &right) const
composition with AstrometryTransformLinear
#define LOGL_ERROR(logger, message...)
Log a error-level message using a varargs/printf style interface.
std::shared_ptr< AstrometryTransformPolynomial > inversePolyTransform(AstrometryTransform const &forward, Frame const &domain, double const precision, std::size_t maxOrder=9, std::size_t nSteps=50)
Approximate the inverse by a polynomial, to some precision.
long double & coeff(std::size_t powX, std::size_t powY)
A Point with uncertainties.
void setCorrections(std::unique_ptr< AstrometryTransformPolynomial > corrections)
Assign the correction polynomial (what it means is left to derived classes)
std::ostream & operator<<(std::ostream &os, CameraSysPrefix const &detSysPrefix)
std::unique_ptr< AstrometryTransform > roughInverse(const Frame ®ion) const
Overload the "generic routine" (available for all AstrometryTransform types.
std::unique_ptr< AstrometryTransformPolynomial > corr
LSST DM logging module built on log4cxx.
AstrometryTransformLinear getLinPart() const
The Linear part (corresponding to CD's and CRPIX's)
double getHeight() const
size along y axis
TanPixelToRaDec inverted() const
exact typed inverse:
Reports attempts to access elements using an invalid key.
virtual char const * what(void) const noexcept
Return a character string summarizing this exception.
void setTangentPoint(Point const &tangentPoint)
Resets the projection (or tangent) point.
std::unique_ptr< AstrometryTransform > roughInverse(const Frame ®ion) const
Overload the "generic routine" (available for all AstrometryTransform types.
AstrometryTransformLinear getLinPart() const
The Linear part (corresponding to CD's and CRPIX's)
#define LOGL_FATAL(logger, message...)
Log a fatal-level message using a varargs/printf style interface.
virtual void pixToTangentPlane(double xPixel, double yPixel, double &xTangentPlane, double &yTangentPlane) const
transforms from pixel space to tangent plane (degrees)
rectangle with sides parallel to axes.
AstrometryTransformLinear normalizeCoordinatesTransform(const Frame &frame)
Returns the transformation that maps the input frame along both axes to [-1,1].
void dump(std::ostream &stream) const
dumps the transform coefficients to stream.
A base class for image defects.
#define LOGLS_TRACE(logger, message)
Log a trace-level message using an iostream-based interface.
AstrometryTransformPolynomial getPixelToTangentPlane() const
the transformation from pixels to tangent plane (degrees)
std::unique_ptr< AstrometryTransform > clone() const
returns a copy (allocated by new) of the transformation.
Point getCrPix() const
Get the pixel origin of the WCS (CRPIX in FITS WCS terminology, but zero-based)
void dump(std::ostream &stream) const
dumps the transform coefficients to stream.
std::unique_ptr< AstrometryTransform > compose(AstrometryTransform const &left, AstrometryTransform const &right)
Returns a pointer to a composition of transforms, representing left(right()).
PolyXY(AstrometryTransformPolynomial const &transform, std::size_t whichCoord)
def getParams(record, galType='sersic')
table::Key< table::Array< int > > degree
This one is the Tangent Plane (called gnomonic) projection (from celestial sphere to tangent plane) ...
T dynamic_pointer_cast(T... args)
void apply(const double xIn, const double yIn, double &xOut, double &yOut) const
#define LOGL_WARN(logger, message...)
Log a warn-level message using a varargs/printf style interface.
Reports errors in the logical structure of the program.
std::unique_ptr< AstrometryTransform > clone() const
returns a copy (allocated by new) of the transformation.
double fit(StarMatchList const &starMatchList)
Not implemented yet, because we do it otherwise.
double getWidth() const
size along x axis
std::unique_ptr< AstrometryTransform > inverseTransform(const double precision, const Frame ®ion) const
Inverse transform: returns a TanPixelToRaDec.
BaseTanWcs(AstrometryTransformLinear const &pixToTan, Point const &tangentPoint, const AstrometryTransformPolynomial *corrections=nullptr)
void transformPosAndErrors(const FatPoint &in, FatPoint &out) const
transform with analytical derivatives
std::unique_ptr< AstrometryTransform > astrometryTransformRead(const std::string &fileName)
The virtual constructor from a file.
Point getCenter() const
Center of the frame.
std::size_t getOrder() const
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
void dump(std::ostream &stream) const
dumps the transform coefficients to stream.
virtual void pixToTangentPlane(double xPixel, double yPixel, double &xTangentPlane, double &yTangentPlane) const
transforms from pixel space to tangent plane (degrees)
Point getTangentPoint() const
Get the sky origin (CRVAL in FITS WCS terminology) in degrees.
Reports invalid arguments.
#define LOGLS_FATAL(logger, message)
Log a fatal-level message using an iostream-based interface.
TanRaDecToPixel inverted() const
approximate inverse : it ignores corrections;
#define LOG_GET(logger)
Returns a Log object associated with logger.
T setprecision(T... args)
void operator=(const BaseTanWcs &original)
Reports errors that are due to events beyond the control of the program.
Point getTangentPoint() const
tangent point coordinates (degrees)
T emplace_back(T... args)
long double coeff(std::size_t powX, std::size_t powY) const