fire v0.19.0
Framework for sImulation and Reconstruction of Events
Writer.h
1#ifndef FIRE_IO_H5_WRITER_H
2#define FIRE_IO_H5_WRITER_H
3
4// using HighFive
5#include <highfive/H5File.hpp>
6
7#include "fire/config/Parameters.h"
8#include "fire/io/Atomic.h"
9#include "fire/io/Constants.h"
10
11namespace fire::io {
12
19class Writer {
20 public:
29 Writer(const int& event_limit, const config::Parameters& ps);
30
34 ~Writer();
35
41 void flush();
42
46 const std::string& name() const;
47
62 void structure(const std::string& path, const std::pair<std::string,int>& type);
63
67 inline std::size_t entries() const { return entries_; }
68
84 template <typename AtomicType>
85 void save(const std::string& path, const AtomicType& val) {
86 static_assert(
87 is_atomic_v<AtomicType>,
88 "Type unsupported by HighFive as Atomic made its way to Writer::save");
89 if (buffers_.find(path) == buffers_.end()) {
90 // first save attempt, need to create the data set to be saved
91 // - we pass the newly created dataset to the buffer to hold onto
92 // for flushing purposes
93 // - the length of the buffer is the same size as the chunks in
94 // HDF5, this is done on purpose
95 // - if the type is a bool, we define the HighFive type to be
96 // our custom enum which mimics the type used by h5py
97 HighFive::DataType t;
98 if constexpr (std::is_same_v<AtomicType,bool>) {
99 t = create_enum_bool();
100 } else {
101 t = HighFive::AtomicType<AtomicType>();
102 }
103 auto ds = file_->createDataSet(path, space_, t, create_props_);
104 ds.createAttribute(constants::TYPE_ATTR_NAME, boost::core::demangle(typeid(AtomicType).name()));
105 ds.createAttribute(constants::VERS_ATTR_NAME, 0);
106 buffers_.emplace(path,
107 std::make_unique<Buffer<AtomicType>>(rows_per_chunk_, ds));
108 }
109 dynamic_cast<Buffer<AtomicType>&>(*buffers_.at(path)).save(val);
110 }
111
122 return s << "Writer(" << w.name() << ")";
123 }
124
126 Writer(const Writer&) = delete;
128 void operator=(const Writer&) = delete;
129
130 private:
139 protected:
143 HighFive::DataSet set_;
144
145 public:
152 explicit BufferHandle(std::size_t max, HighFive::DataSet s)
153 : max_len_{max}, set_{s} {}
157 virtual ~BufferHandle() = default;
166 virtual void flush() = 0;
167 };
168
174 template <typename AtomicType>
175 class Buffer : public BufferHandle {
180
181 public:
194 explicit Buffer(std::size_t max, HighFive::DataSet s)
195 : BufferHandle(max, s), buffer_{}, i_file_{0} {
196 buffer_.reserve(this->max_len_);
197 }
199 virtual ~Buffer() = default;
208 void save(const AtomicType& val) {
209 buffer_.push_back(val);
210 if (buffer_.size() > this->max_len_) flush();
211 }
212
242 virtual void flush() final override {
243 if (buffer_.size() == 0) return;
244 std::size_t new_extent = i_file_ + buffer_.size();
245 // throws if not created yet
246 if (this->set_.getDimensions().at(0) < new_extent) {
247 this->set_.resize({new_extent});
248 }
249 if constexpr (std::is_same_v<AtomicType, bool>) {
250 // handle bool specialization
252 buff.reserve(buffer_.size());
253 for (const auto& v : buffer_) buff.push_back(v ? Bool::TRUE : Bool::FALSE);
254 this->set_.select({i_file_}, {buffer_.size()}).write(buff);
255 } else {
256 this->set_.select({i_file_}, {buffer_.size()}).write(buffer_);
257 }
258 i_file_ += buffer_.size();
259 buffer_.clear();
260 buffer_.reserve(this->max_len_);
261 }
262 };
263
264 private:
274 HighFive::DataSetCreateProps create_props_;
276 HighFive::DataSpace space_;
283};
284
285} // namespace fire::h5
286
287#endif // FIRE_H5_WRITER_H
Definitions for names of structures required by serialization methods.
Class encapsulating parameters for configuring a processor.
Definition: Parameters.h:28
Type-less handle to buffers.
Definition: Writer.h:138
std::size_t max_len_
the maximum size of the buffer
Definition: Writer.h:141
virtual ~BufferHandle()=default
virtual destructor so derived Buffer can be destructed properly
BufferHandle(std::size_t max, HighFive::DataSet s)
Define the maximum size of the buffer and the dataset we are writing to.
Definition: Writer.h:152
HighFive::DataSet set_
the H5 dataset we are writing to
Definition: Writer.h:143
virtual void flush()=0
Pure virtual flush mechanism.
Buffer atomic data types in-memory for efficient disk operations.
Definition: Writer.h:175
std::size_t i_file_
the index of the file we will write to on the next flush
Definition: Writer.h:179
void save(const AtomicType &val)
Put the new value into the buffer.
Definition: Writer.h:208
virtual void flush() final override
Flush our in-memory buffer onto disk.
Definition: Writer.h:242
virtual ~Buffer()=default
destruct the in-memory buffer
Buffer(std::size_t max, HighFive::DataSet s)
Define the buffer size and the set we will write to.
Definition: Writer.h:194
std::vector< AtomicType > buffer_
the actual buffer of data in-memory
Definition: Writer.h:177
Write the fire DataSets into a deterministic structure in the output HDF5 data file.
Definition: Writer.h:19
void save(const std::string &path, const AtomicType &val)
Save an atomic type into the dataset at the passed path.
Definition: Writer.h:85
std::size_t rows_per_chunk_
number of rows to keep in each chunk
Definition: Writer.h:280
void structure(const std::string &path, const std::pair< std::string, int > &type)
Persist the structure of the event object at the input path.
Definition: Writer.cxx:40
HighFive::DataSetCreateProps create_props_
the creation properties to be used on datasets we are writing
Definition: Writer.h:274
friend std::ostream & operator<<(std::ostream &s, const Writer &w)
Stream this writer.
Definition: Writer.h:121
std::size_t entries() const
Get the number of entries in the file.
Definition: Writer.h:67
Writer(const int &event_limit, const config::Parameters &ps)
Open the file in write mode.
Definition: Writer.cxx:7
Writer(const Writer &)=delete
don't allow copies of the Writer
std::unordered_map< std::string, std::unique_ptr< BufferHandle > > buffers_
our in-memory buffers for data to be written to disk
Definition: Writer.h:282
HighFive::DataSpace space_
the dataspace shared amongst all of our datasets
Definition: Writer.h:276
void flush()
Flush the data to disk.
Definition: Writer.cxx:31
std::unique_ptr< HighFive::File > file_
our highfive file
Definition: Writer.h:272
void operator=(const Writer &)=delete
don't allow copies of the Writer
const std::string & name() const
Get the name of this file.
Definition: Writer.cxx:38
~Writer()
Close up our file, making sure to flush contents to disk.
Definition: Writer.cxx:29
std::size_t entries_
the expected number of entries in this file
Definition: Writer.h:278
Geant4 does a GLOBAL definition of the keyword TRUE.
Definition: AbstractData.h:11
HighFive::EnumType< Bool > create_enum_bool()
HighFive method for creating the enum data type.
Definition: Atomic.cxx:5
T push_back(T... args)
T reserve(T... args)
static const std::string VERS_ATTR_NAME
the name of the fire version attribute
Definition: Constants.h:28
static const std::string TYPE_ATTR_NAME
the name of the HDF5 object attribute that holds the event object type
Definition: Constants.h:26