00001 #ifndef MultiHistogramFitFCN_h__
00002 #define MultiHistogramFitFCN_h__
00003
00004 #include "Minuit2/FCNBase.h"
00005 #include "TH1D.h"
00006 #include "AlcapExcept.h"
00007
00008 #include "debug_tools.h"
00009 #include <iostream>
00010
00011 #include <vector>
00012
00013 MAKE_EXCEPTION(MultiHistogramFitFCN, Base);
00014 MAKE_EXCEPTION(SlimlyOverlappingTemplates,MultiHistogramFitFCN);
00015
00016 class MultiHistogramFitFCN : public ROOT::Minuit2::FCNBase {
00017 struct HistogramDetails_t {
00018 double fTimeOffset, fAmplitudeScale;
00019 const TH1D* fTemplateHist;
00020 int fNDoF;
00021 double GetHeight(double t)const;
00022 double GetError2(double t)const;
00023 };
00024 typedef std::vector<HistogramDetails_t> TemplateList;
00025
00026 public:
00027 MultiHistogramFitFCN(double refine_factor=1);
00028 ~MultiHistogramFitFCN();
00029
00030 void AddTemplate(const TH1D* hist, double time=0){
00031 HistogramDetails_t tmp;
00032 tmp.fTemplateHist=hist;
00033 tmp.fTimeOffset=time;
00034 tmp.fNDoF=0;
00035 fTemplates.push_back(tmp);
00036 }
00037 void SetTemplateHist( int n , const TH1D* hist){
00038 fTemplates.at(n).fTemplateHist=hist;
00039 }
00040 void SetTimeOffset(int n, double offset){
00041 fTemplates.at(n).fTimeOffset=offset;
00042 }
00043 void SetTime(int n, double time){
00044 fTemplates.at(n).fTimeOffset=time - fTemplates[n].fTemplateHist->GetMaximumBin();
00045 }
00046 void SetAmplitude(int n, double amp){
00047 fTemplates.at(n).fAmplitudeScale=amp/fTemplates[n].fTemplateHist->GetMaximum();
00048 }
00049 void SetInitialValues(int n, double time_offset, double amp){
00050 SetTime(n, time_offset);
00051 SetAmplitude(n, amp);
00052 }
00053
00054 void SetPulseHist(const TH1D* pulse){fPulseHist=pulse;}
00055 void SetRefineFactor(int refine_factor) {fRefineFactor = refine_factor;}
00056
00057 double& GetAmplitudeScaleFactor(int i)const{return fTemplates.at(i).fAmplitudeScale;}
00058 double& GetTimeOffset(int i)const{return fTemplates.at(i).fTimeOffset;}
00059 int GetNTemplates()const{return fTemplates.size();}
00060
00071 double operator() (const std::vector<double>& par) const;
00072
00074 double Up() const {return 1.;}
00075
00076 int GetNDoF() { return fNDoF; }
00077
00078 private:
00079 inline void UnpackParameters(const std::vector<double>& par)const;
00080 inline void GetHistogramBounds(int safety, int &low_edge, int& high_edge)const;
00081
00084 mutable int fNDoF;
00085 mutable double fChi2;
00086 mutable double fPedestal;
00087
00088 int fRefineFactor;
00089
00090 mutable TemplateList fTemplates;
00091
00092 const TH1D* fPulseHist;
00093
00094 };
00095
00096 inline void MultiHistogramFitFCN::GetHistogramBounds(int safety, int &low_edge, int& high_edge)const{
00097
00098 low_edge=safety;
00099 high_edge=fPulseHist->GetNbinsX()-safety;
00100
00101
00102 int tpl_start, tpl_stop;
00103 for(TemplateList::const_iterator i_tpl=fTemplates.begin(); i_tpl!=fTemplates.end(); ++i_tpl){
00104 tpl_start=i_tpl->fTimeOffset + safety;
00105 tpl_stop=i_tpl->fTimeOffset+i_tpl->fTemplateHist->GetNbinsX() - safety;
00106
00107
00108 if(high_edge>tpl_stop) high_edge=tpl_stop;
00109
00110
00111 if(low_edge>tpl_start) low_edge=tpl_start;
00112 }
00113 }
00114
00115 inline void MultiHistogramFitFCN::UnpackParameters(const std::vector<double>& par)const{
00116 if ( par.size() < fTemplates.size()+1) return;
00117 const std::vector<double>::const_iterator begin=par.begin();
00118 std::vector<double>::const_iterator i_par=begin;
00119 fPedestal=*i_par;
00120 for(++i_par ; i_par!=par.end(); ++i_par){
00121 int n= (i_par-begin-1) ;
00122 fTemplates.at(n).fAmplitudeScale=*i_par;
00123 }
00124 }
00125
00126 #endif