Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
HAPI_HDFNode.cc
Go to the documentation of this file.
1/*
2# <<BEGIN-copyright>>
3# Copyright 2019, Lawrence Livermore National Security, LLC.
4# This file is part of the gidiplus package (https://github.com/LLNL/gidiplus).
5# gidiplus is licensed under the MIT license (see https://opensource.org/licenses/MIT).
6# SPDX-License-Identifier: MIT
7# <<END-copyright>>
8*/
9#include "HAPI.hpp"
10
11#ifdef HAPI_USE_HDF5
12
13hid_t getNodeId(hid_t loc_id, std::string name);
14herr_t map_children(hid_t loc_id, char const *name, const H5L_info_t *info, void *opdata);
15
16namespace HAPI {
17
18/*
19=========================================================
20 *
21 * @return
22 */
23HDFNode::HDFNode() :
25 m_node_id( 0 ),
26 m_parent_id( 0 ),
27 m_index( 0 ) {
28
29}
30/*
31=========================================================
32 *
33 * @param a_node
34 * @return
35 */
36HDFNode::HDFNode( hid_t a_node_id, hid_t a_parent_id, size_t a_index, std::vector<childInfo> a_siblings ) :
37 Node_internal( NodeInteralType::HDF5 ),
38 m_node_id( a_node_id ),
39 m_parent_id( a_parent_id ),
40 m_index( a_index ),
41 m_siblings( a_siblings ) {
42
43 H5I_type_t id_type = H5Iget_type( m_node_id );
44 if (H5I_GROUP == id_type) {
45 hsize_t start_idx = 0;
46 H5Literate(m_node_id, H5_INDEX_NAME, H5_ITER_NATIVE, &start_idx, map_children, &m_children);
47 }
48 else if (H5I_DATASET == id_type) {
49 return; // has no child elements
50 }
51 else {
52 throw "Unknown object type encountered in HDF file";
53 }
54}
55/*
56=========================================================
57 *
58 * Alternate constructor to allow treating H5File as a Node
59 *
60 * @param a_file
61 * @return
62 */
63HDFNode::HDFNode( hid_t a_file_id) :
64 Node_internal( NodeInteralType::HDF5 ),
65 m_node_id( a_file_id ),
66 m_parent_id( 0 ),
67 m_index( 0 ) {
68
69 hsize_t start_idx = 0;
70 H5Literate(m_node_id, H5_INDEX_NAME, H5_ITER_NATIVE, &start_idx, map_children, &m_children);
71
72}
73/*
74============================================================
75====================== copy constructor ====================
76============================================================
77 */
78HDFNode::HDFNode(const HDFNode &other) :
79 Node_internal( other ),
80 m_node_id( other.m_node_id ),
81 m_parent_id( other.m_parent_id ),
82 m_index( other.m_index ),
83 m_siblings( other.m_siblings ),
84 m_children( other.m_children ) {
85
86}
87/*
88=========================================================
89*/
90HDFNode::~HDFNode( ) {
91
92}
93/*
94============================================================
95=================== get attribute by name ==================
96============================================================
97 *
98 * @param a_name
99 * @return
100 */
101std::string HDFNode::attribute(char const *a_name) {
102
103 if ((m_node_id == 0) || (!H5Aexists(m_node_id, a_name)))
104 return "";
105
106 hid_t attr_id = H5Aopen(m_node_id, a_name, H5P_DEFAULT);
107 size_t attr_len = H5Aget_storage_size(attr_id);
108 hid_t atype = H5Aget_type(attr_id);
109
110 std::vector<char> buffer(attr_len+1, 0);
111 H5Aread(attr_id, atype, buffer.data());
112
113 std::string attrValue(buffer.data());
114
115 return attrValue;
116}
117
118
119int HDFNode::attribute_as_int(const char* a_name){
120 hid_t attr_id = H5Aopen(m_node_id, a_name, H5P_DEFAULT);
121 size_t attr_len = H5Aget_storage_size(attr_id);
122 hid_t atype = H5Aget_type(attr_id);
123
124 std::vector<char> buffer(attr_len+1, 0);
125 H5Aread(attr_id, atype, buffer.data());
126
127 return atoi(buffer.data());
128
129}
130long HDFNode::attribute_as_long(const char* a_name){
131 hid_t attr_id = H5Aopen(m_node_id, a_name, H5P_DEFAULT);
132 size_t attr_len = H5Aget_storage_size(attr_id);
133
134 std::vector<char> buffer(attr_len+1, 0);
135 H5Aread(attr_id, H5T_NATIVE_CHAR, buffer.data());
136
137 return atol(buffer.data());
138
139}
140double HDFNode::attribute_as_double(const char* a_name){
141 hid_t attr_id = H5Aopen(m_node_id, a_name, H5P_DEFAULT);
142 size_t attr_len = H5Aget_storage_size(attr_id);
143 hid_t atype = H5Aget_type(attr_id);
144
145 std::vector<char> buffer(attr_len+1, 0);
146 H5Aread(attr_id, atype, buffer.data());
147
148 return atof(buffer.data());
149}
150
151/*
152============================================================
153===================== get child element ====================
154============================================================
155 *
156 * @return
157 */
158Node_internal *HDFNode::child(char const *a_name) {
159
160 for (size_t idx=0; idx<m_children.size(); idx++)
161 {
162 if ( m_children[idx].xmlName == a_name ) {
163 hid_t child_id = getNodeId(m_node_id, m_children[idx].name.c_str());
164 HDFNode *child = new HDFNode(child_id, m_node_id, idx, m_children);
165 return child;
166 }
167 }
168 return new HDFNode();
169
170}
171/*
172============================================================
173===================== get first child node =================
174============================================================
175*/
176Node_internal *HDFNode::first_child() {
177
178 if (m_children.size() == 0)
179 return new HDFNode();
180 hid_t child_id = getNodeId(m_node_id, m_children[0].name);
181 HDFNode *child = new HDFNode(child_id, m_node_id, 0, m_children);
182 return child;
183}
184/*
185============================================================
186===================== get sibling element ==================
187============================================================
188 *
189 * @return
190 */
191Node_internal *HDFNode::next_sibling() {
192
193 size_t nextIndex = m_index + 1;
194 if (nextIndex >= this->m_siblings.size())
195 return new HDFNode();
196 hid_t sibling_id = this->m_siblings[nextIndex].node_id;
197 HDFNode *sibling = new HDFNode(sibling_id, m_parent_id, nextIndex, m_siblings);
198 return sibling;
199
200}
201/*
202============================================================
203============ update self to point to next sibling ==========
204============================================================
205 *
206 * @return
207 */
208void HDFNode::to_next_sibling() {
209
210 size_t nextIndex = m_index + 1;
211 size_t nsibs = this->m_siblings.size();
212 if (nextIndex >= nsibs)
213 {
214 m_node_id = 0;
215 }
216 else
217 {
218 m_node_id = this->m_siblings[nextIndex].node_id;
219 m_index = nextIndex;
220 }
221}
222/*
223============================================================
224======================== make a copy =======================
225============================================================
226 *
227 * @return
228 */
229Node_internal *HDFNode::copy() {
230
231 if (m_node_id == 0)
232 return new HDFNode();
233
234 HDFNode *copy = new HDFNode( m_node_id, m_parent_id, m_index, m_siblings );
235 copy->m_children = m_children;
236 return copy;
237
238}
239/*
240============================================================
241===================== assignment operator ==================
242============================================================
243 */
244Node_internal &HDFNode::operator=(const HDFNode &other) {
245
246 this->m_node_id = other.m_node_id;
247 this->m_parent_id = other.m_parent_id;
248 this->m_index = other.m_index;
249 this->m_siblings = other.m_siblings;
250 this->m_children = other.m_children;
251 return *this;
252
253}
254/*
255============================================================
256===================== get tag name =========================
257============================================================
258 *
259 * @return
260 */
261std::string HDFNode::name() const {
262
263 if (m_node_id == 0)
264 return "";
265
266 hid_t attr_id = H5Aopen(m_node_id, "_xmltag", H5P_DEFAULT);
267 size_t attr_len = H5Aget_storage_size(attr_id);
268 hid_t atype = H5Aget_type(attr_id);
269
270 std::vector<char> buffer(attr_len+1, 0);
271 H5Aread(attr_id, atype, buffer.data());
272
273 return std::string(buffer.data());
274
275}
276/*
277============================================================
278================== test for empty node =====================
279============================================================
280 *
281 * @return
282 */
283bool HDFNode::empty() const {
284
285 return (m_node_id == 0);
286
287}
288/*
289============================================================
290======================= text data ==========================
291============================================================
292 *
293 * @return
294 */
295Text HDFNode::text() const {
296
297#if H5_VERSION_GE(1,12,0)
298 H5O_info2_t infobuf;
299 herr_t status = H5Oget_info3(m_node_id, &infobuf, H5O_INFO_NUM_ATTRS);
300#else
301 H5O_info_t infobuf;
302 herr_t status = H5Oget_info(m_node_id, &infobuf);
303#endif
304 if (status != 0) throw "unable to extract text from HDF";
305
306 switch (infobuf.type) {
307 case H5O_TYPE_GROUP:
308 return Text( );
309 break;
310 case H5O_TYPE_DATASET: {
311 size_t len = H5Dget_storage_size(m_node_id);
312 hid_t dtype = H5Dget_type(m_node_id);
313 std::vector<char> buffer(len+1,0);
314 H5Dread(m_node_id, dtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer.data());
315
316 return Text(std::string(buffer.data())); }
317 break;
318 default:
319 throw "encountered unexpected type in HDF::text()!";
320 }
321}
322/*
323============================================================
324===================== numeric data =========================
325============================================================
326 *
327 * @return
328 */
329Data_internal *HDFNode::data() const {
330
331 return new HDFData( m_node_id );
332
333}
334
335}
336
337
338/*
339============================================================
340=============== get child HDF5 id by name ==================
341============================================================
342 */
343hid_t getNodeId(hid_t loc_id, std::string name)
344{
345#if H5_VERSION_GE(1,12,0)
346 H5O_info2_t infobuf;
347 herr_t status = H5Oget_info_by_name3( loc_id, name.c_str( ), &infobuf, H5O_INFO_NUM_ATTRS, H5P_DEFAULT );
348#else
349 H5O_info_t infobuf;
350 herr_t status = H5Oget_info_by_name(loc_id, name.c_str(), &infobuf, H5P_DEFAULT);
351#endif
352 if (status != 0) {
353 throw "requested child node not found in getNodeId";
354 }
355
356 hid_t node_id;
357
358 switch (infobuf.type) {
359 case H5O_TYPE_GROUP:
360 node_id = H5Gopen(loc_id, name.c_str(), H5P_DEFAULT);
361 break;
362 case H5O_TYPE_DATASET:
363 node_id = H5Dopen(loc_id, name.c_str(), H5P_DEFAULT);
364 break;
365 default:
366 throw "encountered unexpected type in getNodeId!";
367 }
368
369 return node_id;
370}
371
372/*
373============================================================
374========== called by iterateElems in constructor ===========
375============================================================
376 */
377herr_t map_children(hid_t loc_id, char const *name, LUPI_maybeUnused const H5L_info_t *info, void *opdata)
378{
379 std::vector<HAPI::childInfo> *children =
380 static_cast< std::vector<HAPI::childInfo>* >(opdata);
381
382 hid_t node_id = H5Oopen(loc_id, name, H5P_DEFAULT);
383
384 std::string xmlTag;
385 {
386 hid_t attr_id = H5Aopen(node_id, "_xmltag", H5P_DEFAULT);
387 hid_t atype = H5Aget_type(attr_id);
388 size_t attr_len = H5Aget_storage_size(attr_id);
389
390 std::vector<char> buffer(attr_len+1, 0);
391 H5Aread(attr_id, atype, buffer.data());
392
393 xmlTag = std::string(buffer.data());
394 }
395
396
397 uint index;
398 {
399 hid_t attr_id = H5Aopen(node_id, "_xmlindex", H5P_DEFAULT);
400
401 H5Aread(attr_id, H5T_NATIVE_UINT16_g, &index);
402 }
403
404 HAPI::childInfo infos = {
405 std::string(name),
406 xmlTag,
407 index,
408 node_id
409 };
410
411 if (index >= children->size())
412 {
413 children->resize(index+1);
414 }
415 (*children)[index] = infos;
416
417 //printf("ITER: id=%d, index=%d, name=%s\n", (int)node_id, (int)index, name);
418
419 //H5Oclose(node_id);
420
421 return 0;
422 }
423#endif
#define LUPI_maybeUnused
const char * name(G4int ptype)
Definition HAPI.hpp:34
NodeInteralType
Definition HAPI.hpp:36
void copy(G4double dst[], const G4double src[], std::size_t size=G4FieldTrack::ncompSVEC)