5 #include "lsst/log/Log.h"
11 #include "Eigen/Sparse"
12 #include "Eigen/CholmodSupport"
13 #include "lsst/pex/exceptions.h"
17 typedef Eigen::SparseMatrix<double>
SpMat;
20 template<
typename _MatrixType,
int _UpLo = Eigen::Lower>
21 class CholmodSupernodalLLT2 :
public Eigen::CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT2<_MatrixType, _UpLo> >
23 typedef Eigen::CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT2> Base;
24 using Base::m_cholmod;
28 typedef _MatrixType MatrixType;
29 typedef typename MatrixType::Index Index;
31 CholmodSupernodalLLT2() : Base() { init(); }
33 CholmodSupernodalLLT2(
const MatrixType& matrix) : Base()
36 this->compute(matrix);
40 int update(
const SpMat &H,
const bool UpOrDown)
43 const Index size = Base::m_cholmodFactor->n;
44 EIGEN_UNUSED_VARIABLE(size);
45 eigen_assert(size == H.rows());
46 cholmod_sparse C_cs = viewAsCholmod(H);
49 cholmod_sparse *C_cs_perm = cholmod_submatrix(C_cs,
50 Base::m_cholmodFactor->Perm,
51 Base::m_cholmodFactor->n,
52 nullptr, -1,
nullptr,
true,
true,
55 int ret = cholmod_updown(UpOrDown, &C_cs_perm, Base::m_cholmodFactor, &this->cholmod());
56 cholmod_free_sparse(C_cs_perm, &this->cholmod());
60 ~CholmodSupernodalLLT2() {}
64 m_cholmod.final_asis = 1;
65 m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
68 Base::m_shiftOffset[0] = Base::m_shiftOffset[1] = RealScalar(0.0);
78 template <
typename _MatrixType,
int _UpLo = Eigen::Lower>
80 :
public Eigen::CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT2<_MatrixType, _UpLo> > {
81 typedef Eigen::CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT2> Base;
82 using Base::m_cholmod;
86 typedef typename MatrixType::Index
Index;
93 this->compute(matrix);
99 const Index size = Base::m_cholmodFactor->n;
100 EIGEN_UNUSED_VARIABLE(size);
101 eigen_assert(size == H.rows());
103 cholmod_sparse C_cs = viewAsCholmod(H);
106 cholmod_sparse *C_cs_perm =
107 cholmod_submatrix(&C_cs, (
int *)Base::m_cholmodFactor->Perm, Base::m_cholmodFactor->n,
108 nullptr, -1,
true,
true, &this->cholmod());
110 int ret = cholmod_updown(UpOrDown, C_cs_perm, Base::m_cholmodFactor, &this->cholmod());
111 cholmod_free_sparse(&C_cs_perm, &this->cholmod());
120 m_cholmod.final_asis = 1;
121 m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
124 Base::m_shiftOffset[0] = Base::m_shiftOffset[1] =
RealScalar(0.0);
130 static double sqr(
double x) {
return x * x; }
135 LOG_LOGGER _log = LOG_GET(
"jointcal.AstrometryFit");
142 : _assoc(associations), _astrometryModel(astrometryModel), _posError(posError) {
146 _posError = posError;
152 _referenceColor += i->color;
153 _sigCol += sqr(i->color);
157 _referenceColor /= double(count);
158 if (_sigCol > 0) _sigCol = sqrt(_sigCol / count - sqr(_referenceColor));
160 LOGLS_INFO(_log,
"Reference Color: " << _referenceColor <<
" sig " << _sigCol);
162 _nRefrac = _assoc.
NBands();
163 _refractionCoefficient = 0;
177 Point AstrometryFit::transformFittedStar(
const FittedStar &fittedStar,
const Gtransfo *sky2TP,
178 const Point &refractionVector,
double refractionCoeff,
180 Point fittedStarInTP = sky2TP->apply(fittedStar);
181 if (fittedStar.mightMove) {
182 fittedStarInTP.x += fittedStar.pmx * mjd;
183 fittedStarInTP.y += fittedStar.pmy * mjd;
188 double color = fittedStar.color - _referenceColor;
189 fittedStarInTP.x += refractionVector.x * color * refractionCoeff;
190 fittedStarInTP.y += refractionVector.y * color * refractionCoeff;
191 return fittedStarInTP;
197 static void tweakAstromMeasurementErrors(FatPoint &P,
const MeasuredStar &Ms,
double error) {
198 static bool called =
false;
199 static double increment = 0;
201 increment = sqr(error);
219 if (msList) assert(&(msList->front()->getCcdImage()) == &ccdImage);
224 unsigned npar_mapping = (_fittingDistortions) ? mapping->
getNpar() : 0;
225 unsigned npar_pos = (_fittingPos) ? 2 : 0;
226 unsigned npar_refrac = (_fittingRefrac) ? 1 : 0;
227 unsigned npar_pm = (_fittingPM) ?
NPAR_PM : 0;
228 unsigned npar_tot = npar_mapping + npar_pos + npar_refrac + npar_pm;
231 if (npar_tot == 0)
return;
232 vector<unsigned> indices(npar_tot, -1);
236 double mjd = ccdImage.
getMjd() - _JDRef;
246 Eigen::Matrix2d transW(2, 2);
247 Eigen::Matrix2d alpha(2, 2);
248 Eigen::VectorXd grad(npar_tot);
253 for (
auto &i : catalog) {
258 tweakAstromMeasurementErrors(inPos, ms, _posError);
262 if (_fittingDistortions)
267 unsigned ipar = npar_mapping;
268 double det = outPos.
vx * outPos.
vy - sqr(outPos.
vxy);
269 if (det <= 0 || outPos.
vx <= 0 || outPos.
vy <= 0) {
270 LOGLS_WARN(_log,
"Inconsistent measurement errors: drop measurement at "
274 transW(0, 0) = outPos.
vy / det;
275 transW(1, 1) = outPos.
vx / det;
276 transW(0, 1) = transW(1, 0) = -outPos.
vxy / det;
279 alpha(0, 0) = sqrt(transW(0, 0));
281 alpha(1, 0) = transW(0, 1) / alpha(0, 0);
284 alpha(1, 1) = 1. / sqrt(det * transW(0, 0));
289 Point fittedStarInTP =
290 transformFittedStar(*fs, sky2TP, refractionVector, _refractionCoefficient, mjd);
298 h(npar_mapping, 0) = -dypdy.
A11();
299 h(npar_mapping + 1, 0) = -dypdy.
A12();
300 h(npar_mapping, 1) = -dypdy.
A21();
301 h(npar_mapping + 1, 1) = -dypdy.
A22();
302 indices[npar_mapping] = fs->getIndexInMatrix();
303 indices.at(npar_mapping + 1) = fs->getIndexInMatrix() + 1;
308 if (_fittingPM && fs->mightMove) {
310 h(ipar + 1, 1) = -mjd;
311 indices[ipar] = fs->getIndexInMatrix() + 2;
312 indices[ipar + 1] = fs->getIndexInMatrix() + 3;
315 if (_fittingRefrac) {
318 double color = fs->color - _referenceColor;
320 h(ipar, 0) = -refractionVector.
x * color;
321 h(ipar, 1) = -refractionVector.
y * color;
322 indices[ipar] = _refracPosInMatrix;
327 Eigen::Vector2d res(fittedStarInTP.
x - outPos.
x, fittedStarInTP.
y - outPos.
y);
335 for (
unsigned ipar = 0; ipar < npar_tot; ++ipar) {
336 for (
unsigned ic = 0; ic < 2; ++ic) {
337 double val = halpha(ipar, ic);
338 if (val == 0)
continue;
339 #if (TRIPLET_INTERNAL_COORD == COL)
340 tList.
addTriplet(indices[ipar], kTriplets + ic, val);
342 tList.
addTriplet(kTriplets + ic, indices[ipar], val);
345 rhs(indices[ipar]) += grad(ipar);
355 #define HACK_REF_ERRORS 1. // used to isolate the measurement or ref terms
358 Eigen::VectorXd &rhs)
const {
362 if (!_fittingPos)
return;
366 Eigen::Matrix2d w(2, 2);
367 Eigen::Matrix2d alpha(2, 2);
368 Eigen::Matrix2d h(2, 2), halpha(2, 2), hw(2, 2);
370 Eigen::Vector2d res, grad;
380 for (
auto const &i : fsl) {
383 if (rs ==
nullptr)
continue;
390 h(0, 0) = -der.
A11();
391 h(1, 0) = -der.
A12();
392 h(0, 1) = -der.
A21();
393 h(1, 1) = -der.
A22();
395 double det = rsProj.
vx * rsProj.
vy - sqr(rsProj.
vxy);
396 if (rsProj.
vx <= 0 || rsProj.
vy <= 0 || det <= 0) {
397 LOGLS_WARN(_log,
"RefStar error matrix not positive definite for: " << *rs);
400 w(0, 0) = rsProj.
vy / det;
401 w(0, 1) = w(1, 0) = -rsProj.
vxy / det;
402 w(1, 1) = rsProj.
vx / det;
407 alpha(0, 0) = sqrt(w(0, 0));
409 alpha(1, 0) = w(0, 1) / alpha(0, 0);
410 alpha(1, 1) = 1. / sqrt(det * w(0, 0));
414 unsigned npar_tot = 2;
430 for (
unsigned ipar = 0; ipar < npar_tot; ++ipar) {
431 for (
unsigned ic = 0; ic < 2; ++ic) {
432 double val = halpha(ipar, ic);
433 if (val == 0)
continue;
434 #if (TRIPLET_INTERNAL_COORD == COL)
435 tList.
addTriplet(indices[ipar], kTriplets + ic, val);
437 tList.
addTriplet(kTriplets + ic, indices[ipar], val);
440 rhs(indices[ipar]) += grad(ipar);
451 for (
auto const &im : L) {
463 template <
class ImType,
class Accum>
464 void AstrometryFit::accumulateStatImage(ImType &image, Accum &accu)
const {
472 double mjd = image.getMjd() - _JDRef;
474 Point refractionVector = image.getRefractionVector();
478 Eigen::Matrix2Xd transW(2, 2);
480 auto &catalog = image.getCatalogForFit();
481 for (
auto const &ms : catalog) {
482 if (!ms->isValid())
continue;
485 tweakAstromMeasurementErrors(inPos, *ms, _posError);
490 double det = outPos.
vx * outPos.
vy - sqr(outPos.
vxy);
491 if (det <= 0 || outPos.
vx <= 0 || outPos.
vy <= 0) {
492 LOGLS_WARN(_log,
" Inconsistent measurement errors :drop measurement at "
493 <<
Point(*ms) <<
" in image " << image.getName());
496 transW(0, 0) = outPos.
vy / det;
497 transW(1, 1) = outPos.
vx / det;
498 transW(0, 1) = transW(1, 0) = -outPos.
vxy / det;
500 auto fs = ms->getFittedStar();
501 Point fittedStarInTP =
502 transformFittedStar(*fs, sky2TP, refractionVector, _refractionCoefficient, mjd);
504 Eigen::Vector2d res(fittedStarInTP.x - outPos.
x, fittedStarInTP.y - outPos.
y);
505 double chi2Val = res.transpose() * transW * res;
507 accu.addEntry(chi2Val, 2, ms);
512 template <
class ListType,
class Accum>
513 void AstrometryFit::accumulateStatImageList(ListType &list, Accum &accum)
const {
514 for (
auto &im : list) {
515 accumulateStatImage(*im, accum);
519 template <
class Accum>
520 void AstrometryFit::accumulateStatRefStars(Accum &accum)
const {
524 TanRaDec2Pix proj(GtransfoLin(), Point(0., 0.));
525 for (
auto const &fs : fsl) {
526 const RefStar *rs = fs->getRefStar();
527 if (rs ==
nullptr)
continue;
528 proj.setTangentPoint(*fs);
531 proj.transformPosAndErrors(*rs, rsProj);
533 double rx = rsProj.x;
534 double ry = rsProj.y;
535 double det = rsProj.vx * rsProj.vy - sqr(rsProj.vxy);
536 double wxx = rsProj.vy / det;
537 double wyy = rsProj.vx / det;
538 double wxy = -rsProj.vxy / det;
542 accum.addEntry(wxx * sqr(rx) + 2 * wxy * rx * ry + wyy * sqr(ry), 2, fs);
550 accumulateStatRefStars(chi2);
553 chi2.
ndof -= _nParTot;
564 std::shared_ptr<BaseStar>
ps;
572 void addEntry(
double Chi2Val,
unsigned ndof, std::shared_ptr<BaseStar> ps) {
573 this->push_back(
Chi2Entry(Chi2Val, std::move(ps)));
580 void AstrometryFit::setMeasuredStarIndices(
const MeasuredStar &ms, std::vector<unsigned> &indices)
const {
581 if (_fittingDistortions) {
582 const Mapping *mapping = _astrometryModel->
getMapping(ms.getCcdImage());
585 auto fs = ms.getFittedStar();
586 unsigned fsIndex = fs->getIndexInMatrix();
588 indices.push_back(fsIndex);
589 indices.push_back(fsIndex + 1);
593 for (
unsigned k = 0; k <
NPAR_PM; ++k) indices.push_back(fsIndex + 2 + k);
603 for (
auto const &i : msOutliers) {
606 const CcdImage &ccd = i->getCcdImage();
615 unsigned n =
findOutliers(nSigmaCut, msOutliers, fsOutliers, measOrRef);
623 bool searchMeas = (measOrRef.find(
"Meas") != std::string::npos);
624 bool searchRef = (measOrRef.find(
"Ref") != std::string::npos);
628 chi2s.reserve(_nMeasuredStars + _assoc.
refStarList.size());
630 if (searchMeas) accumulateStatImageList(_assoc.
ccdImageList, chi2s);
632 if (searchRef) accumulateStatRefStars(chi2s);
635 unsigned nval = chi2s.size();
636 if (nval == 0)
return 0;
637 sort(chi2s.begin(), chi2s.end());
639 (nval & 1) ? chi2s[nval / 2].chi2 : 0.5 * (chi2s[nval / 2 - 1].chi2 + chi2s[nval / 2].chi2);
643 for (
auto i = chi2s.begin(); i != chi2s.end(); ++i) {
645 sum2 += sqr(i->chi2);
647 double average = sum / nval;
648 double sigma = sqrt(sum2 / nval - sqr(average));
650 "RemoveOutliers chi2 stat: mean/median/sigma " << average <<
'/' << median <<
'/' << sigma);
651 double cut = average + nSigmaCut * sigma;
657 Eigen::VectorXi affectedParams(_nParTot);
658 affectedParams.setZero();
660 unsigned nOutliers = 0;
662 for (
auto i = chi2s.rbegin(); i != chi2s.rend(); ++i) {
663 if (i->chi2 < cut)
break;
664 vector<unsigned> indices;
665 indices.reserve(100);
670 auto ms = std::dynamic_pointer_cast<
MeasuredStar>(i->ps);
671 std::shared_ptr<FittedStar> fs;
674 fs = std::dynamic_pointer_cast<
FittedStar>(i->ps);
675 indices.push_back(fs->getIndexInMatrix());
676 indices.push_back(fs->getIndexInMatrix() + 1);
681 setMeasuredStarIndices(*ms, indices);
689 for (
auto const &i : indices)
690 if (affectedParams(i) != 0) drop_it =
false;
695 msOutliers.push_back(ms);
697 fsOutliers.push_back(fs);
699 for (
auto const &i : indices) affectedParams(i)++;
703 LOGLS_INFO(_log,
"findOutliers: found " << msOutliers.size() <<
" meas outliers and " << fsOutliers.size()
704 <<
" ref outliers ");
710 for (
auto &i : outliers) {
714 fs->getMeasurementCount()--;
719 for (
auto &i : outliers) {
726 _whatToFit = whatToFit;
727 LOGLS_INFO(_log,
"assignIndices: Now fitting " << whatToFit);
728 _fittingDistortions = (_whatToFit.find(
"Distortions") != string::npos);
729 _fittingPos = (_whatToFit.find(
"Positions") != string::npos);
730 _fittingRefrac = (_whatToFit.find(
"Refrac") != string::npos);
731 if (_sigCol == 0 && _fittingRefrac) {
733 "Cannot fit refraction coefficients without a color lever arm. Ignoring refraction.");
734 _fittingRefrac =
false;
736 _fittingPM = (_whatToFit.find(
"PM") != string::npos);
739 _nParDistortions = 0;
740 if (_fittingDistortions) _nParDistortions = _astrometryModel->
assignIndices(0, _whatToFit);
741 unsigned ipar = _nParDistortions;
745 for (
auto const &i : fsl) {
756 _nParPositions = ipar - _nParDistortions;
757 if (_fittingRefrac) {
758 _refracPosInMatrix = ipar;
765 if (delta.size() != _nParTot)
766 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
767 "AstrometryFit::offsetParams : the provided vector length is not compatible with "
768 "the current whatToFit setting");
769 if (_fittingDistortions) _astrometryModel->
offsetParams(delta);
773 for (
auto const &i : fsl) {
779 fs.
x += delta(index);
780 fs.
y += delta(index + 1);
782 fs.
pmx += delta(index + 2);
783 fs.
pmy += delta(index + 3);
787 if (_fittingRefrac) {
788 _refractionCoefficient += delta(_refracPosInMatrix);
794 static void write_sparse_matrix_in_fits(
const SpMat &mat,
const string &fitsName) {
795 if (mat.rows() * mat.cols() > 2e8) {
797 "write_sparse_matrix_in_fits: yout matrix is too large. " << fitsName <<
" not generated");
800 Mat m(mat.rows(), mat.cols());
801 for (
int k = 0; k < mat.outerSize(); ++k)
802 for (SpMat::InnerIterator it(mat, k); it; ++it) {
803 m(it.row(), it.col()) = it.value();
805 m.writeFits(fitsName);
808 static void write_vect_in_fits(
const Eigen::VectorXd &vectorXd,
const string &fitsName) {
809 Vect v(vectorXd.size());
810 for (
int k = 0; k < vectorXd.size(); ++k) v(k) = V(k);
811 Mat(v).writeFits(fitsName);
823 unsigned returnCode = 0;
826 unsigned nTrip = (_LastNTrip) ? _LastNTrip : 1e6;
828 Eigen::VectorXd grad(_nParTot);
833 _LastNTrip = tList.size();
835 LOGLS_DEBUG(_log,
"End of triplet filling, ntrip = " << tList.size());
839 #if (TRIPLET_INTERNAL_COORD == COL)
841 jacobian.setFromTriplets(tList.begin(), tList.end());
844 hessian = jacobian * jacobian.transpose();
846 SpMat jacobian(tList.NextRank(), _nParTot);
847 jacobian.setFromTriplets(tList.begin(), tList.end());
850 LOGLS_DEBUG(_log,
" starting H=JtJ ");
851 hessian = jacobian.transpose() * jacobian;
855 LOGLS_DEBUG(_log,
"Starting factorization, hessian: dim="
856 << hessian.rows() <<
" nnz=" << hessian.nonZeros()
857 <<
" filling-frac = " << hessian.nonZeros() / sqr(hessian.rows()));
860 if (chol.info() != Eigen::Success) {
861 LOGLS_ERROR(_log,
"minimize: factorization failed ");
865 unsigned tot_outliers = 0;
869 Eigen::VectorXd delta = chol.solve(grad);
872 LOGLS_DEBUG(_log, current_chi2);
873 if (current_chi2.
chi2 > old_chi2) {
874 LOGL_WARN(_log,
"chi2 went up, exiting outlier rejection loop");
878 old_chi2 = current_chi2.
chi2;
880 if (nSigRejCut == 0)
break;
883 int n_outliers =
findOutliers(nSigRejCut, moutliers, foutliers);
884 tot_outliers += n_outliers;
885 if (n_outliers == 0)
break;
895 h.setFromTriplets(tList.begin(), tList.end());
896 int update_status = chol.
update(h,
false );
897 LOGLS_DEBUG(_log,
"cholmod update_status " << update_status);
904 LOGLS_INFO(_log,
"Total number of outliers " << tot_outliers);
911 const char *what2fit[] = {
"Positions",
914 "Positions Distortions",
916 "Distortions Refrac",
917 "Positions Distortions Refrac"};
919 const char *what2fit[] = {
"Positions",
"Distortions",
"Positions Distortions"};
921 for (
unsigned k = 0; k <
sizeof(what2fit) /
sizeof(what2fit[0]); ++k) {
924 Eigen::VectorXd rhs(_nParTot);
928 jacobian.setFromTriplets(tList.begin(), tList.end());
929 SpMat hessian = jacobian * jacobian.transpose();
932 sprintf(name,
"h%d.fits", k);
933 write_sparse_matrix_in_fits(hessian, name);
934 sprintf(name,
"g%d.fits", k);
935 write_vect_in_fits(rhs, name);
937 LOGLS_DEBUG(_log,
"npar : " << _nParTot <<
' ' << _nParDistortions);
944 size_t dot = tupleName.rfind(
'.');
945 size_t slash = tupleName.rfind(
'/');
946 if (dot == string::npos || (slash != string::npos && dot < slash)) dot = tupleName.size();
947 std::string meas_tuple(tupleName);
948 meas_tuple.insert(dot,
"-meas");
950 std::string ref_tuple(tupleName);
951 ref_tuple.insert(dot,
"-ref");
956 std::ofstream tuple(tupleName.c_str());
957 tuple <<
"#xccd: coordinate in CCD" << endl
959 <<
"#rx: residual in degrees in TP" << endl
961 <<
"#xtp: transformed coordinate in TP " << endl
963 <<
"#mag: rough mag" << endl
964 <<
"#jd: Julian date of the measurement" << endl
965 <<
"#rvx: transformed measurement uncertainty " << endl
968 <<
"#color : " << endl
969 <<
"#fsindex: some unique index of the object" << endl
970 <<
"#ra: pos of fitted star" << endl
971 <<
"#dec: pos of fitted star" << endl
972 <<
"#chi2: contribution to Chi2 (2D dofs)" << endl
973 <<
"#nm: number of measurements of this FittedStar" << endl
974 <<
"#chip: chip number" << endl
975 <<
"#visit: visit id" << endl
978 for (
auto const &i : L) {
983 double mjd = im.
getMjd() - _JDRef;
984 for (
auto const &is : cat) {
989 tweakAstromMeasurementErrors(inPos, ms, _posError);
994 Point fittedStarInTP =
995 transformFittedStar(*fs, sky2TP, refractionVector, _refractionCoefficient, mjd);
996 Point res = tpPos - fittedStarInTP;
997 double det = tpPos.
vx * tpPos.
vy - sqr(tpPos.
vxy);
998 double wxx = tpPos.
vy / det;
999 double wyy = tpPos.
vx / det;
1000 double wxy = -tpPos.
vxy / det;
1002 double chi2 = wxx * res.
x * res.
x + wyy * res.
y * res.
y + 2 * wxy * res.
x * res.
y;
1003 tuple << std::setprecision(9);
1004 tuple << ms.
x <<
' ' << ms.
y <<
' ' << res.
x <<
' ' << res.
y <<
' ' << tpPos.
x <<
' ' << tpPos.
y
1005 <<
' ' << fs->getMag() <<
' ' << mjd <<
' ' << tpPos.
vx <<
' ' << tpPos.
vy <<
' '
1006 << tpPos.
vxy <<
' ' << fs->color <<
' ' << fs->getIndexInMatrix() <<
' ' << fs->x <<
' '
1007 << fs->y <<
' ' << chi2 <<
' ' << fs->getMeasurementCount() <<
' ' << im.
getCcdId() <<
' '
1014 std::ofstream tuple(tupleName.c_str());
1015 tuple <<
"#ra: coordinates of FittedStar" << endl
1017 <<
"#rx: residual in degrees in TP" << endl
1019 <<
"#mag: mag" << endl
1020 <<
"#rvx: transformed measurement uncertainty " << endl
1023 <<
"#color : " << endl
1024 <<
"#fsindex: some unique index of the object" << endl
1025 <<
"#chi2: contribution to Chi2 (2D dofs)" << endl
1026 <<
"#nm: number of measurements of this FittedStar" << endl
1031 for (
auto const &i : fsl) {
1034 if (rs ==
nullptr)
continue;
1039 double rx = rsProj.
x;
1040 double ry = rsProj.
y;
1041 double det = rsProj.
vx * rsProj.
vy - sqr(rsProj.
vxy);
1042 double wxx = rsProj.
vy / det;
1043 double wyy = rsProj.
vx / det;
1044 double wxy = -rsProj.
vxy / det;
1045 double chi2 = wxx * sqr(rx) + 2 * wxy * rx * ry + wyy * sqr(ry);
1046 tuple << std::setprecision(9);
1047 tuple << fs.
x <<
' ' << fs.
y <<
' ' << rx <<
' ' << ry <<
' ' << fs.
getMag() <<
' ' << rsProj.
vx
Point getRefractionVector() const
void addEntry(double Chi2Val, unsigned ndof, std::shared_ptr< BaseStar > ps)
Objects used as position anchors, typically USNO stars.
void outliersContributions(MeasuredStarList &mOutliers, FittedStarList &fOutLiers, TripletList &tList, Eigen::VectorXd &grad)
Contributions to derivatives from (presumably) outlier terms.
implements the linear transformations (6 real coefficients).
void makeMeasResTuple(const std::string &tupleName) const
Produces a tuple containing residuals of measurement terms.
double getMjd() const
Julian Date.
virtual void transformPosAndErrors(const FatPoint &where, FatPoint &outPoint) const =0
The same as above but without the parameter derivatives (used to evaluate chi^2)
a class to accumulate chi2 contributions together with pointers to the contributors.
unsigned findOutliers(double nSigmaCut, MeasuredStarList &mSOutliers, FittedStarList &fSOutliers, const std::string &measOrRef="Meas Ref") const
Find Measurements and references contributing more than a cut, computed as The outliers are NOT remo...
virtual void setMappingIndices(std::vector< unsigned > &indices) const =0
Sets how this set of parameters (of length Npar()) map into the "grand" fit Expects that indices has ...
virtual class needed in the abstraction of the distortion model
const RefStar * getRefStar() const
Get the astrometric reference star associated with this star.
void makeResTuple(const std::string &tupleName) const
Produces both ntuples (cook up names from the provided string)
void LSDerivatives(TripletList &tList, Eigen::VectorXd &rhs) const
Evaluates the chI^2 derivatives (Jacobian and gradient) for the current whatToFit setting...
std::shared_ptr< const FittedStar > getFittedStar() const
std::shared_ptr< BaseStar > ps
Interface class between AstrometryFit and an actual model for the Mapping (s) from pixels to some tan...
CcdImageList ccdImageList
unsigned removeOutliers(double nSigmaCut, const std::string &measOrRef="Meas Ref")
Discards measurements and reference contributions contributing to the chi2 more than nSigmaCut...
void removeMeasOutliers(MeasuredStarList &outliers)
Just removes outliers from the fit. No Refit done.
double getMag() const
derived using available zero points in input images. In the absence ofZP, ZP= 0.
The class that implements the relations between MeasuredStar and FittedStar.
A Point with uncertainties.
void LSDerivatives1(const CcdImage &ccdImage, TripletList &tList, Eigen::VectorXd &rhs, const MeasuredStarList *msList=nullptr) const
Compute derivatives of measurement terms for this CcdImage.
unsigned minimize(const std::string &whatToFit, const double nSigRejCut=0)
Does a 1 step minimization, assuming a linear model.
A list of MeasuredStar. They are usually filled in Associations::AddImage.
Simple structure to accumulate Chi2 and Ndof.
bool operator<(const Chi2Entry &R) const
virtual const Gtransfo * getSky2TP(const CcdImage &ccdImage) const =0
The transformation used to project the positions of FittedStars.
virtual const Mapping * getMapping(const CcdImage &) const =0
Mapping associated to a given CcdImage.
const CcdImageList & getCcdImageList() const
void setIndexInMatrix(const unsigned &index)
index is a value that a fit can set and reread....
void setRefStar(const RefStar *_refStar)
Set the astrometric reference star associated with this star.
int getIndexInMatrix() const
void addTriplet(const unsigned i, const unsigned j, double val)
void makeRefResTuple(const std::string &tupleName) const
Produces a tuple containing residuals of reference terms.
MatrixType::RealScalar RealScalar
CholmodSimplicialLDLT2(const MatrixType &matrix)
A list of FittedStar s. Such a list is typically constructed by Associations.
Chi2Entry(double c, std::shared_ptr< BaseStar > s)
Chi2 computeChi2() const
Returns a chi2 for the current state.
objects measured on actual images.
~CholmodSimplicialLDLT2()
const MeasuredStarList & getCatalogForFit() const
Gets the catalog to be used for fitting, which may have been cleaned-up.
Eigen::Matrix< double, Eigen::Dynamic, 2 > MatrixX2d
unsigned NBands() const
Number of different bands in the input image list. Not implemented so far.
void transformPosAndErrors(const FatPoint &in, FatPoint &out) const
transform with analytical derivatives
int update(const SpMat &H, const bool UpOrDown)
void assignIndices(const std::string &whatToFit)
Set parameter groups fixed or variable and assign indices to each parameter in the big matrix (which ...
virtual unsigned getNpar() const =0
Number of parameters in total.
void removeRefOutliers(FittedStarList &outliers)
Just removes outliers from the fit. No Refit done.
void setTangentPoint(const Point &tangentPoint)
Resets the projection (or tangent) point.
unsigned getNextFreeIndex() const
This one is the Tangent Plane (called gnomonic) projection (from celestial sphere to tangent plane) ...
Cholesky factorization class using cholmod, with the small-rank update capability.
void setValid(bool v)
Fits may use that to discard outliers.
a virtual (interface) class for geometric transformations.
int getMeasurementCount() const
virtual void computeDerivative(const Point &where, GtransfoLin &derivative, const double step=0.01) const
Computes the local Derivative of a transfo. Step is used for numerical derivation.
std::list< std::shared_ptr< CcdImage > > CcdImageList
Handler of an actual image from a single CCD.
Eigen::SparseMatrix< double > SpMat
virtual void computeTransformAndDerivatives(const FatPoint &where, FatPoint &outPoint, Eigen::MatrixX2d &H) const =0
Actually applies the mapping and evaluates the derivatives w.r.t the fitted parameters.
void checkStuff()
DEBUGGING routine.
bool isValid() const
Fits may use that to discard outliers.
void offsetParams(const Eigen::VectorXd &delta)
Offset the parameters by the requested quantities.
virtual unsigned assignIndices(unsigned firstIndex, const std::string &whatToFit)=0
Assign indices to parameters involved in mappings, starting at firstIndex.
std::string getName() const
Return the _name that identifies this ccdImage.
The objects which have been measured several times.
void setNextFreeIndex(unsigned index)
VisitIdType getVisit() const
returns visit ID
virtual void offsetParams(const Eigen::VectorXd &delta)=0
Offset the parameters by the provided amounts.
int getCcdId() const
returns ccd ID
FittedStarList fittedStarList
void LSDerivatives2(const FittedStarList &fsl, TripletList &tList, Eigen::VectorXd &rhs) const
Compute derivatives of reference terms (if any), associated to the FittedStarList.