10#include <boost/multi_index/detail/index_matcher.hpp>
21using boost::multi_index::detail::index_matcher::entry;
35herr_t readStringAttribute(hid_t attr,
char **data) {
37 hsize_t thedims[H5S_MAX_RANK];
39 hid_t atype = H5Aget_type(attr);
40 hsize_t sdim = H5Tget_size(atype);
41 hid_t space = H5Aget_space(attr);
42 int ndims = H5Sget_simple_extent_dims(space, thedims, NULL);
45 if (H5Tis_variable_str(atype)) {
46 hid_t btype = H5Tget_native_type(atype, H5T_DIR_ASCEND);
47 iRet = H5Aread(attr, btype, data);
50 *data = (
char *)malloc(sdim + 1);
51 iRet = H5Aread(attr, atype, *data);
54 }
else if (ndims == 1) {
58 strings = (
char **)malloc(thedims[0] *
sizeof(
char *));
60 if (!H5Tis_variable_str(atype)) {
61 strings[0] = (
char *)malloc(thedims[0] * sdim *
sizeof(
char));
62 for (i = 1; i < thedims[0]; i++) {
63 strings[i] = strings[0] + i * sdim;
67 iRet = H5Aread(attr, atype, strings[0]);
68 *data = (
char *)calloc((sdim + 2) * thedims[0],
sizeof(char));
69 for (i = 0; i < thedims[0]; i++) {
71 strncpy(*data, strings[i], sdim);
74 strncat(*data, strings[i], sdim);
77 if (H5Tis_variable_str(atype)) {
78 H5Dvlen_reclaim(atype, space, H5P_DEFAULT, strings);
85 *data = (
char *)malloc(33);
86 strcpy(*data,
" higher dimensional string array\0");
101std::pair<std::string, herr_t> readStringAttributeN(hid_t attr) {
103 const auto iRet = readStringAttribute(attr, &vdat);
104 std::string attrData;
108 return std::make_pair(attrData, iRet);
111void getGroup(hid_t groupID, std::map<std::string, std::set<std::string>> &allEntries) {
116 auto lf_getNxClassAttribute = [&](hid_t groupID,
const char *objectName) -> std::string {
117 std::string attribute =
"";
118 hid_t attributeID = H5Aopen_by_name(groupID, objectName,
"NX_class", H5P_DEFAULT, H5P_DEFAULT);
119 if (attributeID < 0) {
120 H5Aclose(attributeID);
124 auto pairData = readStringAttributeN(attributeID);
126 attribute = pairData.first;
127 H5Aclose(attributeID);
133 constexpr std::size_t maxLength = 1024;
134 char groupName[maxLength];
135 char memberName[maxLength];
136 std::size_t groupNameLength =
static_cast<std::size_t
>(H5Iget_name(groupID, groupName, maxLength));
137 hsize_t nObjects = 0;
138 H5Gget_num_objs(groupID, &nObjects);
140 const std::string groupNameStr(groupName, groupNameLength);
141 const std::string nxClass = (groupNameStr ==
"/") ?
"" : lf_getNxClassAttribute(groupID, groupNameStr.c_str());
143 if (!nxClass.empty()) {
144 allEntries[nxClass].insert(groupNameStr);
147 for (
unsigned int i = 0; i < nObjects; ++i) {
149 const int type = H5Gget_objtype_by_idx(groupID,
static_cast<size_t>(i));
150 const std::size_t memberNameLength =
151 static_cast<std::size_t
>(H5Gget_objname_by_idx(groupID,
static_cast<hsize_t
>(i), memberName, maxLength));
153 if (type == H5O_TYPE_GROUP) {
154 hid_t subGroupID = H5Gopen2(groupID, memberName, H5P_DEFAULT);
155 getGroup(subGroupID, allEntries);
156 H5Gclose(subGroupID);
158 }
else if (type == H5O_TYPE_DATASET) {
159 const std::string memberNameStr(memberName, memberNameLength);
160 const std::string absoluteEntryName = groupNameStr +
"/" + memberNameStr;
161 allEntries[
"SDS"].insert(absoluteEntryName);
174 : m_filename(
std::move(filename)), m_allEntries(initAllEntries()) {}
186 hid_t fapl = H5Pcreate(H5P_FILE_ACCESS);
187 H5Pset_fclose_degree(fapl, H5F_CLOSE_STRONG);
189 hid_t fileID = H5Fopen(
m_filename.c_str(), H5F_ACC_RDONLY, fapl);
192 throw std::invalid_argument(
"ERROR: Kernel::NexusHDF5Descriptor couldn't open hdf5 file " +
m_filename +
196 hid_t groupID = H5Gopen2(fileID,
"/", H5P_DEFAULT);
198 std::map<std::string, std::set<std::string>> allEntries;
200 getGroup(groupID, allEntries);
210 auto itClass = m_allEntries.find(groupClass);
211 if (itClass == m_allEntries.end()) {
215 if (itClass->second.count(entryName) == 1) {
224 for (
auto itClass = m_allEntries.rbegin(); itClass != m_allEntries.rend(); ++itClass) {
225 if (itClass->second.count(entryName) == 1) {
static bool isReadable(const std::string &filename, const Version version=AnyVersion)
Returns true if the file is considered to store data in a hierarchy.
static bool isReadable(const std::string &filename)
Returns true if the file is considered to store data in a hierarchy.
NexusHDF5Descriptor()=delete
const std::map< std::string, std::set< std::string > > m_allEntries
All entries metadata.
const std::map< std::string, std::set< std::string > > & getAllEntries() const noexcept
Returns a const reference of the internal map holding all entries in the NeXus HDF5 file.
std::string getFilename() const noexcept
Returns a copy of the current file name.
bool isEntry(const std::string &entryName, const std::string &groupClass) const noexcept
Checks if a full-path entry exists for a particular groupClass in a Nexus dataset.
std::string m_filename
NeXus HDF5 file name.
std::map< std::string, std::set< std::string > > initAllEntries()
Sets m_allEntries, called in HDF5 constructor.
std::string to_string(const wide_integer< Bits, Signed > &n)