将boost::multi_array写入hdf5数据集

8

是否有任何库或头文件可用于使编写c ++向量或boost :: multi_arrays到HDF5数据集容易?

我查看了HDF5 C ++示例,它们只使用c ++语法调用c函数,并且仅将静态c数组写入其数据集(请参见create.cpp)。

我错过了什么吗!?

非常感谢, 亚当


2
是的,是的,是的,HDF5 C++ API 真的很糟糕。它非常接近底层的 C API,没有任何有用的 C++ 接口。 - Walter
2个回答

7

以下是如何以HDF5格式编写N维multi_array的方法:

这是一个简短的示例:

#include <boost/multi_array.hpp>
using boost::multi_array;
using boost::extents;


// allocate array
int NX = 5,  NY = 6,  NZ = 7;
multi_array<double, 3>  float_data(extents[NX][NY][NZ]);

// initialise the array
for (int ii = 0; ii != NX; ii++)
    for (int jj = 0; jj != NY; jj++)
        for (int kk = 0; kk != NZ; kk++)
            float_data[ii][jj][kk]  = ii + jj + kk;

// 
// write to HDF5 format
// 
H5::H5File file("SDS.h5", H5F_ACC_TRUNC);
write_hdf5(file, "doubleArray", float_data );

这里是write_hdf5()的代码。

首先,我们必须将c++类型映射到HDF5类型(从H5 c++ API中)。我已经注释掉了导致重复定义的行,因为一些<stdint.h>类型(例如uint8_t)是标准类型(例如unsigned char)的别名。

#include <cstdint>

//!_______________________________________________________________________________________
//!     
//!     map types to HDF5 types
//!         
//!     
//!     \author lg (04 March 2013)
//!_______________________________________________________________________________________ 

template<typename T> struct get_hdf5_data_type
{   static H5::PredType type()  
    {   
        //static_assert(false, "Unknown HDF5 data type"); 
        return H5::PredType::NATIVE_DOUBLE; 
    }
};
template<> struct get_hdf5_data_type<char>                  {   H5::IntType type    {   H5::PredType::NATIVE_CHAR       };  };
//template<> struct get_hdf5_data_type<unsigned char>       {   H5::IntType type    {   H5::PredType::NATIVE_UCHAR      };  };
//template<> struct get_hdf5_data_type<short>               {   H5::IntType type    {   H5::PredType::NATIVE_SHORT      };  };
//template<> struct get_hdf5_data_type<unsigned short>      {   H5::IntType type    {   H5::PredType::NATIVE_USHORT     };  };
//template<> struct get_hdf5_data_type<int>                 {   H5::IntType type    {   H5::PredType::NATIVE_INT        };  };
//template<> struct get_hdf5_data_type<unsigned int>        {   H5::IntType type    {   H5::PredType::NATIVE_UINT       };  };
//template<> struct get_hdf5_data_type<long>                {   H5::IntType type    {   H5::PredType::NATIVE_LONG       };  };
//template<> struct get_hdf5_data_type<unsigned long>       {   H5::IntType type    {   H5::PredType::NATIVE_ULONG      };  };
template<> struct get_hdf5_data_type<long long>             {   H5::IntType type    {   H5::PredType::NATIVE_LLONG      };  };
template<> struct get_hdf5_data_type<unsigned long long>    {   H5::IntType type    {   H5::PredType::NATIVE_ULLONG     };  };
template<> struct get_hdf5_data_type<int8_t>                {   H5::IntType type    {   H5::PredType::NATIVE_INT8       };  };
template<> struct get_hdf5_data_type<uint8_t>               {   H5::IntType type    {   H5::PredType::NATIVE_UINT8      };  };
template<> struct get_hdf5_data_type<int16_t>               {   H5::IntType type    {   H5::PredType::NATIVE_INT16      };  };
template<> struct get_hdf5_data_type<uint16_t>              {   H5::IntType type    {   H5::PredType::NATIVE_UINT16     };  };
template<> struct get_hdf5_data_type<int32_t>               {   H5::IntType type    {   H5::PredType::NATIVE_INT32      };  };
template<> struct get_hdf5_data_type<uint32_t>              {   H5::IntType type    {   H5::PredType::NATIVE_UINT32     };  };
template<> struct get_hdf5_data_type<int64_t>               {   H5::IntType type    {   H5::PredType::NATIVE_INT64      };  };
template<> struct get_hdf5_data_type<uint64_t>              {   H5::IntType type    {   H5::PredType::NATIVE_UINT64     };  };
template<> struct get_hdf5_data_type<float>                 {   H5::FloatType type  {   H5::PredType::NATIVE_FLOAT      };  };
template<> struct get_hdf5_data_type<double>                {   H5::FloatType type  {   H5::PredType::NATIVE_DOUBLE     };  };
template<> struct get_hdf5_data_type<long double>           {   H5::FloatType type  {   H5::PredType::NATIVE_LDOUBLE    };  };

然后,我们可以使用一些模板转发技巧来创建一个输出数据的正确类型函数。由于这是模板代码,如果您要从程序中的多个源文件输出HDF5数组,则需要将其放在头文件中:

//!_______________________________________________________________________________________
//!     
//!     write_hdf5 multi_array
//!         
//!     \author leo Goodstadt (04 March 2013)
//!     
//!_______________________________________________________________________________________
template<typename T, std::size_t DIMENSIONS, typename hdf5_data_type>
void do_write_hdf5(H5::H5File file, const std::string& data_set_name, const boost::multi_array<T, DIMENSIONS>& data, hdf5_data_type& datatype)
{
    // Little endian for x86
    //FloatType datatype(get_hdf5_data_type<T>::type());
    datatype.setOrder(H5T_ORDER_LE);

    vector<hsize_t> dimensions(data.shape(), data.shape() + DIMENSIONS);
    H5::DataSpace dataspace(DIMENSIONS, dimensions.data());

    H5::DataSet dataset = file.createDataSet(data_set_name, datatype, dataspace);

    dataset.write(data.data(), datatype);
}

template<typename T, std::size_t DIMENSIONS>
void write_hdf5(H5::H5File file, const std::string& data_set_name, const boost::multi_array<T, DIMENSIONS>& data )
{

    get_hdf5_data_type<T> hdf_data_type;
    do_write_hdf5(file, data_set_name, data, hdf_data_type.type);
}

你是不是想使用 template<> struct get_hdf5_data_type<char> { static H5::IntType type() { return H5::PredType::NATIVE_CHAR; } }; - R Sahu

1

我不知道有没有现成的。HDF5 C++包装器并不是很好,特别是因为它们不允许与并行HDF5结合使用。所以,我在大约2个小时内编写了自己的包装器,它完全可以正常工作。最终,您只需直接调用它(或间接调用,如果选择创建C++绑定)。

幸运的是,向量和多维数组在存储上是连续的,因此您可以直接将它们的数据传递到HDF5函数调用中。


嗨,好的,谢谢你让我知道了 - 那我就得继续做下去了!;-) - AdamC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接