[ 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 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>
241 bool rf_import_HDF5(RandomForest<T, Tag> & rf,
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>
295 bool rf_import_HDF5(RandomForest<T, Tag> & rf,
296 const std::string & filename,
297 const std::string & pathname = "")
298 {
299 HDF5File h5context(filename, HDF5File::OpenReadOnly);
300 return rf_import_HDF5(rf, h5context, pathname);
301 }
302
303 } // namespace vigra
304
305 #endif // VIGRA_RANDOM_FOREST_HDF5_IMPEX_HXX

© 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.10.0 (Mon Nov 18 2013)