MaCh3 2.2.1
Reference Guide
Loading...
Searching...
No Matches
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
11void 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
35double 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
50double 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
63TH1D* 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
131TH1D* 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
198TH2Poly* 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
211void 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
222template<class HistType>
223HistType* 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
235TH2Poly* 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// ****************
248TH2D* 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// ****************
282TH2Poly* 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
331TH2Poly* 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
351double 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// *********************
370TH2Poly* 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
394void 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
405void 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
424void 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
443void 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
466int 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
495void 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// *************************
516std::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
548void 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
570double 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
589double 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
608namespace M3 {
609// **************************************************************************
610TFile* 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:106
#define _MaCh3_Safe_Include_End_
KS: Restore warning checking after including external headers.
Definition: Core.h:117
TH2D * ConvertTH2PolyToTH2D(TH2Poly *poly, TH2D *h2dhist)
KS: Convert TH2D to TH2Poly.
TH1D * PolyProjectionX(TObject *poly, std::string TempName, const std::vector< double > &xbins, const bool computeErrors)
WP: Poly Projectors.
void MakeFluctuatedHistogramAlternative(TH1D *FluctHist, TH1D *PolyHist, TRandom3 *rand)
Make Poisson fluctuation of TH1D hist using slow method which is only for cross-check.
TH2Poly * ConvertTH2DtoTH2Poly(TH2D *hist)
KS: Convert TH2Poly to TH2D.
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.
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 * PolyScaleWidth(TH2Poly *Histogram, double scale)
WP: Helper to scale th2poly analogous to th2d scale with option "width".
double returnCherenkovThresholdMomentum(int PDG)
DB Get the Cherenkov momentum threshold in MeV.
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.
HistType * RatioHists(HistType *NumHist, HistType *DenomHist)
Helper to make ratio histograms.
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".
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.
TH1D * PolyProjectionY(TObject *poly, std::string TempName, const std::vector< double > &ybins, const bool computeErrors)
WP: Poly Projectors.
_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 * RatioPolys(TH2Poly *NumHist, TH2Poly *DenomHist)
Helper to make ratio of TH2Polys.
TH2Poly * NormalisePoly(TH2Poly *Histogram)
WP: Helper to Normalise histograms.
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:25
#define MACH3LOG_TRACE
Definition: MaCh3Logger.h:21
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.