5#include "TTreeReader.h"
9#include "Framework/EventFile.h"
10#include "Framework/Exception/Exception.h"
11#include "Framework/RunHeader.h"
16 const std::string& filename,
EventFile* parent,
17 bool is_output_file,
bool is_single_output,
19 : file_name_(filename),
20 is_output_file_(is_output_file),
21 is_single_output_(is_single_output),
22 is_loopable_(is_loopable),
27 if (!
file_->IsOpen() or !
file_->IsWritable()) {
28 EXCEPTION_RAISE(
"FileError",
29 "Output file '" +
file_name_ +
"' is not writable.");
36 file_->SetCompressionSettings(params.
get<
int>(
"compression_setting", 9));
58 if (!
file_->IsOpen()) {
59 EXCEPTION_RAISE(
"FileError",
"Input file '" +
file_name_ +
60 "' is not readable or does not exist.");
63 bool skip_corrupted = params.
get<
bool>(
"skip_corrupted_input_files",
false);
68 if (
file_->IsZombie()) {
69 if (not skip_corrupted) {
70 EXCEPTION_RAISE(
"FileError",
"Input file '" +
file_name_ +
71 "' is corrupted. Framework will not "
72 "attempt to recover this file.");
78 auto tree_name{params.
get<std::string>(
"tree_name")};
79 tree_ =
static_cast<TTree*
>(
file_->Get(tree_name.c_str()));
81 if (not skip_corrupted) {
82 EXCEPTION_RAISE(
"FileError",
"File '" +
file_name_ +
83 "' does not have a TTree named '" +
84 tree_name +
"' in it.");
95 const std::string& filename,
bool is_loopable)
96 :
EventFile(params, filename, nullptr, false, false, is_loopable) {}
99 const std::string& filename)
100 :
EventFile(params, filename, nullptr, false, false, false) {}
103 const std::string& filename,
EventFile* parent,
104 bool is_single_output)
105 :
EventFile(params, filename, parent, true, is_single_output, false) {}
124 bool is_keep =
false, is_drop =
false, is_ignore =
false;
126 if (rule.find(
"keep") == 0) {
129 }
else if (rule.find(
"drop") == 0) {
132 }
else if (rule.find(
"ignore") == 0) {
138 if (
int(is_keep) +
int(is_drop) +
int(is_ignore) != 1)
return;
140 std::string srule = rule.substr(offset);
142 for (i = srule.find_first_of(
" \t\n\r"); i != std::string::npos;
143 i = srule.find_first_of(
" \t\n\r"))
147 if (srule.length() == 0)
return;
150 if (srule.back() !=
'*') srule +=
".*";
153 if (is_drop or is_ignore) {
155 if (regcomp(&guard_reg, srule.c_str(),
156 REG_EXTENDED | REG_ICASE | REG_NOSUB) == 0) {
157 bool matches_event_header =
161 if (matches_event_header) {
162 EXCEPTION_RAISE(
"BadRule",
163 "Drop/ignore rule '" + rule +
164 "' would affect EventHeader which is required by "
165 "the framework and cannot be removed.");
173 srule.erase(std::remove(srule.begin(), srule.end(),
'.'), srule.end());
176 }
else if (is_ignore) {
181 srule.erase(std::remove(srule.begin(), srule.end(),
'.'), srule.end());
184 ldmx_log(fatal) <<
"Ignore rule '" << rule
185 <<
"' will hide all input collections from processors.";
188 }
else if (is_drop) {
194 srule.erase(std::remove(srule.begin(), srule.end(),
'.'), srule.end());
197 ldmx_log(fatal) <<
"Drop rule '" << rule
198 <<
"' will drop all collections from the output file.";
213 EXCEPTION_RAISE(
"EventFile",
"No event tree in the file");
225 parent_->
tree_->SetBranchStatus(rule_pair.first.c_str(),
241 if (storeCurrentEvent)
335 parent_->
tree_->SetBranchStatus(rule_pair.first.c_str(), rule_pair.second);
355 EXCEPTION_RAISE(
"MisCall",
356 "Cannot write the run tree on an input event file.");
363 auto run_tree{
static_cast<TTree*
>(
file_->Get(
"LDMX_Run"))};
365 EXCEPTION_RAISE(
"RunTree",
366 "RunTree 'LDMX_Run' already exists in output file '" +
381 run_tree =
new TTree(
"LDMX_Run",
"LDMX run header");
385 run_tree->Branch(
"RunHeader",
"ldmx::RunHeader", &the_handle, 32000, 3);
388 for (
auto& [num, header_pair] :
run_map_) {
389 the_handle = header_pair.second;
391 if (header_pair.first)
delete header_pair.second;
401 EXCEPTION_RAISE(
"RunMap",
"Run map already contains a run with number '" +
402 std::to_string(run_number) +
"'.");
405 run_map_[run_number] = std::make_pair(
false, &run_header);
412 return run_map_.at(run_number).second;
422 EXCEPTION_RAISE(
"RunHeader",
"Unable to find header for run " +
423 std::to_string(run_number));
428 auto the_import_file{
file_};
434 if (the_import_file) {
436 TTreeReader old_run_tree(
"LDMX_Run", the_import_file);
437 TTreeReaderValue<ldmx::RunHeader> old_run_header(old_run_tree,
"RunHeader");
439 while (old_run_tree.Next()) {
440 auto* old_run_header_ptr = old_run_header.Get();
441 if (old_run_header_ptr !=
nullptr) {
444 run_map_[old_run_header_ptr->getRunNumber()] =
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.
Long64_t entries_
The number of entries in the tree.
void writeRunTree()
Write the map of run headers to the file as a TTree of RunHeader.
bool nextEvent(bool storeCurrentEvent=true)
Prepare the next event.
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.
void writeRunHeader(ldmx::RunHeader &runHeader)
Write the run header into the run map.
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.
int skipToEvent(int offset)
Skip events using an offset.
std::map< int, std::pair< bool, ldmx::RunHeader * > > run_map_
Map of run numbers to RunHeader objects.
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.