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.