42 #include "Eigen/Cholesky" 49 LOG_LOGGER _log =
LOG_GET(
"jointcal.Gtransfo");
57 if (shift ==
nullptr)
return false;
59 static const double eps = 1e-5;
61 double dx = shift->
coeff(0, 0, 0);
62 double dy = shift->
coeff(0, 0, 1);
64 static Point dumb(4000, 4000);
66 fabs(dumb.
x + dx - shift->
apply(dumb).x) < eps &&
fabs(dumb.
y + dy - shift->
apply(dumb).y) < eps)
74 Frame Gtransfo::apply(
Frame const &inputframe,
bool inscribed)
const {
76 double xtmin1, xtmax1, ytmin1, ytmax1;
77 apply(inputframe.
xMin, inputframe.
yMin, xtmin1, ytmin1);
78 apply(inputframe.
xMax, inputframe.
yMax, xtmax1, ytmax1);
82 double xtmin2, xtmax2, ytmin2, ytmax2;
83 apply(inputframe.
xMin, inputframe.
yMax, xtmin2, ytmax2);
84 apply(inputframe.
xMax, inputframe.
yMin, xtmax2, ytmin2);
88 if (inscribed)
return fr1 * fr2;
97 double Gtransfo::getJacobian(
const double x,
const double y)
const {
99 double eps = x * 0.01;
100 if (eps == 0) eps = 0.01;
103 apply(x + eps, y, dxdx, dydx);
107 apply(x, y + eps, dxdy, dydy);
110 return ((dxdx * dydy - dxdy * dydx) / (eps * eps));
116 void Gtransfo::computeDerivative(
Point const &where,
GtransfoLin &derivative,
const double step)
const {
120 apply(x, y, xp0, yp0);
123 apply(x + step, y, xp, yp);
124 derivative.
a11() = (xp - xp0) / step;
125 derivative.
a21() = (yp - yp0) / step;
126 apply(x, y + step, xp, yp);
127 derivative.
a12() = (xp - xp0) / step;
128 derivative.
a22() = (yp - yp0) / step;
134 Point outwhere = apply(where);
136 computeDerivative(where, der, step);
146 computeDerivative(in, der, 0.01);
147 double a11 = der.
A11();
148 double a22 = der.
A22();
149 double a21 = der.
A21();
150 double a12 = der.
A12();
151 res.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
152 res.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
153 res.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
157 void Gtransfo::transformErrors(
Point const &where,
const double *vIn,
double *vOut)
const {
159 computeDerivative(where, der, 0.01);
160 double a11 = der.
A11();
161 double a22 = der.
A22();
162 double a21 = der.
A21();
163 double a12 = der.
A12();
178 double b11 = a11 * vIn[xx] + a12 * vIn[xy];
179 double b22 = a21 * vIn[xy] + a22 * vIn[yy];
180 double b12 = a11 * vIn[xy] + a12 * vIn[yy];
181 double b21 = a21 * vIn[xx] + a22 * vIn[xy];
185 vOut[xx] = b11 * a11 + b12 * a12;
186 vOut[xy] = b11 * a21 + b12 * a22;
187 vOut[yy] = b21 * a21 + b22 * a22;
193 Point centerIn = apply(centerOut);
210 void Gtransfo::getParams(
double *params)
const {
211 int npar = getNpar();
212 for (
int i = 0; i < npar; ++i) params[i] = paramRef(i);
215 void Gtransfo::offsetParams(Eigen::VectorXd
const &delta) {
216 int npar = getNpar();
217 for (
int i = 0; i < npar; ++i) paramRef(i) += delta[i];
220 double Gtransfo::paramRef(
const int)
const {
222 std::string(
"Gtransfo::paramRef should never be called "));
225 double &Gtransfo::paramRef(
const int) {
229 void Gtransfo::paramDerivatives(
Point const &,
double *,
double *)
const {
231 "Gtransfo::paramDerivatives() should never be called ");
235 gtransfo.
dump(stream);
246 "Gtransfo::write, something went wrong for file " + fileName);
251 "Gtransfo::write(ostream), should never be called. MEans that it is missing in some " 270 void apply(
const double xIn,
const double yIn,
double &xOut,
double &yOut)
const;
272 void dump(
ostream &stream)
const;
296 GtransfoInverse::GtransfoInverse(
const Gtransfo *direct,
const double precision,
const Frame ®ion) {
297 _direct = direct->
clone();
298 _roughInverse = _direct->roughInverse(region);
299 precision2 = precision * precision;
303 _direct = model._direct->clone();
304 _roughInverse = model._roughInverse->clone();
305 precision2 = model.precision2;
311 _direct = model._direct->clone();
312 _roughInverse = model._roughInverse->clone();
313 precision2 = model.precision2;
318 Point outGuess = _roughInverse->apply(in);
325 Point inGuess = _direct->apply(outGuess);
326 _direct->computeDerivative(outGuess, directDer);
328 double xShift, yShift;
329 reverseDer.
apply(xIn - inGuess.
x, yIn - inGuess.
y, xShift, yShift);
330 outGuess.
x += xShift;
331 outGuess.
y += yShift;
332 move2 = xShift * xShift + yShift * yShift;
333 }
while ((move2 > precision2) && (loop < maxloop));
334 if (loop == maxloop)
LOGLS_WARN(_log,
"Problems applying GtransfoInverse at " << in);
340 stream <<
" GtransfoInverse of :" <<
endl << *_direct <<
endl;
367 void apply(
const double xIn,
const double yIn,
double &xOut,
double &yOut)
const;
378 _first = first.
clone();
379 _second = second.
clone();
384 _first->apply(xIn, yIn, xout, yout);
385 _second->apply(xout, yout, xOut, yOut);
389 _first->dump(stream);
390 _second->dump(stream);
395 return _first->fit(starMatchList);
399 return std::make_unique<GtransfoComposition>(*_second, *_first);
413 if (composition ==
nullptr)
414 return std::make_unique<GtransfoComposition>(left, right);
430 return std::make_shared<ast::UnitMap>(2);
440 " GtransfoIdentity::read : format is not 1 ");
448 _nterms = (order + 1) * (order + 2) / 2;
451 _coeffs.
resize(2 * _nterms, 0.);
464 for (
double x = frame.
xMin + step / 2;
x <= frame.
xMax;
x += step)
465 for (
double y = frame.
yMin + step / 2;
y <= frame.
yMax;
y += step) {
466 auto pix = std::make_shared<BaseStar>(
x,
y, 0, 0);
468 gtransfo->
apply(x, y, xtr, ytr);
469 auto tp = std::make_shared<BaseStar>(xtr, ytr, 0, 0);
481 jointcal::Frame const &domain,
unsigned const order,
unsigned const nSteps) {
483 double xStart = domain.
xMin;
484 double yStart = domain.
yMin;
485 double xStep = domain.
getWidth() / (nSteps + 1);
486 double yStep = domain.
getHeight() / (nSteps + 1);
487 for (
unsigned i = 0; i < nSteps; ++i) {
488 for (
unsigned j = 0; j < nSteps; ++j) {
491 afw::geom::Point2D inAfw(in.
x, in.
y);
492 afw::geom::Point2D outAfw = transform->applyForward(inAfw);
498 poly.
fit(starMatchList);
502 void GtransfoPoly::computeMonomials(
double xIn,
double yIn,
double *monomial)
const {
513 for (
unsigned ix = 0; ix <= _order; ++ix) {
515 unsigned k = ix * (ix + 1) / 2;
516 for (
unsigned iy = 0; iy <= _order - ix; ++iy) {
517 monomial[k] = xx * yy;
527 unsigned old_nterms = _nterms;
528 _nterms = (_order + 1) * (_order + 2) / 2;
533 _coeffs.
resize(2 * _nterms);
536 for (
unsigned k = 0; k < _nterms; ++k) _coeffs[k] = 0;
538 unsigned kmax =
min(old_nterms, _nterms);
539 for (
unsigned k = 0; k < kmax; ++k) {
540 _coeffs[k] = old_coeffs[k];
541 _coeffs[k + _nterms] = old_coeffs[k + old_nterms];
556 double monomials[_nterms];
557 computeMonomials(xIn, yIn, monomials);
561 const double *c = &_coeffs[0];
562 const double *pm = &monomials[0];
564 for (
int k = _nterms; k--;) xOut += (*(pm++)) * (*(c++));
566 for (
int k = _nterms; k--;) yOut += (*(pm++)) * (*(c++));
573 derivative.
dx() = derivative.
dy() = 0;
577 double dermx[2 * _nterms];
578 double *dermy = dermx + _nterms;
579 double xin = where.
x;
580 double yin = where.
y;
584 for (
unsigned ix = 0; ix <= _order; ++ix) {
585 unsigned k = (ix) * (ix + 1) / 2;
587 dermx[k] = ix * xxm1;
591 for (
unsigned iy = 1; iy <= _order - ix; ++iy) {
592 dermx[k] = ix * xxm1 * yym1 * yin;
593 dermy[k] = iy * xx * yym1;
598 if (ix >= 1) xxm1 *= xin;
604 const double *mx = &dermx[0];
605 const double *my = &dermy[0];
606 const double *c = &_coeffs[0];
608 double a11 = 0, a12 = 0;
609 for (
int k = _nterms; k--;) {
610 a11 += (*(mx++)) * (*c);
611 a12 += (*(my++)) * (*(c++));
613 derivative.
a11() = a11;
614 derivative.
a12() = a12;
616 double a21 = 0, a22 = 0;
619 for (
int k = _nterms; k--;) {
620 a21 += (*(mx++)) * (*c);
621 a22 += (*(my++)) * (*(c++));
623 derivative.
a21() = a21;
624 derivative.
a22() = a22;
640 double monomials[_nterms];
644 double dermx[2 * _nterms];
645 double *dermy = dermx + _nterms;
651 for (
unsigned ix = 0; ix <= _order; ++ix) {
652 unsigned k = (ix) * (ix + 1) / 2;
654 dermx[k] = ix * xxm1;
660 for (
unsigned iy = 1; iy <= _order - ix; ++iy) {
661 monomials[k] = xx * yy;
662 dermx[k] = ix * xxm1 * yy;
663 dermy[k] = iy * xx * yym1;
669 if (ix >= 1) xxm1 *= xin;
673 double xout = 0, yout = 0;
674 const double *c = &_coeffs[0];
675 const double *pm = &monomials[0];
676 for (
int k = _nterms; k--;) xout += (*(pm++)) * (*(c++));
678 for (
int k = _nterms; k--;) yout += (*(pm++)) * (*(c++));
684 const double *mx = &dermx[0];
685 const double *my = &dermy[0];
686 double a11 = 0, a12 = 0;
687 for (
int k = _nterms; k--;) {
688 a11 += (*(mx++)) * (*c);
689 a12 += (*(my++)) * (*(c++));
692 double a21 = 0, a22 = 0;
695 for (
int k = _nterms; k--;) {
696 a21 += (*(mx++)) * (*c);
697 a22 += (*(my++)) * (*(c++));
701 res.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
702 res.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
703 res.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
712 assert((degX + degY <= _order) && whichCoord < 2);
716 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
720 assert((degX + degY <= _order) && whichCoord < 2);
721 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
726 assert(whichCoord < 2);
727 if (degX + degY <= _order)
728 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
734 assert(
unsigned(i) < 2 * _nterms);
739 assert(
unsigned(i) < 2 * _nterms);
745 computeMonomials(where.
x, where.
y, dx);
746 for (
unsigned k = 0; k < _nterms; ++k) {
747 dy[_nterms + k] = dx[k];
748 dx[_nterms + k] = dy[k] = 0;
753 static string monomialString(
const unsigned powX,
const unsigned powY) {
755 if (powX + powY) ss <<
"*";
756 if (powX > 0) ss <<
"x";
757 if (powX > 1) ss <<
"^" << powX;
758 if (powY > 0) ss <<
"y";
759 if (powY > 1) ss <<
"^" << powY;
766 for (
unsigned ic = 0; ic < 2; ++ic) {
771 for (
unsigned p = 0; p <= _order; ++p)
772 for (
unsigned py = 0; py <= p; ++py) {
773 if (p + py != 0) stream <<
" + ";
774 stream <<
coeff(p - py, py, ic) << monomialString(p - py, py);
778 if (_order > 0) stream <<
" Linear determinant = " <<
determinant() <<
endl;
801 for (
auto it = starMatchList.
begin(); it != starMatchList.
end(); ++it) {
819 static double sq(
double x) {
return x *
x; }
822 const bool useErrors) {
823 Eigen::MatrixXd A(2 * _nterms, 2 * _nterms);
825 Eigen::VectorXd B(2 * _nterms);
828 double monomials[_nterms];
829 for (
auto it = starMatchList.
begin(); it != starMatchList.
end(); ++it) {
834 double wxx, wyy, wxy;
836 computeMonomials(point1.
x, point1.
y, monomials);
839 double vxx = (tr1.
vx + point2.
vx);
840 double vyy = (tr1.
vy + point2.
vy);
841 double vxy = (tr1.
vxy + point2.
vxy);
842 double det = vxx * vyy - vxy * vxy;
851 double resx = point2.
x - tr1.
x;
852 double resy = point2.
y - tr1.
y;
853 sumr2 += wxx * sq(resx) + wyy * sq(resy) + 2 * wxy * resx * resy;
855 double bxcoeff = wxx * resx + wxy * resy;
856 double bycoeff = wyy * resy + wxy * resx;
857 for (
unsigned j = 0; j < _nterms; ++j) {
858 for (
unsigned i = j; i < _nterms; ++i) {
859 A(i, j) += wxx * monomials[i] * monomials[j];
860 A(i + _nterms, j + _nterms) += wyy * monomials[i] * monomials[j];
861 A(j, i + _nterms) = A(i, j + _nterms) += wxy * monomials[i] * monomials[j];
863 B(j) += bxcoeff * monomials[j];
864 B(j + _nterms) += bycoeff * monomials[j];
867 Eigen::LDLT<Eigen::MatrixXd, Eigen::Lower> factor(A);
869 if (factor.info() != Eigen::Success) {
870 LOGL_ERROR(_log,
"GtransfoPoly::fit could not factorize");
874 Eigen::VectorXd sol = factor.solve(B);
875 for (
unsigned k = 0; k < 2 * _nterms; ++k) _coeffs[k] += sol(k);
876 if (starMatchList.
size() == _nterms)
return 0;
877 return (sumr2 - B.dot(sol));
881 if (starMatchList.
size() < _nterms) {
882 LOGLS_FATAL(_log,
"GtransfoPoly::fit trying to fit a polynomial transfo of order " 883 << _order <<
" with only " << starMatchList.
size() <<
" matches.");
887 GtransfoPoly conditionner = shiftAndNormalize(starMatchList);
889 computeFit(starMatchList, conditionner,
false);
890 computeFit(starMatchList, conditionner,
true);
891 double chi2 = computeFit(starMatchList, conditionner,
true);
893 (*this) = (*this) * conditionner;
894 if (starMatchList.
size() == _nterms)
return 0;
900 return std::make_unique<GtransfoLin>((*
this) * (right));
902 return std::make_unique<GtransfoPoly>((*this) * (right));
920 PolyXY(
const int order) : order(order), nterms((order + 1) * (order + 2) / 2) {
928 : order(gtransfoPoly.
getOrder()), nterms((order + 1) * (order + 2) / 2), coeffs(nterms, 0L) {
929 for (
unsigned px = 0; px <= order; ++px)
930 for (
unsigned py = 0; py <= order - px; ++py)
931 coeff(px, py) = gtransfoPoly.
coeff(px, py, whichCoord);
934 long double coeff(
const unsigned powX,
const unsigned powY)
const {
935 assert(powX + powY <= order);
936 return coeffs.
at((powX + powY) * (powX + powY + 1) / 2 + powY);
939 long double &
coeff(
const unsigned powX,
const unsigned powY) {
940 assert(powX + powY <= order);
941 return coeffs.
at((powX + powY) * (powX + powY + 1) / 2 + powY);
950 for (
unsigned i = 0; i <= rdeg; ++i)
951 for (
unsigned j = 0; j <= rdeg - i; ++j) left.
coeff(i, j) += right.
coeff(i, j);
959 for (
unsigned i = 0; i <= order; ++i)
960 for (
unsigned j = 0; j <= order - i; ++j) result.
coeff(i, j) *= a;
969 for (
unsigned i1 = 0; i1 <= deg1; ++i1)
970 for (
unsigned j1 = 0; j1 <= deg1 - i1; ++j1)
971 for (
unsigned i2 = 0; i2 <= deg2; ++i2)
972 for (
unsigned j2 = 0; j2 <= deg2 - i2; ++j2)
981 powers[0].coeff(0, 0) = 1L;
982 for (
unsigned k = 1; k <= maxP; ++k) powers.
push_back(product(powers[k - 1], polyXY));
991 computePowers(polyX, pdeg, pXPowers);
992 computePowers(polyY, pdeg, pYPowers);
993 for (
unsigned px = 0; px <= pdeg; ++px)
994 for (
unsigned py = 0; py <= pdeg - px; ++py)
995 result += polyXY.
coeff(px, py) * product(pXPowers.
at(px), pYPowers.
at(py));
1011 PolyXY rx(composition(plx, prx, pry));
1012 PolyXY ry(composition(ply, prx, pry));
1016 for (
unsigned px = 0; px <= result._order; ++px)
1017 for (
unsigned py = 0; py <= result._order - px; ++py) {
1025 if (_order >= right._order) {
1027 for (
unsigned i = 0; i <= right._order; ++i)
1028 for (
unsigned j = 0; j <= right._order - i; ++j) {
1034 return (right + (*
this));
1039 for (
unsigned i = 0; i <= res._order; ++i)
1040 for (
unsigned j = 0; j <= res._order - i; ++j) {
1049 return std::make_shared<ast::PolyMap>(toAstPolyMapCoefficients(), inverse->toAstPolyMapCoefficients());
1053 s <<
" GtransfoPoly 1" <<
endl;
1054 s <<
"order " << _order << endl;
1057 for (
unsigned k = 0; k < 2 * _nterms; ++k) s << _coeffs[k] <<
' ';
1059 s << setprecision(oldprec);
1069 s >> order >> _order;
1070 if (order !=
"order")
1072 " GtransfoPoly::read : expecting \"order\" and found " + order);
1074 for (
unsigned k = 0; k < 2 * _nterms; ++k) s >> _coeffs[k];
1077 ndarray::Array<double, 2, 2> GtransfoPoly::toAstPolyMapCoefficients()
const {
1078 int nCoeffs = _coeffs.size();
1079 ndarray::Array<double, 2, 2>
result = ndarray::allocate(ndarray::makeVector(nCoeffs, 4));
1081 ndarray::Size k = 0;
1082 for (
unsigned iCoord = 0; iCoord < 2; ++iCoord) {
1083 for (
unsigned p = 0; p <= _order; ++p) {
1084 for (
unsigned py = 0; py <= p; ++py, ++k) {
1085 result[k][0] =
coeff(p - py, py, iCoord);
1086 result[k][1] = iCoord + 1;
1087 result[k][2] = p - py;
1097 double const precision,
int const maxOrder,
1098 unsigned const nSteps) {
1100 double xStart = domain.
xMin;
1101 double yStart = domain.
yMin;
1102 double xStep = domain.
getWidth() / (nSteps - 1);
1103 double yStep = domain.
getHeight() / (nSteps - 1);
1104 for (
unsigned i = 0; i < nSteps; ++i) {
1105 for (
unsigned j = 0; j < nSteps; ++j) {
1106 Point in(xStart + i * xStep, yStart + j * yStep);
1111 unsigned npairs = sm.
size();
1117 for (order = 1; order <= maxOrder; ++order) {
1119 auto success = poly->fit(sm);
1120 if (success == -1) {
1122 errMsg <<
"Cannot fit a polynomial of order " << order <<
" with " << nSteps <<
"^2 points";
1127 for (
auto const &i : sm) chi2 += i.point2.computeDist2(poly->apply((i.point1)));
1128 LOGLS_TRACE(_log,
"inversePoly order " << order <<
": " << chi2 <<
" / " << npairs <<
" = " 1129 << chi2 / npairs <<
" < " << precision * precision);
1131 if (chi2 / npairs < precision * precision)
break;
1134 if (chi2 > oldChi2) {
1135 LOGLS_WARN(_log,
"inversePolyTransfo: chi2 increases (" << chi2 <<
" > " << oldChi2
1136 <<
"); ending fit with order: " << order);
1137 LOGLS_WARN(_log,
"inversePolyTransfo: requested precision not reached: " 1138 << chi2 <<
" / " << npairs <<
" = " << chi2 / npairs <<
" < " 1139 << precision * precision);
1149 if (order > maxOrder)
1150 LOGLS_WARN(_log,
"inversePolyTransfo: Reached max order without reaching requested precision: " 1151 << chi2 <<
" / " << npairs <<
" = " << chi2 / npairs <<
" < " 1152 << precision * precision);
1162 const double A21,
const double A22)
1175 "Trying to build a GtransfoLin from a higher order transfo. Aborting. ");
1196 derivative.
coeff(0, 0, 0) = 0;
1197 derivative.
coeff(0, 0, 1) = 0;
1213 double d = (a11 * a22 - a12 *
a21);
1216 "GtransfoLin::invert singular transformation: transfo contents will be dumped to stderr.");
1237 int npairs = starMatchList.
size();
1239 LOGLS_FATAL(_log,
"GtransfoLinShift::fit trying to fit a linear transfo with only " << npairs
1246 Eigen::VectorXd B(2);
1248 Eigen::MatrixXd A(2, 2);
1251 for (
auto const &it : starMatchList) {
1252 FatPoint const &point1 = it.point1;
1253 FatPoint const &point2 = it.point2;
1254 double deltax = point2.
x - point1.
x;
1255 double deltay = point2.
y - point1.
y;
1256 double vxx = point1.
vx + point2.
vx;
1257 double vyy = point1.
vy + point2.
vy;
1258 double vxy = point1.
vxy + point2.
vxy;
1259 double det = vxx * vyy - vxy * vxy;
1260 double wxx = vyy / det;
1261 double wyy = vxx / det;
1262 double wxy = -vxy / det;
1263 B(0) += deltax * wxx + wxy * deltay;
1264 B(1) += deltay * wyy + wxy * deltax;
1268 sumr2 += deltax * deltax * wxx + deltay * deltay * wyy + 2. * wxy * deltax * deltay;
1270 double det = A(0, 0) * A(1, 1) - A(0, 1) * A(1, 0);
1271 if (det <= 0)
return -1;
1272 double tmp = A(0, 0);
1273 A(0, 0) = A(1, 1) / det;
1274 A(1, 1) = tmp / det;
1275 A(0, 1) = A(1, 0) = -A(0, 1) / det;
1276 Eigen::VectorXd sol = A * B;
1278 return (sumr2 - sol.dot(B));
1282 double c = scaleFactor *
std::cos(angleRad);
1283 double s = scaleFactor *
std::sin(angleRad);
1289 Point a_point(0., 0.);
1290 if (center) a_point = *center;
1294 dx() = a_point.
x -
Dx();
1295 dy() = a_point.
y -
dy();
1298 static double deg2rad(
double degree) {
return degree *
M_PI / 180.; }
1300 static double rad2deg(
double rad) {
return rad * 180. /
M_PI; }
1323 linPix2Tan = pix2Tan;
1324 ra0 = deg2rad(tangentPoint.
x);
1325 dec0 = deg2rad(tangentPoint.
y);
1329 if (corrections) corr.reset(
new GtransfoPoly(*corrections));
1362 LOGL_WARN(_log,
"No sidereal coordinates at pole!");
1371 if (rat < 0.0) rat += (2. *
M_PI);
1373 xOut = rad2deg(rat);
1374 yOut = rad2deg(dect);
1392 return Point(inverse.
Dx(), inverse.
Dy());
1400 auto const outCoord = _skyWcs->pixelToSky(afw::geom::Point2D(xIn, yIn));
1401 xOut = outCoord[0].asDegrees();
1402 yOut = outCoord[1].asDegrees();
1419 :
BaseTanWcs(pix2Tan, tangentPoint, corrections) {}
1426 return std::make_unique<TanPix2RaDec>((*this) * (right));
1439 if (
corr !=
nullptr) {
1440 LOGL_WARN(_log,
"You are inverting a TanPix2RaDec with corrections.");
1441 LOGL_WARN(_log,
"The inverse you get ignores the corrections!");
1468 double xtmp = xTangentPlane;
1469 double ytmp = yTangentPlane;
1470 corr->apply(xtmp, ytmp, xTangentPlane, yTangentPlane);
1481 stream <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1483 stream <<
" crpix " << crpix.
x <<
' ' << crpix.
y <<
endl;
1484 if (
corr) stream <<
"PV correction: " <<
endl << *
corr;
1497 "TanPix2RaDec::fit is NOT implemented (although it is doable)) ");
1505 :
BaseTanWcs(pix2Tan, tangentPoint, corrections) {}
1533 double &yTangentPlane)
const {
1537 corr->apply(xPixel, yPixel, xtmp, ytmp);
1550 stream <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1552 stream <<
" crpix " << crpix.
x <<
' ' << crpix.
y <<
endl;
1553 if (
corr) stream <<
"PV correction: " <<
endl << *
corr;
1566 "TanSipPix2RaDec::fit is NOT implemented (although it is doable)) ");
1579 ra0 = deg2rad(tangentPoint.
x);
1580 dec0 = deg2rad(tangentPoint.
y);
1612 double ra = deg2rad(in.
x);
1613 double dec = deg2rad(in.
y);
1614 if (ra - ra0 >
M_PI) ra -= (2. *
M_PI);
1615 if (ra - ra0 < -
M_PI) ra += (2. *
M_PI);
1623 double l = sinda * coss;
1624 double m = sins * sin0 + coss * cos0 * cosda;
1626 m = (sins * cos0 - coss * sin0 * cosda) / m;
1630 sq(sin0) - sq(coss) + sq(coss * cos0) * (1 + sq(cosda)) + 2 * sins * sin0 * coss * cos0 * cosda;
1631 double a11 = coss * (cosda * sins * sin0 + coss * cos0) / deno;
1632 double a12 = -sinda * sin0 / deno;
1633 double a21 = coss * sinda * sins / deno;
1634 double a22 = cosda / deno;
1637 tmp.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
1638 tmp.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
1639 tmp.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
1649 double ra = deg2rad(xIn);
1650 double dec = deg2rad(yIn);
1651 if (ra - ra0 >
M_PI) ra -= (2. *
M_PI);
1652 if (ra - ra0 < -
M_PI) ra += (2. *
M_PI);
1657 double l =
std::sin(ra - ra0) * coss;
1658 double m = sins * sin0 + coss * cos0 *
std::cos(ra - ra0);
1660 m = (sins * cos0 - coss * sin0 *
std::cos(ra - ra0)) / m;
1664 linTan2Pix.
apply(l, m, xOut, yOut);
1673 stream <<
" tan2pix " << linTan2Pix <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1690 "TanRaDec2Pix::fit is NOT implemented (although it is doable)) ");
1698 : _userFun(userFun), _userData(userData) {}
1701 _userFun(xIn, yIn, xOut, yOut, _userData);
1705 stream <<
"UserTransfo with user function @ " << _userFun <<
"and userData@ " << _userData <<
endl;
1710 "UserTransfo::fit is NOT implemented (and will never be)) ");
1739 "gtransfoRead : could not find a Gtransfotype");
1740 if (type ==
"GtransfoIdentity") {
1744 }
else if (type ==
"GtransfoPoly") {
1750 " 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.
double fit(StarMatchList const &starMatchList)
fits a transfo to a std::list of Point pairs (p1,p2, the Point fields in StarMatch).
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).
void apply(const double xIn, const double yIn, double &xOut, double &yOut) const override
std::unique_ptr< Gtransfo > inverseTransfo(const double precision, const Frame ®ion) const
Inverse transfo: returns a TanPix2RaDec.
std::shared_ptr< ast::Mapping > toAstMap(jointcal::Frame const &domain) const override
Create an equivalent AST mapping for this transformation, including an analytic inverse if possible...
double paramRef(const int i) const override
GtransfoLin inverted() const
returns the inverse: T1 = T2.inverted();
std::ostream & operator<<(std::ostream &out, CcdImageKey const &key)
A hanger for star associations.
BaseTanWcs(GtransfoLin const &pix2Tan, Point const &tangentPoint, const GtransfoPoly *corrections=nullptr)
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)
double fit(StarMatchList const &starMatchList)
fits a transfo to a std::list of Point pairs (p1,p2, the Point fields in StarMatch).
virtual char const * what(void) const noexcept
long double & coeff(const unsigned powX, const unsigned powY)
double fit(StarMatchList const &starMatchList)
guess what
PolyXY(GtransfoPoly const >ransfoPoly, const unsigned whichCoord)
TanPix2RaDec operator*(GtransfoLin const &right) const
composition with GtransfoLin
void setOrder(const unsigned order)
Sets the polynomial order (the highest sum of exponents of the largest monomial). ...
GtransfoLin operator*(GtransfoLin const &right) const
enables to combine linear tranformations: T1=T2*T3 is legal.
void write(std::ostream &s) const override
GtransfoPoly(const unsigned order=1)
Default transfo : identity for all orders (>=1 ).
table::PointKey< double > crpix
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 apply(const double xIn, const double yIn, double &xOut, double &yOut) const
#define LOGLS_TRACE(logger, message)
void computeDerivative(Point const &where, GtransfoLin &derivative, const double step=0.01) const override
Computes the local Derivative of a transfo, w.r.t.
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.
void computeDerivative(Point const &where, GtransfoLin &derivative, const double step=0.01) const
specialised analytic routine
double xMin
coordinate of boundary.
double fit(StarMatchList const &starMatchList)
Not implemented yet, because we do it otherwise.
Extent< double, N > & operator+=(Extent< double, N > &lhs, Extent< int, N > const &rhs) noexcept
GtransfoPoly operator*(GtransfoPoly const &right) const
Composition (internal stuff in quadruple precision)
void dump(std::ostream &stream) const
dumps the transfo coefficients to stream.
double fit(StarMatchList const &starMatchList)
fits a transfo to a std::list of Point pairs (p1,p2, the Point fields in StarMatch).
#define LOGLS_FATAL(logger, message)
Polynomial transformation class.
std::shared_ptr< GtransfoPoly > inversePolyTransfo(Gtransfo const &forward, Frame const &domain, double const precision, int const maxOrder=9, unsigned const nSteps=50)
Approximate the inverse by a polynomial, to some precision.
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)
std::unique_ptr< Gtransfo > composeAndReduce(GtransfoLin const &right) const
Return a reduced composition of newTransfo = this(right()), or nullptr if it cannot be reduced...
GtransfoPoly getPix2TangentPlane() const
the transformation from pixels to tangent plane (degrees)
A Point with uncertainties.
std::unique_ptr< Gtransfo > clone() const
returns a copy (allocated by new) of the transformation.
std::unique_ptr< Gtransfo > roughInverse(const Frame ®ion) const
Overload the "generic routine" (available for all Gtransfo types.
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.
double getHeight() const
size along y axis
double coeffOrZero(const unsigned powX, const unsigned powY, const unsigned whichCoord) const
read access, zero if beyond order
void read(std::istream &s)
rectangle with sides parallel to axes.
GtransfoComposition(Gtransfo const &second, Gtransfo const &first)
will pipe transfos
TanRaDec2Pix inverted() const
approximate inverse : it ignores corrections;
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.
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 > 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.
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)
Point getTangentPoint() const
tangent point coordinates (degrees)
std::shared_ptr< afw::geom::SkyWcs > getSkyWcs() const
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.
virtual std::unique_ptr< Gtransfo > composeAndReduce(Gtransfo const &right) const
Return a reduced composition of newTransfo = this(right()), or nullptr if it cannot be reduced...
double fit(StarMatchList const &starMatchList) override
guess what
T dynamic_pointer_cast(T... args)
std::shared_ptr< ast::Mapping > toAstMap(jointcal::Frame const &domain) const override
Create an equivalent AST mapping for this transformation, including an analytic inverse if possible...
double fit(StarMatchList const &starMatchList)
guess what
void dump(std::ostream &stream=std::cout) const override
print out of coefficients in a readable form.
virtual GtransfoLin linearApproximation(Point const &where, const double step=0.01) const override
linear approximation.
double fit(StarMatchList const &starMatchList)
fits a transfo to a std::list of Point pairs (p1,p2, the Point fields in StarMatch).
std::unique_ptr< SchemaItem< U > > result
double getWidth() const
size along x axis
unsigned getOrder() const
Returns the polynomial order.
Point getCenter() const
Center of the frame.
A do-nothing transformation. It anyway has dummy routines to mimick a Gtransfo.
#define LSST_EXCEPT(type,...)
just here to provide a specialized constructor, and fit.
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...
void computeDerivative(Point const &where, GtransfoLin &derivative, const double step=0.01) const override
specialised analytic routine
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
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.
TanPix2RaDec inverted() const
exact typed inverse:
void dump(std::ostream &stream) const
dumps the transfo coefficients to stream.
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.
GtransfoPoly operator-(GtransfoPoly const &right) const
Subtraction.
GtransfoPoly getPix2TangentPlane() const
the transformation from pixels to tangent plane (degrees)
GtransfoSkyWcs(std::shared_ptr< afw::geom::SkyWcs > skyWcs)
long double coeff(const unsigned powX, const unsigned powY) const
void paramDerivatives(Point const &where, double *dx, double *dy) const override
Derivative w.r.t parameters.
void write(std::ostream &s) const override
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.
void setTangentPoint(Point const &tangentPoint)
Resets the projection (or tangent) point.
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...)
virtual void dump(std::ostream &stream=std::cout) const =0
dumps the transfo coefficients to stream.
void apply(const double xIn, const double yIn, double &xOut, double &yOut) const override
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)
unsigned getOrder() const
double fit(const StarMatchList &starMatchList) override
Not implemented; throws pex::exceptions::LogicError.
double fit(StarMatchList const &starMatchList)
Not implemented yet, because we do it otherwise.
GtransfoLin linearApproximation(Point const &where, const double step=0.01) const
linear (local) approximation.
virtual void transformPosAndErrors(const FatPoint &in, FatPoint &out) const override
a mix of apply and Derivative
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!
std::unique_ptr< Gtransfo > composeAndReduce(GtransfoPoly const &right) const
Return a reduced composition of newTransfo = this(right()), or nullptr if it cannot be reduced...
double determinant() const
void dump(std::ostream &stream=std::cout) const override
dumps the transfo coefficients to stream.
T emplace_back(T... args)
GtransfoPoly operator+(GtransfoPoly const &right) const
Addition.
std::unique_ptr< Gtransfo > gtransfoCompose(Gtransfo const &left, Gtransfo const &right)
Returns a pointer to a composition of gtransfos, representing left(right()).