diff --git a/src/base/serialiser.h b/src/base/serialiser.h index c1efe6ac1d..e77fca1082 100644 --- a/src/base/serialiser.h +++ b/src/base/serialiser.h @@ -54,6 +54,14 @@ class Serialisable return false; } + // Place the named value into the supplied object, but only if it exists + template bool getIfPresent(const SerialisedValue &node, std::string name, U &destination) + { + if (!node.contains(name)) + return false; + destination = toml::find(node, name); + return true; + } // A helper function to add elements of a vector to a node under the named heading template static void fromVectorToTable(const std::vector &vector, std::string name, SerialisedValue &node) @@ -176,14 +184,14 @@ class Serialisable SerialisedValue result; for (auto &[key, value] : map) if constexpr (serialisablePointer) - value->serialise(std::string(key), result); + value->serialise(std::format("{}", key), result); else if constexpr (std::is_base_of_v) - value.serialise(key, result); + value.serialise(std::format("{}", key), result); else // We use the direct value (with casting) instead of // value.serialise() to handle the case where the value // is a raw type (e.g. int) - result[std::string(key)] = value; + result[std::format("{}", key)] = value; if (!map.empty()) node[name] = result; } diff --git a/src/math/data3D.cpp b/src/math/data3D.cpp index 4c3f84a376..0e54800132 100644 --- a/src/math/data3D.cpp +++ b/src/math/data3D.cpp @@ -440,3 +440,30 @@ bool Data3D::serialise(LineParser &parser) const return true; } + +// Express as a serialisable value +void Data3D::serialise(std::string tag, SerialisedValue &target) const +{ + target[tag] = {{"tag", tag_}, {"x", x_}, {"y", y_}, {"z", z_}, {"values", values_.linearArray()}}; + if (hasError_) + target[tag]["errors"] = errors_.linearArray(); +} + +// Read values from a serialisable value +void Data3D::deserialise(const SerialisedValue &node) +{ + tag_ = toml::find(node, "tag"); + x_ = toml::find>(node, "x"); + y_ = toml::find>(node, "y"); + z_ = toml::find>(node, "z"); + values_.initialise(x_.size(), y_.size(), z_.size()); + values_.linearArray() = toml::find>(node, "values"); + + Serialisable::optionalOn(node, "errors", + [this](const auto errors) + { + hasError_ = true; + errors_.initialise(x_.size(), y_.size(), z_.size()); + errors_.linearArray() = toml::get>(errors); + }); +} diff --git a/src/math/data3D.h b/src/math/data3D.h index f9bb4c98b1..404ecb285a 100644 --- a/src/math/data3D.h +++ b/src/math/data3D.h @@ -11,7 +11,7 @@ class Histogram3D; // One-Dimensional Data -class Data3D : public Data3DBase +class Data3D : public Data3DBase, public Serialisable { public: Data3D(); @@ -122,4 +122,8 @@ class Data3D : public Data3DBase bool deserialise(LineParser &parser); // Write data through specified LineParser bool serialise(LineParser &parser) const; + // Express as a serialisable value + void serialise(std::string tag, SerialisedValue &target) const override; + // Read values from a serialisable value + void deserialise(const SerialisedValue &node) override; }; diff --git a/src/math/histogram2D.cpp b/src/math/histogram2D.cpp index b29f86ec6d..528ecabd23 100644 --- a/src/math/histogram2D.cpp +++ b/src/math/histogram2D.cpp @@ -43,6 +43,22 @@ void Histogram2D::clear() * Data */ +// Update accumulated data +void Histogram2D::updateAccumulatedData() +{ + // Set up arrays + accumulatedData_.initialise(bins_.size(), true); + + // Store bin centres and accumulated averages in the object + for (auto n = 0; n < bins_.size(); ++n) + { + accumulatedData_.xAxis(n) = xBinCentres_[n]; + accumulatedData_.yAxis(n) = yBinCentres_[n]; + accumulatedData_.values().linearArray()[n] = averages_[n]; + accumulatedData_.errors().linearArray()[n] = averages_[n].stDev(); + } +} + // Initialise with specified bin range void Histogram2D::initialise(double xMin, double xMax, double xBinWidth, double yMin, double yMax, double yBinWidth) { @@ -244,3 +260,28 @@ bool Histogram2D::serialise(LineParser &parser) const return true; } + +// Express as a serialisable value +void Histogram2D::serialise(std::string tag, SerialisedValue &target) const +{ + target[tag] = {{"xMinimum", xMinimum_}, {"xMaximum", xMaximum_}, {"xBinWidth", xBinWidth_}, + {"yMinimum", yMinimum_}, {"yMaximum", yMaximum_}, {"yBinWidth", yBinWidth_}, + {"nBinned", nBinned_}, {"nMissed", nMissed_}, {"averages", averages_.linearArray()}}; +} + +// Read values from a serialisable value +void Histogram2D::deserialise(const SerialisedValue &node) +{ + clear(); + + initialise(toml::find(node, "xMinimum"), toml::find(node, "xMaximum"), + toml::find(node, "yBinWidth"), toml::find(node, "yMinimum"), + toml::find(node, "yMaximum"), toml::find(node, "yBinWidth")); + + nBinned_ = toml::find(node, "nBinned"); + nMissed_ = toml::find(node, "nMissed"); + + averages_.linearArray() = toml::find>(node, "averages"); + + updateAccumulatedData(); +} \ No newline at end of file diff --git a/src/math/histogram2D.h b/src/math/histogram2D.h index 81072a8e64..98106b9888 100644 --- a/src/math/histogram2D.h +++ b/src/math/histogram2D.h @@ -8,7 +8,7 @@ #include "templates/array2D.h" // Two-Dimensional Histogram -class Histogram2D +class Histogram2D : public Serialisable { public: Histogram2D(); @@ -53,6 +53,10 @@ class Histogram2D // Accumulated data Data2D accumulatedData_; + private: + // Update accumulated data + void updateAccumulatedData(); + public: // Initialise with specified bin range void initialise(double xMinimum, double xMaximum, double xBinWidth, double yMinimum, double yMaximum, double yBinWidth); @@ -105,4 +109,8 @@ class Histogram2D bool deserialise(LineParser &parser); // Write data through specified LineParser bool serialise(LineParser &parser) const; + // Express as a serialisable value + void serialise(std::string tag, SerialisedValue &target) const override; + // Read values from a serialisable value + void deserialise(const SerialisedValue &node) override; }; diff --git a/src/math/histogram3D.cpp b/src/math/histogram3D.cpp index 713c01b241..d2f8761517 100644 --- a/src/math/histogram3D.cpp +++ b/src/math/histogram3D.cpp @@ -278,3 +278,30 @@ bool Histogram3D::serialise(LineParser &parser) const return true; } + +// Express as a serialisable value +void Histogram3D::serialise(std::string tag, SerialisedValue &target) const +{ + target[tag] = {{"xMinimum", xMinimum_}, {"xMaximum", xMaximum_}, {"xBinWidth", xBinWidth_}, + {"yMinimum", yMinimum_}, {"yMaximum", yMaximum_}, {"yBinWidth", yBinWidth_}, + {"zMinimum", zMinimum_}, {"zMaximum", zMaximum_}, {"zBinWidth", zBinWidth_}, + {"nBinned", nBinned_}, {"nMissed", nMissed_}, {"averages", averages_.linearArray()}}; +} + +// Read values from a serialisable value +void Histogram3D::deserialise(const SerialisedValue &node) +{ + clear(); + + initialise( + toml::find(node, "xMinimum"), toml::find(node, "xMaximum"), toml::find(node, "yBinWidth"), + toml::find(node, "yMinimum"), toml::find(node, "yMaximum"), toml::find(node, "yBinWidth"), + toml::find(node, "zMinimum"), toml::find(node, "zMaximum"), toml::find(node, "zBinWidth")); + + nBinned_ = toml::find(node, "nBinned"); + nMissed_ = toml::find(node, "nMissed"); + + averages_.linearArray() = toml::find>(node, "averages"); + + updateAccumulatedData(); +} \ No newline at end of file diff --git a/src/math/histogram3D.h b/src/math/histogram3D.h index 638cff0484..72fe2840aa 100644 --- a/src/math/histogram3D.h +++ b/src/math/histogram3D.h @@ -7,8 +7,7 @@ #include "math/sampledDouble.h" #include "templates/array3D.h" -// Three-Dimensional Histogram -class Histogram3D +class Histogram3D : public Serialisable { public: Histogram3D(); @@ -132,4 +131,8 @@ class Histogram3D bool deserialise(LineParser &parser); // Write data through specified LineParser bool serialise(LineParser &parser) const; + // Express as a serialisable value + void serialise(std::string tag, SerialisedValue &target) const override; + // Read values from a serialisable value + void deserialise(const SerialisedValue &node) override; }; diff --git a/src/math/integerHistogram1D.cpp b/src/math/integerHistogram1D.cpp index 4b4a8d324d..94d8b02b7f 100644 --- a/src/math/integerHistogram1D.cpp +++ b/src/math/integerHistogram1D.cpp @@ -212,3 +212,33 @@ bool IntegerHistogram1D::serialise(LineParser &parser) const return true; } + +// Express as a serialisable value +void IntegerHistogram1D::serialise(std::string tag, SerialisedValue &target) const +{ + target[tag] = {{"zeroCounter", zeroCounter_}, {"nBinned", nBinned_}, {"nMissed", nMissed_}}; + + if (minimum_) + target[tag]["minimum"] = *minimum_; + if (maximum_) + target[tag]["maximum"] = *maximum_; + + fromMap(averages_, "averages", target); +} + +// Read values from a serialisable value +void IntegerHistogram1D::deserialise(const SerialisedValue &node) +{ + clear(); + + getIfPresent(node, "minimum", minimum_); + getIfPresent(node, "maximum", maximum_); + + nBinned_ = toml::find(node, "nBinned"); + nMissed_ = toml::find(node, "nMissed"); + zeroCounter_ = toml::find(node, "nMissed"); + + toMap(node, "averages", [&](const auto &key, const auto &value) { averages_[std::stoi(key)].deserialise(value); }); + + updateAccumulatedData(); +} diff --git a/src/math/integerHistogram1D.h b/src/math/integerHistogram1D.h index bc72d60eaa..87c000b87c 100644 --- a/src/math/integerHistogram1D.h +++ b/src/math/integerHistogram1D.h @@ -8,8 +8,7 @@ #include "math/sampledDouble.h" #include -// Pure Integer Histogram -class IntegerHistogram1D +class IntegerHistogram1D : public Serialisable { public: IntegerHistogram1D(); @@ -74,4 +73,8 @@ class IntegerHistogram1D bool deserialise(LineParser &parser); // Write data through specified LineParser bool serialise(LineParser &parser) const; + // Express as a serialisable value + void serialise(std::string tag, SerialisedValue &target) const override; + // Read values from a serialisable value + void deserialise(const SerialisedValue &node) override; };