R3BROOT
R3B analysis software
Loading...
Searching...
No Matches
R3BFileSource2.cxx
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) 2019 GSI Helmholtzzentrum für Schwerionenforschung GmbH *
3 * Copyright (C) 2019-2025 Members of R3B Collaboration *
4 * *
5 * This software is distributed under the terms of the *
6 * GNU General Public Licence (GPL) version 3, *
7 * copied verbatim in the file "LICENSE". *
8 * *
9 * In applying this license GSI does not waive the privileges and immunities *
10 * granted to it by virtue of its status as an Intergovernmental Organization *
11 * or submit itself to any jurisdiction. *
12 ******************************************************************************/
13
14#include "R3BFileSource2.h"
15#include "R3BEventHeader.h"
16#include "R3BException.h"
17#include "R3BShared.h"
18#include <FairEventHeader.h>
19#include <FairFileHeader.h>
20#include <FairMCEventHeader.h>
21#include <FairRootManager.h>
22#include <FairRun.h>
23#include <Rtypes.h>
24#include <RtypesCore.h>
25#include <TBranchElement.h>
26#include <TClonesArray.h>
27#include <TCollection.h>
28#include <TFolder.h>
29#include <TKey.h>
30#include <TObjString.h>
31#include <TObject.h>
32#include <algorithm>
33#include <array>
34#include <chrono>
35#include <cmath>
36#include <cstdint>
37#include <cstdio>
38#include <fairlogger/Logger.h>
39#include <fmt/base.h>
40#include <fmt/color.h>
41#include <fmt/core.h>
42#include <fmt/format.h>
43#include <memory>
44#include <optional>
45#include <string>
46#include <string_view>
47#include <sys/types.h>
48#include <type_traits>
49#include <typeinfo>
50#include <utility>
51#include <vector>
52
53namespace
54{
55 constexpr auto DEFAULT_TITLE = "InputRootFile";
56 constexpr auto DEFAULT_RUN_ID = 999;
57
58 template <typename ContainerType, typename DataType>
59 auto Vector2TContainer(std::vector<DataType>& vec) -> std::unique_ptr<ContainerType>
60 {
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)
65 {
66 if constexpr (std::is_pointer_v<DataType>)
67 {
68 list->Add(iter);
69 }
70 else
71 {
72 list->Add(&iter);
73 }
74 }
75 return list;
76 }
77
78 template <typename StringType = std::string>
79 auto GetBranchList(TFile* rootFile, std::string_view listName) -> std::vector<StringType>
80 {
81 auto branchList = std::vector<StringType>{};
82 if (auto* list = dynamic_cast<TList*>(rootFile->Get(listName.data())); list != nullptr)
83 {
84 for (const auto& str : TRangeDynCast<TObjString>(list))
85 {
86 branchList.emplace_back(str->GetString().Data());
87 }
88 }
89 else
90 {
91 throw R3B::logic_error(
92 fmt::format("No branch list named {0} in input file {1}", listName, rootFile->GetName()));
93 }
94 return branchList;
95 }
96
97 template <typename UnaryFunc>
98 void loop_through_branch_elements(TFile* root_file, std::string_view tree_name, UnaryFunc action)
99 {
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))
104 {
105 auto* branch = dynamic_cast<TBranchElement*>(branch_obj);
106 if (branch == nullptr)
107 {
108 continue;
109 }
110 action(branch);
111 }
112 }
113
114 template <typename UnaryFunc>
115 void loop_through_branches(TFile* root_file, std::string_view tree_name, UnaryFunc action)
116 {
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))
121 {
122 auto* branch = dynamic_cast<TBranch*>(branch_obj);
123 if (branch == nullptr)
124 {
125 continue;
126 }
127 action(branch);
128 }
129 }
130
131 template <typename StringType = std::string>
132 auto GetBranchListFromTree(TFile* root_file, std::string_view tree_name) -> std::vector<StringType>
133 {
134 auto branch_name_list = std::vector<StringType>{};
135 loop_through_branch_elements(root_file,
136 tree_name,
137 [&branch_name_list](auto* branch)
138 { branch_name_list.emplace_back(branch->GetName()); });
139 return branch_name_list;
140 }
141
142 auto get_tca_data_class(TBranchElement* branch) -> std::string
143 {
144 TClonesArray* buffer = nullptr;
145 branch->SetAddress(&buffer); // NOLINT: Nasty ROOT API
146 branch->GetEntry(0);
147 branch->SetAddress(nullptr);
148 if (buffer != nullptr)
149 {
150 auto class_name = std::string{ buffer->GetClass()->GetName() };
151 LOGP(debug, "Determine the class name {:?} of the branch {:?}", class_name, branch->GetName());
152 return class_name;
153 }
154 LOGP(warn, "Cannot determine the class name of the branch {:?}", branch->GetName());
155 return std::string{ "TObject" };
156 }
157
158 void add_branches_to_folder(TFolder* folder, TFile* root_file, std::string_view tree_name)
159 {
160 loop_through_branch_elements(root_file,
161 tree_name,
162 [folder](auto* branch)
163 {
164 auto class_name = std::string_view{ branch->GetClassName() };
165 if (class_name == "TClonesArray")
166 {
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());
171 }
172 });
173
174 // TODO: what if it's branch with signle literal value?
175 }
176
177 auto HasBranchList(TFile* rootFile, const std::vector<std::string>& branchList) -> bool
178 {
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());
182
183#ifdef HAS_CXX_17
184 std::sort(view1.begin(), view1.end());
185 std::sort(view2.begin(), view2.end());
186#else
187 std::ranges::sort(view1);
188 std::ranges::sort(view2);
189#endif
190 return view1 == view2;
191 }
192
193 template <typename ContainerType>
194 auto GetDataFromAnyFolder(TFile* rootFile, const ContainerType& folderNames) -> std::optional<TKey*>
195 {
196 for (auto const& name : folderNames)
197 {
198 LOGP(debug, "Looking for {}", name);
199 auto* dataFolder = dynamic_cast<TKey*>(rootFile->FindKey(name.c_str()));
200 if (dataFolder != nullptr)
201 {
202 LOGP(debug, "{} has been found!", name);
203 return dataFolder;
204 }
205 }
206 return {};
207 }
208
209 auto Get_TChain_FromFairRM(FairRootManager* rootMan) -> TChain*
210 {
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();
217 }
218} // namespace
219
221{
222 if (rate <= 0.)
223 {
224 throw R3B::logic_error(fmt::format("Refresh rate {} must be a positive floating point value", rate));
225 }
226
227 refresh_rate_ = rate;
228 refresh_period_ = std::chrono::milliseconds(static_cast<int>(1000. / rate));
229}
230
232{
233 if (event_num < 1)
234 {
235 return;
236 }
237 if (max_event_num_ == 0)
238 {
239 throw R3B::logic_error("Maximal event number has not been set up!");
240 }
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_);
243 if (time_spent > refresh_period_)
244 {
245 const auto total_time_spent = std::chrono::ceil<std::chrono::milliseconds>(now_t - begin_t_);
246 const auto processed_events = event_num - previous_event_num_;
247 const auto events_per_millisecond = [&, this]()
248 {
249 if (mode_ == Mode::piecewise)
250 {
251 return static_cast<double>(processed_events) / static_cast<double>(time_spent.count());
252 }
253 return static_cast<double>(event_num) / static_cast<double>(total_time_spent.count());
254 }();
255
256 Print(event_num, events_per_millisecond);
257
258 previous_t_ = now_t;
259 previous_event_num_ = event_num;
260 }
261}
262
263void R3BEventProgressPrinter::Print(uint64_t event_num, double speed_per_ms)
264{
265 if (speed_per_ms <= 0.)
266 {
267 return;
268 }
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,
273 "{:^6.2F}",
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",
278 event_num_str,
279 speed_str,
280 progress_str,
281 std::chrono::ceil<std::chrono::seconds>(time_left_ms),
282 run_id_);
283 std::fflush(stdout);
284}
285
286auto R3BInputRootFiles::AddFileName(std::string fileName, bool is_tree_file) -> std::optional<std::string>
287{
288 LOGP(info, "Adding {} to file source\n", fileName);
289 if (fileNames_.empty())
290 {
291 Intitialize(fileName, is_tree_file);
293 }
294 if (!ValidateFile(fileName, is_tree_file))
295 {
296 return fileName;
297 }
298 fileNames_.emplace_back(std::move(fileName));
299 return {};
300}
301
303{
304
305 for (auto const& branchName : branchList_)
306 {
307 FairRootManager::Instance()->AddBranchToList(branchName.c_str());
308 }
309}
310
312{
313 if (rootChain_ != nullptr)
314 {
315 throw R3B::logic_error("TChain has already been created!");
316 }
317 rootChain_ = chain;
318 for (auto const& filename : fileNames_)
319 {
320 rootChain_->AddFile(filename.c_str(), TTree::kMaxEntries, treeName_.c_str());
321 }
322}
323void R3BInputRootFiles::RegisterTo(FairRootManager* rootMan)
324{
325 if (is_friend_)
326 {
327 return;
328 }
329
330 if (validMainFolders_.empty())
331 {
332 throw R3B::runtime_error("There is no main folder to be registered!");
333 }
334
335 if (!is_friend_)
336 {
337 auto listOfFolders = Vector2TContainer<TObjArray>(validMainFolders_);
338 LOGP(debug, "Set {} main folder(s) to FairRootManager.", listOfFolders->GetEntries());
339 rootMan->SetListOfFolders(listOfFolders.release());
340 rootMan->SetTimeBasedBranchNameList(Vector2TContainer<TList>(timeBasedBranchList_).release());
341 SetInputFileChain(Get_TChain_FromFairRM(rootMan));
342 }
343}
344
345auto R3BInputRootFiles::ExtractMainFolder(TFile* rootFile) -> std::optional<TKey*>
346{
347 auto const folderNames =
348 std::array<std::string, 4>{ FairRootManager::GetFolderName(), "r3broot", "cbmout", "cbmroot" };
349
350 return GetDataFromAnyFolder(rootFile, folderNames);
351}
352
353auto R3BInputRootFiles::ValidateFile(const std::string& filename, bool is_tree_file) -> bool
354{
355 auto rootFile = R3B::make_rootfile(filename.c_str());
356
357 if (is_tree_file)
358 {
359 if (!is_friend_)
360 {
361 auto folder = std::make_unique<TFolder>("r3broot", "r3broot");
362 add_branches_to_folder(folder.get(), rootFile.get(), treeName_);
363 validRootFiles_.push_back(std::move(rootFile));
364 validMainFolders_.push_back(folder.release());
365 }
366 return true;
367 }
368
369 auto folderKey = ExtractMainFolder(rootFile.get());
370 auto res1 = folderKey.has_value();
371 auto res2 = HasBranchList(rootFile.get(), branchList_);
372 if (res1 and res2)
373 {
374 if (!folderName_.empty() && (folderKey.value()->GetName() != folderName_))
375 {
376 LOGP(warn, "Different folder name!");
377 }
378 if (!is_friend_)
379 {
380 validRootFiles_.push_back(std::move(rootFile));
381 validMainFolders_.push_back((folderKey.value())->ReadObject<TFolder>());
382 }
383 }
384 else
385 {
386 if (not res1)
387 {
388 LOGP(warn, "folder has no key");
389 }
390 if (not res2)
391 {
392 LOGP(warn, "HasBranchList is false!");
393 }
394 }
395 return res1 and res2;
396}
397
398auto R3BInputRootFiles::ExtractRunId(TFile* rootFile) -> std::optional<int>
399{
400 //
401 auto* header = rootFile->Get<FairFileHeader>(fileHeader_.c_str());
402 if (header == nullptr)
403 {
404 return {};
405 }
406 auto runID = header->GetRunId();
407 return runID;
408}
409
410void R3BInputRootFiles::Intitialize(std::string_view filename, bool is_tree_file)
411{
412 auto file = R3B::make_rootfile(filename.data());
413
414 if (is_tree_file)
415 {
416 branchList_ = GetBranchListFromTree(file.get(), treeName_);
417 return;
418 }
419
420 if (const auto runID = ExtractRunId(file.get()); runID.has_value() && runID.value() != 0)
421 {
422 LOGP(debug, "Successfully extract RunID {} from root file {:?}", runID.value(), filename);
423 initial_RunID_ = runID.value();
424 }
425 else
426 {
427 LOGP(error, "Failed to extract RunID from root file {:?}", filename);
428 }
429
430 if (auto folderKey = ExtractMainFolder(file.get()); folderKey.has_value())
431 {
432 folderName_ = folderKey.value()->GetName();
433 }
434 else
435 {
436 throw R3B::logic_error(fmt::format("Cannot find main folder from the root file {}!", filename));
437 }
438
439 branchList_ = GetBranchList(file.get(), "BranchList");
440
441 if (timeBasedBranchList_ = GetBranchList<TObjString>(file.get(), "TimeBasedBranchList");
442 timeBasedBranchList_.empty())
443 {
444 LOG(info) << "No time based branch list in input file";
445 }
446}
447
449{
450 if (is_friend_)
451 {
452 throw R3B::logic_error("Can not set friendFiles with another friendFile!");
453 }
454 auto chain = std::make_unique<TChain>(friendFiles.GetTitle().c_str(), friendFiles.GetFolderName().c_str());
455 friendFiles.SetInputFileChain(chain.get());
456 rootChain_->AddFriend(chain.release());
457}
458
459[[nodiscard]] auto R3BInputRootFiles::GetEntries() const -> int64_t
460{
461 if (rootChain_ == nullptr)
462 {
463 throw R3B::logic_error("Can't get entries before being initialized!");
464 }
465 return rootChain_->GetEntries();
466}
467
468R3BFileSource2::R3BFileSource2(std::vector<std::string> fileNames, std::string_view title)
469{
470 LOG(debug) << "Creating a new R3BFileSource!";
471 inputDataFiles_.SetTitle(title);
472 inputDataFiles_.SetFileHeaderName("FileHeader");
473 for (auto& name : fileNames)
474 {
475 if (name.empty())
476 {
477 continue;
478 }
479 AddFile(std::move(name));
480 }
481}
482
483R3BFileSource2::R3BFileSource2(std::string file, std::string_view title)
484 : R3BFileSource2(std::vector<std::string>{ std::move(file) }, title)
485{
486}
487
488R3BFileSource2::R3BFileSource2(std::vector<std::string> fileNames)
489 : R3BFileSource2(std::move(fileNames), DEFAULT_TITLE)
490{
491}
492
494 : R3BFileSource2(std::string{})
495{
496}
497
498void R3BFileSource2::AddFile(std::string file_name, bool is_tree_file)
499{
500 if (auto const res = inputDataFiles_.AddFileName(std::move(file_name), is_tree_file); res.has_value())
501 {
502 if (not dataFileNames_.empty())
503 {
504
505 LOGP(error,
506 "Root file {:?} is incompatible with the first root file {:?}",
507 res.value(),
508 dataFileNames_.front());
509 }
510 else
511 {
512 LOGP(error, "Failed to add the first root file {:?}", file_name);
513 }
514 }
515 dataFileNames_.emplace_back(file_name);
516}
517
518void R3BFileSource2::AddFile(std::vector<std::string> file_names, bool is_tree_file)
519{
520 for (auto& file_name : file_names)
521 {
522 AddFile(std::move(file_name), is_tree_file);
523 }
524}
525
526void R3BFileSource2::AddFriend(std::vector<std::string> file_names, bool is_tree_file)
527{
528 for (auto& file_name : file_names)
529 {
530 AddFriend(std::move(file_name), is_tree_file);
531 }
532}
533
534void R3BFileSource2::AddFriend(std::string file_name, bool is_tree_file)
535{
536 //
537 auto rootfile = R3B::make_rootfile(file_name.c_str());
538#ifdef HAS_CXX_17
539 auto friendGroup = std::find_if(inputFriendFiles_.begin(),
540 inputFriendFiles_.end(),
541 [&rootfile](const auto& friends)
542 { return HasBranchList(rootfile.get(), friends.GetBranchListRef()); });
543#else
544 auto friendGroup = std::ranges::find_if(inputFriendFiles_,
545 [&rootfile](const auto& friends)
546 { return HasBranchList(rootfile.get(), friends.GetBranchListRef()); });
547#endif
548 if (friendGroup == inputFriendFiles_.end())
549 {
550 auto newFriendGroup = R3BInputRootFiles{};
551 newFriendGroup.Make_as_friend();
552 inputFriendFiles_.push_back(std::move(newFriendGroup));
553 friendGroup = --inputFriendFiles_.end();
554 friendGroup->SetTitle(fmt::format("FriendTree_{}", inputFriendFiles_.size()));
555 }
556 auto res = friendGroup->AddFileName(file_name, is_tree_file);
557 if (res.has_value())
558 {
559 LOGP(error,
560 "Friend file {} is incompatible with the first friend file {:?}",
561 res.value(),
562 friendGroup->GetBaseFileName());
563 }
564 else
565 {
566 // TODO: really need it?
567 friendFileNames_.emplace_back(std::move(file_name));
568 }
569}
570
572{
573 if (inputDataFiles_.is_empty())
574 {
575 throw R3B::logic_error{ "No input file available!" };
576 }
577
578 inputDataFiles_.RegisterTo(FairRootManager::Instance());
579
580 for (auto& friendGroup : inputFriendFiles_)
581 {
582 inputDataFiles_.SetFriend(friendGroup);
583 }
584
585 event_progress_.SetMaxEventNum(inputDataFiles_.GetEntries());
586 event_progress_.SetRunID(inputDataFiles_.GetInitialRunID());
587
588 r3b_event_header_ = dynamic_cast<R3BEventHeader*>(FairRootManager::Instance()->GetObject("EventHeader."));
589 mc_event_header_ = dynamic_cast<FairMCEventHeader*>(FairRootManager::Instance()->GetObject("MCEventHeader."));
590
591 if (r3b_event_header_ == nullptr and mc_event_header_ == nullptr)
592 {
593 throw R3B::runtime_error(
594 "Event header from the input root file can neither be casted as R3BEventHeader nor FairMCEventHeader!");
595 }
596
597 return true;
598}
599
600void R3BFileSource2::FillEventHeader(FairEventHeader* evtHeader)
601{
602 if (evtHeader == nullptr)
603 {
604 throw R3B::logic_error("Filled event header is empty!");
605 }
606
607 auto* event_header = dynamic_cast<R3BEventHeader*>(evtHeader);
608 if (event_header == nullptr)
609 {
610 if (r3b_event_header_ != nullptr)
611 {
612 r3b_event_header_->Copy(*evtHeader);
613 }
614 }
615 else
616 {
617 if (r3b_event_header_ != nullptr)
618 {
619 (*event_header) = *r3b_event_header_;
620 }
621 else if (mc_event_header_ != nullptr)
622 {
623 (*event_header) = *mc_event_header_;
624 }
625 }
626
627 // Set runID for event header:
628 auto const init_runID = inputDataFiles_.GetInitialRunID();
629
630 if (init_runID == 0)
631 {
632 throw R3B::logic_error("RunId is not being set!");
633 }
634
635 if (GetRunId() != DEFAULT_RUN_ID and init_runID != GetRunId())
636 {
637 LOGP(warn,
638 "runID {} being set is different from the runID {} in the data file! Use the runID in the data file.",
639 GetRunId(),
640 init_runID);
641 }
642 SetRunId(init_runID); // NOLINT
643 evtHeader->SetRunId(init_runID);
644}
645
647{
648 event_end_ = (EvtEnd <= 0) ? inputDataFiles_.GetEntries() : EvtEnd; // NOLINT
649 LOGP(info, "Setting printing event max to {}", event_end_);
650 event_progress_.SetMaxEventNum(event_end_);
651 return event_end_;
652}
653
654void R3BFileSource2::ReadBranchEvent(const char* BrName)
655{
656 auto const currentEventID = r3b_event_header_->GetMCEntryNumber();
657 ReadBranchEvent(BrName, currentEventID);
658}
659
660void R3BFileSource2::ReadBranchEvent(const char* BrName, int entryID)
661{
662 auto const read_bytes = inputDataFiles_.GetChain()->FindBranch(BrName)->GetEntry(entryID);
663 if (read_bytes == 0)
664 {
665 LOG(warn) << fmt::format("Failed to read the data of the event {0} from the branch {1}", entryID, BrName);
666 }
667}
668
669Int_t R3BFileSource2::ReadEvent(unsigned int eventID)
670{
671 auto* chain = inputDataFiles_.GetChain();
672 if (fair::Logger::GetConsoleSeverity() == fair::Severity::info)
673 {
674 event_progress_.ShowProgress(eventID);
675 }
676
677 auto read_bytes = chain->GetEntry(eventID);
678 if (read_bytes == 0)
679 {
680 LOG(warn) << fmt::format("Failed to read the data of the event {0} from the source", eventID);
681 return 1;
682 }
683 return 0;
684}
685
686Bool_t R3BFileSource2::ActivateObject(TObject** obj, const char* BrName)
687{
688 auto* chain = inputDataFiles_.GetChain();
689 chain->SetBranchStatus(BrName, true);
690 chain->SetBranchAddress(BrName, obj);
691 return kTRUE;
692}
693
694Bool_t R3BFileSource2::ActivateObjectAny(void** obj, const std::type_info& info, const char* BrName)
695{
696 auto* chain = inputDataFiles_.GetChain();
697 if (chain != nullptr)
698 {
699 return ActivateObjectAnyImpl(chain, obj, info, BrName);
700 }
701 return kFALSE;
702}
703
ClassImp(R3BFileSource2)
void SetRefreshRate_Hz(float rate)
std::chrono::milliseconds refresh_period_
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_
Bool_t Init() override
static auto ExtractMainFolder(TFile *) -> std::optional< TKey * >
std::vector< TObjString > timeBasedBranchList_
auto GetTitle() const -> const auto &
R3BInputRootFiles()=default
auto GetEntries() const -> int64_t
void SetFriend(R3BInputRootFiles &friendFiles)
auto GetChain() const -> TChain *
std::string folderName_
void Intitialize(std::string_view filename, bool is_tree_file=false)
void RegisterTo(FairRootManager *)
std::string fileHeader_
auto AddFileName(std::string name, bool is_tree_file=false) -> std::optional< std::string >
std::vector< TFolder * > validMainFolders_
void SetInputFileChain(TChain *chain)
auto ExtractRunId(TFile *rootFile) -> std::optional< int >
auto GetFolderName() const -> const auto &
auto ValidateFile(const std::string &filename, bool is_tree_file=false) -> bool
std::string treeName_
std::vector< R3B::unique_rootfile > validRootFiles_
auto make_rootfile(Args &&... args)
Definition R3BShared.h:93
constexpr int DEFAULT_RUN_ID