2011-09-14 17 views
8

मैं 2 डी सरणी डेटासेट फ़ाइलों को लिखने के लिए HDF5 C++ API का उपयोग कर रहा हूं। एचडीएफ समूह में an example to create एक एचडीएफ 5 फ़ाइल है जो एक स्थिर रूप से परिभाषित सरणी आकार से है, जिसे मैंने नीचे अपनी आवश्यकताओं को सुइट करने के लिए संशोधित किया है। हालांकि, मुझे एक गतिशील सरणी की आवश्यकता है, जहां NX और NY रनटाइम पर निर्धारित किए गए हैं। मुझे गतिशील सरणी बनाने में मदद के लिए another solution to create 2D arrays using the "new" keyword मिला है।एचडीएफ 5 सी ++ इंटरफ़ेस: गतिशील 2 डी सरणी लिखना

#include "StdAfx.h" 
#include "H5Cpp.h" 
using namespace H5; 

const H5std_string FILE_NAME("C:\\SDS.h5"); 
const H5std_string DATASET_NAME("FloatArray"); 
const int NX = 5; // dataset dimensions 
const int NY = 6; 

int main (void) 
{ 
    // Create a 2D array using "new" method 
    double **data = new double*[NX]; 
    for (int j = 0; j < NX; j++)   // 0 1 2 3 4 5 
    {         // 1 2 3 4 5 6 
     data[j] = new double[NY];  // 2 3 4 5 6 7 
     for (int i = 0; i < NY; i++)  // 3 4 5 6 7 8 
      data[j][i] = (float)(i + j); // 4 5 6 7 8 9 
    } 

    // Create HDF5 file and dataset 
    H5File file(FILE_NAME, H5F_ACC_TRUNC); 
    hsize_t dimsf[2] = {NX, NY}; 
    DataSpace dataspace(2, dimsf); 
    DataSet dataset = file.createDataSet(DATASET_NAME, PredType::NATIVE_DOUBLE, 
              dataspace); 
    // Attempt to write data to HDF5 file 
    dataset.write(data, PredType::NATIVE_DOUBLE); 

    // Clean up 
    for(int j = 0; j < NX; j++) 
     delete [] data[j]; 
    delete [] data; 
    return 0; 
} 

परिणामी फ़ाइल, तथापि, के रूप में उम्मीद नहीं कर रहा है (hdf5dump से उत्पादन):

HDF5 "SDS.h5" { 
GROUP "/" { 
    DATASET "FloatArray" { 
     DATATYPE H5T_IEEE_F64LE 
     DATASPACE SIMPLE { (5, 6)/(5, 6) } 
     DATA { 
     (0,0): 4.76465e-307, 4.76541e-307, -7.84591e+298, -2.53017e-098, 0, 
     (0,5): 3.8981e-308, 
     (1,0): 4.76454e-307, 0, 2.122e-314, -7.84591e+298, 0, 1, 
     (2,0): 2, 3, 4, 5, -2.53017e-098, -2.65698e+303, 
     (3,0): 0, 3.89814e-308, 4.76492e-307, 0, 2.122e-314, -7.84591e+298, 
     (4,0): 1, 2, 3, 4, 5, 6 
     } 
    } 
} 
} 

समस्या कैसे 2 डी सरणी बनाया गया था करने के लिए वापस उपजी (इस के बाद से यहाँ मैं क्या है उदाहरण एक स्थिर सरणी विधि के साथ ठीक काम करता है)। मैं this email thread से समझने के रूप में:

HDF5 पुस्तकालय तत्वों का एक सन्निहित सरणी होने की उम्मीद है, कम आयामों में तत्वों की ओर इशारा नहीं

के रूप में मैं नहीं बल्कि नई सी ++/HDF5 को हूँ, मैं कर रहा हूँ सुनिश्चित नहीं है कि रनटाइम पर गतिशील रूप से आकार का सरणी कैसे बनाएं, जो तत्वों की एक संगत सरणी है। मैं ईमेल थ्रेड में वर्णित अधिक जटिल "हाइपरस्लैब" विधि नहीं करना चाहता, क्योंकि यह अत्यधिक जटिल दिखता है। किसी भी मदद की सराहना की है।

उत्तर

7

ठीक है, मुझे एचडीएफ 5 के बारे में कुछ भी पता नहीं है, लेकिन एक संगत बफर के साथ सी ++ में गतिशील 2 डी सरणी आकार NX * NY के 1 डी सरणी का उपयोग कर अनुकरण किया जा सकता है।

आवंटन:

double *data = new double[NX*NY]; 

तत्व पहुँच:

data[j*NY + i] 

(data[j][i] के बजाय)

+1

यह समाधान लागू करने के लिए सरल है और वास्तव में अच्छी तरह से अनुरूप (मैं कर रहा हूँ 21.9 एम तत्वों के साथ सरणी आकार का उपयोग)। नतीजा एचडीएफ 5 फाइल आउटपुट में पूरी तरह से सत्यापित करता है। –

+0

एक आकर्षण की तरह काम करता है। धन्यवाद। – CuriousCase

+0

मुझे पता है कि यह काफी पुराना है, लेकिन, मुझे लगता है कि अंतिम वाक्य में कोई त्रुटि है। यह होना चाहिए: (डेटा के बजाय [i] [j] ') –

2

वैज्ञानिक प्रोग्रामिंग में यह एक बड़ा -1 डी सरणी के रूप में बहुआयामी सरणियों प्रतिनिधित्व करने के लिए आम है और उदाहरण के लिए फिर बहुआयामी सूचकांक से संबंधित ऑफसेट की गणना, उदाहरण के लिए जैसा कि डॉक्टर ब्राउन द्वारा जवाब में देखा गया है।

वैकल्पिक रूप से, आप एक इंटरफ़ेस प्रदान करने के लिए सबस्क्रिप्ट ऑपरेटर (operator[]()) को अधिभारित कर सकते हैं जो 1 डी सरणी द्वारा समर्थित बहु-आयामी सूचकांक के उपयोग की अनुमति देता है। या बेहतर अभी तक, लाइब्रेरी का उपयोग करें जो ऐसा करता है, जैसे कि Boost multi_array। या यदि आपके 2 डी सरणी matrices हैं, तो आप Eigen जैसे एक अच्छी सी ++ रैखिक बीजगणित पुस्तकालय का उपयोग कर सकते हैं।

5

यहाँ कैसे HDF5 प्रारूप

में एन आयाम सरणियों लिखने के लिए यह बहुत boostmulti_array वर्ग का उपयोग करने के लिए बेहतर है। यह कच्चे सरणी के बजाय std::vector का उपयोग करने के बराबर है: यह आपके लिए सभी मेमोरी प्रबंधन करता है और आप परिचित सबस्क्रिप्टिंग (उदा।

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

// dataset dimensions set at run time 
int NX = 5, NY = 6, NZ = 7; 


// allocate array using the "extents" helper. 
// This makes it easier to see how big the array is 
multi_array<double, 3> float_data(extents[NX][NY][NZ]); 

// use resize to change size when necessary 
// float_data.resize(extents[NX + 5][NY + 4][NZ + 3]); 


// This is how you would fill the entire array with a value (e.g. 3.0) 
std::fill_n(float_data.data(), float_data.num_elements(), 3.0) 

// initialise the array to some variables 
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); 

अंतिम पंक्ति एक समारोह जो किसी भी आयाम और किसी भी मानक संख्या प्रकार (ints, chars, floats आदि) की multi_array रों लिख सकते हैं कॉल: data[12][13] = 46)

यहाँ एक छोटी उदाहरण है।

यहां write_hdf5() के लिए कोड है।

सबसे पहले, हम नक्शा चाहिए C++ HDF5 प्रकार के प्रकार (H5 C++ एपीआई से):

#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); 
} 
संबंधित मुद्दे