ARJO SEGERS, ROELAND VAN OSS, GIJS VAN SOEST, JOS VAN GEFFEN
KNMI
Date: 3 March 2009
The routines facilitate reading/writing of integer or real arrays. The following type/kinds are possible:
| integer(1) | |
| integer(2) | |
| integer(4) | real(4) |
| integer(8) | real(8) |
Subroutines convert where possible between types and/or kinds:
The module includes the file "hdf.f90" from the HDF4 distribution. The include directory with this file should be specified in an argument of the 'configure' script:
./configure --includes=/usr/local/include
The library should be linked together with the default hdf libraries.
use file_hdf
HDF files
---------
type(THdfFile) :: hdf
call Init( hdf, '/data/test.hdf', 'read'|'create'|'write', status )
call GetInfo( hdf, status [,num_datasets=] [,num_global_attrs=] )
call Done( hdf, status )
Scientific Data Sets
--------------------
type(TSds) :: sds
!
! *** basic access
!
call Init( sds, status )
!
! select sds in hdf file;
! index : sets numbered 0,..,num_datasets-1
!
call Select( sds, hdf, index, status )
!
! extract properties
!
call GetInfo( sds, status [,name=] [,data_rank=] [,data_dims=] [,data_type=] [,num_attrs=] )
!
! check sds params:
! name : case independent
!
! status : on input : if non-zero, do not print error messages
! on output : <0 check failed, =0 check success, >0 error
!
call CheckInfo( sds, status [,name=] [,data_rank=] [,data_dims=] [,data_type=] [,num_attrs=] )
call Done( sds, status )
!
! *** init for reading
!
call Init( sds, hdf, 'name', status )
call ReadData( sds, x(:,:,..), status [,start=(/0,0,../)] [,stride=(/1,1,../)] )
call Done( sds, status )
!
! *** init for creation
!
call Init( sds, hdf, 'name', shape(x), <typekey>, status [,knd=] [,bits=] )
! The last value of the shape array might be the
! hdf constant 'SD_UNLIMITED' to specify an unlimited dimension.
!
! The <typekey> with optional knd or bits specify
! how the data is storred:
!
! 'int8' | 'integer(1)' | ('int' |'integer'), (bits=8 |knd=1)
! 'int16' | 'integer(2)' | ('int' |'integer'), (bits=16|knd=2)
! 'int32' | 'integer(4)' | ('int' |'integer'), (bits=32|knd=4)
! 'int64' | 'integer(8)' | ('int' |'integer'), (bits=64|knd=8)
! 'float32' | 'real(4)' | ('float'|'real' ), (bits=32|knd=4)
! 'float64' | 'real(8)' | ('float'|'real' ), (bits=64|knd=8)
!
! 'char'
!
call Compress( sds, 'none' , status )
call Compress( sds, 'rle' , status )
call Compress( sds, 'skphuff', status [,skip_size=1..] )
call Compress( sds, 'deflate', status [,deflate_level=0..9] )
call WriteData( sds, x, status [,start=(/0,0,../)] [,stride=(/1,1,../)] )
call Done( sds, status )
!
! *** init for creation with unlimited dimension
!
call Init( sds, hdf, 'name', (/2,3,..,SD_UNLIMITED/), &
<typekey>, status [,knd=] [,bits=] )
call WriteData( sds, x(:,:,..,1), status, start=(/0,0,..,0/) [,stride=(/1,1,../)] )
call WriteData( sds, x(:,:,..,1), status, start=(/0,0,..,1/) [,stride=(/1,1,../)] )
:
call Done( sds, status )
SDS dimensions
--------------
Simple usage:
call SetDim( sds, dim_index, 'name', 'unit', (/../), status [,knd=] )
or using the expert routines:
type(TSdsDim) :: dim
call Init( dim, status )
call Select( dim, sds, dim_index, status ) ! 0,..,n-1
call SetName( dim, 'name'. status )
call SetScale( dim, (/../), status [,knd=] )
call Done( dim, status )
Attributes
----------
!
! select attribute index of certain attribute;
! status /= 0 if not found
!
call FindAttribute( hdf|sds|dim, 'name', attr_index, status )
!
! get attribute params:
! attr_index : sets numbered 0,..,num_attrs-1
! data_type : internal hdf number, see hdf manual
! data_type_descr : 'i', 'r', 's'
! (no 'l', since logicals are storred as integers)
!
call GetAttributeInfo( hdf|sds|dim, attr_index, status &
[,name=] &
[,data_type=] [,data_type_descr=c] &
[,n_values=] )
!
! check attribute params:
! name : case independent
! attr_index : sets numbered 0,..,num_attrs-1
!
! status : on input : if zero, print error messages;
! on output : <0 check failed, =0 check success, >0 error
!
call CheckAttributeInfo( hdf|sds|dim, attr_index, status [,name=] [,data_type=] [,n_values=] )
call ReadAttribute( hdf|sds|dim, 'name', i, status )
call ReadAttribute( hdf|sds|dim, 'name', r, status )
call ReadAttribute( hdf|sds|dim, 'name', l, status )
call ReadAttribute( hdf|sds|dim, 'name', s, status )
!
! status : on input : if non-zero, do not print error messages
! on output : <0 check failed, =0 check success, >0 error
!
call CheckAttribute( hdf|sds|dim, 'name', 1 ,status )
call CheckAttribute( hdf|sds|dim, 'name', 1.0 ,status )
call CheckAttribute( hdf|sds|dim, 'name', .true.,status )
call CheckAttribute( hdf|sds|dim, 'name', 's' ,status )
call WriteAttribute( hdf|sds|dim, 'name', 1 ,status [,knd=] )
call WriteAttribute( hdf|sds|dim, 'name', 1.0 ,status [,knd=] )
call WriteAttribute( hdf|sds|dim, 'name', .true.,status )
call WriteAttribute( hdf|sds|dim, 'name', 's' ,status )
Time series
-----------
Write time series of n-D arrays to a hdf file.
type(TTimeSeriesHDF) :: F
! Open file, specify maximum number of data sets:
call Init( F, 'test.hdf', 40, status )
! Add new record for field.
! If field does not exist yet, it is created with the specified:
! o unit as attribute
! o type key : 'real(4)', 'integer(2)', etc
! o maximum shape
! For arrays, the maximum size should be provided.
! first calls initialise the data sets and fill first temporal record:
call AddRecord( F, 'psurf' , 'comment', 'hPa', 'real(4)', 1000.0, status )
call AddRecord( F, 'press' , 'comment', 'hPa', 'real(4)', (/60/) , pp(:) , status )
call AddRecord( F, 'kernel', 'comment', 'c/c', 'real(4)', (/20,20/), A(:,:), status )
call AddRecord( F, 'key', 5, 'ab123', status )
! extra calls add records:
call AddRecord( F, 'press' , 'comment', 'hPa', 'real(4)', (/60/) , pp(:) , status )
call AddRecord( F, 'press' , 'comment', 'hPa', 'real(4)', (/60/) , pp(:) , status )
! Close file:
call Done( F, status )
! Extract array from existing hdf file.
! Sds is identified by name 'aaa' .
! Attribute 'version' should be 'v1.23' .
! Error messages are issued in case of any error.
type(THdfFile) :: hdf
type(TSds) :: sds
real :: x(10,20)
call Init( hdf, 'test.hdf', 'read', status )
call Init( sds, hdf, 'aaa', status )
call CheckAttribute( sds, 'version', 'v1.23', status )
call ReadData( sds, x, status )
call Done( sds, status )
call Done( hdf, status )
! Extract array from existing hdf file.
! Sds is identified by name 'aaa' and a time attribure.
! Error messages are issued in case of any error.
type(THdfFile) :: hdf
type(TSds) :: sds
real :: x(10,20)
integer :: n, k
integer :: status
call Init( hdf, 'test.hdf', 'read', status )
call Init( sds, status )
call GetInfo( hdf, status, num_datasets=n )
k = 0
do
k = k + 1
if ( k > n ) stop 'sds not found'
call Select( sds, hdf, k-1, status ) ! <-- sets numbered 0..n-1 !
call CheckInfo( sds, name='aaa', status )
if ( status /= 0 ) cycle
call CheckAttribute( sds, 'time', (/2000,1,1,0,0,0/), status )
if ( status /= 0 ) cycle
call ReadData( sds, x, status )
end do
call Done( sds, status )
call Done( hdf, status )
! Write array to a hdf file.
type(THdfFile) :: hdf
type(TSds) :: sds
real :: x(10,20)
x = 0.0
call Init( hdf, 'test.hdf', 'create', status )
call Init( sds, hdf, 'aaa', shape(x), 'real(4)', status )
call SetDim( sds, 0, 'lon', 'deg', lons, status )
call SetDim( sds, 1, 'lat', 'deg', lats, status )
call Compress( sds, 'deflate', status, deflate_level=6 )
call WriteData( sds, x, status )
call Done( sds, status )
call Done( hdf, status )
configure : script to generate source files and Makefile
file_hdf_base.f90 : definition of types, basic routines
file_hdf_iwp.F90.in : template for routines dealing with integer
variables of different kinds in files named:
file_hdf_i4.f90
file_hdf_i8.f90
etc; the template contains keys '<wp>' that are
replaced by '4', '8' etc via a sed command in
the makefile
file_hdf_rwp.F90.in : template for routines dealing with real
variables of different kinds
file_hdf_l.f90 : routines dealing with logical variables
file_hdf_s.f90 : routines dealing with charcter string variables
file_hdf.f90.in : Template for the main module that collects all other;
comments '!i<wp>!' etc are removed if the
corresponding kind specific modules are generated
Also contains types and routines for time series.