diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d8dd6ae..e82fa37 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -13,8 +13,13 @@ if(PROJECT_LINK_DIRECTORIES) link_directories(${PROJECT_LINK_DIRECTORIES}) endif() -add_executable(example example.cpp) -add_dependencies(example AnalysisTreeQA) -target_link_libraries(example ${ROOT_LIBRARIES} AnalysisTreeQA AnalysisTreeBase AnalysisTreeInfra) +set(EXECUTABLES example + ) -install (TARGETS example RUNTIME DESTINATION bin) \ No newline at end of file +foreach(EXE ${EXECUTABLES}) + add_executable(${EXE} ${EXE}.cpp) + add_dependencies(${EXE} AnalysisTreeQA) + target_link_libraries(${EXE} ${ROOT_LIBRARIES} AnalysisTreeQA AnalysisTreeBase AnalysisTreeInfra) + install (TARGETS ${EXE} RUNTIME DESTINATION bin) + install (FILES ${EXE}.cpp DESTINATION share) +endforeach() diff --git a/examples/example.cpp b/examples/example.cpp index e9e43f0..913e99c 100644 --- a/examples/example.cpp +++ b/examples/example.cpp @@ -64,7 +64,7 @@ void example(const std::string& filelist){ //Integral plot 1D SimpleCut vtx_chi2_track_cut = RangeCut({"VtxTracks.vtx_chi2"}, 0, 3); SimpleCut nhits_cut = RangeCut({"VtxTracks.nhits"}, 4, 100); - SimpleCut chi2_cut({"VtxTracks.chi2", "VtxTracks.ndf"}, [](std::vector par){ return par[0]/par[1] < 10; }); + SimpleCut chi2_cut((std::vector){"VtxTracks.chi2", "VtxTracks.ndf"}, [](std::vector par){ return par[0]/par[1] < 10; }); SimpleCut eta_cut = RangeCut({"VtxTracks.eta"}, 0, 3); Cuts* vertex_tracks_cuts = new Cuts("GoodCentralityTracks", {vtx_chi2_track_cut, nhits_cut, chi2_cut, eta_cut}); task->AddIntegral({"Multiplicity", Variable::FromString("VtxTracks.ones"), {1000, 0, 1000}}, vertex_tracks_cuts); diff --git a/src/EntryConfig.cpp b/src/EntryConfig.cpp index ce01a01..4ac232f 100644 --- a/src/EntryConfig.cpp +++ b/src/EntryConfig.cpp @@ -13,8 +13,7 @@ using TH1FD = TH1F; using TH2FD = TH2F; #endif -namespace AnalysisTree { -namespace QA { +namespace AnalysisTree::QA { struct fill2_struct : public Utils::Visitor { fill2_struct(double val1, double val2) : val1_(val1), val2_(val2) {} @@ -32,13 +31,6 @@ struct fill3_struct : public Utils::Visitor { double val1_, val2_, val3_; }; -struct write_struct : public Utils::Visitor { - explicit write_struct(std::string n) : name_(std::move(n)) {} - template - void operator()(PlotType* p) const { p->Write(name_.c_str()); } - std::string name_; -}; - EntryConfig::EntryConfig(const Axis& axis, Variable& weight, const std::string& name, Cuts* cuts, bool is_integral) : name_(name == "" ? axis.GetName() : name), type_(is_integral ? PlotType::kIntegral1D : PlotType::kHisto1D), @@ -138,8 +130,8 @@ void EntryConfig::InitPlot() { } void EntryConfig::Set2DName(const std::string& name) { - name_ = name == "" ? Form("%s_%s", axes_[0].GetName(), axes_[1].GetName()) : name; - if (name == "") { + name_ = name.empty() ? Form("%s_%s", axes_[0].GetName(), axes_[1].GetName()) : name; + if (name.empty()) { if (entry_cuts_ != nullptr) name_ += "_" + entry_cuts_->GetName(); @@ -161,12 +153,6 @@ void EntryConfig::Fill(double value1, double value2, double value3) { ANALYSISTREE_UTILS_VISIT(fill3_struct(value1, value2, value3), plot_); } -void EntryConfig::Write() const { - assert(out_dir_); - out_dir_->cd(); - ANALYSISTREE_UTILS_VISIT(write_struct(name_), plot_); -} - void EntryConfig::Fill(double value) { ANALYSISTREE_UTILS_GET(plot_)->Fill(value); } std::string EntryConfig::GetDirectoryName() const { @@ -186,9 +172,7 @@ std::string EntryConfig::GetDirectoryName() const { if (!var4weight_.GetName().empty() && var4weight_.GetFields().at(0).GetName() != "ones") { name += "_weight_" + var4weight_.GetName(); } - if (!toplevel_dir_name_.empty()) name.insert(0, toplevel_dir_name_ + "/"); return name; } -}// namespace QA -}// namespace AnalysisTree \ No newline at end of file +} // namespace AnalysisTree::QA diff --git a/src/EntryConfig.hpp b/src/EntryConfig.hpp index 3adea8f..46269ef 100644 --- a/src/EntryConfig.hpp +++ b/src/EntryConfig.hpp @@ -5,16 +5,14 @@ #include #include +#include +#include +#include #include "AnalysisTree/Cuts.hpp" #include "AnalysisTree/Utils.hpp" -class TH1; -class TH2; -class TProfile; - -namespace AnalysisTree { -namespace QA { +namespace AnalysisTree::QA { class Axis : public Variable, public TAxis { public: @@ -59,12 +57,8 @@ class EntryConfig { void Fill(double value); void Fill(double value1, double value2); void Fill(double value1, double value2, double value3); - void Write() const; - - ANALYSISTREE_ATTR_NODISCARD const std::vector& GetAxes() const { return axes_; } - std::vector& Axes() { return axes_; } - ANALYSISTREE_ATTR_NODISCARD unsigned int GetNdimentions() const { return axes_.size(); } + ANALYSISTREE_ATTR_NODISCARD unsigned int GetNdimensions() const { return axes_.size(); } ANALYSISTREE_ATTR_NODISCARD Cuts* GetEntryCuts() const { return entry_cuts_; } ANALYSISTREE_ATTR_NODISCARD PlotType GetType() const { return type_; } @@ -85,12 +79,10 @@ class EntryConfig { ANALYSISTREE_ATTR_NODISCARD std::string GetDirectoryName() const; - void SetOutDir(TDirectory* out_dir) { out_dir_ = out_dir; } - - void SetTopLevelDirName(const std::string& name) { toplevel_dir_name_ = name; } - PlotPointer GetPlot() { return plot_; } + const std::string& GetName() const { return name_; } + protected: void InitPlot(); ANALYSISTREE_ATTR_NODISCARD TH1* CreateHisto1D() const; @@ -107,12 +99,9 @@ class EntryConfig { Variable var4weight_{}; Cuts* entry_cuts_{nullptr}; std::vector> vars_id_{}; - std::string toplevel_dir_name_{""}; - TDirectory* out_dir_{nullptr}; ClassDef(EntryConfig, 1); }; -}// namespace QA -}// namespace AnalysisTree +}// namespace AnalysisTree::QA #endif//ANALYSISTREE_QA_ENTRYCONFIG_H diff --git a/src/Task.cpp b/src/Task.cpp index 325d1e3..5bb24f7 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -1,10 +1,86 @@ #include "Task.hpp" -namespace AnalysisTree { -namespace QA { +#include + +namespace AnalysisTree::QA { + +size_t Task::AddH1(const std::string& name, const Axis& x, Cuts* cuts, Variable weight) { + CreateOutputFileIfNotYet(); + weight.IfEmptyVariableConvertToOnes(x); + entries_.emplace_back(x, weight, name, cuts, false); + TDirectory* dir = MkMultiLevelDir(out_file_, toplevel_dir_name_ + "/" + entries_.back().GetDirectoryName()); + ANALYSISTREE_UTILS_VISIT(setdirectory_struct(dir), entries_.back().GetPlot()); + ANALYSISTREE_UTILS_VISIT(setname_struct(entries_.back().GetName()), entries_.back().GetPlot()); + auto var_id = AddEntry(AnalysisEntry(entries_.back().GetVariables(), entries_.back().GetEntryCuts(), entries_.back().GetVariableForWeight())); + entries_.back().SetVariablesId({{var_id.first, var_id.second.at(0)}}); + return entries_.size() - 1; +} -void Task::FillIntegral(EntryConfig& plot) { +size_t Task::AddH1(const Axis& x, Cuts* cuts, Variable weight) { + return AddH1("", x, cuts, std::move(weight)); +} + +size_t Task::AddH2(const std::string& name, const Axis& x, const Axis& y, Cuts* cuts, Variable weight) { + CreateOutputFileIfNotYet(); + weight.IfEmptyVariableConvertToOnes(x); + entries_.emplace_back(x, y, weight, name, cuts); + TDirectory* dir = MkMultiLevelDir(out_file_, toplevel_dir_name_ + "/" + entries_.back().GetDirectoryName()); + ANALYSISTREE_UTILS_VISIT(setdirectory_struct(dir), entries_.back().GetPlot()); + ANALYSISTREE_UTILS_VISIT(setname_struct(entries_.back().GetName()), entries_.back().GetPlot()); + auto var_id = AddEntry(AnalysisEntry(entries_.back().GetVariables(), entries_.back().GetEntryCuts(), entries_.back().GetVariableForWeight())); + entries_.back().SetVariablesId({{var_id.first, var_id.second.at(0)}, {var_id.first, var_id.second.at(1)}}); + return entries_.size() - 1; +} + +size_t Task::AddH2(const Axis& x, const Axis& y, Cuts* cuts, Variable weight) { + return AddH2("", x, y, cuts, std::move(weight)); +} + +size_t Task::AddProfile(const std::string& name, const Axis& x, const Axis& y, Cuts* cuts, Variable weight) { + CreateOutputFileIfNotYet(); + weight.IfEmptyVariableConvertToOnes(x); + entries_.emplace_back(x, y, weight, name, cuts, true); + TDirectory* dir = MkMultiLevelDir(out_file_, toplevel_dir_name_ + "/" + entries_.back().GetDirectoryName()); + ANALYSISTREE_UTILS_VISIT(setdirectory_struct(dir), entries_.back().GetPlot()); + ANALYSISTREE_UTILS_VISIT(setname_struct(entries_.back().GetName()), entries_.back().GetPlot()); + auto var_id = AddEntry(AnalysisEntry(entries_.back().GetVariables(), entries_.back().GetEntryCuts(), entries_.back().GetVariableForWeight())); + entries_.back().SetVariablesId({{var_id.first, var_id.second.at(0)}, {var_id.first, var_id.second.at(1)}}); + return entries_.size() - 1; +} +size_t Task::AddProfile(const Axis& x, const Axis& y, Cuts* cuts, Variable weight) { + return AddProfile("", x, y, cuts, std::move(weight)); +} + +size_t Task::AddIntegral(const std::string& name, const Axis& x, Cuts* cuts, Variable weight) { + CreateOutputFileIfNotYet(); + weight.IfEmptyVariableConvertToOnes(x); + entries_.emplace_back(x, weight, name, cuts, true); + TDirectory* dir = MkMultiLevelDir(out_file_, toplevel_dir_name_ + "/" + entries_.back().GetDirectoryName()); + ANALYSISTREE_UTILS_VISIT(setdirectory_struct(dir), entries_.back().GetPlot()); + ANALYSISTREE_UTILS_VISIT(setname_struct(entries_.back().GetName()), entries_.back().GetPlot()); + auto var_id = AddEntry(AnalysisEntry(entries_.back().GetVariables(), entries_.back().GetEntryCuts(), entries_.back().GetVariableForWeight())); + entries_.back().SetVariablesId({{var_id.first, var_id.second.at(0)}}); + return entries_.size() - 1; +} + +size_t Task::AddIntegral(const Axis& x, Cuts* cuts, Variable weight) { + return AddIntegral("", x, cuts, std::move(weight)); +} + +size_t Task::AddIntegral(const Axis& x, const Axis& y, Cuts* cuts_x, Cuts* cuts_y) { + CreateOutputFileIfNotYet(); + entries_.emplace_back(x, cuts_x, y, cuts_y); + TDirectory* dir = MkMultiLevelDir(out_file_, toplevel_dir_name_ + "/" + entries_.back().GetDirectoryName()); + ANALYSISTREE_UTILS_VISIT(setdirectory_struct(dir), entries_.back().GetPlot()); + ANALYSISTREE_UTILS_VISIT(setname_struct(entries_.back().GetName()), entries_.back().GetPlot()); + auto var_id_x = AddEntry(AnalysisEntry({entries_.back().GetVariables()[0]}, cuts_x)); + auto var_id_y = AddEntry(AnalysisEntry({entries_.back().GetVariables()[1]}, cuts_y)); + entries_.back().SetVariablesId({{var_id_x.first, var_id_x.second.at(0)}, {var_id_y.first, var_id_y.second.at(0)}}); + return entries_.size() - 1; +} + +void Task::FillIntegral(EntryConfig& plot) { double integral_x{0.}; double integral_y{0.}; auto var_ids = plot.GetVariablesId(); @@ -12,12 +88,12 @@ void Task::FillIntegral(EntryConfig& plot) { for (const auto& var : this->GetValues(var_ids.at(0).first)) { integral_x += var[var_ids.at(0).second]; } - if (plot.GetNdimentions() > 1) { + if (plot.GetNdimensions() > 1) { for (const auto& var : this->GetValues(var_ids.at(1).first)) { integral_y += var[var_ids.at(1).second]; } } - if (plot.GetNdimentions() == 1) { + if (plot.GetNdimensions() == 1) { plot.Fill(integral_x); } else { plot.Fill(integral_x, integral_y); @@ -25,7 +101,6 @@ void Task::FillIntegral(EntryConfig& plot) { } void Task::Exec() { - AnalysisTask::Exec(); for (auto& plot : entries_) { @@ -41,7 +116,7 @@ void Task::Exec() { ++ivw; auto weight = weights.at(ivw); if (std::fabs(weight) < 1e-6) continue; - switch (plot.GetNdimentions()) { + switch (plot.GetNdimensions()) { case 1: { if (std::fabs(weight - 1) < 1e-4) plot.Fill(var[var_ids.at(0).second]); else @@ -56,37 +131,28 @@ void Task::Exec() { } } } - }// plots } void Task::Finish() { - out_file_->cd(); - for (auto& plot : entries_) { - plot.Write(); - } + out_file_->Write(); out_file_->Close(); } -void Task::Init() { +TDirectory* Task::MkMultiLevelDir(TFile* file, const std::string& name) const { + auto splitBySlash = [] (const std::string& str) { + std::vector result; + std::stringstream ss(str); + std::string item; + + // Split the string by slashes + while (std::getline(ss, item, '/')) { + result.push_back(item); + } - AnalysisTask::Init(); - std::set dirs{}; + return result; + }; - for (auto& entry : entries_) { - dirs.insert(entry.GetDirectoryName()); - } - out_file_ = new TFile(out_file_name_.c_str(), "recreate"); - for (const auto& dir : dirs) { - out_file_->cd(); - dir_map_.insert(std::make_pair(dir, MkMultiLevelDir(out_file_, dir))); - } - for (auto& entry : entries_) { - entry.SetOutDir(dir_map_.find(entry.GetDirectoryName())->second); - } -} - -TDirectory* Task::MkMultiLevelDir(TFile* file, const std::string& name) const { auto vDirs = splitBySlash(name); TDirectory* result; for (int iDir = 0; iDir < vDirs.size(); iDir++) { @@ -97,18 +163,9 @@ TDirectory* Task::MkMultiLevelDir(TFile* file, const std::string& name) const { return result; } -std::vector Task::splitBySlash(const std::string& str) { - std::vector result; - std::stringstream ss(str); - std::string item; - - // Split the string by slashes - while (std::getline(ss, item, '/')) { - result.push_back(item); - } - - return result; +void Task::CreateOutputFileIfNotYet() { + if (out_file_ == nullptr) out_file_ = new TFile(out_file_name_.c_str(), "recreate"); } -}// namespace QA -}// namespace AnalysisTree +} // namespace AnalysisTree::QA + diff --git a/src/Task.hpp b/src/Task.hpp index 0d15e98..267692f 100644 --- a/src/Task.hpp +++ b/src/Task.hpp @@ -12,74 +12,44 @@ namespace AnalysisTree { namespace QA { +struct setdirectory_struct : Utils::Visitor { + explicit setdirectory_struct(TDirectory* dir) : dir_(dir) {} + template + void operator()(PlotType* p) const { p->SetDirectory(dir_); } + TDirectory* dir_; +}; + +struct setname_struct : Utils::Visitor { + explicit setname_struct(const std::string& name) : name_(name) {} + template + void operator()(PlotType* p) const { p->SetName(name_.c_str()); } + std::string name_; +}; + class Task : public AnalysisTask { public: Task() = default; - void Init() override; void Exec() override; void Finish() override; - size_t AddH1(const std::string& name, const Axis& x, Cuts* cuts = nullptr, Variable weight = Variable{}) { - weight.IfEmptyVariableConvertToOnes(x); - entries_.emplace_back(EntryConfig(x, weight, name, cuts, false)); - entries_.back().SetTopLevelDirName(toplevel_dir_name_); - auto var_id = AddEntry(AnalysisEntry(entries_.back().GetVariables(), entries_.back().GetEntryCuts(), entries_.back().GetVariableForWeight())); - entries_.back().SetVariablesId({{var_id.first, var_id.second.at(0)}}); - return entries_.size() - 1; - } + size_t AddH1(const std::string& name, const Axis& x, Cuts* cuts = nullptr, Variable weight = Variable{}); - size_t AddH1(const Axis& x, Cuts* cuts = nullptr, Variable weight = Variable{}) { - return AddH1("", x, cuts, weight); - } + size_t AddH1(const Axis& x, Cuts* cuts = nullptr, Variable weight = Variable{}); - size_t AddH2(const std::string& name, const Axis& x, const Axis& y, Cuts* cuts = nullptr, Variable weight = Variable{}) { - weight.IfEmptyVariableConvertToOnes(x); - entries_.emplace_back(EntryConfig(x, y, weight, name, cuts)); - entries_.back().SetTopLevelDirName(toplevel_dir_name_); - auto var_id = AddEntry(AnalysisEntry(entries_.back().GetVariables(), entries_.back().GetEntryCuts(), entries_.back().GetVariableForWeight())); - entries_.back().SetVariablesId({{var_id.first, var_id.second.at(0)}, {var_id.first, var_id.second.at(1)}}); - return entries_.size() - 1; - } + size_t AddH2(const std::string& name, const Axis& x, const Axis& y, Cuts* cuts = nullptr, Variable weight = Variable{}); - size_t AddH2(const Axis& x, const Axis& y, Cuts* cuts = nullptr, Variable weight = Variable{}) { - return AddH2("", x, y, cuts, weight); - } + size_t AddH2(const Axis& x, const Axis& y, Cuts* cuts = nullptr, Variable weight = Variable{}); - size_t AddProfile(const std::string& name, const Axis& x, const Axis& y, Cuts* cuts = nullptr, Variable weight = Variable{}) { - weight.IfEmptyVariableConvertToOnes(x); - entries_.emplace_back(EntryConfig(x, y, weight, name, cuts, true)); - entries_.back().SetTopLevelDirName(toplevel_dir_name_); - auto var_id = AddEntry(AnalysisEntry(entries_.back().GetVariables(), entries_.back().GetEntryCuts(), entries_.back().GetVariableForWeight())); - entries_.back().SetVariablesId({{var_id.first, var_id.second.at(0)}, {var_id.first, var_id.second.at(1)}}); - return entries_.size() - 1; - } + size_t AddProfile(const std::string& name, const Axis& x, const Axis& y, Cuts* cuts = nullptr, Variable weight = Variable{}); - size_t AddProfile(const Axis& x, const Axis& y, Cuts* cuts = nullptr, Variable weight = Variable{}) { - return AddProfile("", x, y, cuts, weight); - } + size_t AddProfile(const Axis& x, const Axis& y, Cuts* cuts = nullptr, Variable weight = Variable{}); - size_t AddIntegral(const std::string& name, const Axis& x, Cuts* cuts = nullptr, Variable weight = Variable{}) { - weight.IfEmptyVariableConvertToOnes(x); - entries_.emplace_back(EntryConfig(x, weight, name, cuts, true)); - entries_.back().SetTopLevelDirName(toplevel_dir_name_); - auto var_id = AddEntry(AnalysisEntry(entries_.back().GetVariables(), entries_.back().GetEntryCuts(), entries_.back().GetVariableForWeight())); - entries_.back().SetVariablesId({{var_id.first, var_id.second.at(0)}}); - return entries_.size() - 1; - } + size_t AddIntegral(const std::string& name, const Axis& x, Cuts* cuts = nullptr, Variable weight = Variable{}); - size_t AddIntegral(const Axis& x, Cuts* cuts = nullptr, Variable weight = Variable{}) { - return AddIntegral("", x, cuts, weight); - } + size_t AddIntegral(const Axis& x, Cuts* cuts = nullptr, Variable weight = Variable{}); - size_t AddIntegral(const Axis& x, const Axis& y, Cuts* cuts_x = nullptr, Cuts* cuts_y = nullptr) { - entries_.emplace_back(EntryConfig(x, cuts_x, y, cuts_y)); - entries_.back().SetTopLevelDirName(toplevel_dir_name_); - auto var_id_x = AddEntry(AnalysisEntry({entries_.back().GetVariables()[0]}, cuts_x)); - auto var_id_y = AddEntry(AnalysisEntry({entries_.back().GetVariables()[1]}, cuts_y)); - entries_.back().SetVariablesId({{var_id_x.first, var_id_x.second.at(0)}, {var_id_y.first, var_id_y.second.at(0)}}); - return entries_.size() - 1; - } + size_t AddIntegral(const Axis& x, const Axis& y, Cuts* cuts_x = nullptr, Cuts* cuts_y = nullptr); std::vector& Entries() { return entries_; } void SetOutputFileName(std::string name) { out_file_name_ = std::move(name); } @@ -92,12 +62,13 @@ class Task : public AnalysisTask { template TDirectory* MkDirIfNotExists(T* fod, std::string name) const { + if(fod == nullptr) throw std::runtime_error("Task::MkDirIfNotExists(): file or directory ptr is null"); TDirectory* result = fod->GetDirectory(name.c_str()); if (result == nullptr) result = fod->mkdir(name.c_str()); return result; } - static std::vector splitBySlash(const std::string& str); + void CreateOutputFileIfNotYet(); std::vector entries_{}; std::map dir_map_{};