HDF5 boost multi array transparent support
This commit is contained in:
parent
1d59f4e93d
commit
47255ea25a
@ -34,6 +34,9 @@ target_link_libraries(testPool ${tolink})
|
|||||||
if (HDF5_FOUND)
|
if (HDF5_FOUND)
|
||||||
add_executable(testReadFlash testReadFlash.cpp)
|
add_executable(testReadFlash testReadFlash.cpp)
|
||||||
target_link_libraries(testReadFlash ${tolink})
|
target_link_libraries(testReadFlash ${tolink})
|
||||||
|
|
||||||
|
add_executable(testHDF5 testHDF5.cpp)
|
||||||
|
target_link_libraries(testHDF5 ${tolink})
|
||||||
endif (HDF5_FOUND)
|
endif (HDF5_FOUND)
|
||||||
|
|
||||||
|
|
||||||
|
65
sample/testHDF5.cpp
Normal file
65
sample/testHDF5.cpp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <H5Cpp.h>
|
||||||
|
#include "hdf5_array.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
typedef boost::multi_array<float, 2> array_type;
|
||||||
|
typedef boost::multi_array<float, 3> array3_type;
|
||||||
|
typedef boost::multi_array<std::complex<double>, 2> arrayc_type;
|
||||||
|
typedef array_type::index index;
|
||||||
|
|
||||||
|
H5::H5File f("test.h5", H5F_ACC_TRUNC);
|
||||||
|
|
||||||
|
H5::Group g = f.createGroup("test_group");
|
||||||
|
|
||||||
|
array_type A(boost::extents[2][3]);
|
||||||
|
array_type B;
|
||||||
|
array3_type C(boost::extents[2][3][4]);
|
||||||
|
arrayc_type D, E;
|
||||||
|
|
||||||
|
int values = 0;
|
||||||
|
for (index i = 0; i != 2; i++)
|
||||||
|
for (index j = 0; j != 3; j++)
|
||||||
|
A[i][j] = values++;
|
||||||
|
|
||||||
|
CosmoTool::hdf5_write_array(g, "test_data", A);
|
||||||
|
|
||||||
|
CosmoTool::hdf5_read_array(g, "test_data", B);
|
||||||
|
|
||||||
|
int verify = 0;
|
||||||
|
for (index i = 0; i != 2; i++)
|
||||||
|
for (index j = 0; j != 3; j++)
|
||||||
|
if (B[i][j] != verify++) {
|
||||||
|
std::cout << "Invalid array content" << endl;
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CosmoTool::hdf5_read_array(g, "test_data", C);
|
||||||
|
std::cout << "Did not throw InvalidDimensions" << endl;
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
catch (const CosmoTool::InvalidDimensions&)
|
||||||
|
{}
|
||||||
|
|
||||||
|
D.resize(boost::extents[2][3]);
|
||||||
|
D = A;
|
||||||
|
|
||||||
|
CosmoTool::hdf5_write_array(g, "test_data_c", D);
|
||||||
|
|
||||||
|
CosmoTool::hdf5_read_array(g, "test_data_c", E);
|
||||||
|
|
||||||
|
verify = 0;
|
||||||
|
for (index i = 0; i != 2; i++)
|
||||||
|
for (index j = 0; j != 3; j++)
|
||||||
|
if (E[i][j].real() != verify++) {
|
||||||
|
std::cout << "Invalid array content" << endl;
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
175
src/hdf5_array.hpp
Normal file
175
src/hdf5_array.hpp
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
#ifndef __COSMO_HDF5_ARRAY_HPP
|
||||||
|
#define __COSMO_HDF5_ARRAY_HPP
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <boost/static_assert.hpp>
|
||||||
|
#include <boost/utility.hpp>
|
||||||
|
#include <boost/mpl/assert.hpp>
|
||||||
|
#include <boost/multi_array.hpp>
|
||||||
|
#include <boost/type_traits/is_same.hpp>
|
||||||
|
#include <boost/type_traits/is_floating_point.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <H5Cpp.h>
|
||||||
|
|
||||||
|
namespace CosmoTool {
|
||||||
|
|
||||||
|
//!_______________________________________________________________________________________
|
||||||
|
//!
|
||||||
|
//! map types to HDF5 types
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! Leo Goodstadt (04 March 2013), improved with enable_if by Guilhem Lavaux (May 2014)
|
||||||
|
//!_______________________________________________________________________________________
|
||||||
|
|
||||||
|
template<typename T, class Enable = void> struct get_hdf5_data_type
|
||||||
|
{
|
||||||
|
static H5::PredType type()
|
||||||
|
{
|
||||||
|
BOOST_MPL_ASSERT_MSG(0, Unknown_HDF5_data_type, ());
|
||||||
|
return H5::PredType::NATIVE_DOUBLE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define HDF5_TYPE(tl, thdf5) \
|
||||||
|
template<typename T> struct get_hdf5_data_type<T, typename boost::enable_if<boost::is_same<T, tl> >::type> \
|
||||||
|
{ static H5::PredType type() { return H5::PredType::thdf5; }; }
|
||||||
|
|
||||||
|
HDF5_TYPE(char , NATIVE_CHAR);
|
||||||
|
HDF5_TYPE(long long , NATIVE_LLONG);
|
||||||
|
HDF5_TYPE(unsigned long long, NATIVE_ULLONG);
|
||||||
|
HDF5_TYPE(int8_t , NATIVE_INT8);
|
||||||
|
HDF5_TYPE(uint8_t , NATIVE_UINT8);
|
||||||
|
HDF5_TYPE(int16_t , NATIVE_INT16);
|
||||||
|
HDF5_TYPE(uint16_t , NATIVE_UINT16);
|
||||||
|
HDF5_TYPE(int32_t , NATIVE_INT32);
|
||||||
|
HDF5_TYPE(uint32_t , NATIVE_UINT32);
|
||||||
|
HDF5_TYPE(int64_t , NATIVE_INT64);
|
||||||
|
HDF5_TYPE(uint64_t , NATIVE_UINT64);
|
||||||
|
HDF5_TYPE(float , NATIVE_FLOAT);
|
||||||
|
HDF5_TYPE(double , NATIVE_DOUBLE);
|
||||||
|
HDF5_TYPE(long double , NATIVE_LDOUBLE);
|
||||||
|
|
||||||
|
#undef HDF5_TYPE
|
||||||
|
|
||||||
|
//!_______________________________________________________________________________________
|
||||||
|
//!
|
||||||
|
//! write_hdf5 multi_array
|
||||||
|
//!
|
||||||
|
//! \author leo Goodstadt (04 March 2013)
|
||||||
|
//!
|
||||||
|
//!_______________________________________________________________________________________
|
||||||
|
template<typename T, std::size_t DIMENSIONS, typename hdf5_data_type>
|
||||||
|
void hdf5_write_array(H5::CommonFG& fg, const std::string& data_set_name,
|
||||||
|
const boost::multi_array<T, DIMENSIONS>& data,
|
||||||
|
const hdf5_data_type& datatype)
|
||||||
|
{
|
||||||
|
std::vector<hsize_t> dimensions(data.shape(), data.shape() + DIMENSIONS);
|
||||||
|
H5::DataSpace dataspace(DIMENSIONS, dimensions.data());
|
||||||
|
|
||||||
|
H5::DataSet dataset = fg.createDataSet(data_set_name, datatype, dataspace);
|
||||||
|
|
||||||
|
dataset.write(data.data(), datatype);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HDF5 complex type */
|
||||||
|
template<typename T>
|
||||||
|
class hdf5_ComplexType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
H5::CompType type;
|
||||||
|
|
||||||
|
hdf5_ComplexType()
|
||||||
|
: type(sizeof(std::complex<T>))
|
||||||
|
{
|
||||||
|
get_hdf5_data_type<T> hdf_data_type;
|
||||||
|
type.insertMember("r", 0, hdf_data_type.type());
|
||||||
|
type.insertMember("i", sizeof(T), hdf_data_type.type());
|
||||||
|
type.pack();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const hdf5_ComplexType<T> *ctype()
|
||||||
|
{
|
||||||
|
static hdf5_ComplexType<T> singleton;
|
||||||
|
|
||||||
|
return &singleton;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, std::size_t DIMENSIONS>
|
||||||
|
void hdf5_write_array(H5::CommonFG& fg, const std::string& data_set_name, const boost::multi_array<T, DIMENSIONS>& data )
|
||||||
|
{
|
||||||
|
get_hdf5_data_type<T> hdf_data_type;
|
||||||
|
hdf5_write_array(fg, data_set_name, data, hdf_data_type.type());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t DIMENSIONS>
|
||||||
|
void hdf5_write_array(H5::CommonFG& fg, const std::string& data_set_name, const boost::multi_array<std::complex<T>, DIMENSIONS>& data )
|
||||||
|
{
|
||||||
|
hdf5_write_array(fg, data_set_name, data, hdf5_ComplexType<T>::ctype()->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// HDF5 array reader
|
||||||
|
//
|
||||||
|
// Author Guilhem Lavaux (May 2014)
|
||||||
|
|
||||||
|
class InvalidDimensions: virtual std::exception {
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t r>
|
||||||
|
struct hdf5_extent_gen {
|
||||||
|
typedef typename boost::detail::multi_array::extent_gen<r> type;
|
||||||
|
|
||||||
|
static inline type build(hsize_t *d)
|
||||||
|
{
|
||||||
|
return (hdf5_extent_gen<r-1>::build(d))[d[r-1]];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct hdf5_extent_gen<0> {
|
||||||
|
static inline boost::multi_array_types::extent_gen build(hsize_t *d)
|
||||||
|
{
|
||||||
|
return boost::extents;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, std::size_t DIMENSIONS, typename hdf5_data_type>
|
||||||
|
void hdf5_read_array(H5::CommonFG& fg, const std::string& data_set_name,
|
||||||
|
boost::multi_array<T, DIMENSIONS>& data,
|
||||||
|
const hdf5_data_type& datatype)
|
||||||
|
{
|
||||||
|
H5::DataSet dataset = fg.openDataSet(data_set_name);
|
||||||
|
H5::DataSpace dataspace = dataset.getSpace();
|
||||||
|
std::vector<hsize_t> dimensions(DIMENSIONS);
|
||||||
|
|
||||||
|
if (dataspace.getSimpleExtentNdims() != DIMENSIONS)
|
||||||
|
{
|
||||||
|
throw InvalidDimensions();
|
||||||
|
}
|
||||||
|
|
||||||
|
dataspace.getSimpleExtentDims(dimensions.data());
|
||||||
|
data.resize(hdf5_extent_gen<DIMENSIONS>::build(dimensions.data()));
|
||||||
|
dataset.read(data.data(), datatype);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t DIMENSIONS>
|
||||||
|
void hdf5_read_array(H5::CommonFG& fg, const std::string& data_set_name, boost::multi_array<T, DIMENSIONS>& data )
|
||||||
|
{
|
||||||
|
get_hdf5_data_type<T> hdf_data_type;
|
||||||
|
hdf5_read_array(fg, data_set_name, data, hdf_data_type.type());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t DIMENSIONS>
|
||||||
|
void hdf5_read_array(H5::CommonFG& fg, const std::string& data_set_name, boost::multi_array<std::complex<T>, DIMENSIONS>& data )
|
||||||
|
{
|
||||||
|
hdf5_read_array(fg, data_set_name, data, hdf5_ComplexType<T>::ctype()->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user