Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/AnalysisTreeCoreLinkDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#pragma link C++ typedef AnalysisTree::ModuleDetector;
#pragma link C++ typedef AnalysisTree::HitDetector;
#pragma link C++ typedef AnalysisTree::ModulePositions;
#pragma link C++ typedef AnalysisTree::GenericDetector;

#pragma link C++ defined_in "Constants.h";

Expand Down
3 changes: 2 additions & 1 deletion core/Constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ enum class DetType : ShortInt_t {
kModule,
kTrack,
kEventHeader,
kParticle
kParticle,
kGeneric
};

enum class Types : ShortInt_t {
Expand Down
4 changes: 2 additions & 2 deletions examples/AnalysisTreeUserLinkDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#pragma link off all functions;
#pragma link C++ nestedclasses;

//#pragma link C++ class UserTaskRead++;
#pragma link C++ class UserTaskWrite++;
#pragma link C++ class UserTaskRead+;
#pragma link C++ class UserTaskWrite+;

#endif
3 changes: 2 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ message(STATUS "CMAKE_PROJECT_NAME ${CMAKE_PROJECT_NAME}")
string(REPLACE ".cpp" ".hpp" HEADERS "${SOURCES}")

include_directories(${CMAKE_SOURCE_DIR}/core ${CMAKE_SOURCE_DIR}/infra ${CMAKE_CURRENT_SOURCE_DIR} $<$<BOOL:${Boost_FOUND}>:${Boost_INCLUDE_DIRS}>)
add_library(AnalysisTreeUser SHARED ${SOURCES} G__AnalysisTreeUser.cxx)
add_library(AnalysisTreeUser SHARED ${SOURCES})
target_compile_definitions(AnalysisTreeUser PUBLIC
$<$<BOOL:${Boost_FOUND}>:ANALYSISTREE_BOOST_FOUND>)

Expand All @@ -23,6 +23,7 @@ ROOT_GENERATE_DICTIONARY(G__AnalysisTreeUser ${HEADERS}
OPTIONS
-I${CMAKE_BINARY_DIR}/include
$<$<BOOL:${Boost_FOUND}>:-DANALYSISTREE_BOOST_FOUND>
MODULE AnalysisTreeUser
)
target_link_libraries(AnalysisTreeUser
PUBLIC
Expand Down
2 changes: 1 addition & 1 deletion examples/UserTaskRead.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef ANALYSISTREE_EXAMPLES_USERTASKREAD_HPP_
#define ANALYSISTREE_EXAMPLES_USERTASKREAD_HPP_

#include <Task.hpp>
#include <AnalysisTree/Task.hpp>

class UserTaskRead : public AnalysisTree::Task {

Expand Down
4 changes: 2 additions & 2 deletions examples/UserTaskWrite.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#ifndef ANALYSISTREE_EXAMPLES_USERTASKWRITE_HPP_
#define ANALYSISTREE_EXAMPLES_USERTASKWRITE_HPP_

#include <Branch.hpp>
#include <Detector.hpp>
#include <Task.hpp>
#include <AnalysisTree/Branch.hpp>
#include <AnalysisTree/Task.hpp>

class UserTaskWrite : public AnalysisTree::Task {

Expand Down
2 changes: 1 addition & 1 deletion examples/example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ void example(const std::string& filename, const std::string& treename){
data_header->Print();
config->Print();

auto rec_particles = chain->GetBranch("VtxTracks");
auto rec_particles = chain->GetBranchObject("VtxTracks");
auto rec2sim_particles = chain->GetMatching("VtxTracks", "SimParticles");

auto rec_pT = rec_particles.GetField("pT");
Expand Down
4 changes: 4 additions & 0 deletions infra/Branch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ void Branch::InitDataPtr() {
data_ = temp;
break;
}
case DetType::kGeneric: {
data_ = new GenericDetector(config_.GetId());
break;
}
default: throw std::runtime_error("Branch type is not known!");
}
}
Expand Down
4 changes: 3 additions & 1 deletion infra/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ set(SOURCES
Branch.cpp
BranchChannel.cpp
AnalysisEntry.cpp
GenericContainerFiller.cpp
)


Expand All @@ -22,7 +23,7 @@ string(REPLACE ".cpp" ".hpp" HEADERS "${SOURCES}")
list(APPEND HEADERS "VariantMagic.hpp" "ToyMC.hpp" "Utils.hpp" "BranchHashHelper.hpp" "HelperFunctions.hpp")

include_directories(${CMAKE_SOURCE_DIR}/core ${CMAKE_CURRENT_SOURCE_DIR} $<$<BOOL:${Boost_FOUND}>:${Boost_INCLUDE_DIRS}>)
add_library(AnalysisTreeInfra SHARED ${SOURCES} G__AnalysisTreeInfra.cxx)
add_library(AnalysisTreeInfra SHARED ${SOURCES})
target_compile_definitions(AnalysisTreeInfra PUBLIC
$<$<BOOL:${Boost_FOUND}>:ANALYSISTREE_BOOST_FOUND>)

Expand All @@ -31,6 +32,7 @@ ROOT_GENERATE_DICTIONARY(G__AnalysisTreeInfra ${HEADERS}
OPTIONS
-I${CMAKE_BINARY_DIR}/include
$<$<BOOL:${Boost_FOUND}>:-DANALYSISTREE_BOOST_FOUND>
MODULE AnalysisTreeInfra
)
target_link_libraries(AnalysisTreeInfra
PUBLIC
Expand Down
4 changes: 4 additions & 0 deletions infra/Chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ void Chain::InitPointersToBranches(std::set<std::string> names) {
branch_ptr = new ModuleDetector;
break;
}
case DetType::kGeneric: {
branch_ptr = new GenericDetector;
break;
}
}
branches_.emplace(branch, branch_ptr);
}
Expand Down
125 changes: 125 additions & 0 deletions infra/GenericContainerFiller.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
//
// Created by oleksii on 09.04.25.
//

#include "GenericContainerFiller.hpp"

using namespace AnalysisTree;

GenericContainerFiller::GenericContainerFiller(std::string fileInName, std::string treeInName) : file_in_name_(std::move(fileInName)),
tree_in_name_(std::move(treeInName)) {}

void GenericContainerFiller::Init() {
file_in_ = TFile::Open(file_in_name_.c_str(), "read");
if (file_in_ == nullptr) throw std::runtime_error("GenericContainerFiller::Run(): file_in_ == nullptr");

tree_in_ = file_in_->Get<TTree>(tree_in_name_.c_str());
if (tree_in_ == nullptr) throw std::runtime_error("GenericContainerFiller::Run(): tree_in_ == nullptr");

if (!fields_to_ignore_.empty() && !fields_to_preserve_.empty()) throw std::runtime_error("GenericContainerFiller::Run(): !fields_to_ignore_.empty() && !fields_to_preserve_.empty()");

BranchConfig branchConfig(branch_out_name_, DetType::kGeneric);

auto lol = tree_in_->GetListOfLeaves();
const int nLeaves = lol->GetEntries();
for (int iLeave = 0; iLeave < nLeaves; iLeave++) {
auto leave = lol->At(iLeave);
const std::string fieldName = leave->GetName();
const std::string fieldType = leave->ClassName();
if (!fields_to_ignore_.empty() && (std::find(fields_to_ignore_.begin(), fields_to_ignore_.end(), fieldName) != fields_to_ignore_.end())) continue;
if (!fields_to_preserve_.empty() && (std::find(fields_to_preserve_.begin(), fields_to_preserve_.end(), fieldName) == fields_to_preserve_.end())) continue;
if (fieldType == "TLeafF") {
branchConfig.AddField<float>(fieldName);
} else if (fieldType == "TLeafI" || fieldType == "TLeafB" || fieldType == "TLeafS") {
branchConfig.AddField<int>(fieldName);
}
branch_map_.emplace_back((IndexMap){fieldName, fieldType, branchConfig.GetFieldId(fieldName)});
}
branch_values_.resize(branch_map_.size());

config_.AddBranchConfig(branchConfig);

for (int iV = 0; iV < branch_values_.size(); iV++) {
TBranch* branch = tree_in_->GetBranch(branch_map_.at(iV).name_.c_str());
SetAddressFICS(branch, branch_map_.at(iV), branch_values_.at(iV));
}

generic_detector_ = new GenericDetector(branchConfig.GetId());

file_out_ = TFile::Open(file_out_name_.c_str(), "recreate");
tree_out_ = new TTree(tree_out_name_.c_str(), "Analysis Tree");
tree_out_->SetAutoSave(0);
tree_out_->Branch((branchConfig.GetName() + ".").c_str(), "AnalysisTree::GenericDetector", &generic_detector_);

entry_switch_trigger_id_ = entry_switch_trigger_var_name_.empty() ? -999 : DetermineFieldIdByName(branch_map_, entry_switch_trigger_var_name_);
}

int GenericContainerFiller::Exec(int iEntry, int previousTriggerVar) {
tree_in_->GetEntry(iEntry);
const int currentTriggerVar = entry_switch_trigger_id_ >= 0 ? branch_values_.at(entry_switch_trigger_id_).get() : previousTriggerVar;
auto isNewATEntry = [&]() { return iEntry == 0 || (currentTriggerVar != previousTriggerVar) || (n_channels_per_entry_ >= 0 && iEntry % n_channels_per_entry_ == 0); };

if (isNewATEntry()) {
if (iEntry != 0) tree_out_->Fill();
generic_detector_->ClearChannels();
}
auto& channel = generic_detector_->AddChannel(config_.GetBranchConfig(generic_detector_->GetId()));
SetFieldsFICS(branch_map_, channel, branch_values_);

return currentTriggerVar;
}

void GenericContainerFiller::Finish() {
file_out_->cd();
config_.Write("Configuration");
tree_out_->Write();
file_out_->Close();
file_in_->Close();
}

void GenericContainerFiller::Run(int nEntries) {
Init();

const size_t nTreeEntries = tree_in_->GetEntries();
const size_t nRunEntries = (nEntries < 0 || nEntries > nTreeEntries) ? nTreeEntries : nEntries;

int previousTriggerVar{-799};
for (int iEntry = 0; iEntry < nRunEntries; iEntry++) {
previousTriggerVar = Exec(iEntry, previousTriggerVar);
}// iEntry
tree_out_->Fill();

Finish();
}

int GenericContainerFiller::DetermineFieldIdByName(const std::vector<IndexMap>& iMap, const std::string& name) {
auto distance = std::distance(iMap.begin(), std::find_if(iMap.begin(), iMap.end(), [&name](const IndexMap& p) { return p.name_ == name; }));
if (distance == iMap.size()) throw std::runtime_error("DetermineFieldIdByName(): name " + name + " is missing");
return distance;
}

void GenericContainerFiller::SetAddressFICS(TBranch* branch, const IndexMap& imap, FICS& ficc) {
if (imap.field_type_ == "TLeafF") branch->SetAddress(&ficc.float_);
else if (imap.field_type_ == "TLeafI")
branch->SetAddress(&ficc.int_);
else if (imap.field_type_ == "TLeafB")
branch->SetAddress(&ficc.char_);
else if (imap.field_type_ == "TLeafS")
branch->SetAddress(&ficc.short_);
else
throw std::runtime_error("GenericContainerFiller::SetAddressFICS(): unsupported filed type " + imap.field_type_);
}

void GenericContainerFiller::SetFieldsFICS(const std::vector<IndexMap>& imap, Container& container, const std::vector<FICS>& ficc) {
for (int iV = 0; iV < ficc.size(); iV++) {
if (imap.at(iV).field_type_ == "TLeafF") container.SetField(ficc.at(iV).float_, imap.at(iV).index_);
else if (imap.at(iV).field_type_ == "TLeafI")
container.SetField(ficc.at(iV).int_, imap.at(iV).index_);
else if (imap.at(iV).field_type_ == "TLeafB")
container.SetField(static_cast<int>(ficc.at(iV).char_), imap.at(iV).index_);
else if (imap.at(iV).field_type_ == "TLeafS")
container.SetField(static_cast<int>(ficc.at(iV).short_), imap.at(iV).index_);
else
throw std::runtime_error("GenericContainerFiller::SetFieldsFICS(): unsupported filed type " + imap.at(iV).field_type_);
}
}
100 changes: 100 additions & 0 deletions infra/GenericContainerFiller.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//
// Created by oleksii on 09.04.25.
//

#ifndef ANALYSISTREE_GENERICCONTAINERFILLER_HPP
#define ANALYSISTREE_GENERICCONTAINERFILLER_HPP

#include "Configuration.hpp"
#include "Container.hpp"
#include "Detector.hpp"

#include <TFile.h>
#include <TTree.h>

#include <string>
#include <vector>

struct IndexMap {
std::string name_;
std::string field_type_;
short index_;
};

struct FICS {// FICS stands for float, int, char, short
float float_{-199.f};
int int_{-199};
char char_{static_cast<char>(-199)};
short short_{static_cast<short>(-199)};

float get() {
if (std::fabs(float_ + 199.f) > 1e-4) return float_;
if (int_ != -199) return static_cast<float>(int_);
if (char_ != static_cast<char>(-199)) return static_cast<float>(char_);
if (short_ != static_cast<short>(-199)) return static_cast<float>(short_);
throw std::runtime_error("GenericContainerFiller, FICS::get(): none of values initialized");
}
};

namespace AnalysisTree {

class GenericContainerFiller {
public:
GenericContainerFiller() = delete;
explicit GenericContainerFiller(std::string fileInName, std::string treeInName = "pTree");
virtual ~GenericContainerFiller() = default;

void SetOutputFileName(const std::string& name) { file_out_name_ = name; }
void SetOutputTreeName(const std::string& name) { tree_out_name_ = name; }
void SetOutputBranchName(const std::string& name) { branch_out_name_ = name; }

void SetFieldsToIgnore(const std::vector<std::string>& fields) { fields_to_ignore_ = fields; }
void SetFieldsToPreserve(const std::vector<std::string>& fields) { fields_to_preserve_ = fields; }

void SetEntrySwitchTriggerVarName(const std::string& name) { entry_switch_trigger_var_name_ = name; }

void SetNChannelsPerEntry(int n) { n_channels_per_entry_ = n; }

void Run(int nEntries = -1);

protected:
void Init();
int Exec(int iEntry, int previousTriggerVar);
void Finish();

static int DetermineFieldIdByName(const std::vector<IndexMap>& iMap, const std::string& name);
static void SetAddressFICS(TBranch* branch, const IndexMap& imap, FICS& ficc);
static void SetFieldsFICS(const std::vector<IndexMap>& imap, AnalysisTree::Container& container, const std::vector<FICS>& ficc);

std::string file_in_name_;
std::string tree_in_name_;

std::string file_out_name_{"AnalysisTree.root"};
std::string tree_out_name_{"aTree"};
std::string branch_out_name_{"PlainBranch"};

TFile* file_in_{nullptr};
TTree* tree_in_{nullptr};
TFile* file_out_{nullptr};
TTree* tree_out_{nullptr};

AnalysisTree::Configuration config_;
AnalysisTree::GenericDetector* generic_detector_{nullptr};
std::vector<IndexMap> branch_map_;
std::vector<FICS> branch_values_;

// variable, change of value of which triggers switch to a new AT event
std::string entry_switch_trigger_var_name_{""};

int entry_switch_trigger_id_{-1};

// if entry_switch_trigger_var_name_ is not empty, this field does not matter
// if entry_switch_trigger_var_name_ is empty, sets how many AT channels
// will constitute a single AT entry (event)
int n_channels_per_entry_{-1};

std::vector<std::string> fields_to_ignore_{};
std::vector<std::string> fields_to_preserve_{};
};
}// namespace AnalysisTree
#endif//ANALYSISTREE_GENERICCONTAINERFILLER_HPP
10 changes: 9 additions & 1 deletion infra/HelperFunctions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ inline std::string ToStringWithSignificantFigures(const T a_value, const int n)
inline std::vector<AnalysisTree::SimpleCut> CreateRangeCuts(const std::vector<float>& ranges, const std::string& cutNamePrefix, const std::string& branchFieldName, int precision = 2) {
std::vector<AnalysisTree::SimpleCut> 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), precision);
const std::string cutName = cutNamePrefix + ToStringWithPrecision(ranges.at(iRange), precision) + "_" + ToStringWithPrecision(ranges.at(iRange + 1), precision);
sliceCuts.emplace_back(AnalysisTree::RangeCut(branchFieldName, ranges.at(iRange), ranges.at(iRange + 1), cutName));
}

Expand All @@ -50,5 +50,13 @@ inline std::vector<AnalysisTree::SimpleCut> CreateEqualCuts(const std::vector<fl
return sliceCuts;
}

inline bool StringToBool(const std::string& str) {
if (str == "true") return true;
else if (str == "false")
return false;
else
throw std::runtime_error("HelperFunctions::StringToBool(): argument must be either true or false");
}

}// namespace HelperFunctions
#endif// ANALYSISTREE_INFRA_HELPER_FUNCTIONS_HPP
7 changes: 4 additions & 3 deletions infra/TaskManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ class TaskManager {
AddBranch(branch->GetDataRaw<EventHeader*>(), branch->GetConfig());
break;
}
case DetType::kGeneric: {
AddBranch(branch->GetDataRaw<GenericDetector*>(), branch->GetConfig());
break;
}
}
}

Expand All @@ -126,9 +130,6 @@ class TaskManager {
configuration_->GetBranchConfig(br2).GetId());

configuration_->AddMatch(match);
// if (write_mode_ == eBranchWriteMode::kCreateNewTree) {
// chain_->GetConfiguration()->AddMatch(match);
// }
out_tree_->Branch((configuration_->GetMatchName(br1, br2) + ".").c_str(), &match);
}

Expand Down
Loading