19#include <FairEventHeader.h>
20#include <FairFileHeader.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>
39#include <fmt/chrono.h>
54 constexpr auto DEFAULT_TITLE =
"InputRootFile";
56 template <
typename ContainerType,
typename DataType>
57 auto Vector2TContainer(std::vector<DataType>& vec) -> std::unique_ptr<ContainerType>
59 using RawType = std::remove_reference_t<std::remove_pointer_t<DataType>>;
60 static_assert(std::is_base_of_v<TObject, RawType>);
61 auto list = std::make_unique<ContainerType>();
62 for (
auto& iter : vec)
64 if constexpr (std::is_pointer_v<DataType>)
76 template <
typename StringType = std::
string>
77 auto GetBranchList(TFile* rootFile, std::string_view listName) -> std::vector<StringType>
79 auto branchList = std::vector<StringType>{};
80 if (
auto* list =
dynamic_cast<TList*
>(rootFile->Get(listName.data())); list !=
nullptr)
82 for (
const auto& str : TRangeDynCast<TObjString>(list))
84 branchList.emplace_back(str->GetString().Data());
90 fmt::format(
"No branch list named {0} in input file {1}", listName, rootFile->GetName()));
95 template <
typename UnaryFunc>
96 void loop_through_branch_elements(TFile* root_file, std::string_view tree_name, UnaryFunc action)
98 auto* tree = root_file->Get<TTree>(tree_name.data());
99 auto* branches = tree->GetListOfBranches();
101 fmt::format(
"Get {} branches from the tree file {}", branches->GetEntries(), root_file->GetName()));
102 for (
auto* branch_obj : TRangeDynCast<TObject>(branches))
104 auto* branch =
dynamic_cast<TBranchElement*
>(branch_obj);
105 if (branch ==
nullptr)
113 template <
typename UnaryFunc>
114 void loop_through_branches(TFile* root_file, std::string_view tree_name, UnaryFunc action)
116 auto* tree = root_file->Get<TTree>(tree_name.data());
117 auto* branches = tree->GetListOfBranches();
119 fmt::format(
"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() };
152 fmt::format(
"Determine the class name {:?} of the branch {:?}", class_name, branch->GetName()));
155 R3BLOG(warn, fmt::format(
"Cannot determine the class name of the branch {:?}", branch->GetName()));
156 return std::string{
"TObject" };
159 void add_branches_to_folder(TFolder* folder, TFile* root_file, std::string_view tree_name)
161 loop_through_branch_elements(root_file,
163 [folder](
auto* branch)
165 auto class_name = std::string_view{ branch->GetClassName() };
166 if (class_name ==
"TClonesArray")
168 const auto data_class = get_tca_data_class(branch);
169 auto tca_obj = std::make_unique<TClonesArray>(data_class.data());
170 tca_obj->SetName(branch->GetName());
171 folder->Add(tca_obj.release());
178 auto HasBranchList(TFile* rootFile,
const std::vector<std::string>& branchList) ->
bool
180 auto const newBranchList = GetBranchList(rootFile,
"BranchList");
181 auto view1 = std::vector<std::string_view>(branchList.begin(), branchList.end());
182 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());
186 return view1 == view2;
189 template <
typename ContainerType>
190 auto GetDataFromAnyFolder(TFile* rootFile,
const ContainerType& folderNames) -> std::optional<TKey*>
192 for (
auto const& name : folderNames)
194 R3BLOG(debug,
"looking for " + name);
195 auto* dataFolder =
dynamic_cast<TKey*
>(rootFile->FindKey(name.c_str()));
196 if (dataFolder !=
nullptr)
198 R3BLOG(debug, name +
" has been found!");
205 auto Get_TChain_FromFairRM(FairRootManager* rootMan) -> TChain*
207 auto const chainTitle =
"/" + std::string{ FairRootManager::GetFolderName() };
208 auto inChain = std::make_unique<TChain>(FairRootManager::GetTreeName(), chainTitle.c_str());
209 R3BLOG(debug,
"Chain created");
210 LOG(info) <<
"chain name: " << FairRootManager::GetTreeName();
211 rootMan->SetInChain(inChain.release());
212 return FairRootManager::Instance()->GetInChain();
220 throw R3B::logic_error(fmt::format(
"Refresh rate {} must be a positive floating point value", rate));
224 refresh_period_ = std::chrono::milliseconds(
static_cast<int>(1000. / rate));
237 const auto now_t = std::chrono::steady_clock::now();
238 const auto time_spent = std::chrono::ceil<std::chrono::milliseconds>(now_t -
previous_t_);
242 const auto events_per_millisecond =
243 static_cast<double>(processed_events) /
static_cast<double>(time_spent.count());
244 Print(event_num, events_per_millisecond);
253 if (speed_per_ms <= 0.)
257 const auto event_num_str =
258 fmt::format(fg(fmt::terminal_color::bright_green) | fmt::emphasis::bold,
"{:^5d}k", event_num / 1000);
259 const auto speed_str = fmt::format(fg(fmt::color::white),
"{:^6.1F}k/s", speed_per_ms);
260 const auto progress_str = fmt::format(fg(fmt::terminal_color::bright_yellow) | fmt::emphasis::bold,
262 100. *
static_cast<double>(event_num) /
static_cast<double>(
max_event_num_));
263 const auto time_left_ms =
264 std::chrono::milliseconds{ (
max_event_num_ - event_num) /
static_cast<int>(std::ceil(speed_per_ms)) };
265 fmt::print(
"Events processed: {0} ({1}) Progress: {2}% (time left: {3:%H h %M m %S s}) Run ID: {4}\r",
269 std::chrono::ceil<std::chrono::seconds>(time_left_ms),
276 auto const msg = fmt::format(
"Adding {} to file source\n", fileName);
296 FairRootManager::Instance()->AddBranchToList(branchName.c_str());
327 R3BLOG(debug, fmt::format(
"Set {} main folder(s) to FairRootManager.", listOfFolders->GetEntries()));
328 rootMan->SetListOfFolders(listOfFolders.release());
336 auto const folderNames =
337 std::array<std::string, 4>{ FairRootManager::GetFolderName(),
"r3broot",
"cbmout",
"cbmroot" };
339 return GetDataFromAnyFolder(rootFile, folderNames);
350 auto folder = std::make_unique<TFolder>(
"r3broot",
"r3broot");
351 add_branches_to_folder(folder.get(), rootFile.get(),
treeName_);
359 auto res1 = folderKey.has_value();
360 auto res2 = HasBranchList(rootFile.get(),
branchList_);
365 R3BLOG(warn,
"Different folder name!");
377 R3BLOG(warn,
"folder has no key");
381 R3BLOG(warn,
"HasBranchList is false!");
384 return res1 and res2;
390 auto* header = rootFile->Get<FairFileHeader>(
fileHeader_.c_str());
391 if (header ==
nullptr)
395 auto runID = header->GetRunId();
409 if (
const auto runID =
ExtractRunId(file.get()); runID.has_value() && runID.value() != 0)
411 auto const msg = fmt::format(R
"(Successfully extract RunID "{}" from root file "{}")", runID.value(), filename);
417 auto const msg = fmt::format(
"Failed to extract RunID from root file \"{}\"", filename);
427 throw R3B::logic_error(fmt::format(
"Cannot find main folder from the root file {}!", filename));
430 branchList_ = GetBranchList(file.get(),
"BranchList");
435 LOG(warn) <<
"No time based branch list in input file";
445 auto chain = std::make_unique<TChain>(friendFiles.
GetTitle().c_str(), friendFiles.
GetFolderName().c_str());
461 LOG(debug) <<
"Creating a new R3BFileSource!";
464 for (
auto& name : fileNames)
475 :
R3BFileSource2(std::vector<std::string>{ std::move(file) }, title)
491 if (
auto const res =
inputDataFiles_.AddFileName(std::move(file_name), is_tree_file); res.has_value())
499 "Root file {0} is incompatible with the first root file {1}", res.value(),
dataFileNames_.front()));
503 R3BLOG(error, fmt::format(
"Failed to add the first root file {:?}", file_name));
511 for (
auto& file_name : file_names)
513 AddFile(std::move(file_name), is_tree_file);
519 for (
auto& file_name : file_names)
521 AddFriend(std::move(file_name), is_tree_file);
531 [&rootfile](
const auto& friends)
532 { return HasBranchList(rootfile.get(), friends.GetBranchListRef()); });
541 auto res = friendGroup->AddFileName(file_name, is_tree_file);
545 fmt::format(
"Friend file {0} is incompatible with the first friend file {1}",
547 friendGroup->GetBaseFileName()));
578 if (evtHeader ==
nullptr)
592 if (init_runID != GetRunId())
596 fmt::format(
"runID {} being set is different from the runID {} in the data file!", GetRunId(), init_runID));
598 SetRunId(init_runID);
599 evtHeader->SetRunId(init_runID);
612 auto const currentEventID =
evtHeader_->GetMCEntryNumber();
618 auto const read_bytes =
inputDataFiles_.GetChain()->FindBranch(BrName)->GetEntry(entryID);
621 LOG(warn) << fmt::format(
"Failed to read the data of the event {0} from the branch {1}", entryID, BrName);
628 if (fair::Logger::GetConsoleSeverity() == fair::Severity::info)
633 auto read_bytes = chain->GetEntry(eventID);
636 LOG(warn) << fmt::format(
"Failed to read the data of the event {0} from the source", eventID);
645 chain->SetBranchStatus(BrName,
true);
646 chain->SetBranchAddress(BrName, obj);
653 if (chain !=
nullptr)
655 return ActivateObjectAnyImpl(chain, obj, info, BrName);
#define R3BLOG(severity, x)
void SetRefreshRate_Hz(float rate)
std::chrono::milliseconds refresh_period_
uint64_t previous_event_num_
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)
Int_t CheckMaxEventNo(Int_t EvtEnd=0) override
R3BInputRootFiles inputDataFiles_
Bool_t ActivateObjectAny(void **obj, const std::type_info &info, const char *BrName) override
FairEventHeader * evtHeader_
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_
auto make_rootfile(Args &&... args)