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) {}
126 bool is_keep =
false, is_drop =
false, is_ignore =
false;
128 if (rule.find(
"keep") == 0) {
131 }
else if (rule.find(
"drop") == 0) {
134 }
else if (rule.find(
"ignore") == 0) {
140 if (
int(is_keep) +
int(is_drop) +
int(is_ignore) != 1)
return;
142 std::string srule = rule.substr(offset);
144 for (i = srule.find_first_of(
" \t\n\r"); i != std::string::npos;
145 i = srule.find_first_of(
" \t\n\r"))
149 if (srule.length() == 0)
return;
152 if (srule.back() !=
'*') srule +=
".*";
155 if (is_drop or is_ignore) {
157 if (regcomp(&guard_reg, srule.c_str(),
158 REG_EXTENDED | REG_ICASE | REG_NOSUB) == 0) {
159 bool matches_event_header =
163 if (matches_event_header) {
164 EXCEPTION_RAISE(
"BadRule",
165 "Drop/ignore rule '" + rule +
166 "' would affect EventHeader which is required by "
167 "the framework and cannot be removed.");
175 srule.erase(std::remove(srule.begin(), srule.end(),
'.'), srule.end());
178 }
else if (is_ignore) {
183 srule.erase(std::remove(srule.begin(), srule.end(),
'.'), srule.end());
186 ldmx_log(fatal) <<
"Ignore rule '" << rule
187 <<
"' will hide all input collections from processors.";
190 }
else if (is_drop) {
196 srule.erase(std::remove(srule.begin(), srule.end(),
'.'), srule.end());
199 ldmx_log(fatal) <<
"Drop rule '" << rule
200 <<
"' will drop all collections from the output file.";
215 EXCEPTION_RAISE(
"EventFile",
"No event tree in the file");
227 parent_->
tree_->SetBranchStatus(rule_pair.first.c_str(),
243 if (storeCurrentEvent)
337 parent_->
tree_->SetBranchStatus(rule_pair.first.c_str(), rule_pair.second);
357 EXCEPTION_RAISE(
"MisCall",
358 "Cannot write the run tree on an input event file.");
365 auto run_tree{
static_cast<TTree *
>(
file_->Get(
"LDMX_Run"))};
367 EXCEPTION_RAISE(
"RunTree",
368 "RunTree 'LDMX_Run' already exists in output file '" +
383 run_tree =
new TTree(
"LDMX_Run",
"LDMX run header");
387 run_tree->Branch(
"RunHeader",
"ldmx::RunHeader", &the_handle, 32000, 3);
390 for (
auto &[num, header_pair] :
run_map_) {
391 the_handle = header_pair.second;
393 if (header_pair.first)
delete header_pair.second;
403 EXCEPTION_RAISE(
"RunMap",
"Run map already contains a run with number '" +
404 std::to_string(run_number) +
"'.");
407 run_map_[run_number] = std::make_pair(
false, &run_header);
414 return run_map_.at(run_number).second;
424 EXCEPTION_RAISE(
"RunHeader",
"Unable to find header for run " +
425 std::to_string(run_number));
430 auto the_import_file{
file_};
436 if (the_import_file) {
438 TTreeReader old_run_tree(
"LDMX_Run", the_import_file);
439 TTreeReaderValue<ldmx::RunHeader> old_run_header(old_run_tree,
"RunHeader");
441 while (old_run_tree.Next()) {
442 auto *old_run_header_ptr = old_run_header.Get();
443 if (old_run_header_ptr !=
nullptr) {
446 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.
std::map< int, std::pair< bool, ldmx::RunHeader * > > run_map_
Map of run numbers to RunHeader objects.
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::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.