LDMX Software
Process.cxx
Go to the documentation of this file.
1
6#include "Framework/Process.h"
7
8#include <dlfcn.h>
9
10#include <iostream>
11#include <memory>
12#include <set>
13
14#include "Framework/Event.h"
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"
21#include "TFile.h"
22#include "TROOT.h"
23
24// Preemption flag that can be set by signal handlers
25// NOLINTNEXTLINE(readability-identifier-naming)
26volatile std::sig_atomic_t preemption_received_ = 0;
27
28namespace framework {
29
31 : conditions_{*this} {
32 config_ = configuration;
33
34 pass_name_ = configuration.get<std::string>("pass_name", "");
35 histo_filename_ = configuration.get<std::string>("histogram_file", "");
36
37 max_tries_ = configuration.get<int>("max_tries_per_event", 1);
38 event_limit_ = configuration.get<int>("max_events", -1);
39 min_events_ = configuration.get<int>("min_events", -1);
40 total_events_ = configuration.get<int>("total_events", -1);
41 log_frequency_ = configuration.get<int>("log_frequency", -1);
42 compression_setting_ = configuration.get<int>("compression_setting", 9);
44 configuration.get<bool>("skip_corrupted_input_files", false);
45
46 input_files_ = configuration.get<std::vector<std::string>>("input_files", {});
48 configuration.get<std::vector<std::string>>("output_files", {});
49 drop_keep_rules_ = configuration.get<std::vector<std::string>>("keep", {});
50
51 event_header_ = 0;
52
53 // set up the logging for this run
54 logging::open(configuration.get<framework::config::Parameters>("logger", {}));
55
56 auto run{configuration.get<int>("run", -1)};
57 if (run > 0) run_for_generation_ = run;
58
59 auto libs{configuration.get<std::vector<std::string>>("libraries", {})};
60 std::set<std::string> libraries_loaded;
61 for (const auto& lib : libs) {
62 if (libraries_loaded.find(lib) != libraries_loaded.end()) {
63 continue;
64 }
65
66 void* handle = dlopen(lib.c_str(), RTLD_NOW);
67 if (handle == nullptr) {
68 EXCEPTION_RAISE("LibraryLoadFailure",
69 "Error loading library '" + lib + "':" + dlerror());
70 }
71
72 libraries_loaded.insert(lib);
73 }
74
76 configuration.get<bool>("skim_default_is_keep", true));
77 auto skim_rules{
78 configuration.get<std::vector<std::string>>("skim_rules", {})};
79 for (size_t i = 0; i < skim_rules.size(); i += 2) {
80 storage_controller_.addRule(skim_rules[i], skim_rules[i + 1]);
81 }
82
83 auto sequence{configuration.get<std::vector<framework::config::Parameters>>(
84 "sequence", {})};
85 if (sequence.empty() && configuration.get<bool>("testing_mode", false)) {
86 EXCEPTION_RAISE(
87 "NoSeq",
88 "No sequence has been defined. What should I be doing?\nUse "
89 "p.sequence to tell me what processors to run.");
90 }
91 for (auto proc : sequence) {
92 auto class_name{proc.get<std::string>("class_name")};
93 auto instance_name{proc.get<std::string>("instance_name")};
94 auto ep{
95 EventProcessor::Factory::get().make(class_name, instance_name, *this)};
96 if (not ep) {
97 EXCEPTION_RAISE("UnableToCreate",
98 "The EventProcessor Factory was unable to create " +
99 instance_name + " of type " + class_name +
100 ". Did you inherit from framework::Producer or "
101 "framework::Analyzer? "
102 "Did you DECLARE_PRODUCER or DECLARE_ANALYZER in the "
103 "implementation (.cxx) file? "
104 "Did you use the class's full name (including "
105 "namespaces) in the Python configuration class? "
106 "Does the Python configuration class reference the "
107 "correct library it is a part of?");
108 }
109 auto histograms{
110 proc.get<std::vector<framework::config::Parameters>>("histograms", {})};
111 if (!histograms.empty()) {
112 ep.value()->getHistoDirectory();
113 ep.value()->createHistograms(histograms);
114 }
115 ep.value()->configure(proc);
116 sequence_.push_back(ep.value());
117 }
118
119 auto conditions_object_providers{
120 configuration.get<std::vector<framework::config::Parameters>>(
121 "conditions_object_providers", {})};
122 for (auto cop : conditions_object_providers) {
123 auto class_name{cop.get<std::string>("class_name")};
124 auto object_name{cop.get<std::string>("object_name")};
125 auto tag_name{cop.get<std::string>("tag_name")};
126 conditions_.createConditionsObjectProvider(class_name, object_name,
127 tag_name, cop);
128 }
129
130 bool log_performance = configuration.get<bool>("log_performance", false);
131 if (log_performance) {
132 std::vector<std::string> names{sequence_.size()};
133 for (std::size_t i{0}; i < sequence_.size(); i++) {
134 names[i] = sequence_[i]->getName();
135 }
137 new performance::Tracker(makeHistoDirectory("performance"), names);
138 }
139}
140
142 // need to delete the performance object so that it is
143 // written before we close the histogram file below
144 if (performance_) delete performance_;
145 for (EventProcessor* ep : sequence_) {
146 delete ep;
147 }
148 if (histo_t_file_) {
149 histo_t_file_->Write();
150 delete histo_t_file_;
151 histo_t_file_ = 0;
152 }
153}
154
157
158 // Counter to keep track of the number of events that have been
159 // procesed
160 auto n_events_processed{0};
161
162 // make sure the ntuple manager is in a blank state
164
165 // event bus for this process
166 Event the_event(pass_name_);
167 // the EventHeader object is created with the event bus as
168 // one of its members, we obtain a pointer for the header
169 // here so we can share it with the conditions system
170 event_header_ = the_event.getEventHeaderPtr();
172
173 // Start by notifying everyone that modules processing is beginning
174 std::size_t i_proc{0};
175 if (performance_)
176 performance_->start(performance::Callback::onProcessStart, 0);
178 for (auto proc : sequence_) {
179 i_proc++;
180 if (performance_)
181 performance_->start(performance::Callback::onProcessStart, i_proc);
182 proc->onProcessStart();
183 if (performance_)
184 performance_->stop(performance::Callback::onProcessStart, i_proc);
185 }
186 if (performance_)
187 performance_->stop(performance::Callback::onProcessStart, 0);
188
189 // If we have no input files, but do have an event number, run for
190 // that number of events and generate an output file.
191 if (input_files_.empty() && event_limit_ > 0) {
192 if (output_files_.empty()) {
193 EXCEPTION_RAISE("InvalidConfig",
194 "No input files or output files were given.");
195 } else if (output_files_.size() > 1) {
196 ldmx_log(warn) << "Several output files given with no input files. "
197 << "Only the first output file '" << output_files_.at(0)
198 << "' will be used.";
199 }
200 std::string output_file_name = output_files_.at(0);
201
202 // Configure the event file to create an output file with no parent. This
203 // requires setting the parameters isOutputFile and isSingleOutput to true.
204 EventFile out_file(config_, output_file_name, nullptr, true, true, false);
205 onFileOpen(out_file);
206 out_file.setupEvent(&the_event);
207
208 for (auto rule : drop_keep_rules_) out_file.addDrop(rule);
209
210 auto run_header = std::make_shared<ldmx::RunHeader>(run_for_generation_);
211 run_header->setRunStart(std::time(nullptr)); // set run starting
212 run_header_ = run_header.get(); // give handle to run header to process
213 out_file.writeRunHeader(run_header); // add run header to file
214
215 newRun(*run_header);
216
217 int total_tries = 0; // total number of tries for entire run
218 int num_tries = 0; // number of tries for the current event number
219 int event_limit = event_limit_;
220 if (total_events_ > 0) {
221 // Have a warning at the first event
222 if (num_tries == 0)
223 ldmx_log(warn) << "The total_events was set, so max_events and "
224 "max_tries_per_event will be ignored!";
225 event_limit = total_events_;
226 }
227 while (n_events_processed < event_limit) {
228 // Check for preemption before processing each event
229 if (preemption_received_) {
230 ldmx_log(fatal)
231 << "Preemption signal received, stopping event generation";
232 break;
233 }
234
235 total_tries++;
236 num_tries++;
237
238 ldmx::EventHeader& eh = the_event.getEventHeader();
240 eh.setEventNumber(n_events_processed + 1);
241 eh.setTimestamp(TTimeStamp());
242
243 // reset the storage controller state
246
247 bool completed = process(n_events_processed, num_tries, the_event);
248
249 out_file.nextEvent(storage_controller_.keepEvent(completed));
250
251 // reset try counter only on successfully completed events
252 if (completed) num_tries = 0;
253
254 // we use modulo here insetad of >= because we want to carry
255 // the number of tries across the number of events processed boundary
256 // total_events_ is set let's not exit until that's reached
257 if (completed or (total_events_ < 0 and num_tries % max_tries_ == 0)) {
258 n_events_processed++; // increment events made
259 NtupleManager::getInstance().fill(); // fill ntuples
260 }
261
263 }
264
265 onFileClose(out_file);
266
267 run_header->setRunEnd(std::time(nullptr));
268 run_header->setNumTries(total_tries);
269 out_file.writeRunTree();
270
271 // Give a warning that this filter has very low efficiency
272 if (n_events_processed < total_tries / 10000) { // integer division is okay
273 ldmx_log(warn)
274 << "Less than 1 event out of every 10k events tried was accepted!";
275 ldmx_log(warn)
276 << "This could be an issue with your filtering and biasing procedure "
277 "since this is incredibly inefficient.";
278 }
279
280 } else {
281 // there are input files
282
283 EventFile* out_file(0);
284
285 bool single_output = false;
286 if (output_files_.size() == 1) {
287 single_output = true;
288 } else if (!output_files_.empty() and
289 output_files_.size() != input_files_.size()) {
290 EXCEPTION_RAISE("Process",
291 "Unable to handle case of different number of input and "
292 "output files (other than zero/one ouput file).");
293 }
294
295 // next, loop through the files
296 int ifile = 0;
297 int was_run = -1;
298 for (auto infilename : input_files_) {
299 EventFile in_file(config_, infilename);
300 if (in_file.isCorrupted()) {
302 ldmx_log(warn) << "Input file '" << infilename
303 << "' was found to be corrupted. Skipping.";
304 continue;
305 } else {
306 EXCEPTION_RAISE(
307 "BadCode",
308 "We should never get here. "
309 "EventFile is corrupted but we aren't skipping corrupted inputs. "
310 "EventFile should be throwing its own exceptions in this case.");
311 }
312 }
313
314 ldmx_log(info) << "Opening file " << infilename;
315 onFileOpen(in_file);
316
317 // configure event file that will be iterated over
318 EventFile* master_file;
319 if (!output_files_.empty()) {
320 // setup new output file if either
321 // 1) we are not in single output mode
322 // 2) this is the first input file
323 if (!single_output or ifile == 0) {
324 // setup new output file
325 out_file = new EventFile(config_, output_files_[ifile], &in_file,
326 single_output);
327 ifile++;
328
329 // setup theEvent we will iterate over
330 if (out_file) {
331 out_file->setupEvent(&the_event);
332 master_file = out_file;
333 } else {
334 EXCEPTION_RAISE("Process", "Unable to construct output file for " +
335 output_files_[ifile]);
336 }
337
338 for (auto rule : drop_keep_rules_) out_file->addDrop(rule);
339
340 } else {
341 // all other input files
342 out_file->updateParent(&in_file);
343 master_file = out_file;
344
345 } // check if in singleOutput mode
346
347 } else {
348 // empty output file list, use inputFile as master file
349 in_file.setupEvent(&the_event);
350 master_file = &in_file;
351 }
352
353 // In case we'd like to skip up to the event of min_events_
354 while (n_events_processed < (min_events_ - 1) &&
355 master_file->nextEvent(false)) {
356 n_events_processed++;
357 }
358
359 bool event_completed = true;
360 while (!preemption_received_ &&
361 master_file->nextEvent(
362 storage_controller_.keepEvent(event_completed)) &&
363 ((event_limit_ < 0) || (n_events_processed < event_limit_))) {
364 // clean up for storage control calculation
367
368 // notify for new run if necessary
369 if (the_event.getEventHeader().getRun() != was_run) {
370 was_run = the_event.getEventHeader().getRun();
371 ldmx::RunHeader* rh{master_file->getRunHeaderPtr(was_run)};
372 if (rh != nullptr) {
373 run_header_ = rh;
374 ldmx_log(info) << "Got new run header from '"
375 << master_file->getFileName() << "'";
377 } else {
378 ldmx_log(warn) << "Run header for run " << was_run
379 << " was not found!";
380 }
381 }
382
383 event_completed = process(n_events_processed, 1, the_event);
384
385 if (event_completed) NtupleManager::getInstance().fill();
387
388 n_events_processed++;
389 } // loop through events
390
391 if (preemption_received_) {
392 ldmx_log(fatal) << "Preemption signal received, stopping event "
393 "processing and closing files";
394 }
395
396 bool leave_early{false};
397 if (event_limit_ > 0 && n_events_processed == event_limit_) {
398 ldmx_log(info) << "Reached event limit of " << event_limit_
399 << " events";
400 leave_early = true;
401 }
402
403 if (event_limit_ == 0 && n_events_processed > event_limit_) {
404 ldmx_log(warn) << "Processing interrupted";
405 leave_early = true;
406 }
407
408 ldmx_log(info) << "Closing file " << infilename;
409 onFileClose(in_file);
410
411 // Reset the event in case of multiple input files
412 the_event.onEndOfFile();
413
414 if (out_file and !single_output) {
415 out_file->writeRunTree();
416 delete out_file;
417 out_file = nullptr;
418 }
419
420 if (leave_early) {
421 break;
422 }
423 } // loop through input files
424
425 if (out_file) {
426 // close outFile
427 // outFile would survive to here in single output mode
428 out_file->writeRunTree();
429 delete out_file;
430 out_file = nullptr;
431 }
432
433 } // are there input files? if-else tree
434
435 // finally, notify everyone that we are stopping
436 if (performance_) performance_->start(performance::Callback::onProcessEnd, 0);
437 i_proc = 0;
438 for (auto proc : sequence_) {
439 i_proc++;
440 if (performance_)
441 performance_->start(performance::Callback::onProcessEnd, i_proc);
442 proc->onProcessEnd();
443 if (performance_)
444 performance_->stop(performance::Callback::onProcessEnd, i_proc);
445 }
446 if (performance_) performance_->stop(performance::Callback::onProcessEnd, 0);
447
448 // we're done so let's close up the logging
449 logging::close();
451}
452
456
457TDirectory* Process::makeHistoDirectory(const std::string& dirName) {
458 auto owner{openHistoFile()};
459 TDirectory* child = owner->mkdir((char*)dirName.c_str());
460 if (child) child->cd();
461 return child;
462}
463
465 TDirectory* owner{nullptr};
466
467 if (histo_filename_.empty()) {
468 // trying to write histograms/ntuples but no file defined
469 EXCEPTION_RAISE(
470 "NoHistFileName",
471 "You did not provide the necessary histogram file name to "
472 "put your histograms (or performance data) in.\n Provide this "
473 "name in the python configuration with 'p.histogramFile = "
474 "\"myHistFile.root\"' where p is the Process object.");
475 } else if (histo_t_file_ == nullptr) {
476 histo_t_file_ = new TFile(histo_filename_.c_str(), "RECREATE");
477 owner = histo_t_file_;
478 } else {
479 owner = histo_t_file_;
480 }
481 owner->cd();
482
483 return owner;
484}
485
487 // Producers are allowed to put parameters into
488 // the run header through 'beforeNewRun' method
489
490 // Put the version into the rh string param
491 header.setStringParameter("Pass = " + pass_name_ + ", version",
492 LDMXSW_VERSION);
493 if (performance_) performance_->start(performance::Callback::beforeNewRun, 0);
494 std::size_t i_proc{0};
495 for (auto proc : sequence_) {
496 i_proc++;
497 if (performance_)
498 performance_->start(performance::Callback::beforeNewRun, i_proc);
499 proc->beforeNewRun(header);
500 if (performance_)
501 performance_->stop(performance::Callback::beforeNewRun, i_proc);
502 }
503 if (performance_) performance_->stop(performance::Callback::beforeNewRun, 0);
504 // now run header has been modified by Producers,
505 // it is valid to read from for everyone else in 'onNewRun'
506 if (performance_) performance_->start(performance::Callback::onNewRun, 0);
507 conditions_.onNewRun(header);
508 i_proc = 0;
509 for (auto proc : sequence_) {
510 i_proc++;
511 if (performance_)
512 performance_->start(performance::Callback::onNewRun, i_proc);
513 proc->onNewRun(header);
514 if (performance_)
515 performance_->stop(performance::Callback::onNewRun, i_proc);
516 }
517 if (performance_) performance_->stop(performance::Callback::onNewRun, 0);
518 ldmx_log(info) << header;
519}
520
521bool Process::process(int n, int n_try, Event& event) const {
522 if ((log_frequency_ != -1) && ((n + 1) % log_frequency_ == 0) &&
523 (n_try < 2)) {
524 // only printout event counter if we've enabled log frequency, the event
525 // matches the frequency and we are on the first try
526 TTimeStamp t;
527 ldmx_log(info) << "Processing " << n + 1 << " Run "
528 << event.getEventHeader().getRun() << " Event "
529 << event.getEventHeader().getEventNumber() << " ("
530 << t.AsString("lc") << ")";
531 }
532
533 if (performance_) performance_->start(performance::Callback::process, 0);
534 std::size_t i_proc{0};
535 try {
536 for (auto proc : sequence_) {
537 i_proc++;
538 if (performance_)
539 performance_->start(performance::Callback::process, i_proc);
540 proc->process(event);
541 if (performance_)
542 performance_->stop(performance::Callback::process, i_proc);
543 }
544 } catch (AbortEventException&) {
545 if (performance_) {
546 performance_->stop(performance::Callback::process, i_proc);
547 performance_->stop(performance::Callback::process, 0);
548 performance_->endEvent(false);
549 }
550 return false;
551 }
552 if (performance_) {
553 performance_->stop(performance::Callback::process, 0);
554 performance_->endEvent(true);
555 }
556 return true;
557}
558
560 if (performance_) performance_->start(performance::Callback::onFileOpen, 0);
561 std::size_t i_proc{0};
562 for (auto proc : sequence_) {
563 i_proc++;
564 if (performance_)
565 performance_->start(performance::Callback::onFileOpen, i_proc);
566 proc->onFileOpen(file);
567 if (performance_)
568 performance_->stop(performance::Callback::onFileOpen, i_proc);
569 }
570 if (performance_) performance_->stop(performance::Callback::onFileOpen, 0);
571}
572
574 if (performance_) performance_->start(performance::Callback::onFileClose, 0);
575 std::size_t i_proc{0};
576 for (auto proc : sequence_) {
577 i_proc++;
578 if (performance_)
579 performance_->start(performance::Callback::onFileClose, i_proc);
580 proc->onFileClose(file);
581 if (performance_)
582 performance_->stop(performance::Callback::onFileClose, i_proc);
583 }
584 if (performance_) performance_->stop(performance::Callback::onFileClose, 0);
585}
586
587} // namespace framework
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 &params)
Create a ConditionsObjectProvider given the information.
This class manages all ROOT file input/output operations.
Definition EventFile.h:28
void updateParent(EventFile *parent)
Change pointer to different parent file.
const std::string & getFileName()
Definition EventFile.h:255
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.
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.
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.
Definition Event.h:42
int getEventNumber() const
Get the event number.
Definition Event.h:81
void onEndOfFile()
Perform end of file action.
Definition Event.cxx:186
ldmx::EventHeader & getEventHeader()
Get the event header.
Definition Event.h:59
const ldmx::EventHeader * getEventHeaderPtr()
Get the event header as a pointer.
Definition Event.h:75
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.
Definition Process.h:169
bool skip_corrupted_input_files_
allow the Process to skip input files that are corrupted
Definition Process.h:177
std::string histo_filename_
Filename for histograms and other user products.
Definition Process.h:211
int max_tries_
Maximum number of attempts to make before giving up on an event.
Definition Process.h:172
int run_for_generation_
Run number to use if generating events.
Definition Process.h:208
int compression_setting_
Compression setting to pass to output files.
Definition Process.h:202
void run()
Run the process.
Definition Process.cxx:155
int event_limit_
Limit on events to process.
Definition Process.h:158
std::string pass_name_
Processing pass name.
Definition Process.h:155
void newRun(ldmx::RunHeader &header)
Run through the processors and let them know that we are starting a new run.
Definition Process.cxx:486
TFile * histo_t_file_
TFile for histograms and other user products.
Definition Process.h:220
TDirectory * openHistoFile()
Open a ROOT TFile to write histograms and TTrees.
Definition Process.cxx:464
int total_events_
Number of events we'd like to produce independetly of the number of tries it would take.
Definition Process.h:166
~Process()
Class Destructor.
Definition Process.cxx:141
void onFileClose(EventFile &file) const
File is begin closed.
Definition Process.cxx:573
std::vector< EventProcessor * > sequence_
Ordered list of EventProcessors to execute.
Definition Process.h:183
std::vector< std::string > drop_keep_rules_
Set of drop/keep rules.
Definition Process.h:205
ldmx::RunHeader * run_header_
Pointer to the current RunHeader, used for Conditions information.
Definition Process.h:217
TDirectory * makeHistoDirectory(const std::string &dirName)
Construct a TDirectory* for the given module.
Definition Process.cxx:457
performance::Tracker * performance_
class with calls backs to track performance measurements of software
Definition Process.h:223
int min_events_
When reading a file in, what's the first event to read.
Definition Process.h:161
StorageControl storage_controller_
Storage controller.
Definition Process.h:180
std::vector< std::string > output_files_
List of output file names.
Definition Process.h:193
std::vector< std::string > input_files_
List of input files to process.
Definition Process.h:190
const ldmx::EventHeader * event_header_
Pointer to the current EventHeader, used for Conditions information.
Definition Process.h:214
bool process(int n, int n_tries, Event &event) const
Process the input event through the sequence of processors.
Definition Process.cxx:521
void onFileOpen(EventFile &file) const
File is being opened.
Definition Process.cxx:559
Conditions conditions_
Set of ConditionsProviders.
Definition Process.h:186
Process(const framework::config::Parameters &configuration)
Class constructor.
Definition Process.cxx:30
int getRunNumber() const
Get the current run number or the run number to be used when initiating new events from the job.
Definition Process.cxx:453
framework::config::Parameters config_
The parameters used to configure this class.
Definition Process.h:152
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.
Definition Parameters.h:29
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:78
static void set(int n)
set the event number in the current Formatter
Definition Logger.cxx:158
Class to interface between framework::Process and various measurements that can eventually be written...
Definition Tracker.h:20
void start(Callback cb, std::size_t i_proc)
start the timer for a specific callback and specific processor
Definition Tracker.cxx:90
void absoluteStop()
literally last line of Process::run (if run compeletes without error)
Definition Tracker.cxx:88
void endEvent(bool completed)
inform us that we finished an event (and whether it was completed or not)
Definition Tracker.cxx:98
void stop(Callback cb, std::size_t i_proc)
stop the timer for a specific callback and specific processor
Definition Tracker.cxx:94
void absoluteStart()
literally first line of Process::run
Definition Tracker.cxx:86
Provides header information an event such as event number and timestamp.
Definition EventHeader.h:44
int getRun() const
Return the run number.
Definition EventHeader.h:84
void setEventNumber(int eventNumber)
Set the event number.
void setRun(int run)
Set the run number.
void setTimestamp(const TTimeStamp &timestamp)
Set the timestamp.
Run-specific configuration and data stored in its own output TTree alongside the event TTree in the o...
Definition RunHeader.h:57
void setStringParameter(const std::string &name, std::string value)
Set a string parameter value.
Definition RunHeader.h:222
All classes in the ldmx-sw project use this namespace.