next up previous index
Next: Compound Datatypes Up: HDF5 Previous: Chunking

Point Selection

The previous section (or, to be more exact, the section, which was subdivided into two subsections, of which the second was subdivided into 4 sub-sub-sections) talked about selecting hyperslabs, i.e., subsets of a dataset. But what if we want to modify just a specific element of the dataset, not its whole subset? There is an HDF5 dataspace function, H5Sselect_elements , that lets us focus the dataspace on individual points. We are going to demonstrate how this function works in this section.

We are going to create two HDF5 files. The first one is going to have just one $3\times4$ data set in it filled with zeros, and the second one is going to have just one $3\times4$ data set in it filled with ones. Then we're going to close the files and open them again for an update. We are going to write 59 in the (0,1) location of each dataset and 53 in the (0,3) location of each dataset. Then the files will get closed again, re-opened for reading, their datasets read and printed on standard output.

Here you can see how the program works on the AVIDD cluster.

gustav@bh1 $ pwd
/N/B/gustav/src/I590/HDF5/points
gustav@bh1 $ h5cc -o h5_copy h5_copy.c
gustav@bh1 $ ./h5_copy

Dataset 'Copy1' in file 'copy1.h5' contains: 
  0   59    0   53  
  0    0    0    0  
  0    0    0    0  

Dataset 'Copy2' in file 'copy2.h5' contains: 
  1   59    1   53  
  1    1    1    1  
  1    1    1    1  
gustav@bh1 $ ls
copy1.h5  copy2.h5  h5_copy  h5_copy.c  h5_copy.o
gustav@bh1 $ h5dump copy1.h5
HDF5 "copy1.h5" {
GROUP "/" {
   DATASET "Copy1" {
      DATATYPE  H5T_STD_I32LE
      DATASPACE  SIMPLE { ( 3, 4 ) / ( 3, 4 ) }
      DATA {
         0, 59, 0, 53,
         0, 0, 0, 0,
         0, 0, 0, 0
      }
   }
}
}
gustav@bh1 $ h5dump copy2.h5
HDF5 "copy2.h5" {
GROUP "/" {
   DATASET "Copy2" {
      DATATYPE  H5T_STD_I32LE
      DATASPACE  SIMPLE { ( 3, 4 ) / ( 3, 4 ) }
      DATA {
         1, 59, 1, 53,
         1, 1, 1, 1,
         1, 1, 1, 1
      }
   }
}
}
gustav@bh1 $

This is the listing of the program taken from the NCSA HDF5 Tutorial:

/***********************************************************************/
/*                                                                     */
/*  PROGRAM:   h5_copy.c                                               */
/*  PURPOSE:   Shows how to use the H5SCOPY function.                  */
/*  DESCRIPTION:                                                       */
/*             This program creates two files, copy1.h5, and copy2.h5. */
/*             In copy1.h5, it creates a 3x4 dataset called 'Copy1',   */
/*             and write 0's to this dataset.                          */
/*             In copy2.h5, it create a 3x4 dataset called 'Copy2',    */
/*             and write 1's to this dataset.                          */
/*             It closes both files, reopens both files, selects two   */
/*             points in copy1.h5 and writes values to them.  Then it  */
/*             does an H5Scopy from the first file to the second, and  */
/*             writes the values to copy2.h5.  It then closes the      */
/*             files, reopens them, and prints the contents of the     */
/*             two datasets.                                           */
/*                                                                     */
/***********************************************************************/
 
#include "hdf5.h"
#define FILE1 "copy1.h5"
#define FILE2 "copy2.h5"

#define RANK  2
#define DIM1  3
#define DIM2  4
#define NUMP  2 

int main (void)
{
     hid_t   file1, file2, dataset1, dataset2;
     hid_t   mid1, mid2, fid1, fid2;
     hsize_t fdim[] = {DIM1, DIM2};
     hsize_t mdim[] = {DIM1, DIM2};
     hsize_t start[2], stride[2], count[2], block[2];
     int buf1[DIM1][DIM2];
     int buf2[DIM1][DIM2];
     int bufnew[DIM1][DIM2];
     int val[] = {53, 59};
     hsize_t marray[] = {2};
     hssize_t coord[NUMP][RANK];
     herr_t ret;
     uint  i, j;

/***********************************************************************/
/*                                                                     */
/* Create two files containing identical datasets. Write 0's to one    */
/* and 1's to the other.                                               */
/*                                                                     */
/***********************************************************************/

for ( i = 0; i < DIM1; i++ ) 
         for ( j = 0; j < DIM2; j++ )
             buf1[i][j] = 0;

     for ( i = 0; i < DIM1; i++ ) 
         for ( j = 0; j < DIM2; j++ )
             buf2[i][j] = 1;

     file1 = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
     file2 = H5Fcreate(FILE2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);

     fid1 = H5Screate_simple (RANK, fdim, NULL);
     fid2 = H5Screate_simple (RANK, fdim, NULL);

     dataset1 = H5Dcreate (file1, "Copy1", H5T_NATIVE_INT, fid1, H5P_DEFAULT);
     dataset2 = H5Dcreate (file2, "Copy2", H5T_NATIVE_INT, fid2, H5P_DEFAULT);

     ret = H5Dwrite(dataset1, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf1);
     ret = H5Dwrite(dataset2, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf2);

     ret = H5Dclose (dataset1);
     ret = H5Dclose (dataset2);

     ret = H5Sclose (fid1);
     ret = H5Sclose (fid2);

     ret = H5Fclose (file1);
     ret = H5Fclose (file2);

/***********************************************************************/
/*                                                                     */
/* Open the two files.  Select two points in one file, write values to */
/* those point locations, then do H5Scopy and write the values to the  */
/* other file.  Close files.                                           */
/*                                                                     */
/***********************************************************************/
 
     file1 = H5Fopen (FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
     file2 = H5Fopen (FILE2, H5F_ACC_RDWR, H5P_DEFAULT);
     dataset1 = H5Dopen (file1, "Copy1");
     dataset2 = H5Dopen (file2, "Copy2");
     fid1 = H5Dget_space (dataset1);
     mid1 = H5Screate_simple(1, marray, NULL); 
     coord[0][0] = 0; coord[0][1] = 3;
     coord[1][0] = 0; coord[1][1] = 1;

     ret = H5Sselect_elements (fid1, H5S_SELECT_SET, NUMP, (const hssize_t **)coord);

     ret = H5Dwrite (dataset1, H5T_NATIVE_INT, mid1, fid1, H5P_DEFAULT, val); 

     fid2 = H5Scopy (fid1);

     ret = H5Dwrite (dataset2, H5T_NATIVE_INT, mid1, fid2, H5P_DEFAULT, val); 

     ret = H5Dclose (dataset1);
     ret = H5Dclose (dataset2);
     ret = H5Sclose (fid1);
     ret = H5Sclose (fid2);
     ret = H5Fclose (file1);
     ret = H5Fclose (file2);
     ret = H5Sclose (mid1);

/***********************************************************************/
/*                                                                     */
/* Open both files and print the contents of the datasets.             */
/*                                                                     */
/***********************************************************************/

     file1 = H5Fopen (FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
     file2 = H5Fopen (FILE2, H5F_ACC_RDWR, H5P_DEFAULT);
     dataset1 = H5Dopen (file1, "Copy1");
     dataset2 = H5Dopen (file2, "Copy2");

     ret = H5Dread (dataset1, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
                    H5P_DEFAULT, bufnew);
     
     printf ("\nDataset 'Copy1' in file 'copy1.h5' contains: \n");
     for (i=0;i<DIM1; i++) {
        for (j=0;j<DIM2;j++) printf ("%3d  ", bufnew[i][j]);
        printf("\n");
     }

     printf ("\nDataset 'Copy2' in file 'copy2.h5' contains: \n");

     ret = H5Dread (dataset2, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
                    H5P_DEFAULT, bufnew);

     for (i=0;i<DIM1; i++) {
        for (j=0;j<DIM2;j++) printf ("%3d  ", bufnew[i][j]);
        printf("\n");
     }
     ret = H5Dclose (dataset1);
     ret = H5Dclose (dataset2);
     ret = H5Fclose (file1);
     ret = H5Fclose (file2);

}
This is not an MPI program (just in case you got used to the HDF5/MPI-IO mixture). Its first part is completely standard HDF5: we create the files, we create simple dataspaces, then we create the datasets, we write zeros on one and ones on the other one, then close it all.

In the second part of the program new things happen. We open both files and the datasets within them. Then we extract the dataspace from the first dataset, create a simple dataspace for the two numbers {53, 59}, and call H5Sselect_elements to narrow the dataspace to just the two selected locations:

#define NUMP  2 
...
     fid1 = H5Dget_space (dataset1);
     mid1 = H5Screate_simple(1, marray, NULL); 
     coord[0][0] = 0; coord[0][1] = 3;
     coord[1][0] = 0; coord[1][1] = 1;
     ret = H5Sselect_elements (fid1, H5S_SELECT_SET, NUMP, (const hssize_t **)coord);
The first parameter in the call to H5Sselect_elements is the dataset. This is followed by the mode of selection, in this case we use the same mode as in our previous examples with hyperslabs, i.e., we are going to replace the original dataspace with the one that focuses on the two points in the dataspace only. The third parameter, here it is NUMP, specifies the number of points and the last parameter is the array that provides the point coordinates. Here they are (0,3) and (0,1).

Now we can write our data on just these two locations:

    int val[] = {53, 59};
...
    ret = H5Dwrite (dataset1, H5T_NATIVE_INT, mid1, fid1, H5P_DEFAULT, val);
Observe that number 53 corresponds to (0,3) and 59 corresponds to (0,1).

Because the datasets on both files have the same geometry and we want to write the data on exactly the same points in the second dataset, we don't need to re-create the dataspace for this operation. We can simply copy fid1 onto a new dataspace fid2 by calling function  H5Scopy:

     fid2 = H5Scopy (fid1);
Having done this we complete the write on the second file:
ret = H5Dwrite (dataset2, H5T_NATIVE_INT, mid1, fid2, H5P_DEFAULT, val);
and then close everything again.

The last part of the program opens the files, the datasets, reads them, prints them, and then closes it all. There is nothing new in it, so I'll just skip it.


next up previous index
Next: Compound Datatypes Up: HDF5 Previous: Chunking
Zdzislaw Meglicki
2004-04-29