//----------------------------------------------------------------------- // // Convoluted Landau and Gaussian Fitting Function // (using ROOT's Landau and Gauss functions) // // Based on a Fortran code by R.Fruehwirth (fruhwirth@hephy.oeaw.ac.at) // Adapted for C++/ROOT by H.Pernegger (Heinz.Pernegger@cern.ch) and // Markus Friedl (Markus.Friedl@cern.ch) // // to execute this example, do: // root > .x langaus.C // or // root > .x langaus.C++ // //----------------------------------------------------------------------- #include "../../Tools/Lib.C" #include "../../Tools/lhcbStyle.C" #include "../../Tools/Style.C" #include "../../Tools/FindAndReplaceString.C" Double_t langaufun(Double_t *x, Double_t *par) { //Fit parameters: //par[0]=Width (scale) parameter of Landau density //par[1]=Most Probable (MP, location) parameter of Landau density //par[2]=Total area (integral -inf to inf, normalization constant) //par[3]=Width (sigma) of convoluted Gaussian function // //In the Landau distribution (represented by the CERNLIB approximation), //the maximum is located at x=-0.22278298 with the location parameter=0. //This shift is corrected within this function, so that the actual //maximum is identical to the MP parameter. // Numeric constants Double_t invsq2pi = 0.3989422804014; // (2 pi)^(-1/2) Double_t mpshift = -0.22278298; // Landau maximum location // Control constants Double_t np = 100.0; // number of convolution steps Double_t sc = 5.0; // convolution extends to +-sc Gaussian sigmas // Variables Double_t xx; Double_t mpc; Double_t fland; Double_t sum = 0.0; Double_t xlow,xupp; Double_t step; Double_t i; // MP shift correction mpc = par[1] - mpshift * par[0]; // Range of convolution integral xlow = x[0] - sc * par[3]; xupp = x[0] + sc * par[3]; step = (xupp-xlow) / np; // Convolution integral of Landau and Gaussian by sum for(i=1.0; i<=np/2; i++) { xx = xlow + (i-.5) * step; fland = TMath::Landau(xx,mpc,par[0]) / par[0]; sum += fland * TMath::Gaus(x[0],xx,par[3]); xx = xupp - (i-.5) * step; fland = TMath::Landau(xx,mpc,par[0]) / par[0]; sum += fland * TMath::Gaus(x[0],xx,par[3]); } return (par[2] * step * sum * invsq2pi / par[3]); } TF1 *langaufit(TH1F *his, Double_t *fitrange, Double_t *startvalues, Double_t *parlimitslo, Double_t *parlimitshi, Double_t *fitparams, Double_t *fiterrors, Double_t *ChiSqr, Int_t *NDF) { // Once again, here are the Landau * Gaussian parameters: // par[0]=Width (scale) parameter of Landau density // par[1]=Most Probable (MP, location) parameter of Landau density // par[2]=Total area (integral -inf to inf, normalization constant) // par[3]=Width (sigma) of convoluted Gaussian function // // Variables for langaufit call: // his histogram to fit // fitrange[2] lo and hi boundaries of fit range // startvalues[4] reasonable start values for the fit // parlimitslo[4] lower parameter limits // parlimitshi[4] upper parameter limits // fitparams[4] returns the final fit parameters // fiterrors[4] returns the final fit errors // ChiSqr returns the chi square // NDF returns ndf Int_t i; Char_t FunName[100]; sprintf(FunName,"Fitfcn_%s",his->GetName()); TF1 *ffitold = (TF1*)gROOT->GetListOfFunctions()->FindObject(FunName); if (ffitold) delete ffitold; TF1 *ffit = new TF1(FunName,langaufun,fitrange[0],fitrange[1],4); ffit->SetParameters(startvalues); ffit->SetParNames("Width","MP","Area","GSigma"); for (i=0; i<4; i++) { ffit->SetParLimits(i, parlimitslo[i], parlimitshi[i]); } his->Fit(FunName,"RB0"); // fit within specified range, use ParLimits, do not plot ffit->GetParameters(fitparams); // obtain fit parameters for (i=0; i<4; i++) { fiterrors[i] = ffit->GetParError(i); // obtain fit parameter errors } ChiSqr[0] = ffit->GetChisquare(); // obtain chi^2 NDF[0] = ffit->GetNDF(); // obtain ndf return (ffit); // return fit function } Int_t langaupro(Double_t *params, Double_t &maxx, Double_t &FWHM) { // Seaches for the location (x value) at the maximum of the // Landau-Gaussian convolute and its full width at half-maximum. // // The search is probably not very efficient, but it's a first try. Double_t p,x,fy,fxr,fxl; Double_t step; Double_t l,lold; Int_t i = 0; Int_t MAXCALLS = 10000; // Search for maximum p = params[1] - 0.1 * params[0]; step = 0.05 * params[0]; lold = -2.0; l = -1.0; while ( (l != lold) && (i < MAXCALLS) ) { i++; lold = l; x = p + step; l = langaufun(&x,params); if (l < lold) step = -step/10; p += step; } if (i == MAXCALLS) return (-1); maxx = x; fy = l/2; // Search for right x location of fy p = maxx + params[0]; step = params[0]; lold = -2.0; l = -1e300; i = 0; while ( (l != lold) && (i < MAXCALLS) ) { i++; lold = l; x = p + step; l = TMath::Abs(langaufun(&x,params) - fy); if (l > lold) step = -step/10; p += step; } if (i == MAXCALLS) return (-2); fxr = x; // Search for left x location of fy p = maxx - 0.5 * params[0]; step = -params[0]; lold = -2.0; l = -1e300; i = 0; while ( (l != lold) && (i < MAXCALLS) ) { i++; lold = l; x = p + step; l = TMath::Abs(langaufun(&x,params) - fy); if (l > lold) step = -step/10; p += step; } if (i == MAXCALLS) return (-3); fxl = x; FWHM = fxr - fxl; return (0); } int N = 512; // string filename = "~flionett/work/LHCb/UTTestBeam/Repository/KeplerDev_v3r0/output/Run_Bias_Scan-B6-A-299-8431_Tuple.root"; // string filename = "~flionett/work/LHCb/UTTestBeam/Repository/KeplerDev_v3r0/output/Plots/AnalysisOutput_A6_300_1_8431.root"; // int channel = -1; void TbUTLandauFits(string filename, int channel); int main(int argc, char *argv[]) { getLHCbStyle(); PersonalStyle(); if ((argc ==2) && (string(argv[1]) == "--info")) { cout << "**************************************************" << endl; cout << "Put comments here." << endl; cout << "**************************************************" << endl; return 0; } else if (argc < 3) { cout << "**************************************************" << endl; cout << "Error! Arguments missing..." << endl; cout << "Please use the following format:" << endl; cout << "./TbUTLandauFits [1] [2]" << endl; cout << "with:" << endl; cout << "[1] = filename (full path);" << endl; cout << "[2] = channel." << endl; cout << "Type ./TbUTLandauFits --info for more information." << endl; cout << "**************************************************" << endl; return 0; } else if (argc == 3) { cout << "**************************************************" << endl; cout << "Filename: " << argv[1] << endl; cout << "Channel: " << argv[2] << endl; cout << "**************************************************" << endl; TbUTLandauFits(string(argv[1]),atoi(argv[2])); return 0; } else { cout << "**************************************************" << endl; cout << "Error! Too many arguments provided..." << endl; cout << "**************************************************" << endl; return 0; } } // The <filename> variable is the filename with the complete path. void TbUTLandauFits(string filename, int channel) { TString inFilename = filename.substr(0,filename.find(".root")); // No file extension. cout << inFilename << endl; TString outFilename = filename.substr(0,filename.find(".root"))+"_LandauFits"; // No file extension. cout << outFilename << endl; TString pathToInput = filename.substr(0,filename.find_last_of("/")); cout << pathToInput << endl; TString pathToOutput = filename.substr(0,filename.find_last_of("/"))+"/LandauFits"; cout << pathToOutput << endl; TString pathToFigures = filename.substr(0,filename.find_last_of("/"))+"/LandauFits/Figures"; // Create output folders if they do not exist. TString pathToOutputMake = "mkdir -p "+pathToOutput; cout << "Create folder " << pathToOutput << " where output will be saved" << endl; system(string(pathToOutputMake).c_str()); TString path_to_make_figures = "mkdir -p "+pathToFigures; system(string(path_to_make_figures).c_str()); cout << "Setting figures to: " << path_to_make_figures << endl; TFile *fIn = new TFile(inFilename+".root","READ"); TFile *fOut = new TFile(outFilename+".root","RECREATE"); TH1F *hS = 0; TH1F *hS1ch[N]; if (channel == -1) { TList *list = new TList; for (int i=0; i<N; ++i) { // Convert the integer to string. stringstream s; s << i; string ch(s.str()); hS1ch[i] = (TH1F *)fIn->Get("hlandau_"+TString(ch)); InitHist(hS1ch[i],Form("Signal distribution on channel %d",i),"ADC counts",""); list->Add(hS1ch[i]); } hS=(TH1F *)hS1ch[0]->Clone("hlandau_0"); InitHist(hS,"Signal distribution","ADC counts",""); hS->Reset(); hS->Merge(list); /* TTree *t = (TTree *)fIn->Get("TbUT/Clusters"); vector<double> clustersCharge(10); t->SetBranchAddress("clustersCharge",&(&clustersCharge[10])); if (fIn->GetListOfKeys()->Contains("TbUT/Clusters/clustersCharge")) { hS = (TH1F *)fIn->Get("TbUT/Clusters/clustersCharge"); } else { cout << "ERROR! No input object found." << endl; return ; } */ } else { // Convert the integer to string. stringstream s; s << channel; string ch(s.str()); hS = (TH1F *)fIn->Get("hlandau_"+TString(ch)); InitHist(hS,"Signal distribution","ADC counts",""); if (hS->GetEntries() == 0) { cout << "ERROR! The selected histogram is empty." << endl; return; } } // Fitting S histo printf("Fitting...\n"); // Setting fit range and start values Double_t fr[2]; Double_t sv[4], pllo[4], plhi[4], fp[4], fpe[4]; fr[0]=0.4*hS->GetMean(); fr[1]=3.0*hS->GetMean(); pllo[0]=0.; pllo[1]=100.0; pllo[2]=1.; pllo[3]=0.01; plhi[0]=50.; plhi[1]=350.0; plhi[2]=100000000.; plhi[3]=50.; sv[0]=30.; sv[1]=250.; sv[2]=500.; sv[3]=3.; Double_t chisqr; Int_t ndf; TF1 *fitsnr = langaufit(hS,fr,sv,pllo,plhi,fp,fpe,&chisqr,&ndf); Double_t SPeak, SFWHM; langaupro(fp,SPeak,SFWHM); printf("Fitting done\nPlotting results...\n"); // Global style settings gStyle->SetOptStat(1111); gStyle->SetOptFit(111); gStyle->SetLabelSize(0.03,"x"); gStyle->SetLabelSize(0.03,"y"); // hS->GetXaxis()->SetRange(0,70); // hS->Draw(); // fitsnr->Draw("lsame"); TCanvas *cS = new TCanvas("cS","",800,600); cS->cd(); fitsnr->SetLineColor(kRed); DrawHistFunc(cS,hS,fitsnr,pathToFigures); fOut->cd(); hS->Write(); fIn->Close(); fOut->Close(); return; }