00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <shogun/lib/config.h>
00012
00013 #ifdef HAVE_HDF5
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #include <hdf5.h>
00018
00019 #include "lib/HDF5File.h"
00020
00021 #include "features/StringFeatures.h"
00022 #include "features/SparseFeatures.h"
00023
00024 using namespace shogun;
00025
00026 CHDF5File::CHDF5File(char* fname, char rw, const char* name) : CFile()
00027 {
00028 get_boolean_type();
00029 H5Eset_auto(NULL, NULL);
00030
00031 if (name)
00032 set_variable_name(name);
00033
00034 switch (rw)
00035 {
00036 case 'r':
00037 h5file = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT);
00038 break;
00039 case 'w':
00040 h5file = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
00041 break;
00042 case 'a':
00043 h5file = H5Fopen(fname, H5F_ACC_RDWR, H5P_DEFAULT);
00044 if (h5file <0)
00045 h5file = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
00046 break;
00047 default:
00048 SG_ERROR("unknown mode '%c'\n", rw);
00049 };
00050
00051 if (h5file<0)
00052 SG_ERROR("Could not open file '%s'\n", fname);
00053 }
00054
00055 CHDF5File::~CHDF5File()
00056 {
00057 H5Fclose(h5file);
00058 }
00059
00060 #define GET_VECTOR(fname, sg_type, datatype) \
00061 void CHDF5File::fname(sg_type*& vec, int32_t& len) \
00062 { \
00063 if (!h5file) \
00064 SG_ERROR("File invalid.\n"); \
00065 \
00066 int32_t* dims; \
00067 int32_t ndims; \
00068 int64_t nelements; \
00069 hid_t dataset = H5Dopen(h5file, variable_name); \
00070 if (dataset<0) \
00071 SG_ERROR("Error opening data set\n"); \
00072 hid_t dtype = H5Dget_type(dataset); \
00073 H5T_class_t t_class=H5Tget_class(dtype); \
00074 hid_t h5_type=get_compatible_type(t_class, datatype); \
00075 if (h5_type==-1) \
00076 { \
00077 H5Dclose(dataset); \
00078 SG_INFO("No compatible datatype found\n"); \
00079 } \
00080 get_dims(dataset, dims, ndims, nelements); \
00081 if (!((ndims==2 && dims[0]==nelements && dims[1]==1) || \
00082 (ndims==2 && dims[0]==1 && dims[1]==nelements) || \
00083 (ndims==1 && dims[0]==nelements))) \
00084 SG_ERROR("Error not a 1-dimensional vector (ndims=%d, dims[0]=%d)\n", ndims, dims[0]); \
00085 vec=new sg_type[nelements]; \
00086 len=nelements; \
00087 herr_t status = H5Dread(dataset, h5_type, H5S_ALL, \
00088 H5S_ALL, H5P_DEFAULT, vec); \
00089 H5Dclose(dataset); \
00090 H5Tclose(dtype); \
00091 delete[] dims; \
00092 if (status<0) \
00093 { \
00094 delete[] vec; \
00095 SG_ERROR("Error reading dataset\n"); \
00096 } \
00097 }
00098
00099 GET_VECTOR(get_bool_vector, bool, DT_VECTOR_BOOL)
00100 GET_VECTOR(get_byte_vector, uint8_t, DT_VECTOR_BYTE)
00101 GET_VECTOR(get_char_vector, char, DT_VECTOR_CHAR)
00102 GET_VECTOR(get_int_vector, int32_t, DT_VECTOR_INT)
00103 GET_VECTOR(get_shortreal_vector, float32_t, DT_VECTOR_SHORTREAL)
00104 GET_VECTOR(get_real_vector, float64_t, DT_VECTOR_REAL)
00105 GET_VECTOR(get_short_vector, int16_t, DT_VECTOR_SHORT)
00106 GET_VECTOR(get_word_vector, uint16_t, DT_VECTOR_WORD)
00107 #undef GET_VECTOR
00108
00109 #define GET_MATRIX(fname, sg_type, datatype) \
00110 void CHDF5File::fname(sg_type*& matrix, int32_t& num_feat, int32_t& num_vec) \
00111 { \
00112 if (!h5file) \
00113 SG_ERROR("File invalid.\n"); \
00114 \
00115 int32_t* dims; \
00116 int32_t ndims; \
00117 int64_t nelements; \
00118 hid_t dataset = H5Dopen(h5file, variable_name); \
00119 if (dataset<0) \
00120 SG_ERROR("Error opening data set\n"); \
00121 hid_t dtype = H5Dget_type(dataset); \
00122 H5T_class_t t_class=H5Tget_class(dtype); \
00123 hid_t h5_type=get_compatible_type(t_class, datatype); \
00124 if (h5_type==-1) \
00125 { \
00126 H5Dclose(dataset); \
00127 SG_INFO("No compatible datatype found\n"); \
00128 } \
00129 get_dims(dataset, dims, ndims, nelements); \
00130 if (ndims!=2) \
00131 SG_ERROR("Error not a 2-dimensional matrix\n"); \
00132 matrix=new sg_type[nelements]; \
00133 num_feat=dims[0]; \
00134 num_vec=dims[1]; \
00135 herr_t status = H5Dread(dataset, h5_type, H5S_ALL, \
00136 H5S_ALL, H5P_DEFAULT, matrix); \
00137 H5Dclose(dataset); \
00138 H5Tclose(dtype); \
00139 delete[] dims; \
00140 if (status<0) \
00141 { \
00142 delete[] matrix; \
00143 SG_ERROR("Error reading dataset\n"); \
00144 } \
00145 }
00146
00147 GET_MATRIX(get_bool_matrix, bool, DT_DENSE_BOOL)
00148 GET_MATRIX(get_char_matrix, char, DT_DENSE_CHAR)
00149 GET_MATRIX(get_byte_matrix, uint8_t, DT_DENSE_BYTE)
00150 GET_MATRIX(get_int_matrix, int32_t, DT_DENSE_INT)
00151 GET_MATRIX(get_uint_matrix, uint32_t, DT_DENSE_UINT)
00152 GET_MATRIX(get_long_matrix, int64_t, DT_DENSE_LONG)
00153 GET_MATRIX(get_ulong_matrix, uint64_t, DT_DENSE_ULONG)
00154 GET_MATRIX(get_short_matrix, int16_t, DT_DENSE_SHORT)
00155 GET_MATRIX(get_word_matrix, uint16_t, DT_DENSE_WORD)
00156 GET_MATRIX(get_shortreal_matrix, float32_t, DT_DENSE_SHORTREAL)
00157 GET_MATRIX(get_real_matrix, float64_t, DT_DENSE_REAL)
00158 GET_MATRIX(get_longreal_matrix, floatmax_t, DT_DENSE_LONGREAL)
00159 #undef GET_MATRIX
00160
00161 void CHDF5File::get_byte_ndarray(uint8_t*& array, int32_t*& dims, int32_t& num_dims)
00162 {
00163 }
00164
00165 void CHDF5File::get_char_ndarray(char*& array, int32_t*& dims, int32_t& num_dims)
00166 {
00167 }
00168
00169 void CHDF5File::get_int_ndarray(int32_t*& array, int32_t*& dims, int32_t& num_dims)
00170 {
00171 }
00172
00173 void CHDF5File::get_shortreal_ndarray(float32_t*& array, int32_t*& dims, int32_t& num_dims)
00174 {
00175 }
00176
00177 void CHDF5File::get_real_ndarray(float64_t*& array, int32_t*& dims, int32_t& num_dims)
00178 {
00179 }
00180
00181 void CHDF5File::get_short_ndarray(int16_t*& array, int32_t*& dims, int32_t& num_dims)
00182 {
00183 }
00184
00185 void CHDF5File::get_word_ndarray(uint16_t*& array, int32_t*& dims, int32_t& num_dims)
00186 {
00187 }
00188
00189 #define GET_SPARSEMATRIX(fname, sg_type, datatype) \
00190 void CHDF5File::fname(TSparse<sg_type>*& matrix, int32_t& num_feat, int32_t& num_vec) \
00191 { \
00192 if (!(file)) \
00193 SG_ERROR("File invalid.\n"); \
00194 }
00195 GET_SPARSEMATRIX(get_bool_sparsematrix, bool, DT_SPARSE_BOOL)
00196 GET_SPARSEMATRIX(get_char_sparsematrix, char, DT_SPARSE_CHAR)
00197 GET_SPARSEMATRIX(get_byte_sparsematrix, uint8_t, DT_SPARSE_BYTE)
00198 GET_SPARSEMATRIX(get_int_sparsematrix, int32_t, DT_SPARSE_INT)
00199 GET_SPARSEMATRIX(get_uint_sparsematrix, uint32_t, DT_SPARSE_UINT)
00200 GET_SPARSEMATRIX(get_long_sparsematrix, int64_t, DT_SPARSE_LONG)
00201 GET_SPARSEMATRIX(get_ulong_sparsematrix, uint64_t, DT_SPARSE_ULONG)
00202 GET_SPARSEMATRIX(get_short_sparsematrix, int16_t, DT_SPARSE_SHORT)
00203 GET_SPARSEMATRIX(get_word_sparsematrix, uint16_t, DT_SPARSE_WORD)
00204 GET_SPARSEMATRIX(get_shortreal_sparsematrix, float32_t, DT_SPARSE_SHORTREAL)
00205 GET_SPARSEMATRIX(get_real_sparsematrix, float64_t, DT_SPARSE_REAL)
00206 GET_SPARSEMATRIX(get_longreal_sparsematrix, floatmax_t, DT_SPARSE_LONGREAL)
00207 #undef GET_SPARSEMATRIX
00208
00209
00210 #define GET_STRING_LIST(fname, sg_type, datatype) \
00211 void CHDF5File::fname(T_STRING<sg_type>*& strings, int32_t& num_str, int32_t& max_string_len) \
00212 { \
00213 }
00214
00215 GET_STRING_LIST(get_bool_string_list, bool, DT_STRING_BOOL)
00216 GET_STRING_LIST(get_char_string_list, char, DT_STRING_CHAR)
00217 GET_STRING_LIST(get_byte_string_list, uint8_t, DT_STRING_BYTE)
00218 GET_STRING_LIST(get_int_string_list, int32_t, DT_STRING_INT)
00219 GET_STRING_LIST(get_uint_string_list, uint32_t, DT_STRING_UINT)
00220 GET_STRING_LIST(get_long_string_list, int64_t, DT_STRING_LONG)
00221 GET_STRING_LIST(get_ulong_string_list, uint64_t, DT_STRING_ULONG)
00222 GET_STRING_LIST(get_short_string_list, int16_t, DT_STRING_SHORT)
00223 GET_STRING_LIST(get_word_string_list, uint16_t, DT_STRING_WORD)
00224 GET_STRING_LIST(get_shortreal_string_list, float32_t, DT_STRING_SHORTREAL)
00225 GET_STRING_LIST(get_real_string_list, float64_t, DT_STRING_REAL)
00226 GET_STRING_LIST(get_longreal_string_list, floatmax_t, DT_STRING_LONGREAL)
00227 #undef GET_STRING_LIST
00228
00231 #define SET_VECTOR(fname, sg_type, dtype, h5type) \
00232 void CHDF5File::fname(const sg_type* vec, int32_t len) \
00233 { \
00234 if (h5file<0 || !vec) \
00235 SG_ERROR("File or vector invalid.\n"); \
00236 \
00237 create_group_hierarchy(); \
00238 \
00239 hsize_t dims=(hsize_t) len; \
00240 hid_t dataspace, dataset, status; \
00241 dataspace=H5Screate_simple(1, &dims, NULL); \
00242 if (dataspace<0) \
00243 SG_ERROR("Could not create hdf5 dataspace\n"); \
00244 dataset=H5Dcreate(h5file, variable_name, h5type, dataspace, H5P_DEFAULT); \
00245 if (dataset<0) \
00246 { \
00247 SG_ERROR("Could not create hdf5 dataset - does" \
00248 " dataset '%s' already exist?\n", variable_name); \
00249 } \
00250 status=H5Dwrite(dataset, h5type, H5S_ALL, H5S_ALL, H5P_DEFAULT, vec); \
00251 if (status<0) \
00252 SG_ERROR("Failed to write hdf5 dataset\n"); \
00253 H5Dclose(dataset); \
00254 H5Sclose(dataspace); \
00255 }
00256 SET_VECTOR(set_bool_vector, bool, DT_VECTOR_BOOL, boolean_type)
00257 SET_VECTOR(set_byte_vector, uint8_t, DT_VECTOR_BYTE, H5T_NATIVE_UINT8)
00258 SET_VECTOR(set_char_vector, char, DT_VECTOR_CHAR, H5T_NATIVE_CHAR)
00259 SET_VECTOR(set_int_vector, int32_t, DT_VECTOR_INT, H5T_NATIVE_INT32)
00260 SET_VECTOR(set_shortreal_vector, float32_t, DT_VECTOR_SHORTREAL, H5T_NATIVE_FLOAT)
00261 SET_VECTOR(set_real_vector, float64_t, DT_VECTOR_REAL, H5T_NATIVE_DOUBLE)
00262 SET_VECTOR(set_short_vector, int16_t, DT_VECTOR_SHORT, H5T_NATIVE_INT16)
00263 SET_VECTOR(set_word_vector, uint16_t, DT_VECTOR_WORD, H5T_NATIVE_UINT16)
00264 #undef SET_VECTOR
00265
00266 #define SET_MATRIX(fname, sg_type, dtype, h5type) \
00267 void CHDF5File::fname(const sg_type* matrix, int32_t num_feat, int32_t num_vec) \
00268 { \
00269 if (h5file<0 || !matrix) \
00270 SG_ERROR("File or matrix invalid.\n"); \
00271 \
00272 create_group_hierarchy(); \
00273 \
00274 hsize_t dims[2]={(hsize_t) num_feat, (hsize_t) num_vec}; \
00275 hid_t dataspace, dataset, status; \
00276 dataspace=H5Screate_simple(2, dims, NULL); \
00277 if (dataspace<0) \
00278 SG_ERROR("Could not create hdf5 dataspace\n"); \
00279 dataset=H5Dcreate(h5file, variable_name, h5type, dataspace, H5P_DEFAULT); \
00280 if (dataset<0) \
00281 { \
00282 SG_ERROR("Could not create hdf5 dataset - does" \
00283 " dataset '%s' already exist?\n", variable_name); \
00284 } \
00285 status=H5Dwrite(dataset, h5type, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix); \
00286 if (status<0) \
00287 SG_ERROR("Failed to write hdf5 dataset\n"); \
00288 H5Dclose(dataset); \
00289 H5Sclose(dataspace); \
00290 }
00291 SET_MATRIX(set_bool_matrix, bool, DT_DENSE_BOOL, boolean_type)
00292 SET_MATRIX(set_char_matrix, char, DT_DENSE_CHAR, H5T_NATIVE_CHAR)
00293 SET_MATRIX(set_byte_matrix, uint8_t, DT_DENSE_BYTE, H5T_NATIVE_UINT8)
00294 SET_MATRIX(set_int_matrix, int32_t, DT_DENSE_INT, H5T_NATIVE_INT32)
00295 SET_MATRIX(set_uint_matrix, uint32_t, DT_DENSE_UINT, H5T_NATIVE_UINT32)
00296 SET_MATRIX(set_long_matrix, int64_t, DT_DENSE_LONG, H5T_NATIVE_INT64)
00297 SET_MATRIX(set_ulong_matrix, uint64_t, DT_DENSE_ULONG, H5T_NATIVE_UINT64)
00298 SET_MATRIX(set_short_matrix, int16_t, DT_DENSE_SHORT, H5T_NATIVE_INT16)
00299 SET_MATRIX(set_word_matrix, uint16_t, DT_DENSE_WORD, H5T_NATIVE_UINT16)
00300 SET_MATRIX(set_shortreal_matrix, float32_t, DT_DENSE_SHORTREAL, H5T_NATIVE_FLOAT)
00301 SET_MATRIX(set_real_matrix, float64_t, DT_DENSE_REAL, H5T_NATIVE_DOUBLE)
00302 SET_MATRIX(set_longreal_matrix, floatmax_t, DT_DENSE_LONGREAL, H5T_NATIVE_LDOUBLE)
00303 #undef SET_MATRIX
00304
00305 #define SET_SPARSEMATRIX(fname, sg_type, dtype) \
00306 void CHDF5File::fname(const TSparse<sg_type>* matrix, \
00307 int32_t num_feat, int32_t num_vec) \
00308 { \
00309 if (!(file && matrix)) \
00310 SG_ERROR("File or matrix invalid.\n"); \
00311 \
00312 }
00313 SET_SPARSEMATRIX(set_bool_sparsematrix, bool, DT_SPARSE_BOOL)
00314 SET_SPARSEMATRIX(set_char_sparsematrix, char, DT_SPARSE_CHAR)
00315 SET_SPARSEMATRIX(set_byte_sparsematrix, uint8_t, DT_SPARSE_BYTE)
00316 SET_SPARSEMATRIX(set_int_sparsematrix, int32_t, DT_SPARSE_INT)
00317 SET_SPARSEMATRIX(set_uint_sparsematrix, uint32_t, DT_SPARSE_UINT)
00318 SET_SPARSEMATRIX(set_long_sparsematrix, int64_t, DT_SPARSE_LONG)
00319 SET_SPARSEMATRIX(set_ulong_sparsematrix, uint64_t, DT_SPARSE_ULONG)
00320 SET_SPARSEMATRIX(set_short_sparsematrix, int16_t, DT_SPARSE_SHORT)
00321 SET_SPARSEMATRIX(set_word_sparsematrix, uint16_t, DT_SPARSE_WORD)
00322 SET_SPARSEMATRIX(set_shortreal_sparsematrix, float32_t, DT_SPARSE_SHORTREAL)
00323 SET_SPARSEMATRIX(set_real_sparsematrix, float64_t, DT_SPARSE_REAL)
00324 SET_SPARSEMATRIX(set_longreal_sparsematrix, floatmax_t, DT_SPARSE_LONGREAL)
00325 #undef SET_SPARSEMATRIX
00326
00327 #define SET_STRING_LIST(fname, sg_type, dtype) \
00328 void CHDF5File::fname(const T_STRING<sg_type>* strings, int32_t num_str) \
00329 { \
00330 if (!(file && strings)) \
00331 SG_ERROR("File or strings invalid.\n"); \
00332 \
00333 }
00334 SET_STRING_LIST(set_bool_string_list, bool, DT_STRING_BOOL)
00335 SET_STRING_LIST(set_char_string_list, char, DT_STRING_CHAR)
00336 SET_STRING_LIST(set_byte_string_list, uint8_t, DT_STRING_BYTE)
00337 SET_STRING_LIST(set_int_string_list, int32_t, DT_STRING_INT)
00338 SET_STRING_LIST(set_uint_string_list, uint32_t, DT_STRING_UINT)
00339 SET_STRING_LIST(set_long_string_list, int64_t, DT_STRING_LONG)
00340 SET_STRING_LIST(set_ulong_string_list, uint64_t, DT_STRING_ULONG)
00341 SET_STRING_LIST(set_short_string_list, int16_t, DT_STRING_SHORT)
00342 SET_STRING_LIST(set_word_string_list, uint16_t, DT_STRING_WORD)
00343 SET_STRING_LIST(set_shortreal_string_list, float32_t, DT_STRING_SHORTREAL)
00344 SET_STRING_LIST(set_real_string_list, float64_t, DT_STRING_REAL)
00345 SET_STRING_LIST(set_longreal_string_list, floatmax_t, DT_STRING_LONGREAL)
00346 #undef SET_STRING_LIST
00347
00348 void CHDF5File::get_boolean_type()
00349 {
00350 boolean_type=H5T_NATIVE_UCHAR;
00351 switch (sizeof(bool))
00352 {
00353 case 1:
00354 boolean_type = H5T_NATIVE_UCHAR;
00355 break;
00356 case 2:
00357 boolean_type = H5T_NATIVE_UINT16;
00358 break;
00359 case 4:
00360 boolean_type = H5T_NATIVE_UINT32;
00361 break;
00362 case 8:
00363 boolean_type = H5T_NATIVE_UINT64;
00364 break;
00365 default:
00366 SG_ERROR("Boolean type not supported on this platform\n");
00367 }
00368 }
00369
00370 hid_t CHDF5File::get_compatible_type(H5T_class_t t_class, SGDataType datatype)
00371 {
00372 switch (t_class)
00373 {
00374 case H5T_FLOAT:
00375 case H5T_INTEGER:
00376 switch (datatype)
00377 {
00378 case DT_VECTOR_SHORTREAL:
00379 case DT_NDARRAY_SHORTREAL:
00380 case DT_DENSE_SHORTREAL:
00381 return H5T_NATIVE_FLOAT;
00382 case DT_VECTOR_REAL:
00383 case DT_NDARRAY_REAL:
00384 case DT_DENSE_REAL:
00385 return H5T_NATIVE_DOUBLE;
00386 case DT_VECTOR_LONGREAL:
00387 case DT_NDARRAY_LONGREAL:
00388 case DT_DENSE_LONGREAL:
00389 return H5T_NATIVE_LDOUBLE;
00390 case DT_VECTOR_BOOL:
00391 case DT_DENSE_BOOL:
00392 case DT_NDARRAY_BOOL:
00393 return boolean_type;
00394 case DT_VECTOR_BYTE:
00395 case DT_DENSE_BYTE:
00396 case DT_NDARRAY_BYTE:
00397 return H5T_NATIVE_UINT8;
00398 case DT_VECTOR_CHAR:
00399 case DT_DENSE_CHAR:
00400 case DT_NDARRAY_CHAR:
00401 return H5T_NATIVE_CHAR;
00402 case DT_VECTOR_INT:
00403 case DT_DENSE_INT:
00404 case DT_NDARRAY_INT:
00405 return H5T_NATIVE_INT32;
00406 case DT_VECTOR_UINT:
00407 case DT_DENSE_UINT:
00408 case DT_NDARRAY_UINT:
00409 return H5T_NATIVE_UINT32;
00410 case DT_VECTOR_LONG:
00411 case DT_DENSE_LONG:
00412 case DT_NDARRAY_LONG:
00413 return H5T_NATIVE_INT64;
00414 case DT_VECTOR_ULONG:
00415 case DT_DENSE_ULONG:
00416 case DT_NDARRAY_ULONG:
00417 return H5T_NATIVE_UINT64;
00418 case DT_VECTOR_SHORT:
00419 case DT_DENSE_SHORT:
00420 case DT_NDARRAY_SHORT:
00421 return H5T_NATIVE_INT16;
00422 case DT_VECTOR_WORD:
00423 case DT_DENSE_WORD:
00424 case DT_NDARRAY_WORD:
00425 return H5T_NATIVE_UINT16;
00426 default:
00427 return -1;
00428 }
00429 case H5T_STRING:
00430 SG_ERROR("Strings not supported");
00431 return -1;
00432 case H5T_VLEN:
00433 SG_ERROR("Variable length containers currently not supported");
00434 return -1;
00435 case H5T_ARRAY:
00436 SG_ERROR("Array containers currently not supported");
00437 return -1;
00438 default:
00439 SG_ERROR("Datatype mismatchn");
00440 return -1;
00441 }
00442 }
00443
00444 void CHDF5File::get_dims(hid_t dataset, int32_t*& dims, int32_t& ndims, int64_t& total_elements)
00445 {
00446 hid_t dataspace = H5Dget_space(dataset);
00447 if (dataspace<0)
00448 SG_ERROR("Error obtaining hdf5 dataspace\n");
00449
00450 ndims = H5Sget_simple_extent_ndims(dataspace);
00451 total_elements=H5Sget_simple_extent_npoints(dataspace);
00452 hsize_t* dims_out=new hsize_t[ndims];
00453 dims=new int32_t[ndims];
00454 H5Sget_simple_extent_dims(dataspace, dims_out, NULL);
00455 for (int32_t i=0; i<ndims; i++)
00456 dims[i]=dims_out[i];
00457 delete[] dims_out;
00458 H5Sclose(dataspace);
00459 }
00460
00461 void CHDF5File::create_group_hierarchy()
00462 {
00463 char* vname=strdup(variable_name);
00464 int32_t vlen=strlen(vname);
00465 for (int32_t i=0; i<vlen; i++)
00466 {
00467 if (i!=0 && vname[i]=='/')
00468 {
00469 vname[i]='\0';
00470 hid_t g = H5Gopen(h5file, vname);
00471 if (g<0)
00472 {
00473 g=H5Gcreate(h5file, vname, 0);
00474 if (g<0)
00475 SG_ERROR("Error creating group '%s'\n", vname);
00476 vname[i]='/';
00477 }
00478 H5Gclose(g);
00479 }
00480 }
00481 free(vname);
00482 }
00483 #endif // HDF5