18 #include "Eigen/Cholesky" 25 LOG_LOGGER _log =
LOG_GET(
"jointcal.Gtransfo");
33 if (shift ==
nullptr)
return false;
35 static const double eps = 1e-5;
37 double dx = shift->
coeff(0, 0, 0);
38 double dy = shift->
coeff(0, 0, 1);
40 static Point dumb(4000, 4000);
42 fabs(dumb.
x + dx - shift->
apply(dumb).x) < eps &&
fabs(dumb.
y + dy - shift->
apply(dumb).y) < eps)
50 Frame Gtransfo::apply(
Frame const &inputframe,
bool inscribed)
const {
52 double xtmin1, xtmax1, ytmin1, ytmax1;
53 apply(inputframe.
xMin, inputframe.
yMin, xtmin1, ytmin1);
54 apply(inputframe.
xMax, inputframe.
yMax, xtmax1, ytmax1);
58 double xtmin2, xtmax2, ytmin2, ytmax2;
59 apply(inputframe.
xMin, inputframe.
yMax, xtmin2, ytmax2);
60 apply(inputframe.
xMax, inputframe.
yMin, xtmax2, ytmin2);
64 if (inscribed)
return fr1 * fr2;
73 double Gtransfo::getJacobian(
const double x,
const double y)
const {
75 double eps = x * 0.01;
76 if (eps == 0) eps = 0.01;
79 apply(x + eps, y, dxdx, dydx);
83 apply(x, y + eps, dxdy, dydy);
86 return ((dxdx * dydy - dxdy * dydx) / (eps * eps));
92 void Gtransfo::computeDerivative(
Point const &where,
GtransfoLin &derivative,
const double step)
const {
96 apply(x, y, xp0, yp0);
99 apply(x + step, y, xp, yp);
100 derivative.
a11() = (xp - xp0) / step;
101 derivative.
a21() = (yp - yp0) / step;
102 apply(x, y + step, xp, yp);
103 derivative.
a12() = (xp - xp0) / step;
104 derivative.
a22() = (yp - yp0) / step;
110 Point outwhere = apply(where);
112 computeDerivative(where, der, step);
122 computeDerivative(in, der, 0.01);
123 double a11 = der.
A11();
124 double a22 = der.
A22();
125 double a21 = der.
A21();
126 double a12 = der.
A12();
127 res.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
128 res.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
129 res.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
133 void Gtransfo::transformErrors(
Point const &where,
const double *vIn,
double *vOut)
const {
135 computeDerivative(where, der, 0.01);
136 double a11 = der.
A11();
137 double a22 = der.
A22();
138 double a21 = der.
A21();
139 double a12 = der.
A12();
154 double b11 = a11 * vIn[xx] + a12 * vIn[xy];
155 double b22 = a21 * vIn[xy] + a22 * vIn[yy];
156 double b12 = a11 * vIn[xy] + a12 * vIn[yy];
157 double b21 = a21 * vIn[xx] + a22 * vIn[xy];
161 vOut[xx] = b11 * a11 + b12 * a12;
162 vOut[xy] = b11 * a21 + b12 * a22;
163 vOut[yy] = b21 * a21 + b22 * a22;
169 Point centerIn = apply(centerOut);
171 computeDerivative(centerOut, der,
sqrt(region.
getArea()) / 5.);
186 void Gtransfo::getParams(
double *params)
const {
187 int npar = getNpar();
188 for (
int i = 0; i < npar; ++i) params[i] = paramRef(i);
191 void Gtransfo::offsetParams(Eigen::VectorXd
const &delta) {
192 int npar = getNpar();
193 for (
int i = 0; i < npar; ++i) paramRef(i) += delta[i];
196 double Gtransfo::paramRef(
const int)
const {
198 std::string(
"Gtransfo::paramRef should never be called "));
201 double &Gtransfo::paramRef(
const int) {
205 void Gtransfo::paramDerivatives(
Point const &,
double *,
double *)
const {
207 "Gtransfo::paramDerivatives() should never be called ");
211 gtransfo.
dump(stream);
222 "Gtransfo::write, something went wrong for file " + fileName);
227 "Gtransfo::write(ostream), should never be called. MEans that it is missing in some " 246 void apply(
const double xIn,
const double yIn,
double &xOut,
double &yOut)
const;
248 void dump(
ostream &stream)
const;
272 GtransfoInverse::GtransfoInverse(
const Gtransfo *direct,
const double precision,
const Frame ®ion) {
273 _direct = direct->
clone();
274 _roughInverse = _direct->roughInverse(region);
275 precision2 = precision * precision;
279 _direct = model._direct->clone();
280 _roughInverse = model._roughInverse->clone();
281 precision2 = model.precision2;
287 _direct = model._direct->clone();
288 _roughInverse = model._roughInverse->clone();
289 precision2 = model.precision2;
294 Point outGuess = _roughInverse->apply(in);
301 Point inGuess = _direct->apply(outGuess);
302 _direct->computeDerivative(outGuess, directDer);
303 reverseDer = directDer.
invert();
304 double xShift, yShift;
305 reverseDer.
apply(xIn - inGuess.
x, yIn - inGuess.
y, xShift, yShift);
306 outGuess.
x += xShift;
307 outGuess.
y += yShift;
308 move2 = xShift * xShift + yShift * yShift;
309 }
while ((move2 > precision2) && (loop < maxloop));
310 if (loop == maxloop)
LOGLS_WARN(_log,
"Problems applying GtransfoInverse at " << in);
316 stream <<
" GtransfoInverse of :" <<
endl << *_direct <<
endl;
343 void apply(
const double xIn,
const double yIn,
double &xOut,
double &yOut)
const;
354 _first = first.
clone();
355 _second = second.
clone();
360 _first->apply(xIn, yIn, xout, yout);
361 _second->apply(xout, yout, xOut, yOut);
365 _first->dump(stream);
366 _second->dump(stream);
371 return _first->fit(starMatchList);
375 return std::make_unique<GtransfoComposition>(*_second, *_first);
389 if (composition ==
nullptr)
390 return std::make_unique<GtransfoComposition>(left, right);
406 return std::make_shared<ast::UnitMap>(2);
416 " GtransfoIdentity::read : format is not 1 ");
424 _nterms = (order + 1) * (order + 2) / 2;
427 _coeffs.
resize(2 * _nterms, 0.);
440 for (
double x = frame.
xMin + step / 2;
x <= frame.
xMax;
x += step)
441 for (
double y = frame.
yMin + step / 2;
y <= frame.
yMax;
y += step) {
442 auto pix = std::make_shared<BaseStar>(
x,
y, 0, 0);
444 gtransfo->
apply(x, y, xtr, ytr);
445 auto tp = std::make_shared<BaseStar>(xtr, ytr, 0, 0);
457 jointcal::Frame const &domain,
unsigned const order,
unsigned const nSteps) {
459 double xStart = domain.
xMin;
460 double yStart = domain.
yMin;
461 double xStep = domain.
getWidth() / (nSteps + 1);
462 double yStep = domain.
getHeight() / (nSteps + 1);
463 for (
unsigned i = 0; i < nSteps; ++i) {
464 for (
unsigned j = 0; j < nSteps; ++j) {
474 poly.
fit(starMatchList);
478 void GtransfoPoly::computeMonomials(
double xIn,
double yIn,
double *monomial)
const {
489 for (
unsigned ix = 0; ix <= _order; ++ix) {
491 unsigned k = ix * (ix + 1) / 2;
492 for (
unsigned iy = 0; iy <= _order - ix; ++iy) {
493 monomial[k] = xx * yy;
503 unsigned old_nterms = _nterms;
504 _nterms = (_order + 1) * (_order + 2) / 2;
509 _coeffs.
resize(2 * _nterms);
512 for (
unsigned k = 0; k < _nterms; ++k) _coeffs[k] = 0;
514 unsigned kmax =
min(old_nterms, _nterms);
515 for (
unsigned k = 0; k < kmax; ++k) {
516 _coeffs[k] = old_coeffs[k];
517 _coeffs[k + _nterms] = old_coeffs[k + old_nterms];
532 double monomials[_nterms];
533 computeMonomials(xIn, yIn, monomials);
537 const double *c = &_coeffs[0];
538 const double *pm = &monomials[0];
540 for (
int k = _nterms; k--;) xOut += (*(pm++)) * (*(c++));
542 for (
int k = _nterms; k--;) yOut += (*(pm++)) * (*(c++));
549 derivative.
dx() = derivative.
dy() = 0;
553 double dermx[2 * _nterms];
554 double *dermy = dermx + _nterms;
555 double xin = where.
x;
556 double yin = where.
y;
560 for (
unsigned ix = 0; ix <= _order; ++ix) {
561 unsigned k = (ix) * (ix + 1) / 2;
563 dermx[k] = ix * xxm1;
567 for (
unsigned iy = 1; iy <= _order - ix; ++iy) {
568 dermx[k] = ix * xxm1 * yym1 * yin;
569 dermy[k] = iy * xx * yym1;
574 if (ix >= 1) xxm1 *= xin;
580 const double *mx = &dermx[0];
581 const double *my = &dermy[0];
582 const double *c = &_coeffs[0];
584 double a11 = 0, a12 = 0;
585 for (
int k = _nterms; k--;) {
586 a11 += (*(mx++)) * (*c);
587 a12 += (*(my++)) * (*(c++));
589 derivative.
a11() = a11;
590 derivative.
a12() = a12;
592 double a21 = 0, a22 = 0;
595 for (
int k = _nterms; k--;) {
596 a21 += (*(mx++)) * (*c);
597 a22 += (*(my++)) * (*(c++));
599 derivative.
a21() = a21;
600 derivative.
a22() = a22;
616 double monomials[_nterms];
620 double dermx[2 * _nterms];
621 double *dermy = dermx + _nterms;
627 for (
unsigned ix = 0; ix <= _order; ++ix) {
628 unsigned k = (ix) * (ix + 1) / 2;
630 dermx[k] = ix * xxm1;
636 for (
unsigned iy = 1; iy <= _order - ix; ++iy) {
637 monomials[k] = xx * yy;
638 dermx[k] = ix * xxm1 * yy;
639 dermy[k] = iy * xx * yym1;
645 if (ix >= 1) xxm1 *= xin;
649 double xout = 0, yout = 0;
650 const double *c = &_coeffs[0];
651 const double *pm = &monomials[0];
652 for (
int k = _nterms; k--;) xout += (*(pm++)) * (*(c++));
654 for (
int k = _nterms; k--;) yout += (*(pm++)) * (*(c++));
660 const double *mx = &dermx[0];
661 const double *my = &dermy[0];
662 double a11 = 0, a12 = 0;
663 for (
int k = _nterms; k--;) {
664 a11 += (*(mx++)) * (*c);
665 a12 += (*(my++)) * (*(c++));
668 double a21 = 0, a22 = 0;
671 for (
int k = _nterms; k--;) {
672 a21 += (*(mx++)) * (*c);
673 a22 += (*(my++)) * (*(c++));
677 res.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
678 res.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
679 res.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
688 assert((degX + degY <= _order) && whichCoord < 2);
692 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
696 assert((degX + degY <= _order) && whichCoord < 2);
697 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
702 assert(whichCoord < 2);
703 if (degX + degY <= _order)
704 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
710 assert(
unsigned(i) < 2 * _nterms);
715 assert(
unsigned(i) < 2 * _nterms);
721 computeMonomials(where.
x, where.
y, dx);
722 for (
unsigned k = 0; k < _nterms; ++k) {
723 dy[_nterms + k] = dx[k];
724 dx[_nterms + k] = dy[k] = 0;
729 static string monomialString(
const unsigned powX,
const unsigned powY) {
731 if (powX + powY) ss <<
"*";
732 if (powX > 0) ss <<
"x";
733 if (powX > 1) ss <<
"^" << powX;
734 if (powY > 0) ss <<
"y";
735 if (powY > 1) ss <<
"^" << powY;
742 for (
unsigned ic = 0; ic < 2; ++ic) {
747 for (
unsigned p = 0; p <= _order; ++p)
748 for (
unsigned py = 0; py <= p; ++py) {
749 if (p + py != 0) stream <<
" + ";
750 stream <<
coeff(p - py, py, ic) << monomialString(p - py, py);
754 if (_order > 0) stream <<
" Linear determinant = " <<
determinant() <<
endl;
777 for (
auto it = starMatchList.
begin(); it != starMatchList.
end(); ++it) {
790 double xspan = 3.5 *
sqrt(x2 / count -
std::pow(xav, 2));
791 double yspan = 3.5 *
sqrt(y2 / count -
std::pow(yav, 2));
795 static double sq(
double x) {
return x *
x; }
798 const bool useErrors) {
799 Eigen::MatrixXd A(2 * _nterms, 2 * _nterms);
801 Eigen::VectorXd B(2 * _nterms);
804 double monomials[_nterms];
805 for (
auto it = starMatchList.
begin(); it != starMatchList.
end(); ++it) {
810 double wxx, wyy, wxy;
812 computeMonomials(point1.
x, point1.
y, monomials);
815 double vxx = (tr1.
vx + point2.
vx);
816 double vyy = (tr1.
vy + point2.
vy);
817 double vxy = (tr1.
vxy + point2.
vxy);
818 double det = vxx * vyy - vxy * vxy;
827 double resx = point2.
x - tr1.
x;
828 double resy = point2.
y - tr1.
y;
829 sumr2 += wxx * sq(resx) + wyy * sq(resy) + 2 * wxy * resx * resy;
831 double bxcoeff = wxx * resx + wxy * resy;
832 double bycoeff = wyy * resy + wxy * resx;
833 for (
unsigned j = 0; j < _nterms; ++j) {
834 for (
unsigned i = j; i < _nterms; ++i) {
835 A(i, j) += wxx * monomials[i] * monomials[j];
836 A(i + _nterms, j + _nterms) += wyy * monomials[i] * monomials[j];
837 A(j, i + _nterms) = A(i, j + _nterms) += wxy * monomials[i] * monomials[j];
839 B(j) += bxcoeff * monomials[j];
840 B(j + _nterms) += bycoeff * monomials[j];
843 Eigen::LDLT<Eigen::MatrixXd, Eigen::Lower> factor(A);
845 if (factor.info() != Eigen::Success) {
846 LOGL_ERROR(_log,
"GtransfoPoly::fit could not factorize");
850 Eigen::VectorXd sol = factor.solve(B);
851 for (
unsigned k = 0; k < 2 * _nterms; ++k) _coeffs[k] += sol(k);
852 if (starMatchList.
size() == _nterms)
return 0;
853 return (sumr2 - B.dot(sol));
857 if (starMatchList.
size() < _nterms) {
858 LOGLS_FATAL(_log,
"GtransfoPoly::fit trying to fit a polynomial transfo of order " 859 << _order <<
" with only " << starMatchList.
size() <<
" matches.");
863 GtransfoPoly conditionner = shiftAndNormalize(starMatchList);
865 computeFit(starMatchList, conditionner,
false);
866 computeFit(starMatchList, conditionner,
true);
867 double chi2 = computeFit(starMatchList, conditionner,
true);
869 (*this) = (*this) * conditionner;
870 if (starMatchList.
size() == _nterms)
return 0;
876 return std::make_unique<GtransfoLin>((*
this) * (right));
878 return std::make_unique<GtransfoPoly>((*this) * (right));
896 PolyXY(
const int order) : order(order), nterms((order + 1) * (order + 2) / 2) {
904 : order(gtransfoPoly.
getOrder()), nterms((order + 1) * (order + 2) / 2), coeffs(nterms, 0L) {
905 for (
unsigned px = 0; px <= order; ++px)
906 for (
unsigned py = 0; py <= order - px; ++py)
907 coeff(px, py) = gtransfoPoly.
coeff(px, py, whichCoord);
910 long double coeff(
const unsigned powX,
const unsigned powY)
const {
911 assert(powX + powY <= order);
912 return coeffs.
at((powX + powY) * (powX + powY + 1) / 2 + powY);
915 long double &
coeff(
const unsigned powX,
const unsigned powY) {
916 assert(powX + powY <= order);
917 return coeffs.
at((powX + powY) * (powX + powY + 1) / 2 + powY);
926 for (
unsigned i = 0; i <= rdeg; ++i)
927 for (
unsigned j = 0; j <= rdeg - i; ++j) left.
coeff(i, j) += right.
coeff(i, j);
935 for (
unsigned i = 0; i <= order; ++i)
936 for (
unsigned j = 0; j <= order - i; ++j) result.
coeff(i, j) *= a;
945 for (
unsigned i1 = 0; i1 <= deg1; ++i1)
946 for (
unsigned j1 = 0; j1 <= deg1 - i1; ++j1)
947 for (
unsigned i2 = 0; i2 <= deg2; ++i2)
948 for (
unsigned j2 = 0; j2 <= deg2 - i2; ++j2)
957 powers[0].coeff(0, 0) = 1L;
958 for (
unsigned k = 1; k <= maxP; ++k) powers.
push_back(product(powers[k - 1], polyXY));
967 computePowers(polyX, pdeg, pXPowers);
968 computePowers(polyY, pdeg, pYPowers);
969 for (
unsigned px = 0; px <= pdeg; ++px)
970 for (
unsigned py = 0; py <= pdeg - px; ++py)
971 result += polyXY.
coeff(px, py) * product(pXPowers.
at(px), pYPowers.
at(py));
987 PolyXY rx(composition(plx, prx, pry));
988 PolyXY ry(composition(ply, prx, pry));
992 for (
unsigned px = 0; px <= result._order; ++px)
993 for (
unsigned py = 0; py <= result._order - px; ++py) {
1001 if (_order >= right._order) {
1003 for (
unsigned i = 0; i <= right._order; ++i)
1004 for (
unsigned j = 0; j <= right._order - i; ++j) {
1010 return (right + (*
this));
1015 for (
unsigned i = 0; i <= res._order; ++i)
1016 for (
unsigned j = 0; j <= res._order - i; ++j) {
1025 return std::make_shared<ast::PolyMap>(toAstPolyMapCoefficients(), inverse->toAstPolyMapCoefficients());
1029 s <<
" GtransfoPoly 1" <<
endl;
1030 s <<
"order " << _order << endl;
1033 for (
unsigned k = 0; k < 2 * _nterms; ++k) s << _coeffs[k] <<
' ';
1035 s << setprecision(oldprec);
1045 s >> order >> _order;
1046 if (order !=
"order")
1048 " GtransfoPoly::read : expecting \"order\" and found " + order);
1050 for (
unsigned k = 0; k < 2 * _nterms; ++k) s >> _coeffs[k];
1053 ndarray::Array<double, 2, 2> GtransfoPoly::toAstPolyMapCoefficients()
const {
1054 int nCoeffs = _coeffs.size();
1055 ndarray::Array<double, 2, 2>
result = ndarray::allocate(ndarray::makeVector(nCoeffs, 4));
1057 ndarray::Size k = 0;
1058 for (
unsigned iCoord = 0; iCoord < 2; ++iCoord) {
1059 for (
unsigned p = 0; p <= _order; ++p) {
1060 for (
unsigned py = 0; py <= p; ++py, ++k) {
1061 result[k][0] =
coeff(p - py, py, iCoord);
1062 result[k][1] = iCoord + 1;
1063 result[k][2] = p - py;
1073 double const precision,
int const maxOrder,
1074 unsigned const nSteps) {
1076 double xStart = domain.
xMin;
1077 double yStart = domain.
yMin;
1078 double xStep = domain.
getWidth() / (nSteps - 1);
1079 double yStep = domain.
getHeight() / (nSteps - 1);
1080 for (
unsigned i = 0; i < nSteps; ++i) {
1081 for (
unsigned j = 0; j < nSteps; ++j) {
1082 Point in(xStart + i * xStep, yStart + j * yStep);
1087 unsigned npairs = sm.
size();
1093 for (order = 1; order <= maxOrder; ++order) {
1095 auto success = poly->fit(sm);
1096 if (success == -1) {
1098 errMsg <<
"Cannot fit a polynomial of order " << order <<
" with " << nSteps <<
"^2 points";
1103 for (
auto const &i : sm) chi2 += i.point2.computeDist2(poly->apply((i.point1)));
1104 LOGLS_TRACE(_log,
"inversePoly order " << order <<
": " << chi2 <<
" / " << npairs <<
" = " 1105 << chi2 / npairs <<
" < " << precision * precision);
1107 if (chi2 / npairs < precision * precision)
break;
1110 if (chi2 > oldChi2) {
1111 LOGLS_WARN(_log,
"inversePolyTransfo: chi2 increases (" << chi2 <<
" > " << oldChi2
1112 <<
"); ending fit with order: " << order);
1113 LOGLS_WARN(_log,
"inversePolyTransfo: requested precision not reached: " 1114 << chi2 <<
" / " << npairs <<
" = " << chi2 / npairs <<
" < " 1115 << precision * precision);
1125 if (order > maxOrder)
1126 LOGLS_WARN(_log,
"inversePolyTransfo: Reached max order without reaching requested precision: " 1127 << chi2 <<
" / " << npairs <<
" = " << chi2 / npairs <<
" < " 1128 << precision * precision);
1138 const double A21,
const double A22)
1151 "Trying to build a GtransfoLin from a higher order transfo. Aborting. ");
1172 derivative.
coeff(0, 0, 0) = 0;
1173 derivative.
coeff(0, 0, 1) = 0;
1189 double d = (a11 * a22 - a12 *
a21);
1192 "GtransfoLin::invert singular transformation: transfo contents will be dumped to stderr.");
1213 int npairs = starMatchList.
size();
1215 LOGLS_FATAL(_log,
"GtransfoLinShift::fit trying to fit a linear transfo with only " << npairs
1222 Eigen::VectorXd B(2);
1224 Eigen::MatrixXd A(2, 2);
1227 for (
auto const &it : starMatchList) {
1228 FatPoint const &point1 = it.point1;
1229 FatPoint const &point2 = it.point2;
1230 double deltax = point2.
x - point1.
x;
1231 double deltay = point2.
y - point1.
y;
1232 double vxx = point1.
vx + point2.
vx;
1233 double vyy = point1.
vy + point2.
vy;
1234 double vxy = point1.
vxy + point2.
vxy;
1235 double det = vxx * vyy - vxy * vxy;
1236 double wxx = vyy / det;
1237 double wyy = vxx / det;
1238 double wxy = -vxy / det;
1239 B(0) += deltax * wxx + wxy * deltay;
1240 B(1) += deltay * wyy + wxy * deltax;
1244 sumr2 += deltax * deltax * wxx + deltay * deltay * wyy + 2. * wxy * deltax * deltay;
1246 double det = A(0, 0) * A(1, 1) - A(0, 1) * A(1, 0);
1247 if (det <= 0)
return -1;
1248 double tmp = A(0, 0);
1249 A(0, 0) = A(1, 1) / det;
1250 A(1, 1) = tmp / det;
1251 A(0, 1) = A(1, 0) = -A(0, 1) / det;
1252 Eigen::VectorXd sol = A * B;
1254 return (sumr2 - sol.dot(B));
1258 double c = scaleFactor *
cos(angleRad);
1259 double s = scaleFactor *
sin(angleRad);
1265 Point a_point(0., 0.);
1266 if (center) a_point = *center;
1270 dx() = a_point.
x -
Dx();
1271 dy() = a_point.
y -
dy();
1274 static double deg2rad(
double degree) {
return degree *
M_PI / 180.; }
1276 static double rad2deg(
double rad) {
return rad * 180. /
M_PI; }
1299 linPix2Tan = pix2Tan;
1300 ra0 = deg2rad(tangentPoint.
x);
1301 dec0 = deg2rad(tangentPoint.
y);
1305 if (corrections) corr.reset(
new GtransfoPoly(*corrections));
1338 LOGL_WARN(_log,
"No sidereal coordinates at pole!");
1347 if (rat < 0.0) rat += (2. *
M_PI);
1349 xOut = rad2deg(rat);
1350 yOut = rad2deg(dect);
1368 return Point(inverse.
Dx(), inverse.
Dy());
1377 xOut = outCoord[0].asDegrees();
1378 yOut = outCoord[1].asDegrees();
1395 :
BaseTanWcs(pix2Tan, tangentPoint, corrections) {}
1402 return std::make_unique<TanPix2RaDec>((*this) * (right));
1415 if (
corr !=
nullptr) {
1416 LOGL_WARN(_log,
"You are inverting a TanPix2RaDec with corrections.");
1417 LOGL_WARN(_log,
"The inverse you get ignores the corrections!");
1444 double xtmp = xTangentPlane;
1445 double ytmp = yTangentPlane;
1446 corr->apply(xtmp, ytmp, xTangentPlane, yTangentPlane);
1457 stream <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1459 stream <<
" crpix " << crpix.
x <<
' ' << crpix.
y <<
endl;
1460 if (
corr) stream <<
"PV correction: " <<
endl << *
corr;
1473 "TanPix2RaDec::fit is NOT implemented (although it is doable)) ");
1481 :
BaseTanWcs(pix2Tan, tangentPoint, corrections) {}
1509 double &yTangentPlane)
const {
1513 corr->apply(xPixel, yPixel, xtmp, ytmp);
1526 stream <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1528 stream <<
" crpix " << crpix.
x <<
' ' << crpix.
y <<
endl;
1529 if (
corr) stream <<
"PV correction: " <<
endl << *
corr;
1542 "TanSipPix2RaDec::fit is NOT implemented (although it is doable)) ");
1555 ra0 = deg2rad(tangentPoint.
x);
1556 dec0 = deg2rad(tangentPoint.
y);
1588 double ra = deg2rad(in.
x);
1589 double dec = deg2rad(in.
y);
1590 if (ra - ra0 >
M_PI) ra -= (2. *
M_PI);
1591 if (ra - ra0 < -
M_PI) ra += (2. *
M_PI);
1595 double coss =
cos(dec);
1596 double sins =
sin(dec);
1597 double sinda =
sin(ra - ra0);
1598 double cosda =
cos(ra - ra0);
1599 double l = sinda * coss;
1600 double m = sins * sin0 + coss * cos0 * cosda;
1602 m = (sins * cos0 - coss * sin0 * cosda) / m;
1606 sq(sin0) - sq(coss) + sq(coss * cos0) * (1 + sq(cosda)) + 2 * sins * sin0 * coss * cos0 * cosda;
1607 double a11 = coss * (cosda * sins * sin0 + coss * cos0) / deno;
1608 double a12 = -sinda * sin0 / deno;
1609 double a21 = coss * sinda * sins / deno;
1610 double a22 = cosda / deno;
1613 tmp.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
1614 tmp.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
1615 tmp.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
1625 double ra = deg2rad(xIn);
1626 double dec = deg2rad(yIn);
1627 if (ra - ra0 >
M_PI) ra -= (2. *
M_PI);
1628 if (ra - ra0 < -
M_PI) ra += (2. *
M_PI);
1631 double coss =
cos(dec);
1632 double sins =
sin(dec);
1633 double l =
sin(ra - ra0) * coss;
1634 double m = sins * sin0 + coss * cos0 *
cos(ra - ra0);
1636 m = (sins * cos0 - coss * sin0 * cos(ra - ra0)) / m;
1640 linTan2Pix.
apply(l, m, xOut, yOut);
1647 stream <<
" tan2pix " << linTan2Pix <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1664 "TanRaDec2Pix::fit is NOT implemented (although it is doable)) ");
1672 : _userFun(userFun), _userData(userData) {}
1675 _userFun(xIn, yIn, xOut, yOut, _userData);
1679 stream <<
"UserTransfo with user function @ " << _userFun <<
"and userData@ " << _userData <<
endl;
1684 "UserTransfo::fit is NOT implemented (and will never be)) ");
1713 "gtransfoRead : could not find a Gtransfotype");
1714 if (type ==
"GtransfoIdentity") {
1718 }
else if (type ==
"GtransfoPoly") {
1724 " 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).
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::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
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)
Relationship invert(Relationship r)
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)
GtransfoLin invert() const
returns the inverse: T1 = T2.invert();
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.
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
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.
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.
#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.
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()).