LDMX Software
Event.h
Go to the documentation of this file.
1
8#ifndef FRAMEWORK_EVENT_H_
9#define FRAMEWORK_EVENT_H_
10
11// ROOT
12#include "TTree.h"
13
14// LDMX
15#include "Framework/Bus.h"
17#include "Framework/Exception/Exception.h"
19
20// STL
21#include <regex.h>
22
23#include <algorithm>
24#include <iostream>
25#include <map>
26#include <set>
27#include <sstream>
28#include <string>
29#include <typeinfo>
30
31namespace framework {
32
42class Event {
43 public:
48 Event(const std::string &passName);
49
53 ~Event();
54
60
66
76
82
87 double getEventWeight() const { return event_header_.getWeight(); }
88
94 void print() const;
95
112 std::vector<ProductTag> searchProducts(const std::string &namematch,
113 const std::string &passmatch,
114 const std::string &typematch,
115 bool full_string_match = false) const;
116
145 bool exists(const std::string &name, const std::string &passName,
146 bool unique = true) const;
147
156 void addDrop(const std::string &exp);
157
183 template <typename T>
184 void add(const std::string &collectionName, T &obj) {
185 if (collectionName.find('_') != std::string::npos) {
186 EXCEPTION_RAISE("IllegalName",
187 "The product name '" + collectionName +
188 "' is illegal as it contains an underscore.");
189 }
190
191 // determine the branch name
192 std::string branch_name;
193 if (collectionName == ldmx::EventHeader::BRANCH)
194 branch_name = collectionName;
195 else
196 branch_name = makeBranchName(collectionName);
197
198 if (branches_filled_.find(branch_name) != branches_filled_.end()) {
199 EXCEPTION_RAISE("ProductExists",
200 "A product named '" + collectionName +
201 "' already exists in the event (has been loaded by a "
202 "previous producer in this process).");
203 }
204 branches_filled_.insert(branch_name);
205 // MEMORY add is leaking memory when given a vector (possible upon
206 // destruction of Event?) MEMORY add is 'conditional jump or move depends on
207 // uninitialised values' for all types of objects
208 // TTree::BranchImpRef or TTree::BronchExec
209 if (not bus_.isOnBoard(branch_name)) {
210 // create a new branch for this collection
211
212 // have type T board bus under name 'branchName'
213 bus_.board<T>(branch_name);
214
215 // type name (want to use branch element if possible)
216 std::string tname = typeid(obj).name();
217
218 if (output_tree_ and not shouldDrop(branch_name)) {
219 // we are writing this branch to an output file, so let's
220 // attach this passenger to the output tree
221 TBranch *out_branch = bus_.attach(output_tree_, branch_name, true);
222 // get type name from branch if possible,
223 // otherwise use compiler level type name (above)
224 std::string class_name{out_branch->GetClassName()};
225 if (not class_name.empty()) tname = class_name;
226 } // output tree exists or not
227
228 // check for cache entry to remove
229 auto it_known{known_lookups_.find(collectionName)};
230 if (it_known != known_lookups_.end()) known_lookups_.erase(it_known);
231
232 // add us to list of products
233 products_.emplace_back(collectionName, pass_name_, tname);
234 }
235
236 // copy input contents into bus passenger
237 try {
238 bus_.update(branch_name, obj);
239 } catch (const std::bad_cast &) {
240 EXCEPTION_RAISE("TypeMismatch",
241 "Attempting to add an object whose type '" +
242 std::string(typeid(obj).name()) +
243 "' doesn't match the type stored in the collection.");
244 }
245
246 return;
247 }
248
287 template <typename T>
288 const T &getObject(const std::string &collectionName,
289 const std::string &passName) const {
290 // get branch name
291 std::string branch_name;
292 if (collectionName == ldmx::EventHeader::BRANCH) {
293 branch_name = collectionName;
294 } else if (passName.empty()) {
295 // if no passName, then find branchName by looking over known products
296 if (known_lookups_.find(collectionName) == known_lookups_.end()) {
297 // this collectionName hasn't been found before
298 // this collection name is the whole name and not a partial name
299 // so we search products with a full-string match required
300 auto matches = searchProducts(collectionName, "", "", true);
301 if (matches.empty()) {
302 // no matches found
303 EXCEPTION_RAISE("ProductNotFound",
304 "No product found for name '" + collectionName + "'");
305 } else if (matches.size() > 1) {
306 // more than one branch found
307 std::stringstream names;
308 for (auto strs : matches) {
309 names << "\n" << strs;
310 }
311 EXCEPTION_RAISE("ProductAmbiguous",
312 "Multiple products found for name '" +
313 collectionName +
314 "' without specified pass name :" + names.str());
315 } else {
316 // exactly one branch found -> cache for later
317 known_lookups_[collectionName] =
318 makeBranchName(collectionName, matches.at(0).passname());
319 } // different options for number of possible branch matches
320 } // collection not in known lookups
321 branch_name = known_lookups_.at(collectionName);
322 } else {
323 branch_name = makeBranchName(collectionName, passName);
324 }
325
326 // now we have determined the unique branch name to look for
327 // so we can start looking on the bus and the input tree
328 // (if it exists) for it
329 bool already_on_board{bus_.isOnBoard(branch_name)};
330 if (not already_on_board and input_tree_) {
331 // branch is not on the bus but there is an input tree
332 // -> let's look for a new branch to load
333
334 // default construct a new passenger
335 bus_.board<T>(branch_name);
336
337 // attempt to attach the new passenger to the input tree
338 TBranch *branch = bus_.attach(input_tree_, branch_name, false);
339 if (branch == 0) {
340 // inputTree doesn't have that branch
341 EXCEPTION_RAISE(
342 "ProductNotFound",
343 "No product found for branch '" + branch_name + "' on input tree.");
344 }
345 // ooh, new branch!
346 branch->SetStatus(1); // overrides any 'ignore' rules
357 long long int ientry{input_tree_->GetReadEntry()};
358 if (ientry < 0) {
359 // reached getObject without initializing inputTree's read entry
360 EXCEPTION_RAISE("InTreeInit",
361 "The input tree was un-initialized with read entry " +
362 std::to_string(ientry) +
363 " when attempting to get '" + branch_name + "'.");
364 }
365 branch->GetEntry(ientry);
366 } else if (not already_on_board) {
367 // not found in loaded branches and there is no inputTree,
368 // so no hope of finding an unloaded object
369 EXCEPTION_RAISE("ProductNotFound", "No product found for name '" +
370 collectionName + "' and pass '" +
371 pass_name_ + "'");
372 }
373
374 // we've made sure the passenger is on the bus
375 // and the branch we are reading from (if we are reading)
376 // has been updated
377 // let's return the object that the passenger is carrying
378 try {
379 const T &obj = bus_.get<T>(branch_name);
380 return obj;
381 } catch (const std::bad_cast &) {
382 EXCEPTION_RAISE("BadType",
383 "Trying to get product from '" + branch_name +
384 "' but asking for wrong type: " + typeid(T).name());
385 }
386 } // getObject
387
399 template <typename ContentType>
400 const std::vector<ContentType> &getCollection(
401 const std::string &collectionName, const std::string &passName) const {
402 return getObject<std::vector<ContentType> >(collectionName, passName);
403 }
404
416 template <typename KeyType, typename ValType>
417 const std::map<KeyType, ValType> &getMap(const std::string &collectionName,
418 const std::string &passName) const {
419 return getObject<std::map<KeyType, ValType> >(collectionName, passName);
420 }
425 void setInputTree(TTree *tree);
426
431 void setOutputTree(TTree *tree);
432
437 TTree *createTree();
438
442 const std::vector<ProductTag> &getProducts() const { return products_; }
443
454 bool nextEvent();
455
459 void beforeFill();
460
464 void clear();
465
469 void onEndOfEvent();
470
477 void onEndOfFile();
478
483 std::string getPassName() { return pass_name_; }
484
486 int getElectronCount() const { return electron_count_; }
487
493 void setElectronCount(const int &electronCount) {
494 electron_count_ = electronCount;
495 }
496
497 private:
504 bool shouldDrop(const std::string &collName) const;
505
511 std::string makeBranchName(const std::string &collectionName,
512 const std::string &passName) const {
513 return collectionName + "_" + passName;
514 }
515
520 std::string makeBranchName(const std::string &collectionName) const {
521 return makeBranchName(collectionName, pass_name_);
522 }
523
524 private:
529
533 std::string pass_name_;
534
538 TTree *output_tree_{nullptr};
539
543 TTree *input_tree_{nullptr};
544
547
557
566 std::set<std::string> branches_filled_;
567
571 std::vector<regex_t> regex_drop_collections_;
572
576 mutable std::map<std::string, std::string> known_lookups_;
577
581 std::vector<ProductTag> products_;
582};
583} // namespace framework
584
585#endif /* FRAMEWORK_EVENT_H_ */
Class that provides header information about an event such as event number and timestamp.
Class defining the identity of a data product in the event.
A map of bus passengers.
Definition Bus.h:29
const BaggageType & get(const std::string &name)
Get the baggage carried by the passenger with the passed name.
Definition Bus.h:43
void update(const std::string &name, const BaggageType &obj)
Update the object a passenger is carrying.
Definition Bus.h:83
bool isOnBoard(const std::string &name)
Check if a passenger is on the bus.
Definition Bus.h:117
TBranch * attach(TTree *tree, const std::string &name, bool can_create)
Attach the input tree to the object a passenger is carrying.
Definition Bus.h:107
void board(const std::string &name)
Board a new passenger onto the bus.
Definition Bus.h:65
Implements an event buffer system for storing event data.
Definition Event.h:42
const ldmx::EventHeader & getEventHeader() const
Get the event header.
Definition Event.h:65
std::string makeBranchName(const std::string &collectionName) const
Make a branch name from a collection and the default(current) pass name.
Definition Event.h:520
bool exists(const std::string &name, const std::string &passName, bool unique=true) const
Check for the existence of an object or collection with the given name and pass name in the event.
Definition Event.cxx:92
TTree * input_tree_
The input tree for reading existing data.
Definition Event.h:543
std::vector< ProductTag > products_
List of all the event products.
Definition Event.h:581
int getEventNumber() const
Get the event number.
Definition Event.h:81
std::vector< ProductTag > searchProducts(const std::string &namematch, const std::string &passmatch, const std::string &typematch, bool full_string_match=false) const
Get a list of products which match the given POSIX-Extended, case-insenstive regular-expressions.
Definition Event.cxx:66
int electron_count_
The total number of electrons in the event.
Definition Event.h:546
void clear()
Clear this object's data (including passengers).
Definition Event.cxx:165
~Event()
Class destructor.
Definition Event.cxx:9
void onEndOfFile()
Perform end of file action.
Definition Event.cxx:172
std::string makeBranchName(const std::string &collectionName, const std::string &passName) const
Make a branch name from a collection and pass name.
Definition Event.h:511
TTree * createTree()
Create the output data tree.
Definition Event.cxx:102
ldmx::EventHeader event_header_
The event header object.
Definition Event.h:528
void setElectronCount(const int &electronCount)
Set the beam electron count.
Definition Event.h:493
const std::map< KeyType, ValType > & getMap(const std::string &collectionName, const std::string &passName) const
Get a map (std::map) of objects from the event bus.
Definition Event.h:417
void setOutputTree(TTree *tree)
Set the output data tree.
Definition Event.cxx:108
std::string pass_name_
The default pass name.
Definition Event.h:533
double getEventWeight() const
Get the event weight.
Definition Event.h:87
void beforeFill()
Action to be executed before the tree is filled.
Definition Event.cxx:156
void onEndOfEvent()
Perform end of event action (doesn't do anything right now).
Definition Event.cxx:170
const std::vector< ProductTag > & getProducts() const
Get a list of the data products in the event.
Definition Event.h:442
framework::Bus bus_
The Bus.
Definition Event.h:556
Event(const std::string &passName)
Class constructor.
Definition Event.cxx:7
const T & getObject(const std::string &collectionName, const std::string &passName) const
Get an general object from the event bus.
Definition Event.h:288
std::set< std::string > branches_filled_
Names of branches filled during this event.
Definition Event.h:566
bool nextEvent()
Go to the next event by retrieving the event header.
Definition Event.cxx:151
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
std::vector< regex_t > regex_drop_collections_
Regex of collection names to not store in event.
Definition Event.h:571
const std::vector< ContentType > & getCollection(const std::string &collectionName, const std::string &passName) const
Get a collection (std::vector) of objects from the event bus.
Definition Event.h:400
void setInputTree(TTree *tree)
Set the input data tree.
Definition Event.cxx:110
void print() const
Print event bus.
Definition Event.cxx:15
std::string getPassName()
Get the current/default pass name.
Definition Event.h:483
void add(const std::string &collectionName, T &obj)
Adds an object to the event bus.
Definition Event.h:184
bool shouldDrop(const std::string &collName) const
Check if collection should be dropped.
Definition Event.cxx:181
TTree * output_tree_
The output tree for writing a new file.
Definition Event.h:538
std::map< std::string, std::string > known_lookups_
Efficiency cache for empty pass name lookups.
Definition Event.h:576
void addDrop(const std::string &exp)
Add a drop rule to the list of regex expressions to drop.
Definition Event.cxx:21
int getElectronCount() const
Definition Event.h:486
Provides header information an event such as event number and timestamp.
Definition EventHeader.h:44
double getWeight() const
Get the event weight (default of 1.0).
Definition EventHeader.h:98
int getEventNumber() const
Return the event number.
Definition EventHeader.h:78
static const std::string BRANCH
Name of EventHeader branch.
Definition EventHeader.h:49
All classes in the ldmx-sw project use this namespace.