fire v0.19.0
Framework for sImulation and Reconstruction of Events
Event.h
1#ifndef FIRE_EVENT_H
2#define FIRE_EVENT_H
3
4#include <regex>
5#include <boost/core/demangle.hpp>
6
7#include "fire/io/Data.h"
9#include "fire/EventHeader.h"
10
11namespace fire {
12
14class Process;
15class UserReader;
16
28class Event {
29 public:
43 public:
52 const std::string& type, int vers, bool keep)
53 : name_{name}, pass_{pass}, type_{type}, version_{vers}, keep_{keep} {}
54
59 const std::string& name() const { return name_; }
60
65 const std::string& pass() const { return pass_; }
66
71 const std::string& type() const { return type_; }
72
77 int version() const { return version_; }
78
83 const bool keep() const { return keep_; }
84
89 const bool loaded() const { return loaded_; }
90
95 return os << "Object(pass=" << t.pass() <<", name=" << t.name() << "type=" << t.type() << ")";
96 }
97
101 inline bool match(const std::regex& name, const std::regex& pass, const std::regex& type) const {
103 }
104
105 private:
112 friend class Event;
113
118
123
128
133
139 bool keep_;
140
148 mutable bool loaded_{false};
149 };
150
151 public:
156 const EventHeader& header() const { return *header_; }
157
168 EventHeader& header() { return *header_; }
169
188 const std::string& passmatch,
189 const std::string& typematch) const;
190
203 bool exists(const std::string& name, const std::string& pass = "") const {
204 return search("^" + name + "$", pass, "").size() == 1;
205 }
206
241 template <typename DataType>
242 void add(const std::string& name, const DataType& data) {
243 static const bool ADD_KEEP_DEFAULT = true;
244 std::string full_name{fullName(name, pass_)};
245 if (objects_.find(full_name) == objects_.end()) {
246 // check available_objects_ listing so we don't in-advertently replace
247 // any datasets of the same name read in from the inputfile
248 // we know we are worried about data from the input file
249 // because data from previous producers in the sequence
250 // would already exist in the objects_ map
251 // we rely on trusting that setInputFile gets the listing
252 // of event objects from the input file and puts them
253 // into availble_objects_
254 if (search("^"+name+"$","^"+pass_+"$",".*").size() > 0) {
255 throw Exception("Repeat",
256 "Data named "+full_name+" already exists in the input file.");
257 }
258 auto& tag{available_objects_.emplace_back(name, pass_,
259 boost::core::demangle(typeid(DataType).name()),
260 io::class_version<DataType>,
261 keep(full_name, ADD_KEEP_DEFAULT))};
262 tag.loaded_ = true;
263
264 // a data set hasn't been created for this data yet
265 // we good, lets create the new data set
266 //
267 // NOTES:
268 // - check if new data is going to be written to output file
269 // or just used during this run
270 // - without any applicable drop/keep rules,
271 // we do save these datasets
272 // - we mark these objects as should_load == false because
273 // they are new and not from an input file
274 auto& obj{objects_[full_name]};
275 obj.data_ = std::make_unique<io::Data<DataType>>(io::constants::EVENT_GROUP+"/"+full_name);
276 obj.should_save_ = tag.keep_;
277 obj.should_load_ = false;
278 obj.updated_ = false;
279
280 // if we are saving this object, we should save the structure and the default value
281 // for all entries up to this one. This (along with 'clearing' at the end of each event)
282 // allows users to asyncronously add event objects and the events without an 'add'
283 // have a 'default' or 'cleared' object value.
284 if (obj.should_save_) {
285 obj.data_->structure(*output_file_);
286 obj.data_->clear();
287 for (std::size_t i{0}; i < i_entry_; i++)
288 obj.data_->save(*output_file_);
289 }
290 }
291
292 auto& obj{objects_.at(full_name)};
293 if (obj.updated_) {
294 // this data set has been updated by another processor in the sequence
295 throw Exception("Repeat",
296 "Data named " + full_name + " already added to the event"
297 " by a previous producer in the sequence.");
298 }
299
300 try {
302 obj.getDataRef<DataType>().update(data);
303 obj.updated_ = true;
304 } catch (std::bad_cast const&) {
305 throw Exception("TypeMismatch",
306 "Data corresponding to " + full_name + " has different type.");
307 }
308 }
309
348 template <typename DataType>
349 const DataType& get(const std::string& name,
350 const std::string& pass = "") const {
351 std::string full_name, type;
352 if (not pass.empty()) {
353 // easy case, pass was specified explicitly
354 full_name = fullName(name, pass);
355 } else if (known_lookups_.find(name) != known_lookups_.end()) {
356 full_name = known_lookups_.at(name);
357 } else {
358 // need to search current (and potential) available_objects using partial name
359 auto options{search("^" + name + "$", ".*", ".*")};
360 if (options.size() == 0) {
361 throw Exception("Miss",
362 "Data " + name + " not found.");
363 } else if (options.size() > 1) {
364 throw Exception("Ambig",
365 "Data " + name + " is ambiguous. Provide a pass name.");
366 }
367
368 // exactly one option
369 full_name = fullName(options.at(0).name(), options.at(0).pass());
370 type = options.at(0).type();
371 // add into cache
372 known_lookups_[name] = full_name;
373 }
374
375 if (objects_.find(full_name) == objects_.end()) {
376 // final check for input file, never should enter here without one
377 if (not input_file_) {
378 throw Exception("Miss",
379 "Data " + full_name + " was not created by an earlier processor "
380 "and there is no input file to attempt to read it from.");
381 }
382
383 // when setting up the in-memory object, we need to find the tag so we can
384 // 1. get whether the object should be copied to the output file and
385 // 2. set the loaded_ flag to true
386 // we can do a simple linear search since this will only happen once per input file
387 auto tag_it = std::find_if(available_objects_.begin(), available_objects_.end(),
388 [&full_name,this](const EventObjectTag& tag) {
389 return fullName(tag.name(),tag.pass()) == full_name;
390 });
391 tag_it->loaded_ = true;
392
393 // a data set hasn't been created for this data yet
394 // we good, lets create the new data set
395 //
396 // NOTES:
397 // - check if new data is going to be written to output file
398 // or just used during this run
399 // - without any applicable drop/keep rules,
400 // we do save these datasets
401 // - we mark these objects as should_load == false because
402 // they are new and not from an input file
403 auto& obj{objects_[full_name]};
404 obj.data_ = std::make_unique<io::Data<DataType>>(io::constants::EVENT_GROUP+"/"+full_name,
406 obj.should_save_ = tag_it->keep();
407 obj.should_load_ = true;
408 obj.updated_ = false;
409
410 // get this object up to the current entry
411 // loading may throw an H5 error if the shape of the data on disk
412 // cannot be loaded into the input type
413 try {
414 // copy structure into output file if this object should be saved
415 if (obj.should_save_) {
416 obj.data_->structure(*output_file_);
417 }
418
419 if (not obj.should_save_ or not input_file_->canCopy()) {
420 // only skip the first i_entry_ entries if the input file cannot copy
421 // or the object is not being saved
422 // the objects that are being saved are being mirrored by the input file
423 // if the input file can copy
424 for (std::size_t i{0}; i < i_entry_; i++) input_file_->load_into(*obj.data_);
425 }
426 input_file_->load_into(*obj.data_);
427 } catch (const HighFive::DataSetException&) {
428 throw Exception("BadType",
429 "Data " + full_name + " could not be loaded into "
430 + boost::core::demangle(typeid(DataType).name())
431 + " from the type it was written as " + type);
432 }
433 }
434
435 // type casting, 'bad_cast' thrown if unable
436 try {
437 return objects_[full_name].getDataRef<DataType>().get();
438 } catch (const std::bad_cast&) {
439 throw Exception("BadType",
440 "Data " + full_name + " was initialy loaded with type " + type
441 + " which cannot be casted into "
442 + boost::core::demangle(typeid(DataType).name()));
443 }
444 }
445
447 Event(const Event&) = delete;
448
450 void operator=(const Event&) = delete;
451
452 private:
463 inline std::string fullName(const std::string& name, const std::string& pass) const {
464 return (pass.empty() ? pass_ : pass) + "/" + name;
465 }
466
479 bool keep(const std::string& full_name, bool def) const;
480
481 private:
490 friend class Process;
491
495 friend class UserReader;
496
513 Event(io::Writer* output_file,
514 const std::string& pass,
515 const std::vector<config::Parameters>& dk_rules);
516
521 void save();
522
527 void load();
528
537 void setInputFile(io::Reader* r);
538
546 void next();
547
554 void done();
555
556 private:
568 struct EventObject {
584 template <typename DataType>
586 return dynamic_cast<io::Data<DataType>&>(*data_);
587 }
594 void clear() {
595 updated_ = false;
596 data_->clear();
597 }
598 };
602 long unsigned int i_entry_;
610}; // Event
611
612} // namespace fire
613
614#endif // FIRE_EVENT_H
Serialization class version deduction.
T at(T... args)
Header information of an event such as event number and timestamp.
Definition: EventHeader.h:27
Identification for a specific event object.
Definition: Event.h:42
std::string name_
Name given to the object.
Definition: Event.h:117
const bool keep() const
Get if this object will be kept (i.e.
Definition: Event.h:83
int version_
The version of the type.
Definition: Event.h:132
bool loaded_
If the object represented by this tag has been loaded into a memory object.
Definition: Event.h:148
std::string type_
Type name of the object.
Definition: Event.h:127
std::string pass_
Pass name given when object was generated.
Definition: Event.h:122
friend std::ostream & operator<<(std::ostream &os, const EventObjectTag &t)
String method for printing this tag in a helpful manner.
Definition: Event.h:94
bool match(const std::regex &name, const std::regex &pass, const std::regex &type) const
Checks if we match the passed regex for name, pass, and type.
Definition: Event.h:101
int version() const
Get the version number of the type of this object.
Definition: Event.h:77
EventObjectTag(const std::string &name, const std::string &pass, const std::string &type, int vers, bool keep)
Wrap the three pieces of information in our class.
Definition: Event.h:51
const std::string & pass() const
Get the pass name the object was produced on.
Definition: Event.h:65
const bool loaded() const
Get if this object is currently loaded in memory.
Definition: Event.h:89
const std::string & type() const
Get the name of the type of the object.
Definition: Event.h:71
const std::string & name() const
Get the object name.
Definition: Event.h:59
bool keep_
If the object represented by this tag should be kept.
Definition: Event.h:139
Event class for interfacing with processors.
Definition: Event.h:28
const EventHeader & header() const
Get the event header.
Definition: Event.h:156
EventHeader & header()
Get non-const event header.
Definition: Event.h:168
long unsigned int i_entry_
current index in the datasets
Definition: Event.h:602
std::string pass_
name of current processing pass
Definition: Event.h:564
io::Writer * output_file_
handle to output file (owned by Process)
Definition: Event.h:562
Event(const Event &)=delete
Delete the copy constructor to prevent any in-advertent copies.
std::vector< std::pair< std::regex, bool > > drop_keep_rules_
regular expressions determining if a dataset should be written to output file
Definition: Event.h:605
void operator=(const Event &)=delete
Delete the assignment operator to prevent any in-advertent copies.
void next()
Move to the next event we just need to keep our entry index up-to-date for loading a newly requested ...
Definition: Event.cxx:109
std::string fullName(const std::string &name, const std::string &pass) const
Deduce full data set name given a pass or using our pass.
Definition: Event.h:463
std::vector< EventObjectTag > search(const std::string &namematch, const std::string &passmatch, const std::string &typematch) const
Search through the available objects for a specific match.
Definition: Event.cxx:5
std::unique_ptr< EventHeader > header_
header that we control
Definition: Event.h:558
io::Reader * input_file_
pointer to input file (nullptr if no input files)
Definition: Event.h:560
void load()
Go through and load the next entry into the in-memory objects from the input file.
Definition: Event.cxx:84
const DataType & get(const std::string &name, const std::string &pass="") const
get a piece of data from the event
Definition: Event.h:349
bool keep(const std::string &full_name, bool def) const
Determine if the passed data set should be saved into output file.
Definition: Event.cxx:22
std::unordered_map< std::string, EventObject > objects_
list of event objects being processed
Definition: Event.h:600
void add(const std::string &name, const DataType &data)
add a piece of data to the event
Definition: Event.h:242
void save()
Go through and save the current in-memory objects into the output file.
Definition: Event.cxx:68
bool exists(const std::string &name, const std::string &pass="") const
Check if the input name and (optional) pass exist in the bus.
Definition: Event.h:203
void setInputFile(io::Reader *r)
Attach a file to this event as the input file.
Definition: Event.cxx:90
std::vector< EventObjectTag > available_objects_
list of objects available to us either on disk or newly created
Definition: Event.h:607
std::unordered_map< std::string, std::string > known_lookups_
cache of known lookups when requesting an object without a pass name
Definition: Event.h:609
void done()
Let the event bus know we are done.
Definition: Event.cxx:114
Standard base exception class with some useful output information.
Definition: Exception.h:18
The central object managing the data processing.
Definition: Process.h:16
class for easier reading of files written by fire
Definition: UserReader.h:44
General data set.
Definition: Data.h:90
Prototype for reading files within fire.
Definition: Reader.h:29
virtual void load_into(BaseData &d)=0
Load the current event into the passed data object.
virtual bool canCopy() const
Event::get needs to know if the reader implements a copy that advances the entry index of the data se...
Definition: Reader.h:97
Write the fire DataSets into a deterministic structure in the output HDF5 data file.
Definition: Writer.h:19
T empty(T... args)
T find_if(T... args)
fire::Process Process
alias Process into this namespace
Definition: EventProcessor.h:105
T regex_match(T... args)
structure to hold event data in memory
Definition: Event.h:568
bool should_load_
should we load the data from the input file?
Definition: Event.h:576
void clear()
Clear the event object at the end of an event.
Definition: Event.h:594
std::unique_ptr< io::BaseData > data_
the data for save/load
Definition: Event.h:572
io::Data< DataType > & getDataRef()
Helper for getting a reference to the dataset.
Definition: Event.h:585
bool should_save_
should we save the data into output file?
Definition: Event.h:574
bool updated_
have we been updated on the current event?
Definition: Event.h:578
static const std::string EVENT_GROUP
the name of the group in the file holding all event objects
Definition: Constants.h:22