31#include "Eigen/Sparse"
56 double wxx = refStar.
vy /
det;
57 double wyy = refStar.
vx /
det;
58 double wxy = -refStar.
vxy /
det;
59 return wxx *
std::pow(refStar.
x, 2) + 2 * wxy * refStar.
x * refStar.
y + wyy *
std::pow(refStar.
y, 2);
69 _astrometryModel(
std::
move(astrometryModel)),
70 _epoch(_associations->getEpoch()),
79 double deltaYears)
const {
84 fittedStarInTP = sky2TP.
apply(temp);
86 fittedStarInTP = sky2TP.
apply(fittedStar);
88 return fittedStarInTP;
94static void tweakAstromMeasurementErrors(FatPoint &P, MeasuredStar
const &Ms,
double error) {
95 static bool called =
false;
96 static double increment = 0;
108 Eigen::VectorXd &fullGrad,
119 if (msList) assert(&(msList->
front()->getCcdImage()) == &ccdImage);
127 std::size_t npar_tot = npar_mapping + npar_pos + npar_pm;
130 if (npar_tot == 0)
return;
135 double deltaYears = _epoch - ccdImage.
getEpoch();
137 auto sky2TP = _astrometryModel->getSkyToTangentPlane(ccdImage);
142 Eigen::MatrixX2d H(npar_tot, 2), halpha(npar_tot, 2), HW(npar_tot, 2);
143 Eigen::Matrix2d transW(2, 2);
144 Eigen::Matrix2d alpha(2, 2);
145 Eigen::VectorXd grad(npar_tot);
150 for (
auto &i : catalog) {
155 tweakAstromMeasurementErrors(inPos, ms, _posError);
159 if (_fittingDistortions)
166 if (
det <= 0 || outPos.
vx <= 0 || outPos.
vy <= 0) {
167 LOGLS_WARN(
_log,
"Inconsistent measurement errors: drop measurement at "
171 transW(0, 0) = outPos.
vy /
det;
172 transW(1, 1) = outPos.
vx /
det;
173 transW(0, 1) = transW(1, 0) = -outPos.
vxy /
det;
176 alpha(0, 0) =
sqrt(transW(0, 0));
178 alpha(1, 0) = transW(0, 1) / alpha(0, 0);
181 alpha(1, 1) = 1. /
sqrt(
det * transW(0, 0));
186 Point fittedStarInTP = transformFittedStar(*fs, *sky2TP, deltaYears);
194 H(npar_mapping, 0) = -dypdy.
A11();
195 H(npar_mapping + 1, 0) = -dypdy.
A12();
196 H(npar_mapping, 1) = -dypdy.
A21();
197 H(npar_mapping + 1, 1) = -dypdy.
A22();
198 indices[npar_mapping] = fs->getIndexInMatrix();
199 indices.
at(npar_mapping + 1) = fs->getIndexInMatrix() + 1;
215 Eigen::Vector2d res(fittedStarInTP.
x - outPos.
x, fittedStarInTP.
y - outPos.
y);
223 for (
std::size_t ipar = 0; ipar < npar_tot; ++ipar) {
225 double val = halpha(ipar, ic);
226 if (
val == 0)
continue;
229 fullGrad(indices[ipar]) += grad(ipar);
238 Eigen::VectorXd &fullGrad)
const {
247 if (!_fittingPos)
return;
251 Eigen::Matrix2d W(2, 2);
252 Eigen::Matrix2d alpha(2, 2);
253 Eigen::Matrix2d H(2, 2), halpha(2, 2), HW(2, 2);
255 Eigen::Vector2d res, grad;
256 Eigen::Index indices[2];
265 for (
auto const &i : fittedStarList) {
268 if (rs ==
nullptr)
continue;
276 H(0, 0) = -der.
A11();
277 H(1, 0) = -der.
A12();
278 H(0, 1) = -der.
A21();
279 H(1, 1) = -der.
A22();
282 if (rsProj.
vx <= 0 || rsProj.
vy <= 0 ||
det <= 0) {
283 LOGLS_WARN(
_log,
"RefStar error matrix not positive definite for: " << *rs);
286 W(0, 0) = rsProj.
vy /
det;
287 W(0, 1) = W(1, 0) = -rsProj.
vxy /
det;
288 W(1, 1) = rsProj.
vx /
det;
291 alpha(0, 0) =
sqrt(W(0, 0));
293 alpha(1, 0) = W(0, 1) / alpha(0, 0);
294 alpha(1, 1) = 1. /
sqrt(
det * W(0, 0));
298 unsigned npar_tot = 2;
314 for (
std::size_t ipar = 0; ipar < npar_tot; ++ipar) {
315 for (
unsigned ic = 0; ic < 2; ++ic) {
316 double val = halpha(ipar, ic);
317 if (
val == 0)
continue;
320 fullGrad(indices[ipar]) += grad(ipar);
336 double deltaYears = _epoch - ccdImage.
getEpoch();
338 auto sky2TP = _astrometryModel->getSkyToTangentPlane(ccdImage);
340 Eigen::Matrix2Xd transW(2, 2);
343 for (
auto const &ms : catalog) {
344 if (!ms->isValid())
continue;
347 tweakAstromMeasurementErrors(inPos, *ms, _posError);
353 if (
det <= 0 || outPos.
vx <= 0 || outPos.
vy <= 0) {
354 LOGLS_WARN(
_log,
" Inconsistent measurement errors :drop measurement at "
358 transW(0, 0) = outPos.
vy /
det;
359 transW(1, 1) = outPos.
vx /
det;
360 transW(0, 1) = transW(1, 0) = -outPos.
vxy /
det;
363 Point fittedStarInTP = transformFittedStar(*fs, *sky2TP, deltaYears);
365 Eigen::Vector2d res(fittedStarInTP.x - outPos.
x, fittedStarInTP.y - outPos.
y);
366 double chi2Val = res.transpose() * transW * res;
373 for (
auto const &ccdImage : ccdImageList) {
374 accumulateStatImage(*ccdImage, accum);
388 for (
auto const &fs : fittedStarList) {
389 auto rs = fs->getRefStar();
390 if (rs ==
nullptr)
continue;
396 double chi2 = computeProjectedRefStarChi2(rsProj);
405 if (_fittingDistortions) {
410 Eigen::Index fsIndex = fs->getIndexInMatrix();
426 _fittingDistortions = (
_whatToFit.
find(
"Distortions") != std::string::npos);
427 _fittingPos = (
_whatToFit.
find(
"Positions") != std::string::npos);
437 for (
auto &fittedStar : fittedStarList) {
457 "AstrometryFit::offsetParams : the provided vector length is not compatible with "
458 "the current whatToFit setting");
459 if (_fittingDistortions) _astrometryModel->offsetParams(delta);
463 for (
auto const &i : fittedStarList) {
469 fs.
x += delta(index);
470 fs.
y += delta(index + 1);
481 const char *what2fit[] = {
"Positions",
"Distortions",
"Positions Distortions"};
483 for (
unsigned k = 0; k <
sizeof(what2fit) /
sizeof(what2fit[0]); ++k) {
490 jacobian.setFromTriplets(tripletList.
begin(), tripletList.
end());
500 ofile <<
"id" << separator <<
"xccd" << separator <<
"yccd " << separator;
501 ofile <<
"rx" << separator <<
"ry" << separator;
502 ofile <<
"xtp" << separator <<
"ytp" << separator;
503 ofile <<
"mag" << separator <<
"deltaYears" << separator;
504 ofile <<
"xErr" << separator <<
"yErr" << separator <<
"xyCov" << separator;
505 ofile <<
"xtpi" << separator <<
"ytpi" << separator;
506 ofile <<
"rxi" << separator <<
"ryi" << separator;
507 ofile <<
"fsindex" << separator;
508 ofile <<
"ra" << separator <<
"dec" << separator;
509 ofile <<
"chi2" << separator <<
"nm" << separator;
510 ofile <<
"detector" << separator <<
"visit" <<
std::endl;
512 ofile <<
"id in source catalog" << separator <<
"coordinates in CCD (pixels)" << separator << separator;
513 ofile <<
"residual on TP (degrees)" << separator << separator;
514 ofile <<
"transformed coordinate in TP (degrees)" << separator << separator;
515 ofile <<
"rough magnitude" << separator <<
"Julian epoch year delta from fit epoch" << separator;
516 ofile <<
"transformed measurement uncertainty (degrees)" << separator << separator << separator;
517 ofile <<
"as-read position on TP (degrees)" << separator << separator;
518 ofile <<
"as-read residual on TP (degrees)" << separator << separator;
519 ofile <<
"unique index of the fittedStar" << separator;
520 ofile <<
"on sky position of fittedStar" << separator << separator;
521 ofile <<
"contribution to chi2 (2D dofs)" << separator <<
"number of measurements of this fittedStar"
523 ofile <<
"detector id" << separator <<
"visit id" <<
std::endl;
526 for (
auto const &ccdImage : ccdImageList) {
529 const auto readTransform = ccdImage->
getReadWcs();
531 double deltaYears = _epoch - ccdImage->
getEpoch();
532 for (
auto const &ms : cat) {
533 if (!ms->isValid())
continue;
536 tweakAstromMeasurementErrors(inPos, *ms, _posError);
538 auto sky2TP = _astrometryModel->getSkyToTangentPlane(*ccdImage);
540 compose(*sky2TP, *readTransform);
541 FatPoint inputTpPos = readPixToTangentPlane->apply(inPos);
544 Point fittedStarInTP = transformFittedStar(*fs, *sky2TP, deltaYears);
545 Point res = tpPos - fittedStarInTP;
546 Point inputRes = inputTpPos - fittedStarInTP;
548 double wxx = tpPos.
vy /
det;
549 double wyy = tpPos.
vx /
det;
550 double wxy = -tpPos.
vxy /
det;
551 double chi2 = wxx * res.
x * res.
x + wyy * res.
y * res.
y + 2 * wxy * res.
x * res.
y;
554 ofile << ms->getId() << separator << ms->x << separator << ms->y << separator;
555 ofile << res.
x << separator << res.
y << separator;
556 ofile << tpPos.
x << separator << tpPos.
y << separator;
557 ofile << fs->getMag() << separator << deltaYears << separator;
558 ofile << tpPos.
vx << separator << tpPos.
vy << separator << tpPos.
vxy << separator;
559 ofile << inputTpPos.
x << separator << inputTpPos.
y << separator;
560 ofile << inputRes.
x << separator << inputRes.
y << separator;
561 ofile << fs->getIndexInMatrix() << separator;
562 ofile << fs->x << separator << fs->y << separator;
563 ofile << chi2 << separator << fs->getMeasurementCount() << separator;
573 ofile <<
"ra" << separator <<
"dec " << separator;
574 ofile <<
"rx" << separator <<
"ry" << separator;
575 ofile <<
"mag" << separator;
576 ofile <<
"xErr" << separator <<
"yErr" << separator <<
"xyCov" << separator;
577 ofile <<
"fsindex" << separator;
578 ofile <<
"chi2" << separator <<
"nm" <<
std::endl;
580 ofile <<
"coordinates of fittedStar (degrees)" << separator << separator;
581 ofile <<
"residual on TP (degrees)" << separator << separator;
582 ofile <<
"magnitude" << separator;
583 ofile <<
"refStar transformed measurement uncertainty (degrees)" << separator << separator << separator;
584 ofile <<
"unique index of the fittedStar" << separator;
585 ofile <<
"refStar contribution to chi2 (2D dofs)" << separator
586 <<
"number of measurements of this FittedStar" <<
std::endl;
591 for (
auto const &i : fittedStarList) {
594 if (rs ==
nullptr)
continue;
599 double chi2 = computeProjectedRefStarChi2(rsProj);
602 ofile << fs.
x << separator << fs.
y << separator;
603 ofile << rsProj.
x << separator << rsProj.
y << separator;
604 ofile << fs.
getMag() << separator;
605 ofile << rsProj.
vx << separator << rsProj.
vy << separator << rsProj.
vxy << separator;
Eigen::SparseMatrix< double, 0, Eigen::Index > SparseMatrixD
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
LSST DM logging module built on log4cxx.
#define LOGLS_WARN(logger, message)
Log a warn-level message using an iostream-based interface.
#define LOG_GET(logger)
Returns a Log object associated with logger.
#define LOGLS_INFO(logger, message)
Log a info-level message using an iostream-based interface.
#define LOGLS_DEBUG(logger, message)
Log a debug-level message using an iostream-based interface.
void checkStuff()
DEBUGGING routine.
void leastSquareDerivativesMeasurement(CcdImage const &ccdImage, TripletList &tripletList, Eigen::VectorXd &grad, MeasuredStarList const *msList=nullptr) const override
Compute the derivatives of the measured stars and model for one CcdImage.
void accumulateStatImageList(CcdImageList const &ccdImageList, Chi2Accumulator &accum) const override
Compute the chi2 (per star or total, depending on which Chi2Accumulator is used) for measurements.
void accumulateStatRefStars(Chi2Accumulator &accum) const override
Compute the chi2 (per star or total, depending on which Chi2Accumulator is used) for RefStars.
void saveChi2RefContributions(std::string const &filename) const override
Save a CSV file containing residuals of reference terms.
void offsetParams(Eigen::VectorXd const &delta) override
Offset the parameters by the requested quantities.
AstrometryFit(std::shared_ptr< Associations > associations, std::shared_ptr< AstrometryModel > astrometryModel, double posError)
this is the only constructor
void assignIndices(std::string const &whatToFit) override
Set parameters to fit and assign indices in the big matrix.
void leastSquareDerivativesReference(FittedStarList const &fittedStarList, TripletList &tripletList, Eigen::VectorXd &grad) const override
Compute the derivatives of the reference terms.
void getIndicesOfMeasuredStar(MeasuredStar const &measuredStar, IndexVector &indices) const override
this routine is to be used only in the framework of outlier removal
void saveChi2MeasContributions(std::string const &filename) const override
Save a CSV file containing residuals of measurement terms.
virtual class needed in the abstraction of the distortion model
virtual void transformPosAndErrors(FatPoint const &where, FatPoint &outPoint) const =0
The same as above but without the parameter derivatives (used to evaluate chi^2)
virtual void computeTransformAndDerivatives(FatPoint const &where, FatPoint &outPoint, Eigen::MatrixX2d &H) const =0
Actually applies the AstrometryMapping and evaluates the derivatives w.r.t the fitted parameters.
virtual void getMappingIndices(IndexVector &indices) const =0
Sets how this set of parameters (of length Npar()) map into the "grand" fit Expects that indices has ...
virtual std::size_t getNpar() const =0
Number of parameters in total.
Handler of an actual image from a single CCD.
CcdIdType getCcdId() const
returns ccd ID
VisitIdType getVisit() const
returns visit ID
std::shared_ptr< AstrometryTransform > const getReadWcs() const
the wcs read in the header. NOT updated when fitting.
MeasuredStarList const & getCatalogForFit() const
Gets the catalog to be used for fitting, which may have been cleaned-up.
std::string getName() const
Return the _name that identifies this ccdImage.
Base class for Chi2Statistic and Chi2List, to allow addEntry inside Fitter for either class.
virtual void addEntry(double inc, std::size_t dof, std::shared_ptr< BaseStar > star)=0
A Point with uncertainties.
FittedStars are objects whose position or flux is going to be fitted, and which come from the associa...
void setIndexInMatrix(Eigen::Index const index)
index is a value that a fit can set and reread....
const RefStar * getRefStar() const
Get the astrometric reference star associated with this star.
int getMeasurementCount() const
The number of MeasuredStars currently associated with this FittedStar.
Eigen::Index getIndexInMatrix() const
A list of FittedStar s. Such a list is typically constructed by Associations.
void leastSquareDerivatives(TripletList &tripletList, Eigen::VectorXd &grad) const
Evaluates the chI^2 derivatives (Jacobian and gradient) for the current whatToFit setting.
Eigen::Index _nModelParams
std::shared_ptr< Associations > _associations
Eigen::Index _nStarParams
Sources measured on images.
bool isValid() const
Fits may use that to discard outliers.
CcdImage const & getCcdImage() const
std::shared_ptr< FittedStar > getFittedStar() const
A list of MeasuredStar. They are usually filled in Associations::createCcdImage.
Point applyProperMotion(const Point &star, double timeDeltaYears) const
Apply proper motion correction to the input star, returning a star with PM-corrected coordinates and ...
This one is the Tangent Plane (called gnomonic) projection (from celestial sphere to tangent plane)
void transformPosAndErrors(const FatPoint &in, FatPoint &out) const
transform with analytical derivatives
void setTangentPoint(Point const &tangentPoint)
Resets the projection (or tangent) point.
Eigen::Index getNextFreeIndex() const
void setNextFreeIndex(Eigen::Index index)
void addTriplet(Eigen::Index i, Eigen::Index j, double val)
Reports invalid arguments.
std::unique_ptr< AstrometryTransform > compose(AstrometryTransform const &left, AstrometryTransform const &right)
Returns a pointer to a composition of transforms, representing left(right()).
T setprecision(T... args)