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, run_header] :
run_map_) {
389 the_handle = run_header.get();
400 EXCEPTION_RAISE(
"RunMap",
"Run map already contains a run with number '" +
401 std::to_string(run_number) +
"'.");
409 return run_map_.at(run_number).get();
419 EXCEPTION_RAISE(
"RunHeader",
"Unable to find header for run " +
420 std::to_string(run_number));
425 auto the_import_file{
file_};
431 if (the_import_file) {
433 TTreeReader old_run_tree(
"LDMX_Run", the_import_file);
434 TTreeReaderValue<ldmx::RunHeader> old_run_header(old_run_tree,
"RunHeader");
436 while (old_run_tree.Next()) {
437 auto* old_run_header_ptr = old_run_header.Get();
438 if (old_run_header_ptr !=
nullptr) {
439 int run_number = old_run_header_ptr->getRunNumber();
441 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.
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.
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.