data analysis scripts
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

345 lines
11 KiB

  1. /// \ingroup tutorial_fit
  2. /// \notebook
  3. /// Convoluted Landau and Gaussian Fitting Function
  4. /// (using ROOT's Landau and Gauss functions)
  5. ///
  6. /// Based on a Fortran code by R.Fruehwirth (fruhwirth@hephy.oeaw.ac.at)
  7. ///
  8. /// to execute this example, do:
  9. ///
  10. /// ~~~{.cpp}
  11. /// root > .x langaus.C
  12. /// ~~~
  13. ///
  14. /// or
  15. ///
  16. /// ~~~{.cpp}
  17. /// root > .x langaus.C++
  18. /// ~~~
  19. ///
  20. /// \macro_image
  21. /// \macro_output
  22. /// \macro_code
  23. ///
  24. /// \authors H.Pernegger, Markus Friedl
  25. #include "TH1.h"
  26. #include "TF1.h"
  27. #include "TROOT.h"
  28. #include "TStyle.h"
  29. #include "TMath.h"
  30. Double_t langaufun(Double_t *x, Double_t *par) {
  31. //Fit parameters:
  32. //par[0]=Width (scale) parameter of Landau density
  33. //par[1]=Most Probable (MP, location) parameter of Landau density
  34. //par[2]=Total area (integral -inf to inf, normalization constant)
  35. //par[3]=Width (sigma) of convoluted Gaussian function
  36. //
  37. //In the Landau distribution (represented by the CERNLIB approximation),
  38. //the maximum is located at x=-0.22278298 with the location parameter=0.
  39. //This shift is corrected within this function, so that the actual
  40. //maximum is identical to the MP parameter.
  41. // Numeric constants
  42. Double_t invsq2pi = 0.3989422804014; // (2 pi)^(-1/2)
  43. Double_t mpshift = -0.22278298; // Landau maximum location
  44. // Control constants
  45. Double_t np = 100.0; // number of convolution steps
  46. Double_t sc = 5.0; // convolution extends to +-sc Gaussian sigmas
  47. // Variables
  48. Double_t xx;
  49. Double_t mpc;
  50. Double_t fland;
  51. Double_t sum = 0.0;
  52. Double_t xlow,xupp;
  53. Double_t step;
  54. Double_t i;
  55. // MP shift correction
  56. mpc = par[1] - mpshift * par[0];
  57. // Range of convolution integral
  58. xlow = x[0] - sc * par[3];
  59. xupp = x[0] + sc * par[3];
  60. step = (xupp-xlow) / np;
  61. // Convolution integral of Landau and Gaussian by sum
  62. for(i=1.0; i<=np/2; i++) {
  63. xx = xlow + (i-.5) * step;
  64. fland = TMath::Landau(xx,mpc,par[0]) / par[0];
  65. sum += fland * TMath::Gaus(x[0],xx,par[3]);
  66. xx = xupp - (i-.5) * step;
  67. fland = TMath::Landau(xx,mpc,par[0]) / par[0];
  68. sum += fland * TMath::Gaus(x[0],xx,par[3]);
  69. }
  70. return (par[2] * step * sum * invsq2pi / par[3]);
  71. }
  72. TF1 *langaufit(TH1D *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)
  73. {
  74. // Once again, here are the Landau * Gaussian parameters:
  75. // par[0]=Width (scale) parameter of Landau density
  76. // par[1]=Most Probable (MP, location) parameter of Landau density
  77. // par[2]=Total area (integral -inf to inf, normalization constant)
  78. // par[3]=Width (sigma) of convoluted Gaussian function
  79. //
  80. // Variables for langaufit call:
  81. // his histogram to fit
  82. // fitrange[2] lo and hi boundaries of fit range
  83. // startvalues[4] reasonable start values for the fit
  84. // parlimitslo[4] lower parameter limits
  85. // parlimitshi[4] upper parameter limits
  86. // fitparams[4] returns the final fit parameters
  87. // fiterrors[4] returns the final fit errors
  88. // ChiSqr returns the chi square
  89. // NDF returns ndf
  90. Int_t i;
  91. Char_t FunName[100];
  92. sprintf(FunName,"Fitfcn_%s",his->GetName());
  93. TF1 *ffitold = (TF1*)gROOT->GetListOfFunctions()->FindObject(FunName);
  94. if (ffitold) delete ffitold;
  95. TF1 *ffit = new TF1(FunName,langaufun,fitrange[0],fitrange[1],4);
  96. ffit->SetParameters(startvalues);
  97. ffit->SetParNames("Width","MP","Area","GSigma");
  98. for (i=0; i<4; i++) {
  99. ffit->SetParLimits(i, parlimitslo[i], parlimitshi[i]);
  100. }
  101. his->Fit(FunName,"RB0"); // fit within specified range, use ParLimits, do not plot
  102. ffit->GetParameters(fitparams); // obtain fit parameters
  103. for (i=0; i<4; i++) {
  104. fiterrors[i] = ffit->GetParError(i); // obtain fit parameter errors
  105. }
  106. ChiSqr[0] = ffit->GetChisquare(); // obtain chi^2
  107. NDF[0] = ffit->GetNDF(); // obtain ndf
  108. return (ffit); // return fit function
  109. }
  110. Int_t langaupro(Double_t *params, Double_t &maxx, Double_t &FWHM) {
  111. // Seaches for the location (x value) at the maximum of the
  112. // Landau-Gaussian convolute and its full width at half-maximum.
  113. //
  114. // The search is probably not very efficient, but it's a first try.
  115. Double_t p,x,fy,fxr,fxl;
  116. Double_t step;
  117. Double_t l,lold;
  118. Int_t i = 0;
  119. Int_t MAXCALLS = 10000;
  120. // Search for maximum
  121. p = params[1] - 0.1 * params[0];
  122. step = 0.05 * params[0];
  123. lold = -2.0;
  124. l = -1.0;
  125. while ( (l != lold) && (i < MAXCALLS) ) {
  126. i++;
  127. lold = l;
  128. x = p + step;
  129. l = langaufun(&x,params);
  130. if (l < lold)
  131. step = -step/10;
  132. p += step;
  133. }
  134. if (i == MAXCALLS)
  135. return (-1);
  136. maxx = x;
  137. fy = l/2;
  138. // Search for right x location of fy
  139. p = maxx + params[0];
  140. step = params[0];
  141. lold = -2.0;
  142. l = -1e300;
  143. i = 0;
  144. while ( (l != lold) && (i < MAXCALLS) ) {
  145. i++;
  146. lold = l;
  147. x = p + step;
  148. l = TMath::Abs(langaufun(&x,params) - fy);
  149. if (l > lold)
  150. step = -step/10;
  151. p += step;
  152. }
  153. if (i == MAXCALLS)
  154. return (-2);
  155. fxr = x;
  156. // Search for left x location of fy
  157. p = maxx - 0.5 * params[0];
  158. step = -params[0];
  159. lold = -2.0;
  160. l = -1e300;
  161. i = 0;
  162. while ( (l != lold) && (i < MAXCALLS) ) {
  163. i++;
  164. lold = l;
  165. x = p + step;
  166. l = TMath::Abs(langaufun(&x,params) - fy);
  167. if (l > lold)
  168. step = -step/10;
  169. p += step;
  170. }
  171. if (i == MAXCALLS)
  172. return (-3);
  173. fxl = x;
  174. FWHM = fxr - fxl;
  175. return (0);
  176. }
  177. void langaus(string rootfilename, int ionsort) {
  178. // Fill Histogram
  179. /* Int_t data[100] = {10,20,50,3,10,5,2,6,11,18,18,55,90,141,255,323,454,563,681,
  180. 737,821,796,832,720,637,558,519,460,357,291,279,241,212,
  181. 153,164,139,106,95,91,76,80,80,59,58,51,30,49,23,35,28,23,
  182. 22,27,27,24,20,16,17,14,20,12,12,13,10,17,7,6,12,6,12,4,
  183. 9,9,10,3,4,5,2,4,1,5,5,1,7,1,6,3,3,3,4,5,4,4,2,2,7,2,4};
  184. TH1F *hSNR = new TH1F("snr","Signal-to-noise",400,0,400);
  185. */
  186. // for (Int_t i=0; i<100; i++) hSNR->Fill(i,data[i]);
  187. TFile *rootFile = new TFile(rootfilename.c_str(),"OPEN");
  188. TFile *outFile = new TFile("langausout.root","RECREATE");
  189. TH1D * hSNR;
  190. TH1D* h_beamSignal_b0[30];
  191. TH1D* h_beamSignal_b1[30];
  192. TH1D* h_beamSignal_b2[30];
  193. TH1D* h_beamSignal_b3[30];
  194. int energy_indexbin = 0;
  195. char histname[30] = "";
  196. TH1D* h_beamSignal_ic1[30];
  197. Double_t graph_x[30], graph_y[30], graph_xerr[30], graph_yerr[30];
  198. TGraphErrors * graph_1;
  199. Double_t beta_proton[30] = {0.308525262, 0.340993523, 0.366173485, 0.386743776, 0.404197708, 0.4194131, 0.43294541, 0.445179695, 0.456345494, 0.466616582, 0.476154213, 0.48502264, 0.493348242, 0.501186212, 0.50863865, 0.515744144, 0.522562549, 0.52911069, 0.535379917, 0.541397728, 0.549575745, 0.557428612, 0.564849395, 0.571867977, 0.578541117, 0.584900169};
  200. Double_t beta_helium[30] = {0.316661966, 0.34727202, 0.371222186, 0.391037227, 0.408018455, 0.422922098, 0.436235455, 0.44827542, 0.459299095, 0.469441244, 0.478845524, 0.487649369, 0.495886825, 0.503656244, 0.510990953, 0.517959457, 0.52457247, 0.530888884, 0.536925849, 0.54269899, 0.550671248, 0.55845178, 0.565814653, 0.572798702, 0.579448698, 0.585785313};
  201. Double_t beta_carbon[30] = {0.407931067, 0.448122448, 0.479020432, 0.504000457, 0.524971648, 0.543076553, 0.559041917, 0.573329576, 0.586254563, 0.598061846, 0.608917559, 0.618952311, 0.62829287, 0.637039726, 0.645286945, 0.65311609, 0.660570813, 0.667689852, 0.67446932, 0.680943928, 0.689677353, 0.698000799, 0.70580765, 0.71315081, 0.720086739, 0.726650602};
  202. Double_t beta_oxygen[30] = {0.43638582, 0.479000679, 0.51134888, 0.537325331, 0.559061572, 0.57764689, 0.594123989, 0.608730698, 0.621997639, 0.63402408, 0.645050809, 0.655226738, 0.664724227, 0.673475951, 0.681810969, 0.689681788, 0.697243281, 0.704219104, 0.710968918, 0.717442538, 0.726111033, 0.734356548, 0.742073831, 0.749383281, 0.756156282, 0.762562424};
  203. for (int i = 0;i<23;i++){
  204. if (ionsort ==3 ) graph_x[i] = beta_proton[i];
  205. if (ionsort ==1 ) graph_x[i] = beta_helium[i];
  206. if (ionsort ==4 ) graph_x[i] = beta_carbon[i];
  207. if (ionsort ==2 ) graph_x[i] = beta_oxygen[i];
  208. sprintf(histname,"h_beamSignal_b0_%d",i);
  209. h_beamSignal_b0[i] = (TH1D*)rootFile->Get(histname);
  210. sprintf(histname,"h_beamSignal_b1_%d",i);
  211. h_beamSignal_b1[i] = (TH1D*)rootFile->Get(histname);
  212. sprintf(histname,"h_beamSignal_b2_%d",i);
  213. h_beamSignal_b2[i] = (TH1D*)rootFile->Get(histname);
  214. sprintf(histname,"h_beamSignal_b3_%d",i);
  215. h_beamSignal_b3[i] = (TH1D*)rootFile->Get(histname);
  216. sprintf(histname,"h_beamSignal_ic1_%d",i);
  217. h_beamSignal_ic1[i] = (TH1D*)rootFile->Get(histname);
  218. }
  219. // hSNR = h_beamSignal_b0[13];
  220. // Fitting SNR histo
  221. printf("Fitting...\n");
  222. // Setting fit range and start values
  223. Double_t fr[2];
  224. Double_t sv[4], pllo[4], plhi[4], fp[4], fpe[4];
  225. Double_t chisqr;
  226. Int_t ndf;
  227. TF1 *fitsnr[24];
  228. Double_t SNRPeak, SNRFWHM;
  229. TCanvas * c1 = new TCanvas("c1","c1", 800, 600);
  230. Double_t norm = 1;
  231. for (int i = 0; i<23;i++){
  232. //hSNR = h_beamSignal_b0[i];
  233. h_beamSignal_ic1[i]->Scale(norm/h_beamSignal_ic1[i]->Integral("width"));
  234. hSNR = h_beamSignal_ic1[i];
  235. fr[0]=hSNR->GetMean() - 3*hSNR->GetRMS();
  236. fr[1]=hSNR->GetMean() + 3*hSNR->GetRMS();
  237. pllo[0]=0.0075; pllo[1]=1.0; pllo[2]=0.01; pllo[3]=0.07;
  238. plhi[0]=1.0E3; plhi[1]=300.0; plhi[2]=2E2; plhi[3]=0.65;
  239. sv[0]=20.2;
  240. //sv[1]=2.1;
  241. sv[2]=1.0;
  242. sv[3]=hSNR->GetRMS();
  243. sv[1] = hSNR->GetMean();
  244. fitsnr[i] = langaufit(hSNR,fr,sv,pllo,plhi,fp,fpe,&chisqr,&ndf);
  245. langaupro(fp,SNRPeak,SNRFWHM);
  246. graph_y[i] = fp[1];
  247. graph_yerr[i] = sqrt(fitsnr[i]->GetParError(1)*fitsnr[i]->GetParError(1)+0.012*0.012*graph_y[i]*graph_y[i]);
  248. printf("Fitting done\nPlotting results...\n");
  249. // Global style settings
  250. gStyle->SetOptStat(1111);
  251. gStyle->SetOptFit(111);
  252. //gStyle->SetLabelSize(0.03,"x");
  253. //gStyle->SetLabelSize(0.03,"y");
  254. // hSNR->GetXaxis()->SetRange(0,70);
  255. // hSNR->Draw();
  256. // fitsnr[i]->Draw("lsame");
  257. // c1->Update();
  258. // c1->WaitPrimitive();
  259. }
  260. graph_1 = new TGraphErrors(23,graph_x, graph_y, 0, graph_yerr);
  261. TCanvas * c2 = new TCanvas("c2","c2", 800, 600);
  262. c2->cd();
  263. graph_1->Draw("A*");
  264. outFile->Write();
  265. outFile->Close();
  266. }