0
votes

When I try and add an unsigned long long attribute to a dataset, the attribute is added but not the value. Using a similiar method for an integer seems to work file.

Am using HDF view to view the attributes. The attribute names are displayed, but for the unsigned long long attributes, the values are not visible

The code is as follows:

    herr_t Result;

//Open the file
hid_t DataFile = H5Fopen(FileName, H5F_ACC_RDWR, H5P_DEFAULT);

//Open the dataset
hid_t DataSet = H5Dopen2(DataFile, "/Summary", H5P_DEFAULT);

//Create the data space for the attribute.
hsize_t AttributeDims = 1;
hid_t AttributeDataSpace = H5Screate_simple(1, &AttributeDims , NULL);
hid_t Attribute;

//Attribute 1: Fail to write a long long attribute
Attribute = H5Acreate2 (DataSet, "LongAttribute",  H5T_STD_U64BE, AttributeDataSpace, H5P_DEFAULT, H5P_DEFAULT);
if (Attribute < 0) {
    fprintf(stdout, "Failed to add the unsigned long long attribute to the file %s.", FileName);
    return false;
}

//Write the attribute data
unsigned long long* ULLAttribute = (unsigned long long*) malloc(sizeof(unsigned long long) * 1);
ULLAttribute[0] = (unsigned long long) 4;
Result = H5Awrite(Attribute, H5T_NATIVE_ULLONG, ULLAttribute);
if (Result < 0) {
    fprintf(stdout, "Failed to write the unsigned long long attribute to the file %s.", FileName);
    return false;
}

//Attribute 2: Succesfully Write a integer attribute
Attribute = H5Acreate2 (DataSet, "IntAttribute",  H5T_STD_I32BE, AttributeDataSpace, H5P_DEFAULT, H5P_DEFAULT);
if (Attribute < 0) {
    fprintf(stdout, "Failed to create the attribute for the file %s.", FileName);
    return false;
}

//Write the attribute data
int32_t* IAttribute = (int32_t*) malloc(sizeof(int32_t) * 1);
IAttribute[0] = (int32_t) 4;
Result = H5Awrite(Attribute,  H5T_NATIVE_INT, IAttribute);
if (Result < 0) {
    fprintf(stdout, "Failed to add the integer attribute to the file %s.", FileName);
    return false;
}

//Close the attribute, Dataset and DataFile
Result = H5Aclose(Attribute);
Result = H5Dclose(DataSet);
Result = H5Fclose(DataFile);

No error messages are displayed when the code is executed, but when the HDF5 file is viewed, both the attributes, "IntAttribute" and "LongAttribute" are visible, but the LongAttribute has no value.

HFView 2.9, Fedora 20 on intel 64.

Picking some of Timothy's question's Wrt: How come you are creating a simple dataspace for the attribute? I was chewing on storing the model parameters as attributes, kinda like key-value-pairs. Many of the model parameters are simple scalar values.

Wrt: Following the same lines, how come your writing an array for the attribute? I'd edited an example, which had stored 2 values in an array. I see from your example, you've malloc()'ed the space, which I'll use from now on as it seems more clear.

Wrt: Your on an Intel 64, yet your wanting to write big endian? Yes: this still puzzels me: both H5T_STD_I32BE and H5T_STD_I32LE work successfully, but neither H5T_STD_U64BE nor H5T_STD_U64LE show a value in HDFView. I guess that somewhere in the HDF5 library it's checking for big vs little endian and handling the value accordingly, regardless of the parameter. I'll try not to trip over this "feature" later with Postgresql binary numbers which are always big endian values.

The issue appears to be in HDFView, which is still not displaying the unsigned long long in the ull.h5 file produced by Timothy's code, or from my code:enter image description here

I'm using HDFView 2.9 for Linux. As Timothy mentioned this works in HDFView 2.10 I'll use h5dump in the meantime.

1
Interesting that HDFView 2.9 doesn't show it. Postgresql only transmits numbers in big endian (aka network byte order). In talking to Postgresql you really should be using xdr(), ntohl() and friends. So as to abstract the fact that your application doesn't need to know what endian it is running on. Good luck! - Timothy Brown

1 Answers

1
votes

A couple of questions, which should be fine, but I'm just curious.

  1. How come you are creating a simple dataspace for the attribute?
  2. Following the same lines, how come your writing an array for the attribute?
  3. Your on an Intel 64, yet your wanting to write big endian?

Here's a simple example of writing an attribute using a scalar dataspace:

#include <stdio.h>
#include <stdlib.h>
#include <hdf5.h>

int
main(int argc, char **argv)
{
        unsigned long long *ull = NULL;
        hid_t f_id = {0};
        hid_t d_id = {0};
        hid_t s_id = {0};
        hid_t a_id = {0};
        hid_t as_id = {0};
        hsize_t dims[2] = {2, 2};
        herr_t status = {0};

        f_id = H5Fcreate("ull.h5",H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
        s_id = H5Screate_simple(2, dims, NULL);
        d_id = H5Dcreate(f_id, "/data", H5T_STD_I32BE, s_id,
                         H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);

        as_id = H5Screate(H5S_SCALAR);
        a_id = H5Acreate(d_id, "unsigned long long", H5T_STD_U64LE,
                         as_id, H5P_DEFAULT, H5P_DEFAULT);

        ull = malloc(sizeof(unsigned long long));
        *ull = 123;
        status = H5Awrite(a_id, H5T_NATIVE_ULLONG, ull);

        status = H5Aclose(a_id);
        status = H5Dclose(d_id);
        status = H5Sclose(s_id);
        status = H5Fclose(f_id);

        return(EXIT_SUCCESS);
}

When compiled and run:

h5pcc -o test test.c && ./test && h5dump ull.h5

I see it fine:

HDF5 "ull.h5" {
GROUP "/" {
   DATASET "data" {
      DATATYPE  H5T_STD_I32BE
      DATASPACE  SIMPLE { ( 2, 2 ) / ( 2, 2 ) }
      DATA {
      (0,0): 0, 0,
      (1,0): 0, 0
      }
      ATTRIBUTE "unsigned long long" {
         DATATYPE  H5T_STD_U64LE
         DATASPACE  SCALAR
         DATA {
         (0): 1234
         }
      }
   }
}
}

Of course if I change the scalar attribute dataspace to a simple dataspace it still works:

as_id = H5Screate_simple(1, adims, NULL);
a_id = H5Acreate(d_id, "unsigned long long", H5T_STD_U64LE,
                 as_id, H5P_DEFAULT, H5P_DEFAULT);
ull = malloc(sizeof(unsigned long long));
*ull = 123;

We get:

  ATTRIBUTE "unsigned long long" {
     DATATYPE  H5T_STD_U64LE
     DATASPACE  SIMPLE { ( 1 ) / ( 1 ) }
     DATA {
     (0): 123
     }

Right so after a long winded example of how it can be done. Looking at your code, I really can't find your error. In fact using your code as on a empty HDF5 file works:

localhost ~$ h5dump ull.h5
HDF5 "ull.h5" {
GROUP "/" {
   DATASET "Summary" {
      DATATYPE  H5T_STD_I32BE
      DATASPACE  SIMPLE { ( 2, 2 ) / ( 2, 2 ) }
      DATA {
      (0,0): 0, 0,
      (1,0): 0, 0
      }
   }
}
}
localhost ~$ ./foo
localhost ~$ h5dump ull.h5
HDF5 "ull.h5" {
GROUP "/" {
   DATASET "Summary" {
      DATATYPE  H5T_STD_I32BE
      DATASPACE  SIMPLE { ( 2, 2 ) / ( 2, 2 ) }
      DATA {
      (0,0): 0, 0,
      (1,0): 0, 0
      }
      ATTRIBUTE "IntAttribute" {
         DATATYPE  H5T_STD_I32BE
         DATASPACE  SIMPLE { ( 1 ) / ( 1 ) }
         DATA {
         (0): 4
         }
      }
      ATTRIBUTE "LongAttribute" {
         DATATYPE  H5T_STD_U64BE
         DATASPACE  SIMPLE { ( 1 ) / ( 1 ) }
         DATA {
         (0): 4
         }
      }
   }
}
}

Can you check (and post) what h5dump gives you? Maybe it is just an issue in using HDFView?


Update

I just had a look at the file with HDFView (version 2.10) and it seems to be fine. HDFView inspection of Attributes

Can you confirm/re-create your error?