00001 #include "FitOverROI.hh"
00002
00003 #include "TMath.h"
00004 #include "TROOT.h"
00005 #include "TFitResult.h"
00006 #include "TSpectrum.h"
00007 #include "TTree.h"
00008 #include "TFile.h"
00009 #include "TF1.h"
00010 #include "TCanvas.h"
00011 #include "TPad.h"
00012 #include "TLine.h"
00013 #include "TAxis.h"
00014
00015 #include "TList.h"
00016 #include "TCut.h"
00017 #include <algorithm>
00018 #include <numeric>
00019 #include <string>
00020 #include <iomanip>
00021 #include <iostream>
00022 #include <sstream>
00023 #include "TMatrixDSym.h"
00024 #include "TGraph.h"
00025 #include <fstream>
00026
00027
00028 using namespace std;
00029
00030 #define HISTOGRAMWIDTH 7
00031 #define NPEAKS 7
00032
00033
00034
00035 #define mCON params[CONSTANT]
00036 #define mLAM params[LAMBDA]
00037 #define mMEAN params[MEAN]
00038 #define mSIG params[SIGMA]
00039 #define mAMP params[AMP_E]
00040 #define mPE params[P_E]
00041 #define mSHT params[SHOTNOISE]
00042 #define mPDM params[PEDMEAN]
00043
00044
00045 const char* names[] = {"CONSTANT","LAMBDA", "SPE_MEAN", "SPE_SIGMA", "AMP_E", "P_E", "SHOTNOISE" ,"PEDMEAN","NPAR"};
00046
00047
00048 Double_t FitOverROI::response_0(Double_t* x, Double_t* params)
00049 {
00050 double y = x[0] - mPDM;
00051 return mCON*TMath::Poisson(0,mLAM)*TMath::Gaus(y, 0, mSHT, true);
00052 }
00053
00054 Double_t FitOverROI::background_func(Double_t* x, Double_t* params)
00055 {
00056 double y = x[0] - mPDM;
00057
00058
00059 double exp_term=(TMath::Power(TMath::E(),(-2*mAMP*y + mSHT*mSHT)/
00060 (2.*mAMP*mAMP))*mPE*
00061 (1 + TMath::Erf(((mAMP*y)/mSHT - mSHT)/(sqrt(2)*mAMP))))/
00062 (2.*mAMP);
00063 return mCON*TMath::Poisson(1,mLAM)*exp_term;
00064 }
00065
00066 Double_t FitOverROI::gauss_func(Double_t* x, Double_t* params)
00067 {
00068 double y = x[0] - mPDM;
00069 double sigma_1=sqrt(mSHT*mSHT + mSIG*mSIG);
00070
00071 double gauss_term= (1-mPE)*(TMath::Power(TMath::E(), - (mMEAN-y)*(mMEAN-y)/(2*sigma_1*sigma_1)) *
00072 (1 + TMath::Erf((mMEAN*mSHT*mSHT + mSIG*mSIG*y)/(sqrt(2) * mSIG*mSHT *sigma_1))) /
00073 (sqrt(2*TMath::Pi())*sigma_1 * (1+ TMath::Erf(mMEAN/(sqrt(2)*mSIG)))));
00074
00075
00076 double response=mCON*TMath::Poisson(1,mLAM)*gauss_term;
00077 return response;
00078 }
00079
00080 Double_t FitOverROI::response_1(Double_t* x, Double_t* params)
00081 {
00082 double exp_term= background_func(x, params);
00083
00084 double gauss_term= gauss_func(x, params);
00085
00086
00087 double response=gauss_term+exp_term;
00088 return response;
00089 }
00090
00091
00092 Double_t FitOverROI::response_2(Double_t* x, Double_t* params)
00093 {
00094 double y = x[0] - mPDM;
00095 double response=((TMath::Power(TMath::E(),(-2*mAMP*y + TMath::Power(mSHT,2))/
00096 (2.*TMath::Power(mAMP,2)))*mPE*mPE*
00097 (mAMP*y - TMath::Power(mSHT,2)))/TMath::Power(mAMP,3) +
00098 (2*TMath::Power(-1 + mPE,2)*sqrt(2/TMath::Pi()))/
00099 (TMath::Power(TMath::E(),TMath::Power(-2*mMEAN + y,2)/
00100 (2.*(TMath::Power(mSHT,2) +
00101 2*TMath::Power(mSIG,2))))*mSHT*
00102 sqrt(2/TMath::Power(mSHT,2) + TMath::Power(mSIG,-2))*
00103 mSIG*TMath::Power(1 + TMath::Erf(mMEAN/(sqrt(2)*mSIG)),2))
00104 + (2*TMath::Power(TMath::E(),
00105 (2*mAMP*mMEAN - 2*mAMP*y + TMath::Power(mSHT,2) +
00106 TMath::Power(mSIG,2))/(2.*TMath::Power(mAMP,2)))*
00107 (-1 + mPE)*mPE*
00108 (-1 + TMath::Erf((mAMP*(mMEAN - y) +
00109 TMath::Power(mSHT,2) + TMath::Power(mSIG,2))/
00110 (mAMP*sqrt(2*TMath::Power(mSHT,2) +
00111 2*TMath::Power(mSIG,2))))))
00112 /(mAMP*(1 + TMath::Erf(mMEAN/(sqrt(2)*mSIG)))));
00113
00114 return TMath::Poisson(2,mLAM)*mCON*response;
00115
00116
00117
00118
00119
00120
00121
00122 }
00123
00124 Double_t FitOverROI::m_n(const Double_t* params)
00125 {
00126 return mMEAN + mAMP*mPE - mMEAN*mPE +
00127 (sqrt(2/TMath::Pi())*mSIG*
00128 (1/(1 + TMath::Erf(mMEAN/(sqrt(2)*mSIG))) +
00129 mPE/(-2 + TMath::Erfc(mMEAN/(sqrt(2)*mSIG)))))/
00130 TMath::Power(TMath::E(),TMath::Power(mMEAN,2)/(2.*TMath::Power(mSIG,2)));
00131 }
00132
00133 Double_t FitOverROI::sigma_n(const Double_t* params)
00134 {
00135 return sqrt(-(TMath::Power(mMEAN,2)*(-1 + mPE)) +
00136 2*TMath::Power(mAMP,2)*mPE -
00137 (-1 + mPE)*TMath::Power(mSIG,2) -
00138 TMath::Power(mMEAN + mAMP*mPE - mMEAN*mPE +
00139 (sqrt(2/TMath::Pi())*mSIG*
00140 (1/(1 + TMath::Erf(mMEAN/(sqrt(2)*mSIG))) +
00141 mPE/(-2 + TMath::Erfc(mMEAN/(sqrt(2)*mSIG)))
00142 ))/
00143 TMath::Power(TMath::E(),TMath::Power(mMEAN,2)/
00144 (2.*TMath::Power(mSIG,2))),2) +
00145 (mMEAN*sqrt(2/TMath::Pi())*mSIG*
00146 (1/(1 + TMath::Erf(mMEAN/(sqrt(2)*mSIG))) +
00147 mPE/(-2 + TMath::Erfc(mMEAN/(sqrt(2)*mSIG)))))
00148 /TMath::Power(TMath::E(),TMath::Power(mMEAN,2)/
00149 (2.*TMath::Power(mSIG,2))));
00150 }
00151
00152 Double_t FitOverROI::response_multi(Double_t* x, Double_t* params)
00153 {
00154 double y = x[0] - mPDM;
00155
00156
00157 double response=0;
00158
00159 for(int i=3; i<=NPEAKS; i++)
00160 {
00161 response += TMath::Poisson(i,mLAM) *TMath::Gaus(y,m_n(params)*i,sqrt(i*sigma_n(params)*sigma_n(params)+TMath::Power(mSHT,2)),true);
00162 }
00163 return mCON*response;
00164 }
00165
00166 Double_t FitOverROI::SPEFunc(Double_t* x, Double_t* params)
00167 {
00168 double sig = (response_0(x, params)+response_1(x,params)+response_2(x,params)+response_multi(x,params));
00169
00170
00171
00172 return sig;
00173
00174 }
00175
00176 TFitResultPtr FitOverROI::FitSPE(FitTH1F* spe, ChanFitSettings& CFS, int ntriggers,
00177 bool allow_bg,
00178 bool force_old)
00179 {
00180
00181 TF1* spefunc = (TF1*)gROOT->GetFunction("spefunc");
00182 int nEvtsInRange = (int)spe->Integral(0,spe->GetNbinsX()+1,"width");
00183
00184 spe->GetXaxis()->SetRangeUser(CFS.range_min, CFS.range_max);
00185
00186 double fitmin, fitmax;
00187 fitmin = spe->GetBinLowEdge(spe->GetXaxis()->GetFirst());
00188 fitmax = 0;
00189
00190 int bin = spe->GetXaxis()->GetLast();
00191
00192
00193 while(spe->GetBinContent(bin) == 0) {bin--;}
00194 fitmax = spe->GetBinLowEdge(bin);
00195 fitmax = fitmax*1;
00196
00197
00198
00199 Double_t pedmean = CFS.pedmean_min_bound;
00200 if(fitmin<0 && !force_old && (max(fitmin,CFS.pedrange_min)< min(CFS.pedrange_max,fitmax)))
00201 {
00202 spe->GetXaxis()->SetRangeUser(max(fitmin,CFS.pedrange_min), min(CFS.pedrange_max,fitmax));
00203 std::cout<<"Fitting pedestal in range ["<<max(fitmin,CFS.pedrange_min)<<", "<<min(fitmax,CFS.pedrange_max)<<"]"<<std::endl;
00204 TFitResultPtr pedfit = spe->Fit("gaus","QMIS");
00205 if(pedfit.Get())
00206 {
00207 pedmean = pedfit->Value(1);
00208 }
00209 else{pedmean=0;}
00210 }
00211 if(force_old)
00212 {
00213 pedmean=spefunc->GetParameter(PEDMEAN);
00214 }
00215
00216 double params[NPAR];
00217
00218 bin = spe->FindBin(0);
00219
00220
00221
00222 if(!force_old || !spefunc)
00223 {
00224 params[SHOTNOISE] = CFS.shotnoise_start_value;
00225 params[MEAN] = CFS.mean_start_value;
00226 params[SIGMA] = CFS.sigma_start_value;
00227 params[LAMBDA] = CFS.lambda_start_value;
00228 if(CFS.constant_start_value)
00229 {
00230 params[CONSTANT] = nEvtsInRange;
00231 }
00232 else
00233 {
00234 params[CONSTANT] = CFS.constant_start_value;
00235 }
00236 params[AMP_E] = CFS.amp_E_start_value;
00237 params[P_E] = CFS.p_E_start_value;
00238
00239 spefunc = new TF1("spefunc", SPEFunc, fitmin, fitmax, NPAR);
00240
00241 spefunc->SetParameters(params);
00242 for(int i=0; i<NPAR; i++)
00243 spefunc->SetParName(i, names[i]);
00244
00245
00246 spefunc->SetParLimits(LAMBDA, CFS.lambda_min_bound, CFS.lambda_max_bound);
00247 spefunc->SetParLimits(MEAN, CFS.mean_min_bound, CFS.mean_max_bound);
00248 spefunc->SetParLimits(SHOTNOISE, CFS.shotnoise_min_bound, CFS.shotnoise_max_bound);
00249 spefunc->SetParLimits(SIGMA, CFS.sigma_min_bound, CFS.sigma_max_bound);
00250 spefunc->SetParLimits(P_E, CFS.p_E_min_bound, CFS.p_E_max_bound);
00251 spefunc->SetParLimits(AMP_E, CFS.amp_E_min_bound, CFS.amp_E_max_bound);
00252 if(!allow_bg)
00253 {
00254 cout<<"Disallowing exponential background for this fit"<<endl;
00255 spefunc->SetParameter(AMP_E,0);
00256 spefunc->SetParameter(P_E,0);
00257 spefunc->FixParameter(AMP_E,0);
00258 spefunc->FixParameter(P_E,0);
00259 }
00260
00261
00262 spefunc->SetLineStyle(1);
00263 spefunc->SetLineColor(kBlue);
00264 }
00265 else
00266 {
00267 for(int i=0; i<NPAR; i++)
00268 {
00269 if(i == CONSTANT || i == LAMBDA)
00270 continue;
00271 double width=0;
00272 spefunc->SetParLimits(i,
00273 std::max(0. ,spefunc->GetParameter(i)-width*spefunc->GetParError(i)),
00274 spefunc->GetParameter(i) + width*spefunc->GetParError(i));
00275 }
00276 }
00277 spefunc->FixParameter(CONSTANT, nEvtsInRange);
00278 spefunc->FixParameter(PEDMEAN, pedmean);
00279
00280 spe->GetXaxis()->SetRangeUser(fitmin, fitmax);
00281
00282 spe->Draw();
00283 spefunc->Draw("same");
00284
00285
00286
00287 std::cout<<std::endl<<"Fitting entire spectrum"<<std::endl;
00288 TFitResultPtr fitResult = spe->Fit(spefunc,"QMRES");
00289 spe->fitResult= fitResult;
00290
00291
00292 std::cout<<endl<<"Fit Results: "<<endl
00293 <<"Fit Status: "<<spe->fitResult<<endl
00294 <<"Chi2/NDF = "<<spefunc->GetChisquare()<<"/"<<spefunc->GetNDF()<<endl
00295 <<"Prob = "<<spefunc->GetProb()<<std::endl<<std::endl;
00296
00297 for(int i=0; i<NPAR; i++){ params[i] = spefunc->GetParameter(i);}
00298 TList* funclist = spe->GetListOfFunctions();
00299
00300 static TF1* background = new TF1("background",background_func,fitmin,fitmax,NPAR);
00301 background->SetRange(fitmin, fitmax);
00302 background->SetLineColor(kRed);
00303 background->SetParameters(spefunc->GetParameters());
00304 funclist->Add(background->Clone());
00305
00306 static TF1* gauss_curve = new TF1("gause_curve",gauss_func,fitmin,fitmax,NPAR);
00307 gauss_curve->SetRange(fitmin, fitmax);
00308 gauss_curve->SetLineColor(kRed);
00309 gauss_curve->SetParameters(spefunc->GetParameters());
00310 funclist->Add(gauss_curve->Clone());
00311
00312
00313 TF1* response_0_f = (TF1*)gROOT->GetFunction("response_0_f");
00314 if(!response_0_f){response_0_f = new TF1("response_0_f",response_0,fitmin,fitmax,NPAR);}
00315 response_0_f->SetRange(fitmin, fitmax);
00316 response_0_f->SetLineColor(kGreen);
00317 response_0_f->SetParameters(spefunc->GetParameters());
00318 response_0_f->SetRange(fitmin,70);
00319 if(response_0_f){funclist->Add(response_0_f->Clone());}
00320
00321 TF1* response_1_f = (TF1*)gROOT->GetFunction("response_1_f");
00322 if(!response_1_f){response_1_f = new TF1("response_1_f",response_1,fitmin,fitmax,NPAR);}
00323 response_1_f->SetRange(fitmin, fitmax);
00324 response_1_f->SetLineColor(kMagenta);
00325 response_1_f->SetParameters(spefunc->GetParameters());
00326 if(response_1_f){funclist->Add(response_1_f->Clone());}
00327
00328 TF1* response_2_f = (TF1*)gROOT->GetFunction("response_2_f");
00329 if(!response_2_f){response_2_f = new TF1("response_2_f",response_2,fitmin,fitmax,NPAR);}
00330 response_2_f->SetRange(fitmin, fitmax);
00331 response_2_f->SetLineColor(kGreen);
00332 response_2_f->SetParameters(spefunc->GetParameters());
00333 if(response_2_f){funclist->Add(response_2_f->Clone());}
00334
00335 TF1* response_multi_f = (TF1*)gROOT->GetFunction("response_multi_f");
00336 if(!response_multi_f){response_multi_f = new TF1("response_multi_f",response_multi,fitmin,fitmax,NPAR);}
00337 response_multi_f->SetRange(fitmin, fitmax);
00338 response_multi_f->SetLineColor(kGreen);
00339 response_multi_f->SetParameters(spefunc->GetParameters());
00340 if(response_multi_f){funclist->Add(response_multi_f->Clone());}
00341
00342
00343
00344
00345
00346
00347
00348 cout<<"Valid Events collected: "<<ntriggers<<std::endl;
00349 cout<<"Events Passing Cuts: " <<spe->GetEntries()<<std::endl;
00350 cout<<"Noise fraction: "
00351 <<spefunc->GetParameter(AMP_E)/spefunc->GetParameter(CONSTANT)
00352 <<std::endl;
00353 cout<<"Exponential fraction: "<<spefunc->GetParameter(P_E)<<std::endl;
00354 cout<<"Average photoelectrons per pulse: "<<spefunc->GetParameter(LAMBDA)
00355 <<std::endl;
00356 cout<<"Pedestal Mean: "<<spefunc->GetParameter(PEDMEAN)<<" count*samples"<<endl;
00357 cout<<"Pedestal Width: "<<spefunc->GetParameter(SHOTNOISE)<<" count*samples"<<endl;
00358
00359
00360
00361
00362 double conversion = 0.00049 * 4E-9 * 1./25. *
00363 0.1 * 1.E12 ;
00364
00365 cout<<"Single photoelectron Peak: "<<m_n(params)<<" count*samples"<<std::endl
00366 <<"Single photoelectron Width: " <<sigma_n (params)<<" count*samples"<<std::endl
00367 <<"Single photoelectron Charge: "<<m_n(params)*conversion<<" pC"<<std::endl
00368 <<"Phototube Gain: "<<m_n(params)*conversion / 1.602E-7<<std::endl;
00369
00370
00371 double pdfmean_approx = mPE*mAMP+(1-mPE)*mMEAN;
00372
00373
00374
00375
00376
00377
00378
00379 cout<<"Approximated pdfmean (using corr): "<<pdfmean_approx
00380 <<" +- "<<pdfmean_error_corr(fitResult)<<endl;
00381 return fitResult;
00382 }
00383
00384 double FitOverROI::pdfmean_error_corr(TFitResultPtr& fitresult)
00385 {
00386 TMatrixDSym cov = fitresult->GetCovarianceMatrix();
00387 const double* params = fitresult->GetParams();
00388 const double* errors = fitresult->GetErrors();
00389
00390 double pdfmean_error_uncorr_sq = TMath::Power((mAMP-mMEAN)*errors[P_E],2)
00391 +TMath::Power((1-mPE)*errors[MEAN],2)
00392 +TMath::Power(mPE*errors[AMP_E],2);
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 return sqrt(pdfmean_error_uncorr_sq + (2*(mAMP-mMEAN)*(1-mPE)*cov[P_E][MEAN]
00403 + 2*(mAMP-mMEAN)*mPE*cov[P_E][AMP_E]
00404 + 2*(1-mPE)*mPE*cov[MEAN][AMP_E]));
00405
00406
00407
00408
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484