hdf_file.h
Go to the documentation of this file.
1 /*
2  -------------------------------------------------------------------
3 
4  Copyright (C) 2006-2018, Andrew W. Steiner
5 
6  This file is part of O2scl.
7 
8  O2scl is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version.
12 
13  O2scl is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with O2scl. If not, see <http://www.gnu.org/licenses/>.
20 
21  -------------------------------------------------------------------
22 */
23 #ifndef O2SCL_HDF_FILE_H
24 #define O2SCL_HDF_FILE_H
25 
26 /** \file hdf_file.h
27  \brief File defining \ref o2scl_hdf::hdf_file
28 */
29 #include <limits>
30 
31 #ifdef O2SCL_UBUNTU_HDF5
32 #include <hdf5/serial/hdf5.h>
33 #else
34 #include <hdf5.h>
35 #endif
36 
37 #include <boost/numeric/ublas/vector.hpp>
38 #include <boost/numeric/ublas/matrix.hpp>
39 
40 #include <o2scl/vector.h>
41 #include <o2scl/tensor.h>
42 #include <o2scl/format_float.h>
43 
44 /** \brief The \o2 namespace for I/O with HDF
45  */
46 namespace o2scl_hdf {
47 
48  /** \brief Store data in an \o2 compatible HDF5 file
49 
50  See also the \ref hdf_section section of the \o2
51  User's guide.
52 
53  The member functions which write or get data from an HDF file
54  begin with either <tt>get</tt> or <tt>set</tt>. Where
55  appropriate, the next character is either \c c for character, \c
56  d for double, \c f for float, or \c i for int.
57 
58  By default, vectors and matrices are written to HDF files in a
59  chunked format, so their length can be changed later as
60  necessary. The chunk size is chosen in \ref def_chunk() to be
61  the closest power of 10 to the current vector size.
62 
63  All files not closed by the user are closed in the destructor,
64  but the destructor does not automatically close groups.
65 
66  \note Currently, HDF I/O functions write data to HDF files
67  assuming that \c int and \c float have 4 bytes, while \c size_t
68  and \c double are 8 bytes. All output is done in little endian
69  format. While <tt>get</tt> functions can read data with
70  different sizes or in big endian format, the <tt>set</tt>
71  functions cannot currently write data this way.
72 
73  \note It does make sense to write a zero-length vector to an HDF
74  file if the vector does not have a fixed size in order to create
75  a placeholder for future output. Thus the <tt>set_vec()</tt> and
76  allow zero-length vectors and the <tt>set_arr()</tt> functions
77  allow the <tt>size_t</tt> parameter to be zero, in which case
78  the pointer parameter is ignored. The <tt>set_vec_fixed()</tt>
79  and <tt>set_arr_fixed()</tt> functions do not allow this, and
80  will throw an exception if sent a zero-length vector.
81 
82  \warning This class is still in development. Because of this,
83  hdf5 files generated by this class may not be easily read by
84  future versions. Later versions of \o2 will have stronger
85  guarantees on backwards compatibility.
86 
87  \future This class opens all files in R/W mode, which may
88  cause I/O problems in file systems. This needs to be
89  fixed by allowing the user to open a read-only file.
90  \future The \o2 HDF functions do not always consistently choose
91  between throwing \o2 exceptions and throwing HDF5 exceptions.
92  Check and/or fix this.
93  \future Automatically close groups, e.g. by storing hid_t's in a
94  stack?
95  \future Rewrite the _arr_alloc() functions so that they
96  return a shared_ptr.
97  \future Move the code from the 'filelist' acol command here
98  into hdf_file.
99  */
100  class hdf_file {
101 
102  public:
103 
108 
109 #ifndef DOXYGEN_INTERNAL
110 
111  protected:
112 
113  /// File ID
114  hid_t file;
115 
116  /// True if a file has been opened
117  bool file_open;
118 
119  /// Current file or group location
120  hid_t current;
121 
122  /** \brief Default chunk size
123 
124  Choose the closest power of 10 which is greater than or equal
125  to 10 and less than or equal to \f$ 10^6 \f$.
126  */
127  virtual hsize_t def_chunk(size_t n) {
128  size_t ch=(size_t)((1.0+1.0e-12)*
129  pow(10.0,floor(log10(((double)n))+0.5)));
130  if (ch<10) ch=10;
131  if (ch>1000000) ch=1000000;
132  return ch;
133  }
134 
135  /// If true, then the file has read and write access
137 
138 #endif
139 
140  public:
141 
142  hdf_file();
143 
144  virtual ~hdf_file();
145 
146  /// If true, then the file has read and write access
148  return write_access;
149  }
150 
151  /// Compression type (support experimental)
153 
154  /// Minimum size to compress by default
156 
157  /// \name Open and close files
158  //@{
159  /** \brief Open a file named \c fname
160 
161  If \c err_on_fail is \c true, this calls the error handler if
162  opening the file fails (e.g. because the file does not exist).
163  If \c err_on_fail is \c false and opening the file fails,
164  nothing is done and the function returns the value \ref
165  o2scl::exc_efilenotfound. If the open succeeds, this function
166  returns \ref o2scl::success.
167  */
168  int open(std::string fname, bool write_access=false,
169  bool err_on_fail=true);
170 
171  /// Open a file named \c fname or create if it doesn't already exist
172  void open_or_create(std::string fname);
173 
174  /// Close the file
175  void close();
176  //@}
177 
178  /// \name Manipulate ids
179  //@{
180  /// Get the current file id
181  hid_t get_file_id();
182 
183  /// Set the current working id
184  void set_current_id(hid_t cur);
185 
186  /// Retrieve the current working id
187  hid_t get_current_id();
188  //@}
189 
190  /** \name Simple get functions
191 
192  If the specified object is not found, the \o2 error handler
193  will be called.
194  */
195  //@{
196  /// Get a character named \c name
197  int getc(std::string name, char &c);
198 
199  /// Get a double named \c name
200  int getd(std::string name, double &d);
201 
202  /// Get a float named \c name
203  int getf(std::string name, float &f);
204 
205  /// Get a integer named \c name
206  int geti(std::string name, int &i);
207 
208  /// Get an unsigned integer named \c name
209  int get_szt(std::string name, size_t &u);
210 
211  /** \brief Get a string named \c name
212 
213  \note Strings are stored as character arrays and thus
214  retrieving a string from a file requires loading the
215  information from the file into a character array, and then
216  copying it to the string. This will be slow for very long
217  strings.
218  */
219  int gets(std::string name, std::string &s);
220 
221  /** \brief Get a variable length string named \c name
222  */
223  int gets_var(std::string name, std::string &s);
224 
225  /** \brief Get a fixed-length string named \c name
226  */
227  int gets_fixed(std::string name, std::string &s);
228 
229  /** \brief Get a fixed-length string named \c name with default
230  value \c s
231  */
232  int gets_def_fixed(std::string name, std::string def, std::string &s);
233  //@}
234 
235  /// \name Simple set functions
236  //@{
237  /// Set a character named \c name to value \c c
238  void setc(std::string name, char c);
239 
240  /// Set a double named \c name to value \c d
241  void setd(std::string name, double d);
242 
243  /// Set a float named \c name to value \c f
244  void setf(std::string name, float f);
245 
246  /// Set an integer named \c name to value \c i
247  void seti(std::string name, int i);
248 
249  /// Set an unsigned integer named \c name to value \c u
250  void set_szt(std::string name, size_t u);
251 
252  /** \brief Set a string named \c name to value \c s
253 
254  The string is stored in the HDF file as an extensible
255  character array rather than a string.
256  */
257  void sets(std::string name, std::string s);
258 
259  /** \brief Set a fixed-length string named \c name to value \c s
260 
261  This function stores <tt>s</tt> as a fixed-length string
262  in the HDF file. If a dataset named \c name is already
263  present, then \c s must not be longer than the string
264  length already specified in the HDF file.
265  */
266  void sets_fixed(std::string name, std::string s);
267  //@}
268 
269  /// \name Group manipulation
270  //@{
271  /** \brief Open a group relative to the location specified in
272  \c init_id
273 
274  \note In order to ensure that future objects are written to the
275  newly-created group, the user must use set_current_id()
276  using the newly-created group ID for the argument.
277  */
278  hid_t open_group(hid_t init_id, std::string path);
279 
280  /** \brief Open a group relative to the current location
281 
282  \note In order to ensure that future objects are written to the
283  newly-created group, the user must use set_current_id()
284  using the newly-created group ID for the argument.
285  */
286  hid_t open_group(std::string path);
287 
288  /// Close a previously created group
289  int close_group(hid_t group) {
290  return H5Gclose(group);
291  }
292  //@}
293 
294  /** \name Vector get functions
295 
296  These functions automatically free any previously allocated
297  memory in <tt>v</tt> and then allocate the proper space
298  required to read the information from the HDF file.
299  */
300  //@{
301  /// Get vector dataset and place data in \c v
302  int getd_vec(std::string name, std::vector<double> &v);
303 
304  /** \brief Get vector dataset and place data in \c v
305 
306  This works with any vector class which has a
307  <tt>resize()</tt> method.
308 
309  \future This currently requires a copy, but there may
310  be a way to write a new version which does not.
311  \comment
312  AWS 12/10/13: I don't think the ublas library guarantees
313  that the vector occupies a continuous chunk of memory
314  like std::vector<> now does.
315  \endcomment
316  */
317  template<class vec_t>
318  int getd_vec_copy(std::string name, vec_t &v) {
319  std::vector<double> v2;
320  int ret=getd_vec(name,v2);
321  v.resize(v2.size());
322  o2scl::vector_copy(v2.size(),v2,v);
323  return ret;
324  }
325 
326  /// Get vector dataset and place data in \c v
327  int geti_vec(std::string name, std::vector<int> &v);
328  /** \brief Get vector dataset and place data in \c v
329 
330  \future This currently requires a copy, but there may
331  be a way to write a new version which does not.
332  */
333  template<class vec_int_t>
334  int geti_vec_copy(std::string name, vec_int_t &v) {
335  std::vector<int> v2;
336  int ret=geti_vec(name,v2);
337  v.resize(v2.size());
338  for(size_t i=0;i<v2.size();i++) v[i]=v2[i];
339  return ret;
340  }
341  /// Get vector dataset and place data in \c v
342  int get_szt_vec(std::string name, std::vector<size_t> &v);
343  /** \brief Get vector dataset and place data in \c v
344 
345  \future This currently requires a copy, but there may
346  be a way to write a new version which does not.
347  */
348  template<class vec_size_t>
349  int get_szt_vec_copy(std::string name, vec_size_t &v) {
350  std::vector<int> v2;
351  int ret=geti_vec(name,v2);
352  v.resize(v2.size());
353  for(size_t i=0;i<v2.size();i++) v[i]=v2[i];
354  return ret;
355  }
356  /** \brief Get a vector of strings named \c name and store it in \c s
357  */
358  int gets_vec(std::string name, std::vector<std::string> &s);
359  //@}
360 
361  /** \name Vector set functions
362 
363  These functions automatically write all of the vector elements
364  to the HDF file, if necessary extending the data that is
365  already present.
366  */
367  //@{
368  /// Set vector dataset named \c name with \c v
369  int setd_vec(std::string name, const std::vector<double> &v);
370 
371  /** \brief Set vector dataset named \c name with \c v
372 
373  This requires a copy before the vector is written to
374  the file.
375  */
376  template<class vec_t>
377  int setd_vec_copy(std::string name, const vec_t &v) {
378  if (v.size()==0) {
379  return setd_arr(name,0,0);
380  }
381 
382  // We have to copy to an std::vector first
383  std::vector<double> v2(v.size());
384  o2scl::vector_copy(v.size(),v,v2);
385 
386  return setd_arr(name,v2.size(),&v2[0]);
387  }
388 
389  /// Set vector dataset named \c name with \c v
390  int seti_vec(std::string name, const std::vector<int> &v);
391  /** \brief Set vector dataset named \c name with \c v
392 
393  This requires a copy before the vector is written to
394  the file.
395  */
396  template<class vec_int_t>
397  int seti_vec_copy(std::string name, vec_int_t &v) {
398  if (v.size()==0) {
399  return seti_arr(name,0,0);
400  }
401 
402  // We have to copy to an std::vector first
403  std::vector<int> v2(v.size());
404  vector_copy(v.size(),v,v2);
405 
406  return seti_arr(name,v2.size(),&v2[0]);
407  }
408  /// Set vector dataset named \c name with \c v
409  int set_szt_vec(std::string name, const std::vector<size_t> &v);
410  /** \brief Set vector dataset named \c name with \c v
411 
412  This requires a copy before the vector is written to
413  the file.
414  */
415  template<class vec_size_t>
416  int set_szt_vec_copy(std::string name, const vec_size_t &v) {
417  if (v.size()==0) {
418  return set_szt_arr(name,0,0);
419  }
420 
421  // We have to copy to an std::vector first
422  std::vector<size_t> v2(v.size());
423  vector_copy(v.size(),v,v2);
424 
425  return set_szt_arr(name,v2.size(),&v2[0]);
426  }
427 
428  /** \brief Set a vector of strings named \c name
429 
430  \devnote
431  String vectors are reformatted as a single character array, in
432  order to allow each string to have different length and to
433  make each string extensible. The size of the vector \c s is
434  stored as an integer named <tt>nw</tt>.
435  */
436  int sets_vec(std::string name, const std::vector<std::string> &s);
437  //@}
438 
439  /** \name Matrix get functions
440 
441  These functions automatically free any previously allocated
442  memory in <tt>m</tt> and then allocate the proper space
443  required to read the information from the HDF file.
444  */
445  //@{
446  /// Get matrix dataset and place data in \c m
447  int getd_mat_copy(std::string name, ubmatrix &m);
448  /// Get matrix dataset and place data in \c m
449  int geti_mat_copy(std::string name, ubmatrix_int &m);
450  //@}
451 
452  /** \name Matrix set functions
453 
454  These functions automatically write all of the vector elements
455  to the HDF file, if necessary extending the data that is
456  already present.
457  */
458  //@{
459  /** \brief Set matrix dataset named \c name with \c m
460  */
461  int setd_mat_copy(std::string name, const ubmatrix &m);
462 
463  /** \brief Set matrix dataset named \c name with \c m
464  */
465  int seti_mat_copy(std::string name, const ubmatrix_int &m);
466 
467  /** \brief Set a two-dimensional array dataset named \c name with \c m
468  */
469  template<class arr2d_t>
470  int setd_arr2d_copy(std::string name, size_t r,
471  size_t c, const arr2d_t &a2d) {
472 
473  if (write_access==false) {
474  O2SCL_ERR2("File not opened with write access ",
475  "in hdf_file::setd_arr2d_copy().",o2scl::exc_efailed);
476  }
477 
478  // Copy to a C-style array
479  double *d=new double[r*c];
480  for(size_t i=0;i<r;i++) {
481  for(size_t j=0;j<c;j++) {
482  d[i*c+j]=a2d[i][j];
483  }
484  }
485 
486  hid_t dset, space, dcpl=0;
487  bool chunk_alloc=false;
488 
489  H5E_BEGIN_TRY
490  {
491  // See if the dataspace already exists first
492  dset=H5Dopen(current,name.c_str(),H5P_DEFAULT);
493  }
494  H5E_END_TRY
495 #ifdef O2SCL_NEVER_DEFINED
496  {
497  }
498 #endif
499 
500  // If it doesn't exist, create it
501  if (dset<0) {
502 
503  // Create the dataspace
504  hsize_t dims[2]={r,c};
505  hsize_t max[2]={H5S_UNLIMITED,H5S_UNLIMITED};
506  space=H5Screate_simple(2,dims,max);
507 
508  // Set chunk with size determined by def_chunk()
509  dcpl=H5Pcreate(H5P_DATASET_CREATE);
510  hsize_t chunk[2]={def_chunk(r),def_chunk(c)};
511  int status2=H5Pset_chunk(dcpl,2,chunk);
512 
513 #ifdef O2SCL_HDF5_COMP
514  // Compression part
515  if (compr_type==1) {
516  int status3=H5Pset_deflate(dcpl,6);
517  } else if (compr_type==2) {
518  int status3=H5Pset_szip(dcpl,H5_SZIP_NN_OPTION_MASK,16);
519  } else if (compr_type!=0) {
520  O2SCL_ERR2("Invalid compression type in ",
521  "hdf_file::setd_arr2d_copy().",o2scl::exc_einval);
522  }
523 #endif
524 
525  // Create the dataset
526  dset=H5Dcreate(current,name.c_str(),H5T_IEEE_F64LE,space,H5P_DEFAULT,
527  dcpl,H5P_DEFAULT);
528  chunk_alloc=true;
529 
530  } else {
531 
532  // Get current dimensions
533  space=H5Dget_space(dset);
534  hsize_t dims[2];
535  int ndims=H5Sget_simple_extent_dims(space,dims,0);
536 
537  // Set error if this dataset is more than 1-dimensional
538  if (ndims!=2) {
539  O2SCL_ERR2("Tried to set a non-matrix dataset with a ",
540  "matrix in hdf_file::setd_arr2d_copy().",
542  }
543 
544  // If necessary, extend the dataset
545  if (r!=dims[0] || c!=dims[1]) {
546  hsize_t new_dims[2]={r,c};
547  int status3=H5Dset_extent(dset,new_dims);
548  }
549 
550  }
551 
552  // Write the data
553  int status;
554  status=H5Dwrite(dset,H5T_NATIVE_DOUBLE,H5S_ALL,
555  H5S_ALL,H5P_DEFAULT,d);
556 
557  status=H5Dclose(dset);
558  status=H5Sclose(space);
559  if (chunk_alloc) {
560  status=H5Pclose(dcpl);
561  }
562 
563  // Free the C-style array
564  delete[] d;
565 
566  return 0;
567  }
568 
569  /** \brief Set a two-dimensional array dataset named \c name with \c m
570  */
571  template<class arr2d_t>
572  int seti_arr2d_copy(std::string name, size_t r,
573  size_t c, const arr2d_t &a2d) {
574 
575  if (write_access==false) {
576  O2SCL_ERR2("File not opened with write access ",
577  "in hdf_file::seti_arr2d_copy().",o2scl::exc_efailed);
578  }
579 
580  // Copy to a C-style array
581  int *d=new int[r*c];
582  for(size_t i=0;i<r;i++) {
583  for(size_t j=0;j<c;j++) {
584  d[i*c+j]=a2d[i][j];
585  }
586  }
587 
588  hid_t dset, space, dcpl=0;
589  bool chunk_alloc=false;
590 
591  H5E_BEGIN_TRY
592  {
593  // See if the dataspace already exists first
594  dset=H5Dopen(current,name.c_str(),H5P_DEFAULT);
595  }
596  H5E_END_TRY
597 #ifdef O2SCL_NEVER_DEFINED
598  {
599  }
600 #endif
601 
602  // If it doesn't exist, create it
603  if (dset<0) {
604 
605  // Create the dataspace
606  hsize_t dims[2]={r,c};
607  hsize_t max[2]={H5S_UNLIMITED,H5S_UNLIMITED};
608  space=H5Screate_simple(2,dims,max);
609 
610  // Set chunk with size determined by def_chunk()
611  dcpl=H5Pcreate(H5P_DATASET_CREATE);
612  hsize_t chunk[2]={def_chunk(r),def_chunk(c)};
613  int status2=H5Pset_chunk(dcpl,2,chunk);
614 
615 #ifdef O2SCL_HDF5_COMP
616  // Compression part
617  if (compr_type==1) {
618  int status3=H5Pset_deflate(dcpl,6);
619  } else if (compr_type==2) {
620  int status3=H5Pset_szip(dcpl,H5_SZIP_NN_OPTION_MASK,16);
621  } else if (compr_type!=0) {
622  O2SCL_ERR2("Invalid compression type in ",
623  "hdf_file::seti_arr2d_copy().",o2scl::exc_einval);
624  }
625 #endif
626 
627  // Create the dataset
628  dset=H5Dcreate(current,name.c_str(),H5T_STD_I32LE,space,H5P_DEFAULT,
629  dcpl,H5P_DEFAULT);
630  chunk_alloc=true;
631 
632  } else {
633 
634  // Get current dimensions
635  space=H5Dget_space(dset);
636  hsize_t dims[2];
637  int ndims=H5Sget_simple_extent_dims(space,dims,0);
638 
639  // Set error if this dataset is more than 1-dimensional
640  if (ndims!=2) {
641  O2SCL_ERR2("Tried to set a non-matrix dataset with a ",
642  "matrix in hdf_file::seti_arr2d_copy().",
644  }
645 
646  // If necessary, extend the dataset
647  if (r!=dims[0] || c!=dims[1]) {
648  hsize_t new_dims[2]={r,c};
649  int status3=H5Dset_extent(dset,new_dims);
650  }
651 
652  }
653 
654  // Write the data
655  int status;
656  status=H5Dwrite(dset,H5T_NATIVE_INT,H5S_ALL,
657  H5S_ALL,H5P_DEFAULT,d);
658 
659  status=H5Dclose(dset);
660  status=H5Sclose(space);
661  if (chunk_alloc) {
662  status=H5Pclose(dcpl);
663  }
664 
665  // Free the C-style array
666  delete[] d;
667 
668  return 0;
669  }
670 
671  /** \brief Set a two-dimensional array dataset named \c name with \c m
672  */
673  template<class arr2d_t>
674  int set_szt_arr2d_copy(std::string name, size_t r,
675  size_t c, const arr2d_t &a2d) {
676 
677  if (write_access==false) {
678  O2SCL_ERR2("File not opened with write access ",
679  "in hdf_file::set_szt_arr2d_copy().",o2scl::exc_efailed);
680  }
681 
682  // Copy to a C-style array
683  size_t *d=new size_t[r*c];
684  for(size_t i=0;i<r;i++) {
685  for(size_t j=0;j<c;j++) {
686  d[i*c+j]=a2d[i][j];
687  }
688  }
689 
690  hid_t dset, space, dcpl=0;
691  bool chunk_alloc=false;
692 
693  H5E_BEGIN_TRY
694  {
695  // See if the dataspace already exists first
696  dset=H5Dopen(current,name.c_str(),H5P_DEFAULT);
697  }
698  H5E_END_TRY
699 #ifdef O2SCL_NEVER_DEFINED
700  {
701  }
702 #endif
703 
704  // If it doesn't exist, create it
705  if (dset<0) {
706 
707  // Create the dataspace
708  hsize_t dims[2]={r,c};
709  hsize_t max[2]={H5S_UNLIMITED,H5S_UNLIMITED};
710  space=H5Screate_simple(2,dims,max);
711 
712  // Set chunk with size determined by def_chunk()
713  dcpl=H5Pcreate(H5P_DATASET_CREATE);
714  hsize_t chunk[2]={def_chunk(r),def_chunk(c)};
715  int status2=H5Pset_chunk(dcpl,2,chunk);
716 
717 #ifdef O2SCL_HDF5_COMP
718  // Compression part
719  if (compr_type==1) {
720  int status3=H5Pset_deflate(dcpl,6);
721  } else if (compr_type==2) {
722  int status3=H5Pset_szip(dcpl,H5_SZIP_NN_OPTION_MASK,16);
723  } else if (compr_type!=0) {
724  O2SCL_ERR2("Invalid compression type in ",
725  "hdf_file::set_szt_arr2d_copy().",o2scl::exc_einval);
726  }
727 #endif
728 
729  // Create the dataset
730  dset=H5Dcreate(current,name.c_str(),H5T_STD_U64LE,space,H5P_DEFAULT,
731  dcpl,H5P_DEFAULT);
732  chunk_alloc=true;
733 
734  } else {
735 
736  // Get current dimensions
737  space=H5Dget_space(dset);
738  hsize_t dims[2];
739  int ndims=H5Sget_simple_extent_dims(space,dims,0);
740 
741  // Set error if this dataset is more than 1-dimensional
742  if (ndims!=2) {
743  O2SCL_ERR2("Tried to set a non-matrix dataset with a ",
744  "matrix in hdf_file::set_szt_arr2d_copy().",
746  }
747 
748  // If necessary, extend the dataset
749  if (r!=dims[0] || c!=dims[1]) {
750  hsize_t new_dims[2]={r,c};
751  int status3=H5Dset_extent(dset,new_dims);
752  }
753 
754  }
755 
756  // Write the data
757  int status;
758  status=H5Dwrite(dset,H5T_NATIVE_HSIZE,H5S_ALL,
759  H5S_ALL,H5P_DEFAULT,d);
760 
761  status=H5Dclose(dset);
762  status=H5Sclose(space);
763  if (chunk_alloc) {
764  status=H5Pclose(dcpl);
765  }
766 
767  // Free the C-style array
768  delete[] d;
769 
770  return 0;
771  }
772  //@}
773 
774  /// \name Tensor I/O functions
775  //@{
776  /** \brief Get a tensor from an HDF file
777 
778  This version does not require a full copy of the tensor.
779  */
780  int getd_ten(std::string name,
781  o2scl::tensor<std::vector<double>,std::vector<size_t> > &t);
782 
783  /** \brief Get a tensor from an HDF file
784 
785  This version requires a full copy of the tensor from the
786  HDF5 file into the \ref o2scl::tensor object.
787  */
788  template<class vec_t, class vec_size_t>
789  int getd_ten_copy(std::string name, o2scl::tensor<vec_t,vec_size_t> &t) {
790  o2scl::tensor<std::vector<double>,std::vector<size_t> > t2;
791  int ret=getd_ten(name,t2);
792  t=t2;
793  return ret;
794  }
795 
796  /** \brief Write a tensor to an HDF file
797 
798  You may overwrite a tensor already present in the
799  HDF file only if it has the same rank. This version
800  does not require a full copy of the tensor.
801  */
802  int setd_ten(std::string name,
803  const o2scl::tensor<std::vector<double>,
804  std::vector<size_t> > &t);
805 
806  /** \brief Write a tensor to an HDF file
807 
808  You may overwrite a tensor already present in the
809  HDF file only if it has the same rank. This version
810  requires a full copy of the tensor from the \ref o2scl::tensor
811  object into the HDF5 file.
812  */
813  template<class vec_t, class vec_size_t>
814  int setd_ten_copy(std::string name,
815  const o2scl::tensor<std::vector<double>,
816  std::vector<size_t> > &t) {
817  o2scl::tensor<std::vector<double>,std::vector<size_t> > t2;
818  t2=t;
819  int ret=getd_ten(name,t2);
820  return ret;
821  }
822  //@}
823 
824  /** \name Array get functions
825 
826  All of these functions assume that the
827  pointer allocated beforehand, and matches the size of the
828  array in the HDF file. If the specified object is not found,
829  the \o2 error handler will be called.
830  */
831  //@{
832  /** \brief Get a character array named \c name of size \c n
833 
834  \note The pointer \c c must be allocated beforehand to
835  hold \c n entries, and \c n must match the size of the
836  array in the HDF file.
837  */
838  int getc_arr(std::string name, size_t n, char *c);
839 
840  /** \brief Get a double array named \c name of size \c n
841 
842  \note The pointer \c d must be allocated beforehand to
843  hold \c n entries, and \c n must match the size of the
844  array in the HDF file.
845  */
846  int getd_arr(std::string name, size_t n, double *d);
847  int getd_arr(std::string name, size_t n, double *d, int &compr);
848 
849  /** \brief Get a float array named \c name of size \c n
850 
851  \note The pointer \c f must be allocated beforehand to
852  hold \c n entries, and \c n must match the size of the
853  array in the HDF file.
854  */
855  int getf_arr(std::string name, size_t n, float *f);
856 
857  /** \brief Get an integer array named \c name of size \c n
858 
859  \note The pointer \c i must be allocated beforehand to
860  hold \c n entries, and \c n must match the size of the
861  array in the HDF file.
862  */
863  int geti_arr(std::string name, size_t n, int *i);
864  //@}
865 
866  /** \name Array get functions with memory allocation
867 
868  These functions allocate memory with \c new, which
869  should be freed by the user with \c delete .
870  */
871  //@{
872  /// Get a character array named \c name of size \c n
873  int getc_arr_alloc(std::string name, size_t &n, char *c);
874 
875  /// Get a double array named \c name of size \c n
876  int getd_arr_alloc(std::string name, size_t &n, double *d);
877 
878  /// Get a float array named \c name of size \c n
879  int getf_arr_alloc(std::string name, size_t &n, float *f);
880 
881  /// Get an integer array named \c name of size \c n
882  int geti_arr_alloc(std::string name, size_t &n, int *i);
883  //@}
884 
885  /** \name Array set functions
886  */
887  //@{
888  /// Set a character array named \c name of size \c n to value \c c
889  int setc_arr(std::string name, size_t n, const char *c);
890 
891  /// Set a double array named \c name of size \c n to value \c d
892  int setd_arr(std::string name, size_t n, const double *d);
893 
894  /// Set a float array named \c name of size \c n to value \c f
895  int setf_arr(std::string name, size_t n, const float *f);
896 
897  /// Set a integer array named \c name of size \c n to value \c i
898  int seti_arr(std::string name, size_t n, const int *i);
899 
900  /// Set a integer array named \c name of size \c n to value \c i
901  int set_szt_arr(std::string name, size_t n, const size_t *u);
902  //@}
903 
904  /** \name Fixed-length array set functions
905 
906  If a dataset named \c name is already present, then the
907  user-specified array must not be longer than the array already
908  present in the HDF file.
909  */
910  //@{
911  /// Set a character array named \c name of size \c n to value \c c
912  int setc_arr_fixed(std::string name, size_t n, const char *c);
913 
914  /// Set a double array named \c name of size \c n to value \c d
915  int setd_arr_fixed(std::string name, size_t n, const double *c);
916 
917  /// Set a float array named \c name of size \c n to value \c f
918  int setf_arr_fixed(std::string name, size_t n, const float *f);
919 
920  /// Set an integer array named \c name of size \c n to value \c i
921  int seti_arr_fixed(std::string name, size_t n, const int *i);
922  //@}
923 
924  /** \name Get functions with default values
925 
926  If the requested dataset is not found in the HDF file,
927  the object is set to the specified default value
928  and the error handler is not called.
929  */
930  //@{
931  /// Get a character named \c name
932  int getc_def(std::string name, char def, char &c);
933 
934  /// Get a double named \c name
935  int getd_def(std::string name, double def, double &d);
936 
937  /// Get a float named \c name
938  int getf_def(std::string name, float def, float &f);
939 
940  /// Get a integer named \c name
941  int geti_def(std::string name, int def, int &i);
942 
943  /// Get a size_t named \c name
944  int get_szt_def(std::string name, size_t def, size_t &i);
945 
946  /// Get a string named \c name
947  int gets_def(std::string name, std::string def, std::string &s);
948 
949  /// Get a variable length string named \c name
950  int gets_var_def(std::string name, std::string def, std::string &s);
951  //@}
952 
953  /** \name Get functions with pre-allocated pointer
954  */
955  //@{
956  /// Get a double array \c d pre-allocated to have size \c n
957  int getd_vec_prealloc(std::string name, size_t n, double *d);
958 
959  /// Get an integer array \c i pre-allocated to have size \c n
960  int geti_vec_prealloc(std::string name, size_t n, int *i);
961 
962  /// Get a double matrix \c d pre-allocated to have size <tt>(n,m)</tt>
963  int getd_mat_prealloc(std::string name, size_t n, size_t m, double *d);
964 
965  /// Get an integer matrix \c i pre-allocated to have size <tt>(n,m)</tt>
966  int geti_mat_prealloc(std::string name, size_t n, size_t m, int *i);
967  //@}
968 
969  /// \name Find a group
970  //@{
971  /** \brief Look in hdf_file \c hf for an \o2 object of type \c
972  type and if found, set \c group_name to the associated object
973  name
974 
975  This function returns 0 if an object of type \c type is found
976  and \ref o2scl::exc_enoprog if it fails.
977  */
978  int find_group_by_type(std::string type,
979  std::string &group_name, int verbose=0);
980 
981  /** \brief Look in hdf_file \c hf for an \o2 object with name
982  \c name and if found, set \c type to the associated type
983 
984  This function returns 0 if an object with name \c name is
985  found and \ref o2scl::exc_enoprog if it fails.
986  */
987  int find_group_by_name(std::string name,
988  std::string &type, int verbose=0);
989  //@}
990 
991 #ifndef DOXYGEN_INTERNAL
992 
993  private:
994 
995  /*
996  In principle, one might be able to copy the IDs, but then we'd
997  have to worry about the possibility that the file would be
998  closed twice.
999  */
1000  hdf_file(const hdf_file &);
1001  hdf_file& operator=(const hdf_file&);
1002 
1003 #endif
1004 
1005  };
1006 
1007  /// \name Helper functions
1008  //@{
1009  /** \brief An internal structure to pass information to and
1010  from \ref iterate_match_type() and \ref iterate_match_name()
1011  */
1012  typedef struct {
1013  hdf_file *hf;
1014  std::string type;
1015  std::string group_name;
1016  bool found;
1017  int verbose;
1018  } iterate_parms;
1019 
1020  /** \brief Look at location \c loc in an HDF file for an \o2 object
1021  of a specified type
1022 
1023  This is used by \ref hdf_file::find_group_by_type() where \c
1024  op_data is a pointer to an object of type \ref iterate_parms to
1025  look for \o2 objects of a specified type without knowing the
1026  group name.
1027  */
1028  int iterate_match_type(hid_t loc, const char *name,
1029  const H5L_info_t *inf, void *op_data);
1030 
1031  /** \brief Look at location \c loc in an HDF file for an \o2 object
1032  with a specified name
1033 
1034  This is used by \ref hdf_file::find_group_by_name() where \c
1035  op_data is a pointer to an object of type \ref iterate_parms to
1036  look for \o2 objects with a specified name without knowing the
1037  type.
1038  */
1039  int iterate_match_name(hid_t loc, const char *name,
1040  const H5L_info_t *inf, void *op_data);
1041  //@}
1042 
1043 }
1044 
1045 #endif
int gets_var_def(std::string name, std::string def, std::string &s)
Get a variable length string named name.
int getf_arr_alloc(std::string name, size_t &n, float *f)
Get a float array named name of size n.
int seti_vec_copy(std::string name, vec_int_t &v)
Set vector dataset named name with v.
Definition: hdf_file.h:397
int getd_ten_copy(std::string name, o2scl::tensor< vec_t, vec_size_t > &t)
Get a tensor from an HDF file.
Definition: hdf_file.h:789
int seti_mat_copy(std::string name, const ubmatrix_int &m)
Set matrix dataset named name with m.
hid_t current
Current file or group location.
Definition: hdf_file.h:120
int getd_vec(std::string name, std::vector< double > &v)
Get vector dataset and place data in v.
int setd_mat_copy(std::string name, const ubmatrix &m)
Set matrix dataset named name with m.
int setd_vec_copy(std::string name, const vec_t &v)
Set vector dataset named name with v.
Definition: hdf_file.h:377
int setd_vec(std::string name, const std::vector< double > &v)
Set vector dataset named name with v.
int setd_arr(std::string name, size_t n, const double *d)
Set a double array named name of size n to value d.
int geti(std::string name, int &i)
Get a integer named name.
int getd_arr(std::string name, size_t n, double *d)
Get a double array named name of size n.
int set_szt_vec(std::string name, const std::vector< size_t > &v)
Set vector dataset named name with v.
int get_szt_def(std::string name, size_t def, size_t &i)
Get a size_t named name.
int find_group_by_name(std::string name, std::string &type, int verbose=0)
Look in hdf_file hf for an O<span style=&#39;position: relative; top: 0.3em; font-size: 0...
int set_szt_vec_copy(std::string name, const vec_size_t &v)
Set vector dataset named name with v.
Definition: hdf_file.h:416
int find_group_by_type(std::string type, std::string &group_name, int verbose=0)
Look in hdf_file hf for an O<span style=&#39;position: relative; top: 0.3em; font-size: 0...
int getf_arr(std::string name, size_t n, float *f)
Get a float array named name of size n.
void close()
Close the file.
void set_szt(std::string name, size_t u)
Set an unsigned integer named name to value u.
int getd(std::string name, double &d)
Get a double named name.
void setd(std::string name, double d)
Set a double named name to value d.
int gets_def(std::string name, std::string def, std::string &s)
Get a string named name.
bool file_open
True if a file has been opened.
Definition: hdf_file.h:117
int setf_arr(std::string name, size_t n, const float *f)
Set a float array named name of size n to value f.
int iterate_match_name(hid_t loc, const char *name, const H5L_info_t *inf, void *op_data)
Look at location loc in an HDF file for an O<span style=&#39;position: relative; top: 0...
int set_szt_arr(std::string name, size_t n, const size_t *u)
Set a integer array named name of size n to value i.
invalid argument supplied by user
Definition: err_hnd.h:59
int getd_ten(std::string name, o2scl::tensor< std::vector< double >, std::vector< size_t > > &t)
Get a tensor from an HDF file.
int getc_arr(std::string name, size_t n, char *c)
Get a character array named name of size n.
int getc_arr_alloc(std::string name, size_t &n, char *c)
Get a character array named name of size n.
void seti(std::string name, int i)
Set an integer named name to value i.
int setd_arr_fixed(std::string name, size_t n, const double *c)
Set a double array named name of size n to value d.
void sets_fixed(std::string name, std::string s)
Set a fixed-length string named name to value s.
int geti_vec_copy(std::string name, vec_int_t &v)
Get vector dataset and place data in v.
Definition: hdf_file.h:334
int geti_arr_alloc(std::string name, size_t &n, int *i)
Get an integer array named name of size n.
int sets_vec(std::string name, const std::vector< std::string > &s)
Set a vector of strings named name.
int geti_arr(std::string name, size_t n, int *i)
Get an integer array named name of size n.
int iterate_match_type(hid_t loc, const char *name, const H5L_info_t *inf, void *op_data)
Look at location loc in an HDF file for an O<span style=&#39;position: relative; top: 0...
int get_szt(std::string name, size_t &u)
Get an unsigned integer named name.
hid_t get_current_id()
Retrieve the current working id.
int getf_def(std::string name, float def, float &f)
Get a float named name.
generic failure
Definition: err_hnd.h:61
An internal structure to pass information to and from iterate_match_type() and iterate_match_name() ...
Definition: hdf_file.h:1012
int getd_vec_prealloc(std::string name, size_t n, double *d)
Get a double array d pre-allocated to have size n.
int geti_vec(std::string name, std::vector< int > &v)
Get vector dataset and place data in v.
void sets(std::string name, std::string s)
Set a string named name to value s.
int setd_ten_copy(std::string name, const o2scl::tensor< std::vector< double >, std::vector< size_t > > &t)
Write a tensor to an HDF file.
Definition: hdf_file.h:814
int close_group(hid_t group)
Close a previously created group.
Definition: hdf_file.h:289
int getf(std::string name, float &f)
Get a float named name.
int gets_fixed(std::string name, std::string &s)
Get a fixed-length string named name.
int setc_arr(std::string name, size_t n, const char *c)
Set a character array named name of size n to value c.
int geti_def(std::string name, int def, int &i)
Get a integer named name.
void vector_copy(const vec_t &src, vec2_t &dest)
Simple vector copy.
Definition: vector.h:127
void open_or_create(std::string fname)
Open a file named fname or create if it doesn&#39;t already exist.
int getd_mat_copy(std::string name, ubmatrix &m)
Get matrix dataset and place data in m.
int seti_vec(std::string name, const std::vector< int > &v)
Set vector dataset named name with v.
int setd_ten(std::string name, const o2scl::tensor< std::vector< double >, std::vector< size_t > > &t)
Write a tensor to an HDF file.
#define O2SCL_ERR2(d, d2, n)
Set an error, two-string version.
Definition: err_hnd.h:281
The O<span style=&#39;position: relative; top: 0.3em; font-size: 0.8em&#39;>2</span>scl O$_2$scl namespace ...
Definition: table.h:53
bool has_write_access()
If true, then the file has read and write access.
Definition: hdf_file.h:147
void set_current_id(hid_t cur)
Set the current working id.
int set_szt_arr2d_copy(std::string name, size_t r, size_t c, const arr2d_t &a2d)
Set a two-dimensional array dataset named name with m.
Definition: hdf_file.h:674
int geti_vec_prealloc(std::string name, size_t n, int *i)
Get an integer array i pre-allocated to have size n.
int getd_def(std::string name, double def, double &d)
Get a double named name.
int setf_arr_fixed(std::string name, size_t n, const float *f)
Set a float array named name of size n to value f.
int compr_type
Compression type (support experimental)
Definition: hdf_file.h:152
int geti_mat_prealloc(std::string name, size_t n, size_t m, int *i)
Get an integer matrix i pre-allocated to have size (n,m)
int gets_var(std::string name, std::string &s)
Get a variable length string named name.
int geti_mat_copy(std::string name, ubmatrix_int &m)
Get matrix dataset and place data in m.
int setd_arr2d_copy(std::string name, size_t r, size_t c, const arr2d_t &a2d)
Set a two-dimensional array dataset named name with m.
Definition: hdf_file.h:470
int getd_mat_prealloc(std::string name, size_t n, size_t m, double *d)
Get a double matrix d pre-allocated to have size (n,m)
hid_t file
File ID.
Definition: hdf_file.h:114
virtual hsize_t def_chunk(size_t n)
Default chunk size.
Definition: hdf_file.h:127
hid_t get_file_id()
Get the current file id.
Store data in an O<span style=&#39;position: relative; top: 0.3em; font-size: 0.8em&#39;>2</span>scl O$_2$sc...
Definition: hdf_file.h:100
int getc(std::string name, char &c)
Get a character named name.
int gets_vec(std::string name, std::vector< std::string > &s)
Get a vector of strings named name and store it in s.
int setc_arr_fixed(std::string name, size_t n, const char *c)
Set a character array named name of size n to value c.
void setc(std::string name, char c)
Set a character named name to value c.
int gets(std::string name, std::string &s)
Get a string named name.
size_t min_compr_size
Minimum size to compress by default.
Definition: hdf_file.h:155
int seti_arr_fixed(std::string name, size_t n, const int *i)
Set an integer array named name of size n to value i.
int getd_vec_copy(std::string name, vec_t &v)
Get vector dataset and place data in v.
Definition: hdf_file.h:318
int open(std::string fname, bool write_access=false, bool err_on_fail=true)
Open a file named fname.
int get_szt_vec_copy(std::string name, vec_size_t &v)
Get vector dataset and place data in v.
Definition: hdf_file.h:349
void setf(std::string name, float f)
Set a float named name to value f.
int gets_def_fixed(std::string name, std::string def, std::string &s)
Get a fixed-length string named name with default value s.
int seti_arr2d_copy(std::string name, size_t r, size_t c, const arr2d_t &a2d)
Set a two-dimensional array dataset named name with m.
Definition: hdf_file.h:572
bool write_access
If true, then the file has read and write access.
Definition: hdf_file.h:136
int get_szt_vec(std::string name, std::vector< size_t > &v)
Get vector dataset and place data in v.
int getd_arr_alloc(std::string name, size_t &n, double *d)
Get a double array named name of size n.
int seti_arr(std::string name, size_t n, const int *i)
Set a integer array named name of size n to value i.
Tensor class with arbitrary dimensions.
Definition: tensor.h:120
hid_t open_group(hid_t init_id, std::string path)
Open a group relative to the location specified in init_id.
int getc_def(std::string name, char def, char &c)
Get a character named name.

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).