Program Listing for File h5write.cxx¶
↰ Return to documentation for file (dx2/h5/h5write.cxx)
#include "dx2/h5/h5write.hpp"
#include <fmt/core.h>
#include <stdexcept>
#pragma region Raw writer
h5utils::H5Group traverse_or_create_groups(hid_t parent,
const std::string &path) {
// Strip leading '/' characters, if any, to prevent empty group names
size_t start_pos = path.find_first_not_of('/');
if (start_pos == std::string::npos) {
return h5utils::H5Group(parent); // Path is just "/", return parent as-is
}
std::string cleaned_path = path.substr(start_pos);
/*
* This is the base case for recursion. When the path is empty, we
* have reached the final group in the path and we return the parent
* group.
*/
if (cleaned_path.empty()) {
return h5utils::H5Group(parent);
}
// Split the path into the current group name and the remaining path
size_t pos = cleaned_path.find('/');
std::string group_name =
(pos == std::string::npos) ? cleaned_path : cleaned_path.substr(0, pos);
std::string remaining_path =
(pos == std::string::npos) ? "" : cleaned_path.substr(pos + 1);
// Try to open group, suppress errors if not found
H5ErrorSilencer silencer;
h5utils::H5Group next_group(H5Gopen(parent, group_name.c_str(), H5P_DEFAULT));
// If the group does not exist, create it
if (!next_group) {
next_group = h5utils::H5Group(H5Gcreate(
parent, group_name.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT));
if (!next_group) {
throw std::runtime_error("Error: Unable to create or open group: " +
group_name);
}
}
// If there are no remaining path components, return the current group
if (remaining_path.empty()) {
return next_group;
}
// Recursively traverse or create the next group in the path
return traverse_or_create_groups(next_group, remaining_path);
}
#pragma endregion
#pragma region Attribute writer
void write_experiment_metadata(hid_t group_id,
const std::vector<uint64_t> &experiment_ids,
const std::vector<std::string> &identifiers) {
// Check if the input vectors are empty
if (experiment_ids.empty() || identifiers.empty()) {
throw std::runtime_error(
"Experiment IDs and identifiers must not be empty.");
}
// Write experiment_ids
{
hsize_t dims = experiment_ids.size();
h5utils::H5Space space(H5Screate_simple(1, &dims, nullptr));
h5utils::H5Attr attr(H5Acreate2(group_id, "experiment_ids",
H5T_NATIVE_ULLONG, space, H5P_DEFAULT,
H5P_DEFAULT));
if (!space || !attr ||
H5Awrite(attr, H5T_NATIVE_ULLONG, experiment_ids.data()) < 0) {
throw std::runtime_error(
fmt::format("Failed to write experiment_ids attribute ({} entries)",
experiment_ids.size()));
}
}
// Write identifiers
{
hsize_t dims = identifiers.size();
h5utils::H5Space space(H5Screate_simple(1, &dims, nullptr));
h5utils::H5Type str_type(H5Tcopy(H5T_C_S1));
if (!str_type || H5Tset_size(str_type, H5T_VARIABLE) < 0 ||
H5Tset_cset(str_type, H5T_CSET_UTF8) < 0 ||
H5Tset_strpad(str_type, H5T_STR_NULLTERM) < 0) {
throw std::runtime_error("Failed to create identifiers string type");
}
std::vector<const char *> c_strs;
for (const auto &s : identifiers) {
c_strs.push_back(s.c_str());
}
h5utils::H5Attr attr(H5Acreate2(group_id, "identifiers", str_type, space,
H5P_DEFAULT, H5P_DEFAULT));
if (!space || !attr || H5Awrite(attr, str_type, c_strs.data()) < 0) {
throw std::runtime_error(
fmt::format("Failed to write identifiers attribute ({} entries)",
identifiers.size()));
}
}
}
#pragma endregion