1#ifndef ANALYSISTREE_INFRA_HELPER_FUNCTIONS_HPP
2#define ANALYSISTREE_INFRA_HELPER_FUNCTIONS_HPP
4#include "SimpleCut.hpp"
13namespace HelperFunctions {
16inline std::string ToStringWithPrecision(
const T a_value,
const int n) {
17 std::ostringstream out;
19 out << std::fixed << a_value;
24inline std::string ToStringWithSignificantFigures(
const T a_value,
const int n) {
25 if (a_value == 0)
return "0";
27 const double dMag = std::log10(std::abs(a_value));
28 const int iMag =
static_cast<int>(dMag - n + 1 > 0 ? dMag - n + 1 : dMag - n);
29 const T shifted_value = a_value / std::pow(10, iMag);
30 const T rounded_value =
static_cast<T
>(std::round(shifted_value));
31 const T reshifted_value = rounded_value * std::pow(10, iMag);
32 const int precision = iMag < 0 ? -iMag : 0;
33 return ToStringWithPrecision(reshifted_value, precision);
36inline std::vector<AnalysisTree::SimpleCut> CreateRangeCuts(
const std::vector<float>& ranges,
const std::string& cutNamePrefix,
const std::string& branchFieldName,
bool isAppendWithOpenCut =
false,
int precision = -1) {
37 auto checkHasFractionalPart = [](
float value) {
38 float fracPart = std::round(value) - value;
39 return std::abs(fracPart) > 1e-4;
42 auto countDigisAfterComma = [&](
float value) {
44 while (checkHasFractionalPart(value)) {
52 auto evaluateMaxDigisAfterComma = [&](
const std::vector<float>& vec) {
54 for (
const auto& v : vec) {
55 result = std::max(result, countDigisAfterComma(v));
61 if (precision < 0) precision = evaluateMaxDigisAfterComma(ranges);
63 std::vector<AnalysisTree::SimpleCut> sliceCuts;
64 for (
int iRange = 0; iRange < static_cast<int>(ranges.size()) - 1; iRange++) {
65 const std::string cutName = cutNamePrefix + ToStringWithPrecision(ranges.at(iRange), precision) +
"_" + ToStringWithPrecision(ranges.at(iRange + 1), precision);
66 sliceCuts.emplace_back(
AnalysisTree::RangeCut(branchFieldName, ranges.at(iRange), ranges.at(iRange + 1), cutName));
69 if (isAppendWithOpenCut) sliceCuts.emplace_back(
AnalysisTree::OpenCut(branchFieldName.substr(0, branchFieldName.find(
'.'))));
74inline std::vector<AnalysisTree::SimpleCut> CreateEqualCuts(
const std::vector<int>& values,
const std::string& cutNamePrefix,
const std::string& branchFieldName) {
75 std::vector<AnalysisTree::SimpleCut> sliceCuts;
76 for (
const auto& value : values) {
77 const std::string cutName = cutNamePrefix + std::to_string(value);
84inline bool StringToBool(
const std::string& str) {
85 if (str ==
"true")
return true;
86 else if (str ==
"false")
89 throw std::runtime_error(
"HelperFunctions::StringToBool(): argument must be either true or false");
93inline std::vector<T> MergeVectors(
const std::vector<T>& vec1,
const std::vector<T>& vec2) {
94 std::vector<T> result;
95 result.reserve(vec1.size() + vec2.size());
96 result.insert(result.end(), vec1.begin(), vec1.end());
97 result.insert(result.end(), vec2.begin(), vec2.end());
102template<
typename T,
typename... Args>
103inline std::vector<T> MergeVectors(
const std::vector<T>& vec1,
const std::vector<T>& vec2,
const Args&... args) {
104 return MergeVectors(vec1, MergeVectors(vec2, args...));
107inline TFile* OpenFileWithNullptrCheck(
const std::string& fileName,
const std::string& option =
"read") {
108 TFile* file = TFile::Open(fileName.c_str(), option.c_str());
109 if (file ==
nullptr) {
110 throw std::runtime_error(
"HelperFunctions::OpenFileWithNullptrCheck() - file " + fileName +
" is missing");
116inline T* GetObjectWithNullptrCheck(TFile* fileIn,
const std::string& objectName) {
117 T* ptr = fileIn->Get<T>(objectName.c_str());
118 if (ptr ==
nullptr) {
119 throw std::runtime_error(
"HelperFunctions::GetObjectWithNullptrCheck() - object " + objectName +
" in file " + fileIn->GetName() +
" is missing");
124inline void CheckHistogramsForXaxisIdentity(
const TH1* h1,
const TH1* h2) {
125 if (h1->GetNbinsX() != h2->GetNbinsX()) {
126 throw std::runtime_error(
"HelperFunctions::CheckHistogramsForXaxisIdentity(): nBinsX do not match for " +
static_cast<std::string
>(h1->GetName()) +
" and " + h2->GetName());
128 const int nBins = h1->GetNbinsX();
129 for (
int iBin = 1; iBin <= nBins; iBin++) {
130 if (std::abs(h1->GetBinCenter(iBin) - h2->GetBinCenter(iBin)) > 1e-6) {
131 throw std::runtime_error(
"HelperFunctions::CheckHistogramsForXaxisIdentity(): bins do not coincide for " +
static_cast<std::string
>(h1->GetName()) +
" and " + h2->GetName());
136inline void Sumw2IfNotYet(TH1* histo,
bool value =
true) {
137 const bool isSumw2Already = histo->GetSumw2N() > 0;
138 if (isSumw2Already != value) histo->Sumw2(value);
141inline TH1* MergeHistograms(
const std::vector<TH1*>& histos) {
143 for(
const auto& h : histos) {
144 CheckHistogramsForXaxisIdentity(h, histos.at(0));
145 isSumw2 |= h->GetSumw2N() > 0;
148 TH1* hResult =
dynamic_cast<TH1*
>(histos.at(0)->Clone(
"hMerged"));
149 Sumw2IfNotYet(hResult);
150 hResult->SetDirectory(
nullptr);
151 for(
size_t iH = 1, nHs = histos.size(); iH < nHs; ++iH) {
152 hResult->Add(histos.at(iH));
154 Sumw2IfNotYet(hResult, isSumw2);
159inline TH1* MergeHistograms(TFile* fileIn,
const std::vector<std::string>& histoNames) {
160 std::vector<TH1*> histos;
161 for (
const auto& hN : histoNames) {
162 histos.emplace_back(GetObjectWithNullptrCheck<TH1>(fileIn, hN));
164 TH1* hResult = MergeHistograms(histos);
170inline TDirectory* MkDirIfNotExists(T* fileOrDirectory,
const std::string& name) {
171 if (fileOrDirectory ==
nullptr)
throw std::runtime_error(
"HelperFunctions::MkDirIfNotExists(): file or directory ptr is null");
172 TDirectory* result = fileOrDirectory->GetDirectory(name.c_str());
173 if (result ==
nullptr) fileOrDirectory->mkdir(name.c_str());
174 result = fileOrDirectory->GetDirectory(name.c_str());
179inline void CD(T* fileOrDirectory,
const std::string& name) {
180 auto destination = MkDirIfNotExists(fileOrDirectory, name);
184inline double InterpolateTH1SuppressWarning(
const TH1* h,
double value) {
186 if (value <= h->GetBinLowEdge(1) || value >= h->GetBinLowEdge(h->GetNbinsX() + 1)) result = 0.;
188 result = h->Interpolate(value);
SimpleCut EqualsCut(const std::string &variable_name, int value, const std::string &title)
Definition SimpleCut.cpp:34
SimpleCut RangeCut(const std::string &variable_name, double lo, double hi, const std::string &title)
Definition SimpleCut.cpp:30
SimpleCut OpenCut(const std::string &branchName)
Definition SimpleCut.cpp:46