Ecco come scrivere N dimensione multi_array
s in formato HDF5
Ecco un breve esempio:
#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);
Ecco il codice per write_hdf5()
.
In primo luogo, dobbiamo mappare i tipi di C++ ai tipi di HDF5 (dal H5
C++ api). Ho commentato le linee che portano a duplicare le definizioni perché alcuni dei <stdint.h>
tipi (ad esempio uint8_t
) sono gli alias di tipo standard (ad esempio 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 }; };
Poi possiamo usare un po 'di template spedizioni magica per rendere una funzione del tipo giusto per emettere i nostri dati. Dal momento che questo è il codice del modello, ha bisogno di vivere in un file di intestazione, se avete intenzione di array di uscita HDF5 da più file di origine nel programma:
//!_______________________________________________________________________________________
//!
//! 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);
}
sì sì sì, l'API HDF5 C++ è ** ** terribile . È molto vicino all'API C sottostante senza alcun tentativo di fornire un'interfaccia C++ utile. – Walter