diff --git a/include/aare/Hdf5MasterFile.hpp b/include/aare/Hdf5MasterFile.hpp index 27154f5..196c130 100644 --- a/include/aare/Hdf5MasterFile.hpp +++ b/include/aare/Hdf5MasterFile.hpp @@ -89,7 +89,7 @@ class Hdf5MasterFile { // exptimearray // gatedelay array std::optional m_gates{}; - // additional json header + std::optional> m_additional_json_header{}; size_t m_frames_in_file{}; @@ -147,7 +147,7 @@ class Hdf5MasterFile { // exptimearray // gatedelay array std::optional gates() const; - // additional json header + std::optional> additional_json_header() const; size_t frames_in_file() const; size_t n_modules() const; diff --git a/include/aare/defs.hpp b/include/aare/defs.hpp index 9e26dc8..537175a 100644 --- a/include/aare/defs.hpp +++ b/include/aare/defs.hpp @@ -300,6 +300,108 @@ enum class BurstMode { Burst_Interal, Burst_External, Continuous_Internal, Continuous_External }; +/** ToString and StringTo Conversions */ + + +// generic +template ::value>> +std::string ToString(T arg) { return T(arg); } + +template ::value, int> = 0 > +T StringTo(const std::string &arg) { return T(arg); } + + +// so that StringTo> below doesnt complain about the above +// generic overload +template <> inline size_t StringTo(const std::string &arg) { + return std::stoi(arg); +} + + +// vector +template std::string ToString(const std::vector &vec) { + std::ostringstream oss; + oss << "["; + for (size_t i = 0; i < vec.size(); ++i) { + oss << vec[i]; + if (i != vec.size() - 1) + oss << ", "; + } + oss << "]"; + return oss.str(); +} +template <> inline std::vector StringTo(const std::string &s) { + std::vector result; + std::string str = s; + // Remove brackets and spaces + str.erase(std::remove_if(str.begin(), str.end(), + [](unsigned char c) { + return c == '[' || c == ']' || std::isspace(c); + }), + str.end()); + std::stringstream ss(str); + std::string item; + while (std::getline(ss, item, ',')) { + if (!item.empty()) + result.push_back(StringTo(item)); + } + return result; +} + + +// map +template +std::string ToString(const std::map &m) { + std::ostringstream os; + os << '{'; + if (!m.empty()) { + auto it = m.cbegin(); + os << ToString(it->first) << ": " << ToString(it->second); + it++; + while (it != m.cend()) { + os << ", " << ToString(it->first) << ": " << ToString(it->second); + it++; + } + } + os << '}'; + return os.str(); +} +template <> inline std::map StringTo(const std::string &s) { + std::map result; + std::string str = s; + + // Remove outer braces if present + if (!str.empty() && str.front() == '{' && str.back() == '}') { + str = str.substr(1, str.size() - 2); + } + + std::stringstream ss(str); + std::string item; + + auto trim = [](std::string& t) { + // trim leading white spaces + t.erase(t.begin(), std::find_if(t.begin(), t.end(), [](unsigned char c){ return !std::isspace(c); })); + // trim trailing white spaces + t.erase(std::find_if(t.rbegin(), t.rend(), [](unsigned char c){ return !std::isspace(c); }).base(), t.end()); + }; + + while (std::getline(ss, item, ',')) { + auto colon_pos = item.find(':'); + if (colon_pos == std::string::npos) + throw std::runtime_error("Missing ':' in item: " + item); + + std::string key = item.substr(0, colon_pos); + std::string value = item.substr(colon_pos + 1); + + trim(key); + trim(value); + + result[key] = value; + } + return result; +} + +// time std::string RemoveUnit(std::string &str); /** Convert std::chrono::duration with specified output unit */ @@ -375,48 +477,20 @@ T StringTo(const std::string &t) { return StringTo(tmp, unit); } -template ::value, int> = 0 > -T StringTo(const std::string &arg) { return T(arg); } - -// so that StringTo> below doesnt complain about the above -// generic overload -template <> inline size_t StringTo(const std::string &arg) { - return std::stoi(arg); -} - -template <> inline std::vector StringTo(const std::string &s) { - std::vector result; - std::string str = s; - // Remove brackets and spaces - str.erase(std::remove_if(str.begin(), str.end(), - [](unsigned char c) { - return c == '[' || c == ']' || std::isspace(c); - }), - str.end()); - std::stringstream ss(str); - std::string item; - while (std::getline(ss, item, ',')) { - if (!item.empty()) - result.push_back(StringTo(item)); - } - return result; -} - -template ::value>> -std::string ToString(T arg) { return T(arg); } - -template std::string ToString(const std::vector &vec) { - std::ostringstream oss; - oss << "["; - for (size_t i = 0; i < vec.size(); ++i) { - oss << vec[i]; - if (i != vec.size() - 1) - oss << ", "; - } - oss << "]"; - return oss.str(); +// optional +template std::string ToString(const std::optional &opt) { + return opt ? ToString(*opt) : "nullopt"; +} +template +std::ostream &operator<<(std::ostream &os, const std::optional &opt) { + if (opt) + os << *opt; + else + os << "nullopt"; + return os; } +// enums template <> DetectorType StringTo(const std::string & /*name*/); template <> std::string ToString(DetectorType arg); @@ -436,18 +510,6 @@ template <> std::string ToString(ScanParameters arg); std::ostream &operator<<(std::ostream &os, const ROI &roi); template <> std::string ToString(ROI arg); -template std::string ToString(const std::optional &opt) { - return opt ? ToString(*opt) : "nullopt"; -} - -template -std::ostream &operator<<(std::ostream &os, const std::optional &opt) { - if (opt) - os << *opt; - else - os << "nullopt"; - return os; -} using DataTypeVariants = std::variant; diff --git a/src/Hdf5MasterFile.cpp b/src/Hdf5MasterFile.cpp index 35e53e4..15ffe36 100644 --- a/src/Hdf5MasterFile.cpp +++ b/src/Hdf5MasterFile.cpp @@ -168,7 +168,9 @@ std::optional Hdf5MasterFile::counter_mask() const { return m_counter_ma // exptimearray // gatedelay array std::optional Hdf5MasterFile::gates() const { return m_gates; } -// additional json header +std::optional> Hdf5MasterFile::additional_json_header() const { + return m_additional_json_header; +} size_t Hdf5MasterFile::frames_in_file() const { return m_frames_in_file; } size_t Hdf5MasterFile::n_modules() const { return m_geometry.row * m_geometry.col; @@ -578,6 +580,9 @@ void Hdf5MasterFile::parse_acquisition_metadata( } // exptimearray + //std::vector exptimearray = {std::chrono::nanoseconds(10), std::chrono::milliseconds(500)}; + //std::cout << "exptimearray: " << ToString(exptimearray) << std::endl; + // gatedelay array // Gates @@ -590,6 +595,13 @@ void Hdf5MasterFile::parse_acquisition_metadata( } // additional json header + try { + m_additional_json_header = StringTo>(h5_get_scalar_dataset( + file, std::string(metadata_group_name + "Additional JSON Header"))); + LOG(logDEBUG) << "Additional JSON Header: " << ToString(m_additional_json_header); + } catch (H5::FileIException &e) { + // keep the optional empty + } // Frames in File m_frames_in_file = h5_get_scalar_dataset(