vigra - vigra/random_forest_hdf5_impex.hxx Source File

[ 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>
176 void rf_export_HDF5(const RandomForest<T, Tag> & rf,
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>
219 void rf_export_HDF5(const RandomForest<T, Tag> & rf,
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>
245 void rf_export_HDF5(const RandomForest<T, Tag> & rf,
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>
268 bool rf_import_HDF5(RandomForest<T, Tag> & rf,
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>
323 bool rf_import_HDF5(RandomForest<T, Tag> & rf,
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>
349 bool rf_import_HDF5(RandomForest<T, Tag> & rf,
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
vigra::ArrayVectorView::back
reference back()
Definition: array_vector.hxx:321
vigra::HDF5File::readAttribute
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:1637
vigra::HDF5File::cd_mk
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:1262
vigra::HDF5File::existsAttribute
bool existsAttribute(std::string object_name, std::string attribute_name)
Test if attribute exists.
Definition: hdf5impex.hxx:1620
vigra::RandomForest::ext_param
ProblemSpec_t const & ext_param() const
return external parameters for viewing
Definition: random_forest.hxx:257
vigra::RandomForest::tree
DecisionTree_t const & tree(int index) const
access const trees
Definition: random_forest.hxx:305
vigra::HDF5HandleShared
Wrapper for shared hid_t objects.
Definition: hdf5impex.hxx:412
vigra::RandomForest
Definition: random_forest.hxx:145
vigra::RandomForest::options
Options_t const & options() const
access const random forest options
Definition: random_forest.hxx:298
vigra::rf_export_HDF5
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
vigra::HDF5File::writeAttribute
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:1550
vigra::rf_import_HDF5
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
vigra::HDF5File::cd
void cd(std::string groupName)
Change the current group. Both absolute and relative group names are allowed.
Definition: hdf5impex.hxx:1193
vigra::HDF5File
Access to HDF5 files.
Definition: hdf5impex.hxx:958
vigra::HDF5File::ls
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:1287

© 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.0 (Thu Mar 17 2016)