Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HistMacro_PID.C
Go to the documentation of this file.
1 // hnamepath: /highlevel/EventInfo
2 // hnamepath: /highlevel/TwoGammaMass
3 // hnamepath: /highlevel/PiPlusPiMinus
4 // hnamepath: /highlevel/KPlusKMinus
5 // hnamepath: /highlevel/PiPlusPiMinusPiZero
6 // hnamepath: /highlevel/L1bits_gtp
7 // hnamepath: /highlevel/PSPairEnergy
8 //
9 // e-mail: davidl@jlab.org
10 // e-mail: staylor@jlab.org
11 // e-mail: sdobbs@jlab.org
12 // e-mail: tbritton@jlab.org
13 //
14 
15 #include <time.h>
16 
17 
18 {
19 
20 // The following are empty versions of routines defined in RootSpy
21 // compiled executables. These are defined here for when this
22 // macro is run outside that context.
23 #ifndef ROOTSPY_MACROS
24 #define rs_SetFlag(A) cout<<"rs_SetFlag ignored outside of RootSpy context"<<endl
25 #define rs_GetFlag(A) 0
26 #define rs_ResetHisto(A) cout<<"rs_ResetHisto ignored outside of RootSpy context"<<endl
27 #define rs_RestoreHisto(A) cout<<"rs_RestoreHisto ignored outside of RootSpy context"<<endl
28 #define InsertSeriesData(A) cout<<"InsertSeriesData ignored outside of RootSpy context"<<endl
29 #define InsertSeriesMassFit(A,B,C,D,E,F) cout<<"InsertSeriesMassFit ignored outside of RootSpy context"<<endl
30 #endif
31 
32 
33 // This is a trick to get ROOT to use a function for a TF1 without
34 // defining it in global namespace. This is needed since ROOTSpy
35 // requires all macros to be nameless. The start of the actual
36 // macro starts after the class definition.
37 class FitWrapper{
38  public:
39 
40  // The following provided by Eugene C. (see e-mails to David L.
41  // on 3/1/2017 amd 3/2/2017).
42 
43  //....................................................
44  // mass_bg_1
45  //
46  // Function for the background in mass plots
47  // a*(x-m0)^b*exp(-c*x)
48  //....................................................
49  static Double_t mass_bg_1(Double_t *xptr, Double_t *p)
50  {
51  Double_t x=xptr[0];
52  Double_t bg=0;
53  if(x-p[1] >0.) bg=p[0]*pow((x-p[1]),p[2])*exp(-p[3]*x);
54  return bg;
55  }
56 
57  //....................................................
58  // peak_gs
59  //
60  // Gaussian - the first parameter is the integral
61  // p[0]/sqrt(2pi)/p[2]*exp(-pow((x[0]-p[2])/p[3],2)/2.)
62  //....................................................
63  static Double_t peak_gs(Double_t *xptr, Double_t *p)
64  {
65  Double_t x=xptr[0];
66  Double_t gs;
67  gs=0.;
68  if(abs(p[2])>1.E-20){
69  gs=p[0]/sqrt(2.0*3.1416)/p[2] * exp(-pow((x-p[1])/p[2],2)/2.0);
70  }
71  return gs;
72  }
73 
74  //....................................................
75  // fun_peak_bg_1
76  //
77  // Mass fit: peaks and background
78  //....................................................
79  static Double_t fun_peak_bg_1(Double_t *xptr, Double_t *p)
80  {
81  Double_t x=xptr[0];
82  Int_t n_peaks=Int_t(p[0]+0.1);
83 
84  Double_t fun = mass_bg_1(xptr,&p[1]);
85  for(int i=0;i<n_peaks;i++){
86  Int_t iflg=Int_t(p[5+4*i]+0.5); // <0 - reject the points close to the peak, =0 - ignore, =1 - Gauss
87  if(p[5+4*i]<0.) iflg=Int_t(p[5+4*i]-0.5);
88  if(iflg == 1){
89  fun+=peak_gs( xptr,&p[5+4*i+1]); // add a Gauss peak
90  } else if (iflg < 0){
91  // Reject the point if in a range of +/- 3*sigma
92  if(x>p[5+4*i+2]-p[5+4*i+3]*3. && x<p[5+4*i+2]+p[5+4*i+3]*3.){
93  TF1::RejectPoint();
94  return 0.;
95  }
96  }
97  }
98 
99  return fun;
100  }
101 
102 
103  //-----------------------------------
104  // FitPeaksWithBackgr
105  //-----------------------------------
106  static Double_t FitPeaksWithBackgr(
107  TH1* h1, // histogram pointer
108  Double_t mass_thresh = 0.139*2.+0.135, // mass threshold of the reaction
109  Double_t bg_pos = 1.2, // some point of pure background (+/- 5 bins)
110  TString type_peaks = "G", // types of the peaks: G -Gaussian, also limits the number of peaks
111  // There are places for 4 peaks, ="GGG" means that 3 Gaussian peak should be used
112  Double_t peak_pos_1 = 0.78, // 1-st peak position (mass)
113  Double_t peak_width_1 = 0.03, // 1-st peak width, =0 - peak ignored
114  Double_t peak_pos_2 = 0.0, // 2-nd peak position (mass)
115  Double_t peak_width_2 = 0.0, // 2-nd peak width, =0 - peak ignored
116  Double_t peak_pos_3 = 0.0, // 2-nd peak position (mass)
117  Double_t peak_width_3 = 0.0, // 2-nd peak width, =0 - peak ignored
118  Double_t peak_pos_4 = 0.0, // 2-nd peak position (mass)
119  Double_t peak_width_4 = 0.0, // 2-nd peak width, =0 - peak ignored
120  Double_t *pars_out = NULL, // fit pars (if not NULL)
121  Double_t *errs_out = NULL) // fit par errors (if not NULL)
122  {
123 
124  if(h1 == NULL){
125 // cout << "FitPeaksWithBackgr: No histogram name " <<hname << endl;
126  return 0;
127  }
128  TString hname = TString(h1->GetName());
129  Int_t nbins=h1->GetNbinsX();
130  if(nbins <= 0){
131  cout << "FitPeaksWithBackgr: Histogram name " <<hname << " N bins "<<nbins << endl;
132  return 0;
133  }
134  Double_t xmin = h1->GetXaxis()->GetXmin();
135  Double_t xmax = h1->GetXaxis()->GetXmax();
136  Double_t xbin = (xmax-xmin)/nbins;
137 
138  gPad->SetLeftMargin(0.12);
139  h1->GetYaxis()->SetTitleOffset(0.75);
140  h1->GetYaxis()->SetTitle(Form("Combinations / %5.1f MeV",xbin*1000.));
141  h1->Draw("");
142 
143  if(nbins<20){
144  cout << "FitPeaksWithBackgr: No fit - too few bins " << nbins << endl;
145  return 0;
146  }
147 
148  if(h1->GetEntries()<20){
149  cout << "FitPeaksWithBackgr: No fit - too few entries " << h1->GetEntries() << endl;
150  return 0;
151  }
152 
153  // Specify the peaks
154  Double_t set_peaks[10][2]; // [i_peak,i_par] = pos,width
155  Int_t cod_peaks[10]; // [i_peak] = a code for the peak, =1 - Gauss
156  set_peaks[0][0]=peak_pos_1;
157  set_peaks[0][1]=peak_width_1;
158  set_peaks[1][0]=peak_pos_2;
159  set_peaks[1][1]=peak_width_2;
160  set_peaks[2][0]=peak_pos_3;
161  set_peaks[2][1]=peak_width_3;
162  set_peaks[3][0]=peak_pos_4;
163  set_peaks[3][1]=peak_width_4;
164  Int_t n_peaks=0; // The number of peaks defined, limited by the length of the string type_peaks
165  for(int i=0; i<int(type_peaks.Length()) && i<4 ; i++){
166  // for(int i=0; i<1; i++){
167  if(set_peaks[i][1]>0.){
168  set_peaks[n_peaks][0]=set_peaks[i][0]; // compress holes if any
169  set_peaks[n_peaks][1]=set_peaks[i][1];
170  cod_peaks[n_peaks]=1; // Defult - Gauss
171  if(char(type_peaks(i))=='G' || char(type_peaks(i))=='g') cod_peaks[n_peaks]=1; // room for other function
172  n_peaks++;
173  }
174  }
175 
176  // cout << "n_peaks "<<n_peaks<<" "<<type_peaks.Length()<<endl;
177  // Range for fitting
178  // Double_t xminfit = mass_thresh>xmin ? mass_thresh:xmin;
179  Double_t xminfit = mass_thresh;
180  if(xminfit<xmin) xminfit=xmin;
181  Double_t xmaxfit = xmax;
182 
183  // Check the position of the specified background
184  if( bg_pos - 5.*xbin < xminfit || bg_pos + 5.*xbin > xmaxfit){
185  cout << "FitPeaksWithBackgr: No fit - the specified bg position "<< bg_pos <<
186  " is outside of the fit range, or too close to the edge "<<endl;
187  return 0;
188  }
189  for(int i=0;i<n_peaks;i++){
190  if( bg_pos + 5.*xbin > set_peaks[i][0]-3.*set_peaks[i][1] &&
191  bg_pos - 5.*xbin < set_peaks[i][0]+3.*set_peaks[i][1] ){
192  cout << "FitPeaksWithBackgr: No fit - the specified bg position "<< bg_pos <<
193  " is too close to peak "<< i <<endl;
194  return 0;
195  }
196  }
197 
198 
199  // Define fit function
200  Int_t n_par = 1+4+4*n_peaks; // number of parameters controlling the function
201  TString fun_name = hname + TString("_fun");
202  TF1 *ftf = (TF1 *)gROOT->FindObject(fun_name);
203  if(ftf!=NULL){
204  if(ftf->GetNpar() != n_par){
205  cout << " Function exists with wrong parameter number " << ftf->GetNpar() << endl;
206  ftf->Delete();
207  ftf=NULL;
208  }
209  }
210  if(ftf == NULL) ftf = new TF1(fun_name, fun_peak_bg_1, 0., 0., n_par);
211  ftf->SetRange(xminfit, xmaxfit);
212  ftf->SetParName( 0, "Function code ."); // n_peaks+10*BG_type
213  ftf->SetParName( 1, "Bkgnd Amp .");
214  ftf->SetParName( 2, "Bkgnd threshold");
215  ftf->SetParName( 3, "Bkgnd power .");
216  ftf->SetParName( 4, "Bkgnd exponent.");
217  for(int i=0;i<n_peaks;i++){
218  TString nam_p="Peak ";
219  if(char(type_peaks(i))=='G' || char(type_peaks(i))=='g') nam_p="Gauss ";
220  nam_p.Append(Form("%d",i+1));
221  ftf->SetParName( 5+i*4+0,nam_p+TString(" code ."));
222  ftf->SetParName( 5+i*4+1,nam_p+TString(" integr."));
223  ftf->SetParName( 5+i*4+2,nam_p+TString(" mean ."));
224  ftf->SetParName( 5+i*4+3,nam_p+TString(" width ."));
225  }
226 
227  // Set starting parameters. We initially fix the peak parameters
228  // so we can fit the background first.
229 
230  ftf->FixParameter(0, Double_t(n_peaks));
231  ftf->SetParameter(1, 1.0);
232  ftf->FixParameter(2, mass_thresh);
233  ftf->SetParameter(3, 2.0);
234  ftf->SetParameter(4, 4.0);
235 
236  for(int i=0;i<n_peaks;i++){ // Set the defined peaks
237  ftf->FixParameter(5+i*4+0,-2.); // at first fit the BG and reject the area around the peaks
238  ftf->FixParameter(5+i*4+1, 0.); // integral
239  ftf->FixParameter(5+i*4+2, set_peaks[i][0]); // position
240  ftf->FixParameter(5+i*4+3, set_peaks[i][1]); // width
241  }
242 
243  // Find the backround in 10 bins around the set point
244  Double_t x1=bg_pos-5.*xbin;
245  Double_t x2=bg_pos+5.*xbin;
246  Int_t ix1=h1->GetXaxis()->FindBin(x1);
247  Int_t ix2=h1->GetXaxis()->FindBin(x2);
248  Double_t bg=h1->Integral(ix1,ix2)/(ix2-ix1+1);
249  Double_t fun=ftf->Eval((x1+x2)/2.);
250  Double_t norm = 1.;
251  if(fun>0.) norm=bg/fun;
252  ftf->SetParameter(1, norm); // scale background function to match histo at the set point
253 
254  ftf->SetParLimits(3,0.3,4.);
255  ftf->SetParLimits(4,0.5,8.);
256 
257  Int_t fit_status = h1->Fit(ftf, "0Q", "", xminfit, xmaxfit); // Fit the BG, the peaks excluded
258  if(fit_status != 0 ){
259  cout << "FitPeaksWithBackgr: Fit of backgound failed, code "<< fit_status <<endl;
260  return 0;
261  }
262 
263  //Add the peaks one by one to the fit, starting with the LAST peak in the list
264  Int_t n_ok_fit=0; // number of peaks fitted successfully
265  for(int i=n_peaks-1;i>=0;i--){
266  // Find the size of the peak - integrate the peak and subtract the BG
267  x1=set_peaks[i][0]-set_peaks[i][1]*3.;
268  x2=set_peaks[i][0]+set_peaks[i][1]*3.;
269  ix1=h1->GetXaxis()->FindBin(x1);
270  ix2=h1->GetXaxis()->FindBin(x2);
271  Double_t peak_tot=h1->Integral(ix1,ix2); // peak total
272 
273  ftf->FixParameter(5+i*4,0.); // include the BG in the peak area, but ignore the peak
274  Double_t peak_bg=ftf->Integral(x1,x2)/xbin; // BG
275 
276  ftf->SetParameter(5+i*4+1,(peak_tot-peak_bg)*xbin);
277  // Release peak parameters
278  ftf->FixParameter(5+i*4,Double_t(cod_peaks[i])); // Gaussian peak
279  ftf->ReleaseParameter(5+i*4+1);
280  ftf->ReleaseParameter(5+i*4+2);
281  ftf->ReleaseParameter(5+i*4+3);
282  Double_t wd=ftf->GetParameter(5+i*4+3);
283  ftf->SetParLimits(5+i*4+3,wd*0.3,wd*3.);
284 
285  fit_status = h1->Fit(ftf, "0Q", "", xminfit, xmaxfit); // Fit the BG + peak
286  if(fit_status != 0 ){
287  cout << "FitPeaksWithBackgr: Fit of peak+backgound failed, code "<< fit_status <<endl;
288  return 0;
289  }
290  n_ok_fit++;
291 
292  }
293 
294  ftf->Draw("same");
295 
296  // Copy parameters into new function for plotting background
297  TString fun_name_bg = fun_name + TString("_bg");
298  TF1 *fbg = (TF1 *)gROOT->FindObject(fun_name_bg);
299  if(fbg!=NULL){
300  if(fbg->GetNpar() != n_par){
301  cout << "FitPeaksWithBackgr: Function exists with wrong parameter number " << fbg->GetNpar() << endl;
302  fbg->Delete();
303  fbg=NULL;
304  }
305  }
306  if(fbg == NULL) fbg = new TF1("fun_bg", fun_peak_bg_1, 0., 0., n_par); // For some reason Clone doesn't work right here!
307  fbg->SetParameters(ftf->GetParameters());
308  for(int i=0;i<n_peaks;i++){fbg->FixParameter(5+i*4,0.);} // Turn off the peaks
309  fbg->SetLineStyle(2);
310  fbg->SetRange(xminfit, xmaxfit);
311  fbg->Draw("same");
312  // canv1->Update();
313 
314  if(n_peaks != n_ok_fit){
315  cout << "FitPeaksWithBackgr: Fit of " << n_peaks << " failed: successes = " << n_ok_fit << endl;
316  return 0;
317  }
318 
319  // Double_t par_peaks[10][3]; // Peak parameters integr,pos,width
320  cout << " Peak Integral Center Width " << endl;
321  Double_t peak_integral=0.; // Integral of the 1-st peak
322  for(int i=0;i<n_peaks;i++){
323  Double_t par[3], epar[3];
324  for(int j=0;j<3;j++){
325  par[j]=ftf->GetParameter(5+i*4+1+j);
326  epar[j]=ftf->GetParError(5+i*4+1+j);
327  if(pars_out) pars_out[i*3 + j] = par[j];
328  if(errs_out) errs_out[i*3 + j] = epar[j];
329  }
330  printf(" %d %8.1f +/- %7.1f ",i+1,par[0]/xbin,epar[0]/xbin);
331  printf(" %8.4f +/- %7.4f ",par[1],epar[1]);
332  printf(" %8.4f +/- %7.4f ",par[2],epar[2]);
333  cout << endl;
334  if(i==0){
335  peak_integral=par[0]/xbin;
336  }
337  }
338 
339  // Draw line at nominal peak position
340  if(n_peaks>0){
341  Double_t ymax = 1.05*h1->GetMaximum();
342  Double_t ymin = 0.;
343  TLine lin;
344  lin.SetLineColor(kMagenta);
345  lin.SetLineWidth(1);
346  lin.DrawLine(set_peaks[0][0], ymin, set_peaks[0][0], ymax);
347 
348  char str[256];
349  sprintf(str, "%d MeV", (int)(1000*set_peaks[0][0]));
350 
351  TLatex latex;
352  latex.SetTextAngle(90.0);
353  latex.SetTextSize(0.030);
354  latex.SetTextAlign(21);
355  latex.SetTextColor(kMagenta);
356  latex.DrawLatex(set_peaks[0][0] - (xmax-xmin)*0.02, ymin*0.8+ymax*0.2, str);
357  }
358 
359  return peak_integral;
360  }
361 
362  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
363  // The following methods (gauss_bg1 and FitWithBackground) were used up until
364  // 3/3/2017 when they were replaced by the above. (See e-mails from Eugene C.
365  // to David L. on 3/1/2017 and 3/2/2017)
366 
367  //....................................................
368  // gauss_bg1
369  //
370  // Fit function that allows excluded range to be
371  // specified using last 2 parameters. Functional
372  // form provided by E. Chudakov.
373  //....................................................
374  static Double_t gauss_bg1(Double_t *xptr, Double_t *p)
375  {
376  Double_t x = xptr[0];
377  Double_t xexcl_min = p[7];
378  Double_t xexcl_max = p[8];
379  if( x>xexcl_min && x<xexcl_max ){
380  TF1::RejectPoint();
381  return 0;
382  }
383 
384  Double_t signal = p[0]*TMath::Gaus(x, p[1],p[2]);
385  Double_t bkgnd = p[3]*pow((x-p[4]),p[5])*exp(-x*p[6]);
386 
387  return signal + bkgnd;
388  }
389 
390  //-----------------------------------
391  // FitWithBackground
392  //-----------------------------------
393  static Double_t FitWithBackground(
394  TH1* h1,
395  Double_t peak_pos,
396  Double_t peak_width,
397  Double_t mass_thresh,
398  Double_t xmaxfit=0.0)
399  {
400 
401  // If too few events then just plot histogram and return
402  if(h1->GetEntries()<100){
403  h1->Draw();
404  return 0.0;
405  }
406 
407  // Make unique names for signal and background functions
408  // for each histogram fit so they can be displayed
409  // simultaneously.
410  char ftfname[256];
411  char fbgname[256];
412  sprintf(ftfname, "f%s_signal", h1->GetName());
413  sprintf(fbgname, "f%s_bkgrnd", h1->GetName());
414 
415  // Define fit function
416  TF1 *ftf = (TF1 *)gROOT->FindObject(ftfname);
417  if(!ftf){
418  ftf = new TF1(ftfname, gauss_bg1, 0.0, 0.0, 9);
419  ftf->SetParName(0, "Gauss Amp");
420  ftf->SetParName(1, "Gauss mean");
421  ftf->SetParName(2, "Gauss sigma");
422  ftf->SetParName(3, "Bkgnd Amp");
423  ftf->SetParName(4, "Bkgnd offset");
424  ftf->SetParName(5, "Bkgnd exponent");
425  ftf->SetParName(6, "Bkgnd expo-rate");
426  ftf->SetParName(7, "xmin excluded region");
427  ftf->SetParName(8, "xmax excluded region");
428  }
429 
430  // Threshold parameter is either mass thresh or histogram low edge
431  Double_t xmin = h1->GetXaxis()->GetXmin();
432 
433  // Set starting parameters. We initially fix the peak parameters
434  // so we can fit the background first.
435  ftf->FixParameter(0, 0.5*h1->GetBinContent(h1->FindBin(peak_pos)));
436  ftf->FixParameter(1, peak_pos);
437  ftf->FixParameter(2, peak_width);
438  ftf->SetParameter(3, 1.0);
439  ftf->SetParameter(4, mass_thresh>xmin ? mass_thresh:xmin);
440  ftf->SetParameter(5, 2.0);
441  ftf->SetParameter(6, 4.0);
442 
443  // Limits of signal region to exclude from initial fit
444  Double_t xexcl_1 = peak_pos - 3.0*peak_width;
445  Double_t xexcl_2 = peak_pos + 3.0*peak_width;
446  ftf->FixParameter(7, xexcl_1); // Set excluded region min
447  ftf->FixParameter(8, xexcl_2); // Set excluded region max
448 
449  // Find limits of initial background fit and do it
450  Double_t xminfit = mass_thresh;
451  if(xmaxfit==0.0) xmaxfit = h1->GetXaxis()->GetXmax();
452  Int_t minbin_int = h1->FindBin(xexcl_2);
453  Int_t maxbin_int = minbin_int + 5; // Integrate 6 bins
454  Double_t xmin_int = h1->GetBinLowEdge(minbin_int); // low edge of integration region
455  Double_t xmax_int = h1->GetBinLowEdge(maxbin_int+1); // high edge of integration region
456  Double_t norm = h1->GetBinContent(minbin_int, maxbin_int)/h1->GetBinWidth(minbin_int)/ftf->Integral(xmin_int, xmax_int);
457  ftf->SetParameter(3, norm); // scale background function to match histo integral near edge of excluded region
458  h1->Fit(ftf, "0Q", "", xminfit, xmaxfit);
459 
460  // Release peak parameters and fit to full range
461  ftf->ReleaseParameter(0);
462  ftf->ReleaseParameter(1);
463  ftf->ReleaseParameter(2);
464  ftf->ReleaseParameter(9);
465  ftf->FixParameter(7, -1.0E6); // disable excluded region
466  ftf->FixParameter(8, -1.0E6); // disable excluded region
467  h1->Fit(ftf, "Q", "", xminfit, xmaxfit);
468 
469  // Copy parameters into new function for plotting background
470  TF1 *fbg = (TF1 *)gROOT->FindObject(fbgname);
471  if(!fbg) fbg = new TF1(fbgname, gauss_bg1, xminfit, xmaxfit, ftf->GetNpar()); // For some reason Clone doesn't work right here!
472  fbg->SetParameters(ftf->GetParameters());
473  fbg->SetParameter(0, 0.0); // zero out peak
474  fbg->SetLineStyle(2);
475  fbg->SetLineColor(kMagenta);
476  fbg->Draw("same");
477 
478  // Draw line at nominal peak position
479  double max = 1.05*h1->GetMaximum();
480  TLine lin;
481  lin.SetLineColor(kMagenta);
482  lin.SetLineWidth(1);
483  lin.DrawLine(peak_pos, 0.0, peak_pos, max);
484 
485  char str[256];
486  sprintf(str, "%d MeV", (int)(1000*peak_pos));
487 
488  TLatex latex;
489  latex.SetTextAngle(90.0);
490  latex.SetTextSize(0.035);
491  latex.SetTextAlign(21);
492  latex.SetTextColor(kMagenta);
493  latex.DrawLatex(peak_pos - 0.005, max/2.0, str);
494 
495  // Get number of signal particless
496  Double_t I = ftf->Integral(xminfit, xmaxfit) - fbg->Integral(xminfit, xmaxfit);
497  I /= h1->GetBinWidth(1);
498 
499  return I;
500  }
501 
502 };
503 
504  //------------------------- Macro starts here ------------------------
505 
506  vector<bool> trig(34, false); // triggers to include (33 is any physics bit was set)
507  trig[33-1] = true; // Any physics trigger (either bit 1 or bit 3)
508 
509  TDirectory *locTopDirectory = gDirectory;
510 
511  //Goto Beam Path
512  TDirectory *locDirectory = (TDirectory*)gDirectory->FindObjectAny("highlevel");
513  if(!locDirectory)return;
514  locDirectory->cd();
515 
516  TH1* EventInfo = (TH1*)gDirectory->Get("EventInfo");
517  TH1* TwoGammaMass = (TH1*)gDirectory->Get("TwoGammaMass");
518  TH1* PiPlusPiMinus = (TH1*)gDirectory->Get("PiPlusPiMinus");
519  TH1* KPlusKMinus = (TH1*)gDirectory->Get("KPlusKMinus");
520  TH1* PiPlusPiMinusPiZero = (TH1*)gDirectory->Get("PiPlusPiMinusPiZero");
521  TH1* L1bits_gtp = (TH1*)gDirectory->Get("L1bits_gtp");
522  TH1* PSPairEnergy = (TH1*)gDirectory->Get("PSPairEnergy");
523 
524  // These are used to keep track of normalization values when the PID
525  // histogram was last reset. This is only used for the Time Series
526  // DB. Because we can't use global variables here, we must store them
527  // in a histogram and retrieve them each time the macro is run.
528  enum {
538  };
539  TH1* PIDNorms = (TH1*)gDirectory->Get("PIDNorms");
540  if( !PIDNorms ) PIDNorms = new TH1I("PIDNorms","", NORM_NUM, 0.0, NORM_NUM);
541  double Ntrig_tot_pi0 = PIDNorms->GetBinContent(NORM_pi0_trig);
542  double Ntrig_tot_rho = PIDNorms->GetBinContent(NORM_rho_trig);
543  double Ntrig_tot_phi = PIDNorms->GetBinContent(NORM_phi_trig);
544  double Ntrig_tot_omega = PIDNorms->GetBinContent(NORM_omega_trig);
545  double Nps_pi0 = PIDNorms->GetBinContent(NORM_pi0_trig);
546  double Nps_rho = PIDNorms->GetBinContent(NORM_rho_ps);
547  double Nps_phi = PIDNorms->GetBinContent(NORM_phi_ps);
548  double Nps_omega = PIDNorms->GetBinContent(NORM_omega_ps);
549 
550  //Get/Make Canvas
551  TCanvas *locCanvas = NULL;
552  if(TVirtualPad::Pad() == NULL)
553  locCanvas = new TCanvas("PID", "PID", 1200, 600); //for testing
554  else
555  locCanvas = gPad->GetCanvas();
556  locCanvas->Divide(2, 2);
557 
558  double Ntrig_tot = 0.0;
559  double Ntrig_phys = 0.0;
560  double Ntrig_ps = 0.0;
561  if(L1bits_gtp){
562  for(int itrig=1; itrig<=trig.size(); itrig++){
563  if(itrig > L1bits_gtp->GetNbinsX()) break;
564  if(trig[itrig-1]) Ntrig_tot += (double)L1bits_gtp->GetBinContent(itrig);
565  }
566  Ntrig_phys = (double)(L1bits_gtp->GetBinContent(1) + L1bits_gtp->GetBinContent(2));
567  Ntrig_ps = (double)L1bits_gtp->GetBinContent(4);
568  }
569 
570  double Nps = 0.0;
571  if(PSPairEnergy){
572  Nps = PSPairEnergy->Integral();
573  }
574 
575  // Get unix time for time series DB entries
576  double unix_time = 0;
577  if(EventInfo){
578  Double_t Nunix = EventInfo->GetBinContent(1);
579  if(Nunix>0.0){
580  Double_t sum_unix_time = EventInfo->GetBinContent(2);
581  unix_time = (sum_unix_time/Nunix);
582  time_t t = (time_t)unix_time;
583  cout << ctime(&t);
584  }
585  }
586 
587  TLatex latex;
588 
589 
590  //----------- Pi0 --------------
591  locCanvas->cd(1);
592  gPad->SetTicks();
593  gPad->SetGrid();
594  if(TwoGammaMass != NULL)
595  {
596 
597  TwoGammaMass->GetXaxis()->SetTitleSize(0.05);
598  TwoGammaMass->GetYaxis()->SetTitleSize(0.05);
599  TwoGammaMass->GetXaxis()->SetLabelSize(0.05);
600  TwoGammaMass->GetYaxis()->SetLabelSize(0.035);
601  TwoGammaMass->SetStats(0);
602 
603  // Fit to pi0 peak
604  TF1 *fun = (TF1*)gDirectory->FindObjectAny("fun_pi0_fit");
605  if(!fun)fun = new TF1("fun_pi0_fit", "gaus(0) + pol2(3)");
606 
607  // Fit once with fixed parameters to force finding of polynomial params
608  fun->FixParameter(0, TwoGammaMass->GetBinContent(TwoGammaMass->FindBin(0.134))*0.1);
609  fun->FixParameter(1, 0.134);
610  fun->FixParameter(2, 0.01);
611  fun->SetParameter(3, 0.0);
612  fun->SetParameter(4, 0.0);
613  fun->SetParameter(5, 0.0);
614 
615  // Region of interest for fit
616  double lo = 0.080;
617  double hi = 0.190;
618 
619  // Fit and Draw
620  TwoGammaMass->Fit(fun, "Q", "", lo, hi);
621 
622  // Release gaussian parameters and fit again
623  fun->ReleaseParameter(0);
624  fun->ReleaseParameter(1);
625  fun->ReleaseParameter(2);
626 
627  // Fit and Draw again (histogram and function)
628  TwoGammaMass->Fit(fun, "Q", "", lo, hi);
629 
630  // Second function for drawing background
631  TF1 *fun2 = (TF1*)gDirectory->FindObjectAny("fun_pi0_fit2");
632  if(!fun2) fun2 = new TF1("fun_pi0_fit", "pol2(0)" , lo, hi);
633  double pars[10];
634  fun->GetParameters(pars);
635  const Double_t *errs = fun->GetParErrors();
636  fun2->SetParameters(&pars[3]);
637  fun2->SetLineColor(kMagenta);
638  fun2->SetLineStyle(2);
639  fun2->Draw("same");
640 
641  // Get number of pi0's
642  double I = fun->GetParameter(0)*fun->GetParameter(2)*sqrt(TMath::TwoPi());
643  I /= TwoGammaMass->GetBinWidth(1);
644 
645 
646  char str[256];
647  sprintf(str, "num. #pi^{o} : %g", I);
648 
649  double max = 1.05*TwoGammaMass->GetMaximum();
650  latex.SetTextColor(kBlack);
651  latex.SetTextAngle(0.0);
652  latex.SetTextAlign(11);
653  latex.SetTextSize(0.075);
654  latex.DrawLatex(0.175, max*3.0/4.0, str);
655 
656  // Print rate per trigger
657  double Ntrig = Ntrig_tot - Ntrig_tot_pi0;
658  double rate_per_1ktrig = I/Ntrig*1000.0;
659  if(Ntrig>0.0){
660  sprintf(str, "%3.1f per 1k triggers (bits 1,3)", rate_per_1ktrig);
661  latex.SetTextSize(0.06);
662  latex.DrawLatex(0.3, max*0.65, str);
663  }
664 
665  // Print rate per PS (integral of reconstructed energy hist)
666  double Nmy_ps = Nps - Nps_pi0;
667  double rate_per_ps = I/Nmy_ps*1000.0;
668  if(Nmy_ps>0.0){
669  sprintf(str, "%3.1f per 1k PS coin(>7GeV)", rate_per_ps);
670  latex.SetTextSize(0.06);
671  latex.DrawLatex(0.3, max*0.565, str);
672  }
673 
674  // Only try adding to time series if we have more than 2000 particles in peak
675  cout << "====== pi0: I="<<I<<" mean: " << pars[1] << " +/- " << errs[1] << " sigma: "<< pars[2] << " +/- " << errs[2] << endl;
676  if( (I>2000.0) && (errs[1]<0.07*pars[1]) && (errs[2]<0.2*pars[2]) ){
677  // Add to time series
678  InsertSeriesMassFit("pi0", pars[1], pars[2], errs[1], errs[2], unix_time);
679 
680  // per 1k triggers
681  if(Ntrig>0.0){
682  stringstream ss;
683  ss << "fit_stats,ptype=pi0 ";
684  ss << "rate_per_1ktrig="<<rate_per_1ktrig;
685  ss << ",rate_per_1kps="<<rate_per_ps;
686  ss << ",counts="<<I;
687  ss << ",Ntrig_phys="<<Ntrig_phys;
688  ss << ",Ntrig_ps="<<Ntrig_ps;
689  ss << ",Nps="<<Nmy_ps;
690  if(unix_time!=0.0) ss<<" "<<(uint64_t)(unix_time*1.0E9); // time is in units of ns
691  InsertSeriesData( ss.str() );
692  }
693 
694  // Optionally reset the histogram so next fit is independent of this one
695  if(rs_GetFlag("RESET_AFTER_FIT")) {
696  rs_ResetHisto("/highlevel/TwoGammaMass");
697  PIDNorms->SetBinContent(NORM_pi0_trig, Ntrig_tot);
698  PIDNorms->SetBinContent(NORM_pi0_ps , Nps);
699  }
700  }
701 
702  TLine lin;
703  lin.SetLineColor(kMagenta);
704  lin.SetLineWidth(1);
705  lin.DrawLine(0.135, 0.0, 0.135, max);
706 
707  latex.SetTextAngle(90.0);
708  latex.SetTextSize(0.035);
709  latex.SetTextAlign(21);
710  latex.SetTextColor(kMagenta);
711  latex.DrawLatex(0.131, max/2.0, "135 MeV");
712 
713  // Print number of L1 triggers
714  latex.SetTextColor(kBlack);
715  latex.SetTextAngle(0.0);
716  latex.SetTextSize(0.05);
717  latex.SetTextAlign(12);
718  if(L1bits_gtp){
719  sprintf(str, "trig bit 1 (FCAL/BCAL): %g", (double)L1bits_gtp->GetBinContent(1));
720  latex.DrawLatex(0.4, max*0.45, str);
721  sprintf(str, "trig bit 3 (BCAL): %g", (double)L1bits_gtp->GetBinContent(3));
722  latex.DrawLatex(0.4, max*0.35, str);
723  sprintf(str, "trig bit 4 (PS): %g", (double)L1bits_gtp->GetBinContent(4));
724  latex.DrawLatex(0.4, max*0.25, str);
725  }
726  }
727 
728  //----------- Phi --------------
729  locCanvas->cd(2);
730  gPad->SetTicks();
731  gPad->SetGrid();
732  if(KPlusKMinus != NULL)
733  {
734  KPlusKMinus->GetXaxis()->SetTitleSize(0.05);
735  KPlusKMinus->GetYaxis()->SetTitleSize(0.05);
736  KPlusKMinus->GetXaxis()->SetLabelSize(0.05);
737  KPlusKMinus->GetYaxis()->SetLabelSize(0.035);
738  KPlusKMinus->SetStats(0);
739  KPlusKMinus->GetXaxis()->SetRangeUser(0.8, 2.0);
740 
741  Double_t pars_out[3*2];
742  Double_t errs_out[3*2];
743  Double_t I = FitWrapper::FitPeaksWithBackgr(KPlusKMinus, 0.494*2, 1.8, "GG", 1.02, 0.01, 1.22, 0.05, 0.0, 0.0, 0.0, 0.0, pars_out, errs_out);
744 
745  if(I>0.0){
746  char str[256];
747  sprintf(str, "num. #phi : %g", I);
748 
749  double max = 1.05*KPlusKMinus->GetMaximum();
750  latex.SetTextColor(kBlack);
751  latex.SetTextAngle(0.0);
752  latex.SetTextAlign(11);
753  latex.SetTextSize(0.075);
754  latex.DrawLatex(1.4, max*3.0/4.0, str);
755 
756  // Print rate per trigger
757  double Ntrig = Ntrig_tot - Ntrig_tot_phi;
758  double rate_per_1ktrig = I/Ntrig*1000.0;
759  if(Ntrig_tot>0.0){
760  sprintf(str, "%3.3f per 1k triggers (bits 1,3)", rate_per_1ktrig);
761  latex.SetTextSize(0.06);
762  latex.DrawLatex(1.4, max*0.65, str);
763  }
764 
765  // Print rate per PS (integral of reconstructed energy hist)
766  double Nmy_ps = Nps - Nps_phi;
767  double rate_per_ps = I/Nmy_ps*1000.0;
768  if(Nmy_ps>0.0){
769  sprintf(str, "%3.3f per 1k PS coin(>7GeV)", rate_per_ps);
770  latex.SetTextSize(0.06);
771  latex.DrawLatex(1.4, max*0.565, str);
772  }
773 
774  // Only try adding to time series if we have more than 200 particles in peak
775  cout << "====== phi: I="<<I<<" mean: " << pars_out[1] << " +/- " << errs_out[1] << " sigma: "<< pars_out[2] << " +/- " << errs_out[2] << endl;
776  if( (I>200.0) && (errs_out[1]<0.07*pars_out[1]) && (errs_out[2]<0.2*pars_out[2]) ){
777 
778  // Add to time series
779  InsertSeriesMassFit("phi", pars_out[1], pars_out[2], errs_out[1], errs_out[2], unix_time);
780 
781  // per 1k triggers
782  if(Ntrig_tot>0.0){
783  stringstream ss;
784  ss << "fit_stats,ptype=phi ";
785  ss << "rate_per_1ktrig="<<rate_per_1ktrig;
786  ss << ",rate_per_1kps="<<rate_per_ps;
787  ss << ",counts="<<I;
788  ss << ",Ntrig_phys="<<Ntrig_phys;
789  ss << ",Ntrig_ps="<<Ntrig_ps;
790  ss << ",Nps="<<Nmy_ps;
791  if(unix_time!=0.0) ss<<" "<<(uint64_t)(unix_time*1.0E9); // time is in units of ns
792  InsertSeriesData( ss.str() );
793  }
794 
795  // Optionally reset the histogram so next fit is independent of this one
796  if(rs_GetFlag("RESET_AFTER_FIT")){
797  rs_ResetHisto("/highlevel/KPlusKMinus");
798  PIDNorms->SetBinContent(NORM_phi_trig, Ntrig_tot);
799  PIDNorms->SetBinContent(NORM_phi_ps , Nps);
800  }
801  }
802  }
803  }
804 
805  //----------- Rho --------------
806  locCanvas->cd(3);
807  gPad->SetTicks();
808  gPad->SetGrid();
809  if(PiPlusPiMinus != NULL)
810  {
811  PiPlusPiMinus->GetXaxis()->SetTitleSize(0.05);
812  PiPlusPiMinus->GetYaxis()->SetTitleSize(0.05);
813  PiPlusPiMinus->GetXaxis()->SetLabelSize(0.05);
814  PiPlusPiMinus->GetYaxis()->SetLabelSize(0.035);
815  PiPlusPiMinus->SetStats(0);
816 
817  Double_t pars_out[3*2];
818  Double_t errs_out[3*2];
819  //Double_t I = FitWrapper::FitWithBackground(PiPlusPiMinus, 0.770, 0.1, 0.3, 1.6);
820  Double_t I = FitWrapper::FitPeaksWithBackgr(PiPlusPiMinus, 0.139*2, 1.8, "G", 0.770, 0.085, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, pars_out, errs_out);
821 
822  if(I>0.0){
823  char str[256];
824  sprintf(str, "num. #rho : %g", I);
825 
826  double max = 1.05*PiPlusPiMinus->GetMaximum();
827  latex.SetTextColor(kBlack);
828  latex.SetTextAngle(0.0);
829  latex.SetTextAlign(11);
830  latex.SetTextSize(0.075);
831  latex.DrawLatex(1.005, max*3.0/4.0, str);
832 
833  // Print rate per trigger
834  double Ntrig = Ntrig_tot - Ntrig_tot_rho;
835  double rate_per_1ktrig = I/Ntrig*1000.0;
836  if(Ntrig_tot>0.0){
837  sprintf(str, "%3.3f per 1k triggers (bits 1,3)", rate_per_1ktrig);
838  latex.SetTextSize(0.06);
839  latex.DrawLatex(1.010, max*0.65, str);
840  }
841 
842  // Print rate per PS (integral of reconstructed energy hist)
843  double Nmy_ps = Nps - Nps_rho;
844  double rate_per_ps = I/Nmy_ps*1000.0;
845  if(Nmy_ps>0.0){
846  sprintf(str, "%3.3f per 1k PS coin(>7GeV)", rate_per_ps);
847  latex.SetTextSize(0.06);
848  latex.DrawLatex(1.010, max*0.565, str);
849  }
850 
851  // Only try adding to time series if we have more than 1000 particles in peak
852  cout << "====== rho: I="<<I<<" mean: " << pars_out[1] << " +/- " << errs_out[1] << " sigma: "<< pars_out[2] << " +/- " << errs_out[2] << endl;
853  if( (I>1000.0) && (errs_out[1]<0.07*pars_out[1]) && (errs_out[2]<0.2*pars_out[2]) ){
854  // Add to time series
855  InsertSeriesMassFit("rho", pars_out[1], pars_out[2], errs_out[1], errs_out[2], unix_time);
856 
857  // per 1k triggers
858  if(Ntrig_tot>0.0){
859  stringstream ss;
860  ss << "fit_stats,ptype=rho ";
861  ss << "rate_per_1ktrig="<<rate_per_1ktrig;
862  ss << ",rate_per_1kps="<<rate_per_ps;
863  ss << ",counts="<<I;
864  ss << ",Ntrig_phys="<<Ntrig_phys;
865  ss << ",Ntrig_ps="<<Ntrig_ps;
866  ss << ",Nps="<<Nmy_ps;
867  if(unix_time!=0.0) ss<<" "<<(uint64_t)(unix_time*1.0E9); // time is in units of ns
868  InsertSeriesData( ss.str() );
869  }
870 
871  // Optionally reset the histogram so next fit is independent of this one
872  if(rs_GetFlag("RESET_AFTER_FIT")){
873  rs_ResetHisto("/highlevel/PiPlusPiMinus");
874  PIDNorms->SetBinContent(NORM_rho_trig, Ntrig_tot);
875  PIDNorms->SetBinContent(NORM_rho_ps , Nps);
876  }
877  }
878  }
879  }
880 
881  //----------- Omega --------------
882  locCanvas->cd(4);
883  gPad->SetTicks();
884  gPad->SetGrid();
885  if(PiPlusPiMinusPiZero != NULL)
886  {
887  PiPlusPiMinusPiZero->GetXaxis()->SetTitleSize(0.05);
888  PiPlusPiMinusPiZero->GetYaxis()->SetTitleSize(0.05);
889  PiPlusPiMinusPiZero->GetXaxis()->SetLabelSize(0.05);
890  PiPlusPiMinusPiZero->GetYaxis()->SetLabelSize(0.035);
891  PiPlusPiMinusPiZero->SetStats(0);
892 
893  Double_t pars_out[3*2];
894  Double_t errs_out[3*2];
895  //Double_t I = FitWrapper::FitWithBackground(PiPlusPiMinusPiZero, 0.782, 0.03, 0.42, 1.6);
896  Double_t I = FitWrapper::FitPeaksWithBackgr(PiPlusPiMinusPiZero, 0.139*2+0.135, 1.3, "G", 0.782, 0.009, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, pars_out, errs_out);
897 
898  if(I>0.0){
899  char str[256];
900  sprintf(str, "num. #omega : %g", I);
901 
902  double max = 1.05*PiPlusPiMinusPiZero->GetMaximum();
903  latex.SetTextColor(kBlack);
904  latex.SetTextAngle(0.0);
905  latex.SetTextAlign(11);
906  latex.SetTextSize(0.075);
907  latex.DrawLatex(1.005, max*0.8, str);
908 
909  // Print rate per trigger
910  double Ntrig = Ntrig_tot - Ntrig_tot_omega;
911  double rate_per_1ktrig = I/Ntrig*1000.0;
912  if(Ntrig_tot>0.0){
913  sprintf(str, "%3.3f per 1k triggers (bits 1,3)", rate_per_1ktrig);
914  latex.SetTextSize(0.06);
915  latex.DrawLatex(1.010, max*0.65, str);
916  }
917 
918  // Print rate per PS (integral of reconstructed energy hist)
919  double Nmy_ps = Nps - Nps_omega;
920  double rate_per_ps = I/Nmy_ps*1000.0;
921  if(Nmy_ps>0.0){
922  sprintf(str, "%3.3f per 1k PS coin(>7GeV)", rate_per_ps);
923  latex.SetTextSize(0.06);
924  latex.DrawLatex(1.010, max*0.565, str);
925  }
926 
927  // Only try adding to time series if we have more than 200 particles in peak
928  cout << "====== omega: I="<<I<<" mean: " << pars_out[1] << " +/- " << errs_out[1] << " sigma: "<< pars_out[2] << " +/- " << errs_out[2] << endl;
929  if( (I>200.0) && (errs_out[1]<0.07*pars_out[1]) && (errs_out[2]<0.2*pars_out[2]) ){
930  // Add to time series
931  InsertSeriesMassFit("omega", pars_out[1], pars_out[2], errs_out[1], errs_out[2], unix_time);
932 
933  // per 1k triggers
934  if(Ntrig_tot>0.0){
935  stringstream ss;
936  ss << "fit_stats,ptype=omega ";
937  ss << "rate_per_1ktrig="<<rate_per_1ktrig;
938  ss << ",rate_per_1kps="<<rate_per_ps;
939  ss << ",counts="<<I;
940  ss << ",Ntrig_phys="<<Ntrig_phys;
941  ss << ",Ntrig_ps="<<Ntrig_ps;
942  ss << ",Nps="<<Nmy_ps;
943  if(unix_time!=0.0) ss<<" "<<(uint64_t)(unix_time*1.0E9); // time is in units of ns
944  InsertSeriesData( ss.str() );
945  }
946 
947  // Optionally reset the histogram so next fit is independent of this one
948  if(rs_GetFlag("RESET_AFTER_FIT")){
949  rs_ResetHisto("/highlevel/PiPlusPiMinusPiZero");
950  PIDNorms->SetBinContent(NORM_omega_trig, Ntrig_tot);
951  PIDNorms->SetBinContent(NORM_omega_ps , Nps);
952  }
953  }
954  }
955  }
956 }
double Ntrig_ps
TH1 * PiPlusPiMinusPiZero
char str[256]
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
double Ntrig_phys
sprintf(text,"Post KinFit Cut")
#define InsertSeriesData(A)
double Nps_pi0
#define rs_ResetHisto(A)
trig[33-1]
TH1 * EventInfo
double Ntrig_tot_phi
double Ntrig_tot_pi0
TDirectory * locTopDirectory
Definition: HistMacro_p4pi.C:2
#define InsertSeriesMassFit(A, B, C, D, E, F)
TDirectory * locDirectory
TH1 * L1bits_gtp
TH1 * TwoGammaMass
double Nps
TH1 * PiPlusPiMinus
#define rs_GetFlag(A)
double Nps_rho
TH1 * PSPairEnergy
TH1 * PIDNorms
double sqrt(double)
double unix_time
double Ntrig_tot_omega
double Nps_omega
double Ntrig_tot
Double_t ymin
Definition: bcal_hist_eff.C:89
double Nps_phi
double Ntrig_tot_rho
TH1 * KPlusKMinus
Double_t ymax
Definition: bcal_hist_eff.C:91
printf("string=%s", string)
TCanvas * locCanvas
#define I(x, y, z)