5#include "TBranchElement.h"
6#include "TTreeReader.h"
10#include "Framework/EventFile.h"
11#include "Framework/Exception/Exception.h"
12#include "Framework/RunHeader.h"
22int onDiskRunHeaderVersion(TTree* run_tree) {
23 if (not run_tree)
return 0;
24 auto* branch{
dynamic_cast<TBranchElement*
>(run_tree->GetBranch(
"RunHeader"))};
25 if (not branch)
return 0;
26 return branch->GetClassVersion();
31 const std::string& filename,
EventFile* parent,
32 bool is_output_file,
bool is_single_output,
34 : file_name_(filename),
35 is_output_file_(is_output_file),
36 is_single_output_(is_single_output),
37 is_loopable_(is_loopable),
42 if (!
file_->IsOpen() or !
file_->IsWritable()) {
43 EXCEPTION_RAISE(
"FileError",
44 "Output file '" +
file_name_ +
"' is not writable.");
51 file_->SetCompressionSettings(params.
get<
int>(
"compression_setting", 9));
73 if (!
file_->IsOpen()) {
74 EXCEPTION_RAISE(
"FileError",
"Input file '" +
file_name_ +
75 "' is not readable or does not exist.");
78 bool skip_corrupted = params.
get<
bool>(
"skip_corrupted_input_files",
false);
83 if (
file_->IsZombie()) {
84 if (not skip_corrupted) {
85 EXCEPTION_RAISE(
"FileError",
"Input file '" +
file_name_ +
86 "' is corrupted. Framework will not "
87 "attempt to recover this file.");
93 auto tree_name{params.
get<std::string>(
"tree_name")};
94 tree_ =
static_cast<TTree*
>(
file_->Get(tree_name.c_str()));
96 if (not skip_corrupted) {
97 EXCEPTION_RAISE(
"FileError",
"File '" +
file_name_ +
98 "' does not have a TTree named '" +
99 tree_name +
"' in it.");
110 const std::string& filename,
bool is_loopable)
111 :
EventFile(params, filename, nullptr, false, false, is_loopable) {}
114 const std::string& filename)
115 :
EventFile(params, filename, nullptr, false, false, false) {}
118 const std::string& filename,
EventFile* parent,
119 bool is_single_output)
120 :
EventFile(params, filename, parent, true, is_single_output, false) {}
139 bool is_keep =
false, is_drop =
false, is_ignore =
false;
141 if (rule.find(
"keep") == 0) {
144 }
else if (rule.find(
"drop") == 0) {
147 }
else if (rule.find(
"ignore") == 0) {
153 if (
int(is_keep) +
int(is_drop) +
int(is_ignore) != 1)
return;
155 std::string srule = rule.substr(offset);
157 for (i = srule.find_first_of(
" \t\n\r"); i != std::string::npos;
158 i = srule.find_first_of(
" \t\n\r"))
162 if (srule.length() == 0)
return;
165 if (srule.back() !=
'*') srule +=
".*";
168 if (is_drop or is_ignore) {
170 if (regcomp(&guard_reg, srule.c_str(),
171 REG_EXTENDED | REG_ICASE | REG_NOSUB) == 0) {
172 bool matches_event_header =
176 if (matches_event_header) {
177 EXCEPTION_RAISE(
"BadRule",
178 "Drop/ignore rule '" + rule +
179 "' would affect EventHeader which is required by "
180 "the framework and cannot be removed.");
188 srule.erase(std::remove(srule.begin(), srule.end(),
'.'), srule.end());
191 }
else if (is_ignore) {
196 srule.erase(std::remove(srule.begin(), srule.end(),
'.'), srule.end());
199 ldmx_log(fatal) <<
"Ignore rule '" << rule
200 <<
"' will hide all input collections from processors.";
203 }
else if (is_drop) {
209 srule.erase(std::remove(srule.begin(), srule.end(),
'.'), srule.end());
212 ldmx_log(fatal) <<
"Drop rule '" << rule
213 <<
"' will drop all collections from the output file.";
228 EXCEPTION_RAISE(
"EventFile",
"No event tree in the file");
240 parent_->
tree_->SetBranchStatus(rule_pair.first.c_str(),
256 if (storeCurrentEvent)
350 parent_->
tree_->SetBranchStatus(rule_pair.first.c_str(), rule_pair.second);
370 EXCEPTION_RAISE(
"MisCall",
371 "Cannot write the run tree on an input event file.");
377 for (
auto& [num, run_header] :
run_map_) run_header->setCompleted(completed);
394 file_->Delete(
"LDMX_Run;*");
395 run_tree_ =
new TTree(
"LDMX_Run",
"LDMX run header");
399 run_tree_->Branch(
"RunHeader",
"ldmx::RunHeader", &the_handle, 32000, 3);
402 std::unique_ptr<ldmx::RunHeader> root_allocated(the_handle);
405 for (
auto& [num, run_header] :
run_map_) {
406 the_handle = run_header.get();
410 run_tree_->Write(
"", TObject::kOverwrite);
415 int run_number = run_header->getRunNumber();
418 EXCEPTION_RAISE(
"RunMap",
"Run map already contains a run with number '" +
419 std::to_string(run_number) +
"'.");
427 return run_map_.at(run_number).get();
437 EXCEPTION_RAISE(
"RunHeader",
"Unable to find header for run " +
438 std::to_string(run_number));
442 std::vector<int> incomplete;
445 for (
const auto& [num, run_header] :
run_map_) {
446 if (not run_header->isCompleted()) incomplete.push_back(num);
453 auto the_import_file{
file_};
459 if (the_import_file) {
461 TTreeReader old_run_tree(
"LDMX_Run", the_import_file);
462 TTreeReaderValue<ldmx::RunHeader> old_run_header(old_run_tree,
"RunHeader");
465 onDiskRunHeaderVersion(old_run_tree.GetTree()) >=
468 while (old_run_tree.Next()) {
469 auto* old_run_header_ptr = old_run_header.Get();
470 if (old_run_header_ptr !=
nullptr) {
471 int run_number = old_run_header_ptr->getRunNumber();
473 std::make_shared<ldmx::RunHeader>(*old_run_header_ptr);
Class implementing an event buffer system for storing event data.
This class manages all ROOT file input/output operations.
void updateParent(EventFile *parent)
Change pointer to different parent file.
TFile * file_
The backing TFile for this EventFile.
void addDrop(const std::string &rule)
Add a rule for dropping collections from the output.
void setupEvent(Event *evt)
Set an Event object containing the event data to work with this file.
std::map< int, std::shared_ptr< ldmx::RunHeader > > run_map_
Map of run numbers to RunHeader objects (owned via shared_ptr)
Long64_t entries_
The number of entries in the tree.
void writeRunHeader(std::shared_ptr< ldmx::RunHeader > runHeader)
Write the run header into the run map.
bool nextEvent(bool storeCurrentEvent=true)
Prepare the next event.
void writeRunTree(bool completed=false)
Write the map of run headers to the file as a TTree of RunHeader.
ldmx::RunHeader * getRunHeaderPtr(int runNumber)
Update the RunHeader for a given run, if it exists in the input file.
Long64_t ientry_
The current entry in the tree.
std::vector< std::pair< std::string, bool > > pre_clone_rules_
Pre-clone rules.
bool run_headers_have_completeness_
True when the run headers we read were written with a completion flag.
TTree * run_tree_
The run tree, owned by file_ once written.
bool is_loopable_
True if this is an input file with pileup overlay events */.
void importRunHeaders()
Fill the internal map of run numbers to RunHeader objects from the input file.
std::vector< int > getIncompleteRuns() const
The runs in this file whose writer did not close cleanly.
int skipToEvent(int offset)
Skip events using an offset.
std::string file_name_
The file name.
ldmx::RunHeader & getRunHeader(int runNumber)
Get the RunHeader for a given run, if it exists in the input file.
bool is_single_output_
True if there is only one output file.
EventFile(const framework::config::Parameters ¶ms, const std::string &filename, EventFile *parent, bool isOutputFile, bool isSingleOutput, bool isLoopable)
Constructor to make a general file.
EventFile * parent_
A parent file containing event data.
std::vector< std::string > reactivate_rules_
Vector of drop rules that have been parsed and need to be used to reactivate these branches on the in...
bool is_output_file_
True if file is an output file being written to disk.
TTree * tree_
The tree with event data.
Event * event_
The object containing the actual event data (trees and branches).
bool isCorrupted() const
Check if the file we have is corrupted.
Implements an event buffer system for storing event data.
void addIgnore(const std::string &exp)
Add an ignore rule to the list of regex expressions to ignore on input.
void clear()
Clear this object's data (including passengers).
TTree * createTree()
Create the output data tree.
void setOutputTree(TTree *tree)
Set the output data tree.
void beforeFill()
Action to be executed before the tree is filled.
void onEndOfEvent()
Perform end of event action (doesn't do anything right now).
bool nextEvent()
Go to the next event by retrieving the event header.
void setInputTree(TTree *tree)
Set the input data tree.
void addDrop(const std::string &exp)
Add a drop rule to the list of regex expressions to drop.
Class encapsulating parameters for configuring a processor.
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
All classes in the ldmx-sw project use this namespace.