18#include <FairEventHeader.h>
19#include <FairFileHeader.h>
20#include <FairMCEventHeader.h>
21#include <FairRootManager.h>
24#include <RtypesCore.h>
25#include <TBranchElement.h>
26#include <TClonesArray.h>
27#include <TCollection.h>
30#include <TObjString.h>
38#include <fairlogger/Logger.h>
42#include <fmt/format.h>
55 constexpr auto DEFAULT_TITLE =
"InputRootFile";
58 template <
typename ContainerType,
typename DataType>
59 auto Vector2TContainer(std::vector<DataType>& vec) -> std::unique_ptr<ContainerType>
61 using RawType = std::remove_reference_t<std::remove_pointer_t<DataType>>;
62 static_assert(std::is_base_of_v<TObject, RawType>);
63 auto list = std::make_unique<ContainerType>();
64 for (
auto& iter : vec)
66 if constexpr (std::is_pointer_v<DataType>)
78 template <
typename StringType = std::
string>
79 auto GetBranchList(TFile* rootFile, std::string_view listName) -> std::vector<StringType>
81 auto branchList = std::vector<StringType>{};
82 if (
auto* list =
dynamic_cast<TList*
>(rootFile->Get(listName.data())); list !=
nullptr)
84 for (
const auto& str : TRangeDynCast<TObjString>(list))
86 branchList.emplace_back(str->GetString().Data());
92 fmt::format(
"No branch list named {0} in input file {1}", listName, rootFile->GetName()));
97 template <
typename UnaryFunc>
98 void loop_through_branch_elements(TFile* root_file, std::string_view tree_name, UnaryFunc action)
100 auto* tree = root_file->Get<TTree>(tree_name.data());
101 auto* branches = tree->GetListOfBranches();
102 LOGP(debug,
"Get {} branches from the tree file {}", branches->GetEntries(), root_file->GetName());
103 for (
auto* branch_obj : TRangeDynCast<TObject>(branches))
105 auto* branch =
dynamic_cast<TBranchElement*
>(branch_obj);
106 if (branch ==
nullptr)
114 template <
typename UnaryFunc>
115 void loop_through_branches(TFile* root_file, std::string_view tree_name, UnaryFunc action)
117 auto* tree = root_file->Get<TTree>(tree_name.data());
118 auto* branches = tree->GetListOfBranches();
119 LOGP(debug,
"Get {} branches from the tree file {}", branches->GetEntries(), root_file->GetName());
120 for (
auto* branch_obj : TRangeDynCast<TObject>(branches))
122 auto* branch =
dynamic_cast<TBranch*
>(branch_obj);
123 if (branch ==
nullptr)
131 template <
typename StringType = std::
string>
132 auto GetBranchListFromTree(TFile* root_file, std::string_view tree_name) -> std::vector<StringType>
134 auto branch_name_list = std::vector<StringType>{};
135 loop_through_branch_elements(root_file,
137 [&branch_name_list](
auto* branch)
138 { branch_name_list.emplace_back(branch->GetName()); });
139 return branch_name_list;
142 auto get_tca_data_class(TBranchElement* branch) -> std::string
144 TClonesArray* buffer =
nullptr;
145 branch->SetAddress(&buffer);
147 branch->SetAddress(
nullptr);
148 if (buffer !=
nullptr)
150 auto class_name = std::string{ buffer->GetClass()->GetName() };
151 LOGP(debug,
"Determine the class name {:?} of the branch {:?}", class_name, branch->GetName());
154 LOGP(warn,
"Cannot determine the class name of the branch {:?}", branch->GetName());
155 return std::string{
"TObject" };
158 void add_branches_to_folder(TFolder* folder, TFile* root_file, std::string_view tree_name)
160 loop_through_branch_elements(root_file,
162 [folder](
auto* branch)
164 auto class_name = std::string_view{ branch->GetClassName() };
165 if (class_name ==
"TClonesArray")
167 const auto data_class = get_tca_data_class(branch);
168 auto tca_obj = std::make_unique<TClonesArray>(data_class.data());
169 tca_obj->SetName(branch->GetName());
170 folder->Add(tca_obj.release());
177 auto HasBranchList(TFile* rootFile,
const std::vector<std::string>& branchList) ->
bool
179 auto const newBranchList = GetBranchList(rootFile,
"BranchList");
180 auto view1 = std::vector<std::string_view>(branchList.begin(), branchList.end());
181 auto view2 = std::vector<std::string_view>(newBranchList.begin(), newBranchList.end());
184 std::sort(view1.begin(), view1.end());
185 std::sort(view2.begin(), view2.end());
187 std::ranges::sort(view1);
188 std::ranges::sort(view2);
190 return view1 == view2;
193 template <
typename ContainerType>
194 auto GetDataFromAnyFolder(TFile* rootFile,
const ContainerType& folderNames) -> std::optional<TKey*>
196 for (
auto const& name : folderNames)
198 LOGP(debug,
"Looking for {}", name);
199 auto* dataFolder =
dynamic_cast<TKey*
>(rootFile->FindKey(name.c_str()));
200 if (dataFolder !=
nullptr)
202 LOGP(debug,
"{} has been found!", name);
209 auto Get_TChain_FromFairRM(FairRootManager* rootMan) -> TChain*
211 auto const chainTitle =
"/" + std::string{ FairRootManager::GetFolderName() };
212 auto inChain = std::make_unique<TChain>(FairRootManager::GetTreeName(), chainTitle.c_str());
213 LOGP(debug,
"Chain created");
214 LOG(info) <<
"chain name: " << FairRootManager::GetTreeName();
215 rootMan->SetInChain(inChain.release());
216 return FairRootManager::Instance()->GetInChain();
224 throw R3B::logic_error(fmt::format(
"Refresh rate {} must be a positive floating point value", rate));
228 refresh_period_ = std::chrono::milliseconds(
static_cast<int>(1000. / rate));
241 const auto now_t = std::chrono::steady_clock::now();
242 const auto time_spent = std::chrono::ceil<std::chrono::milliseconds>(now_t -
previous_t_);
245 const auto total_time_spent = std::chrono::ceil<std::chrono::milliseconds>(now_t -
begin_t_);
247 const auto events_per_millisecond = [&,
this]()
251 return static_cast<double>(processed_events) /
static_cast<double>(time_spent.count());
253 return static_cast<double>(event_num) /
static_cast<double>(total_time_spent.count());
256 Print(event_num, events_per_millisecond);
265 if (speed_per_ms <= 0.)
269 const auto event_num_str =
270 fmt::format(fg(fmt::terminal_color::bright_green) | fmt::emphasis::bold,
"{:^5d}k", event_num / 1000);
271 const auto speed_str = fmt::format(fg(fmt::color::white),
"{:^6.1F}k/s", speed_per_ms);
272 const auto progress_str = fmt::format(fg(fmt::terminal_color::bright_yellow) | fmt::emphasis::bold,
274 100. *
static_cast<double>(event_num) /
static_cast<double>(
max_event_num_));
275 const auto time_left_ms =
276 std::chrono::milliseconds{ (
max_event_num_ - event_num) /
static_cast<int>(std::ceil(speed_per_ms)) };
277 fmt::print(
"Events processed: {0} ({1}) Progress: {2}% (time left: {3:%H h %M m %S s}) Run ID: {4}\r",
281 std::chrono::ceil<std::chrono::seconds>(time_left_ms),
288 LOGP(info,
"Adding {} to file source\n", fileName);
307 FairRootManager::Instance()->AddBranchToList(branchName.c_str());
338 LOGP(debug,
"Set {} main folder(s) to FairRootManager.", listOfFolders->GetEntries());
339 rootMan->SetListOfFolders(listOfFolders.release());
347 auto const folderNames =
348 std::array<std::string, 4>{ FairRootManager::GetFolderName(),
"r3broot",
"cbmout",
"cbmroot" };
350 return GetDataFromAnyFolder(rootFile, folderNames);
361 auto folder = std::make_unique<TFolder>(
"r3broot",
"r3broot");
362 add_branches_to_folder(folder.get(), rootFile.get(),
treeName_);
370 auto res1 = folderKey.has_value();
371 auto res2 = HasBranchList(rootFile.get(),
branchList_);
376 LOGP(warn,
"Different folder name!");
388 LOGP(warn,
"folder has no key");
392 LOGP(warn,
"HasBranchList is false!");
395 return res1 and res2;
401 auto* header = rootFile->Get<FairFileHeader>(
fileHeader_.c_str());
402 if (header ==
nullptr)
406 auto runID = header->GetRunId();
420 if (
const auto runID =
ExtractRunId(file.get()); runID.has_value() && runID.value() != 0)
422 LOGP(debug,
"Successfully extract RunID {} from root file {:?}", runID.value(), filename);
427 LOGP(error,
"Failed to extract RunID from root file {:?}", filename);
436 throw R3B::logic_error(fmt::format(
"Cannot find main folder from the root file {}!", filename));
439 branchList_ = GetBranchList(file.get(),
"BranchList");
444 LOG(info) <<
"No time based branch list in input file";
454 auto chain = std::make_unique<TChain>(friendFiles.
GetTitle().c_str(), friendFiles.
GetFolderName().c_str());
470 LOG(debug) <<
"Creating a new R3BFileSource!";
473 for (
auto& name : fileNames)
484 :
R3BFileSource2(std::vector<std::string>{ std::move(file) }, title)
500 if (
auto const res =
inputDataFiles_.AddFileName(std::move(file_name), is_tree_file); res.has_value())
506 "Root file {:?} is incompatible with the first root file {:?}",
512 LOGP(error,
"Failed to add the first root file {:?}", file_name);
520 for (
auto& file_name : file_names)
522 AddFile(std::move(file_name), is_tree_file);
528 for (
auto& file_name : file_names)
530 AddFriend(std::move(file_name), is_tree_file);
541 [&rootfile](
const auto& friends)
542 { return HasBranchList(rootfile.get(), friends.GetBranchListRef()); });
545 [&rootfile](
const auto& friends)
546 {
return HasBranchList(rootfile.get(), friends.GetBranchListRef()); });
556 auto res = friendGroup->AddFileName(file_name, is_tree_file);
560 "Friend file {} is incompatible with the first friend file {:?}",
562 friendGroup->GetBaseFileName());
589 mc_event_header_ =
dynamic_cast<FairMCEventHeader*
>(FairRootManager::Instance()->GetObject(
"MCEventHeader."));
594 "Event header from the input root file can neither be casted as R3BEventHeader nor FairMCEventHeader!");
602 if (evtHeader ==
nullptr)
608 if (event_header ==
nullptr)
638 "runID {} being set is different from the runID {} in the data file! Use the runID in the data file.",
642 SetRunId(init_runID);
643 evtHeader->SetRunId(init_runID);
649 LOGP(info,
"Setting printing event max to {}",
event_end_);
665 LOG(warn) << fmt::format(
"Failed to read the data of the event {0} from the branch {1}", entryID, BrName);
672 if (fair::Logger::GetConsoleSeverity() == fair::Severity::info)
677 auto read_bytes = chain->GetEntry(eventID);
680 LOG(warn) << fmt::format(
"Failed to read the data of the event {0} from the source", eventID);
689 chain->SetBranchStatus(BrName,
true);
690 chain->SetBranchAddress(BrName, obj);
697 if (chain !=
nullptr)
699 return ActivateObjectAnyImpl(chain, obj, info, BrName);
void SetRefreshRate_Hz(float rate)
std::chrono::milliseconds refresh_period_
uint64_t previous_event_num_
std::chrono::time_point< std::chrono::steady_clock > begin_t_
void Print(uint64_t event_num, double speed_per_ms)
void ShowProgress(uint64_t event_num)
std::chrono::time_point< std::chrono::steady_clock > previous_t_
Int_t ReadEvent(UInt_t eventID=0) override
Bool_t ActivateObject(TObject **obj, const char *BrName) override
void ReadBranchEvent(const char *BrName) override
R3BEventProgressPrinter event_progress_
std::vector< R3BInputRootFiles > inputFriendFiles_
void AddFriend(std::string, bool is_tree_file=false)
FairMCEventHeader * mc_event_header_
Int_t CheckMaxEventNo(Int_t EvtEnd=0) override
R3BInputRootFiles inputDataFiles_
Bool_t ActivateObjectAny(void **obj, const std::type_info &info, const char *BrName) override
void AddFile(std::string file_name, bool is_tree_file=false)
std::vector< std::string > dataFileNames_
void FillEventHeader(FairEventHeader *evtHeader) override
std::vector< std::string > friendFileNames_
R3BEventHeader * r3b_event_header_
auto make_rootfile(Args &&... args)
constexpr int DEFAULT_RUN_ID