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

vigra/random_forest_hdf5_impex.hxx |

    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.9.0 (Tue Nov 6 2012)