Friday, June 14, 2019

Research Note #22 - Reading GCOM-C 250m-Res HDF5 Data with Fortran

There were not so many references about 'simple' ways to open and read HDF5 data file with Fortran as well as compiling the codes. I said 'simple', because there are actually manuals and tutorials about that purpose, however, most of them were too complicated and refer to other sub-references, thus blah .. blah ... it takes too much time, especially if you just simply want to open, read and compile a HDF dataset. Here, I posted a very basic way to access HDF5 data, using very minimal Fortran code. Before starting, here's the convention:
  • I used Linux OS. 
  • I used Fortran 90 for programming.
  • HDF5 (ver 1.8.17) libraries has been already installed in my system as module.
  • I used JAXA's GCOM-C NDVI Monthly statistics (Level-2 data) with 250m spatial resolution with Sinusoidal/EQA projection. This data contains 4800x4800 pixels. For exemplary purpose, I renamed it to "ndvi.h5".
So, the following is a very basic example of Fortran code to open and read HDF5 data:

PROGRAM HDF5test

   USE HDF5
   IMPLICIT NONE

   INTEGER :: hdferr, i, j
   INTEGER(HID_T) :: fileid, dset
   CHARACTER(LEN=7), PARAMETER :: filename = "ndvi.h5"
   CHARACTER(LEN=19), PARAMETER :: dataset = "Image_data/NDVI_AVE"
   INTEGER, PARAMETER :: xdim = 4800
   INTEGER, PARAMETER :: ydim = 4800
   INTEGER, DIMENSION(1:xdim, 1:ydim) :: ndvi_ave
   INTEGER(HSIZE_T), DIMENSION(1:2) :: dims = (/xdim, ydim/)
   
   CALL h5open_f(hdferr)
   CALL h5fopen_f(filename, H5F_ACC_RDONLY_F, fileid, hdferr)
   CALL h5dopen_f(fileid, dataset, dset, hdferr)
   CALL h5dread_f(dset, H5T_NATIVE_INTEGER, ndvi_ave, dims, hdferr)

    DO j = 1, ydim
      DO i = 1, xdim
         print *, ndvi_ave(i,j)
      ENDDO
   ENDDO

  CALL h5dclose_f(dset, hdferr)
  CALL h5fclose_f(fileid, hdferr)
  CALL h5close_f(hdferr)

END PROGRAM HDFtest

The most important lines are:
  • CALL h5open_f(hdferr)This function initializes HDF5 library for Fortran uses. Returns 0 (to hdferr variable) if it's successful, and -1 if it's failed.
  • CALL h5fopen_f(filename, H5F_ACC_RDONLY_F, fileid, hdferr). This function opens an existing HDF5 file. In this example, I just want to read it, hence H5F_ACC_RDONLY_F was used as argument. This function will return integers for file identifier and status to fileid and hdferr variables, respectively.
  • CALL h5dopen_f(fileid, dataset, dset, hdferr). This function opens an existing dataset in the opened file. Take notice that it needs file identifier (from h5fopen_f), dataset name, dataset identifier and status (as previous functions).
  • CALL h5dread_f(dset, H5T_NATIVE_INTEGER, ndvi_ave, dims, hdferr). This function reads raw data from dataset of the file, into a buffer. The buffer means a space in the computer memory, this could be a variable or array. Take notice that it need dataset identifier (from h5dopen_f), memory data type (Native integer), buffer, dimension (to store buffer dimension) and as always, status (hdferr).
To make it simple, the program will firstly initialize HDF5 library, opens an existing HDF5 datafile, opens a dataset from that file (a file could consist of many datasets), read the raw data from the dataset, put the data into an array buffer, then prints the contents of the buffer into the screen. Finally, it closes the dataset, closes the file and ultimately deactivates HDF5 library (flush and cleans the memory). That's all.

Another important thing is variable declaration. HID_T and HSIZE_T are parameters for predefined datatype used by HDF5 library. So, don't be confused with them (for details, just read: https://support.hdfgroup.org/HDF5/doc/fortran/index.html).

Finally, save and give the codes a name (for example: test.f90). To compile the code, just use this command on (bash) shell:

$ h5fc -o test.exe test.f90

It's just similar with a normal Fortran compiler command. If you don't specify a name for the output, a file named 'a.out' will be generated by the compiler.

No comments:

Post a Comment