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
30namespace framework {
31
41class Event {
42 public:
47 Event(const std::string &passName);
48
52 ~Event();
53
59
65
70 int getEventNumber() const { return eventHeader_.getEventNumber(); }
71
76 double getEventWeight() const { return eventHeader_.getWeight(); }
77
83 void Print() const;
84
101 std::vector<ProductTag> searchProducts(const std::string &namematch,
102 const std::string &passmatch,
103 const std::string &typematch,
104 bool full_string_match = false) const;
105
134 bool exists(const std::string &name, const std::string &passName = "",
135 bool unique = true) const;
136
145 void addDrop(const std::string &exp);
146
172 template <typename T>
173 void add(const std::string &collectionName, T &obj) {
174 if (collectionName.find('_') != std::string::npos) {
175 EXCEPTION_RAISE("IllegalName",
176 "The product name '" + collectionName +
177 "' is illegal as it contains an underscore.");
178 }
179
180 // determine the branch name
181 std::string branchName;
182 if (collectionName == ldmx::EventHeader::BRANCH)
183 branchName = collectionName;
184 else
185 branchName = makeBranchName(collectionName);
186
187 if (branchesFilled_.find(branchName) != branchesFilled_.end()) {
188 EXCEPTION_RAISE("ProductExists",
189 "A product named '" + collectionName +
190 "' already exists in the event (has been loaded by a "
191 "previous producer in this process).");
192 }
193 branchesFilled_.insert(branchName);
194 // MEMORY add is leaking memory when given a vector (possible upon
195 // destruction of Event?) MEMORY add is 'conditional jump or move depends on
196 // uninitialised values' for all types of objects
197 // TTree::BranchImpRef or TTree::BronchExec
198 if (not bus_.isOnBoard(branchName)) {
199 // create a new branch for this collection
200
201 // have type T board bus under name 'branchName'
202 bus_.board<T>(branchName);
203
204 // type name (want to use branch element if possible)
205 std::string tname = typeid(obj).name();
206
207 if (outputTree_ and not shouldDrop(branchName)) {
208 // we are writing this branch to an output file, so let's
209 // attach this passenger to the output tree
210 TBranch *outBranch = bus_.attach(outputTree_, branchName, true);
211 // get type name from branch if possible,
212 // otherwise use compiler level type name (above)
213 std::string class_name{outBranch->GetClassName()};
214 if (not class_name.empty()) tname = class_name;
215 } // output tree exists or not
216
217 // check for cache entry to remove
218 auto it_known{knownLookups_.find(collectionName)};
219 if (it_known != knownLookups_.end()) knownLookups_.erase(it_known);
220
221 // add us to list of products
222 products_.emplace_back(collectionName, passName_, tname);
223 }
224
225 // copy input contents into bus passenger
226 try {
227 bus_.update(branchName, obj);
228 } catch (const std::bad_cast &) {
229 EXCEPTION_RAISE("TypeMismatch",
230 "Attempting to add an object whose type '" +
231 std::string(typeid(obj).name()) +
232 "' doesn't match the type stored in the collection.");
233 }
234
235 return;
236 }
237
276 template <typename T>
277 const T &getObject(const std::string &collectionName,
278 const std::string &passName = "") const {
279 // get branch name
280 std::string branchName;
281 if (collectionName == ldmx::EventHeader::BRANCH) {
282 branchName = collectionName;
283 } else if (passName.empty()) {
284 // if no passName, then find branchName by looking over known products
285 if (knownLookups_.find(collectionName) == knownLookups_.end()) {
286 // this collectionName hasn't been found before
287 // this collection name is the whole name and not a partial name
288 // so we search products with a full-string match required
289 auto matches = searchProducts(collectionName, "", "", true);
290 if (matches.empty()) {
291 // no matches found
292 EXCEPTION_RAISE("ProductNotFound",
293 "No product found for name '" + collectionName + "'");
294 } else if (matches.size() > 1) {
295 // more than one branch found
296 std::stringstream names;
297 for (auto strs : matches) {
298 names << "\n" << strs;
299 }
300 EXCEPTION_RAISE("ProductAmbiguous",
301 "Multiple products found for name '" +
302 collectionName +
303 "' without specified pass name :" + names.str());
304 } else {
305 // exactly one branch found -> cache for later
306 knownLookups_[collectionName] =
307 makeBranchName(collectionName, matches.at(0).passname());
308 } // different options for number of possible branch matches
309 } // collection not in known lookups
310 branchName = knownLookups_.at(collectionName);
311 } else {
312 branchName = makeBranchName(collectionName, passName);
313 }
314
315 // now we have determined the unique branch name to look for
316 // so we can start looking on the bus and the input tree
317 // (if it exists) for it
318 bool already_on_board{bus_.isOnBoard(branchName)};
319 if (not already_on_board and inputTree_) {
320 // branch is not on the bus but there is an input tree
321 // -> let's look for a new branch to load
322
323 // default construct a new passenger
324 bus_.board<T>(branchName);
325
326 // attempt to attach the new passenger to the input tree
327 TBranch *branch = bus_.attach(inputTree_, branchName, false);
328 if (branch == 0) {
329 // inputTree doesn't have that branch
330 EXCEPTION_RAISE("ProductNotFound", "No product found for branch '" +
331 branchName + "' on input tree.");
332 }
333 // ooh, new branch!
334 branch->SetStatus(1); // overrides any 'ignore' rules
345 long long int ientry{inputTree_->GetReadEntry()};
346 if (ientry < 0) {
347 // reached getObject without initializing inputTree's read entry
348 EXCEPTION_RAISE("InTreeInit",
349 "The input tree was un-initialized with read entry " +
350 std::to_string(ientry) +
351 " when attempting to get '" + branchName + "'.");
352 }
353 branch->GetEntry(ientry);
354 } else if (not already_on_board) {
355 // not found in loaded branches and there is no inputTree,
356 // so no hope of finding an unloaded object
357 EXCEPTION_RAISE("ProductNotFound", "No product found for name '" +
358 collectionName + "' and pass '" +
359 passName_ + "'");
360 }
361
362 // we've made sure the passenger is on the bus
363 // and the branch we are reading from (if we are reading)
364 // has been updated
365 // let's return the object that the passenger is carrying
366 try {
367 const T &obj = bus_.get<T>(branchName);
368 return obj;
369 } catch (const std::bad_cast &) {
370 EXCEPTION_RAISE("BadType", "Trying to get product from '" + branchName +
371 "' but asking for wrong type.");
372 }
373 } // getObject
374
385 template <typename ContentType>
386 const std::vector<ContentType> &getCollection(
387 const std::string &collectionName,
388 const std::string &passName = "") const {
389 return getObject<std::vector<ContentType> >(collectionName, passName);
390 }
391
403 template <typename KeyType, typename ValType>
404 const std::map<KeyType, ValType> &getMap(
405 const std::string &collectionName,
406 const std::string &passName = "") const {
407 return getObject<std::map<KeyType, ValType> >(collectionName, passName);
408 }
409
414 void setInputTree(TTree *tree);
415
420 void setOutputTree(TTree *tree);
421
426 TTree *createTree();
427
431 const std::vector<ProductTag> &getProducts() const { return products_; }
432
443 bool nextEvent();
444
448 void beforeFill();
449
453 void Clear();
454
458 void onEndOfEvent();
459
466 void onEndOfFile();
467
472 std::string getPassName() { return passName_; }
473
475 int getElectronCount() const { return electronCount_; }
476
482 void setElectronCount(const int &electronCount) {
483 electronCount_ = electronCount;
484 }
485
486 private:
493 bool shouldDrop(const std::string &collName) const;
494
500 std::string makeBranchName(const std::string &collectionName,
501 const std::string &passName) const {
502 return collectionName + "_" + passName;
503 }
504
509 std::string makeBranchName(const std::string &collectionName) const {
510 return makeBranchName(collectionName, passName_);
511 }
512
513 private:
518
522 std::string passName_;
523
527 TTree *outputTree_{nullptr};
528
532 TTree *inputTree_{nullptr};
533
536
546
555 std::set<std::string> branchesFilled_;
556
560 std::vector<regex_t> regexDropCollections_;
561
565 mutable std::map<std::string, std::string> knownLookups_;
566
570 std::vector<ProductTag> products_;
571};
572} // namespace framework
573
574#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:41
std::string makeBranchName(const std::string &collectionName) const
Make a branch name from a collection and the default(current) pass name.
Definition Event.h:509
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:386
void Print() const
Print event bus.
Definition Event.cxx:15
std::vector< ProductTag > products_
List of all the event products.
Definition Event.h:570
int getEventNumber() const
Get the event number.
Definition Event.h:70
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
std::vector< regex_t > regexDropCollections_
Regex of collection names to not store in event.
Definition Event.h:560
std::map< std::string, std::string > knownLookups_
Efficiency cache for empty pass name lookups.
Definition Event.h:565
~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:500
TTree * createTree()
Create the output data tree.
Definition Event.cxx:102
void setElectronCount(const int &electronCount)
Set the beam electron count.
Definition Event.h:482
std::string passName_
The default pass name.
Definition Event.h:522
TTree * inputTree_
The input tree for reading existing data.
Definition Event.h:532
void setOutputTree(TTree *tree)
Set the output data tree.
Definition Event.cxx:108
double getEventWeight() const
Get the event weight.
Definition Event.h:76
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
void Clear()
Clear this object's data (including passengers).
Definition Event.cxx:165
const std::vector< ProductTag > & getProducts() const
Get a list of the data products in the event.
Definition Event.h:431
TTree * outputTree_
The output tree for writing a new file.
Definition Event.h:527
ldmx::EventHeader eventHeader_
The event header object.
Definition Event.h:517
framework::Bus bus_
The Bus.
Definition Event.h:545
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:58
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:404
const ldmx::EventHeader * getEventHeaderPtr()
Get the event header as a pointer.
Definition Event.h:64
std::set< std::string > branchesFilled_
Names of branches filled during this event.
Definition Event.h:555
void setInputTree(TTree *tree)
Set the input data tree.
Definition Event.cxx:110
std::string getPassName()
Get the current/default pass name.
Definition Event.h:472
int electronCount_
The total number of electrons in the event.
Definition Event.h:535
const T & getObject(const std::string &collectionName, const std::string &passName="") const
Get an general object from the event bus.
Definition Event.h:277
void add(const std::string &collectionName, T &obj)
Adds an object to the event bus.
Definition Event.h:173
bool shouldDrop(const std::string &collName) const
Check if collection should be dropped.
Definition Event.cxx:181
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
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:475
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.
Definition PerfDict.cxx:45