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

vigra/random_forest_hdf5_impex.hxx VIGRA

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*       Copyright 2009 by Rahul Nair and  Ullrich Koethe               */
00004 /*                                                                      */
00005 /*    This file is part of the VIGRA computer vision library.           */
00006 /*    The VIGRA Website is                                              */
00007 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
00008 /*    Please direct questions, bug reports, and contributions to        */
00009 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
00010 /*        vigra@informatik.uni-hamburg.de                               */
00011 /*                                                                      */
00012 /*    Permission is hereby granted, free of charge, to any person       */
00013 /*    obtaining a copy of this software and associated documentation    */
00014 /*    files (the "Software"), to deal in the Software without           */
00015 /*    restriction, including without limitation the rights to use,      */
00016 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00017 /*    sell copies of the Software, and to permit persons to whom the    */
00018 /*    Software is furnished to do so, subject to the following          */
00019 /*    conditions:                                                       */
00020 /*                                                                      */
00021 /*    The above copyright notice and this permission notice shall be    */
00022 /*    included in all copies or substantial portions of the             */
00023 /*    Software.                                                         */
00024 /*                                                                      */
00025 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
00026 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
00027 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
00028 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
00029 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
00030 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
00031 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
00032 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
00033 /*                                                                      */
00034 /************************************************************************/
00035 
00036 #ifndef VIGRA_RANDOM_FOREST_IMPEX_HDF5_HXX
00037 #define VIGRA_RANDOM_FOREST_IMPEX_HDF5_HXX
00038 
00039 #include "config.hxx"
00040 #include "random_forest.hxx"
00041 #include "hdf5impex.hxx"
00042 #include <string>
00043 
00044 namespace vigra 
00045 {
00046 
00047 static const char *const rf_hdf5_options       = "_options";
00048 static const char *const rf_hdf5_ext_param     = "_ext_param";
00049 static const char *const rf_hdf5_labels        = "labels";
00050 static const char *const rf_hdf5_topology      = "topology";
00051 static const char *const rf_hdf5_parameters    = "parameters";
00052 static const char *const rf_hdf5_tree          = "Tree_";
00053 static const char *const rf_hdf5_version_group = ".";
00054 static const char *const rf_hdf5_version_tag   = "vigra_random_forest_version";
00055 static const double      rf_hdf5_version       =  0.1;
00056 
00057 namespace detail
00058 {
00059 
00060 VIGRA_EXPORT void options_import_HDF5(HDF5File &, RandomForestOptions &,
00061                                       const std::string &);
00062 
00063 VIGRA_EXPORT void options_export_HDF5(HDF5File &, const RandomForestOptions &,
00064                                       const std::string &);
00065 
00066 VIGRA_EXPORT void dt_import_HDF5(HDF5File &, detail::DecisionTree &,
00067                                  const std::string &);
00068 
00069 VIGRA_EXPORT void dt_export_HDF5(HDF5File &, const detail::DecisionTree &,
00070                                  const std::string &);
00071 
00072 template<class X>
00073 void rf_import_HDF5_to_map(HDF5File & h5context, X & param,
00074                            const char *const ignored_label = 0)
00075 {
00076     // read a map containing all the double fields
00077     typedef typename X::map_type map_type;
00078     typedef std::pair<typename map_type::iterator, bool> inserter_type;
00079     typedef typename map_type::value_type value_type;
00080     typedef typename map_type::mapped_type mapped_type;
00081 
00082     map_type serialized_param;
00083     bool ignored_seen = ignored_label == 0;
00084 
00085     std::vector<std::string> names = h5context.ls();
00086     std::vector<std::string>::const_iterator j;
00087     for (j = names.begin(); j != names.end(); ++j)
00088     {
00089         if (ignored_label && *j == ignored_label)
00090         {
00091             ignored_seen = true;
00092             continue;
00093         }
00094         // get sort of an iterator to a new empty array vector in the map ...
00095         inserter_type new_array
00096             = serialized_param.insert(value_type(*j, mapped_type()));
00097         // ... and read the data into that place.
00098         h5context.readAndResize(*j, (*(new_array.first)).second);
00099     }
00100     vigra_precondition(ignored_seen, "rf_import_HDF5_to_map(): "
00101                                                          "labels are missing.");
00102     param.make_from_map(serialized_param);
00103 }
00104 
00105 template<class T>
00106 void problemspec_import_HDF5(HDF5File & h5context, ProblemSpec<T> & param,
00107                              const std::string & name)
00108 {
00109     h5context.cd(name);
00110     rf_import_HDF5_to_map(h5context, param, rf_hdf5_labels);
00111     // load_class_labels
00112     ArrayVector<T> labels;
00113     h5context.readAndResize(rf_hdf5_labels, labels);
00114     param.classes_(labels.begin(), labels.end());
00115     h5context.cd_up();
00116 }
00117 
00118 template<class X>
00119 void rf_export_map_to_HDF5(HDF5File & h5context, const X & param)
00120 {
00121     typedef typename X::map_type map_type;
00122     map_type serialized_param;
00123     // get a map containing all the double fields
00124     param.make_map(serialized_param);
00125     typename map_type::const_iterator j;
00126     for (j = serialized_param.begin(); j != serialized_param.end(); ++j)
00127         h5context.write(j->first, j->second);
00128 }
00129 
00130 template<class T>
00131 void problemspec_export_HDF5(HDF5File & h5context, ProblemSpec<T> const & param,
00132                              const std::string & name)
00133 {
00134     h5context.cd_mk(name);
00135     rf_export_map_to_HDF5(h5context, param);
00136     h5context.write(rf_hdf5_labels, param.classes);
00137     h5context.cd_up();
00138 }
00139 
00140 struct padded_number_string_data;
00141 class VIGRA_EXPORT padded_number_string
00142 {
00143 private:
00144     padded_number_string_data* padded_number;
00145 protected:
00146     padded_number_string(const padded_number_string &);
00147     void operator=(const padded_number_string &);
00148 public:
00149     padded_number_string(int n);
00150     std::string operator()(int k) const;
00151     ~padded_number_string();
00152 };
00153 
00154 inline std::string get_cwd(HDF5File & h5context)
00155 {
00156     return h5context.get_absolute_path(h5context.pwd());
00157 }
00158 
00159 } // namespace detail
00160 
00161 /** \brief Save a random forest to an HDF5File object into a specified HDF5
00162            group.
00163     
00164     The random forest is saved as a set of HDF5 datasets, groups, and
00165     attributes below a certain HDF5 group (default: current group of the
00166     HDF5File object). No additional data should be stored in that group.
00167     
00168     \param rf        Random forest object to be exported
00169     \param h5context HDF5File object to use
00170     \param pathname  If empty or not supplied, save the random forest to the
00171                      current group of the HDF5File object. Otherwise, save to a
00172                      new-created group specified by the path name, which may
00173                      be either relative or absolute.
00174 */
00175 template<class T, class Tag>
00176 void rf_export_HDF5(const RandomForest<T, Tag> & rf,
00177                     HDF5File & h5context,
00178                     const std::string & pathname = "")
00179 {
00180     std::string cwd;
00181     if (pathname.size()) {
00182         cwd = detail::get_cwd(h5context);
00183         h5context.cd_mk(pathname);
00184     }
00185     // version attribute
00186     h5context.writeAttribute(rf_hdf5_version_group, rf_hdf5_version_tag,
00187                              rf_hdf5_version);
00188     // save serialized options
00189     detail::options_export_HDF5(h5context, rf.options(), rf_hdf5_options);
00190     // save external parameters
00191     detail::problemspec_export_HDF5(h5context, rf.ext_param(),
00192                                     rf_hdf5_ext_param);
00193     // save trees
00194     int tree_count = rf.options_.tree_count_;
00195     detail::padded_number_string tree_number(tree_count);
00196     for (int i = 0; i < tree_count; ++i)
00197         detail::dt_export_HDF5(h5context, rf.tree(i),
00198                                                  rf_hdf5_tree + tree_number(i));
00199 
00200     if (pathname.size())
00201         h5context.cd(cwd);
00202 }
00203 
00204 /** \brief Save a random forest to a named HDF5 file into a specified HDF5
00205            group.
00206     
00207     The random forest is saved as a set of HDF5 datasets, groups, and
00208     attributes below a certain HDF5 group (default: root). No additional data
00209     should be stored in that group.
00210     
00211     \param rf       Random forest object to be exported
00212     \param filename Name of an HDF5 file to open
00213     \param pathname If empty or not supplied, save the random forest to the
00214                     root group of the HDF5 file. Otherwise, save to a
00215                     new-created group specified by the path name (relative
00216                     to the root group).
00217 */
00218 template<class T, class Tag>
00219 void rf_export_HDF5(const RandomForest<T, Tag> & rf,
00220                     const std::string & filename, 
00221                     const std::string & pathname = "")
00222 {
00223     HDF5File h5context(filename , HDF5File::Open);
00224     rf_export_HDF5(rf, h5context, pathname);
00225 }
00226 
00227 /** \brief Read a random forest from an HDF5File object's specified group.
00228     
00229     The random forest is read from a certain HDF5 group (default: current group
00230     of the HDF5File object) as a set of HDF5 datasets, groups, and
00231     attributes. No additional data should be present in that group.
00232     
00233     \param rf        Random forest object to be imported
00234     \param h5context HDF5File object to use
00235     \param pathname  If empty or not supplied, read from the random forest
00236                      from the current group of the HDF5File object. Otherwise,
00237                      use the group specified by the path name, which may
00238                      be either relative or absolute.
00239 */
00240 template<class T, class Tag>
00241 bool rf_import_HDF5(RandomForest<T, Tag> & rf,
00242                     HDF5File & h5context,
00243                     const std::string & pathname = "")
00244 {
00245     std::string cwd;
00246     if (pathname.size()) {
00247         cwd = detail::get_cwd(h5context);
00248         h5context.cd(pathname);
00249     }
00250     // version attribute
00251     if (h5context.existsAttribute(rf_hdf5_version_group, rf_hdf5_version_tag))
00252     {
00253         double read_version;
00254         h5context.readAttribute(rf_hdf5_version_group, rf_hdf5_version_tag,
00255                                 read_version);
00256         vigra_precondition(read_version <= rf_hdf5_version,
00257                           "rf_import_HDF5(): unexpected file format version.");
00258     }
00259     // get serialized options
00260     detail::options_import_HDF5(h5context, rf.options_, rf_hdf5_options);
00261     // get external parameters
00262     detail::problemspec_import_HDF5(h5context, rf.ext_param_,
00263                                     rf_hdf5_ext_param);
00264     // get all groups in base path
00265     // no check for the rf_hdf5_tree prefix...
00266     std::vector<std::string> names = h5context.ls();
00267     std::vector<std::string>::const_iterator j;
00268     for (j = names.begin(); j != names.end(); ++j)
00269     {
00270         if ((*j->rbegin() == '/') && (*j->begin() != '_')) // skip the above
00271         {
00272             rf.trees_.push_back(detail::DecisionTree(rf.ext_param_));
00273             detail::dt_import_HDF5(h5context, rf.trees_.back(), *j);
00274         }
00275     }
00276     if (pathname.size())
00277         h5context.cd(cwd);
00278     return true;
00279 }
00280 
00281 /** \brief Read a random forest from a named HDF5 file's specified group.
00282     
00283     The random forest is read from a certain HDF5 group (default: root group
00284     of the HDF5 file) as a set of HDF5 datasets, groups, and attributes.
00285     No additional data should be present in that group.
00286     
00287     \param rf        Random forest object to be imported
00288     \param filename Name of an HDF5 file to open
00289     \param pathname  If empty or not supplied, read from the random forest
00290                      from the current group of the HDF5 file. Otherwise,
00291                      use the group specified by the path name, which may
00292                      be either relative or absolute.
00293 */
00294 template<class T, class Tag>
00295 bool rf_import_HDF5(RandomForest<T, Tag> & rf,
00296                     const std::string & filename, 
00297                     const std::string & pathname = "")
00298 {
00299     HDF5File h5context(filename, HDF5File::Open);
00300     return rf_import_HDF5(rf, h5context, pathname);
00301 }
00302 
00303 } // namespace vigra
00304 
00305 #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.8.0 (20 Sep 2011)