00001 #define ALCAP_NO_DEBUG
00002 #include "TemplateMultiFitter.h"
00003 #include "MultiHistogramFitFCN.h"
00004 #include "SetupNavigator.h"
00005 #include "EventNavigator.h"
00006 #include "debug_tools.h"
00007 #include <iostream>
00008
00009 #include "TMath.h"
00010
00011 using std::cout;
00012 using std::endl;
00013
00014 TemplateMultiFitter::TemplateMultiFitter(const IDs::channel& ch):
00015 fMinuitFitter(NULL), fFitFCN(NULL), fChannel(ch),fPedestal(0), fRefineFactor(0) {
00016
00017
00018 fMinADC = 0;
00019 fMaxADC = EventNavigator::Instance().GetSetupRecord().GetMaxADC(fChannel);
00020 }
00021
00022 void TemplateMultiFitter::Init(){
00023 if(fFitFCN || fMinuitFitter) {
00024 cout<< "TemplateMultiFitter: Warning: trying to initialize fitter which was already initialised!"<<endl;
00025 return;
00026 }
00027
00028 fFitFCN=new MultiHistogramFitFCN(fRefineFactor);
00029 fFitFCN->SetRefineFactor(fRefineFactor);
00030 for(TemplateList::iterator i_tpl=fTemplates.begin(); i_tpl!=fTemplates.end(); ++i_tpl){
00031 fFitFCN->AddTemplate(i_tpl->fTemplate->GetHisto());
00032 }
00033
00034 int num_params=fTemplates.size()+1;
00035 fMinuitFitter = new TFitterMinuit(num_params);
00036 fMinuitFitter->SetMinuitFCN(fFitFCN);
00037 fMinuitFitter->SetPrintLevel(-1);
00038 }
00039
00040 TemplateMultiFitter::~TemplateMultiFitter() {
00041 }
00042
00043 int TemplateMultiFitter::FitWithOneTimeFree(int index, const TH1D* hPulse){
00044
00045
00046 TemplateDetails_t& current=fTemplates.at(index);
00047
00048
00049 fMinuitFitter->Clear();
00050 fFitFCN->SetPulseHist(hPulse);
00051 fMinuitFitter->CreateMinimizer(TFitterMinuit::kMigrad);
00052
00053
00054 const double offset_range = 10*fRefineFactor;
00055 double best_time_offset = 0;
00056 std::vector<double> best_parameters(1+fTemplates.size());
00057 double best_chi2 = 1e34;
00058 int best_ndof = 0;
00059 int best_status = kInitialised;
00060 int status = kInitialised;
00061
00062
00063 int min_offset = current.fTimeOffset - offset_range;
00064 int max_offset = current.fTimeOffset + offset_range;
00065
00066 std::vector<double> parameters(1+fTemplates.size());
00067 for (double time_offset = min_offset; time_offset <= max_offset; ++time_offset) {
00068 fFitFCN->SetTimeOffset(index, time_offset);
00069
00070
00071 fMinuitFitter->SetParameter(0, "PedestalOffset", fPedestal, 0.1, fPedestal-10, fPedestal+10);
00072 for(TemplateList::const_iterator i_tpl=fTemplates.begin(); i_tpl!=fTemplates.end(); ++i_tpl){
00073 int i=i_tpl-fTemplates.begin();
00074 fMinuitFitter->SetParameter(i+1, Form("AmplitudeScaleFactor_%d",i), i_tpl->fAmplitudeScaleFactor, 0.1, fMinADC, fMaxADC);
00075 }
00076
00077
00078 status = fMinuitFitter->Minimize(1000);
00079 DEBUG_VALUE(status);
00080 if(status!=0) continue;
00081
00082
00083 parameters[0]=fMinuitFitter->GetParameter(0);
00084 for(std::vector<double>::iterator i_par=parameters.begin()+1; i_par!=parameters.end(); ++i_par){
00085 int n=i_par-parameters.begin();
00086 *i_par= fMinuitFitter->GetParameter(n);
00087 }
00088
00089
00090 const double delta_ped_offset_error = 1;
00091 const double delta_amp_sf_error = 0.001;
00092 if ( (parameters[0] < delta_ped_offset_error ) || (parameters[0] > fMaxADC - delta_ped_offset_error) ) {
00093 status = kPedestalOutOfBounds;
00094 } else {
00095 for(std::vector<double>::const_iterator i_par=parameters.begin()+1; i_par!=parameters.end(); ++i_par){
00096 if ( ( *i_par < fMinADC + delta_amp_sf_error ) || ( *i_par > fMaxADC - delta_amp_sf_error ) ) {
00097 DEBUG_VALUE(*i_par, delta_amp_sf_error, fMinADC, fMaxADC);
00098 status = kAmplitudeOutOfBounds;
00099 break;
00100 }
00101 }
00102 }
00103
00104
00105 fChi2 = (*fFitFCN)(parameters);
00106 fNDoF = fFitFCN->GetNDoF();
00107 DEBUG_VALUE(status,parameters[0],fChi2,fNDoF);
00108
00109 if (status == 0 && fChi2 < best_chi2) {
00110 best_time_offset = time_offset;
00111 best_parameters=parameters;
00112 best_chi2 = fChi2;
00113 best_status = status;
00114 best_ndof = fNDoF;
00115 }
00116 }
00117
00118
00119 fChi2 = best_chi2;
00120 fNDoF = best_ndof;
00121 current.fTimeOffset = best_time_offset;
00122 fPedestal = best_parameters[0];
00123 for(TemplateList::iterator i_tpl=fTemplates.begin(); i_tpl!=fTemplates.end(); ++i_tpl){
00124 i_tpl->fAmplitudeScaleFactor=best_parameters[i_tpl-fTemplates.begin()+1];
00125 }
00126
00127 static int offset_safety = 1;
00128 if ( (current.fTimeOffset < min_offset + offset_safety && current.fTimeOffset > min_offset - offset_safety) ||
00129 (current.fTimeOffset < max_offset + offset_safety && current.fTimeOffset > max_offset - offset_safety) ) {
00130
00131 best_status = kTimeOutOfBounds;
00132 }
00133
00134 return best_status;
00135 }
00136
00137 int TemplateMultiFitter::FitWithAllTimesFixed( const TH1D* hPulse){
00138
00139 fMinuitFitter->Clear();
00140 fFitFCN->SetPulseHist(hPulse);
00141 fMinuitFitter->CreateMinimizer(TFitterMinuit::kMigrad);
00142
00143
00144 fMinuitFitter->SetParameter(0, "PedestalOffset", fPedestal, 0.1, fMinADC, fMaxADC);
00145 for(TemplateList::const_iterator i_tpl=fTemplates.begin(); i_tpl!=fTemplates.end(); ++i_tpl){
00146 int i=i_tpl-fTemplates.begin();
00147 fMinuitFitter->SetParameter(i+1, Form("AmplitudeScaleFactor_%d",i), i_tpl->fAmplitudeScaleFactor, 0.1, fMinADC, fMaxADC);
00148 fFitFCN->SetTimeOffset(i, i_tpl->fTimeOffset);
00149 }
00150
00151
00152 int status = fMinuitFitter->Minimize(1000);
00153
00154
00155 std::vector<double> parameters(1+fTemplates.size());
00156 parameters[0]=fPedestal=fMinuitFitter->GetParameter(0);
00157 for(TemplateList::iterator i_tpl=fTemplates.begin(); i_tpl!=fTemplates.end(); ++i_tpl)
00158 parameters[i_tpl-fTemplates.begin()+1]=i_tpl->fAmplitudeScaleFactor= fMinuitFitter->GetParameter(i_tpl-fTemplates.begin()+1);
00159
00160
00161 fChi2 = (*fFitFCN)(parameters);
00162 fNDoF = fFitFCN->GetNDoF();
00163
00164
00165 return status;
00166
00167 }
00168
00169 void TemplateMultiFitter::AddTemplate(TTemplate* tpl){
00170 TemplateDetails_t tmp;
00171 tmp.fTemplate=tpl;
00172 fTemplates.push_back(tmp);
00173 if(fRefineFactor==0) fRefineFactor=tpl->GetRefineFactor();
00174 else if(fRefineFactor!= tpl->GetRefineFactor()){
00175 throw Except::MismatchedTemplateRefineFactors();
00176 }
00177 }