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

random_forest_hdf5_impex.hxx
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 Read a random forest from an HDF5File object's specified group.
228 
229  The random forest is read from a certain HDF5 group (default: current group
230  of the HDF5File object) as a set of HDF5 datasets, groups, and
231  attributes. No additional data should be present in that group.
232 
233  \param rf Random forest object to be imported
234  \param h5context HDF5File object to use
235  \param pathname If empty or not supplied, read from the random forest
236  from the current group of the HDF5File object. Otherwise,
237  use the group specified by the path name, which may
238  be either relative or absolute.
239 */
240 template<class T, class Tag>
242  HDF5File & h5context,
243  const std::string & pathname = "")
244 {
245  std::string cwd;
246  if (pathname.size()) {
247  cwd = detail::get_cwd(h5context);
248  h5context.cd(pathname);
249  }
250  // version attribute
251  if (h5context.existsAttribute(rf_hdf5_version_group, rf_hdf5_version_tag))
252  {
253  double read_version;
254  h5context.readAttribute(rf_hdf5_version_group, rf_hdf5_version_tag,
255  read_version);
256  vigra_precondition(read_version <= rf_hdf5_version,
257  "rf_import_HDF5(): unexpected file format version.");
258  }
259  // get serialized options
260  detail::options_import_HDF5(h5context, rf.options_, rf_hdf5_options);
261  // get external parameters
262  detail::problemspec_import_HDF5(h5context, rf.ext_param_,
263  rf_hdf5_ext_param);
264  // get all groups in base path
265  // no check for the rf_hdf5_tree prefix...
266  std::vector<std::string> names = h5context.ls();
267  std::vector<std::string>::const_iterator j;
268  for (j = names.begin(); j != names.end(); ++j)
269  {
270  if ((*j->rbegin() == '/') && (*j->begin() != '_')) // skip the above
271  {
272  rf.trees_.push_back(detail::DecisionTree(rf.ext_param_));
273  detail::dt_import_HDF5(h5context, rf.trees_.back(), *j);
274  }
275  }
276  if (pathname.size())
277  h5context.cd(cwd);
278  return true;
279 }
280 
281 /** \brief Read a random forest from a named HDF5 file's specified group.
282 
283  The random forest is read from a certain HDF5 group (default: root group
284  of the HDF5 file) as a set of HDF5 datasets, groups, and attributes.
285  No additional data should be present in that group.
286 
287  \param rf Random forest object to be imported
288  \param filename Name of an HDF5 file to open
289  \param pathname If empty or not supplied, read from the random forest
290  from the current group of the HDF5 file. Otherwise,
291  use the group specified by the path name, which may
292  be either relative or absolute.
293 */
294 template<class T, class Tag>
296  const std::string & filename,
297  const std::string & pathname = "")
298 {
299  HDF5File h5context(filename, HDF5File::Open);
300  return rf_import_HDF5(rf, h5context, pathname);
301 }
302 
303 } // namespace vigra
304 
305 #endif // VIGRA_RANDOM_FOREST_HDF5_IMPEX_HXX
reference back()
Definition: array_vector.hxx:293
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:724
bool existsAttribute(std::string object_name, std::string attribute_name)
Test if attribute exists.
Definition: hdf5impex.hxx:949
ProblemSpec_t const & ext_param() const
return external parameters for viewing
Definition: random_forest.hxx:262
DecisionTree_t const & tree(int index) const
access const trees
Definition: random_forest.hxx:309
Definition: random_forest.hxx:143
Options_t const & options() const
access const random forest options
Definition: random_forest.hxx:302
void writeAttribute(std::string object_name, std::string attribute_name, const MultiArrayView< N, T, UnstridedArrayTag > &array)
Write MultiArray Attributes. In contrast to datasets, subarray access, chunks and compression are not...
Definition: hdf5impex.hxx:885
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
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:241
void cd(std::string groupName)
Change the current group. Both absolute and relative group names are allowed.
Definition: hdf5impex.hxx:645
Access to HDF5 files.
Definition: hdf5impex.hxx:513
void readAttribute(std::string object_name, std::string attribute_name, const MultiArrayView< N, T, UnstridedArrayTag > &array)
Read MultiArray Attributes. In contrast to datasets, subarray access is not available.
Definition: hdf5impex.hxx:966
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:746

© 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.9.0 (Sun Aug 10 2014)