MaCh3  2.2.3
Reference Guide
HistogramUtils.cpp
Go to the documentation of this file.
2 
4 #include "TList.h"
5 #include "TObjArray.h"
7 
8 // **************************************************
9 //KS: ROOT changes something with binning when moving from ROOT 5 to ROOT 6. If you open ROOT5 produced file with ROOT6 you will be missing 9 last bins
10 // However if you use ROOT6 and have ROOT6 file exactly the same code will work. Something have changed with how TH2Poly bins are stored in TFile
11 void CheckTH2PolyFileVersion(TFile *file) {
12 // **************************************************
13  int FileROOTVersion = file->GetVersion();
14  int MainFileROOTVersion = FileROOTVersion;
15 
16  // Remove last digit from number
17  // till only one digit is left
18  while (MainFileROOTVersion >= 10)
19  MainFileROOTVersion /= 10;
20 
21  std::string SystemROOTVersion = std::string(ROOT_RELEASE);
22  int MainSystemROOTVersion = SystemROOTVersion.at(0) - '0';
23 
24  if(MainFileROOTVersion != MainSystemROOTVersion)
25  {
26  MACH3LOG_ERROR("File was produced with: {} ROOT version", FileROOTVersion);
27  MACH3LOG_ERROR("Found: {} ROOT version in the system", SystemROOTVersion);
28  MACH3LOG_ERROR("For some documentation please visit me");
29  throw MaCh3Exception(__FILE__, __LINE__);
30  }
31 }
32 
33 // **************************************************
34 //WP: Helper function for calculating unbinned Integral of TH2Poly i.e including overflow
35 double OverflowIntegral(TH2Poly* poly) {
36 // **************************************************
37  double overflow = 0.;
38  //TH2Polys have 9 overflow bins
39  for(int iOverflow = -1; iOverflow > -10; iOverflow--)
40  {
41  overflow += poly->GetBinContent(iOverflow);
42  }
43  double IntegralUn = NoOverflowIntegral(poly) + overflow;
44 
45  return IntegralUn;
46 } // end function
47 
48 // **************************************************
49 //WP: Helper function for calculating binned Integral of TH2Poly i.e not including overflow
50 double NoOverflowIntegral(TH2Poly* poly) {
51 // **************************************************
52  double integral = 0.;
53  for(int i = 1; i < poly->GetNumberOfBins()+1; i++)
54  {
55  integral += poly->GetBinContent(i);
56  }
57 
58  return integral;
59 } // end function
60 
61 // **************************************************
62 //WP: Helper function for projecting TH2Poly onto the X axis
63 TH1D* PolyProjectionX(TObject* poly, std::string TempName, const std::vector<double>& xbins, const bool computeErrors) {
64 // **************************************************
65  TH1D* hProjX = new TH1D((TempName+"_x").c_str(),(TempName+"_x").c_str(), int(xbins.size()-1), &xbins[0]);
66 
67  //KS: Temp Histogram to store error, use double as this is thread safe
68  std::vector<double> hProjX_Error(hProjX->GetXaxis()->GetNbins() + 1, 0.0);
69  double xlow, xup, frac = 0.;
70 
71  //loop over bins in the poly
72  for (int i = 0; i < static_cast<TH2Poly*>(poly)->GetNumberOfBins(); i++)
73  {
74  //get bin and its edges
75  TH2PolyBin* bin = static_cast<TH2PolyBin*>(static_cast<TH2Poly*>(poly)->GetBins()->At(i));
76  xlow = bin->GetXMin();
77  xup = bin->GetXMax();
78 
79  //Loop over projected bins, find fraction of poly bin in each
80  for(int dx = 0; dx < int(xbins.size()); dx++)
81  {
82  if(xbins[dx+1] <= xlow || xbins[dx] >= xup)
83  {
84  frac = 0;
85  }
86  else if(xbins[dx] <= xlow && xbins[dx+1] >= xup)
87  {
88  frac = 1;
89  }
90  else if(xbins[dx] <= xlow && xbins[dx+1] <= xup)
91  {
92  frac = (xbins[dx+1]-xlow)/(xup-xlow);
93  }
94  else if(xbins[dx] >= xlow && xbins[dx+1] >= xup)
95  {
96  frac = (xup-xbins[dx])/(xup-xlow);
97  }
98  else if(xbins[dx] >= xlow && xbins[dx+1] <= xup)
99  {
100  frac = (xbins[dx+1]-xbins[dx])/(xup-xlow);
101  }
102  else
103  {
104  frac = 0;
105  }
106  hProjX->SetBinContent(dx+1,hProjX->GetBinContent(dx+1)+frac*bin->GetContent());
107  //KS: Follow ROOT implementation and sum up the variance
108  if(computeErrors)
109  {
110  //KS: TH2PolyBin doesn't have GetError so we have to use TH2Poly,
111  //but numbering of GetBinError is different than GetBins...
112  const double Temp_Err = frac*static_cast<TH2Poly*>(poly)->GetBinError(i+1)*frac*static_cast<TH2Poly*>(poly)->GetBinError(i+1);
113  hProjX_Error[dx+1] += Temp_Err;
114  }
115  }
116  }
117  //KS: The error is sqrt(summed variance)) https://root.cern.ch/doc/master/TH2_8cxx_source.html#l02266
118  if(computeErrors)
119  {
120  for (int i = 1; i <= hProjX->GetXaxis()->GetNbins(); ++i)
121  {
122  const double Error = std::sqrt(hProjX_Error[i]);
123  hProjX->SetBinError(i, Error);
124  }
125  }
126  return hProjX;
127 } // end project poly X function
128 
129 // **************************************************
130 //WP: Helper function for projecting TH2Poly onto the Y axis
131 TH1D* PolyProjectionY(TObject* poly, std::string TempName, const std::vector<double>& ybins, const bool computeErrors) {
132 // **************************************************
133  TH1D* hProjY = new TH1D((TempName+"_y").c_str(),(TempName+"_y").c_str(),int(ybins.size()-1),&ybins[0]);
134  //KS: Temp Histogram to store error, use double as this is thread safe
135  std::vector<double> hProjY_Error(hProjY->GetXaxis()->GetNbins() + 1, 0.0);
136  double ylow, yup, frac = 0.;
137 
138  //loop over bins in the poly
139  for (int i = 0; i < static_cast<TH2Poly*>(poly)->GetNumberOfBins(); i++)
140  {
141  //get bin and its edges
142  TH2PolyBin* bin = static_cast<TH2PolyBin*>(static_cast<TH2Poly*>(poly)->GetBins()->At(i));
143  ylow = bin->GetYMin();
144  yup = bin->GetYMax();
145 
146  //Loop over projected bins, find fraction of poly bin in each
147  for(int dy = 0; dy < int(ybins.size()); dy++)
148  {
149  if(ybins[dy+1]<=ylow || ybins[dy] >= yup)
150  {
151  frac = 0;
152  }
153  else if(ybins[dy] <= ylow && ybins[dy+1] >= yup)
154  {
155  frac = 1;
156  }
157  else if(ybins[dy] <= ylow && ybins[dy+1] <= yup)
158  {
159  frac = (ybins[dy+1]-ylow)/(yup-ylow);
160  }
161  else if(ybins[dy] >= ylow && ybins[dy+1] >= yup)
162  {
163  frac = (yup-ybins[dy])/(yup-ylow);
164  }
165  else if(ybins[dy] >= ylow && ybins[dy+1] <= yup)
166  {
167  frac = (ybins[dy+1]-ybins[dy])/(yup-ylow);
168  }
169  else
170  {
171  frac = 0;
172  }
173  hProjY->SetBinContent(dy+1,hProjY->GetBinContent(dy+1)+frac*bin->GetContent());
174  //KS: Follow ROOT implementation and sum up the variance
175  if(computeErrors)
176  {
177  //KS: TH2PolyBin doesn't have GetError so we have to use TH2Poly,
178  //but numbering of GetBinError is different than GetBins...
179  const double Temp_Err = frac*static_cast<TH2Poly*>(poly)->GetBinError(i+1)*frac*static_cast<TH2Poly*>(poly)->GetBinError(i+1);
180  hProjY_Error[dy+1] += Temp_Err;
181  }
182  }
183  }
184  //KS: The error is sqrt(summed variance)) https://root.cern.ch/doc/master/TH2_8cxx_source.html#l02266
185  if(computeErrors)
186  {
187  for (int i = 1; i <= hProjY->GetXaxis()->GetNbins(); ++i)
188  {
189  const double Error = std::sqrt(hProjY_Error[i]);
190  hProjY->SetBinError(i, Error);
191  }
192  }
193  return hProjY;
194 } // end project poly Y function
195 
196 // ****************
197 //WP: Normalise a th2poly
198 TH2Poly* NormalisePoly(TH2Poly *Histogram) {
199 // ****************
200  TH2Poly* HistCopy = static_cast<TH2Poly*>(Histogram->Clone());
201  double IntegralWidth = PolyIntegralWidth(HistCopy);
202  HistCopy = PolyScaleWidth(HistCopy, IntegralWidth);
203  std::string title = std::string(HistCopy->GetName())+"_norm";
204  HistCopy->SetNameTitle(title.c_str(), title.c_str());
205 
206  return HistCopy;
207 }
208 
209 // ****************
210 // Normalise a TH2Poly
211 void NormaliseTH2Poly(TH2Poly* Histogram){
212 // ****************
213  const double Integral = NoOverflowIntegral(Histogram);
214  for(int j = 1; j < Histogram->GetNumberOfBins()+1; j++)
215  {
216  Histogram->SetBinContent(j, Histogram->GetBinContent(j)/Integral);
217  }
218 }
219 
220 // ****************
221 // Make a ratio histogram
222 template<class HistType>
223 HistType* RatioHists(HistType *NumHist, HistType *DenomHist) {
224 // ****************
225  HistType *NumCopy = static_cast<HistType*>(NumHist->Clone());
226  std::string title = std::string(DenomHist->GetName()) + "_ratio";
227  NumCopy->SetNameTitle(title.c_str(), title.c_str());
228  NumCopy->Divide(DenomHist);
229 
230  return NumCopy;
231 }
232 
233 // ****************
234 // Make a ratio th2poly
235 TH2Poly* RatioPolys(TH2Poly *NumHist, TH2Poly *DenomHist) {
236 // ****************
237  TH2Poly *NumCopy = static_cast<TH2Poly*>(NumHist->Clone());
238  std::string title = std::string(DenomHist->GetName()) + "_ratio";
239  NumCopy->SetNameTitle(title.c_str(), title.c_str());
240 
241  for(int i = 1; i < NumCopy->GetNumberOfBins()+1; ++i) {
242  NumCopy->SetBinContent(i,NumHist->GetBinContent(i)/DenomHist->GetBinContent(i));
243  }
244  return NumCopy;
245 }
246 
247 // ****************
248 TH2D* ConvertTH2PolyToTH2D(TH2Poly *poly, TH2D *h2dhist) {
249 // ****************
250  double xlow, xup, ylow, yup;
251  std::string HistTempName = poly->GetName();
252 
253  HistTempName += "_";
254  //make the th2d
255  TH2D *hist = static_cast<TH2D*>(h2dhist->Clone());
256  hist->SetNameTitle(HistTempName.c_str(), HistTempName.c_str());
257 
258  for(int ix = 0; ix < hist->GetNbinsX() + 2; ix++) {
259  for(int iy = 0; iy < hist->GetNbinsY() + 2; iy++) {
260  hist->SetBinContent(ix, iy, 0);
261  }
262  }
263  //Loop over poly bins, find the corresponding th2d and setbincontent!
264  for(int i = 0; i< poly->GetNumberOfBins(); i++){
265  TH2PolyBin & polybin = static_cast<TH2PolyBin &>(*poly->GetBins()->At(i));
266  xlow = polybin.GetXMin();
267  xup = polybin.GetXMax();
268  ylow = polybin.GetYMin();
269  yup = polybin.GetYMax();
270  int xbin, ybin;
271 
272  xbin = hist->GetXaxis()->FindBin(xlow+(xup-xlow)/2);
273  ybin = hist->GetYaxis()->FindBin(ylow+(yup-ylow)/2);
274 
275  MACH3LOG_TRACE("Poly bin {}, xlow: {}, xup: {}, ylow: {}, yup: {}. Finding bin for ({}, {}). Found Bin ({}, {}) with content {}. But Poly content: {}",
276  i, xlow, xup, ylow, yup, (xlow + (xup - xlow) / 2), (ylow + (yup - ylow) / 2), xbin, ybin, polybin.GetContent(), poly->GetBinContent(i));
277  hist->SetBinContent(xbin, ybin, polybin.GetContent());
278  }
279  return hist;
280 }
281 // ****************
282 TH2Poly* ConvertTH2DtoTH2Poly(TH2D* hist) {
283 // ****************
284  // Make the x axis from the momentum of lepton
285  TAxis* xaxis = hist->GetXaxis();
286  // Make the y axis from the cos theta of lepton
287  TAxis* yaxis = hist->GetYaxis();
288 
289  TString histname = hist->GetName();
290  // Convert TH2D binning to TH2Poly
291  TH2Poly* poly = new TH2Poly();
292  poly->SetName(histname);
293  poly->SetTitle(histname);
294 
295  // Copy axis titles
296  poly->GetXaxis()->SetTitle(xaxis->GetTitle());
297  poly->GetYaxis()->SetTitle(yaxis->GetTitle());
298 
299  double xmax, xmin, ymax, ymin;
300  for (int iy = 1; iy <= yaxis->GetNbins(); iy++) {
301  ymax = yaxis->GetBinUpEdge(iy);
302  ymin = yaxis->GetBinLowEdge(iy);
303  for (int ix = 1; ix <= xaxis->GetNbins(); ix++) {
304  xmax = xaxis->GetBinUpEdge(ix);
305  xmin = xaxis->GetBinLowEdge(ix);
306  double binofx[] = {xmin, xmax, xmax, xmin};
307  double binofy[] = {ymin, ymin, ymax, ymax};
308  poly->AddBin(4, binofx, binofy);
309  }
310  }
311 
312  for (int iy = 1; iy <= yaxis->GetNbins(); iy++) {
313  ymax = yaxis->GetBinUpEdge(iy);
314  ymin = yaxis->GetBinLowEdge(iy);
315  for (int ix = 1; ix <= xaxis->GetNbins(); ix++) {
316  xmax = xaxis->GetBinUpEdge(ix);
317  xmin = xaxis->GetBinLowEdge(ix);
318 
319  // Get the content of the corresponding bin in TH2D and set it in TH2Poly
320  int bin = hist->GetBin(ix, iy);
321  double content = hist->GetBinContent(bin);
322  poly->SetBinContent(poly->FindBin((xmin + xmax) / 2, (ymin + ymax) / 2), content);
323  }
324  }
325 
326  return poly;
327 }
328 
329 // ****************
330 //WP: Scale a TH2Poly and divide by bin width
331 TH2Poly* PolyScaleWidth(TH2Poly *Histogram, double scale) {
332 // ****************
333  TH2Poly* HistCopy = static_cast<TH2Poly*>(Histogram->Clone());
334  double xlow, xup, ylow, yup, area;
335 
336  for(int i = 1; i < HistCopy->GetNumberOfBins()+1; i++)
337  {
338  TH2PolyBin* bin = static_cast<TH2PolyBin*>(Histogram->GetBins()->At(i - 1));
339  xlow = bin->GetXMin();
340  xup = bin->GetXMax();
341  ylow = bin->GetYMin();
342  yup = bin->GetYMax();
343  area = (xup-xlow)*(yup-ylow);
344  HistCopy->SetBinContent(i, Histogram->GetBinContent(i)/(area*scale));
345  }
346  return HistCopy;
347 }
348 
349 // ****************
350 //WP: Integral of TH2Poly multiplied by bin width
351 double PolyIntegralWidth(TH2Poly *Histogram) {
352 // ****************
353  double integral = 0;
354  double xlow, xup, ylow, yup, area;
355 
356  for(int i = 1; i < Histogram->GetNumberOfBins()+1; i++)
357  {
358  TH2PolyBin* bin = static_cast<TH2PolyBin*>(Histogram->GetBins()->At(i - 1));
359  xlow = bin->GetXMin();
360  xup = bin->GetXMax();
361  ylow = bin->GetYMin();
362  yup = bin->GetYMax();
363  area = (xup-xlow)*(yup-ylow);
364  integral += Histogram->GetBinContent(i)*area;
365  }
366  return integral;
367 }
368 
369 // *********************
370 TH2Poly* MakePolyHist(const std::string& name, const std::vector<double>& BinArray_x, const std::vector<double>& BinArray_y) {
371 // *********************
372  TH2Poly* poly = new TH2Poly();
373  poly->SetName(name.c_str());
374  poly->SetTitle(name.c_str());
375  double xmax, xmin, ymax, ymin;
376  for(unsigned int iy = 0; iy < BinArray_y.size()-1; iy++)
377  {
378  ymax = BinArray_y[iy+1];
379  ymin = BinArray_y[iy];
380  for(unsigned int ix = 0; ix < BinArray_x.size()-1; ix++)
381  {
382  xmax = BinArray_x[ix+1];
383  xmin = BinArray_x[ix];
384  double binofx[] = {xmin, xmax, xmax, xmin};
385  double binofy[] = {ymin, ymin, ymax, ymax};
386  poly->AddBin(4,binofx,binofy);
387  }
388  }
389  return poly;
390 }
391 
392 // *********************
393 //KS: Remove fitted TF1 from hist to make comparison easier
394 void RemoveFitter(TH1D* hist, const std::string& name) {
395 // *********************
396  TList *listOfFunctions = hist->GetListOfFunctions();
397  TF1 *fitter = dynamic_cast<TF1*>(listOfFunctions->FindObject(name.c_str()));
398 
399  listOfFunctions->Remove(fitter);
400  delete fitter;
401 }
402 
403 // ****************
404 // Make Poisson Fluctuation of TH1D hist
405 void MakeFluctuatedHistogramStandard(TH1D *FluctHist, TH1D* PolyHist, TRandom3* rand){
406 // ****************
407  // Make the Poisson fluctuated hist
408  FluctHist->Reset("");
409  FluctHist->Fill(0.0, 0.0);
410 
411  for (int i = 1; i <= PolyHist->GetXaxis()->GetNbins(); ++i)
412  {
413  // Get the posterior predictive bin content
414  const double MeanContent = PolyHist->GetBinContent(i);
415  // Get a Poisson fluctuation of the content
416  const double Random = rand->PoissonD(MeanContent);
417  // Set the fluctuated histogram content to the Poisson variation of the posterior predictive histogram
418  FluctHist->SetBinContent(i,Random);
419  }
420 }
421 
422 // ****************
423 // Make Poisson Fluctuation of TH2Poly hist
424 void MakeFluctuatedHistogramStandard(TH2Poly *FluctHist, TH2Poly* PolyHist, TRandom3* rand) {
425 // ****************
426  // Make the Poisson fluctuated hist
427  FluctHist->Reset("");
428  FluctHist->Fill(0.0, 0.0, 0.0);
429 
430  for (int i = 1; i < FluctHist->GetNumberOfBins()+1; ++i)
431  {
432  // Get the posterior predictive bin content
433  const double MeanContent = PolyHist->GetBinContent(i);
434  // Get a Poisson fluctuation of the content
435  const double Random = rand->PoissonD(MeanContent);
436  // Set the fluctuated histogram content to the Poisson variation of the posterior predictive histogram
437  FluctHist->SetBinContent(i,Random);
438  }
439 }
440 
441 // ****************
442 // Make Poisson Fluctuation of TH1D hist
443 void MakeFluctuatedHistogramAlternative(TH1D* FluctHist, TH1D* PolyHist, TRandom3* rand){
444 // ****************
445  // Make the Poisson fluctuated hist
446  FluctHist->Reset("");
447  FluctHist->Fill(0.0, 0.0);
448 
449  const double evrate = PolyHist->Integral();
450  #pragma GCC diagnostic push
451  #pragma GCC diagnostic ignored "-Wconversion"
452  const int num = rand->Poisson(evrate);
453  #pragma GCC diagnostic pop
454  int count = 0;
455  while(count < num)
456  {
457  const double candidate = PolyHist->GetRandom();
458  FluctHist->Fill(candidate);
459  count++;
460  }
461 }
462 
463 // ****************
464 //KS: ROOT developers were too lazy do develop getRanom2 for TH2Poly, this implementation is based on:
465 // https://root.cern.ch/doc/master/classTH2.html#a883f419e1f6899f9c4255b458d2afe2e
466 int GetRandomPoly2(const TH2Poly* PolyHist, TRandom3* rand){
467 // ****************
468  const int nbins = PolyHist->GetNumberOfBins();
469  const double r1 = rand->Rndm();
470 
471  double* fIntegral = new double[nbins+2];
472  fIntegral[0] = 0.0;
473 
474  //KS: This is custom version of ComputeIntegral, once again ROOT was lazy :(
475  for (int i = 1; i < nbins+1; ++i)
476  {
477  fIntegral[i] = 0.0;
478  const double content = PolyHist->GetBinContent(i);
479  fIntegral[i] += fIntegral[i - 1] + content;
480  }
481  for (Int_t bin = 1; bin < nbins+1; ++bin) fIntegral[bin] /= fIntegral[nbins];
482  fIntegral[nbins+1] = PolyHist->GetEntries();
483 
484  //KS: We just return one rather then X and Y, this way we can use SetBinContent rather than Fill, which is faster
485  int iBin = int(TMath::BinarySearch(nbins, fIntegral, r1));
486  //KS: Have to increment because TH2Poly has stupid offset arghh
487  iBin += 1;
488 
489  delete[] fIntegral;
490  return iBin;
491 }
492 
493 // ****************
494 // Make Poisson fluctuation of TH2Poly hist
495 void MakeFluctuatedHistogramAlternative(TH2Poly *FluctHist, TH2Poly* PolyHist, TRandom3* rand){
496 // ****************
497  // Make the Poisson fluctuated hist
498  FluctHist->Reset("");
499  FluctHist->Fill(0.0, 0.0, 0.0);
500 
501  const double evrate = NoOverflowIntegral(PolyHist);
502  #pragma GCC diagnostic push
503  #pragma GCC diagnostic ignored "-Wconversion"
504  const int num = rand->Poisson(evrate);
505  #pragma GCC diagnostic pop
506  int count = 0;
507  while(count < num)
508  {
509  const int iBin = GetRandomPoly2(PolyHist, rand);
510  FluctHist->SetBinContent(iBin, FluctHist->GetBinContent(iBin) + 1);
511  count++;
512  }
513 }
514 
515 // *************************
516 std::unique_ptr<TGraphAsymmErrors> MakeAsymGraph(TH1* sigmaArrayLeft, TH1* sigmaArrayCentr, TH1* sigmaArrayRight, const std::string& title) {
517 // *************************
518  auto var = std::make_unique<TGraphAsymmErrors>(sigmaArrayCentr);
519  var->SetNameTitle((title).c_str(), (title).c_str());
520 
521  // Need to draw TGraphs to set axes labels
522  var->Draw("AP");
523  var->GetXaxis()->SetTitle(sigmaArrayCentr->GetXaxis()->GetTitle());
524  var->GetYaxis()->SetTitle("Number of events/bin");
525 
526  for (int m = 0; m < var->GetN(); ++m)
527  {
528  double xlow = sigmaArrayLeft->GetBinContent(m+1);
529  double xhigh = sigmaArrayRight->GetBinContent(m+1);
530  double xtemp;
531 
532  // Figure out which variation is larger so we set the error correctly
533  if (xlow > xhigh)
534  {
535  xtemp = xlow;
536  xlow = xhigh;
537  xhigh = xtemp;
538  }
539 
540  var->SetPointEYhigh(m, xhigh - var->GetY()[m]);
541  var->SetPointEYlow(m, var->GetY()[m] - xlow);
542  }
543  return var;
544 }
545 
546 // ****************
547 //Fast and thread safe fill of violin histogram, it assumes both histograms have the same binning
548 void FastViolinFill(TH2D* violin, TH1D* hist_1d){
549 // ****************
550  for (int x = 0; x < violin->GetXaxis()->GetNbins(); ++x)
551  {
552  const int y = violin->GetYaxis()->FindBin(hist_1d->GetBinContent(x+1));
553  violin->SetBinContent(x+1, y, violin->GetBinContent(x+1, y)+1);
554  }
555 }
556 
557 
558 // ****************
559 //DB Get the Cherenkov momentum threshold in MeV
561 // ****************
562  constexpr double refractiveIndex = 1.334; //DB From https://github.com/fiTQun/fiTQun/blob/646cf9c8ba3d4f7400bcbbde029d5ca15513a3bf/fiTQun_shared.cc#L757
563  double mass = MaCh3Utils::GetMassFromPDG(PDG)*1e3;
564  double momentumThreshold = mass/sqrt(refractiveIndex*refractiveIndex-1.);
565  return momentumThreshold;
566 }
567 
568 // **************************************************************************
569 // Recalculate Q^2 after Eb shift. Takes in shifted lepton momentum, lepton angle, and true neutrino energy
570 double CalculateQ2(double PLep, double PUpd, double EnuTrue, double InitialQ2){
571 // ***************************************************************************
572  constexpr double MLep = 0.10565837;
573 
574  // Caluclate muon energy
575  double ELep = sqrt((MLep*MLep)+(PLep*PLep));
576 
577  double CosTh = (2*EnuTrue*ELep - MLep*MLep - InitialQ2)/(2*EnuTrue*PLep);
578 
579  ELep = sqrt((MLep*MLep)+(PUpd*PUpd));
580 
581  // Calculate the new Q2
582  double Q2Upd = -(MLep*MLep) + 2.0*EnuTrue*(ELep - PUpd*CosTh);
583 
584  return Q2Upd - InitialQ2;
585 }
586 
587 // **************************************************************************
588 // Recalculate Enu after Eb shift. Takes in shifted lepton momentum, lepton angle, and binding energy change, and if nu/anu
589 double CalculateEnu(double PLep, double costh, double Eb, bool neutrino){
590 // ***************************************************************************
591  double mNeff = 0.93956536 - Eb / 1000.;
592  double mNoth = 0.93827203;
593 
594  if (!neutrino) {
595  mNeff = 0.93827203 - Eb / 1000.;
596  mNoth = 0.93956536;
597  }
599  constexpr double mLep = 0.10565837;
600  double eLep = sqrt(PLep * PLep + mLep * mLep);
601 
602  double Enu = (2 * mNeff * eLep - mLep * mLep + mNoth * mNoth - mNeff * mNeff) /(2 * (mNeff - eLep + PLep * costh));
603 
604  return Enu;
605 }
606 
607 
608 namespace M3 {
609 // **************************************************************************
610 TFile* Open(const std::string& Name, const std::string& Type, const std::string& File, const int Line) {
611 // **************************************************************************
612  TFile* OutFile = new TFile(Name.c_str(), Type.c_str());
613 
614  // Check if the file is successfully opened and usable
615  if (OutFile->IsZombie()) {
616  MACH3LOG_ERROR("Failed to open file: {}", Name);
617  if (Type == "RECREATE") {
618  MACH3LOG_ERROR("Check if directory exist");
619  }
620  delete OutFile;
621  throw MaCh3Exception(File, Line);
622  }
623  return OutFile;
624 }
625 
626 } //end M3
#define _MaCh3_Safe_Include_Start_
KS: Avoiding warning checking for headers.
Definition: Core.h:109
#define _MaCh3_Safe_Include_End_
KS: Restore warning checking after including external headers.
Definition: Core.h:120
std::unique_ptr< TGraphAsymmErrors > MakeAsymGraph(TH1 *sigmaArrayLeft, TH1 *sigmaArrayCentr, TH1 *sigmaArrayRight, const std::string &title)
Used by sigma variation, check how 1 sigma changes spectra.
void MakeFluctuatedHistogramAlternative(TH1D *FluctHist, TH1D *PolyHist, TRandom3 *rand)
Make Poisson fluctuation of TH1D hist using slow method which is only for cross-check.
TH2D * ConvertTH2PolyToTH2D(TH2Poly *poly, TH2D *h2dhist)
KS: Convert TH2D to TH2Poly.
void NormaliseTH2Poly(TH2Poly *Histogram)
Helper to Normalise histograms.
double OverflowIntegral(TH2Poly *poly)
WP: Helper function for calculating unbinned Integral of TH2Poly i.e including overflow.
void MakeFluctuatedHistogramStandard(TH1D *FluctHist, TH1D *PolyHist, TRandom3 *rand)
Make Poisson fluctuation of TH1D hist using default fast method.
TH1D * PolyProjectionX(TObject *poly, std::string TempName, const std::vector< double > &xbins, const bool computeErrors)
WP: Poly Projectors.
int GetRandomPoly2(const TH2Poly *PolyHist, TRandom3 *rand)
KS: ROOT developers were too lazy do develop getRanom2 for TH2Poly, this implementation is based on l...
void FastViolinFill(TH2D *violin, TH1D *hist_1d)
KS: Fill Violin histogram with entry from a toy.
TH2Poly * NormalisePoly(TH2Poly *Histogram)
WP: Helper to Normalise histograms.
HistType * RatioHists(HistType *NumHist, HistType *DenomHist)
Helper to make ratio histograms.
double returnCherenkovThresholdMomentum(int PDG)
DB Get the Cherenkov momentum threshold in MeV.
TH2Poly * RatioPolys(TH2Poly *NumHist, TH2Poly *DenomHist)
Helper to make ratio of TH2Polys.
TH2Poly * PolyScaleWidth(TH2Poly *Histogram, double scale)
WP: Helper to scale th2poly analogous to th2d scale with option "width".
TH1D * PolyProjectionY(TObject *poly, std::string TempName, const std::vector< double > &ybins, const bool computeErrors)
WP: Poly Projectors.
void RemoveFitter(TH1D *hist, const std::string &name)
KS: Remove fitted TF1 from hist to make comparison easier.
double CalculateEnu(double PLep, double costh, double Eb, bool neutrino)
Recalculate Enu after Eb shift. Takes in shifted lepton momentum, lepton angle, and binding energy ch...
double PolyIntegralWidth(TH2Poly *Histogram)
WP: Helper to calc integral of th2poly analogous to th2d integra; with option "width".
_MaCh3_Safe_Include_Start_ _MaCh3_Safe_Include_End_ void CheckTH2PolyFileVersion(TFile *file)
KS: ROOT changes something with binning when moving from ROOT 5 to ROOT 6. If you open ROOT5 produced...
double NoOverflowIntegral(TH2Poly *poly)
WP: Helper function for calculating binned Integral of TH2Poly i.e not including overflow.
TH2Poly * ConvertTH2DtoTH2Poly(TH2D *hist)
KS: Convert TH2Poly to TH2D.
TH2Poly * MakePolyHist(const std::string &name, const std::vector< double > &BinArray_x, const std::vector< double > &BinArray_y)
WP: Helper function to create TH2Poly histogram with uniform binning.
double CalculateQ2(double PLep, double PUpd, double EnuTrue, double InitialQ2)
Recalculate Q^2 after Eb shift. Takes in shifted lepton momentum, lepton angle, and true neutrino ene...
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:27
#define MACH3LOG_TRACE
Definition: MaCh3Logger.h:23
Custom exception class for MaCh3 errors.
Definition: Core.h:19
TFile * Open(const std::string &Name, const std::string &Type, const std::string &File, const int Line)
Opens a ROOT file with the given name and mode.
double GetMassFromPDG(const int PDG)
Return mass for given PDG.