1

I'm trying to write data in HDF5 using the C++ API. I work on Windows XP 64 bits with Visual Studio 2010. I use version 1.8.9. The target is set to X86 so I had to use the 32 bits version of HDF (to be honest, I'm very new to programming with Windows and VS and didn't configure the whole thing myself, so I'm really not sure it was the right choice).

My issue happens when trying to write a part of a dataset of type H5T_ARRAY.

The HDF5 file structure I want to achieve is a dataset of 4 dimensions (i1,i2,i3,i4), which datatype is : array of double with 2 dimensions (a1,a2). Here is the DDL to sum it up :

HDF5 "result.h5" {
GROUP "/" {
 DATASET "mydata" {
    DATATYPE  H5T_ARRAY { [a1][a2] H5T_IEEE_F64LE }
    DATASPACE  SIMPLE { ( i1,i2,i3,i4) / ( i1,i2,i3,i4 ) }
    DATA { <my data> }
 }
}

Due to my program structure, I write this dataset element by element, ie H5T_ARRAY by H5T_ARRAY.

I've defined a class OutputFile to manage all the HDF5 I/O. It contains these attributes :

H5::H5File *_H5fileHandle ;     // HDF5 file
H5::DataSpace *_dataspaceHandle ;   // Handle of the Dataspace of the datasets
int _dataspaceRank ;        // Rank of the dataspace
H5::ArrayType *_datatypeHandle ;    // Handle of the datatype of the datasets (= array of N dimensions)
int _datatypeRank ;             // Rank of the datatype
H5::DataSet *_datasetHandle ;   // Handle of the dataset

The file is open right at the beginning of the program, and all the handles (dataspace, datatype and dataset) are set then :

void OutputFile ::createFile(std::string filename, 
            std::vector<int> dsdims, 
            std::vector<int> adims, 
            std::vector<std::string> datasetName) {

    _filename = filename ;
    _H5fileHandle = new H5::H5File(_filename.c_str(), H5F_ACC_TRUNC);

    // Defining the dataspace 
    _dataspaceRank = dsdims.size() ; 
    hsize_t *h5dsdims = new hsize_t[_dataspaceRank] ; 
    for (int iDim=0 ; iDim < _dataspaceRank ; iDim++) h5dsdims[iDim] = hsize_t(dsdims[iDim]) ;
    _dataspaceHandle = new H5::DataSpace(_dataspaceRank, h5dsdims, NULL); 

    // Defining the datatype = array type
    _datatypeRank = adims.size() ; 
    hsize_t *h5adims = new hsize_t[_datatypeRank] ; 
    for (int iDim=0 ; iDim < _datatypeRank ; iDim++) h5adims[iDim] = hsize_t(adims[iDim]) ;
    _datatypeHandle = new H5::ArrayType(H5::PredType::IEEE_F64LE, _datatypeRank, h5adims);

   // Creating the dataset
    _datasetHandle = _H5fileHandle->createDataSet( _datasetName.c_str(),*_datatypeHandle, *_dataspaceHandle );

    // Clean up
    delete h5dsdims ;
    delete h5adims ;
}

Then, I write the data each time I get an element ready (i.e a H5T_ARRAY) :

void OutputFile::writeMyData(double **Values, int *positionInDataSet) {

    // set the element position
    hsize_t position[1][4] ; 
    position[0][0] = hsize_t(positionInDataset[0]);
    position[0][1] = hsize_t(positionInDataset[1]);
    position[0][2] = hsize_t(positionInDataset[2]);
    position[0][3] = hsize_t(positionInDataset[3]);
    _fileDataspace->selectElements( H5S_SELECT_SET, 1, (const hsize_t *)position);

    //Set the memory dataspace
    hsize_t memdims[] = {1} ; 
    H5::DataSpace memspace(1, memdims, NULL); 

    // set the memory datatype 
    hsize_t memTypeRank = 2 ;
    hsize_t *memTypedims = new hsize_t[memTypeRank] ; 
    for (int iDim=0 ; iDim < memTypeRank ; iDim++) memTypedims[iDim] = hsize_t(dataDims[iDim]) ;
    H5::ArrayType memtypeHandle(H5::PredType::IEEE_F64LE, memTypeRank, memTypedims);

    _datasetHandle->write(Values, memtypeHandle, memspace, *_dataspaceHandle);
    _H5fileHandle->flush(H5F_SCOPE_GLOBAL) ; 
}   

The Values argument is allocated in the calling function, with size [a1][a2].

Unfortunately, it doesn't work properly. I get invalid data in my HDF5 file, and all elements are equal (meaning that all H5T_ARRAY contains the same values). Exemple :

(0,0,0,0): [ 5.08271e-275, 5.08517e-275, -7.84591e+298, -2.53017e-098, 0, 2.18992e-303,
        5.08094e-275, 0, 2.122e-314, -7.84591e+298, 5.08301e-275, 5.08652e-275,
        -7.84591e+298, -2.53017e-098, 0, 2.18994e-303, 5.08116e-275, 0,
        2.122e-314, -7.84591e+298, 5.08332e-275, 5.08683e-275, -7.84591e+298, -2.53017e-098,
        0, 2.18995e-303, 5.08138e-275, 0, 2.122e-314, -7.84591e+298 ], 

... and so on for every element.

For now, I have :

  • checked that the content of the "Value" array in writeMyData() is correct and contains valid data
  • checked that, if I only write one element, then this element, and only this one, contains invalid data in the HDF5 files (the other ones contain only zeroes)
  • used those additional type combinations, without success :
    • memType = NATIVE_DOUBLE, fileType = IEEE_64LE
    • memType = NATIVE_DOUBLE, fileType = NATIVE_DOUBLE
    • memType = IEEE_32LE, fileType = IEEE_32_LE
  • checked that double-value attributes are written correctly, using the type IEEE_F64LE
  • tried to close the file at the end of writeMyData(), and open it at the beginning, to force writing data on the disk. The results are the same.
  • passed &Values instead of Values in the call to DataSet::write() (the results are the same).

I'm a bit at my wits' end. I've found examples for partial I/0 of a dataset and others for array datatypes, but nothing for partial writing of array-type datasets. I guess it's a memory issue, my feeling is that I do something wrong when passing the "Values" array to DataSet::write(), but I can't pinpoint the problem.

Thanks in advance for any pointers you have.

  • 1
    Could you post a minimal version of your code that reproduces the problem? As it is now, it's hard to diagnostic the problem. Plus there are some errors in your code (it doesn't compile). I suspect the error comes from your use of `**Values` but it's very hard to tell. – Simon Jun 14 '14 at 22:49
  • Any news? Did you solve it? If you did, please post the solution as an answer to your question. – Simon Jun 19 '14 at 17:07

0 Answers0