15#include "Framework/EventFile.h"
17#include "Framework/Exception/Exception.h"
18#include "Framework/Logger.h"
19#include "Framework/NtupleManager.h"
20#include "Framework/RunHeader.h"
26volatile std::sig_atomic_t preemption_received_ = 0;
31 : conditions_{*this} {
37 max_tries_ = configuration.
get<
int>(
"max_tries_per_event", 1);
44 configuration.
get<
bool>(
"skip_corrupted_input_files",
false);
46 configuration.
get<
bool>(
"allow_incomplete_input_files",
false);
48 input_files_ = configuration.
get<std::vector<std::string>>(
"input_files", {});
50 configuration.
get<std::vector<std::string>>(
"output_files", {});
58 auto run{configuration.
get<
int>(
"run", -1)};
61 auto libs{configuration.
get<std::vector<std::string>>(
"libraries", {})};
62 std::set<std::string> libraries_loaded;
63 for (
const auto& lib : libs) {
64 if (libraries_loaded.find(lib) != libraries_loaded.end()) {
68 void* handle = dlopen(lib.c_str(), RTLD_NOW);
69 if (handle ==
nullptr) {
70 EXCEPTION_RAISE(
"LibraryLoadFailure",
71 "Error loading library '" + lib +
"':" + dlerror());
74 libraries_loaded.insert(lib);
78 configuration.
get<
bool>(
"skim_default_is_keep",
true));
80 configuration.
get<std::vector<std::string>>(
"skim_rules", {})};
81 for (
size_t i = 0; i < skim_rules.size(); i += 2) {
85 auto sequence{configuration.
get<std::vector<framework::config::Parameters>>(
87 if (sequence.empty() && configuration.
get<
bool>(
"testing_mode",
false)) {
90 "No sequence has been defined. What should I be doing?\nUse "
91 "p.sequence to tell me what processors to run.");
93 for (
auto proc : sequence) {
94 auto class_name{proc.get<std::string>(
"class_name")};
95 auto instance_name{proc.get<std::string>(
"instance_name")};
97 EventProcessor::Factory::get().make(class_name, instance_name, *
this)};
99 EXCEPTION_RAISE(
"UnableToCreate",
100 "The EventProcessor Factory was unable to create " +
101 instance_name +
" of type " + class_name +
102 ". Did you inherit from framework::Producer or "
103 "framework::Analyzer? "
104 "Did you DECLARE_PRODUCER or DECLARE_ANALYZER in the "
105 "implementation (.cxx) file? "
106 "Did you use the class's full name (including "
107 "namespaces) in the Python configuration class? "
108 "Does the Python configuration class reference the "
109 "correct library it is a part of?");
112 proc.get<std::vector<framework::config::Parameters>>(
"histograms", {})};
113 if (!histograms.empty()) {
114 ep.value()->getHistoDirectory();
115 ep.value()->createHistograms(histograms);
117 ep.value()->configure(proc);
121 auto conditions_object_providers{
122 configuration.
get<std::vector<framework::config::Parameters>>(
123 "conditions_object_providers", {})};
124 for (
auto cop : conditions_object_providers) {
125 auto class_name{cop.get<std::string>(
"class_name")};
126 auto object_name{cop.get<std::string>(
"object_name")};
127 auto tag_name{cop.get<std::string>(
"tag_name")};
132 bool log_performance = configuration.
get<
bool>(
"log_performance",
false);
133 if (log_performance) {
134 std::vector<std::string> names{
sequence_.size()};
135 for (std::size_t i{0}; i <
sequence_.size(); i++) {
162 auto n_events_processed{0};
176 std::size_t i_proc{0};
184 proc->onProcessStart();
195 EXCEPTION_RAISE(
"InvalidConfig",
196 "No input files or output files were given.");
198 ldmx_log(warn) <<
"Several output files given with no input files. "
200 <<
"' will be used.";
213 run_header->setRunStart(std::time(
nullptr));
217 newRun(*run_header, &out_file);
225 ldmx_log(warn) <<
"The total_events was set, so max_events and "
226 "max_tries_per_event will be ignored!";
229 while (n_events_processed < event_limit) {
231 if (preemption_received_) {
233 <<
"Preemption signal received, stopping event generation";
249 bool completed =
process(n_events_processed, num_tries, the_event);
254 if (completed) num_tries = 0;
260 n_events_processed++;
269 run_header->setRunEnd(std::time(
nullptr));
270 run_header->setNumTries(total_tries);
274 if (n_events_processed < total_tries / 10000) {
276 <<
"Less than 1 event out of every 10k events tried was accepted!";
278 <<
"This could be an issue with your filtering and biasing procedure "
279 "since this is incredibly inefficient.";
287 bool single_output =
false;
289 single_output =
true;
292 EXCEPTION_RAISE(
"Process",
293 "Unable to handle case of different number of input and "
294 "output files (other than zero/one ouput file).");
304 ldmx_log(warn) <<
"Input file '" << infilename
305 <<
"' was found to be corrupted. Skipping.";
310 "We should never get here. "
311 "EventFile is corrupted but we aren't skipping corrupted inputs. "
312 "EventFile should be throwing its own exceptions in this case.");
317 if (not incomplete_runs.empty()) {
318 std::string run_list;
319 for (
int run : incomplete_runs) {
320 if (not run_list.empty()) run_list +=
", ";
321 run_list += std::to_string(
run);
324 ldmx_log(warn) <<
"Input file '" << infilename <<
"' holds run(s) "
326 <<
" that were never finished, so events are missing. "
327 "Processing it anyway because "
328 "'allow_incomplete_input_files' is set.";
332 "Input file '" + infilename +
"' holds run(s) " + run_list +
333 " that were never finished, so events are missing from the "
334 "end of them. Set 'allow_incomplete_input_files' on the "
335 "Process to read it anyway, but know that the sample it "
336 "gives you is biased.");
340 ldmx_log(info) <<
"Opening file " << infilename;
349 if (!single_output or ifile == 0) {
358 master_file = out_file;
360 EXCEPTION_RAISE(
"Process",
"Unable to construct output file for " +
369 master_file = out_file;
376 master_file = &in_file;
382 n_events_processed++;
385 bool event_completed =
true;
386 while (!preemption_received_ &&
400 ldmx_log(info) <<
"Got new run header from '"
407 "Run header for run " + std::to_string(was_run) +
408 " was not found in '" + master_file->
getFileName() +
409 "'. Conditions cannot be initialised without it.");
413 event_completed =
process(n_events_processed, 1, the_event);
418 n_events_processed++;
421 if (preemption_received_) {
422 ldmx_log(fatal) <<
"Preemption signal received, stopping event "
423 "processing and closing files";
426 bool leave_early{
false};
428 ldmx_log(info) <<
"Reached event limit of " <<
event_limit_
434 ldmx_log(warn) <<
"Processing interrupted";
438 ldmx_log(info) <<
"Closing file " << infilename;
444 if (out_file and !single_output) {
472 proc->onProcessEnd();
489 TDirectory* child = owner->mkdir((
char*)dirName.c_str());
490 if (child) child->cd();
495 TDirectory* owner{
nullptr};
501 "You did not provide the necessary histogram file name to "
502 "put your histograms (or performance data) in.\n Provide this "
503 "name in the python configuration with 'p.histogramFile = "
504 "\"myHistFile.root\"' where p is the Process object.");
524 std::size_t i_proc{0};
529 proc->beforeNewRun(header);
545 proc->onNewRun(header);
550 ldmx_log(info) << header;
559 ldmx_log(info) <<
"Processing " << n + 1 <<
" Run "
560 <<
event.getEventHeader().getRun() <<
" Event "
561 <<
event.getEventHeader().getEventNumber() <<
" ("
562 << t.AsString(
"lc") <<
")";
566 std::size_t i_proc{0};
572 proc->process(event);
593 std::size_t i_proc{0};
598 proc->onFileOpen(file);
607 std::size_t i_proc{0};
612 proc->onFileClose(file);
Base classes for all user event processing components to extend.
Class implementing an event buffer system for storing event data.
Class which represents the process under execution.
Specific exception used to abort an event.
void onProcessStart()
Calls onProcessStart for all ConditionsObjectProviders.
void onNewRun(ldmx::RunHeader &)
Calls onNewRun for all ConditionsObjectProviders.
void createConditionsObjectProvider(const std::string &classname, const std::string &instancename, const std::string &tagname, const framework::config::Parameters ¶ms)
Create a ConditionsObjectProvider given the information.
This class manages all ROOT file input/output operations.
void updateParent(EventFile *parent)
Change pointer to different parent file.
const std::string & getFileName()
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.
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.
std::vector< int > getIncompleteRuns() const
The runs in this file whose writer did not close cleanly.
bool isCorrupted() const
Check if the file we have is corrupted.
Base class for all event processing components.
Implements an event buffer system for storing event data.
int getEventNumber() const
Get the event number.
void onEndOfFile()
Perform end of file action.
ldmx::EventHeader & getEventHeader()
Get the event header.
const ldmx::EventHeader * getEventHeaderPtr()
Get the event header as a pointer.
void clear()
Reset all of the variables to their limits.
static NtupleManager & getInstance()
void reset()
Reset NtupleManager to blank state.
int log_frequency_
The frequency with which event info is printed.
bool skip_corrupted_input_files_
allow the Process to skip input files that are corrupted
std::string histo_filename_
Filename for histograms and other user products.
int max_tries_
Maximum number of attempts to make before giving up on an event.
int run_for_generation_
Run number to use if generating events.
int compression_setting_
Compression setting to pass to output files.
void run()
Run the process.
int event_limit_
Limit on events to process.
std::string pass_name_
Processing pass name.
TFile * histo_t_file_
TFile for histograms and other user products.
bool allow_incomplete_input_files_
allow the Process to read input files whose runs never finished
TDirectory * openHistoFile()
Open a ROOT TFile to write histograms and TTrees.
int total_events_
Number of events we'd like to produce independetly of the number of tries it would take.
~Process()
Class Destructor.
void onFileClose(EventFile &file) const
File is begin closed.
std::vector< EventProcessor * > sequence_
Ordered list of EventProcessors to execute.
std::vector< std::string > drop_keep_rules_
Set of drop/keep rules.
ldmx::RunHeader * run_header_
Pointer to the current RunHeader, used for Conditions information.
TDirectory * makeHistoDirectory(const std::string &dirName)
Construct a TDirectory* for the given module.
performance::Tracker * performance_
class with calls backs to track performance measurements of software
int min_events_
When reading a file in, what's the first event to read.
StorageControl storage_controller_
Storage controller.
std::vector< std::string > output_files_
List of output file names.
void newRun(ldmx::RunHeader &header, EventFile *out)
Run through the processors and let them know that we are starting a new run.
std::vector< std::string > input_files_
List of input files to process.
const ldmx::EventHeader * event_header_
Pointer to the current EventHeader, used for Conditions information.
bool process(int n, int n_tries, Event &event) const
Process the input event through the sequence of processors.
void onFileOpen(EventFile &file) const
File is being opened.
Conditions conditions_
Set of ConditionsProviders.
Process(const framework::config::Parameters &configuration)
Class constructor.
int getRunNumber() const
Get the current run number or the run number to be used when initiating new events from the job.
framework::config::Parameters config_
The parameters used to configure this class.
void setDefaultKeep(bool keep)
Set the default state.
bool keepEvent(bool event_completed) const
Determine if the current event should be kept, based on the defined rules.
void addRule(const std::string &processor_pat, const std::string &purpose_pat)
Add a listening rule.
void resetEventState()
Reset the event-by-event state.
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.