TRIQS/h5 1.3.0
C++ interface to HDF5
Loading...
Searching...
No Matches
group.cpp
Go to the documentation of this file.
1// Copyright (c) 2019-2024 Simons Foundation
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0.txt
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// Authors: Thomas Hahn, Henri Menke, Olivier Parcollet, Nils Wentzell
16
22#include "./group.hpp"
23
24#include <hdf5.h>
25#include <hdf5_hl.h>
26
27#include <stdexcept>
28#include <string>
29#include <vector>
30
31namespace h5 {
32
33 group::group(file f) : object(), parent_file(f) {
34 id = H5Gopen2(f, "/", H5P_DEFAULT);
35 if (id < 0) throw std::runtime_error("Error in h5::group: Opening the root group / for the file " + f.name() + " failed");
36 }
37
38 // same function is used in h5::file
39 std::string group::name() const {
40 // get length of the name
41 ssize_t size = H5Iget_name(id, nullptr, 1);
42
43 // reserve a buffer and get name
44 std::vector<char> buf(size + 1, 0x00);
45 H5Iget_name(id, buf.data(), size + 1);
46
47 // return string
48 std::string res = "";
49 res.append(&(buf.front()));
50 return res;
51 }
52
53 bool group::has_key(std::string const &key) const { return H5Lexists(id, key.c_str(), H5P_DEFAULT); }
54
55 bool group::has_subgroup(std::string const &key) const {
56 // check if a link with the given name exists
57 if (!has_key(key)) return false;
58
59 // check if the link can be opened
60 hid_t id_node = H5Oopen(id, key.c_str(), H5P_DEFAULT);
61 if (id_node <= 0) return false;
62
63 // check if the opened link is actually a group
64 bool r = (H5Iget_type(id_node) == H5I_GROUP);
65 H5Oclose(id_node);
66 return r;
67 }
68
69 bool group::has_dataset(std::string const &key) const {
70 // check if a link with the given name exists
71 if (!has_key(key)) return false;
72
73 // check if the link can be opened
74 hid_t id_node = H5Oopen(id, key.c_str(), H5P_DEFAULT);
75 if (id_node <= 0) return false;
76
77 // check if the opened link is actually a dataset
78 bool r = (H5Iget_type(id_node) == H5I_DATASET);
79 H5Oclose(id_node);
80 return r;
81 }
82
83 void group::unlink(std::string const &key, bool error_if_absent) const {
84 // check if a link with the given name exists
85 if (!has_key(key)) {
86 // throw an exception if `error_if_absent` is true
87 if (error_if_absent) throw std::runtime_error("Error in h5::group: " + key + " does not exist in the group " + name());
88 return;
89 }
90
91 // remove the link from the group
92 auto err = H5Ldelete(id, key.c_str(), H5P_DEFAULT);
93 if (err < 0) throw std::runtime_error("Error in h5::group: Unlinking " + key + " in the group " + name() + " failed");
94 }
95
96 group group::open_group(std::string const &key) const {
97 // return the current group if the key is empty
98 if (key.empty()) return *this;
99
100 // check if a link with the key exists
101 if (!has_key(key)) throw std::runtime_error("Error in h5::group: " + key + " does not exist in the group " + name());
102
103 // open the subgroup
104 object obj = H5Gopen2(id, key.c_str(), H5P_DEFAULT);
105 if (obj < 0) throw std::runtime_error("Error in h5::group: Opening the subgroup " + key + " in the group " + name() + " failed");
106 return {obj, parent_file};
107 }
108
109 group group::create_group(std::string const &key, bool delete_if_exists) const {
110 // return the current group if the key is empty
111 if (key.empty()) return *this;
112
113 // unlink existing group if 'delete_if_exists' is true
114 if (delete_if_exists) unlink(key);
115
116 // create new subgroup
117 object obj = H5Gcreate2(id, key.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
118 if (not obj.is_valid()) throw std::runtime_error("Error in h5::group: Creating the subgroup " + key + " in the group " + name() + " failed");
119 return {obj, parent_file};
120 }
121
122 void group::create_softlink(std::string const &target_key, std::string const &key, bool delete_if_exists) const {
123 // do nothing if the key or target key is empty
124 if (target_key.empty() || key.empty()) return;
125
126 // check if target exists
127 if (!has_key(target_key)) throw std::runtime_error("Error in h5::group: " + target_key + " does not exist in the group " + name());
128
129 // unlink existing link or throw exception
130 if (delete_if_exists)
131 unlink(key, false);
132 else if (has_key(key))
133 throw std::runtime_error("Error in h5::group: " + key + " already exists in the group " + name());
134
135 // create softlink
136 auto const err = H5Lcreate_soft(target_key.c_str(), id, key.c_str(), H5P_DEFAULT, H5P_DEFAULT);
137 if (err < 0) throw std::runtime_error("Error in h5::group: Creating the softlink " + key + " -> " + target_key + " failed");
138 }
139
140 dataset group::open_dataset(std::string const &key) const {
141 // check if a link with the given name exists
142 if (!has_key(key)) throw std::runtime_error("Error in h5::group: " + key + " does not exist in the group " + name());
143
144 // open the dataset
145 dataset ds = H5Dopen2(id, key.c_str(), H5P_DEFAULT);
146 if (!ds.is_valid()) throw std::runtime_error("Error in h5::group: Opening the dataset " + key + " in the group " + name() + " failed");
147 return ds;
148 }
149
150 dataset group::create_dataset(std::string const &key, datatype ty, dataspace sp, hid_t pl) const {
151 // unlink existing link
152 unlink(key);
153
154 // create new dataset
155 dataset ds = H5Dcreate2(id, key.c_str(), ty, sp, H5P_DEFAULT, pl, H5P_DEFAULT);
156 if (!ds.is_valid()) throw std::runtime_error("Error in h5::group: Creating the dataset " + key + " in the group " + name() + " failed");
157 return ds;
158 }
159
160 dataset group::create_dataset(std::string const &key, datatype ty, dataspace sp) const { return create_dataset(key, ty, sp, H5P_DEFAULT); }
161
162 // C callbacks for the next functions using H5Literate
163 extern "C" {
164
165 herr_t get_group_elements_name_ds(::hid_t loc_id, const char *name, const H5L_info_t *, void *opdata) {
166 H5O_info_t object_info;
167 herr_t err = H5Oget_info_by_name(loc_id, name, &object_info, H5P_DEFAULT);
168 if (err < 0) throw std::runtime_error("Error in h5::get_group_elements_name_ds: H5Oget_info_by_name call failed");
169 if (object_info.type == H5O_TYPE_DATASET) static_cast<std::vector<std::string> *>(opdata)->push_back(name);
170 return 0;
171 }
172
173 herr_t get_group_elements_name_grp(::hid_t loc_id, const char *name, const H5L_info_t *, void *opdata) {
174 H5O_info_t object_info;
175 herr_t err = H5Oget_info_by_name(loc_id, name, &object_info, H5P_DEFAULT);
176 if (err < 0) throw std::runtime_error("Error in h5::get_group_elements_name_grp: H5Oget_info_by_name call failed");
177 if (object_info.type == H5O_TYPE_GROUP) static_cast<std::vector<std::string> *>(opdata)->push_back(name);
178 return 0;
179 }
180
181 herr_t get_group_elements_name_ds_grp(::hid_t loc_id, const char *name, const H5L_info_t *, void *opdata) {
182 H5O_info_t object_info;
183 herr_t err = H5Oget_info_by_name(loc_id, name, &object_info, H5P_DEFAULT);
184 if (err < 0) throw std::runtime_error("Error in h5::get_group_elements_name_ds_grp: H5Oget_info_by_name call failed");
185 if ((object_info.type == H5O_TYPE_GROUP) or (object_info.type == H5O_TYPE_DATASET))
186 static_cast<std::vector<std::string> *>(opdata)->push_back(name);
187 return 0;
188 }
189
190 } // extern "C"
191
192 std::vector<std::string> group::get_all_subgroup_names() const {
193 std::vector<std::string> grp_name;
194 int r = H5Literate(::hid_t(id), H5_INDEX_NAME, H5_ITER_NATIVE, nullptr, get_group_elements_name_grp, static_cast<void *>(&grp_name));
195 if (r != 0) throw std::runtime_error("Error in h5::group: Iterating over subgroups of the group " + name() + "failed");
196 return grp_name;
197 }
198
199 std::vector<std::string> group::get_all_dataset_names() const {
200 std::vector<std::string> ds_name;
201 int r = H5Literate(::hid_t(id), H5_INDEX_NAME, H5_ITER_NATIVE, nullptr, get_group_elements_name_ds, static_cast<void *>(&ds_name));
202 if (r != 0) throw std::runtime_error("Error in h5::group: Iterating over datasets of the group " + name() + "failed");
203 return ds_name;
204 }
205
206 std::vector<std::string> group::get_all_subgroup_dataset_names() const {
207 std::vector<std::string> ds_name;
208 int r = H5Literate(::hid_t(id), H5_INDEX_NAME, H5_ITER_NATIVE, nullptr, get_group_elements_name_ds_grp, static_cast<void *>(&ds_name));
209 if (r != 0) throw std::runtime_error("Error in h5::group: Iterating over datasets and subgroups of the group " + name() + "failed");
210 return ds_name;
211 }
212
213} // namespace h5
A handle to an HDF5 file.
Definition file.hpp:43
std::string name() const
Get the name of the file.
Definition file.cpp:71
A handle to an HDF5 group.
Definition group.hpp:44
bool has_dataset(std::string const &key) const
Check if a dataset with the given key exists in the group and is accessible.
Definition group.cpp:69
dataset create_dataset(std::string const &key, datatype ty, dataspace sp, hid_t pl) const
Create a dataset with the given key, datatype, dataspace and dataset creation property list in this g...
Definition group.cpp:150
dataset open_dataset(std::string const &key) const
Open a dataset with the given key in the group.
Definition group.cpp:140
std::string name() const
Get the name of the group.
Definition group.cpp:39
bool has_subgroup(std::string const &key) const
Check if a subgroup with the given key exists in the group and is accessible.
Definition group.cpp:55
group create_group(std::string const &key, bool delete_if_exists=true) const
Create a subgroup with the given key in the group.
Definition group.cpp:109
group open_group(std::string const &key) const
Open a subgroup with the given key in the group.
Definition group.cpp:96
void create_softlink(std::string const &target_key, std::string const &key, bool delete_if_exists=true) const
Create a softlink with the given key to a target with a given target key in this group.
Definition group.cpp:122
std::vector< std::string > get_all_subgroup_dataset_names() const
Get all the names of the subgroups and datasets in the current group.
Definition group.cpp:206
bool has_key(std::string const &key) const
Check if a link with the given key exists in the group.
Definition group.cpp:53
std::vector< std::string > get_all_dataset_names() const
Get all the names of the datasets in the current group.
Definition group.cpp:199
void unlink(std::string const &key, bool error_if_absent=false) const
Remove a link with the given key from the group.
Definition group.cpp:83
std::vector< std::string > get_all_subgroup_names() const
Get all the names of the subgroups in the current group.
Definition group.cpp:192
group()=default
Default constructor (only necessary for the Python interface).
A generic handle for HDF5 objects.
Definition object.hpp:49
bool is_valid() const
Ensure that the wrapped HDF5 ID is valid (by calling H5Iis_valid).
Definition object.cpp:116
Provides a handle to an HDF5 group and various methods to simplify the creation/opening of subgroups,...
int64_t hid_t
ID type used in HDF5.
Definition utils.hpp:45