diff --git a/core/Particle.test.cpp b/core/Particle.test.cpp index c0932639..761b9402 100644 --- a/core/Particle.test.cpp +++ b/core/Particle.test.cpp @@ -8,6 +8,8 @@ #include "Particle.hpp" +#include "TDatabasePDG.h" + namespace { using namespace AnalysisTree; @@ -28,7 +30,7 @@ TEST(Particle, Basics) { EXPECT_EQ(particle.GetSize(), 0); EXPECT_EQ(particle.GetPid(), 211); - EXPECT_FLOAT_EQ(particle.GetMass(), 0.13957); + EXPECT_FLOAT_EQ(particle.GetMass(), TDatabasePDG::Instance()->GetParticle(211)->Mass()); } }// namespace diff --git a/infra/Chain.cpp b/infra/Chain.cpp index c5b7254c..cac31914 100644 --- a/infra/Chain.cpp +++ b/infra/Chain.cpp @@ -37,6 +37,7 @@ void Chain::InitChain() { TFileCollection fc("fc", "", filelists_[0].c_str()); this->AddFileInfoList(reinterpret_cast(fc.GetList())); + this->ls(); std::vector aliases; aliases.reserve(treenames_.size()); diff --git a/infra/Cuts.hpp b/infra/Cuts.hpp index 809bd246..5a43086c 100644 --- a/infra/Cuts.hpp +++ b/infra/Cuts.hpp @@ -52,24 +52,6 @@ class Cuts { void AddCuts(const std::vector& cuts); - // // Base case for variadic recursion (handles when there's just one argument left) - // template - // void AddCuts(const T& t) { - // AddCuts(t); // Call the appropriate overload for a single argument (like std::vector) - // } - // - // // Recursive case for variadic template (multiple arguments) - // template - // void AddCuts(const T& t, const Args&... args) { - // AddCuts(t); - // AddCuts(args...); - // } - // - // template // TODO this constructor hangs. Needs debugging - // Cuts(std::string name, Args... args) : name_(std::move(name)) { - // AddCuts(args...); - // } - /** * @brief Evaluates all SimpleCuts * @tparam T type of data-object associated with TTree @@ -107,6 +89,8 @@ class Cuts { ANALYSISTREE_ATTR_NODISCARD std::set GetBranchIds() const { return branch_ids_; } ANALYSISTREE_ATTR_NODISCARD const std::string& GetName() const { return name_; } + void SetName(const std::string& name) { name_ = name; } + std::vector& GetCuts() { return cuts_; } friend bool operator==(const Cuts& that, const Cuts& other); diff --git a/infra/HelperFunctions.hpp b/infra/HelperFunctions.hpp index 57c08a64..56b95afc 100644 --- a/infra/HelperFunctions.hpp +++ b/infra/HelperFunctions.hpp @@ -3,6 +3,7 @@ #include "SimpleCut.hpp" +#include #include #include @@ -16,15 +17,38 @@ inline std::string ToStringWithPrecision(const T a_value, const int n) { return out.str(); } -inline std::vector CreateSliceCuts(const std::vector& ranges, const std::string& cutNamePrefix, const std::string& branchFieldName) { +template +inline std::string ToStringWithSignificantFigures(const T a_value, const int n) { + if(a_value == 0) return "0"; + + const double dMag = std::log10(std::abs(a_value)); // scale of the a_value (e.g 1.* for 1.2345, 2.* for 12.345 etc) + const int iMag = static_cast(dMag-n+1 > 0 ? dMag-n+1 : dMag-n); + const T shifted_value = a_value/std::pow(10, iMag); // shift decimal point to have all required digits to l.h.s. from it + const T rounded_value = static_cast(std::round(shifted_value)); // get rid of r.h.s. from decimal point + const T reshifted_value = rounded_value*std::pow(10, iMag); // return decimal point to its original place + const int precision = iMag < 0 ? -iMag : 0; // determine how many digits after decimal point one needs + return ToStringWithPrecision(reshifted_value, precision); +} + +inline std::vector CreateRangeCuts(const std::vector& ranges, const std::string& cutNamePrefix, const std::string& branchFieldName, int precision=2) { std::vector sliceCuts; for (int iRange = 0; iRange < ranges.size() - 1; iRange++) { - const std::string cutName = cutNamePrefix + ToStringWithPrecision(ranges.at(iRange), 2) + "_" + ToStringWithPrecision(ranges.at(iRange + 1), 2); + const std::string cutName = cutNamePrefix + ToStringWithPrecision(ranges.at(iRange), 2) + "_" + ToStringWithPrecision(ranges.at(iRange + 1), precision); sliceCuts.emplace_back(AnalysisTree::RangeCut(branchFieldName, ranges.at(iRange), ranges.at(iRange + 1), cutName)); } return sliceCuts; } +inline std::vector CreateEqualCuts(const std::vector& values, const std::string& cutNamePrefix, const std::string& branchFieldName, int precision=2) { + std::vector sliceCuts; + for (int iValue = 0; iValue < values.size(); iValue++) { + const std::string cutName = cutNamePrefix + ToStringWithPrecision(values.at(iValue), precision); + sliceCuts.emplace_back(AnalysisTree::EqualsCut(branchFieldName, values.at(iValue), cutName)); + } + + return sliceCuts; +} + }// namespace HelperFunctions #endif// ANALYSISTREE_INFRA_HELPER_FUNCTIONS_HPP diff --git a/infra/SimpleCut.cpp b/infra/SimpleCut.cpp index 50db3a2b..29302b46 100644 --- a/infra/SimpleCut.cpp +++ b/infra/SimpleCut.cpp @@ -3,6 +3,8 @@ Authors: Viktor Klochkov, Ilya Selyuzhenkov */ #include "SimpleCut.hpp" +#include "HelperFunctions.hpp" + #include namespace AnalysisTree { @@ -22,7 +24,9 @@ bool operator==(const SimpleCut& that, const SimpleCut& other) { if (&that == &other) { return true; } - return that.vars_ == other.vars_ && that.title_ == other.title_; + // if both SimpleCuts were defined via lambda, they're assumed not equal (unless they're in the same memory place) + if(that.hash_ == 1 && other.hash_ == 1) return false; + return that.vars_ == other.vars_ && that.title_ == other.title_ && that.hash_ == other.hash_; } SimpleCut RangeCut(const std::string& variable_name, double lo, double hi, const std::string& title) { @@ -45,12 +49,18 @@ SimpleCut::SimpleCut(const Variable& var, int value, std::string title) : title_ vars_.emplace_back(var); lambda_ = [value](std::vector& vars) { return vars[0] <= value + SmallNumber && vars[0] >= value - SmallNumber; }; FillBranchNames(); + const std::string stringForHash = var.GetName() + HelperFunctions::ToStringWithPrecision(value, 6) + title_; + std::hash hasher; + hash_ = hasher(stringForHash); } SimpleCut::SimpleCut(const Variable& var, double min, double max, std::string title) : title_(std::move(title)) { vars_.emplace_back(var); lambda_ = [max, min](std::vector& vars) { return vars[0] <= max && vars[0] >= min; }; FillBranchNames(); + const std::string stringForHash = var.GetName() + HelperFunctions::ToStringWithPrecision(min, 6) + HelperFunctions::ToStringWithPrecision(max, 6) + title_; + std::hash hasher; + hash_ = hasher(stringForHash); } bool SimpleCut::Apply(std::vector& bch, std::vector& id) const { diff --git a/infra/SimpleCut.hpp b/infra/SimpleCut.hpp index 7f1f32db..1e9171cd 100644 --- a/infra/SimpleCut.hpp +++ b/infra/SimpleCut.hpp @@ -41,6 +41,7 @@ class SimpleCut { [](const std::string& arg_name) { return Variable::FromString(arg_name); }); FillBranchNames(); + hash_ = 1; // Impossible to calculate for lambda_ } SimpleCut(const std::vector& vars, std::function&)> lambda, std::string title = "") : title_(std::move(title)), @@ -49,6 +50,7 @@ class SimpleCut { vars_.emplace_back(var); } FillBranchNames(); + hash_ = 1; // Impossible to calculate for lambda_ } /** @@ -121,6 +123,7 @@ class SimpleCut { std::vector vars_{}; std::set branch_names_{}; std::function&)> lambda_;///< function used to evaluate the cut. + size_t hash_; ClassDef(SimpleCut, 1); }; diff --git a/infra/SimpleCut.test.cpp b/infra/SimpleCut.test.cpp index 11419070..9bfc05d6 100644 --- a/infra/SimpleCut.test.cpp +++ b/infra/SimpleCut.test.cpp @@ -7,10 +7,58 @@ #include "SimpleCut.hpp" #include +#include + namespace { using namespace AnalysisTree; +TEST(SimpleCut, Basics) { + SimpleCut ecut1 = EqualsCut(Variable::FromString("BranchName.FieldName"), 1); + SimpleCut ecut1same = EqualsCut(Variable::FromString("BranchName.FieldName"), 1); + SimpleCut ecut2 = EqualsCut(Variable::FromString("BranchName.FieldName"), 2); + SimpleCut ecut3 = EqualsCut(Variable::FromString("BranchName3.FieldName3"), 1); + SimpleCut ecut1copy = ecut1; + SimpleCut& ecut1ref = ecut1; + + EXPECT_TRUE(ecut1 == ecut1); + EXPECT_TRUE(ecut1 == ecut1same); + EXPECT_TRUE(ecut1 == ecut1copy); + EXPECT_TRUE(ecut1 == ecut1ref); + EXPECT_FALSE(ecut1 == ecut2); + EXPECT_FALSE(ecut1 == ecut3); + EXPECT_FALSE(ecut2 == ecut3); + + SimpleCut rcut1 = RangeCut(Variable::FromString("BranchName.FieldName"), 1, 2); + SimpleCut rcut1same = RangeCut(Variable::FromString("BranchName.FieldName"), 1, 2); + SimpleCut rcut2 = RangeCut(Variable::FromString("BranchName.FieldName"), 2, 5); + SimpleCut rcut3 = RangeCut(Variable::FromString("BranchName3.FieldName3"), 1, 2); + SimpleCut rcut1copy = rcut1; + SimpleCut& rcut1ref = rcut1; + + EXPECT_TRUE(rcut1 == rcut1); + EXPECT_TRUE(rcut1 == rcut1same); + EXPECT_TRUE(rcut1 == rcut1copy); + EXPECT_TRUE(rcut1 == rcut1ref); + EXPECT_FALSE(rcut1 == rcut2); + EXPECT_FALSE(rcut1 == rcut3); + EXPECT_FALSE(rcut2 == rcut3); + + SimpleCut lcut1 = SimpleCut((std::vector){"B1.f1", "B2.f2", "B3.f3"}, [](std::vector par){ return par[0]/par[1]*par[2] < 10; }); + SimpleCut lcut1same = SimpleCut((std::vector){"B1.f1", "B2.f2", "B3.f3"}, [](std::vector par){ return par[0]/par[1]*par[2] < 10; }); + SimpleCut lcut2 = SimpleCut((std::vector){"B11.f11", "B22.f22", "B33.f33"}, [](std::vector par){ return par[0]/par[1]*par[2] < 5; }); + SimpleCut lcut1copy = lcut1; + SimpleCut& lcut1ref = lcut1; + + EXPECT_TRUE(lcut1 == lcut1); + EXPECT_FALSE(lcut1 == lcut1same); // it should not be like that, but this is a concession + EXPECT_FALSE(lcut1 == lcut1copy); // it should not be like that, but this is a concession + EXPECT_TRUE(lcut1 == lcut1ref); + EXPECT_FALSE(lcut1 == lcut2); + EXPECT_FALSE(lcut1 == ecut1); + EXPECT_FALSE(lcut1 == rcut1); +} + } #endif//ANALYSISTREE_INFRA_SIMPLECUT_TEST_HPP_