1 /*************************************************************************** 2 * Copyright (c) Wolf Vollprecht, Sylvain Corlay and Johan Mabille * 3 * Copyright (c) QuantStack * 4 * * 5 * Distributed under the terms of the BSD 3-Clause License. * 6 * * 7 * The full license is in the file LICENSE, distributed with this software. * 8 ****************************************************************************/ 9 10 #ifndef XTENSOR_IO_XHIGHFIVE_HPP 11 #define XTENSOR_IO_XHIGHFIVE_HPP 12 13 #include <iostream> 14 #include <string> 15 #include <vector> 16 17 #include <highfive/H5DataSet.hpp> 18 #include <highfive/H5File.hpp> 19 #include <highfive/H5Easy.hpp> 20 21 #include <xtensor/xarray.hpp> 22 #include <xtensor/xtensor.hpp> 23 24 #include "xtensor-io.hpp" 25 26 namespace xt 27 { 28 namespace extensions 29 { 30 /** 31 * Check if a path exists (is a Group or DataSet) in an open HDF5 file. 32 * 33 * @param file opened HighFive::File 34 * @param path path of the Group/DataSet 35 */ exist(const HighFive::File & file,const std::string & path)36 inline bool exist(const HighFive::File& file, const std::string& path) 37 { 38 return file.exist(path); 39 } 40 41 /** 42 * Recursively create groups in an open HDF5 file such that a DataSet can be created. 43 * For example if the path = "/path/to/dataset", this function will create the groups 44 * "/path" and "/path/to". 45 * 46 * @param file opened HighFive::File 47 * @param path path of the DataSet 48 */ create_group(HighFive::File & file,const std::string & path)49 inline void create_group(HighFive::File& file, const std::string& path) 50 { 51 file.createGroup(path); 52 } 53 54 /** 55 * Get the size of an existing DataSet in an open HDF5 file. 56 * 57 * @param file opened HighFive::File 58 * @param path path of the DataSet 59 * 60 * @return size the size of the HighFive::DataSet 61 */ size(const HighFive::File & file,const std::string & path)62 inline std::size_t size(const HighFive::File& file, const std::string& path) 63 { 64 return H5Easy::getSize(file, path); 65 } 66 67 /** 68 * Get the shape of an existing DataSet in an open HDF5 file. 69 * 70 * @param file opened HighFive::File 71 * @param path path of the DataSet 72 * 73 * @return shape the shape of the HighFive::DataSet 74 */ shape(const HighFive::File & file,const std::string & path)75 inline std::vector<std::size_t> shape(const HighFive::File& file, const std::string& path) 76 { 77 return H5Easy::getShape(file, path); 78 } 79 } 80 81 namespace detail 82 { highfive_file_mode(xt::file_mode mode)83 inline auto highfive_file_mode(xt::file_mode mode) 84 { 85 switch (mode) 86 { 87 case xt::file_mode::create: 88 return HighFive::File::Create; 89 case xt::file_mode::overwrite: 90 return HighFive::File::Overwrite; 91 case xt::file_mode::append: 92 return HighFive::File::ReadWrite; 93 case xt::file_mode::read: 94 return HighFive::File::ReadOnly; 95 default: 96 return HighFive::File::ReadOnly; 97 } 98 } 99 highfive_dump_mode(xt::dump_mode mode)100 inline auto highfive_dump_mode(xt::dump_mode mode) 101 { 102 switch (mode) 103 { 104 case xt::dump_mode::create: 105 return H5Easy::DumpMode::Create; 106 case xt::dump_mode::overwrite: 107 return H5Easy::DumpMode::Overwrite; 108 default: 109 return H5Easy::DumpMode::Create; 110 } 111 } 112 } 113 114 /** 115 * Write scalar/string to a new DataSet in an open HDF5 file. 116 * 117 * @param file opened HighFive::File (has to be writeable) 118 * @param path path of the DataSet 119 * @param data the data to write 120 * @param dmode DataSet-write mode (xt::dump_mode::create | xt::dump_mode::overwrite) 121 * 122 * @return dataset the newly created HighFive::DataSet (e.g. to add an attribute) 123 */ 124 template <class T> dump(HighFive::File & file,const std::string & path,const T & data,xt::dump_mode dmode=xt::dump_mode::create)125 inline HighFive::DataSet dump(HighFive::File& file, const std::string& path, const T& data, 126 xt::dump_mode dmode=xt::dump_mode::create) 127 { 128 return H5Easy::dump(file, path, data, detail::highfive_dump_mode(dmode)); 129 } 130 131 /** 132 * Write a scalar to a (new, extendible) DataSet in an open HDF5 file. 133 * 134 * @param file opened HighFive::File (has to be writeable) 135 * @param path path of the DataSet 136 * @param data the data to write 137 * @param idx the indices to which to write 138 * 139 * @return dataset the (newly created) HighFive::DataSet (e.g. to add an attribute) 140 */ 141 template <class T> dump(HighFive::File & file,const std::string & path,const T & data,const std::vector<std::size_t> & idx)142 inline HighFive::DataSet dump(HighFive::File& file, const std::string& path, const T& data, 143 const std::vector<std::size_t>& idx) 144 { 145 return H5Easy::dump(file, path, data, idx); 146 } 147 148 /** 149 * Load entry "{i,...}" from a DataSet in an open HDF5 file to a scalar. 150 * 151 * @param file opened HighFive::File (has to be writeable) 152 * @param idx the indices to load 153 * @param path path of the DataSet 154 * 155 * @return data the read data 156 */ 157 template <class T> load(const HighFive::File & file,const std::string & path,const std::vector<std::size_t> & idx)158 inline auto load(const HighFive::File& file, const std::string& path, const std::vector<std::size_t>& idx) 159 { 160 return H5Easy::load<T>(file, path, idx); 161 } 162 163 /** 164 * Load a DataSet in an open HDF5 file to an object (templated). 165 * 166 * @param file opened HighFive::File (has to be writeable) 167 * @param path path of the DataSet 168 * 169 * @return data the read data 170 */ 171 template <class T> load(const HighFive::File & file,const std::string & path)172 inline auto load(const HighFive::File& file, const std::string& path) 173 { 174 return H5Easy::load<T>(file, path); 175 } 176 177 /** 178 * Write field to a new DataSet in an HDF5 file. 179 * 180 * @param file opened HighFive::File (has to be writeable) 181 * @param path path of the DataSet 182 * @param data the data to write 183 * @param dmode DataSet-write mode (xt::dump_mode::create | xt::dump_mode::overwrite) 184 * 185 * @return dataset the newly created HighFive::DataSet (e.g. to add an attribute) 186 */ 187 template <class T> dump_hdf5(const std::string & fname,const std::string & path,const T & data,xt::file_mode fmode=xt::file_mode::create,xt::dump_mode dmode=xt::dump_mode::create)188 inline void dump_hdf5(const std::string& fname, const std::string& path, const T& data, 189 xt::file_mode fmode=xt::file_mode::create, 190 xt::dump_mode dmode=xt::dump_mode::create) 191 { 192 HighFive::File file(fname, detail::highfive_file_mode(fmode)); 193 194 xt::dump(file, path, data, dmode); 195 } 196 197 /** 198 * Load a DataSet in an open HDF5 file to an object (templated). 199 * 200 * @param file opened HighFive::File (has to be writeable) 201 * @param path path of the DataSet 202 * 203 * @return data the read data 204 */ 205 template <class T> load_hdf5(const std::string & fname,const std::string & path)206 inline auto load_hdf5(const std::string& fname, const std::string& path) 207 { 208 HighFive::File file(fname, detail::highfive_file_mode(xt::file_mode::read)); 209 210 return xt::load<T>(file, path); 211 } 212 } 213 214 #endif 215