16 #include "Eigen/Cholesky" 23 LOG_LOGGER _log =
LOG_GET(
"jointcal.Gtransfo");
30 return (dynamic_cast<const GtransfoIdentity *>(gtransfo) !=
nullptr);
35 if (shift ==
nullptr)
return false;
37 static const double eps = 1e-5;
39 double dx = shift->
coeff(0, 0, 0);
40 double dy = shift->
coeff(0, 0, 1);
42 static Point dumb(4000, 4000);
44 fabs(dumb.
x + dx - shift->
apply(dumb).x) < eps &&
fabs(dumb.
y + dy - shift->
apply(dumb).y) < eps)
56 double Gtransfo::getJacobian(
const double x,
const double y)
const {
58 double eps = x * 0.01;
59 if (eps == 0) eps = 0.01;
62 apply(x + eps, y, dxdx, dydx);
66 apply(x, y + eps, dxdy, dydy);
69 return ((dxdx * dydy - dxdy * dydx) / (eps * eps));
75 void Gtransfo::computeDerivative(
const Point &where,
GtransfoLin &derivative,
const double step)
const {
79 apply(x, y, xp0, yp0);
82 apply(x + step, y, xp, yp);
83 derivative.
a11() = (xp - xp0) / step;
84 derivative.
a21() = (yp - yp0) / step;
85 apply(x, y + step, xp, yp);
86 derivative.
a12() = (xp - xp0) / step;
87 derivative.
a22() = (yp - yp0) / step;
92 GtransfoLin Gtransfo::linearApproximation(
const Point &where,
const double step)
const {
93 Point outwhere = apply(where);
95 computeDerivative(where, der, step);
105 computeDerivative(in, der, 0.01);
106 double a11 = der.
A11();
107 double a22 = der.
A22();
108 double a21 = der.
A21();
109 double a12 = der.
A12();
110 res.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
111 res.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
112 res.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
116 void Gtransfo::transformErrors(
const Point &where,
const double *vIn,
double *vOut)
const {
118 computeDerivative(where, der, 0.01);
119 double a11 = der.
A11();
120 double a22 = der.
A22();
121 double a21 = der.
A21();
122 double a12 = der.
A12();
137 double b11 = a11 * vIn[xx] + a12 * vIn[xy];
138 double b22 = a21 * vIn[xy] + a22 * vIn[yy];
139 double b12 = a11 * vIn[xy] + a12 * vIn[yy];
140 double b21 = a21 * vIn[xx] + a22 * vIn[xy];
144 vOut[xx] = b11 * a11 + b12 * a12;
145 vOut[xy] = b11 * a21 + b12 * a22;
146 vOut[yy] = b21 * a21 + b22 * a22;
152 Point centerIn = apply(centerOut);
154 computeDerivative(centerOut, der,
sqrt(region.
getArea()) / 5.);
169 void Gtransfo::getParams(
double *params)
const {
170 int npar = getNpar();
171 for (
int i = 0; i < npar; ++i) params[i] = paramRef(i);
174 void Gtransfo::offsetParams(Eigen::VectorXd
const &delta) {
175 int npar = getNpar();
176 for (
int i = 0; i < npar; ++i) paramRef(i) += delta[i];
179 double Gtransfo::paramRef(
const int)
const {
181 std::string(
"Gtransfo::paramRef should never be called "));
184 double &Gtransfo::paramRef(
const int) {
188 void Gtransfo::paramDerivatives(
const Point &,
double *,
double *)
const {
190 "Gtransfo::paramDerivatives() should never be called ");
194 gtransfo.
dump(stream);
205 "Gtransfo::write, something went wrong for file " + fileName);
210 "Gtransfo::write(ostream), should never be called. MEans that it is missing in some " 229 void apply(
const double xIn,
const double yIn,
double &xOut,
double &yOut)
const;
231 void dump(
ostream &stream)
const;
255 GtransfoInverse::GtransfoInverse(
const Gtransfo *direct,
const double precision,
const Frame ®ion) {
256 _direct = direct->
clone();
257 _roughInverse = _direct->roughInverse(region);
258 precision2 = precision * precision;
262 _direct = model._direct->clone();
263 _roughInverse = model._roughInverse->clone();
264 precision2 = model.precision2;
270 _direct = model._direct->clone();
271 _roughInverse = model._roughInverse->clone();
272 precision2 = model.precision2;
277 Point outGuess = _roughInverse->apply(in);
284 Point inGuess = _direct->apply(outGuess);
285 _direct->computeDerivative(outGuess, directDer);
286 reverseDer = directDer.
invert();
287 double xShift, yShift;
288 reverseDer.
apply(xIn - inGuess.
x, yIn - inGuess.
y, xShift, yShift);
289 outGuess.
x += xShift;
290 outGuess.
y += yShift;
291 move2 = xShift * xShift + yShift * yShift;
292 }
while ((move2 > precision2) && (loop < maxloop));
293 if (loop == maxloop)
LOGLS_WARN(_log,
"Problems applying GtransfoInverse at " << in);
299 stream <<
" GtransfoInverse of :" <<
endl << *_direct <<
endl;
326 void apply(
const double xIn,
const double yIn,
double &xOut,
double &yOut)
const;
337 _first = first->
clone();
338 _second = second->
clone();
343 _first->apply(xIn, yIn, xout, yout);
344 _second->apply(xout, yout, xOut, yOut);
348 _first->dump(stream);
349 _second->dump(stream);
354 return _first->fit(starMatchList);
370 return left->
clone();
378 if (composition ==
nullptr)
401 " GtransfoIdentity::read : format is not 1 ");
409 _nterms = (degree + 1) * (degree + 2) / 2;
412 _coeffs.
resize(2 * _nterms, 0.);
425 for (
double x = frame.
xMin + step / 2;
x <= frame.
xMax;
x += step)
426 for (
double y = frame.
yMin + step / 2; y <= frame.
yMax; y += step) {
427 auto pix = std::make_shared<BaseStar>(
x, y, 0, 0);
429 gtransfo->
apply(x, y, xtr, ytr);
430 auto tp = std::make_shared<BaseStar>(xtr, ytr, 0, 0);
441 void GtransfoPoly::computeMonomials(
double xIn,
double yIn,
double *monomial)
const {
452 for (
unsigned ix = 0; ix <= _degree; ++ix) {
454 unsigned k = ix * (ix + 1) / 2;
455 for (
unsigned iy = 0; iy <= _degree - ix; ++iy) {
456 monomial[k] = xx * yy;
466 unsigned old_nterms = _nterms;
467 _nterms = (_degree + 1) * (_degree + 2) / 2;
472 _coeffs.
resize(2 * _nterms);
475 for (
unsigned k = 0; k < _nterms; ++k) _coeffs[k] = 0;
477 unsigned kmax =
min(old_nterms, _nterms);
478 for (
unsigned k = 0; k < kmax; ++k) {
479 _coeffs[k] = old_coeffs[k];
480 _coeffs[k + _nterms] = old_coeffs[k + old_nterms];
495 double monomials[_nterms];
496 computeMonomials(xIn, yIn, monomials);
500 const double *c = &_coeffs[0];
501 const double *pm = &monomials[0];
503 for (
int k = _nterms; k--;) xOut += (*(pm++)) * (*(c++));
505 for (
int k = _nterms; k--;) yOut += (*(pm++)) * (*(c++));
512 derivative.
dx() = derivative.
dy() = 0;
516 double dermx[2 * _nterms];
517 double *dermy = dermx + _nterms;
518 double xin = where.
x;
519 double yin = where.
y;
523 for (
unsigned ix = 0; ix <= _degree; ++ix) {
524 unsigned k = (ix) * (ix + 1) / 2;
526 dermx[k] = ix * xxm1;
530 for (
unsigned iy = 1; iy <= _degree - ix; ++iy) {
531 dermx[k] = ix * xxm1 * yym1 * yin;
532 dermy[k] = iy * xx * yym1;
537 if (ix >= 1) xxm1 *= xin;
543 const double *mx = &dermx[0];
544 const double *my = &dermy[0];
545 const double *c = &_coeffs[0];
547 double a11 = 0, a12 = 0;
548 for (
int k = _nterms; k--;) {
549 a11 += (*(mx++)) * (*c);
550 a12 += (*(my++)) * (*(c++));
552 derivative.
a11() = a11;
553 derivative.
a12() = a12;
555 double a21 = 0, a22 = 0;
558 for (
int k = _nterms; k--;) {
559 a21 += (*(mx++)) * (*c);
560 a22 += (*(my++)) * (*(c++));
562 derivative.
a21() = a21;
563 derivative.
a22() = a22;
579 double monomials[_nterms];
583 double dermx[2 * _nterms];
584 double *dermy = dermx + _nterms;
590 for (
unsigned ix = 0; ix <= _degree; ++ix) {
591 unsigned k = (ix) * (ix + 1) / 2;
593 dermx[k] = ix * xxm1;
599 for (
unsigned iy = 1; iy <= _degree - ix; ++iy) {
600 monomials[k] = xx * yy;
601 dermx[k] = ix * xxm1 * yy;
602 dermy[k] = iy * xx * yym1;
608 if (ix >= 1) xxm1 *= xin;
612 double xout = 0, yout = 0;
613 const double *c = &_coeffs[0];
614 const double *pm = &monomials[0];
615 for (
int k = _nterms; k--;) xout += (*(pm++)) * (*(c++));
617 for (
int k = _nterms; k--;) yout += (*(pm++)) * (*(c++));
623 const double *mx = &dermx[0];
624 const double *my = &dermy[0];
625 double a11 = 0, a12 = 0;
626 for (
int k = _nterms; k--;) {
627 a11 += (*(mx++)) * (*c);
628 a12 += (*(my++)) * (*(c++));
631 double a21 = 0, a22 = 0;
634 for (
int k = _nterms; k--;) {
635 a21 += (*(mx++)) * (*c);
636 a22 += (*(my++)) * (*(c++));
640 res.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
641 res.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
642 res.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
651 assert((degX + degY <= _degree) && whichCoord < 2);
655 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
659 assert((degX + degY <= _degree) && whichCoord < 2);
660 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
665 assert(whichCoord < 2);
666 if (degX + degY <= _degree)
667 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
673 assert(
unsigned(i) < 2 * _nterms);
678 assert(
unsigned(i) < 2 * _nterms);
684 computeMonomials(where.
x, where.
y, dx);
685 for (
unsigned k = 0; k < _nterms; ++k) {
686 dy[_nterms + k] = dx[k];
687 dx[_nterms + k] = dy[k] = 0;
692 static string monomialString(
const unsigned powX,
const unsigned powY) {
694 if (powX + powY) ss <<
"*";
695 if (powX > 0) ss <<
"x";
696 if (powX > 1) ss <<
"^" << powX;
697 if (powY > 0) ss <<
"y";
698 if (powY > 1) ss <<
"^" << powY;
703 for (
unsigned ic = 0; ic < 2; ++ic) {
708 for (
unsigned p = 0; p <= _degree; ++p)
709 for (
unsigned py = 0; py <= p; ++py) {
710 if (p + py != 0) stream <<
" + ";
711 stream <<
coeff(p - py, py, ic) << monomialString(p - py, py);
715 if (_degree > 0) stream <<
" Linear determinant = " <<
determinant() <<
endl;
737 for (
auto it = starMatchList.
begin(); it != starMatchList.
end(); ++it) {
750 double xspan = 3.5 *
sqrt(x2 / count -
std::pow(xav, 2));
751 double yspan = 3.5 *
sqrt(y2 / count -
std::pow(yav, 2));
755 static double sq(
double x) {
return x *
x; }
758 const bool useErrors) {
759 Eigen::MatrixXd A(2 * _nterms, 2 * _nterms);
761 Eigen::VectorXd B(2 * _nterms);
764 double monomials[_nterms];
765 for (
auto it = starMatchList.
begin(); it != starMatchList.
end(); ++it) {
770 double wxx, wyy, wxy;
772 computeMonomials(point1.
x, point1.
y, monomials);
775 double vxx = (tr1.
vx + point2.
vx);
776 double vyy = (tr1.
vy + point2.
vy);
777 double vxy = (tr1.
vxy + point2.
vxy);
778 double det = vxx * vyy - vxy * vxy;
787 double resx = point2.
x - tr1.
x;
788 double resy = point2.
y - tr1.
y;
789 sumr2 += wxx * sq(resx) + wyy * sq(resy) + 2 * wxy * resx * resy;
791 double bxcoeff = wxx * resx + wxy * resy;
792 double bycoeff = wyy * resy + wxy * resx;
793 for (
unsigned j = 0; j < _nterms; ++j) {
794 for (
unsigned i = j; i < _nterms; ++i) {
795 A(i, j) += wxx * monomials[i] * monomials[j];
796 A(i + _nterms, j + _nterms) += wyy * monomials[i] * monomials[j];
797 A(j, i + _nterms) = A(i, j + _nterms) += wxy * monomials[i] * monomials[j];
799 B(j) += bxcoeff * monomials[j];
800 B(j + _nterms) += bycoeff * monomials[j];
803 Eigen::LDLT<Eigen::MatrixXd, Eigen::Lower> factor(A);
805 if (factor.info() != Eigen::Success) {
806 LOGL_ERROR(_log,
"GtransfoPoly::fit could not factorize");
810 Eigen::VectorXd sol = factor.solve(B);
811 for (
unsigned k = 0; k < 2 * _nterms; ++k) _coeffs[k] += sol(k);
812 if (starMatchList.
size() == _nterms)
return 0;
813 return (sumr2 - B.dot(sol));
817 if (starMatchList.
size() < _nterms) {
818 LOGLS_FATAL(_log,
"GtransfoPoly::fit trying to fit a polynomial transfo of degree " 819 << _degree <<
" with only " << starMatchList.
size() <<
" matches.");
823 GtransfoPoly conditionner = shiftAndNormalize(starMatchList);
825 computeFit(starMatchList, conditionner,
false);
826 computeFit(starMatchList, conditionner,
true);
827 double chi2 = computeFit(starMatchList, conditionner,
true);
829 (*this) = (*this) * conditionner;
830 if (starMatchList.
size() == _nterms)
return 0;
860 PolyXY(
const int degree) : degree(degree), nterms((degree + 1) * (degree + 2) / 2) {
868 : degree(gtransfoPoly.
getDegree()), nterms((degree + 1) * (degree + 2) / 2), coeffs(nterms, 0L) {
869 for (
unsigned px = 0; px <= degree; ++px)
870 for (
unsigned py = 0; py <= degree - px; ++py)
871 coeff(px, py) = gtransfoPoly.
coeff(px, py, whichCoord);
874 long double coeff(
const unsigned powX,
const unsigned powY)
const {
875 assert(powX + powY <= degree);
876 return coeffs.
at((powX + powY) * (powX + powY + 1) / 2 + powY);
879 long double &
coeff(
const unsigned powX,
const unsigned powY) {
880 assert(powX + powY <= degree);
881 return coeffs.
at((powX + powY) * (powX + powY + 1) / 2 + powY);
890 for (
unsigned i = 0; i <= rdeg; ++i)
891 for (
unsigned j = 0; j <= rdeg - i; ++j) left.
coeff(i, j) += right.
coeff(i, j);
899 for (
unsigned i = 0; i <= degree; ++i)
900 for (
unsigned j = 0; j <= degree - i; ++j) result.
coeff(i, j) *= a;
908 PolyXY result(deg1 + deg2);
909 for (
unsigned i1 = 0; i1 <= deg1; ++i1)
910 for (
unsigned j1 = 0; j1 <= deg1 - i1; ++j1)
911 for (
unsigned i2 = 0; i2 <= deg2; ++i2)
912 for (
unsigned j2 = 0; j2 <= deg2 - i2; ++j2)
921 powers[0].coeff(0, 0) = 1L;
922 for (
unsigned k = 1; k <= maxP; ++k) powers.
push_back(product(powers[k - 1], polyXY));
931 computePowers(polyX, pdeg, pXPowers);
932 computePowers(polyY, pdeg, pYPowers);
933 for (
unsigned px = 0; px <= pdeg; ++px)
934 for (
unsigned py = 0; py <= pdeg - px; ++py)
935 result += polyXY.
coeff(px, py) * product(pXPowers.
at(px), pYPowers.
at(py));
951 PolyXY rx(composition(plx, prx, pry));
952 PolyXY ry(composition(ply, prx, pry));
956 for (
unsigned px = 0; px <= result._degree; ++px)
957 for (
unsigned py = 0; py <= result._degree - px; ++py) {
965 if (_degree >= right._degree) {
967 for (
unsigned i = 0; i <= right._degree; ++i)
968 for (
unsigned j = 0; j <= right._degree - i; ++j) {
974 return (right + (*
this));
979 for (
unsigned i = 0; i <= res._degree; ++i)
980 for (
unsigned j = 0; j <= res._degree - i; ++j) {
988 s <<
" GtransfoPoly 1" <<
endl;
989 s <<
"degree " << _degree << endl;
992 for (
unsigned k = 0; k < 2 * _nterms; ++k) s << _coeffs[k] <<
' ';
994 s << setprecision(oldprec);
1004 s >> degree >> _degree;
1005 if (degree !=
"degree")
1007 " GtransfoPoly::read : expecting \"degree\" and found " + degree);
1009 for (
unsigned k = 0; k < 2 * _nterms; ++k) s >> _coeffs[k];
1013 const double precision) {
1016 double stepx = frame.
getWidth() / (nx + 1);
1018 double stepy = frame.
getHeight() / (ny + 1);
1019 for (
unsigned i = 0; i < nx; ++i)
1020 for (
unsigned j = 0; j < ny; ++j) {
1021 Point in((i + 0.5) * stepx, (j + 0.5) * stepy);
1025 unsigned npairs = sm.
size();
1029 for (degree = 1; degree <= maxdeg; ++degree) {
1034 for (
auto const &i : sm) chi2 += i.point2.computeDist2(poly->apply((i.point1)));
1035 if (chi2 / npairs < precision * precision)
break;
1037 if (degree > maxdeg)
1038 LOGLS_WARN(_log,
"inversePolyTransfo: Reached max degree without reaching requested precision: " 1049 const double A21,
const double A22)
1062 "Trying to build a GtransfoLin from a higher order transfo. Aborting. ");
1083 derivative.
coeff(0, 0, 0) = 0;
1084 derivative.
coeff(0, 0, 1) = 0;
1100 double d = (a11 * a22 - a12 *
a21);
1103 "GtransfoLin::invert singular transformation: transfo contents will be dumped to stderr.");
1107 GtransfoLin result(0, 0, a22 / d, -a12 / d, -a21 / d, a11 / d);
1124 int npairs = starMatchList.
size();
1126 LOGLS_FATAL(_log,
"GtransfoLinShift::fit trying to fit a linear transfo with only " << npairs
1133 Eigen::VectorXd B(2);
1135 Eigen::MatrixXd A(2, 2);
1138 for (
auto const &it : starMatchList) {
1139 const FatPoint &point1 = it.point1;
1140 const FatPoint &point2 = it.point2;
1141 double deltax = point2.
x - point1.
x;
1142 double deltay = point2.
y - point1.
y;
1143 double vxx = point1.
vx + point2.
vx;
1144 double vyy = point1.
vy + point2.
vy;
1145 double vxy = point1.
vxy + point2.
vxy;
1146 double det = vxx * vyy - vxy * vxy;
1147 double wxx = vyy / det;
1148 double wyy = vxx / det;
1149 double wxy = -vxy / det;
1150 B(0) += deltax * wxx + wxy * deltay;
1151 B(1) += deltay * wyy + wxy * deltax;
1155 sumr2 += deltax * deltax * wxx + deltay * deltay * wyy + 2. * wxy * deltax * deltay;
1157 double det = A(0, 0) * A(1, 1) - A(0, 1) * A(1, 0);
1158 if (det <= 0)
return -1;
1159 double tmp = A(0, 0);
1160 A(0, 0) = A(1, 1) / det;
1161 A(1, 1) = tmp / det;
1162 A(0, 1) = A(1, 0) = -A(0, 1) / det;
1163 Eigen::VectorXd sol = A * B;
1165 return (sumr2 - sol.dot(B));
1169 double c = scaleFactor *
cos(angleRad);
1170 double s = scaleFactor *
sin(angleRad);
1176 Point a_point(0., 0.);
1177 if (center) a_point = *center;
1181 dx() = a_point.
x -
Dx();
1182 dy() = a_point.
y -
dy();
1185 static double deg2rad(
double degree) {
return degree *
M_PI / 180.; }
1187 static double rad2deg(
double rad) {
return rad * 180. /
M_PI; }
1211 linPix2Tan = pix2Tan;
1212 ra0 = deg2rad(tangentPoint.
x);
1213 dec0 = deg2rad(tangentPoint.
y);
1217 if (corrections) corr.reset(
new GtransfoPoly(*corrections));
1250 LOGL_WARN(_log,
"No sidereal coordinates at pole!");
1259 if (rat < 0.0) rat += (2. *
M_PI);
1261 xOut = rad2deg(rat);
1262 yOut = rad2deg(dect);
1280 return Point(inverse.
Dx(), inverse.
Dy());
1289 :
BaseTanWcs(pix2Tan, tangentPoint, corrections) {}
1307 if (
corr !=
nullptr) {
1308 LOGL_WARN(_log,
"You are inverting a TanPix2RaDec with corrections.");
1309 LOGL_WARN(_log,
"The inverse you get ignores the corrections!");
1336 double xtmp = xTangentPlane;
1337 double ytmp = yTangentPlane;
1338 corr->apply(xtmp, ytmp, xTangentPlane, yTangentPlane);
1349 stream <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1351 stream <<
" crpix " << crpix.
x <<
' ' << crpix.
y <<
endl;
1352 if (
corr) stream <<
"PV correction: " <<
endl << *
corr;
1365 "TanPix2RaDec::fit is NOT implemented (although it is doable)) ");
1373 :
BaseTanWcs(pix2Tan, tangentPoint, corrections) {}
1401 double &yTangentPlane)
const {
1405 corr->apply(xPixel, yPixel, xtmp, ytmp);
1418 stream <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1420 stream <<
" crpix " << crpix.
x <<
' ' << crpix.
y <<
endl;
1421 if (
corr) stream <<
"PV correction: " <<
endl << *
corr;
1434 "TanSipPix2RaDec::fit is NOT implemented (although it is doable)) ");
1447 ra0 = deg2rad(tangentPoint.
x);
1448 dec0 = deg2rad(tangentPoint.
y);
1480 double ra = deg2rad(in.
x);
1481 double dec = deg2rad(in.
y);
1482 if (ra - ra0 >
M_PI) ra -= (2. *
M_PI);
1483 if (ra - ra0 < -
M_PI) ra += (2. *
M_PI);
1487 double coss =
cos(dec);
1488 double sins =
sin(dec);
1489 double sinda =
sin(ra - ra0);
1490 double cosda =
cos(ra - ra0);
1491 double l = sinda * coss;
1492 double m = sins * sin0 + coss * cos0 * cosda;
1494 m = (sins * cos0 - coss * sin0 * cosda) / m;
1498 sq(sin0) - sq(coss) + sq(coss * cos0) * (1 + sq(cosda)) + 2 * sins * sin0 * coss * cos0 * cosda;
1499 double a11 = coss * (cosda * sins * sin0 + coss * cos0) / deno;
1500 double a12 = -sinda * sin0 / deno;
1501 double a21 = coss * sinda * sins / deno;
1502 double a22 = cosda / deno;
1505 tmp.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
1506 tmp.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
1507 tmp.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
1517 double ra = deg2rad(xIn);
1518 double dec = deg2rad(yIn);
1519 if (ra - ra0 >
M_PI) ra -= (2. *
M_PI);
1520 if (ra - ra0 < -
M_PI) ra += (2. *
M_PI);
1523 double coss =
cos(dec);
1524 double sins =
sin(dec);
1525 double l =
sin(ra - ra0) * coss;
1526 double m = sins * sin0 + coss * cos0 *
cos(ra - ra0);
1528 m = (sins * cos0 - coss * sin0 * cos(ra - ra0)) / m;
1532 linTan2Pix.
apply(l, m, xOut, yOut);
1539 stream <<
" tan2pix " << linTan2Pix <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1556 "TanRaDec2Pix::fit is NOT implemented (although it is doable)) ");
1564 : _userFun(userFun), _userData(userData) {}
1567 _userFun(xIn, yIn, xOut, yOut, _userData);
1571 stream <<
"UserTransfo with user function @ " << _userFun <<
"and userData@ " << _userData <<
endl;
1576 "UserTransfo::fit is NOT implemented (and will never be)) ");
1605 "gtransfoRead : could not find a Gtransfotype");
1606 if (type ==
"GtransfoIdentity") {
1610 }
else if (type ==
"GtransfoPoly") {
1616 " gtransfoRead : No reader for Gtransfo type " + type);
#define LOGLS_WARN(logger, message)
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.
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:
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.
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
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.
#define LOGL_ERROR(logger, message...)
double paramRef(const int i) const
void dump(std::ostream &stream) const
dumps the transfo coefficients to stream.
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 (coordinates in 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
#define LOGL_FATAL(logger, message...)
unsigned getDegree() const
void read(std::istream &s)
rectangle with sides parallel to axes.
Class for a simple mapping implementing a generic Gtransfo.
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
the CRPIX values (this is WCS jargon), in 0-based coordinates
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 (in degrees)
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).
#define LOGL_WARN(logger, message...)
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
The tangent point (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
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 (coordinates in 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
#define LOGLS_FATAL(logger, message)
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
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.
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
Transforms from pixel space to tangent plane. deferred to actual implementations. ...
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)
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.
table::PointKey< double > crpix