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