[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

random_forest_hdf5_impex.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2009 by Rahul Nair and Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 #ifndef VIGRA_RANDOM_FOREST_IMPEX_HDF5_HXX
37 #define VIGRA_RANDOM_FOREST_IMPEX_HDF5_HXX
38 
39 #include "config.hxx"
40 #include "random_forest.hxx"
41 #include "hdf5impex.hxx"
42 #include <string>
43 
44 namespace vigra
45 {
46 
47 static const char *const rf_hdf5_options = "_options";
48 static const char *const rf_hdf5_ext_param = "_ext_param";
49 static const char *const rf_hdf5_labels = "labels";
50 static const char *const rf_hdf5_topology = "topology";
51 static const char *const rf_hdf5_parameters = "parameters";
52 static const char *const rf_hdf5_tree = "Tree_";
53 static const char *const rf_hdf5_version_group = ".";
54 static const char *const rf_hdf5_version_tag = "vigra_random_forest_version";
55 static const double rf_hdf5_version = 0.1;
56 
57 namespace detail
58 {
59 
60 VIGRA_EXPORT void options_import_HDF5(HDF5File &, RandomForestOptions &,
61  const std::string &);
62 
63 VIGRA_EXPORT void options_export_HDF5(HDF5File &, const RandomForestOptions &,
64  const std::string &);
65 
66 VIGRA_EXPORT void dt_import_HDF5(HDF5File &, detail::DecisionTree &,
67  const std::string &);
68 
69 VIGRA_EXPORT void dt_export_HDF5(HDF5File &, const detail::DecisionTree &,
70  const std::string &);
71 
72 template<class X>
73 void rf_import_HDF5_to_map(HDF5File & h5context, X & param,
74  const char *const ignored_label = 0)
75 {
76  // read a map containing all the double fields
77  typedef typename X::map_type map_type;
78  typedef std::pair<typename map_type::iterator, bool> inserter_type;
79  typedef typename map_type::value_type value_type;
80  typedef typename map_type::mapped_type mapped_type;
81 
82  map_type serialized_param;
83  bool ignored_seen = ignored_label == 0;
84 
85  std::vector<std::string> names = h5context.ls();
86  std::vector<std::string>::const_iterator j;
87  for (j = names.begin(); j != names.end(); ++j)
88  {
89  if (ignored_label && *j == ignored_label)
90  {
91  ignored_seen = true;
92  continue;
93  }
94  // get sort of an iterator to a new empty array vector in the map ...
95  inserter_type new_array
96  = serialized_param.insert(value_type(*j, mapped_type()));
97  // ... and read the data into that place.
98  h5context.readAndResize(*j, (*(new_array.first)).second);
99  }
100  vigra_precondition(ignored_seen, "rf_import_HDF5_to_map(): "
101  "labels are missing.");
102  param.make_from_map(serialized_param);
103 }
104 
105 template<class T>
106 void problemspec_import_HDF5(HDF5File & h5context, ProblemSpec<T> & param,
107  const std::string & name)
108 {
109  h5context.cd(name);
110  rf_import_HDF5_to_map(h5context, param, rf_hdf5_labels);
111  // load_class_labels
112  ArrayVector<T> labels;
113  h5context.readAndResize(rf_hdf5_labels, labels);
114  param.classes_(labels.begin(), labels.end());
115  h5context.cd_up();
116 }
117 
118 template<class X>
119 void rf_export_map_to_HDF5(HDF5File & h5context, const X & param)
120 {
121  typedef typename X::map_type map_type;
122  map_type serialized_param;
123  // get a map containing all the double fields
124  param.make_map(serialized_param);
125  typename map_type::const_iterator j;
126  for (j = serialized_param.begin(); j != serialized_param.end(); ++j)
127  h5context.write(j->first, j->second);
128 }
129 
130 template<class T>
131 void problemspec_export_HDF5(HDF5File & h5context, ProblemSpec<T> const & param,
132  const std::string & name)
133 {
134  h5context.cd_mk(name);
135  rf_export_map_to_HDF5(h5context, param);
136  h5context.write(rf_hdf5_labels, param.classes);
137  h5context.cd_up();
138 }
139 
140 struct padded_number_string_data;
141 class VIGRA_EXPORT padded_number_string
142 {
143 private:
144  padded_number_string_data* padded_number;
145 protected:
146  padded_number_string(const padded_number_string &);
147  void operator=(const padded_number_string &);
148 public:
149  padded_number_string(int n);
150  std::string operator()(int k) const;
151  ~padded_number_string();
152 };
153 
154 inline std::string get_cwd(HDF5File & h5context)
155 {
156  return h5context.get_absolute_path(h5context.pwd());
157 }
158 
159 } // namespace detail
160 
161 /** \brief Save a random forest to an HDF5File object into a specified HDF5
162  group.
163 
164  The random forest is saved as a set of HDF5 datasets, groups, and
165  attributes below a certain HDF5 group (default: current group of the
166  HDF5File object). No additional data should be stored in that group.
167 
168  \param rf Random forest object to be exported
169  \param h5context HDF5File object to use
170  \param pathname If empty or not supplied, save the random forest to the
171  current group of the HDF5File object. Otherwise, save to a
172  new-created group specified by the path name, which may
173  be either relative or absolute.
174 */
175 template<class T, class Tag>
177  HDF5File & h5context,
178  const std::string & pathname = "")
179 {
180  std::string cwd;
181  if (pathname.size()) {
182  cwd = detail::get_cwd(h5context);
183  h5context.cd_mk(pathname);
184  }
185  // version attribute
186  h5context.writeAttribute(rf_hdf5_version_group, rf_hdf5_version_tag,
187  rf_hdf5_version);
188  // save serialized options
189  detail::options_export_HDF5(h5context, rf.options(), rf_hdf5_options);
190  // save external parameters
191  detail::problemspec_export_HDF5(h5context, rf.ext_param(),
192  rf_hdf5_ext_param);
193  // save trees
194  int tree_count = rf.options_.tree_count_;
195  detail::padded_number_string tree_number(tree_count);
196  for (int i = 0; i < tree_count; ++i)
197  detail::dt_export_HDF5(h5context, rf.tree(i),
198  rf_hdf5_tree + tree_number(i));
199 
200  if (pathname.size())
201  h5context.cd(cwd);
202 }
203 
204 /** \brief Save a random forest to a named HDF5 file into a specified HDF5
205  group.
206 
207  The random forest is saved as a set of HDF5 datasets, groups, and
208  attributes below a certain HDF5 group (default: root). No additional data
209  should be stored in that group.
210 
211  \param rf Random forest object to be exported
212  \param filename Name of an HDF5 file to open
213  \param pathname If empty or not supplied, save the random forest to the
214  root group of the HDF5 file. Otherwise, save to a
215  new-created group specified by the path name (relative
216  to the root group).
217 */
218 template<class T, class Tag>
220  const std::string & filename,
221  const std::string & pathname = "")
222 {
223  HDF5File h5context(filename , HDF5File::Open);
224  rf_export_HDF5(rf, h5context, pathname);
225 }
226 
227 /** \brief Save a random forest to an HDF5 file specified by its id
228 
229  The random forest is saved as a set of HDF5 datasets, groups, and
230  attributes below a certain HDF5 group (default: root). No additional data
231  should be stored in that group.
232 
233  \warning In case the underlying HDF5 library used by Vigra is not
234  exactly the same library used to open the file with the given id, this
235  method will lead to crashes.
236 
237  \param rf Random forest object to be exported
238  \param outf_id HDF5 file id
239  \param pathname If empty or not supplied, save the random forest to the
240  root group of the HDF5 file. Otherwise, save to a
241  new-created group specified by the path name (relative
242  to the root group).
243 */
244 template<class T, class Tag>
246  hid_t outf_id,
247  const std::string & pathname = "")
248 {
249  HDF5HandleShared fileHandle(outf_id, NULL, "");
250  HDF5File h5context(fileHandle, pathname);
251  rf_export_HDF5(rf, h5context);
252 }
253 
254 /** \brief Read a random forest from an HDF5File object's specified group.
255 
256  The random forest is read from a certain HDF5 group (default: current group
257  of the HDF5File object) as a set of HDF5 datasets, groups, and
258  attributes. No additional data should be present in that group.
259 
260  \param rf Random forest object to be imported
261  \param h5context HDF5File object to use
262  \param pathname If empty or not supplied, read from the random forest
263  from the current group of the HDF5File object. Otherwise,
264  use the group specified by the path name, which may
265  be either relative or absolute.
266 */
267 template<class T, class Tag>
269  HDF5File & h5context,
270  const std::string & pathname = "")
271 {
272  std::string cwd;
273  if (pathname.size()) {
274  cwd = detail::get_cwd(h5context);
275  h5context.cd(pathname);
276  }
277  // version attribute
278  if (h5context.existsAttribute(rf_hdf5_version_group, rf_hdf5_version_tag))
279  {
280  double read_version;
281  h5context.readAttribute(rf_hdf5_version_group, rf_hdf5_version_tag,
282  read_version);
283  vigra_precondition(read_version <= rf_hdf5_version,
284  "rf_import_HDF5(): unexpected file format version.");
285  }
286  // get serialized options
287  detail::options_import_HDF5(h5context, rf.options_, rf_hdf5_options);
288  // get external parameters
289  detail::problemspec_import_HDF5(h5context, rf.ext_param_,
290  rf_hdf5_ext_param);
291  rf.trees_.clear();
292  // get all groups in base path
293  // no check for the rf_hdf5_tree prefix...
294  std::vector<std::string> names = h5context.ls();
295  std::vector<std::string>::const_iterator j;
296  for (j = names.begin(); j != names.end(); ++j)
297  {
298  if ((*j->rbegin() == '/') && (*j->begin() != '_')) // skip the above
299  {
300  rf.trees_.push_back(detail::DecisionTree(rf.ext_param_));
301  detail::dt_import_HDF5(h5context, rf.trees_.back(), *j);
302  }
303  }
304  if (pathname.size())
305  h5context.cd(cwd);
306  return true;
307 }
308 
309 /** \brief Read a random forest from a named HDF5 file's specified group.
310 
311  The random forest is read from a certain HDF5 group (default: root group
312  of the HDF5 file) as a set of HDF5 datasets, groups, and attributes.
313  No additional data should be present in that group.
314 
315  \param rf Random forest object to be imported
316  \param filename Name of an HDF5 file to open
317  \param pathname If empty or not supplied, read from the random forest
318  from the current group of the HDF5 file. Otherwise,
319  use the group specified by the path name, which may
320  be either relative or absolute.
321 */
322 template<class T, class Tag>
324  const std::string & filename,
325  const std::string & pathname = "")
326 {
327  HDF5File h5context(filename, HDF5File::OpenReadOnly);
328  return rf_import_HDF5(rf, h5context, pathname);
329 }
330 
331 /** \brief Read a random forest from an HDF5 file specified by its id.
332 
333  The random forest is read from a certain HDF5 group (default: root group
334  of the HDF5 file) as a set of HDF5 datasets, groups, and attributes.
335  No additional data should be present in that group.
336 
337  \warning In case the underlying HDF5 library used by Vigra is not
338  exactly the same library used to open the file with the given id, this
339  method will lead to crashes.
340 
341  \param rf Random forest object to be imported
342  \param inf_id HDF5 file id
343  \param pathname If empty or not supplied, read from the random forest
344  from the current group of the HDF5 file. Otherwise,
345  use the group specified by the path name, which may
346  be either relative or absolute.
347 */
348 template<class T, class Tag>
350  hid_t inf_id,
351  const std::string & pathname = "")
352 {
353  HDF5HandleShared fileHandle(inf_id, NULL, "");
354  HDF5File h5context(fileHandle, pathname, true);
355  return rf_import_HDF5(rf, h5context);
356 }
357 
358 } // namespace vigra
359 
360 #endif // VIGRA_RANDOM_FOREST_HDF5_IMPEX_HXX
reference back()
Definition: array_vector.hxx:321
void readAttribute(std::string object_name, std::string attribute_name, MultiArrayView< N, T, Stride > array)
Read MultiArray Attributes. In contrast to datasets, subarray access is not available.
Definition: hdf5impex.hxx:1698
void cd_mk(std::string groupName)
Change the current group; create it if necessary. If the first character is a "/", the path will be interpreted as absolute path, otherwise it will be interpreted as path relative to the current group.
Definition: hdf5impex.hxx:1285
bool existsAttribute(std::string object_name, std::string attribute_name)
Test if attribute exists.
Definition: hdf5impex.hxx:1681
ProblemSpec_t const & ext_param() const
return external parameters for viewing
Definition: random_forest.hxx:260
DecisionTree_t const & tree(int index) const
access const trees
Definition: random_forest.hxx:308
Wrapper for shared hid_t objects.
Definition: hdf5impex.hxx:431
Random forest version 2 (see also vigra::rf3::RandomForest for version 3)
Definition: random_forest.hxx:147
Options_t const & options() const
access const random forest options
Definition: random_forest.hxx:301
void rf_export_HDF5(const RandomForest< T, Tag > &rf, HDF5File &h5context, const std::string &pathname="")
Save a random forest to an HDF5File object into a specified HDF5 group.
Definition: random_forest_hdf5_impex.hxx:176
void writeAttribute(std::string object_name, std::string attribute_name, const MultiArrayView< N, T, Stride > &array)
Write MultiArray Attributes. In contrast to datasets, subarray access, chunks and compression are not...
Definition: hdf5impex.hxx:1611
bool rf_import_HDF5(RandomForest< T, Tag > &rf, HDF5File &h5context, const std::string &pathname="")
Read a random forest from an HDF5File object's specified group.
Definition: random_forest_hdf5_impex.hxx:268
void cd(std::string groupName)
Change the current group. Both absolute and relative group names are allowed.
Definition: hdf5impex.hxx:1216
Access to HDF5 files.
Definition: hdf5impex.hxx:974
std::vector< std::string > ls() const
List the contents of the current group. The function returns a vector of strings holding the entries ...
Definition: hdf5impex.hxx:1310

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.11.1 (Fri May 19 2017)