MaCh3  2.8.0
Reference Guide
Namespaces | Functions
HistogramUtils.h File Reference
#include "Samples/SampleStructs.h"
#include "Parameters/ParameterStructs.h"
#include "Manager/YamlHelper.h"
#include "Manager/Random.h"
Include dependency graph for HistogramUtils.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Namespaces

 M3
 Main namespace for MaCh3 software.
 

Functions

double OverflowIntegral (TH2Poly *poly)
 WP: Helper function for calculating unbinned Integral of TH2Poly i.e including overflow. More...
 
double NoOverflowIntegral (TH2Poly *poly)
 WP: Helper function for calculating binned Integral of TH2Poly i.e not including overflow. More...
 
TH1D * PolyProjectionX (TObject *poly, const std::string &TempName, const std::vector< double > &xbins, const bool computeErrors=false)
 WP: Poly Projectors. More...
 
TH1D * PolyProjectionY (TObject *poly, const std::string &TempName, const std::vector< double > &ybins, const bool computeErrors=false)
 WP: Poly Projectors. More...
 
TH2D * ConvertTH2PolyToTH2D (TH2Poly *poly, TH2D *TH2Dhist)
 KS: Convert TH2D to TH2Poly. More...
 
TH2Poly * ConvertTH2DtoTH2Poly (TH2D *TH2Dhist)
 KS: Convert TH2Poly to TH2D. More...
 
TH2Poly * NormalisePoly (TH2Poly *Histogram)
 WP: Helper to Normalise histograms. More...
 
void NormaliseTH2Poly (TH2Poly *Histogram)
 Helper to Normalise histograms. More...
 
TH2Poly * PolyScaleWidth (TH2Poly *Histogram, double scale)
 WP: Helper to scale th2poly analogous to th2d scale with option "width". More...
 
double PolyIntegralWidth (TH2Poly *Histogram)
 WP: Helper to calc integral of th2poly analogous to th2d integra; with option "width". More...
 
template<class HistType >
HistType * RatioHists (HistType *NumHist, HistType *DenomHist)
 Helper to make ratio histograms. More...
 
TH2Poly * RatioPolys (TH2Poly *NumPoly, TH2Poly *DenomPoly)
 Helper to make ratio of TH2Polys. More...
 
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. More...
 
void CheckTH2PolyFileVersion (TFile *file)
 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. More...
 
void RemoveFitter (TH1D *hist, const std::string &name)
 KS: Remove fitted TF1 from hist to make comparison easier. More...
 
void MakeFluctuatedHistogramStandard (TH1D *FluctHist, TH1D *PolyHist)
 Make Poisson fluctuation of TH1D hist using default fast method. More...
 
void MakeFluctuatedHistogramAlternative (TH1D *FluctHist, TH1D *PolyHist)
 Make Poisson fluctuation of TH1D hist using slow method which is only for cross-check. More...
 
void MakeFluctuatedHistogramStandard (TH2D *FluctHist, TH2D *PolyHist)
 Make Poisson fluctuation of TH2D hist using default fast method. More...
 
void MakeFluctuatedHistogramAlternative (TH2D *FluctHist, TH2D *PolyHist)
 Make Poisson fluctuation of TH2D hist. More...
 
void MakeFluctuatedHistogramStandard (TH2Poly *FluctHist, TH2Poly *PolyHist)
 Make Poisson fluctuation of TH2Poly hist using default fast method. More...
 
void MakeFluctuatedHistogramAlternative (TH2Poly *FluctHist, TH2Poly *PolyHist)
 Make Poisson fluctuation of TH2Poly hist using slow method which is only for cross-check. More...
 
int GetRandomPoly2 (const TH2Poly *PolyHist)
 KS: ROOT developers were too lazy do develop getRanom2 for TH2Poly, this implementation is based on link More...
 
void FastViolinFill (TH2D *violin, TH1D *hist_1d)
 KS: Fill Violin histogram with entry from a toy. More...
 
template<typename Derived , typename Base >
std::vector< std::unique_ptr< Base > > CastVector (std::vector< std::unique_ptr< Derived >> &&inputVec)
 Converts a vector of pointers from a derived type to a base type. More...
 
std::string file_exists (std::string filename)
 Helper to check if files exist or not. More...
 
double returnCherenkovThresholdMomentum (const int PDG)
 DB Get the Cherenkov momentum threshold in MeV. More...
 
double CalculateQ2 (double PLep, double PUpd, double EnuTrue, double InitialQ2=0.0)
 Recalculate Q^2 after Eb shift. Takes in shifted lepton momentum, lepton angle, and true neutrino energy. More...
 
double CalculateEnu (double PLep, double cosTheta, double EB, bool neutrino)
 Recalculate Enu after Eb shift. Takes in shifted lepton momentum, lepton angle, and binding energy change, and if nu/anu. More...
 
std::unique_ptr< TH1D > MakeSummaryFromSpectra (const TH2D *Spectra, const std::string &name)
 Build a 1D posterior-predictive summary from a violin spectrum. More...
 
std::vector< double > BuildBinEdgesFromNode (YAML::Node const &bin_edges_node, bool &found_range_specifier)
 Builds a single dimension's bin edges from YAML::Node. More...
 
std::vector< double > BinRangeToBinEdges (YAML::Node const &bin_range)
 Converts a range (linspace/logspace) to a std::vector<double> More...
 
template<typename ObjectType >
std::unique_ptr< ObjectType > M3::Clone (const ObjectType *obj, const std::string &name="")
 KS: Creates a copy of a ROOT-like object and wraps it in a smart pointer. More...
 
TFile * M3::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. More...
 
void M3::ScaleHistogram (TH1 *Sample_Hist, const double scale)
 Scale histogram to get divided by bin width. More...
 
void M3::CheckBinningMatch (const TH1D *Hist1, const TH1D *Hist2, const std::string &File, const int Line)
 KS: Helper function check if data and MC binning matches. More...
 
void M3::CheckBinningMatch (const TH2D *Hist1, const TH2D *Hist2, const std::string &File, const int Line)
 KS: Helper function check if data and MC binning matches. More...
 
void M3::CheckBinningMatch (TH2Poly *Hist1, TH2Poly *Hist2, const std::string &File, const int Line)
 KS: Helper function check if data and MC binning matches. More...
 
YAML::Node M3::PolyToYaml (TH2Poly *Hist, const std::string &YamlName, const std::string &File, const int Line)
 KS: Convert TH2Poly into yaml config accepted by MaCh3. More...
 

Detailed Description

Author
Will Parker
Kamil Skwarczynski

Definition in file HistogramUtils.h.

Function Documentation

◆ BinRangeToBinEdges()

std::vector<double> BinRangeToBinEdges ( YAML::Node const &  bin_range)

Converts a range (linspace/logspace) to a std::vector<double>

Parameters
bin_rangeYaml node containing binning

Definition at line 653 of file HistogramUtils.cpp.

653  {
654 // ************************************************
655  bool is_lin = true;
656  YAML::Node bin_range_specifier;
657  if (bin_range["linspace"]) {
658  bin_range_specifier = bin_range["linspace"];
659  } else if (bin_range["logspace"]) {
660  is_lin = false;
661  bin_range_specifier = bin_range["logspace"];
662  } else {
663  std::stringstream ss;
664  ss << bin_range;
665  MACH3LOG_ERROR("When parsing binning, expected bin range specifier with "
666  "key linspace or logspace, but found,\n{}",
667  ss.str());
668  throw MaCh3Exception(__FILE__, __LINE__);
669  }
670 
671  auto nb = Get<int>(bin_range_specifier["nb"], __FILE__, __LINE__);
672  auto low = Get<double>(bin_range_specifier["low"], __FILE__, __LINE__);
673  auto up = Get<double>(bin_range_specifier["up"], __FILE__, __LINE__);
674 
675  std::vector<double> edges(nb + 1, low);
676  // force the last bin to be exactly as parsed to avoid numerical instabilities
677  // not quite lining back up with the end of the range, which could
678  // cause spurious errors or infinitesimally small bins for specifications
679  // like: [ { logspace: { nb: 10, 1E-1, 10}, 10, 11} ]
680  edges.back() = up;
681 
682  if (is_lin) {
683  double bw = (up - low) / nb;
684  for (int i = 0; i < (nb - 1); ++i) {
685  edges[i + 1] = edges[i] + bw;
686  }
687  } else {
688  double llow = std::log10(low);
689  double lup = std::log10(up);
690  double lbw = (lup - llow) / nb;
691  for (int i = 0; i < (nb - 1); ++i) {
692  edges[i + 1] = std::pow(10, llow + (i + 1) * lbw);
693  }
694  }
695 
696  return edges;
697 }
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:37
Custom exception class used throughout MaCh3.

◆ BuildBinEdgesFromNode()

std::vector<double> BuildBinEdgesFromNode ( YAML::Node const &  bin_edges_node,
bool &  found_range_specifier 
)

Builds a single dimension's bin edges from YAML::Node.

Parameters
bin_edges_nodeYaml node containing binning
found_range_specifierWhether or not a range specifier (linspace/logspace) was found

BinEdges: [ <dim0bin0lowedge>, <dim0bin1upedge>, <dim0bin2upedge>, ... <dim0binNupedge> ] BinEdges: { linspace: { nb: 100, low: 0, up: 10} } BinEdges: { logspace: { nb: 100, low: 1E-1, up: 10} } BinEdges: [ { linspace: { nb: 100, low: 0, up: 10} }, 10, 15, { logspace: { nb: 5, low: 15, up: 100} } ]

Definition at line 707 of file HistogramUtils.cpp.

708  {
709 // ************************************************
710  if (bin_edges_node.IsMap()) {
711  found_range_specifier = true;
712  return BinRangeToBinEdges(bin_edges_node);
713  }
714  std::vector<double> edges_builder;
715  if (!bin_edges_node.IsSequence()) {
716  std::stringstream ss;
717  ss << bin_edges_node;
719  "When parsing binning, expected to find a YAML map or sequence, "
720  "but found:\n{}",
721  ss.str());
722  throw MaCh3Exception(__FILE__, __LINE__);
723  }
724  for (auto const &it : bin_edges_node) {
725  if (it.IsScalar()) {
726  edges_builder.push_back(it.as<double>());
727  } else if (it.IsMap()) {
728  found_range_specifier = true;
729  auto range_edges = BinRangeToBinEdges(it);
730  std::copy(range_edges.begin(), range_edges.end(),
731  std::back_inserter(edges_builder));
732  } else {
733  std::stringstream ss;
734  ss << bin_edges_node;
736  "When parsing binning, expected elements in outer sequence to all be "
737  "either scalars or maps, but found:\n{}",
738  ss.str());
739  throw MaCh3Exception(__FILE__, __LINE__);
740  }
741  }
742 
743  // Check for duplicates or out-of-order bins
744  std::vector<double> edges;
745  for (size_t eb_it = 0; eb_it < edges_builder.size(); ++eb_it) {
746  if (edges.size()) {
747  if (edges_builder[eb_it] == edges.back()) { // remove duplicate edges
748  continue;
749  } else if (edges_builder[eb_it] < edges.back()) {
750  std::stringstream ss;
751  ss << "[ ";
752  for(auto const & e : edges_builder){
753  ss << fmt::format("{:.3g} ", e);
754  }
755  ss << "]";
757  "When parsing binning, found edges that were not monotonically "
758  "increasing, problem bin at index: {}:\n{}",
759  eb_it, ss.str());
760  throw MaCh3Exception(__FILE__, __LINE__);
761  }
762  }
763  edges.push_back(edges_builder[eb_it]);
764  }
765 
766  return edges;
767 }
std::vector< double > BinRangeToBinEdges(YAML::Node const &bin_range)
Converts a range (linspace/logspace) to a std::vector<double>

◆ CalculateEnu()

double CalculateEnu ( double  PLep,
double  cosTheta,
double  EB,
bool  neutrino 
)

Recalculate Enu after Eb shift. Takes in shifted lepton momentum, lepton angle, and binding energy change, and if nu/anu.

Parameters
PLepShifted outgoing lepton momentum (MeV/c).
cosThetaCosine of the lepton scattering angle.
EBBinding energy shift applied to the interaction (MeV).
neutrinoTrue if the interaction is neutrino, false if antineutrino.
Todo:
WARNING this is hardcoded

Definition at line 593 of file HistogramUtils.cpp.

593  {
594 // ***************************************************************************
595  double mNeff = 0.93956536 - Eb / 1000.;
596  double mNoth = 0.93827203;
597 
598  if (!neutrino) {
599  mNeff = 0.93827203 - Eb / 1000.;
600  mNoth = 0.93956536;
601  }
603  constexpr double mLep = 0.10565837;
604  constexpr double mLep2 = mLep * mLep;
605 
606  const double eLep = sqrt(PLep * PLep + mLep2);
607  double Enu = (2 * mNeff * eLep - mLep2 + mNoth * mNoth - mNeff * mNeff) /(2 * (mNeff - eLep + PLep * costh));
608 
609  return Enu;
610 }

◆ CalculateQ2()

double CalculateQ2 ( double  PLep,
double  PUpd,
double  EnuTrue,
double  InitialQ2 = 0.0 
)

Recalculate Q^2 after Eb shift. Takes in shifted lepton momentum, lepton angle, and true neutrino energy.

Parameters
PLepShifted outgoing lepton momentum (MeV/c).
PUpdUpdated lepton angle or related kinematic quantity used in the recalculation.
EnuTrueTrue neutrino energy (MeV).
InitialQ2Optional initial Q^2 value (used as seed or fallback, default = 0).

Definition at line 573 of file HistogramUtils.cpp.

573  {
574 // ***************************************************************************
575  constexpr double MLep = 0.10565837;
576  constexpr double MLep2 = MLep * MLep;
577 
578  // Calculate muon energy
579  double ELep = sqrt((MLep2)+(PLep*PLep));
580 
581  double CosTh = (2*EnuTrue*ELep - MLep2 - InitialQ2)/(2*EnuTrue*PLep);
582 
583  ELep = sqrt((MLep2)+(PUpd*PUpd));
584 
585  // Calculate the new Q2
586  double Q2Upd = -(MLep2) + 2.0*EnuTrue*(ELep - PUpd*CosTh);
587 
588  return Q2Upd - InitialQ2;
589 }

◆ CastVector()

template<typename Derived , typename Base >
std::vector<std::unique_ptr<Base> > CastVector ( std::vector< std::unique_ptr< Derived >> &&  inputVec)

Converts a vector of pointers from a derived type to a base type.

Template Parameters
DerivedThe derived class type.
BaseThe base class type.
Parameters
inputVecA std::vector of pointers to Derived objects.
Returns
A std::vector of pointers to Base objects.

Definition at line 94 of file HistogramUtils.h.

94  {
95  std::vector<std::unique_ptr<Base>> outputVec;
96  outputVec.reserve(inputVec.size());
97  for (auto& ptr : inputVec) {
98  outputVec.push_back(std::unique_ptr<Base>(std::move(ptr)));
99  }
100  return outputVec;
101 }

◆ CheckTH2PolyFileVersion()

void CheckTH2PolyFileVersion ( TFile *  file)

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.

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

Parameters
fileROOT file that we will make version checks

Definition at line 13 of file HistogramUtils.cpp.

13  {
14 // **************************************************
15  int FileROOTVersion = file->GetVersion();
16  int MainFileROOTVersion = FileROOTVersion;
17 
18  // Remove last digit from number
19  // till only one digit is left
20  while (MainFileROOTVersion >= 10)
21  MainFileROOTVersion /= 10;
22 
23  std::string SystemROOTVersion = std::string(ROOT_RELEASE);
24  int MainSystemROOTVersion = SystemROOTVersion.at(0) - '0';
25 
26  if(MainFileROOTVersion != MainSystemROOTVersion)
27  {
28  MACH3LOG_ERROR("File was produced with: {} ROOT version", FileROOTVersion);
29  MACH3LOG_ERROR("Found: {} ROOT version in the system", SystemROOTVersion);
30  MACH3LOG_ERROR("For some documentation please visit me");
31  throw MaCh3Exception(__FILE__, __LINE__);
32  }
33 }

◆ ConvertTH2DtoTH2Poly()

TH2Poly* ConvertTH2DtoTH2Poly ( TH2D *  TH2Dhist)

KS: Convert TH2Poly to TH2D.

Definition at line 284 of file HistogramUtils.cpp.

284  {
285 // ****************
286  // Make the x axis from the momentum of lepton
287  TAxis* xaxis = hist->GetXaxis();
288  // Make the y axis from the cos theta of lepton
289  TAxis* yaxis = hist->GetYaxis();
290 
291  TString histname = hist->GetName();
292  // Convert TH2D binning to TH2Poly
293  TH2Poly* poly = new TH2Poly();
294  poly->SetName(histname);
295  poly->SetTitle(histname);
296 
297  // Copy axis titles
298  poly->GetXaxis()->SetTitle(xaxis->GetTitle());
299  poly->GetYaxis()->SetTitle(yaxis->GetTitle());
300 
301  double xmax, xmin, ymax, ymin;
302  for (int iy = 1; iy <= yaxis->GetNbins(); iy++) {
303  ymax = yaxis->GetBinUpEdge(iy);
304  ymin = yaxis->GetBinLowEdge(iy);
305  for (int ix = 1; ix <= xaxis->GetNbins(); ix++) {
306  xmax = xaxis->GetBinUpEdge(ix);
307  xmin = xaxis->GetBinLowEdge(ix);
308  double binofx[] = {xmin, xmax, xmax, xmin};
309  double binofy[] = {ymin, ymin, ymax, ymax};
310  poly->AddBin(4, binofx, binofy);
311  }
312  }
313 
314  for (int iy = 1; iy <= yaxis->GetNbins(); iy++) {
315  ymax = yaxis->GetBinUpEdge(iy);
316  ymin = yaxis->GetBinLowEdge(iy);
317  for (int ix = 1; ix <= xaxis->GetNbins(); ix++) {
318  xmax = xaxis->GetBinUpEdge(ix);
319  xmin = xaxis->GetBinLowEdge(ix);
320 
321  // Get the content of the corresponding bin in TH2D and set it in TH2Poly
322  int bin = hist->GetBin(ix, iy);
323  double content = hist->GetBinContent(bin);
324  poly->SetBinContent(poly->FindBin((xmin + xmax) / 2, (ymin + ymax) / 2), content);
325  }
326  }
327 
328  return poly;
329 }

◆ ConvertTH2PolyToTH2D()

TH2D* ConvertTH2PolyToTH2D ( TH2Poly *  poly,
TH2D *  TH2Dhist 
)

KS: Convert TH2D to TH2Poly.

Definition at line 250 of file HistogramUtils.cpp.

250  {
251 // ****************
252  double xlow, xup, ylow, yup;
253  std::string HistTempName = poly->GetName();
254 
255  HistTempName += "_";
256  //make the th2d
257  TH2D *hist = static_cast<TH2D*>(h2dhist->Clone());
258  hist->SetNameTitle(HistTempName.c_str(), HistTempName.c_str());
259 
260  for(int ix = 0; ix < hist->GetNbinsX() + 2; ix++) {
261  for(int iy = 0; iy < hist->GetNbinsY() + 2; iy++) {
262  hist->SetBinContent(ix, iy, 0);
263  }
264  }
265  //Loop over poly bins, find the corresponding th2d and setbincontent!
266  for(int i = 0; i< poly->GetNumberOfBins(); i++){
267  TH2PolyBin & polybin = static_cast<TH2PolyBin &>(*poly->GetBins()->At(i));
268  xlow = polybin.GetXMin();
269  xup = polybin.GetXMax();
270  ylow = polybin.GetYMin();
271  yup = polybin.GetYMax();
272  int xbin, ybin;
273 
274  xbin = hist->GetXaxis()->FindBin(xlow+(xup-xlow)/2);
275  ybin = hist->GetYaxis()->FindBin(ylow+(yup-ylow)/2);
276 
277  MACH3LOG_TRACE("Poly bin {}, xlow: {}, xup: {}, ylow: {}, yup: {}. Finding bin for ({}, {}). Found Bin ({}, {}) with content {}. But Poly content: {}",
278  i, xlow, xup, ylow, yup, (xlow + (xup - xlow) / 2), (ylow + (yup - ylow) / 2), xbin, ybin, polybin.GetContent(), poly->GetBinContent(i));
279  hist->SetBinContent(xbin, ybin, polybin.GetContent());
280  }
281  return hist;
282 }
#define MACH3LOG_TRACE
Definition: MaCh3Logger.h:33

◆ FastViolinFill()

void FastViolinFill ( TH2D *  violin,
TH1D *  hist_1d 
)

KS: Fill Violin histogram with entry from a toy.

Parameters
violinhist that will be filled
hist_1drefence hist from which we take entries to be filled

Definition at line 551 of file HistogramUtils.cpp.

551  {
552 // ****************
553  for (int x = 0; x < violin->GetXaxis()->GetNbins(); ++x)
554  {
555  const int y = violin->GetYaxis()->FindBin(hist_1d->GetBinContent(x+1));
556  violin->SetBinContent(x+1, y, violin->GetBinContent(x+1, y)+1);
557  }
558 }

◆ file_exists()

std::string file_exists ( std::string  filename)
inline

Helper to check if files exist or not.

Definition at line 104 of file HistogramUtils.h.

104  {
105  std::ifstream infile(filename.c_str());
106  if (!infile.good()) {
107  MACH3LOG_ERROR("File {} does not exist", filename);
108  MACH3LOG_ERROR("Please try again");
109  throw MaCh3Exception(__FILE__ , __LINE__ );
110  }
111  return filename;
112 }

◆ GetRandomPoly2()

int GetRandomPoly2 ( const TH2Poly *  PolyHist)

KS: ROOT developers were too lazy do develop getRanom2 for TH2Poly, this implementation is based on link

Definition at line 504 of file HistogramUtils.cpp.

504  {
505 // ****************
506  const int nbins = PolyHist->GetNumberOfBins();
507  const double r1 = M3::rand::Uniform();;
508 
509  std::vector<double> fIntegral(nbins+2);
510  fIntegral[0] = 0.0;
511 
512  //KS: This is custom version of ComputeIntegral, once again ROOT was lazy :(
513  for (int i = 1; i < nbins+1; ++i)
514  {
515  fIntegral[i] = 0.0;
516  const double content = PolyHist->GetBinContent(i);
517  fIntegral[i] += fIntegral[i - 1] + content;
518  }
519  for (Int_t bin = 1; bin < nbins+1; ++bin) fIntegral[bin] /= fIntegral[nbins];
520  fIntegral[nbins+1] = PolyHist->GetEntries();
521 
522  //KS: We just return one rather then X and Y, this way we can use SetBinContent rather than Fill, which is faster
523  int iBin = int(TMath::BinarySearch(nbins, fIntegral.data(), r1));
524  //KS: Have to increment because TH2Poly has stupid offset arghh
525  iBin += 1;
526 
527  return iBin;
528 }
double Uniform(const double min=0.0, const double max=1.0)
Generate a uniform random number in [min, max).
Definition: Random.h:116

◆ MakeFluctuatedHistogramAlternative() [1/3]

void MakeFluctuatedHistogramAlternative ( TH1D *  FluctHist,
TH1D *  PolyHist 
)

Make Poisson fluctuation of TH1D hist using slow method which is only for cross-check.

Definition at line 468 of file HistogramUtils.cpp.

468  {
469 // ****************
470  // Make the Poisson fluctuated hist
471  FluctHist->Reset("");
472  FluctHist->Fill(0.0, 0.0);
473 
474  const double evrate = PolyHist->Integral();
475  const int num = M3::rand::Poisson(evrate);
476  int count = 0;
477  while(count < num)
478  {
479  const double candidate = PolyHist->GetRandom();
480  FluctHist->Fill(candidate);
481  count++;
482  }
483 }
int Poisson(const double mean)
Generate a Poisson-distributed integer with the given mean.
Definition: Random.h:122

◆ MakeFluctuatedHistogramAlternative() [2/3]

void MakeFluctuatedHistogramAlternative ( TH2D *  FluctHist,
TH2D *  PolyHist 
)

Make Poisson fluctuation of TH2D hist.

Definition at line 487 of file HistogramUtils.cpp.

487  {
488 // ****************
489  FluctHist->Reset();
490  FluctHist->Fill(0.0, 0.0, 0.0);
491 
492  const double evrate = PolyHist->Integral();
493  const int num = M3::rand::Poisson(evrate);
494 
495  double x, y;
496  for (int count = 0; count < num; ++count) {
497  PolyHist->GetRandom2(x, y);
498  FluctHist->Fill(x, y);
499  }
500 }

◆ MakeFluctuatedHistogramAlternative() [3/3]

void MakeFluctuatedHistogramAlternative ( TH2Poly *  FluctHist,
TH2Poly *  PolyHist 
)

Make Poisson fluctuation of TH2Poly hist using slow method which is only for cross-check.

Definition at line 532 of file HistogramUtils.cpp.

532  {
533 // ****************
534  // Make the Poisson fluctuated hist
535  FluctHist->Reset("");
536  FluctHist->Fill(0.0, 0.0, 0.0);
537 
538  const double evrate = NoOverflowIntegral(PolyHist);
539  const int num = M3::rand::Poisson(evrate);
540  int count = 0;
541  while(count < num)
542  {
543  const int iBin = GetRandomPoly2(PolyHist);
544  FluctHist->SetBinContent(iBin, FluctHist->GetBinContent(iBin) + 1);
545  count++;
546  }
547 }
int GetRandomPoly2(const TH2Poly *PolyHist)
KS: ROOT developers were too lazy do develop getRanom2 for TH2Poly, this implementation is based on l...
double NoOverflowIntegral(TH2Poly *poly)
WP: Helper function for calculating binned Integral of TH2Poly i.e not including overflow.

◆ MakeFluctuatedHistogramStandard() [1/3]

void MakeFluctuatedHistogramStandard ( TH1D *  FluctHist,
TH1D *  PolyHist 
)

Make Poisson fluctuation of TH1D hist using default fast method.

Definition at line 407 of file HistogramUtils.cpp.

407  {
408 // ****************
409  // Make the Poisson fluctuated hist
410  FluctHist->Reset("");
411  FluctHist->Fill(0.0, 0.0);
412 
413  for (int i = 1; i <= PolyHist->GetXaxis()->GetNbins(); ++i)
414  {
415  // Get the posterior predictive bin content
416  const double MeanContent = PolyHist->GetBinContent(i);
417  // Get a Poisson fluctuation of the content
418  const double Random = M3::rand::PoissonD(MeanContent);
419  // Set the fluctuated histogram content to the Poisson variation of the posterior predictive histogram
420  FluctHist->SetBinContent(i,Random);
421  }
422 }
double PoissonD(const double mean)
Generate a Poisson-distributed random number with the given mean.
Definition: Random.h:127

◆ MakeFluctuatedHistogramStandard() [2/3]

void MakeFluctuatedHistogramStandard ( TH2D *  FluctHist,
TH2D *  PolyHist 
)

Make Poisson fluctuation of TH2D hist using default fast method.

Definition at line 445 of file HistogramUtils.cpp.

445  {
446 // ****************
447  // Reset the histogram
448  FluctHist->Reset("");
449  FluctHist->Fill(0.0, 0.0, 0.0);
450 
451  // Loop over all bins
452  const int nBinsX = Hist->GetXaxis()->GetNbins();
453  const int nBinsY = Hist->GetYaxis()->GetNbins();
454  for (int ix = 1; ix <= nBinsX; ++ix) {
455  for (int iy = 1; iy <= nBinsY; ++iy) {
456  // Get the original bin content
457  const double MeanContent = Hist->GetBinContent(ix, iy);
458  // Generate Poisson fluctuation
459  const double Random = M3::rand::PoissonD(MeanContent);
460  // Set the Random content
461  FluctHist->SetBinContent(ix, iy, Random);
462  }
463  }
464 }

◆ MakeFluctuatedHistogramStandard() [3/3]

void MakeFluctuatedHistogramStandard ( TH2Poly *  FluctHist,
TH2Poly *  PolyHist 
)

Make Poisson fluctuation of TH2Poly hist using default fast method.

Definition at line 426 of file HistogramUtils.cpp.

426  {
427 // ****************
428  // Make the Poisson fluctuated hist
429  FluctHist->Reset("");
430  FluctHist->Fill(0.0, 0.0, 0.0);
431 
432  for (int i = 1; i < FluctHist->GetNumberOfBins()+1; ++i)
433  {
434  // Get the posterior predictive bin content
435  const double MeanContent = PolyHist->GetBinContent(i);
436  // Get a Poisson fluctuation of the content
437  const double Random = M3::rand::PoissonD(MeanContent);
438  // Set the fluctuated histogram content to the Poisson variation of the posterior predictive histogram
439  FluctHist->SetBinContent(i,Random);
440  }
441 }

◆ MakePolyHist()

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.

Parameters
nameThis will be title of output histogram
BinArray_xBin edges for X axis
BinArray_yBin edges for Y axis

Definition at line 372 of file HistogramUtils.cpp.

372  {
373 // *********************
374  TH2Poly* poly = new TH2Poly();
375  poly->SetName(name.c_str());
376  poly->SetTitle(name.c_str());
377  double xmax, xmin, ymax, ymin;
378  for(unsigned int iy = 0; iy < BinArray_y.size()-1; iy++)
379  {
380  ymax = BinArray_y[iy+1];
381  ymin = BinArray_y[iy];
382  for(unsigned int ix = 0; ix < BinArray_x.size()-1; ix++)
383  {
384  xmax = BinArray_x[ix+1];
385  xmin = BinArray_x[ix];
386  double binofx[] = {xmin, xmax, xmax, xmin};
387  double binofy[] = {ymin, ymin, ymax, ymax};
388  poly->AddBin(4,binofx,binofy);
389  }
390  }
391  return poly;
392 }

◆ MakeSummaryFromSpectra()

std::unique_ptr<TH1D> MakeSummaryFromSpectra ( const TH2D *  Spectra,
const std::string &  name 
)

Build a 1D posterior-predictive summary from a violin spectrum.

Parameters
SpectraInput TH2D violin/density histogram.
nameName of the output TH1D.

Definition at line 613 of file HistogramUtils.cpp.

614  {
615 // ***********************************************
616  const int nBinsX = Spectra->GetNbinsX();
617  // Reuse the exact x binning
618  std::vector<double> edges(nBinsX + 1);
619  for (int i = 0; i < nBinsX; ++i) {
620  edges[i] = Spectra->GetXaxis()->GetBinLowEdge(i+1);
621  }
622  edges[nBinsX] = Spectra->GetXaxis()->GetBinUpEdge(nBinsX);
623 
624  auto h1 = std::make_unique<TH1D>(name.c_str(), name.c_str(), nBinsX, edges.data());
625  h1->SetDirectory(nullptr);
626  h1->Sumw2(true);
627 
628  // ---- Loop X bins and extract Y distribution
629  for (int ix = 1; ix <= nBinsX; ++ix) {
630  // Project THIS x-bin onto Y
631  std::unique_ptr<TH1D> slice(Spectra->ProjectionY(Form("_py_%d", ix), ix, ix));
632  slice->SetDirectory(nullptr);
633  if (slice->GetEntries() == 0) {
634  h1->SetBinContent(ix, 0.0);
635  h1->SetBinError(ix, 0.0);
636  continue;
637  }
638 
639  const double mean = slice->GetMean();
640  const double rms = slice->GetRMS();
641 
642  h1->SetBinContent(ix, mean);
643  h1->SetBinError(ix, rms);
644  }
645 
646  h1->GetXaxis()->SetTitle(Spectra->GetXaxis()->GetTitle());
647  h1->GetYaxis()->SetTitle("Events");
648 
649  return h1;
650 }

◆ NoOverflowIntegral()

double NoOverflowIntegral ( TH2Poly *  poly)

WP: Helper function for calculating binned Integral of TH2Poly i.e not including overflow.

Definition at line 52 of file HistogramUtils.cpp.

52  {
53 // **************************************************
54  double integral = 0.;
55  for(int i = 1; i < poly->GetNumberOfBins()+1; i++)
56  {
57  integral += poly->GetBinContent(i);
58  }
59 
60  return integral;
61 } // end function

◆ NormalisePoly()

TH2Poly* NormalisePoly ( TH2Poly *  Histogram)

WP: Helper to Normalise histograms.

Definition at line 200 of file HistogramUtils.cpp.

200  {
201 // ****************
202  TH2Poly* HistCopy = static_cast<TH2Poly*>(Histogram->Clone());
203  double IntegralWidth = PolyIntegralWidth(HistCopy);
204  HistCopy = PolyScaleWidth(HistCopy, IntegralWidth);
205  std::string title = std::string(HistCopy->GetName())+"_norm";
206  HistCopy->SetNameTitle(title.c_str(), title.c_str());
207 
208  return HistCopy;
209 }
TH2Poly * PolyScaleWidth(TH2Poly *Histogram, double scale)
WP: Helper to scale th2poly analogous to th2d scale with option "width".
double PolyIntegralWidth(TH2Poly *Histogram)
WP: Helper to calc integral of th2poly analogous to th2d integra; with option "width".

◆ NormaliseTH2Poly()

void NormaliseTH2Poly ( TH2Poly *  Histogram)

Helper to Normalise histograms.

Parameters
Histogramhist which we normalise

Definition at line 213 of file HistogramUtils.cpp.

213  {
214 // ****************
215  const double Integral = NoOverflowIntegral(Histogram);
216  for(int j = 1; j < Histogram->GetNumberOfBins()+1; j++)
217  {
218  Histogram->SetBinContent(j, Histogram->GetBinContent(j)/Integral);
219  }
220 }

◆ OverflowIntegral()

double OverflowIntegral ( TH2Poly *  poly)

WP: Helper function for calculating unbinned Integral of TH2Poly i.e including overflow.

Definition at line 37 of file HistogramUtils.cpp.

37  {
38 // **************************************************
39  double overflow = 0.;
40  //TH2Polys have 9 overflow bins
41  for(int iOverflow = -1; iOverflow > -10; iOverflow--)
42  {
43  overflow += poly->GetBinContent(iOverflow);
44  }
45  double IntegralUn = NoOverflowIntegral(poly) + overflow;
46 
47  return IntegralUn;
48 } // end function

◆ PolyIntegralWidth()

double PolyIntegralWidth ( TH2Poly *  Histogram)

WP: Helper to calc integral of th2poly analogous to th2d integra; with option "width".

Definition at line 353 of file HistogramUtils.cpp.

353  {
354 // ****************
355  double integral = 0;
356  double xlow, xup, ylow, yup, area;
357 
358  for(int i = 1; i < Histogram->GetNumberOfBins()+1; i++)
359  {
360  TH2PolyBin* bin = static_cast<TH2PolyBin*>(Histogram->GetBins()->At(i - 1));
361  xlow = bin->GetXMin();
362  xup = bin->GetXMax();
363  ylow = bin->GetYMin();
364  yup = bin->GetYMax();
365  area = (xup-xlow)*(yup-ylow);
366  integral += Histogram->GetBinContent(i)*area;
367  }
368  return integral;
369 }

◆ PolyProjectionX()

TH1D* PolyProjectionX ( TObject *  poly,
const std::string &  TempName,
const std::vector< double > &  xbins,
const bool  computeErrors = false 
)

WP: Poly Projectors.

Definition at line 65 of file HistogramUtils.cpp.

65  {
66 // **************************************************
67  TH1D* hProjX = new TH1D((TempName+"_x").c_str(),(TempName+"_x").c_str(), int(xbins.size()-1), &xbins[0]);
68 
69  //KS: Temp Histogram to store error, use double as this is thread safe
70  std::vector<double> hProjX_Error(hProjX->GetXaxis()->GetNbins() + 1, 0.0);
71  double xlow, xup, frac = 0.;
72 
73  //loop over bins in the poly
74  for (int i = 0; i < static_cast<TH2Poly*>(poly)->GetNumberOfBins(); i++)
75  {
76  //get bin and its edges
77  TH2PolyBin* bin = static_cast<TH2PolyBin*>(static_cast<TH2Poly*>(poly)->GetBins()->At(i));
78  xlow = bin->GetXMin();
79  xup = bin->GetXMax();
80 
81  //Loop over projected bins, find fraction of poly bin in each
82  for(int dx = 0; dx < int(xbins.size()); dx++)
83  {
84  if(xbins[dx+1] <= xlow || xbins[dx] >= xup)
85  {
86  frac = 0;
87  }
88  else if(xbins[dx] <= xlow && xbins[dx+1] >= xup)
89  {
90  frac = 1;
91  }
92  else if(xbins[dx] <= xlow && xbins[dx+1] <= xup)
93  {
94  frac = (xbins[dx+1]-xlow)/(xup-xlow);
95  }
96  else if(xbins[dx] >= xlow && xbins[dx+1] >= xup)
97  {
98  frac = (xup-xbins[dx])/(xup-xlow);
99  }
100  else if(xbins[dx] >= xlow && xbins[dx+1] <= xup)
101  {
102  frac = (xbins[dx+1]-xbins[dx])/(xup-xlow);
103  }
104  else
105  {
106  frac = 0;
107  }
108  hProjX->SetBinContent(dx+1,hProjX->GetBinContent(dx+1)+frac*bin->GetContent());
109  //KS: Follow ROOT implementation and sum up the variance
110  if(computeErrors)
111  {
112  //KS: TH2PolyBin doesn't have GetError so we have to use TH2Poly,
113  //but numbering of GetBinError is different than GetBins...
114  const double Temp_Err = frac*static_cast<TH2Poly*>(poly)->GetBinError(i+1)*frac*static_cast<TH2Poly*>(poly)->GetBinError(i+1);
115  hProjX_Error[dx+1] += Temp_Err;
116  }
117  }
118  }
119  //KS: The error is sqrt(summed variance)) https://root.cern.ch/doc/master/TH2_8cxx_source.html#l02266
120  if(computeErrors)
121  {
122  for (int i = 1; i <= hProjX->GetXaxis()->GetNbins(); ++i)
123  {
124  const double Error = std::sqrt(hProjX_Error[i]);
125  hProjX->SetBinError(i, Error);
126  }
127  }
128  return hProjX;
129 } // end project poly X function

◆ PolyProjectionY()

TH1D* PolyProjectionY ( TObject *  poly,
const std::string &  TempName,
const std::vector< double > &  ybins,
const bool  computeErrors = false 
)

WP: Poly Projectors.

Definition at line 133 of file HistogramUtils.cpp.

133  {
134 // **************************************************
135  TH1D* hProjY = new TH1D((TempName+"_y").c_str(),(TempName+"_y").c_str(),int(ybins.size()-1),&ybins[0]);
136  //KS: Temp Histogram to store error, use double as this is thread safe
137  std::vector<double> hProjY_Error(hProjY->GetXaxis()->GetNbins() + 1, 0.0);
138  double ylow, yup, frac = 0.;
139 
140  //loop over bins in the poly
141  for (int i = 0; i < static_cast<TH2Poly*>(poly)->GetNumberOfBins(); i++)
142  {
143  //get bin and its edges
144  TH2PolyBin* bin = static_cast<TH2PolyBin*>(static_cast<TH2Poly*>(poly)->GetBins()->At(i));
145  ylow = bin->GetYMin();
146  yup = bin->GetYMax();
147 
148  //Loop over projected bins, find fraction of poly bin in each
149  for(int dy = 0; dy < int(ybins.size()); dy++)
150  {
151  if(ybins[dy+1]<=ylow || ybins[dy] >= yup)
152  {
153  frac = 0;
154  }
155  else if(ybins[dy] <= ylow && ybins[dy+1] >= yup)
156  {
157  frac = 1;
158  }
159  else if(ybins[dy] <= ylow && ybins[dy+1] <= yup)
160  {
161  frac = (ybins[dy+1]-ylow)/(yup-ylow);
162  }
163  else if(ybins[dy] >= ylow && ybins[dy+1] >= yup)
164  {
165  frac = (yup-ybins[dy])/(yup-ylow);
166  }
167  else if(ybins[dy] >= ylow && ybins[dy+1] <= yup)
168  {
169  frac = (ybins[dy+1]-ybins[dy])/(yup-ylow);
170  }
171  else
172  {
173  frac = 0;
174  }
175  hProjY->SetBinContent(dy+1,hProjY->GetBinContent(dy+1)+frac*bin->GetContent());
176  //KS: Follow ROOT implementation and sum up the variance
177  if(computeErrors)
178  {
179  //KS: TH2PolyBin doesn't have GetError so we have to use TH2Poly,
180  //but numbering of GetBinError is different than GetBins...
181  const double Temp_Err = frac*static_cast<TH2Poly*>(poly)->GetBinError(i+1)*frac*static_cast<TH2Poly*>(poly)->GetBinError(i+1);
182  hProjY_Error[dy+1] += Temp_Err;
183  }
184  }
185  }
186  //KS: The error is sqrt(summed variance)) https://root.cern.ch/doc/master/TH2_8cxx_source.html#l02266
187  if(computeErrors)
188  {
189  for (int i = 1; i <= hProjY->GetXaxis()->GetNbins(); ++i)
190  {
191  const double Error = std::sqrt(hProjY_Error[i]);
192  hProjY->SetBinError(i, Error);
193  }
194  }
195  return hProjY;
196 } // end project poly Y function

◆ PolyScaleWidth()

TH2Poly* PolyScaleWidth ( TH2Poly *  Histogram,
double  scale 
)

WP: Helper to scale th2poly analogous to th2d scale with option "width".

Definition at line 333 of file HistogramUtils.cpp.

333  {
334 // ****************
335  TH2Poly* HistCopy = static_cast<TH2Poly*>(Histogram->Clone());
336  double xlow, xup, ylow, yup, area;
337 
338  for(int i = 1; i < HistCopy->GetNumberOfBins()+1; i++)
339  {
340  TH2PolyBin* bin = static_cast<TH2PolyBin*>(Histogram->GetBins()->At(i - 1));
341  xlow = bin->GetXMin();
342  xup = bin->GetXMax();
343  ylow = bin->GetYMin();
344  yup = bin->GetYMax();
345  area = (xup-xlow)*(yup-ylow);
346  HistCopy->SetBinContent(i, Histogram->GetBinContent(i)/(area*scale));
347  }
348  return HistCopy;
349 }

◆ RatioHists()

template<class HistType >
HistType* RatioHists ( HistType *  NumHist,
HistType *  DenomHist 
)

Helper to make ratio histograms.

Definition at line 225 of file HistogramUtils.cpp.

225  {
226 // ****************
227  HistType *NumCopy = static_cast<HistType*>(NumHist->Clone());
228  std::string title = std::string(DenomHist->GetName()) + "_ratio";
229  NumCopy->SetNameTitle(title.c_str(), title.c_str());
230  NumCopy->Divide(DenomHist);
231 
232  return NumCopy;
233 }

◆ RatioPolys()

TH2Poly* RatioPolys ( TH2Poly *  NumPoly,
TH2Poly *  DenomPoly 
)

Helper to make ratio of TH2Polys.

Definition at line 237 of file HistogramUtils.cpp.

237  {
238 // ****************
239  TH2Poly *NumCopy = static_cast<TH2Poly*>(NumHist->Clone());
240  std::string title = std::string(DenomHist->GetName()) + "_ratio";
241  NumCopy->SetNameTitle(title.c_str(), title.c_str());
242 
243  for(int i = 1; i < NumCopy->GetNumberOfBins()+1; ++i) {
244  NumCopy->SetBinContent(i,NumHist->GetBinContent(i)/DenomHist->GetBinContent(i));
245  }
246  return NumCopy;
247 }

◆ RemoveFitter()

void RemoveFitter ( TH1D *  hist,
const std::string &  name 
)

KS: Remove fitted TF1 from hist to make comparison easier.

Definition at line 396 of file HistogramUtils.cpp.

396  {
397 // *********************
398  TList *listOfFunctions = hist->GetListOfFunctions();
399  TF1 *fitter = dynamic_cast<TF1*>(listOfFunctions->FindObject(name.c_str()));
400 
401  listOfFunctions->Remove(fitter);
402  delete fitter;
403 }

◆ returnCherenkovThresholdMomentum()

double returnCherenkovThresholdMomentum ( const int  PDG)

DB Get the Cherenkov momentum threshold in MeV.

Parameters
PDGPDG code of the particle for which the Cherenkov threshold is requested.

Definition at line 563 of file HistogramUtils.cpp.

563  {
564 // ****************
565  constexpr double refractiveIndex = 1.334; //DB From https://github.com/fiTQun/fiTQun/blob/646cf9c8ba3d4f7400bcbbde029d5ca15513a3bf/fiTQun_shared.cc#L757
566  double mass = M3::Utils::GetMassFromPDG(PDG)*1e3;
567  double momentumThreshold = mass/sqrt(refractiveIndex*refractiveIndex-1.);
568  return momentumThreshold;
569 }
constexpr double GetMassFromPDG(const int PDG)
Return mass for given PDG.