FLAME  devel
 All Classes Functions Variables Typedefs Enumerations Pages
h5loader.cpp
1 
2 #include <sstream>
3 
4 #include <H5Cpp.h>
5 
6 #include "flame/h5loader.h"
7 
8 // H5::Exception doesn't derive from std::exception
9 // so translate to some type which does.
10 // TODO: sub-class mixing H5::Exception and std::exception?
11 #define CATCH() catch(H5::Exception& he) { \
12  std::ostringstream strm; \
13  strm<<"H5 Error "<<he.getDetailMsg(); \
14  throw std::runtime_error(strm.str()); \
15  }
16 
17 struct H5Loader::Pvt {
18  H5::H5File file;
19  H5::Group group;
20 };
21 
22 
23 H5Loader::H5Loader() :pvt(new Pvt) {}
24 
25 H5Loader::H5Loader(const char *spec) :pvt(new Pvt)
26 {
27  open(spec);
28 }
29 
30 H5Loader::H5Loader(const std::string& spec) :pvt(new Pvt)
31 {
32  open(spec);
33 }
34 
35 H5Loader::~H5Loader()
36 {
37  try{
38  close();
39  } catch(std::runtime_error& e) {
40  std::cerr<<"H5Loader is ignoring exception in dtor : "<<e.what()<<"\n";
41  }
42  delete pvt;
43 }
44 
45 void H5Loader::open(const char *spec)
46 {
47  open(std::string(spec));
48 }
49 
50 void H5Loader::open(const std::string& spec)
51 {
52  close();
53  /* The provided spec may contain both file path and group(s)
54  * seperated by '/' which is ambigious as the file path
55  * may contain '/' as well...
56  * so do as h5ls does and strip off from the right hand side until
57  * and try to open while '/' remain.
58  */
59  size_t sep = spec.npos;
60 
61  while(true) {
62  sep = spec.find_last_of('/', sep-1);
63 
64  std::string fname(spec.substr(0, sep));
65 
66  try {
67  pvt->file.openFile(fname, H5F_ACC_RDONLY);
68  } catch(H5::FileIException& e) {
69  if(sep==spec.npos) {
70  // no more '/' so this is failure
71  throw std::runtime_error("Unable to open file");
72  }
73  continue; // keep trying
74  } CATCH()
75 
76  std::string group(spec.substr(sep+1));
77 
78  try {
79  pvt->group = pvt->file.openGroup(group);
80  } catch(H5::FileIException& e) {
81  throw std::runtime_error("Unable to open group");
82  } CATCH()
83 
84  return;
85  }
86 }
87 
88 void H5Loader::close()
89 {
90  try{
91  pvt->group.close();
92  pvt->file.close();
93  }CATCH()
94 }
95 
97 H5Loader::load(const char * setname)
98 {
99  H5::DataSet dset;
100  try{
101  dset = pvt->group.openDataSet(setname);
102  }catch(H5::GroupIException& e) {
103  throw std::runtime_error("H5 group does not exist");
104  }CATCH()
105 
106  try{
107  H5::DataSpace fspace(dset.getSpace());
108 
109  size_t N = fspace.getSimpleExtentNdims();
110  if(N>2)
111  throw std::runtime_error("Can't load > 2d as matrix");
112 
113  hsize_t fsize[2] = {1,1};
114  fspace.getSimpleExtentDims(fsize);
115 
116  H5::DataSpace mspace(2, fsize);
117 
118  matrix_t ret(fsize[0], fsize[1]);
119 
120  fspace.selectAll();
121  mspace.selectAll();
122 
123  matrix_t::array_type& storage(ret.data());
124  dset.read(&storage[0], H5::PredType::NATIVE_DOUBLE, mspace, fspace);
125 
126  return ret;
127  }CATCH()
128 }
129 
131 H5Loader::load(const std::string& set)
132 {
133  return load(set.c_str());
134 }
135 
136 void H5Loader::dontPrint()
137 {
138  try {
139  H5::Exception::dontPrint();
140  }CATCH()
141 }
H5Loader()
Construct w/o opening. Must call open()
Definition: h5loader.cpp:23
STL namespace.
boost::numeric::ublas::matrix< double, boost::numeric::ublas::row_major, boost::numeric::ublas::unbounded_array< double > > matrix_t
A 2d matrix.
Definition: h5loader.h:37
Helper to read 2d matricies.
Definition: h5loader.h:16