13 #include <fileutils.h>
18 #include "fittedstarmap.h"
19 #include "associations.h"
23 template <
class Model>
33 void LoopOnMeasurements(Op& op)
const;
39 bool InitFit(
int niter=100);
48 bool NewtonRaphsonStep();
51 bool Minimize(
unsigned int maxiter=100);
54 int RemoveOutliers(
double nsig);
58 unsigned int GetNFittedPars()
const;
61 double GetChi2()
const;
70 Vect
const& GetPar()
const;
73 Vect
const& GetParError()
const;
76 Mat
const& GetCovMatrix()
const;
79 Mat
const& GetCorrMatrix()
const;
82 void DumpNTuples(std::string
const& resultdir)
const;
85 void SetVerbose(
bool verbose=
true) { verbose_ = verbose; }
89 bool ComputeCorrMat();
90 void dumpParNTuple_(
const std::string& ntname)
const;
92 void dumpFittedStarNTuple_(
const std::string& ntname)
const;
93 void dumpMeasuredStarNTuple_(
const std::string& ntname,
unsigned int nusrvals=0)
const;
95 void updateFittedStars_();
99 CcdImageList& imstd::list_;
111 mutable bool cleanChi2_;
112 mutable double chi2_;
123 double sq(
double x) {
return x*x; }
125 template<
class Model>
126 PhotFitter<Model>::PhotFitter(
Associations& assoc, Model& model)
127 : assoc_(assoc), model_(model),
128 imstd::list_(assoc_.ccdImageList),
129 fittedstarstd::list_(assoc_.fittedStarList),
134 chi2_(-1), nmes_(-1), ndof_(-1)
151 template<
class Model>
template<
class Op>
152 void PhotFitter<Model>::LoopOnMeasurements(Op& op)
const
154 CcdImageIterator imI;
155 MeasuredStarIterator stI;
157 for(imI=imstd::list_.begin();imI!=imstd::list_.end();imI++)
161 for(stI=catalog.begin();stI!=catalog.end();stI++)
174 template<
class Model>
178 TestModel(Model
const& model)
179 : model_(model), npar_(model_.Size())
182 pars_.allocate(npar_);
189 model_.CanCompute(m, pars_);
194 Vect
const GetPars()
const {
return pars_; }
211 template<
class Model>
212 bool PhotFitter<Model>::InitFit(
int niter)
220 npar_ = model_.Size();
225 TestModel<Model> tmodel(model_);
226 for(iter=0;iter<10;iter++)
228 LoopOnMeasurements(tmodel);
240 model_.InitIndexTables(tmodel.GetPars());
251 npar_ = model_.NPar();
252 pars_.allocate(npar_);
253 model_.InitPars(pars_);
255 double old_chi2, chi2 = GetChi2();
256 int igroup, ngroups = model_.NGroups();
258 for(iter=0;iter<niter;iter++)
262 double chi2 = GetChi2();
265 if( old_chi2 < chi2 )
268 cout <<
"[PhotFitter<>::InitFit] Warning increasing chi2 in InitFit() !"
276 cout <<
"[PhotFitter<>::InitFit] Warning max iter=" << niter
277 <<
" reached" << endl;
281 cout <<
" Chi2=" << chi2 << endl;
289 template<
class Model>
297 MatrixFill(Vect& pars, Mat& M, Vect& B, Model& model,
int igroup=-1)
298 : npar_( model.NPar(igroup) ),
299 npartot_( model.NPar() ),
307 assert( M_.SizeX() == npar_ );
308 assert( M_.SizeY() == npar_ );
309 assert( B_.Size() == npar_ );
311 validpar_.allocate(npar_);
313 deriv_.allocate(npartot_);
342 bool status = model_.Compute(m, pars_, val, deriv_);
345 int g_index = model_.GroupIndex(igroup_);
347 double flux = m.flux;
348 double w = 1. / sq(m.FluxSig());
353 if(deriv_(i+g_index) == 0.)
continue;
354 B_(i) += -(w * (val-flux) * deriv_(i+g_index));
357 if(deriv_(j+g_index) == 0.)
continue;
358 M_(i,j) += w * deriv_(i+g_index) * deriv_(j+g_index);
381 cout <<
" Finalize: M(" << i <<
"," << i <<
")=" << M_(i,i) << endl;
393 bool IsValid(
unsigned int i)
402 unsigned int npartot_;
416 template<
class Model>
423 Chi2Acc(Model& model, Vect
const& pars,
bool cmpsig=
false)
424 : chi2_(0.), medres_(0.), sigres_(0.),
425 model_(model), pars_(pars), nmes_(0), cmpsig_(cmpsig)
427 deriv_.allocate(model_.NPar());
448 bool status = model_.Compute(m, pars_, val, deriv_);
451 double flux = m.flux;
452 double eflux = m.FluxSig();
455 double resid = sq( (flux-val)/eflux );
459 resids_.push_back(resid);
465 unsigned int i, sz=resids_.size();
466 double* residuals =
new double[sz];
467 for(i=0;i<sz;i++) residuals[i] = resids_[i];
469 medres_ = sigres_ = 0.;
470 Dmean_median_sigma(residuals, sz, mean, medres_, sigres_);
474 double Chi2()
const {
return chi2_; }
475 double MedianRes()
const {
return medres_; }
476 double SigmaRes()
const {
return sigres_; }
477 int NMes()
const {
return nmes_; }
488 std::vector<double> resids_;
493 template<
class Model>
494 bool PhotFitter<Model>::FlipFlopStep()
496 cout <<
"[PhotFitter<Model>::FlipFlopStep]" << endl;
500 int igroup, ngroups = model_.NGroups();
501 for(igroup=0;igroup<ngroups;igroup++)
503 unsigned int sz = model_.NPar(igroup);
506 cout <<
" *** igroup=" << igroup
507 <<
", npar=" << sz << endl;
509 MatrixFill<Model> fill(pars_, M, B, model_, igroup);
510 LoopOnMeasurements(fill);
515 int status = cholesky_solve(M, B,
"U");
518 cout <<
"[PhotFitter<>::InitFit] cholesky_solve ERROR, status="
520 M.writeFits(
"toto.fits");
531 unsigned int idx, ig = model_.GroupIndex(igroup);
533 if( fill.IsValid(i) )
544 cout <<
"Cannot update par(" << i <<
")="
546 <<
" B(" << i <<
")=" << B(i)
555 template<
class Model>
556 bool PhotFitter<Model>::NewtonRaphsonStep()
560 unsigned int sz = model_.NPar();
568 MatrixFill<Model> fill(pars_, M, B, model_, -1);
569 LoopOnMeasurements(fill);
571 cout <<
"[PhotFitter<>::NewtonRaphsonStep] " << (double)(stop-start) / (double)CLOCKS_PER_SEC
572 <<
" to fill the fit matrix" << endl;
575 int status = cholesky_solve(M, B,
"U");
577 cout <<
"[PhotFitter<>::NewtonRaphsonStep] " << (double)(stop-start) / (double)CLOCKS_PER_SEC
578 <<
" to invert it (using cholesky_solve)" << endl;
582 cout <<
"[PhotFitter<>::NewtonRaphsonStep] cholesky_solve ERROR, status="
585 M.writeFits(
"NewtonRaphson_DEBUG.fits");
594 if( fill.IsValid(i) )
601 cout <<
"Cannot update pars(" << i <<
")=" << pars_(i)
610 template<
class Model>
611 bool PhotFitter<Model>::Minimize(
unsigned int maxiter)
615 double chi2 = 99.E99;
626 cout <<
"[PhotFitter<Model>::Minimize()] STEP #" << i
635 <<
"[PhotFitter<>::Mininize()] ERROR increasing chi2 "
636 << oldchi2 <<
" --> " << chi2 << endl;
641 if( (oldchi2-chi2) < minstep_ )
645 cout <<
" ... CONVERGED." << endl;
654 <<
"[PhotFitter<>::Minimize()] ERROR, maxiter="
655 << maxiter <<
" reached wo convergence." << endl;
664 status = ComputeCovMat();
665 status = ComputeCorrMat();
667 if(status) updateFittedStars_();
673 template<
class Model>
674 bool PhotFitter<Model>::ComputeCovMat()
676 epars_.allocate(model_.NPar());
677 covmat_.allocate(model_.NPar(), model_.NPar());
680 MatrixFill<Model> fill(pars_, covmat_, epars_, model_, -1);
681 LoopOnMeasurements(fill);
683 int status = cholesky_solve(covmat_, epars_,
"U");
686 cout <<
"[PhotFitter<Model>::ComputeCovMat] cholesky_solve ERROR, status="
692 status = cholesky_invert(covmat_,
"U");
704 epars_(i) = sqrt(covmat_(i,i));
710 template<
class Model>
711 bool PhotFitter<Model>::ComputeCorrMat()
717 if( covmat_.SizeX() != model_.NPar() ||
718 covmat_.SizeY() != model_.NPar() )
719 status = ComputeCovMat();
721 if(!status)
return status;
725 corrmat_.allocate(model_.NPar(), model_.NPar());
727 for(i=0;i<model_.NPar();i++)
729 double cii = sqrt(covmat_(i,i));
730 for(j=i;j<model_.NPar();j++)
732 double cjj = sqrt(covmat_(j,j));
733 corrmat_(i,j) = covmat_(i,j) / (cii*cjj);
742 template<
class Model>
746 OutlierRemover(Model
const& model, Vect
const& pars,
748 : cut_(cut), nkilled_(0), model_(model), pars_(pars)
750 deriv_.allocate(model_.NPar());
753 ~OutlierRemover() { }
758 bool status = model_.Compute(m, pars_, val, deriv_);
765 double flux = m.flux;
766 double eflux = m.FluxSig();
769 double resid = sq( (flux-val) / eflux );
779 unsigned int NKilled()
const {
return nkilled_; }
783 unsigned int nkilled_;
791 template<
class Model>
792 int PhotFitter<Model>::RemoveOutliers(
double nsig)
794 Chi2Acc<Model> acc(model_, pars_,
true);
795 LoopOnMeasurements(acc);
796 double med = acc.MedianRes();
797 double sig = acc.SigmaRes();
798 double cut = med + nsig * sig;
801 cout <<
" med=" << med
803 <<
" cut=" << cut << endl;
805 cout <<
"[PhotFitter<>::RemoveOutliers()] BEFORE OUTLIER REMOVAL: " << GetChi2() << endl;
806 OutlierRemover<Model> rem(model_, pars_, cut);
807 LoopOnMeasurements(rem);
810 cout <<
"[PhotFitter<>::RemoveOutliers()] " << rem.NKilled() <<
" measurements removed" << endl;
811 cout <<
"[PhotFitter<>::RemoveOutliers()] AFTER OUTLIER REMOVAL: " << GetChi2() << endl;
813 return rem.NKilled();
818 template<
class Model>
819 unsigned int PhotFitter<Model>::GetNFittedPars()
const
821 unsigned int ret = 0;
823 for(i=0;i<model_.NPar();i++)
831 template<
class Model>
832 double PhotFitter<Model>::GetChi2()
const
834 if(cleanChi2_)
return chi2_;
835 Chi2Acc<Model> acc(model_, pars_);
836 LoopOnMeasurements(acc);
839 ndof_ = acc.NMes() - model_.NPar();
845 template<
class Model>
846 int PhotFitter<Model>::GetNMes()
const
848 if(cleanChi2_)
return nmes_;
853 template<
class Model>
854 int PhotFitter<Model>::GetNDoF()
const
856 if(cleanChi2_)
return ndof_;
862 template<
class Model>
863 Vect
const& PhotFitter<Model>::GetPar()
const
869 template<
class Model>
870 Vect
const& PhotFitter<Model>::GetParError()
const
876 template<
class Model>
877 Mat
const& PhotFitter<Model>::GetCovMatrix()
const
882 template<
class Model>
883 Mat
const& PhotFitter<Model>::GetCorrMatrix()
const
889 template<
class Model>
890 void PhotFitter<Model>::updateFittedStars_()
892 FittedStarIterator I;
893 for(I=fittedstarstd::list_.begin();I!=fittedstarstd::list_.end();I++)
897 model_.UpdateFittedStar(*fs, pars_, epars_);
902 template<
class Model>
903 void PhotFitter<Model>::dumpParNTuple_(std::string
const& ntname)
const
906 ofstream ofs(ntname.c_str());
907 ofs <<
"# num : " << endl
908 <<
"# val : " << endl
909 <<
"# err : " << endl
912 for(i=0;i<model_.NPar();i++)
916 << epars_(i) << endl;
924 template<
class Model>
925 void PhotFitter<Model>::dumpFittedStarNTuple_(
const std::string& ntname)
const
927 ofstream ofs(ntname.c_str());
928 ofs <<
"# index : " << endl
930 <<
"# dec : " << endl
931 <<
"# flux : " << endl
932 <<
"# eflux : " << endl
933 <<
"# nmeas : " << endl
934 <<
"# ref : " << endl
937 FittedStarCIterator I;
938 for(I=fittedstarstd::list_.begin();I!=fittedstarstd::list_.end();I++)
942 const RefStar* rs = fs->GetRefStar();
943 ofs << fs->Index() <<
" "
947 << fs->FluxErr() <<
" "
948 << fs->MeasurementCount() <<
" "
959 class MeasurementDumper
962 MeasurementDumper(ofstream& ofs, FittedStarMap
const& fsm,
963 unsigned int nusrvals=0)
964 : ofs_(ofs), fsm_(fsm), nusrvals_(nusrvals)
969 ~MeasurementDumper() { }
976 CcdImage const& ccdim = ms.GetCcdImage();
979 double efluxfit = -1;
986 fluxfit = fs->
Flux();
987 efluxfit = fs->FluxErr();
990 nmeas = fs->MeasurementCount();
991 nccds = fsm_.NCcds(fs);
1002 << ccdim.
Shoot() - 700000 <<
" "
1003 << ccdim.
Chip() <<
" "
1010 BaseStarWithError
const* mcstar = ms.GetMCMeas();
1012 ofs_ << mcstar->Flux() <<
" "
1013 << mcstar->EFlux() <<
" ";
1018 BaseStarWithError
const* mcstar_truth = ms.GetMCTruth();
1020 ofs_ << mcstar_truth->Flux();
1025 assert(nusrvals_ <= ms.usrVals.size());
1027 for(i=0;i<nusrvals_;i++)
1028 ofs_ << ms.usrVals[i] <<
" ";
1042 FittedStarMap
const& fsm_;
1043 unsigned int nusrvals_;
1048 void writeHeader_(ofstream& ofs)
1050 ofs <<
"# x : x in ccd" << endl
1051 <<
"# y : y in ccd" << endl
1052 <<
"# flux : flux measured on ccd" << endl
1053 <<
"# eflux : flux error" << endl
1054 <<
"# fluxfit : fitted flux" << endl
1055 <<
"# efluxfit : error on fitted flux" << endl
1056 <<
"# xdeg : x in degrees in tangent plane" << endl
1057 <<
"# ydeg : y in degrees in tangent plane" << endl
1058 <<
"# image : image number - 700000" << endl
1059 <<
"# ccd : ccd" << endl
1060 <<
"# band : band used for this measurement" << endl
1061 <<
"# airmass : airmass of this measurement" << endl
1062 <<
"# nm : number of measurements" << endl
1063 <<
"# nccd : number of diff ccds" << endl
1064 <<
"# mflux : true (distorted) flux on CCD" << endl
1065 <<
"# meflux : true flux error on CCD" << endl
1066 <<
"# iflux : initial flux" << endl;
1068 for(i=0;i<nusrvals_;i++)
1069 ofs <<
"# usr" << i <<
" : " << endl;
1070 ofs <<
"# end" << endl;
1076 template<
class Model>
1077 void PhotFitter<Model>::dumpMeasuredStarNTuple_(
const std::string& ntname,
1078 unsigned int nusrvals)
const
1080 ofstream ofs(ntname.c_str());
1081 FittedStarMap fsm(imstd::list_);
1082 MeasurementDumper dump(ofs, fsm, nusrvals);
1083 LoopOnMeasurements(dump);
1089 template<
class Model>
1090 void PhotFitter<Model>::DumpNTuples(
const std::string& dirname)
const
1094 cout <<
"[PhotFitter<>::DumpNTuple(" << dirname <<
")]" << endl;
1097 if( !FileExists(dirname) )
1098 if( !MKDir(dirname.c_str()) )
1100 cout <<
"[PhotFitter<>::DumpNTuple()] ERROR "
1101 <<
" unable to create dir=" << dirname
1107 std::string parntname = dirname +
"/fitpars.ntuple";
1108 dumpParNTuple_(parntname);
1111 std::string fstarntname = dirname +
"/fstars.std::list";
1112 dumpFittedStarNTuple_(fstarntname);
1115 std::string mstarntname = dirname +
"/mstars.std::list";
1116 dumpMeasuredStarNTuple_(mstarntname);
A list of FittedStar s. Such a list is typically constructed by Associations.
Definition: fittedstar.h:158
Objects used as position anchors, typically USNO stars. Coordinate system defined by user...
Definition: refstar.h:12
The class that implements the relations between MeasuredStar and FittedStar.
Definition: associations.h:17
int Shoot() const
returns shoot ID
Definition: ccdimage.h:138
handler of an actual image from a single CCD
Definition: ccdimage.h:21
int BandIndex() const
return the CcdImage band index. This is a static index that mostly turns a letter (e...
Definition: ccdimage.h:190
The objects which have been measured several times. The MeasuredStar s measuring the same object in d...
Definition: fittedstar.h:37
double Flux() const
getters
Definition: fittedstar.h:135
int Chip() const
returns chip ID
Definition: ccdimage.h:120
double AirMass() const
Airmass.
Definition: ccdimage.h:144
objects measured on actual images. Coordinates and uncertainties are expressed in pixel image frame...
Definition: measuredstar.h:21
A list of MeasuredStar. They are usually filled in Associations::AddImage.
Definition: measuredstar.h:105
void SetValid(bool v)
Fits may use that to discard outliers.
Definition: measuredstar.h:85