fire v0.19.0
Framework for sImulation and Reconstruction of Events
Data.h
1#ifndef FIRE_IO_DATA_H
2#define FIRE_IO_DATA_H
3
4#include <memory>
5#include <type_traits>
6#include <vector>
7#include <map>
8
9#include "fire/exception/Exception.h"
10#include "fire/io/Access.h"
11#include "fire/io/AbstractData.h"
12#include "fire/io/Writer.h"
13#include "fire/io/Constants.h"
14#include "fire/io/h5/Reader.h"
15#ifdef fire_USE_ROOT
16#include "fire/io/root/Reader.h"
17#endif
18
34namespace fire::io {
35
36// need implementation here so we can use the fully defined input file `type` function
37template <typename DataType>
38AbstractData<DataType>::AbstractData(const std::string& path, Reader* input_file, DataType* handle)
39 : BaseData(path), owner_{handle == nullptr} {
40 if (owner_) {
41 handle_ = new DataType;
42 } else {
43 handle_ = handle;
44 }
45 save_type_ = { boost::core::demangle(typeid(DataType).name()), class_version<DataType> };
46 if (input_file) {
47 load_type_ = input_file->type(path);
48 }
49}
50
89template <typename DataType, typename Enable = void>
90class Data : public AbstractData<DataType> {
91 public:
98 enum SaveLoad {
101 SaveOnly
102 };
103
116 explicit Data(const std::string& path, Reader* input_file = nullptr, DataType* handle = nullptr)
117 : AbstractData<DataType>(path, input_file, handle), input_file_{input_file} {
118 fire::io::access::connect(*this->handle_, *this);
119 }
120
135 void load(h5::Reader& f) final override try {
136 for (auto& [save,load,m] : members_) if (load) m->load(f);
137 } catch (const HighFive::DataSetException& e) {
138 const auto& [memt, memv] = this->save_type_;
139 const auto& [diskt, diskv] = f.type(this->path_);
141 ss << "Data at " << this->path_ << " could not be loaded into "
142 << memt << " (version " << memv << ") from the type it was written as "
143 << diskt << " (version " << diskv << ")\n"
144 " Check that your implementation of attach can handle any "
145 "previous versions of your class you are trying to read.\n"
146 " H5 Error:\n" << e.what();
147 throw Exception("BadType",ss.str(), false);
148 }
149
150#ifdef fire_USE_ROOT
155 void load(root::Reader& f) final override {
156 f.load(this->path_, *(this->handle_));
157 }
158#endif
159
160 /*
161 * Saving this dataset from the file involves simply saving
162 * all of the members of the data type.
163 *
164 * @param[in] f file to save to
165 */
166 void save(Writer& f) final override {
167 for (auto& [save,load,m] : members_) if (save) m->save(f);
168 }
169
170 void structure(Writer& f) final override {
171 f.structure(this->path_, this->save_type_);
172 for (auto& [save,load,m] : members_) if (save) m->structure(f);
173 }
174
187 template <typename MemberType>
188 void attach(const std::string& name, MemberType& m, SaveLoad sl = SaveLoad::Both) {
189 if (name == constants::SIZE_NAME) {
190 throw Exception("BadName",
191 "The member name '"+constants::SIZE_NAME+"' is not allowed due to "
192 "its use in the serialization of variable length types.\n"
193 " Please give your member a more detailed name corresponding to "
194 "your class", false);
195 }
196 bool save{false}, load{false};
197 Reader* input_file{input_file_};
198 if (sl == SaveLoad::LoadOnly) load = true;
199 else if (sl == SaveLoad::SaveOnly) { save = true; input_file = nullptr; }
200 else { save = true; load = true; }
202 std::make_unique<Data<MemberType>>(this->path_ + "/" + name, input_file, &m)));
203 }
204
218 template <typename MemberType>
219 void rename(const std::string& old_name, const std::string& new_name, MemberType& m) {
220 attach(old_name,m,SaveLoad::LoadOnly);
221 attach(new_name,m,SaveLoad::SaveOnly);
222 }
223
224 private:
237}; // Data
238
247template <typename AtomicType>
248class Data<AtomicType, std::enable_if_t<is_atomic_v<AtomicType>>>
249 : public AbstractData<AtomicType> {
250 public:
258 explicit Data(const std::string& path, Reader* input_file = nullptr, AtomicType* handle = nullptr)
259 : AbstractData<AtomicType>(path, input_file, handle) {}
260
269 void load(h5::Reader& f) final override {
270 f.load(this->path_, *(this->handle_));
271 }
272
273#ifdef fire_USE_ROOT
278 void load(root::Reader& f) final override {
279 f.load(this->path_, *(this->handle_));
280 }
281#endif
282
291 void save(Writer& f) final override {
292 f.save(this->path_, *(this->handle_));
293 }
294
301 void structure(Writer& f) final override {
302 // atomic types get translated into H5 DataSets
303 // in save so we purposefully DO NOTHING here
304 }
305}; // Data<AtomicType>
306
318template <typename ContentType>
319class Data<std::vector<ContentType>>
320 : public AbstractData<std::vector<ContentType>> {
322 public:
330 explicit Data(const std::string& path, Reader* input_file = nullptr,
331 std::vector<ContentType>* handle = nullptr)
332 : AbstractData<std::vector<ContentType>>(path, input_file, handle),
333 size_{path + "/" + constants::SIZE_NAME, input_file},
334 data_{path + "/data", input_file} {}
335
346 void load(h5::Reader& f) final override {
347 size_.load(f);
348 this->handle_->resize(size_.get());
349 for (std::size_t i_vec{0}; i_vec < size_.get(); i_vec++) {
350 data_.load(f);
351 (*(this->handle_))[i_vec] = data_.get();
352 }
353 }
354
355#ifdef fire_USE_ROOT
360 void load(root::Reader& f) final override {
361 f.load(this->path_, *(this->handle_));
362 }
363#endif
364
374 void save(Writer& f) final override {
375 size_.update(this->handle_->size());
376 size_.save(f);
377 for (std::size_t i_vec{0}; i_vec < this->handle_->size(); i_vec++) {
378 data_.update(this->handle_->at(i_vec));
379 data_.save(f);
380 }
381 }
382
383 void structure(Writer& f) final override {
384 f.structure(this->path_, this->save_type_);
385 size_.structure(f);
386 data_.structure(f);
387 }
388
389 private:
394}; // Data<std::vector>
395
408template <typename KeyType, typename ValType>
409class Data<std::map<KeyType,ValType>>
410 : public AbstractData<std::map<KeyType,ValType>> {
412 public:
420 explicit Data(const std::string& path, Reader* input_file = nullptr,
421 std::map<KeyType,ValType>* handle = nullptr)
422 : AbstractData<std::map<KeyType,ValType>>(path, input_file, handle),
423 size_{path + "/" + constants::SIZE_NAME, input_file},
424 keys_{path + "/keys", input_file},
425 vals_{path + "/vals", input_file} {}
426
437 void load(h5::Reader& f) final override {
438 size_.load(f);
439 for (std::size_t i_map{0}; i_map < size_.get(); i_map++) {
440 keys_.load(f);
441 vals_.load(f);
442 this->handle_->emplace(keys_.get(), vals_.get());
443 }
444 }
445
446#ifdef fire_USE_ROOT
451 void load(root::Reader& f) final override {
452 f.load(this->path_, *(this->handle_));
453 }
454#endif
455
465 void save(Writer& f) final override {
466 size_.update(this->handle_->size());
467 size_.save(f);
468 for (auto const& [key,val] : *(this->handle_)) {
469 keys_.update(key);
470 keys_.save(f);
471 vals_.update(val);
472 vals_.save(f);
473 }
474 }
475
476 void structure(Writer& f) final override {
477 f.structure(this->path_, this->save_type_);
478 size_.structure(f);
479 keys_.structure(f);
480 vals_.structure(f);
481 }
482
483 private:
490}; // Data<std::map>
491
492} // namespace fire::io
493
494#endif // FIRE_H5_DATASET_H
495
#define fire_class_version(VERS)
define the version number for a class
Definition: ClassVersion.h:83
Definitions for names of structures required by serialization methods.
Standard base exception class with some useful output information.
Definition: Exception.h:18
Type-specific base class to hold common data methods.
Definition: AbstractData.h:96
std::pair< std::string, int > save_type_
type this data that is being used to write
Definition: AbstractData.h:234
std::optional< std::pair< std::string, int > > load_type_
type this data is loading from
Definition: AbstractData.h:232
AbstractData(const std::string &path, Reader *input_file=nullptr, DataType *handle=nullptr)
Define the dataset path and provide an optional handle.
Definition: Data.h:38
bool owner_
we own the object in memory
Definition: AbstractData.h:239
DataType * handle_
handle on current object in memory
Definition: AbstractData.h:237
Empty data base allowing recursion.
Definition: AbstractData.h:30
std::string path_
path of data set
Definition: AbstractData.h:82
Data(const std::string &path, Reader *input_file=nullptr, AtomicType *handle=nullptr)
We don't do any more initialization except which is handled by the AbstractData.
Definition: Data.h:258
void structure(Writer &f) final override
do NOT persist any structure for atomic types
Definition: Data.h:301
void load(h5::Reader &f) final override
Down to a type that h5::Reader can handle.
Definition: Data.h:269
void save(Writer &f) final override
Down to a type that io::Writer can handle.
Definition: Data.h:291
Data< KeyType > keys_
the data set holding the content of all the keys
Definition: Data.h:487
void structure(Writer &f) final override
pure virtual method for saving structure
Definition: Data.h:476
void load(h5::Reader &f) final override
Load a map from the input file.
Definition: Data.h:437
Data< ValType > vals_
the data set holding the content of all the vals
Definition: Data.h:489
Data< std::size_t > size_
the data set of sizes of the vectors
Definition: Data.h:485
Data(const std::string &path, Reader *input_file=nullptr, std::map< KeyType, ValType > *handle=nullptr)
We create three child data sets, one for the successive sizes of the maps and two to hold all the key...
Definition: Data.h:420
void save(Writer &f) final override
Save a vector to the output file.
Definition: Data.h:465
void structure(Writer &f) final override
pure virtual method for saving structure
Definition: Data.h:383
Data< std::size_t > size_
the data set of sizes of the vectors
Definition: Data.h:391
void save(Writer &f) final override
Save a vector to the output file.
Definition: Data.h:374
Data< ContentType > data_
the data set holding the content of all the vectors
Definition: Data.h:393
void load(h5::Reader &f) final override
Load a vector from the input file.
Definition: Data.h:346
Data(const std::string &path, Reader *input_file=nullptr, std::vector< ContentType > *handle=nullptr)
We create two child data sets, one to hold the successive sizes of the vectors and one to hold all of...
Definition: Data.h:330
General data set.
Definition: Data.h:90
void save(Writer &f) final override
pure virtual method for saving data
Definition: Data.h:166
Reader * input_file_
pointer to the input file (if there is one)
Definition: Data.h:236
void attach(const std::string &name, MemberType &m, SaveLoad sl=SaveLoad::Both)
Attach a member object from the our data handle.
Definition: Data.h:188
std::vector< std::tuple< bool, bool, std::unique_ptr< BaseData > > > members_
list of members in this dataset
Definition: Data.h:234
void load(h5::Reader &f) final override
Loading this dataset from the file involves simply loading all of the members of the data type.
Definition: Data.h:135
SaveLoad
Flag how a member variable should be accessed by serialization.
Definition: Data.h:98
@ LoadOnly
only load the member (read in)
Definition: Data.h:100
@ SaveOnly
only save the member (write out)
Definition: Data.h:101
@ Both
load and save the member
Definition: Data.h:99
Data(const std::string &path, Reader *input_file=nullptr, DataType *handle=nullptr)
Attach ourselves to the input type after construction.
Definition: Data.h:116
void rename(const std::string &old_name, const std::string &new_name, MemberType &m)
Rename a member variable.
Definition: Data.h:219
void structure(Writer &f) final override
pure virtual method for saving structure
Definition: Data.h:170
Prototype for reading files within fire.
Definition: Reader.h:29
virtual std::pair< std::string, int > type(const std::string &path)=0
Get the type of the input object.
Write the fire DataSets into a deterministic structure in the output HDF5 data file.
Definition: Writer.h:19
Reading a file generated by fire.
Definition: Reader.h:22
Reading ROOT files into our data structures.
Definition: Reader.h:29
T make_tuple(T... args)
Geant4 does a GLOBAL definition of the keyword TRUE.
Definition: AbstractData.h:11
STL namespace.
T str(T... args)
static void connect(T &t, D &d)
Connect the input types by attaching t to do.
Definition: Access.h:33
Structure constants vital to serialization method.
Definition: Constants.h:16
static const std::string SIZE_NAME
the name of the size dataset for variable types
Definition: Constants.h:30