gastro  0.1.0
 All Classes Files Functions Variables Pages
photfitter.h
1 // -*- C++ -*-
2 //
3 
4 #ifndef PHOTFITTER_H
5 #define PHOTFITTER_H
6 
7 #include <time.h>
8 
9 #include <math.h>
10 #include <assert.h>
11 #include <fstream>
12 
13 #include <fileutils.h>
14 #include "vutils.h"
15 
16 #include "measuredstar.h"
17 #include "fittedstar.h"
18 #include "fittedstarmap.h"
19 #include "associations.h"
20 
21 
22 
23 template <class Model>
24 class PhotFitter
25 {
26 public:
27  PhotFitter(Associations& assoc, Model& model);
28 
29  ~PhotFitter() {}
30 
32  template<class Op>
33  void LoopOnMeasurements(Op& op) const;
34 
39  bool InitFit(int niter=100);
40 
42  bool InitModel();
43 
45  bool FlipFlopStep();
46 
48  bool NewtonRaphsonStep();
49 
51  bool Minimize(unsigned int maxiter=100);
52 
54  int RemoveOutliers(double nsig);
55 
58  unsigned int GetNFittedPars() const;
59 
61  double GetChi2() const;
62 
64  int GetNMes() const;
65 
67  int GetNDoF() const;
68 
70  Vect const& GetPar() const;
71 
73  Vect const& GetParError() const;
74 
76  Mat const& GetCovMatrix() const;
77 
79  Mat const& GetCorrMatrix() const;
80 
82  void DumpNTuples(std::string const& resultdir) const;
83 
85  void SetVerbose(bool verbose=true) { verbose_ = verbose; }
86 
87 private:
88  bool ComputeCovMat();
89  bool ComputeCorrMat();
90  void dumpParNTuple_(const std::string& ntname) const;
91 public:
92  void dumpFittedStarNTuple_(const std::string& ntname) const;
93  void dumpMeasuredStarNTuple_(const std::string& ntname, unsigned int nusrvals=0) const;
94 private:
95  void updateFittedStars_();
96 
97  Associations& assoc_;
98  Model& model_;
99  CcdImageList& imstd::list_;
100  FittedStarList& fittedstarstd::list_;
101 
102  unsigned int npar_;
103  Vect pars_;
104  Vect epars_;
105  Mat covmat_;
106  Mat corrmat_;
107 
108  double minstep_;
109 
110  bool verbose_;
111  mutable bool cleanChi2_;
112  mutable double chi2_;
113  mutable int nmes_;
114  mutable int ndof_;
115 };
116 
117 
119 //
120 // template methods
121 //
122 
123 double sq(double x) { return x*x; }
124 
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),
130  npar_(0), // one ne sait pas a l'avance combien on aura de parametres...
131  minstep_(1.E-3),
132  verbose_(false),
133  cleanChi2_(false),
134  chi2_(-1), nmes_(-1), ndof_(-1)
135 {
136  // cout << " MODEL # pars=" << model_.NPar() << endl;
137  // pars_.allocate(npar_);
138  // epars_.allocate(npar_);
139  // cout << " PHOTFITTER: nfittedstars=" << fittedstarstd::list_.size() << endl;
140 
141  // int index = 0;
142  // FittedStarIterator I;
143  // for(I=fittedstarstd::list_.begin();I!=fittedstarstd::list_.end();I++)
144  // {
145  // FittedStar* s = *I;
146  // s->SetIndex(index++);
147  // }
148 }
149 
150 
151 template<class Model> template<class Op>
152 void PhotFitter<Model>::LoopOnMeasurements(Op& op) const
153 {
154  CcdImageIterator imI;
155  MeasuredStarIterator stI;
156 
157  for(imI=imstd::list_.begin();imI!=imstd::list_.end();imI++)
158  {
159  CcdImage& ccdImage = **imI;
160  MeasuredStarList& catalog = ccdImage.CatalogForFit();
161  for(stI=catalog.begin();stI!=catalog.end();stI++)
162  {
163  MeasuredStar& m = **stI;
164  FittedStar* f = m.GetFittedStar();
165  if(!f) continue;
166  op(m);
167  }
168  }
169 
170  op.Finalize();
171 }
172 
173 
174 template<class Model>
175 class TestModel
176 {
177 public:
178  TestModel(Model const& model)
179  : model_(model), npar_(model_.Size())
180  {
181  assert(npar_>0);
182  pars_.allocate(npar_);
183  }
184 
185  ~TestModel() { }
186 
187  void operator()(MeasuredStar const& m)
188  {
189  model_.CanCompute(m, pars_);
190  }
191 
192  void Finalize() {}
193 
194  Vect const GetPars() const { return pars_; }
195 
196 private:
197  Model model_;
198  unsigned int npar_;
199  Vect pars_;
200 };
201 
202 
203 
204 // To initialize the fit, we
205 // fit separately each group
206 // of parameters... If the user
207 // chose them so that the fit is
208 // almost linear, it should give us
209 // a good start ...
210 
211 template<class Model>
212 bool PhotFitter<Model>::InitFit(int niter) // maybe we should call this FlipFlopFit()
213 {
214  unsigned int i;
215 
216  // model_.InitPars(pars_);
217  int iter;
218  int fcount = 0;
219  int rcount = 0;
220  npar_ = model_.Size();
221  // unsigned int nfittedstars = fittedstarstd::list_.size();
222  // unsigned int nccd = 36;
223  // npar_ = nfittedstars + nccd;
224 
225  TestModel<Model> tmodel(model_);
226  for(iter=0;iter<10;iter++)
227  {
228  LoopOnMeasurements(tmodel);
229  // rcount = 0; fcount=0;
230  // for(i=0;i<npar_;i++)
231  // {
232  // if(tmodel.GetPars()(i) == 1) rcount++;
233  // if(tmodel.GetPars()(i) == 2) fcount++;
234  // }
235  // cout << " rcount=" << rcount
236  // << " fcount=" << fcount
237  // << endl;
238  }
239 
240  model_.InitIndexTables(tmodel.GetPars());
241 
242  // for(i=0;i<npar_;i++)
243  // cout << " pars(" << i << ")=" << tmodel.GetPars()(i) << endl;
244 
245  // cout << " model_.NPar() = " << model_.NPar()
246  // << " model_.Npar(0) = " << model_.NPar(0)
247  // << " model_.Npar(1) = " << model_.NPar(1)
248  // << " model_.NPar(2) = " << model_.NPar(2)
249  // << endl;
250 
251  npar_ = model_.NPar();
252  pars_.allocate(npar_);
253  model_.InitPars(pars_);
254 
255  double old_chi2, chi2 = GetChi2();
256  int igroup, ngroups = model_.NGroups();
257 
258  for(iter=0;iter<niter;iter++)
259  {
260  old_chi2 = chi2;
261  FlipFlopStep();
262  double chi2 = GetChi2();
263 
264  // check that the Chi2 is not going up
265  if( old_chi2 < chi2 )
266  {
267  // we should do something clever here
268  cout << "[PhotFitter<>::InitFit] Warning increasing chi2 in InitFit() !"
269  << endl;
270  return false;
271  }
272 
273  // break if too many iterations
274  if( iter >= niter )
275  {
276  cout << "[PhotFitter<>::InitFit] Warning max iter=" << niter
277  << " reached" << endl;
278  return false;
279  }
280 
281  cout << " Chi2=" << chi2 << endl;
282  }
283 
284  return true;
285 }
286 
287 
288 
289 template<class Model>
290 class MatrixFill
291 {
292 public:
293 
297  MatrixFill(Vect& pars, Mat& M, Vect& B, Model& model, int igroup=-1)
298  : npar_( model.NPar(igroup) ),
299  npartot_( model.NPar() ),
300  igroup_(igroup),
301  pars_(pars),
302  M_(M),
303  B_(B),
304  model_(model)
305  {
306  // assert( pars_.Size() == npar_ ); because pars_.Size() = total # of parameters
307  assert( M_.SizeX() == npar_ );
308  assert( M_.SizeY() == npar_ );
309  assert( B_.Size() == npar_ );
310 
311  validpar_.allocate(npar_);
312  validpar_.Zero();
313  deriv_.allocate(npartot_);
314 
315  // if(igroup_<0)
316  // {
317  // cout << " igroup=" << igroup_
318  // << " npar_ = " << npar_
319  // << endl;
320  // }
321  }
322 
326  ~MatrixFill() {}
327 
328 
339  void operator()(MeasuredStar const& m) const
340  {
341  double val;
342  bool status = model_.Compute(m, pars_, val, deriv_);
343  if(!status) return;
344 
345  int g_index = model_.GroupIndex(igroup_);
346 
347  double flux = m.flux;
348  double w = 1. / sq(m.FluxSig());
349 
350  unsigned int i, j;
351  for(i=0;i<npar_;i++)
352  {
353  if(deriv_(i+g_index) == 0.) continue;
354  B_(i) += -(w * (val-flux) * deriv_(i+g_index));
355  for(j=i;j<npar_;j++)
356  {
357  if(deriv_(j+g_index) == 0.) continue;
358  M_(i,j) += w * deriv_(i+g_index) * deriv_(j+g_index);
359  }
360  }
361  }
362 
373  void Finalize()
374  {
375  unsigned int i;
376  for(i=0;i<npar_;i++)
377  if(M_(i,i) == 0.)
378  {
379  // we fix the parameter,
380  // since it seems to be masked...
381  cout << " Finalize: M(" << i << "," << i << ")=" << M_(i,i) << endl;
382  M_(i,i) = 1.;
383  }
384  else
385  validpar_(i) = 1;
386  }
387 
393  bool IsValid(unsigned int i)
394  {
395  assert(i<npar_);
396  return validpar_(i);
397  // return true;
398  }
399 
400 private:
401  unsigned int npar_;
402  unsigned int npartot_;
403  int igroup_;
404 
405  Vect& pars_;
406  Mat& M_;
407  Vect& B_;
408  Model& model_;
409 
410  mutable Vect deriv_;
411  Vect validpar_;
412 };
413 
414 
415 
416 template<class Model>
417 class Chi2Acc
418 {
419 public:
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)
426  {
427  deriv_.allocate(model_.NPar());
428  }
429 
430 
434  ~Chi2Acc() {}
435 
436 
445  void operator()(MeasuredStar& m)
446  {
447  double val;
448  bool status = model_.Compute(m, pars_, val, deriv_);
449  if(!status) return;
450 
451  double flux = m.flux;
452  double eflux = m.FluxSig();
453  assert(eflux>0);
454 
455  double resid = sq( (flux-val)/eflux );
456  chi2_ += resid;
457  nmes_++;
458 
459  resids_.push_back(resid);
460  }
461 
462  void Finalize()
463  {
464  if(!cmpsig_) return;
465  unsigned int i, sz=resids_.size();
466  double* residuals = new double[sz];
467  for(i=0;i<sz;i++) residuals[i] = resids_[i];
468  double mean=0;
469  medres_ = sigres_ = 0.;
470  Dmean_median_sigma(residuals, sz, mean, medres_, sigres_);
471  delete[] residuals;
472  }
473 
474  double Chi2() const { return chi2_; }
475  double MedianRes() const { return medres_; }
476  double SigmaRes() const { return sigres_; }
477  int NMes() const { return nmes_; }
478 
479 private:
480  double chi2_;
481  double medres_;
482  double sigres_;
483 
484  Model model_;
485  Vect const& pars_;
486  Vect deriv_;
487  int nmes_;
488  std::vector<double> resids_;
489  bool cmpsig_;
490 };
491 
492 
493 template<class Model>
494 bool PhotFitter<Model>::FlipFlopStep()
495 {
496  cout << "[PhotFitter<Model>::FlipFlopStep]" << endl;
497  cleanChi2_ = false;
498 
499  unsigned int i;
500  int igroup, ngroups = model_.NGroups();
501  for(igroup=0;igroup<ngroups;igroup++)
502  {
503  unsigned int sz = model_.NPar(igroup);
504  Mat M(sz,sz);
505  Vect B(sz);
506  cout << " *** igroup=" << igroup
507  << ", npar=" << sz << endl;
508 
509  MatrixFill<Model> fill(pars_, M, B, model_, igroup);
510  LoopOnMeasurements(fill);
511 
512  // M.writeFits("toto.fits");
513  // exit(0);
514 
515  int status = cholesky_solve(M, B, "U");
516  if(status!=0)
517  {
518  cout << "[PhotFitter<>::InitFit] cholesky_solve ERROR, status="
519  << status << endl;
520  M.writeFits("toto.fits");
521  return false;
522  }
523  // else
524  // {
525  // cout << "[PhotFitter<>::InitFit] cholesky_solve OK, status="
526  // << status << endl;
527  // }
528 
529  // and now, update the --valid-- parameters
530  // unsigned int np = 0;
531  unsigned int idx, ig = model_.GroupIndex(igroup);
532  for(i=0;i<sz;i++)
533  if( fill.IsValid(i) )
534  {
535  // assert( !isinf(B(i)) ); // ceinture et bretelles
536  idx = ig + i;
537  pars_(idx) += B(i);
538  // cout << " par(" << idx << ") --> "
539  // << pars_(idx) << "(dpar=" << B(i) << ")" << endl;
540  // np++;
541  }
542  else
543  {
544  cout << "Cannot update par(" << i << ")="
545  << pars_(i)
546  << " B(" << i << ")=" << B(i)
547  << endl;
548  }
549  }
550 
551  return true;
552 }
553 
554 
555 template<class Model>
556 bool PhotFitter<Model>::NewtonRaphsonStep()
557 {
558  cleanChi2_ = false;
559 
560  unsigned int sz = model_.NPar();
561  Mat M(sz,sz);
562  Vect B(sz);
563 
564  clock_t start;
565  clock_t stop;
566 
567  start = clock();
568  MatrixFill<Model> fill(pars_, M, B, model_, -1);
569  LoopOnMeasurements(fill);
570  stop = clock();
571  cout << "[PhotFitter<>::NewtonRaphsonStep] " << (double)(stop-start) / (double)CLOCKS_PER_SEC
572  << " to fill the fit matrix" << endl;
573 
574  start = clock();
575  int status = cholesky_solve(M, B, "U");
576  stop = clock();
577  cout << "[PhotFitter<>::NewtonRaphsonStep] " << (double)(stop-start) / (double)CLOCKS_PER_SEC
578  << " to invert it (using cholesky_solve)" << endl;
579 
580  if(status!=0)
581  {
582  cout << "[PhotFitter<>::NewtonRaphsonStep] cholesky_solve ERROR, status="
583  << status
584  << endl;
585  M.writeFits("NewtonRaphson_DEBUG.fits");
586  return false;
587  }
588 
589  // M.writeFits("NewtonRaphson_DEBUG.fits");
590 
591  // update the valid parameters
592  unsigned int i;
593  for(i=0;i<sz;i++)
594  if( fill.IsValid(i) )
595  {
596  pars_(i) += B(i);
597  }
598  else
599  {
600  // should return false here ?????
601  cout << "Cannot update pars(" << i << ")=" << pars_(i)
602  << " <-> " << B(i)
603  << endl;
604  }
605 
606  return true;
607 }
608 
609 
610 template<class Model>
611 bool PhotFitter<Model>::Minimize(unsigned int maxiter)
612 {
613  bool status;
614  double oldchi2;
615  double chi2 = 99.E99;
616 
617  unsigned int i=0;
618  while( 1 )
619  {
620  NewtonRaphsonStep();
621  oldchi2 = chi2;
622  chi2 = GetChi2();
623 
624  if(verbose_)
625  {
626  cout << "[PhotFitter<Model>::Minimize()] STEP #" << i
627  << " CHI2=" << chi2;
628  }
629 
630  if(oldchi2 < chi2)
631  {
632  // we should do something clever here.
633  // backtrack ?
634  cout << endl
635  << "[PhotFitter<>::Mininize()] ERROR increasing chi2 "
636  << oldchi2 << " --> " << chi2 << endl;
637  status = false;
638  break;
639  }
640 
641  if( (oldchi2-chi2) < minstep_ )
642  {
643  if(verbose_)
644  {
645  cout << " ... CONVERGED." << endl;
646  }
647  status = true;
648  break;
649  }
650 
651  if(i>=maxiter)
652  {
653  cout << endl
654  << "[PhotFitter<>::Minimize()] ERROR, maxiter="
655  << maxiter << " reached wo convergence." << endl;
656  status = false;
657  break;
658  }
659 
660  cout << endl;
661  i++;
662  }
663 
664  status = ComputeCovMat();
665  status = ComputeCorrMat();
666 
667  if(status) updateFittedStars_();
668 
669  return status;
670 }
671 
672 
673 template<class Model>
674 bool PhotFitter<Model>::ComputeCovMat()
675 {
676  epars_.allocate(model_.NPar());
677  covmat_.allocate(model_.NPar(), model_.NPar());
678 
679  // we use epars temporarily
680  MatrixFill<Model> fill(pars_, covmat_, epars_, model_, -1);
681  LoopOnMeasurements(fill);
682 
683  int status = cholesky_solve(covmat_, epars_, "U");
684  if(status!=0)
685  {
686  cout << "[PhotFitter<Model>::ComputeCovMat] cholesky_solve ERROR, status="
687  << status << endl;
688  covmat_.Zero();
689  epars_.Zero();
690  return false;
691  }
692  status = cholesky_invert(covmat_, "U");
693  if(status!=0)
694  {
695  cout << "PB !";
696  covmat_.Zero();
697  epars_.Zero();
698  return false;
699 
700  }
701 
702  unsigned int i;
703  for(i=0;i<npar_;i++)
704  epars_(i) = sqrt(covmat_(i,i));
705 
706  return true;
707 }
708 
709 
710 template<class Model>
711 bool PhotFitter<Model>::ComputeCorrMat()
712 {
713  bool status = true;
714 
715  // this is a pretty lame test.
716  // add an internal state record
717  if( covmat_.SizeX() != model_.NPar() ||
718  covmat_.SizeY() != model_.NPar() )
719  status = ComputeCovMat();
720 
721  if(!status) return status;
722 
723  unsigned int i;
724  unsigned int j;
725  corrmat_.allocate(model_.NPar(), model_.NPar());
726 
727  for(i=0;i<model_.NPar();i++)
728  {
729  double cii = sqrt(covmat_(i,i));
730  for(j=i;j<model_.NPar();j++)
731  {
732  double cjj = sqrt(covmat_(j,j));
733  corrmat_(i,j) = covmat_(i,j) / (cii*cjj);
734  }
735  }
736 
737  return status;
738 }
739 
740 
741 
742 template<class Model>
743 class OutlierRemover
744 {
745 public:
746  OutlierRemover(Model const& model, Vect const& pars,
747  double cut)
748  : cut_(cut), nkilled_(0), model_(model), pars_(pars)
749  {
750  deriv_.allocate(model_.NPar());
751  }
752 
753  ~OutlierRemover() { }
754 
755  void operator()(MeasuredStar& m)
756  {
757  double val;
758  bool status = model_.Compute(m, pars_, val, deriv_);
759  if(!status)
760  {
761  m.SetValid(false);
762  nkilled_++;
763  }
764 
765  double flux = m.flux;
766  double eflux = m.FluxSig();
767  assert(eflux>0);
768 
769  double resid = sq( (flux-val) / eflux );
770  if(resid > cut_)
771  {
772  m.SetValid(false);
773  nkilled_++;
774  }
775  }
776 
777  void Finalize() { }
778 
779  unsigned int NKilled() const { return nkilled_; }
780 
781 private:
782  double cut_;
783  unsigned int nkilled_;
784  Model const& model_;
785  Vect const& pars_;
786  Vect deriv_;
787 };
788 
789 
790 
791 template<class Model>
792 int PhotFitter<Model>::RemoveOutliers(double nsig)
793 {
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;
799  assert(cut>0.);
800 
801  cout << " med=" << med
802  << " sig=" << sig
803  << " cut=" << cut << endl;
804 
805  cout << "[PhotFitter<>::RemoveOutliers()] BEFORE OUTLIER REMOVAL: " << GetChi2() << endl;
806  OutlierRemover<Model> rem(model_, pars_, cut);
807  LoopOnMeasurements(rem);
808 
809  cleanChi2_ = false;
810  cout << "[PhotFitter<>::RemoveOutliers()] " << rem.NKilled() << " measurements removed" << endl;
811  cout << "[PhotFitter<>::RemoveOutliers()] AFTER OUTLIER REMOVAL: " << GetChi2() << endl;
812 
813  return rem.NKilled();
814 }
815 
816 
817 
818 template<class Model>
819 unsigned int PhotFitter<Model>::GetNFittedPars() const
820 {
821  unsigned int ret = 0;
822  unsigned int i;
823  for(i=0;i<model_.NPar();i++)
824  // if( !isinf(pars_(i)) )
825  if( pars_(i)>=0 )
826  ret++;
827 
828  return ret;
829 }
830 
831 template<class Model>
832 double PhotFitter<Model>::GetChi2() const
833 {
834  if(cleanChi2_) return chi2_;
835  Chi2Acc<Model> acc(model_, pars_);
836  LoopOnMeasurements(acc);
837  chi2_ = acc.Chi2();
838  nmes_ = acc.NMes();
839  ndof_ = acc.NMes() - model_.NPar();
840  cleanChi2_ = true;
841  return chi2_;
842 }
843 
844 
845 template<class Model>
846 int PhotFitter<Model>::GetNMes() const
847 {
848  if(cleanChi2_) return nmes_;
849  GetChi2();
850  return nmes_;
851 }
852 
853 template<class Model>
854 int PhotFitter<Model>::GetNDoF() const
855 {
856  if(cleanChi2_) return ndof_;
857  GetChi2();
858  return ndof_;
859 }
860 
861 
862 template<class Model>
863 Vect const& PhotFitter<Model>::GetPar() const
864 {
865  return pars_;
866 }
867 
868 
869 template<class Model>
870 Vect const& PhotFitter<Model>::GetParError() const
871 {
872  return epars_;
873 }
874 
875 
876 template<class Model>
877 Mat const& PhotFitter<Model>::GetCovMatrix() const
878 {
879  return covmat_;
880 }
881 
882 template<class Model>
883 Mat const& PhotFitter<Model>::GetCorrMatrix() const
884 {
885  return corrmat_;
886 }
887 
888 
889 template<class Model>
890 void PhotFitter<Model>::updateFittedStars_()
891 {
892  FittedStarIterator I;
893  for(I=fittedstarstd::list_.begin();I!=fittedstarstd::list_.end();I++)
894  {
895  FittedStar* fs = (*I);
896  if(!fs) continue;
897  model_.UpdateFittedStar(*fs, pars_, epars_);
898  }
899 }
900 
901 
902 template<class Model>
903 void PhotFitter<Model>::dumpParNTuple_(std::string const& ntname) const
904 {
905  unsigned int i;
906  ofstream ofs(ntname.c_str());
907  ofs << "# num : " << endl
908  << "# val : " << endl
909  << "# err : " << endl
910  << "# end" << endl;
911 
912  for(i=0;i<model_.NPar();i++)
913  {
914  ofs << i << " "
915  << pars_(i) << " "
916  << epars_(i) << endl;
917  }
918  ofs.close();
919 }
920 
921 
922 
923 // CHECK: WHAT ABOUT THE BAND ????
924 template<class Model>
925 void PhotFitter<Model>::dumpFittedStarNTuple_(const std::string& ntname) const
926 {
927  ofstream ofs(ntname.c_str());
928  ofs << "# index : " << endl
929  << "# ra : " << endl
930  << "# dec : " << endl
931  << "# flux : " << endl
932  << "# eflux : " << endl
933  << "# nmeas : " << endl
934  << "# ref : " << endl
935  << "#end" << endl;
936 
937  FittedStarCIterator I;
938  for(I=fittedstarstd::list_.begin();I!=fittedstarstd::list_.end();I++)
939  {
940  const FittedStar* fs = (*I);
941  if(!fs) continue;
942  const RefStar* rs = fs->GetRefStar();
943  ofs << fs->Index() << " "
944  << fs->X() << " "
945  << fs->Y() << " "
946  << fs->Flux() << " "
947  << fs->FluxErr() << " "
948  << fs->MeasurementCount() << " "
949  << (rs!=0) << " "
950  << endl;
951  }
952 
953  ofs.close();
954 }
955 
956 
957 
958 
959 class MeasurementDumper
960 {
961 public:
962  MeasurementDumper(ofstream& ofs, FittedStarMap const& fsm,
963  unsigned int nusrvals=0)
964  : ofs_(ofs), fsm_(fsm), nusrvals_(nusrvals)
965  {
966  writeHeader_(ofs_);
967  }
968 
969  ~MeasurementDumper() { }
970 
974  void operator()(MeasuredStar const& ms)
975  {
976  CcdImage const& ccdim = ms.GetCcdImage();
977  FittedStar const* fs = ms.GetFittedStar();
978  double fluxfit = -1;
979  double efluxfit = -1;
980  double xdeg = -1;
981  double ydeg = -1;
982  int nmeas = -1;
983  int nccds = -1;
984  if(fs)
985  {
986  fluxfit = fs->Flux();
987  efluxfit = fs->FluxErr();
988  xdeg = fs->x;
989  ydeg = fs->y; // CHECK THIS -- no ra,dec, but CTP coords.
990  nmeas = fs->MeasurementCount();
991  nccds = fsm_.NCcds(fs);
992  }
993 
994  ofs_ << ms.x << " "
995  << ms.y << " "
996  << ms.flux << " "
997  << ms.eflux << " "
998  << fluxfit << " "
999  << efluxfit << " "
1000  << xdeg << " "
1001  << ydeg << " "
1002  << ccdim.Shoot() - 700000 << " "
1003  << ccdim.Chip() << " "
1004  << ccdim.BandIndex() << " "
1005  << ccdim.AirMass() << " "
1006  << nmeas << " "
1007  << nccds << " ";
1008 
1009  // now, possibly the Monte-Carlo Fluxes ...
1010  BaseStarWithError const* mcstar = ms.GetMCMeas();
1011  if(mcstar)
1012  ofs_ << mcstar->Flux() << " "
1013  << mcstar->EFlux() << " ";
1014  else
1015  ofs_ << 0.0 << " "
1016  << 0.0 << " ";
1017 
1018  BaseStarWithError const* mcstar_truth = ms.GetMCTruth();
1019  if(mcstar_truth)
1020  ofs_ << mcstar_truth->Flux();
1021  else
1022  ofs_ << 0.0 << " ";
1023 
1024  // and now, the usrVals
1025  assert(nusrvals_ <= ms.usrVals.size());
1026  unsigned int i;
1027  for(i=0;i<nusrvals_;i++)
1028  ofs_ << ms.usrVals[i] << " ";
1029 
1030  ofs_ << endl;
1031 
1032  // cout << " ++++ >>>> "
1033  // << ms.GetMCTruth() << " "
1034  // << ms.GetMCMeas()
1035  // << endl;
1036  }
1037 
1038  void Finalize() {}
1039 
1040 private:
1041  ofstream& ofs_;
1042  FittedStarMap const& fsm_;
1043  unsigned int nusrvals_;
1044 
1048  void writeHeader_(ofstream& ofs)
1049  {
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;
1067  unsigned int i;
1068  for(i=0;i<nusrvals_;i++)
1069  ofs << "# usr" << i << " : " << endl;
1070  ofs << "# end" << endl;
1071  }
1072 };
1073 
1074 
1075 
1076 template<class Model>
1077 void PhotFitter<Model>::dumpMeasuredStarNTuple_(const std::string& ntname,
1078  unsigned int nusrvals) const
1079 {
1080  ofstream ofs(ntname.c_str());
1081  FittedStarMap fsm(imstd::list_);
1082  MeasurementDumper dump(ofs, fsm, nusrvals);
1083  LoopOnMeasurements(dump);
1084  ofs.close();
1085 }
1086 
1087 
1088 
1089 template<class Model>
1090 void PhotFitter<Model>::DumpNTuples(const std::string& dirname) const
1091 {
1092  if(verbose_)
1093  {
1094  cout << "[PhotFitter<>::DumpNTuple(" << dirname << ")]" << endl;
1095  }
1096 
1097  if( !FileExists(dirname) )
1098  if( !MKDir(dirname.c_str()) )
1099  {
1100  cout << "[PhotFitter<>::DumpNTuple()] ERROR "
1101  << " unable to create dir=" << dirname
1102  << endl;
1103  return;
1104  }
1105 
1106  // the fit parameters
1107  std::string parntname = dirname + "/fitpars.ntuple";
1108  dumpParNTuple_(parntname);
1109 
1111  std::string fstarntname = dirname + "/fstars.std::list";
1112  dumpFittedStarNTuple_(fstarntname);
1113 
1115  std::string mstarntname = dirname + "/mstars.std::list";
1116  dumpMeasuredStarNTuple_(mstarntname);
1117 
1118  return;
1119 }
1120 
1121 #endif
1122 
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