17 #include "Eigen/Cholesky" 24 LOG_LOGGER _log =
LOG_GET(
"jointcal.Gtransfo");
31 return (dynamic_cast<const GtransfoIdentity *>(gtransfo) !=
nullptr);
36 if (shift ==
nullptr)
return false;
38 static const double eps = 1e-5;
40 double dx = shift->
coeff(0, 0, 0);
41 double dy = shift->
coeff(0, 0, 1);
43 static Point dumb(4000, 4000);
45 fabs(dumb.
x + dx - shift->
apply(dumb).x) < eps &&
fabs(dumb.
y + dy - shift->
apply(dumb).y) < eps)
57 double Gtransfo::getJacobian(
const double x,
const double y)
const {
59 double eps = x * 0.01;
60 if (eps == 0) eps = 0.01;
63 apply(x + eps, y, dxdx, dydx);
67 apply(x, y + eps, dxdy, dydy);
70 return ((dxdx * dydy - dxdy * dydx) / (eps * eps));
76 void Gtransfo::computeDerivative(
const Point &where,
GtransfoLin &derivative,
const double step)
const {
80 apply(x, y, xp0, yp0);
83 apply(x + step, y, xp, yp);
84 derivative.
a11() = (xp - xp0) / step;
85 derivative.
a21() = (yp - yp0) / step;
86 apply(x, y + step, xp, yp);
87 derivative.
a12() = (xp - xp0) / step;
88 derivative.
a22() = (yp - yp0) / step;
93 GtransfoLin Gtransfo::linearApproximation(
const Point &where,
const double step)
const {
94 Point outwhere = apply(where);
96 computeDerivative(where, der, step);
106 computeDerivative(in, der, 0.01);
107 double a11 = der.
A11();
108 double a22 = der.
A22();
109 double a21 = der.
A21();
110 double a12 = der.
A12();
111 res.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
112 res.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
113 res.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
117 void Gtransfo::transformErrors(
const Point &where,
const double *vIn,
double *vOut)
const {
119 computeDerivative(where, der, 0.01);
120 double a11 = der.
A11();
121 double a22 = der.
A22();
122 double a21 = der.
A21();
123 double a12 = der.
A12();
138 double b11 = a11 * vIn[xx] + a12 * vIn[xy];
139 double b22 = a21 * vIn[xy] + a22 * vIn[yy];
140 double b12 = a11 * vIn[xy] + a12 * vIn[yy];
141 double b21 = a21 * vIn[xx] + a22 * vIn[xy];
145 vOut[xx] = b11 * a11 + b12 * a12;
146 vOut[xy] = b11 * a21 + b12 * a22;
147 vOut[yy] = b21 * a21 + b22 * a22;
153 Point centerIn = apply(centerOut);
155 computeDerivative(centerOut, der,
sqrt(region.
getArea()) / 5.);
170 void Gtransfo::getParams(
double *params)
const {
171 int npar = getNpar();
172 for (
int i = 0; i < npar; ++i) params[i] = paramRef(i);
175 void Gtransfo::offsetParams(Eigen::VectorXd
const &delta) {
176 int npar = getNpar();
177 for (
int i = 0; i < npar; ++i) paramRef(i) += delta[i];
180 double Gtransfo::paramRef(
const int)
const {
182 std::string(
"Gtransfo::paramRef should never be called "));
185 double &Gtransfo::paramRef(
const int) {
189 void Gtransfo::paramDerivatives(
const Point &,
double *,
double *)
const {
191 "Gtransfo::paramDerivatives() should never be called ");
195 gtransfo.
dump(stream);
206 "Gtransfo::write, something went wrong for file " + fileName);
211 "Gtransfo::write(ostream), should never be called. MEans that it is missing in some " 230 void apply(
const double xIn,
const double yIn,
double &xOut,
double &yOut)
const;
232 void dump(
ostream &stream)
const;
256 GtransfoInverse::GtransfoInverse(
const Gtransfo *direct,
const double precision,
const Frame ®ion) {
257 _direct = direct->
clone();
258 _roughInverse = _direct->roughInverse(region);
259 precision2 = precision * precision;
263 _direct = model._direct->clone();
264 _roughInverse = model._roughInverse->clone();
265 precision2 = model.precision2;
271 _direct = model._direct->clone();
272 _roughInverse = model._roughInverse->clone();
273 precision2 = model.precision2;
278 Point outGuess = _roughInverse->apply(in);
285 Point inGuess = _direct->apply(outGuess);
286 _direct->computeDerivative(outGuess, directDer);
287 reverseDer = directDer.
invert();
288 double xShift, yShift;
289 reverseDer.
apply(xIn - inGuess.
x, yIn - inGuess.
y, xShift, yShift);
290 outGuess.
x += xShift;
291 outGuess.
y += yShift;
292 move2 = xShift * xShift + yShift * yShift;
293 }
while ((move2 > precision2) && (loop < maxloop));
294 if (loop == maxloop)
LOGLS_WARN(_log,
"Problems applying GtransfoInverse at " << in);
300 stream <<
" GtransfoInverse of :" <<
endl << *_direct <<
endl;
327 void apply(
const double xIn,
const double yIn,
double &xOut,
double &yOut)
const;
338 _first = first->
clone();
339 _second = second->
clone();
344 _first->apply(xIn, yIn, xout, yout);
345 _second->apply(xout, yout, xOut, yOut);
349 _first->dump(stream);
350 _second->dump(stream);
355 return _first->fit(starMatchList);
371 return left->
clone();
379 if (composition ==
nullptr)
402 " GtransfoIdentity::read : format is not 1 ");
410 _nterms = (degree + 1) * (degree + 2) / 2;
413 _coeffs.
resize(2 * _nterms, 0.);
426 for (
double x = frame.
xMin + step / 2;
x <= frame.
xMax;
x += step)
427 for (
double y = frame.
yMin + step / 2; y <= frame.
yMax; y += step) {
428 auto pix = std::make_shared<BaseStar>(
x, y, 0, 0);
430 gtransfo->
apply(x, y, xtr, ytr);
431 auto tp = std::make_shared<BaseStar>(xtr, ytr, 0, 0);
442 void GtransfoPoly::computeMonomials(
double xIn,
double yIn,
double *monomial)
const {
453 for (
unsigned ix = 0; ix <= _degree; ++ix) {
455 unsigned k = ix * (ix + 1) / 2;
456 for (
unsigned iy = 0; iy <= _degree - ix; ++iy) {
457 monomial[k] = xx * yy;
467 unsigned old_nterms = _nterms;
468 _nterms = (_degree + 1) * (_degree + 2) / 2;
473 _coeffs.
resize(2 * _nterms);
476 for (
unsigned k = 0; k < _nterms; ++k) _coeffs[k] = 0;
478 unsigned kmax =
min(old_nterms, _nterms);
479 for (
unsigned k = 0; k < kmax; ++k) {
480 _coeffs[k] = old_coeffs[k];
481 _coeffs[k + _nterms] = old_coeffs[k + old_nterms];
496 double monomials[_nterms];
497 computeMonomials(xIn, yIn, monomials);
501 const double *c = &_coeffs[0];
502 const double *pm = &monomials[0];
504 for (
int k = _nterms; k--;) xOut += (*(pm++)) * (*(c++));
506 for (
int k = _nterms; k--;) yOut += (*(pm++)) * (*(c++));
513 derivative.
dx() = derivative.
dy() = 0;
517 double dermx[2 * _nterms];
518 double *dermy = dermx + _nterms;
519 double xin = where.
x;
520 double yin = where.
y;
524 for (
unsigned ix = 0; ix <= _degree; ++ix) {
525 unsigned k = (ix) * (ix + 1) / 2;
527 dermx[k] = ix * xxm1;
531 for (
unsigned iy = 1; iy <= _degree - ix; ++iy) {
532 dermx[k] = ix * xxm1 * yym1 * yin;
533 dermy[k] = iy * xx * yym1;
538 if (ix >= 1) xxm1 *= xin;
544 const double *mx = &dermx[0];
545 const double *my = &dermy[0];
546 const double *c = &_coeffs[0];
548 double a11 = 0, a12 = 0;
549 for (
int k = _nterms; k--;) {
550 a11 += (*(mx++)) * (*c);
551 a12 += (*(my++)) * (*(c++));
553 derivative.
a11() = a11;
554 derivative.
a12() = a12;
556 double a21 = 0, a22 = 0;
559 for (
int k = _nterms; k--;) {
560 a21 += (*(mx++)) * (*c);
561 a22 += (*(my++)) * (*(c++));
563 derivative.
a21() = a21;
564 derivative.
a22() = a22;
580 double monomials[_nterms];
584 double dermx[2 * _nterms];
585 double *dermy = dermx + _nterms;
591 for (
unsigned ix = 0; ix <= _degree; ++ix) {
592 unsigned k = (ix) * (ix + 1) / 2;
594 dermx[k] = ix * xxm1;
600 for (
unsigned iy = 1; iy <= _degree - ix; ++iy) {
601 monomials[k] = xx * yy;
602 dermx[k] = ix * xxm1 * yy;
603 dermy[k] = iy * xx * yym1;
609 if (ix >= 1) xxm1 *= xin;
613 double xout = 0, yout = 0;
614 const double *c = &_coeffs[0];
615 const double *pm = &monomials[0];
616 for (
int k = _nterms; k--;) xout += (*(pm++)) * (*(c++));
618 for (
int k = _nterms; k--;) yout += (*(pm++)) * (*(c++));
624 const double *mx = &dermx[0];
625 const double *my = &dermy[0];
626 double a11 = 0, a12 = 0;
627 for (
int k = _nterms; k--;) {
628 a11 += (*(mx++)) * (*c);
629 a12 += (*(my++)) * (*(c++));
632 double a21 = 0, a22 = 0;
635 for (
int k = _nterms; k--;) {
636 a21 += (*(mx++)) * (*c);
637 a22 += (*(my++)) * (*(c++));
641 res.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
642 res.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
643 res.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
652 assert((degX + degY <= _degree) && whichCoord < 2);
656 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
660 assert((degX + degY <= _degree) && whichCoord < 2);
661 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
666 assert(whichCoord < 2);
667 if (degX + degY <= _degree)
668 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
674 assert(
unsigned(i) < 2 * _nterms);
679 assert(
unsigned(i) < 2 * _nterms);
685 computeMonomials(where.
x, where.
y, dx);
686 for (
unsigned k = 0; k < _nterms; ++k) {
687 dy[_nterms + k] = dx[k];
688 dx[_nterms + k] = dy[k] = 0;
693 static string monomialString(
const unsigned powX,
const unsigned powY) {
695 if (powX + powY) ss <<
"*";
696 if (powX > 0) ss <<
"x";
697 if (powX > 1) ss <<
"^" << powX;
698 if (powY > 0) ss <<
"y";
699 if (powY > 1) ss <<
"^" << powY;
704 for (
unsigned ic = 0; ic < 2; ++ic) {
709 for (
unsigned p = 0; p <= _degree; ++p)
710 for (
unsigned py = 0; py <= p; ++py) {
711 if (p + py != 0) stream <<
" + ";
712 stream <<
coeff(p - py, py, ic) << monomialString(p - py, py);
716 if (_degree > 0) stream <<
" Linear determinant = " <<
determinant() <<
endl;
738 for (
auto it = starMatchList.
begin(); it != starMatchList.
end(); ++it) {
751 double xspan = 3.5 *
sqrt(x2 / count -
std::pow(xav, 2));
752 double yspan = 3.5 *
sqrt(y2 / count -
std::pow(yav, 2));
756 static double sq(
double x) {
return x *
x; }
759 const bool useErrors) {
760 Eigen::MatrixXd A(2 * _nterms, 2 * _nterms);
762 Eigen::VectorXd B(2 * _nterms);
765 double monomials[_nterms];
766 for (
auto it = starMatchList.
begin(); it != starMatchList.
end(); ++it) {
771 double wxx, wyy, wxy;
773 computeMonomials(point1.
x, point1.
y, monomials);
776 double vxx = (tr1.
vx + point2.
vx);
777 double vyy = (tr1.
vy + point2.
vy);
778 double vxy = (tr1.
vxy + point2.
vxy);
779 double det = vxx * vyy - vxy * vxy;
788 double resx = point2.
x - tr1.
x;
789 double resy = point2.
y - tr1.
y;
790 sumr2 += wxx * sq(resx) + wyy * sq(resy) + 2 * wxy * resx * resy;
792 double bxcoeff = wxx * resx + wxy * resy;
793 double bycoeff = wyy * resy + wxy * resx;
794 for (
unsigned j = 0; j < _nterms; ++j) {
795 for (
unsigned i = j; i < _nterms; ++i) {
796 A(i, j) += wxx * monomials[i] * monomials[j];
797 A(i + _nterms, j + _nterms) += wyy * monomials[i] * monomials[j];
798 A(j, i + _nterms) = A(i, j + _nterms) += wxy * monomials[i] * monomials[j];
800 B(j) += bxcoeff * monomials[j];
801 B(j + _nterms) += bycoeff * monomials[j];
804 Eigen::LDLT<Eigen::MatrixXd, Eigen::Lower> factor(A);
806 if (factor.info() != Eigen::Success) {
807 LOGL_ERROR(_log,
"GtransfoPoly::fit could not factorize");
811 Eigen::VectorXd sol = factor.solve(B);
812 for (
unsigned k = 0; k < 2 * _nterms; ++k) _coeffs[k] += sol(k);
813 if (starMatchList.
size() == _nterms)
return 0;
814 return (sumr2 - B.dot(sol));
818 if (starMatchList.
size() < _nterms) {
819 LOGLS_FATAL(_log,
"GtransfoPoly::fit trying to fit a polynomial transfo of degree " 820 << _degree <<
" with only " << starMatchList.
size() <<
" matches.");
824 GtransfoPoly conditionner = shiftAndNormalize(starMatchList);
826 computeFit(starMatchList, conditionner,
false);
827 computeFit(starMatchList, conditionner,
true);
828 double chi2 = computeFit(starMatchList, conditionner,
true);
830 (*this) = (*this) * conditionner;
831 if (starMatchList.
size() == _nterms)
return 0;
861 PolyXY(
const int degree) : degree(degree), nterms((degree + 1) * (degree + 2) / 2) {
869 : degree(gtransfoPoly.
getDegree()), nterms((degree + 1) * (degree + 2) / 2), coeffs(nterms, 0L) {
870 for (
unsigned px = 0; px <= degree; ++px)
871 for (
unsigned py = 0; py <= degree - px; ++py)
872 coeff(px, py) = gtransfoPoly.
coeff(px, py, whichCoord);
875 long double coeff(
const unsigned powX,
const unsigned powY)
const {
876 assert(powX + powY <= degree);
877 return coeffs.
at((powX + powY) * (powX + powY + 1) / 2 + powY);
880 long double &
coeff(
const unsigned powX,
const unsigned powY) {
881 assert(powX + powY <= degree);
882 return coeffs.
at((powX + powY) * (powX + powY + 1) / 2 + powY);
891 for (
unsigned i = 0; i <= rdeg; ++i)
892 for (
unsigned j = 0; j <= rdeg - i; ++j) left.
coeff(i, j) += right.
coeff(i, j);
900 for (
unsigned i = 0; i <= degree; ++i)
901 for (
unsigned j = 0; j <= degree - i; ++j) result.
coeff(i, j) *= a;
909 PolyXY result(deg1 + deg2);
910 for (
unsigned i1 = 0; i1 <= deg1; ++i1)
911 for (
unsigned j1 = 0; j1 <= deg1 - i1; ++j1)
912 for (
unsigned i2 = 0; i2 <= deg2; ++i2)
913 for (
unsigned j2 = 0; j2 <= deg2 - i2; ++j2)
922 powers[0].coeff(0, 0) = 1L;
923 for (
unsigned k = 1; k <= maxP; ++k) powers.
push_back(product(powers[k - 1], polyXY));
932 computePowers(polyX, pdeg, pXPowers);
933 computePowers(polyY, pdeg, pYPowers);
934 for (
unsigned px = 0; px <= pdeg; ++px)
935 for (
unsigned py = 0; py <= pdeg - px; ++py)
936 result += polyXY.
coeff(px, py) * product(pXPowers.
at(px), pYPowers.
at(py));
952 PolyXY rx(composition(plx, prx, pry));
953 PolyXY ry(composition(ply, prx, pry));
957 for (
unsigned px = 0; px <= result._degree; ++px)
958 for (
unsigned py = 0; py <= result._degree - px; ++py) {
966 if (_degree >= right._degree) {
968 for (
unsigned i = 0; i <= right._degree; ++i)
969 for (
unsigned j = 0; j <= right._degree - i; ++j) {
975 return (right + (*
this));
980 for (
unsigned i = 0; i <= res._degree; ++i)
981 for (
unsigned j = 0; j <= res._degree - i; ++j) {
989 s <<
" GtransfoPoly 1" <<
endl;
990 s <<
"degree " << _degree << endl;
993 for (
unsigned k = 0; k < 2 * _nterms; ++k) s << _coeffs[k] <<
' ';
995 s << setprecision(oldprec);
1005 s >> degree >> _degree;
1006 if (degree !=
"degree")
1008 " GtransfoPoly::read : expecting \"degree\" and found " + degree);
1010 for (
unsigned k = 0; k < 2 * _nterms; ++k) s >> _coeffs[k];
1014 const double precision) {
1017 double stepx = frame.
getWidth() / (nx + 1);
1019 double stepy = frame.
getHeight() / (ny + 1);
1020 for (
unsigned i = 0; i < nx; ++i)
1021 for (
unsigned j = 0; j < ny; ++j) {
1022 Point in((i + 0.5) * stepx, (j + 0.5) * stepy);
1026 unsigned npairs = sm.
size();
1030 for (degree = 1; degree <= maxdeg; ++degree) {
1035 for (
auto const &i : sm) chi2 += i.point2.computeDist2(poly->apply((i.point1)));
1036 if (chi2 / npairs < precision * precision)
break;
1038 if (degree > maxdeg)
1039 LOGLS_WARN(_log,
"inversePolyTransfo: Reached max degree without reaching requested precision: " 1050 const double A21,
const double A22)
1063 "Trying to build a GtransfoLin from a higher order transfo. Aborting. ");
1084 derivative.
coeff(0, 0, 0) = 0;
1085 derivative.
coeff(0, 0, 1) = 0;
1101 double d = (a11 * a22 - a12 *
a21);
1104 "GtransfoLin::invert singular transformation: transfo contents will be dumped to stderr.");
1108 GtransfoLin result(0, 0, a22 / d, -a12 / d, -a21 / d, a11 / d);
1125 int npairs = starMatchList.
size();
1127 LOGLS_FATAL(_log,
"GtransfoLinShift::fit trying to fit a linear transfo with only " << npairs
1134 Eigen::VectorXd B(2);
1136 Eigen::MatrixXd A(2, 2);
1139 for (
auto const &it : starMatchList) {
1140 const FatPoint &point1 = it.point1;
1141 const FatPoint &point2 = it.point2;
1142 double deltax = point2.
x - point1.
x;
1143 double deltay = point2.
y - point1.
y;
1144 double vxx = point1.
vx + point2.
vx;
1145 double vyy = point1.
vy + point2.
vy;
1146 double vxy = point1.
vxy + point2.
vxy;
1147 double det = vxx * vyy - vxy * vxy;
1148 double wxx = vyy / det;
1149 double wyy = vxx / det;
1150 double wxy = -vxy / det;
1151 B(0) += deltax * wxx + wxy * deltay;
1152 B(1) += deltay * wyy + wxy * deltax;
1156 sumr2 += deltax * deltax * wxx + deltay * deltay * wyy + 2. * wxy * deltax * deltay;
1158 double det = A(0, 0) * A(1, 1) - A(0, 1) * A(1, 0);
1159 if (det <= 0)
return -1;
1160 double tmp = A(0, 0);
1161 A(0, 0) = A(1, 1) / det;
1162 A(1, 1) = tmp / det;
1163 A(0, 1) = A(1, 0) = -A(0, 1) / det;
1164 Eigen::VectorXd sol = A * B;
1166 return (sumr2 - sol.dot(B));
1170 double c = scaleFactor *
cos(angleRad);
1171 double s = scaleFactor *
sin(angleRad);
1177 Point a_point(0., 0.);
1178 if (center) a_point = *center;
1182 dx() = a_point.
x -
Dx();
1183 dy() = a_point.
y -
dy();
1186 static double deg2rad(
double degree) {
return degree *
M_PI / 180.; }
1188 static double rad2deg(
double rad) {
return rad * 180. /
M_PI; }
1212 linPix2Tan = pix2Tan;
1213 ra0 = deg2rad(tangentPoint.
x);
1214 dec0 = deg2rad(tangentPoint.
y);
1218 if (corrections) corr.reset(
new GtransfoPoly(*corrections));
1251 LOGL_WARN(_log,
"No sidereal coordinates at pole!");
1260 if (rat < 0.0) rat += (2. *
M_PI);
1262 xOut = rad2deg(rat);
1263 yOut = rad2deg(dect);
1281 return Point(inverse.
Dx(), inverse.
Dy());
1291 xOut = outCoord[0].asDegrees();
1292 yOut = outCoord[1].asDegrees();
1296 stream <<
"GtransfoSkyWcs(" << *_skyWcs <<
")";
1311 :
BaseTanWcs(pix2Tan, tangentPoint, corrections) {}
1329 if (
corr !=
nullptr) {
1330 LOGL_WARN(_log,
"You are inverting a TanPix2RaDec with corrections.");
1331 LOGL_WARN(_log,
"The inverse you get ignores the corrections!");
1358 double xtmp = xTangentPlane;
1359 double ytmp = yTangentPlane;
1360 corr->apply(xtmp, ytmp, xTangentPlane, yTangentPlane);
1371 stream <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1373 stream <<
" crpix " << crpix.
x <<
' ' << crpix.
y <<
endl;
1374 if (
corr) stream <<
"PV correction: " <<
endl << *
corr;
1387 "TanPix2RaDec::fit is NOT implemented (although it is doable)) ");
1395 :
BaseTanWcs(pix2Tan, tangentPoint, corrections) {}
1423 double &yTangentPlane)
const {
1427 corr->apply(xPixel, yPixel, xtmp, ytmp);
1440 stream <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1442 stream <<
" crpix " << crpix.
x <<
' ' << crpix.
y <<
endl;
1443 if (
corr) stream <<
"PV correction: " <<
endl << *
corr;
1456 "TanSipPix2RaDec::fit is NOT implemented (although it is doable)) ");
1469 ra0 = deg2rad(tangentPoint.
x);
1470 dec0 = deg2rad(tangentPoint.
y);
1502 double ra = deg2rad(in.
x);
1503 double dec = deg2rad(in.
y);
1504 if (ra - ra0 >
M_PI) ra -= (2. *
M_PI);
1505 if (ra - ra0 < -
M_PI) ra += (2. *
M_PI);
1509 double coss =
cos(dec);
1510 double sins =
sin(dec);
1511 double sinda =
sin(ra - ra0);
1512 double cosda =
cos(ra - ra0);
1513 double l = sinda * coss;
1514 double m = sins * sin0 + coss * cos0 * cosda;
1516 m = (sins * cos0 - coss * sin0 * cosda) / m;
1520 sq(sin0) - sq(coss) + sq(coss * cos0) * (1 + sq(cosda)) + 2 * sins * sin0 * coss * cos0 * cosda;
1521 double a11 = coss * (cosda * sins * sin0 + coss * cos0) / deno;
1522 double a12 = -sinda * sin0 / deno;
1523 double a21 = coss * sinda * sins / deno;
1524 double a22 = cosda / deno;
1527 tmp.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
1528 tmp.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
1529 tmp.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
1539 double ra = deg2rad(xIn);
1540 double dec = deg2rad(yIn);
1541 if (ra - ra0 >
M_PI) ra -= (2. *
M_PI);
1542 if (ra - ra0 < -
M_PI) ra += (2. *
M_PI);
1545 double coss =
cos(dec);
1546 double sins =
sin(dec);
1547 double l =
sin(ra - ra0) * coss;
1548 double m = sins * sin0 + coss * cos0 *
cos(ra - ra0);
1550 m = (sins * cos0 - coss * sin0 * cos(ra - ra0)) / m;
1554 linTan2Pix.
apply(l, m, xOut, yOut);
1561 stream <<
" tan2pix " << linTan2Pix <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1578 "TanRaDec2Pix::fit is NOT implemented (although it is doable)) ");
1586 : _userFun(userFun), _userData(userData) {}
1589 _userFun(xIn, yIn, xOut, yOut, _userData);
1593 stream <<
"UserTransfo with user function @ " << _userFun <<
"and userData@ " << _userData <<
endl;
1598 "UserTransfo::fit is NOT implemented (and will never be)) ");
1627 "gtransfoRead : could not find a Gtransfotype");
1628 if (type ==
"GtransfoIdentity") {
1632 }
else if (type ==
"GtransfoPoly") {
1638 " gtransfoRead : No reader for Gtransfo type " + type);
std::unique_ptr< Gtransfo > roughInverse(const Frame ®ion) const
Overload the "generic routine" (available for all Gtransfo types.
void write(std::ostream &s) const
virtual std::unique_ptr< Gtransfo > clone() const
returns a copy (allocated by new) of the transformation.
#define LOGL_ERROR(logger, message...)
void dump(std::ostream &stream=std::cout) const
dumps the transfo coefficients to stream.
implements the linear transformations (6 real coefficients).
TanPix2RaDec invert() const
exact typed inverse:
void apply(const double xIn, const double yIn, double &xOut, double &yOut) const override
TanRaDec2Pix invert() const
approximate inverse : it ignores corrections;
std::unique_ptr< Gtransfo > inverseTransfo(const double precision, const Frame ®ion) const
Inverse transfo: returns a TanPix2RaDec.
std::unique_ptr< Gtransfo > gtransfoCompose(const Gtransfo *left, const Gtransfo *right)
Returns a pointer to a composition.
void computeDerivative(const Point &where, GtransfoLin &derivative, const double step=0.01) const
specialised analytic routine
void apply(const double xIn, const double yIn, double &xOut, double &yOut) const
double fit(const StarMatchList &starMatchList)
fits a transfo to a std::list of Point pairs (p1,p2, the Point fields in StarMatch).
void computeDerivative(const Point &where, GtransfoLin &derivative, const double step=0.01) const
Computes the local Derivative of a transfo, w.r.t.
std::ostream & operator<<(std::ostream &out, CcdImageKey const &key)
A hanger for star associations.
void() GtransfoFun(const double, const double, double &, double &, const void *)
signature of the user-provided routine that actually does the coordinate transfo for UserTransfo...
the transformation that handles pix to sideral transfos (Gnomonic, possibly with polynomial distortio...
void setCorrections(std::unique_ptr< GtransfoPoly > corrections)
Assign the correction polynomial (what it means is left to derived classes)
long double & coeff(const unsigned powX, const unsigned powY)
GtransfoLin invert() const
returns the inverse: T1 = T2.invert();
std::unique_ptr< Gtransfo > roughInverse(const Frame &) const
Overload the "generic routine".
void apply(const double xIn, const double yIn, double &xOut, double &yOut) const
implements an iterative (Gauss-Newton) solver.
void paramDerivatives(const Point &where, double *dx, double *dy) const
Derivative w.r.t parameters.
void apply(const double xIn, const double yIn, double &xOut, double &yOut) const
void write(std::ostream &s) const
bool isIdentity(const Gtransfo *gtransfo)
Shorthand test to tell if a transfo belongs to the GtransfoIdentity class.
std::unique_ptr< Gtransfo > clone() const override
returns a copy (allocated by new) of the transformation.
void apply(const double xIn, const double yIn, double &xOut, double &yOut) const
return second(first(xIn,yIn))
void apply(const double xIn, const double yIn, double &xOut, double &yOut) const
Transform pixels to ICRS RA, Dec in degrees.
double fit(const StarMatchList &starMatchList)
Not implemented yet, because we do it otherwise.
double xMin
coordinate of boundary.
GtransfoLin linearApproximation(const Point &where, const double step=0.01) const
linear (local) approximation.
double paramRef(const int i) const
void dump(std::ostream &stream) const
dumps the transfo coefficients to stream.
#define LOGLS_FATAL(logger, message)
Polynomial transformation class.
GtransfoLin normalizeCoordinatesTransfo(const Frame &frame)
Returns the transformation that maps the input frame along both axes to [-1,1].
GtransfoInverse(const Gtransfo *direct, const double precision, const Frame ®ion)
GtransfoPoly getPix2TangentPlane() const
the transformation from pixels to tangent plane (degrees)
A Point with uncertainties.
double fit(const StarMatchList &starMatchList)
fits a transfo to a std::list of Point pairs (p1,p2, the Point fields in StarMatch).
std::unique_ptr< Gtransfo > clone() const
returns a copy (allocated by new) of the transformation.
GtransfoComposition(const Gtransfo *second, const Gtransfo *first)
will pipe transfos
std::unique_ptr< Gtransfo > roughInverse(const Frame ®ion) const
Overload the "generic routine" (available for all Gtransfo types.
GtransfoPoly operator*(const GtransfoPoly &right) const
Composition (internal stuff in quadruple precision)
GtransfoLin()
the default constructor constructs the do-nothing transformation.
bool isIntegerShift(const Gtransfo *gtransfo)
Shorthand test to tell if a transfo is a simple integer shift.
std::unique_ptr< GtransfoPoly > inversePolyTransfo(const Gtransfo &Direct, const Frame &frame, const double Prec)
approximates the inverse by a polynomial, up to required precision.
double getHeight() const
size along y axis
double coeffOrZero(const unsigned powX, const unsigned powY, const unsigned whichCoord) const
read access, zero if beyond degree
void computeDerivative(const Point &where, GtransfoLin &derivative, const double step=0.01) const
specialised analytic routine
unsigned getDegree() const
void read(std::istream &s)
rectangle with sides parallel to axes.
Class for a simple mapping implementing a generic Gtransfo.
#define LOGL_FATAL(logger, message...)
std::unique_ptr< Gtransfo > clone() const
returns a copy (allocated by new) of the transformation.
GtransfoPoly operator-(const GtransfoPoly &right) const
Subtraction.
Point getCrPix() const
Get the pixel origin of the WCS (CRPIX in FITS WCS terminology, but zero-based)
GtransfoLin getLinPart() const
The Linear part (corresponding to CD's and CRPIX's)
std::unique_ptr< Gtransfo > reduceCompo(const Gtransfo *right) const
to be overloaded by derived classes if they can really "reduce" the composition (e.g.
std::unique_ptr< Gtransfo > inverseTransfo(const double precision, const Frame ®ion) const
returns an inverse transfo. Numerical if not overloaded.
std::unique_ptr< Gtransfo > clone() const
returns a copy (allocated by new) of the transformation.
double fit(const StarMatchList &starMatchList)
guess what
void apply(const double xIn, const double yIn, double &xOut, double &yOut) const
void dump(ostream &stream=cout) const
dumps the transfo coefficients to stream.
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
void read(std::istream &s)
double fit(const StarMatchList &starMatchList)
fits a transfo to a std::list of Point pairs (p1,p2, the Point fields in StarMatch).
Point getTangentPoint() const
tangent point coordinates (degrees)
std::shared_ptr< afw::geom::SkyWcs > getSkyWcs() const
double fit(const StarMatchList &starMatchList)
Not implemented yet, because we do it otherwise.
void dump(std::ostream &stream) const
dumps the transfo coefficients to stream.
std::unique_ptr< Gtransfo > clone() const
returns a copy (allocated by new) of the transformation.
void dump(std::ostream &stream=std::cout) const
print out of coefficients in a readable form.
double fit(const StarMatchList &starMatchList)
fits a transfo to a std::list of Point pairs (p1,p2, the Point fields in StarMatch).
double getWidth() const
size along x axis
unsigned getDegree() const
returns degree
virtual void transformPosAndErrors(const FatPoint &in, FatPoint &out) const
a mix of apply and Derivative
PolyXY(const GtransfoPoly >ransfoPoly, const unsigned whichCoord)
Extent< double, N > & operator+=(Extent< double, N > &lhs, Extent< int, N > const &rhs)
Point getCenter() const
Center of the frame.
A do-nothing transformation. It anyway has dummy routines to mimick a Gtransfo.
void setTangentPoint(const Point &tangentPoint)
Resets the projection (or tangent) point.
#define LSST_EXCEPT(type,...)
virtual char const * what(void) const
just here to provide a specialized constructor, and fit.
virtual std::unique_ptr< Gtransfo > reduceCompo(const Gtransfo *right) const
to be overloaded by derived classes if they can really "reduce" the composition (e.g.
std::unique_ptr< Gtransfo > inverseTransfo(const double precision, const Frame ®ion) const
Inverse transfo: returns a TanRaDec2Pix if there are no corrections, or the iterative solver if there...
std::unique_ptr< Gtransfo > clone() const
returns a copy (allocated by new) of the transformation.
This one is the Tangent Plane (called gnomonic) projection (from celestial sphere to tangent plane) ...
std::unique_ptr< Gtransfo > inverseTransfo(const double precision, const Frame ®ion) const
Inverse transfo: returns a TanRaDec2Pix if there are no corrections, or the iterative solver if there...
friend class GtransfoPoly
void transformPosAndErrors(const FatPoint &in, FatPoint &out) const
transform with analytical derivatives
GtransfoPoly operator+(const GtransfoPoly &right) const
Addition.
GtransfoLin getLinPart() const
The Linear part (corresponding to CD's and CRPIX's)
just here to provide specialized constructors. GtransfoLin fit routine.
a virtual (interface) class for geometric transformations.
void dump(std::ostream &stream) const
dumps the transfo coefficients to stream.
GtransfoPoly(const unsigned degree=1)
Default transfo : identity for all degrees (>=1 ).
void setDegree(const unsigned degree)
Point getTangentPoint() const
Get the sky origin (CRVAL in FITS WCS terminology) in degrees.
std::unique_ptr< GtransfoPoly > corr
virtual void pix2TP(double xPixel, double yPixel, double &xTangentPlane, double &yTangentPlane) const
transforms from pixel space to tangent plane (degrees)
double coeff(const unsigned powX, const unsigned powY, const unsigned whichCoord) const
access to coefficients (read only)
Private class to handle Gtransfo compositions (i.e.
BaseTanWcs(const GtransfoLin &pix2Tan, const Point &tangentPoint, const GtransfoPoly *corrections=nullptr)
GtransfoPoly getPix2TangentPlane() const
the transformation from pixels to tangent plane (degrees)
double fit(const StarMatchList &starMatchList)
guess what
virtual GtransfoLin linearApproximation(const Point &where, const double step=0.01) const
linear approximation.
TanPix2RaDec operator*(const GtransfoLin &right) const
composition with GtransfoLin
GtransfoSkyWcs(std::shared_ptr< afw::geom::SkyWcs > skyWcs)
long double coeff(const unsigned powX, const unsigned powY) const
std::unique_ptr< Gtransfo > reduceCompo(const Gtransfo *right) const
to be overloaded by derived classes if they can really "reduce" the composition (e.g.
virtual void pix2TP(double xPixel, double yPixel, double &xTangentPlane, double &yTangentPlane) const
transforms from pixel space to tangent plane (degrees)
std::unique_ptr< Gtransfo > gtransfoRead(const std::string &fileName)
The virtual constructor from a file.
T setprecision(T... args)
virtual std::unique_ptr< Gtransfo > clone() const =0
returns a copy (allocated by new) of the transformation.
#define LOGL_WARN(logger, message...)
double fit(const StarMatchList &starMatchList)
guess what
virtual void dump(std::ostream &stream=std::cout) const =0
dumps the transfo coefficients to stream.
UserTransfo(GtransfoFun &fun, const void *userData)
the transfo routine and extra data that it may need.
virtual void pix2TP(double xPixel, double yPixel, double &xTangentPlane, double &yTangentPlane) const =0
Transform from pixels to tangent plane (degrees)
double fit(const StarMatchList &starMatchList) override
Not implemented; throws pex::exceptions::LogicError.
virtual void apply(const double xIn, const double yIn, double &xOut, double &yOut) const =0
void dump(ostream &stream) const
dumps the transfo coefficients to stream.
void operator=(const BaseTanWcs &original)
#define LOGLS_WARN(logger, message)
std::unique_ptr< Gtransfo > inverseTransfo(double, const Frame &) const
Inverse transfo: returns the direct one!
double determinant() const
GtransfoLin operator*(const GtransfoLin &right) const
enables to combine linear tranformations: T1=T2*T3 is legal.
void dump(std::ostream &stream=std::cout) const override
dumps the transfo coefficients to stream.