43 #include "Eigen/Cholesky"
59 if (shift ==
nullptr)
return false;
61 static const double eps = 1e-5;
66 static Point dumb(4000, 4000);
68 fabs(dumb.
x + dx - shift->
apply(dumb).x) < eps &&
fabs(dumb.
y + dy - shift->
apply(dumb).y) < eps)
76 Frame AstrometryTransform::apply(
Frame const &inputframe,
bool inscribed)
const {
78 double xtmin1, xtmax1, ytmin1, ytmax1;
79 apply(inputframe.
xMin, inputframe.
yMin, xtmin1, ytmin1);
80 apply(inputframe.
xMax, inputframe.
yMax, xtmax1, ytmax1);
84 double xtmin2, xtmax2, ytmin2, ytmax2;
85 apply(inputframe.
xMin, inputframe.
yMax, xtmin2, ytmax2);
86 apply(inputframe.
xMax, inputframe.
yMin, xtmax2, ytmin2);
90 if (inscribed)
return fr1 * fr2;
101 double eps =
x * 0.01;
102 if (eps == 0) eps = 0.01;
105 apply(
x + eps,
y, dxdx, dydx);
109 apply(
x,
y + eps, dxdy, dydy);
112 return ((dxdx * dydy - dxdy * dydx) / (eps * eps));
119 const double step)
const {
123 apply(
x,
y, xp0, yp0);
126 apply(
x +
step,
y, xp, yp);
127 derivative.
a11() = (xp - xp0) /
step;
128 derivative.
a21() = (yp - yp0) /
step;
129 apply(
x,
y +
step, xp, yp);
130 derivative.
a12() = (xp - xp0) /
step;
131 derivative.
a22() = (yp - yp0) /
step;
137 const double step)
const {
138 Point outwhere = apply(where);
140 computeDerivative(where, der,
step);
151 computeDerivative(in, der, 0.01);
152 double a11 = der.
A11();
153 double a22 = der.
A22();
154 double a21 = der.
A21();
155 double a12 = der.
A12();
156 res.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
157 res.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
158 res.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
162 void AstrometryTransform::transformErrors(
Point const &where,
const double *vIn,
double *vOut)
const {
164 computeDerivative(where, der, 0.01);
165 double a11 = der.
A11();
166 double a22 = der.
A22();
167 double a21 = der.
A21();
168 double a12 = der.
A12();
183 double b11 = a11 * vIn[xx] + a12 * vIn[xy];
184 double b22 = a21 * vIn[xy] + a22 * vIn[yy];
185 double b12 = a11 * vIn[xy] + a12 * vIn[yy];
186 double b21 = a21 * vIn[xx] + a22 * vIn[xy];
190 vOut[xx] = b11 * a11 + b12 * a12;
191 vOut[xy] = b11 * a21 + b12 * a22;
192 vOut[yy] = b21 * a21 + b22 * a22;
198 Point centerIn = apply(centerOut);
218 for (
std::size_t i = 0; i < npar; ++i) params[i] = paramRef(i);
221 void AstrometryTransform::offsetParams(Eigen::VectorXd
const &delta) {
223 for (
std::size_t i = 0; i < npar; ++i) paramRef(i) += delta[i];
226 double AstrometryTransform::paramRef(Eigen::Index
const)
const {
228 std::string(
"AstrometryTransform::paramRef should never be called "));
231 double &AstrometryTransform::paramRef(Eigen::Index
const) {
233 "AstrometryTransform::paramRef should never be called ");
236 void AstrometryTransform::paramDerivatives(
Point const &,
double *,
double *)
const {
238 "AstrometryTransform::paramDerivatives() should never be called ");
253 "AstrometryTransform::write, something went wrong for file " + fileName);
259 "AstrometryTransform::write(ostream), should never be called. MEans that it is missing in some "
275 const Frame ®ion);
279 void apply(
const double xIn,
const double yIn,
double &xOut,
double &yOut)
const;
281 void print(
ostream &out)
const;
294 return _direct->clone();
304 const Frame ®ion)
const {
309 const double precision,
const Frame ®ion) {
310 _direct = direct->
clone();
311 _roughInverse = _direct->roughInverse(region);
312 precision2 = precision * precision;
317 _direct = model._direct->clone();
318 _roughInverse = model._roughInverse->clone();
319 precision2 = model.precision2;
325 _direct = model._direct->clone();
326 _roughInverse = model._roughInverse->clone();
327 precision2 = model.precision2;
332 Point outGuess = _roughInverse->apply(in);
339 Point inGuess = _direct->apply(outGuess);
340 _direct->computeDerivative(outGuess, directDer);
342 double xShift, yShift;
343 reverseDer.
apply(xIn - inGuess.
x, yIn - inGuess.
y, xShift, yShift);
344 outGuess.
x += xShift;
345 outGuess.
y += yShift;
346 move2 = xShift * xShift + yShift * yShift;
347 }
while ((move2 > precision2) && (loop < maxloop));
348 if (loop == maxloop)
LOGLS_WARN(_log,
"Problems applying AstrometryTransformInverse at " << in);
354 stream <<
" AstrometryTransformInverse of :" <<
endl << *_direct <<
endl;
359 "Cannot fit a AstrometryTransformInverse. Use StarMatchList::inverseTransform instead.");
381 void apply(
const double xIn,
const double yIn,
double &xOut,
double &yOut)
const;
393 _first =
first.clone();
398 double &yOut)
const {
400 _first->apply(xIn, yIn, xout, yout);
401 _second->apply(xout, yout, xOut, yOut);
405 stream <<
"Composed AstrometryTransform consisting of:" <<
std::endl;
406 _first->print(stream);
407 _second->print(stream);
412 return _first->fit(starMatchList);
416 return std::make_unique<AstrometryTransformComposition>(*_second, *_first);
432 if (composition ==
nullptr)
433 return std::make_unique<AstrometryTransformComposition>(
left,
right);
440 const double)
const {
445 const double)
const {
451 return std::make_shared<ast::UnitMap>(2);
455 stream <<
"AstrometryTransformIdentity 1" <<
endl;
463 " AstrometryTransformIdentity::read : format is not 1 ");
471 _nterms = (order + 1) * (order + 2) / 2;
474 _coeffs.
resize(2 * _nterms, 0.);
491 auto pix = std::make_shared<BaseStar>(
x,
y, 0, 0);
494 auto tp = std::make_shared<BaseStar>(xtr, ytr, 0, 0);
509 double xStart = domain.
xMin;
510 double yStart = domain.
yMin;
511 double xStep = domain.
getWidth() / (nSteps + 1);
512 double yStep = domain.
getHeight() / (nSteps + 1);
524 poly.fit(starMatchList);
528 void AstrometryTransformPolynomial::computeMonomials(
double xIn,
double yIn,
double *monomial)
const {
542 for (
std::size_t iy = 0; iy <= _order - ix; ++iy) {
543 monomial[k] = xx * yy;
554 _nterms = (_order + 1) * (_order + 2) / 2;
559 _coeffs.
resize(2 * _nterms);
562 for (
std::size_t k = 0; k < _nterms; ++k) _coeffs[k] = 0;
566 _coeffs[k] = old_coeffs[k];
567 _coeffs[k + _nterms] = old_coeffs[k + old_nterms];
573 double &yOut)
const {
583 double monomials[_nterms];
584 computeMonomials(xIn, yIn, monomials);
588 const double *c = &_coeffs[0];
589 const double *pm = &monomials[0];
591 for (
int k = _nterms; k--;) xOut += (*(pm++)) * (*(c++));
593 for (
int k = _nterms; k--;) yOut += (*(pm++)) * (*(c++));
602 derivative.
dx() = derivative.
dy() = 0;
606 double dermx[2 * _nterms];
607 double *dermy = dermx + _nterms;
608 double xin = where.
x;
609 double yin = where.
y;
616 dermx[k] = ix * xxm1;
620 for (
std::size_t iy = 1; iy <= _order - ix; ++iy) {
621 dermx[k] = ix * xxm1 * yym1 * yin;
622 dermy[k] = iy * xx * yym1;
627 if (ix >= 1) xxm1 *= xin;
633 const double *mx = &dermx[0];
634 const double *my = &dermy[0];
635 const double *c = &_coeffs[0];
637 double a11 = 0, a12 = 0;
638 for (
int k = _nterms; k--;) {
639 a11 += (*(mx++)) * (*c);
640 a12 += (*(my++)) * (*(c++));
642 derivative.
a11() = a11;
643 derivative.
a12() = a12;
645 double a21 = 0, a22 = 0;
648 for (
int k = _nterms; k--;) {
649 a21 += (*(mx++)) * (*c);
650 a22 += (*(my++)) * (*(c++));
652 derivative.
a21() = a21;
653 derivative.
a22() = a22;
669 double monomials[_nterms];
673 double dermx[2 * _nterms];
674 double *dermy = dermx + _nterms;
683 dermx[k] = ix * xxm1;
689 for (
std::size_t iy = 1; iy <= _order - ix; ++iy) {
690 monomials[k] = xx * yy;
691 dermx[k] = ix * xxm1 * yy;
692 dermy[k] = iy * xx * yym1;
698 if (ix >= 1) xxm1 *= xin;
702 double xout = 0, yout = 0;
703 const double *c = &_coeffs[0];
704 const double *pm = &monomials[0];
705 for (
int k = _nterms; k--;) xout += (*(pm++)) * (*(c++));
707 for (
int k = _nterms; k--;) yout += (*(pm++)) * (*(c++));
713 const double *mx = &dermx[0];
714 const double *my = &dermy[0];
715 double a11 = 0, a12 = 0;
716 for (
int k = _nterms; k--;) {
717 a11 += (*(mx++)) * (*c);
718 a12 += (*(my++)) * (*(c++));
721 double a21 = 0, a22 = 0;
724 for (
int k = _nterms; k--;) {
725 a21 += (*(mx++)) * (*c);
726 a22 += (*(my++)) * (*(c++));
730 res.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
731 res.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
732 res.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
742 assert((degX + degY <= _order) && whichCoord < 2);
746 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
751 assert((degX + degY <= _order) && whichCoord < 2);
752 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
758 assert(whichCoord < 2);
759 if (degX + degY <= _order)
760 return _coeffs[(degX + degY) * (degX + degY + 1) / 2 + degY + whichCoord * _nterms];
766 assert(i < 2 * Eigen::Index(_nterms));
771 assert(i < 2 * Eigen::Index(_nterms));
777 computeMonomials(where.
x, where.
y, dx);
779 dy[_nterms + k] = dx[k];
780 dx[_nterms + k] = dy[k] = 0;
787 if (powX + powY) ss <<
"*";
788 if (powX > 0) ss <<
"x";
789 if (powX > 1) ss <<
"^" << powX;
790 if (powY > 0) ss <<
"y";
791 if (powY > 1) ss <<
"^" << powY;
804 bool printed =
false;
808 if (coefficient != 0 ||
isnan(coefficient)) {
810 if (printed && p +
py != 0) stream <<
" + ";
812 stream << coefficient << monomialString(p -
py,
py);
821 if (_order > 0) stream <<
"Linear determinant = " <<
determinant();
840 static AstrometryTransformLinear shiftAndNormalize(StarMatchList
const &starMatchList) {
846 for (
auto it = starMatchList.begin(); it != starMatchList.end(); ++it) {
847 const StarMatch &a_match = *it;
848 Point
const &point1 = a_match.point1;
855 if (count == 0)
return AstrometryTransformLinear();
861 return AstrometryTransformLinearScale(2. / xspan, 2. / yspan) *
862 AstrometryTransformLinearShift(-xav, -yav);
865 static double sq(
double x) {
return x *
x; }
867 double AstrometryTransformPolynomial::computeFit(StarMatchList
const &starMatchList,
868 AstrometryTransform
const &shiftToCenter,
869 const bool useErrors) {
870 Eigen::MatrixXd A(2 * _nterms, 2 * _nterms);
872 Eigen::VectorXd B(2 * _nterms);
875 double monomials[_nterms];
876 for (
auto it = starMatchList.begin(); it != starMatchList.end(); ++it) {
877 const StarMatch &a_match = *it;
878 Point tmp = shiftToCenter.apply(a_match.point1);
879 FatPoint point1(tmp, a_match.point1.vx, a_match.point1.vy, a_match.point1.vxy);
880 FatPoint
const &point2 = a_match.point2;
881 double wxx, wyy, wxy;
883 computeMonomials(point1.x, point1.y, monomials);
886 double vxx = (tr1.vx + point2.vx);
887 double vyy = (tr1.vy + point2.vy);
888 double vxy = (tr1.vxy + point2.vxy);
889 double det = vxx * vyy - vxy * vxy;
896 apply(point1.x, point1.y, tr1.x, tr1.y);
898 double resx = point2.x - tr1.x;
899 double resy = point2.y - tr1.y;
900 sumr2 += wxx * sq(resx) + wyy * sq(resy) + 2 * wxy * resx * resy;
902 double bxcoeff = wxx * resx + wxy * resy;
903 double bycoeff = wyy * resy + wxy * resx;
906 A(i, j) += wxx * monomials[i] * monomials[j];
907 A(i + _nterms, j + _nterms) += wyy * monomials[i] * monomials[j];
908 A(j, i + _nterms) = A(i, j + _nterms) += wxy * monomials[i] * monomials[j];
910 B(j) += bxcoeff * monomials[j];
911 B(j + _nterms) += bycoeff * monomials[j];
914 Eigen::LDLT<Eigen::MatrixXd, Eigen::Lower> factor(A);
916 if (factor.info() != Eigen::Success) {
917 LOGL_ERROR(_log,
"AstrometryTransformPolynomial::fit could not factorize");
921 Eigen::VectorXd sol = factor.solve(B);
922 for (
std::size_t k = 0; k < 2 * _nterms; ++k) _coeffs[k] += sol(k);
923 if (starMatchList.size() == _nterms)
return 0;
924 return (sumr2 - B.dot(sol));
928 if (starMatchList.
size() < _nterms) {
929 LOGLS_FATAL(_log,
"AstrometryTransformPolynomial::fit trying to fit a polynomial transform of order "
930 << _order <<
" with only " << starMatchList.
size() <<
" matches.");
936 computeFit(starMatchList, conditionner,
false);
937 computeFit(starMatchList, conditionner,
true);
938 double chi2 = computeFit(starMatchList, conditionner,
true);
940 (*this) = (*this) * conditionner;
941 if (starMatchList.
size() == _nterms)
return 0;
948 return std::make_unique<AstrometryTransformLinear>((*
this) * (
right));
950 return std::make_unique<AstrometryTransformPolynomial>((*
this) * (
right));
968 PolyXY(
const int order) : order(order), nterms((order + 1) * (order + 2) / 2) {
976 : order(
transform.
getOrder()), nterms((order + 1) * (order + 2) / 2), coeffs(nterms, 0L) {
984 assert(powX + powY <= order);
985 return coeffs.
at((powX + powY) * (powX + powY + 1) / 2 + powY);
989 assert(powX + powY <= order);
990 return coeffs.
at((powX + powY) * (powX + powY + 1) / 2 + powY);
996 static void operator+=(PolyXY &left,
const PolyXY &right) {
998 assert(
left.getOrder() >= rdeg);
1000 for (
std::size_t j = 0; j <= rdeg - i; ++j)
left.getCoefficient(i, j) +=
right.getCoefficient(i, j);
1004 static PolyXY operator*(
const long double &
a,
const PolyXY &polyXY) {
1014 static PolyXY product(
const PolyXY &p1,
const PolyXY &p2) {
1017 PolyXY
result(deg1 + deg2);
1022 result.getCoefficient(i1 + i2, j1 + j2) +=
1023 p1.getCoefficient(i1, j1) * p2.getCoefficient(i2, j2);
1031 powers[0].getCoefficient(0, 0) = 1L;
1036 static PolyXY composition(
const PolyXY &polyXY,
const PolyXY &polyX,
const PolyXY &polyY) {
1038 PolyXY
result(pdeg *
max(polyX.getOrder(), polyY.getOrder()));
1041 computePowers(polyX, pdeg, pXPowers);
1042 computePowers(polyY, pdeg, pYPowers);
1045 result += polyXY.getCoefficient(px,
py) * product(pXPowers.
at(px), pYPowers.
at(
py));
1062 PolyXY rx(composition(plx, prx, pry));
1063 PolyXY ry(composition(ply, prx, pry));
1077 if (_order >=
right._order) {
1086 return (
right + (*
this));
1093 for (
std::size_t j = 0; j <= res._order - i; ++j) {
1102 return std::make_shared<ast::PolyMap>(toAstPolyMapCoefficients(), inverse->toAstPolyMapCoefficients());
1106 s <<
" AstrometryTransformPolynomial 1" <<
endl;
1107 s <<
"order " << _order <<
endl;
1110 for (
std::size_t k = 0; k < 2 * _nterms; ++k) s << _coeffs[k] <<
' ';
1120 " AstrometryTransformPolynomial::read : format is not 1 ");
1123 s >> order >> _order;
1124 if (order !=
"order")
1126 " AstrometryTransformPolynomial::read : expecting \"order\" and found " + order);
1128 for (
std::size_t k = 0; k < 2 * _nterms; ++k) s >> _coeffs[k];
1131 ndarray::Array<double, 2, 2> AstrometryTransformPolynomial::toAstPolyMapCoefficients()
const {
1133 ndarray::Array<double, 2, 2>
result = ndarray::allocate(ndarray::makeVector(nCoeffs,
std::size_t(4)));
1135 ndarray::Size k = 0;
1136 for (
std::size_t iCoord = 0; iCoord < 2; ++iCoord) {
1140 result[k][1] = iCoord + 1;
1151 Frame const &domain,
1152 double const precision,
1156 double xStart = domain.
xMin;
1157 double yStart = domain.
yMin;
1158 double xStep = domain.
getWidth() / (nSteps - 1);
1159 double yStep = domain.
getHeight() / (nSteps - 1);
1162 Point in(xStart + i * xStep, yStart + j * yStep);
1173 for (order = 1; order <= maxOrder; ++order) {
1175 auto success =
poly->fit(sm);
1176 if (success == -1) {
1178 errMsg <<
"Cannot fit a polynomial of order " << order <<
" with " << nSteps <<
"^2 points";
1183 for (
auto const &i : sm) chi2 += i.point2.computeDist2(
poly->apply((i.point1)));
1184 LOGLS_TRACE(_log,
"inversePoly order " << order <<
": " << chi2 <<
" / " << npairs <<
" = "
1185 << chi2 / npairs <<
" < " << precision * precision);
1187 if (chi2 / npairs < precision * precision)
break;
1190 if (chi2 > oldChi2) {
1191 LOGLS_WARN(_log,
"inversePolyTransform: chi2 increases ("
1192 << chi2 <<
" > " << oldChi2 <<
"); ending fit with order: " << order);
1193 LOGLS_WARN(_log,
"inversePolyTransform: requested precision not reached: "
1194 << chi2 <<
" / " << npairs <<
" = " << chi2 / npairs <<
" < "
1195 << precision * precision);
1202 oldPoly = dynamic_pointer_cast<AstrometryTransformPolynomial>(
1206 if (order > maxOrder)
1207 LOGLS_WARN(_log,
"inversePolyTransform: Reached max order without reaching requested precision: "
1208 << chi2 <<
" / " << npairs <<
" = " << chi2 / npairs <<
" < "
1209 << precision * precision);
1219 const double A12,
const double A21,
const double A22)
1233 "Trying to build a AstrometryTransformLinear from a higher order transform. Aborting. ");
1253 const double)
const {
1277 "AstrometryTransformLinear::invert singular transformation: transform contents will be "
1278 "dumped to stderr.");
1291 const Frame &)
const {
1298 stream <<
"Linear AstrometryTransform:" <<
std::endl;
1313 LOGLS_FATAL(_log,
"AstrometryTransformLinearShift::fit trying to fit a linear transform with only "
1314 << npairs <<
" matches.");
1320 Eigen::VectorXd B(2);
1322 Eigen::MatrixXd A(2, 2);
1325 for (
auto const &it : starMatchList) {
1326 FatPoint const &point1 = it.point1;
1327 FatPoint const &point2 = it.point2;
1328 double deltax = point2.
x - point1.
x;
1329 double deltay = point2.
y - point1.
y;
1330 double vxx = point1.
vx + point2.
vx;
1331 double vyy = point1.
vy + point2.
vy;
1332 double vxy = point1.
vxy + point2.
vxy;
1333 double det = vxx * vyy - vxy * vxy;
1334 double wxx = vyy /
det;
1335 double wyy = vxx /
det;
1336 double wxy = -vxy /
det;
1337 B(0) += deltax * wxx + wxy * deltay;
1338 B(1) += deltay * wyy + wxy * deltax;
1342 sumr2 += deltax * deltax * wxx + deltay * deltay * wyy + 2. * wxy * deltax * deltay;
1344 double det = A(0, 0) * A(1, 1) - A(0, 1) * A(1, 0);
1345 if (
det <= 0)
return -1;
1346 double tmp = A(0, 0);
1347 A(0, 0) = A(1, 1) /
det;
1348 A(1, 1) = tmp /
det;
1349 A(0, 1) = A(1, 0) = -A(0, 1) /
det;
1350 Eigen::VectorXd sol = A * B;
1352 return (sumr2 - sol.dot(B));
1356 const double scaleFactor) {
1357 double c = scaleFactor *
std::cos(angleRad);
1358 double s = scaleFactor *
std::sin(angleRad);
1364 Point a_point(0., 0.);
1365 if (center) a_point = *center;
1369 dx() = a_point.
x -
Dx();
1370 dy() = a_point.
y -
dy();
1375 static double rad2deg(
double rad) {
return rad * 180. /
M_PI; }
1399 ra0 = deg2rad(tangentPoint.
x);
1400 dec0 = deg2rad(tangentPoint.
y);
1437 LOGL_WARN(_log,
"No sidereal coordinates at pole!");
1446 if (rat < 0.0) rat += (2. *
M_PI);
1448 xOut = rad2deg(rat);
1449 yOut = rad2deg(dect);
1469 return Point(inverse.
Dx(), inverse.
Dy());
1475 : _skyWcs(skyWcs) {}
1478 auto const outCoord = _skyWcs->pixelToSky(
geom::Point2D(xIn, yIn));
1479 xOut = outCoord[0].asDegrees();
1480 yOut = outCoord[1].asDegrees();
1484 out <<
"AstrometryTransformSkyWcs(" << *_skyWcs <<
")";
1499 :
BaseTanWcs(pixToTan, tangentPoint, corrections) {}
1506 if (
right.getOrder() == 1) {
1507 return std::make_unique<TanPixelToRaDec>((*
this) * (
right));
1520 if (
corr !=
nullptr) {
1521 LOGL_WARN(_log,
"You are inverting a TanPixelToRaDec with corrections.");
1522 LOGL_WARN(_log,
"The inverse you get ignores the corrections!");
1533 const Frame ®ion)
const {
1549 double &yTangentPlane)
const {
1553 double xtmp = xTangentPlane;
1554 double ytmp = yTangentPlane;
1555 corr->apply(xtmp, ytmp, xTangentPlane, yTangentPlane);
1567 stream <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1570 if (
corr) stream <<
"PV correction: " <<
endl << *
corr;
1583 "TanPixelToRaDec::fit is NOT implemented (although it is doable)) ");
1591 :
BaseTanWcs(pixToTan, tangentPoint, corrections) {}
1607 const Frame ®ion)
1620 double &yTangentPlane)
const {
1624 corr->apply(xPixel, yPixel, xtmp, ytmp);
1638 stream <<
" tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1641 if (
corr) stream <<
"PV correction: " <<
endl << *
corr;
1654 "TanSipPixelToRaDec::fit is NOT implemented (although it is doable)) ");
1661 : linTan2Pix(tan2Pix) {
1668 ra0 = deg2rad(tangentPoint.
x);
1669 dec0 = deg2rad(tangentPoint.
y);
1701 double ra = deg2rad(in.
x);
1702 double dec = deg2rad(in.
y);
1703 if (ra - ra0 >
M_PI) ra -= (2. *
M_PI);
1704 if (ra - ra0 < -
M_PI) ra += (2. *
M_PI);
1712 double l = sinda * coss;
1713 double m = sins * sin0 + coss * cos0 * cosda;
1715 m = (sins * cos0 - coss * sin0 * cosda) /
m;
1719 sq(sin0) - sq(coss) + sq(coss * cos0) * (1 + sq(cosda)) + 2 * sins * sin0 * coss * cos0 * cosda;
1720 double a11 = coss * (cosda * sins * sin0 + coss * cos0) / deno;
1721 double a12 = -sinda * sin0 / deno;
1722 double a21 = coss * sinda * sins / deno;
1723 double a22 = cosda / deno;
1726 tmp.
vx = a11 * (a11 * in.
vx + 2 * a12 * in.
vxy) + a12 * a12 * in.
vy;
1727 tmp.
vy = a21 * a21 * in.
vx + a22 * a22 * in.
vy + 2. * a21 * a22 * in.
vxy;
1728 tmp.
vxy = a21 * a11 * in.
vx + a22 * a12 * in.
vy + (a21 * a12 + a11 * a22) * in.
vxy;
1738 double ra = deg2rad(xIn);
1739 double dec = deg2rad(yIn);
1740 if (ra - ra0 >
M_PI) ra -= (2. *
M_PI);
1741 if (ra - ra0 < -
M_PI) ra += (2. *
M_PI);
1746 double l =
std::sin(ra - ra0) * coss;
1747 double m = sins * sin0 + coss * cos0 *
std::cos(ra - ra0);
1749 m = (sins * cos0 - coss * sin0 *
std::cos(ra - ra0)) /
m;
1753 linTan2Pix.
apply(l,
m, xOut, yOut);
1762 stream <<
"tan2pix " << linTan2Pix <<
std::endl;
1763 stream <<
"tangent point " << tp.
x <<
' ' << tp.
y <<
endl;
1782 "TanRaDecToPixel::fit is NOT implemented (although it is doable)) ");
1789 : _userFun(userFun), _userData(userData) {}
1792 _userFun(xIn, yIn, xOut, yOut, _userData);
1796 stream <<
"UserTransform with user function @ " << _userFun <<
"and userData@ " << _userData <<
endl;
1801 "UserTransform::fit is NOT implemented (and will never be)) ");
1815 " astrometryTransformRead : cannot open " + fileName);
1831 "astrometryTransformRead : could not find a AstrometryTransformtype");
1832 if (
type ==
"AstrometryTransformIdentity") {
1836 }
else if (
type ==
"AstrometryTransformPolynomial") {
1842 " astrometryTransformRead : No reader for AstrometryTransform type " +
type);