Skip to content

Instantly share code, notes, and snippets.

@dstuebe
Last active December 19, 2015 06:39
Show Gist options
  • Save dstuebe/5912638 to your computer and use it in GitHub Desktop.
Save dstuebe/5912638 to your computer and use it in GitHub Desktop.
Example fortran code to create compressed dataset with compound data types.
/*-------------------------------------------------------------------------
* Function: H5Z_can_apply_szip
*
* Purpose: Check the parameters for szip compression for validity and
* whether they fit a particular dataset.
*
* Note: This function currently range-checks for datatypes with
* 8-bit boundaries (8, 16, 24, etc.). It appears that the szip
* library can actually handle 1-24, 32 & 64 bit samples. If
* this becomes important, we should make the checks below more
* sophisticated and have them check for n-bit datatypes of the
* correct size, etc. - QAK
*
* Return: Success: Non-negative
* Failure: Negative
*
* Programmer: Quincey Koziol
* Monday, April 7, 2003
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static htri_t
H5Z_can_apply_szip(hid_t UNUSED dcpl_id, hid_t type_id, hid_t UNUSED space_id)
{
const H5T_t *type; /* Datatype */
unsigned dtype_size; /* Datatype's size (in bits) */
H5T_order_t dtype_order; /* Datatype's endianness order */
htri_t ret_value = TRUE; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Get datatype */
if(NULL == (type = H5I_object_verify(type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
/* Get datatype's size, for checking the "bits-per-pixel" */
if((dtype_size = (8 * H5T_get_size(type))) == 0)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad datatype size")
/* Range check datatype's size */
if(dtype_size > 32 && dtype_size != 64)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FALSE, "invalid datatype size")
/* Get datatype's endianness order */
if((dtype_order = H5T_get_order(type)) == H5T_ORDER_ERROR)
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "can't retrieve datatype endianness order")
/* Range check datatype's endianness order */
/* (Note: this may not handle non-atomic datatypes well) */
if(dtype_order != H5T_ORDER_LE && dtype_order != H5T_ORDER_BE)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FALSE, "invalid datatype endianness order")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5Z_can_apply_szip() */
!************************************************************
!
! This example shows how to read and write compound
! datatypes to a dataset.
!
! This file is intended for use with HDF5 Library version 1.8
! with --enable-fortran2003
!
! Compile: gfortran -I/usr/local/Cellar/hdf5/1.8.11/include -L/usr/local/Cellar/hdf5/1.8.11/lib -lhdf5_fortran -lhdf5hl_fortran -lhdf5 -lhdf5_hl hdfWriteParticleType.f90 -o hdfWriteParticleType
!************************************************************
PROGRAM main
USE ISO_C_BINDING
USE HDF5
IMPLICIT NONE
! This should map to REAL*8 on most modern processors
INTEGER, PARAMETER :: real_kind_15 = SELECTED_REAL_KIND(Fortran_REAL_8)
LOGICAL :: avail
INTEGER :: flags, filter_info, filter_info_both, filter_id
CHARACTER(LEN=18), PARAMETER :: filename = "hdfParticleType.h5"
CHARACTER(LEN=3) , PARAMETER :: dataset = "DS1"
INTEGER , PARAMETER :: ntsteps = 100
INTEGER , PARAMETER :: nparticles = 100
INTEGER , PARAMETER :: chunk0 = 10
INTEGER , PARAMETER :: chunk1 = 10
!INTEGER , PARAMETER :: maxstringlen = 80
INTEGER , PARAMETER :: rank2 = 2
INTEGER , PARAMETER :: rank1 = 1
INTEGER , PARAMETER :: compression_level = 9 ! http://www.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetDeflate
INTEGER , PARAMETER :: pixels_per_block = 12 ! http://www.hdfgroup.org/HDF5/doc/RM/H5P/H5Pset_szip.htm
TYPE sensor_t ! Compound data type
INTEGER :: serial_no
!CHARACTER(LEN=maxstringlen) :: location
REAL(real_kind_15) :: temperature
REAL(real_kind_15) :: pressure
END TYPE sensor_t
TYPE(sensor_t), DIMENSION(1:nparticles), TARGET :: wdata ! Write buffer
TYPE(sensor_t), DIMENSION(1:nparticles), TARGET :: rdata ! Read buffer
INTEGER(HID_T) :: file, filetype, memtype, spaceParticles, spaceMemory, dset, strtype, dcplParticles ! Handles
INTEGER :: hdferr
INTEGER(HSIZE_T), DIMENSION(1:2) :: dimParticles = (/nparticles, ntsteps /), &
chunkParticles = (/chunk1, chunk0/)
INTEGER(HSIZE_T), DIMENSION(1:2) :: start2, stride2, count2, block2
INTEGER(HSIZE_T), DIMENSION(1:1) :: start1, stride1, count1, block1
INTEGER(HSIZE_T), Dimension(1:2) :: memSize2
INTEGER(HSIZE_T), Dimension(1:1) :: memSize1
TYPE(C_PTR) :: f_ptr
INTEGER :: i
real*4 :: tic, toc
!
! Initialize FORTRAN interface.
!
CALL h5open_f(hdferr)
! SZIP filter check
CALL h5zfilter_avail_f(H5Z_FILTER_SZIP_F, avail, hdferr)
IF (.NOT.avail) THEN
WRITE(*,'("szip filter not available.",/)')
STOP
ENDIF
CALL h5zget_filter_info_f(H5Z_FILTER_SZIP_F, filter_info, hdferr)
filter_info_both=IOR(H5Z_FILTER_ENCODE_ENABLED_F,H5Z_FILTER_DECODE_ENABLED_F)
IF (filter_info .NE. filter_info_both) THEN
WRITE(*,'("szip filter not available for encoding and decoding.",/)')
STOP
ENDIF
! GZIP filter check
CALL h5zfilter_avail_f(H5Z_FILTER_DEFLATE_F, avail, hdferr)
IF (.NOT.avail) THEN
WRITE(*,'("gzip filter not available.",/)')
STOP
ENDIF
CALL h5zget_filter_info_f(H5Z_FILTER_DEFLATE_F, filter_info, hdferr)
filter_info_both=IOR(H5Z_FILTER_ENCODE_ENABLED_F,H5Z_FILTER_DECODE_ENABLED_F)
IF (filter_info .NE. filter_info_both) THEN
WRITE(*,'("gzip filter not available for encoding and decoding.",/)')
STOP
ENDIF
!
! Initialize data.
!
call random_seed()
! Initialize data arrays with a value
call random_number(wdata%temperature)
call random_number(wdata%pressure)
wdata%serial_no = 0
!
! Create a new file using the default properties.
!
CALL h5fcreate_f(filename, H5F_ACC_TRUNC_F, file, hdferr)
!
! Create the compound datatype for memory.
!
CALL h5tcreate_f(H5T_COMPOUND_F, H5OFFSETOF(C_LOC(wdata(1)), C_LOC(wdata(2))), memtype, hdferr)
CALL h5tinsert_f(memtype, "Serial number", &
H5OFFSETOF(C_LOC(wdata(1)),C_LOC(wdata(1)%serial_no)), H5T_NATIVE_INTEGER, hdferr)
!
! Create datatype for the String attribute.
!
!CALL h5tcopy_f(H5T_NATIVE_CHARACTER, strtype, hdferr)
!CALL h5tset_size_f(strtype, INT(maxstringlen,size_t), hdferr)
!
!CALL h5tinsert_f(memtype, "Location", &
! H5OFFSETOF(C_LOC(wdata(1)),C_LOC(wdata(1)%location)), strtype, hdferr)
CALL h5tinsert_f(memtype, "Temperature (F)", &
H5OFFSETOF(C_LOC(wdata(1)),C_LOC(wdata(1)%temperature)), &
h5kind_to_type(real_kind_15,H5_REAL_KIND), hdferr)
CALL h5tinsert_f(memtype, "Pressure (inHg)", &
H5OFFSETOF(C_LOC(wdata(1)),C_LOC(wdata(1)%pressure)), &
h5kind_to_type(real_kind_15,H5_REAL_KIND), hdferr)
!
! Create the compound datatype for the file. Because the standard
! types we are using for the file may have different sizes than
! the corresponding native types, we must manually calculate the
! offset of each member.
!
!CALL h5tcreate_f(H5T_COMPOUND_F, INT(8 + maxstringlen + 8 + 8 , size_t), filetype, hdferr)
CALL h5tcreate_f(H5T_COMPOUND_F, INT(8 + 8 + 8 , size_t), filetype, hdferr)
CALL h5tinsert_f(filetype, "Serial number", 0_size_t, H5T_STD_I64BE, hdferr)
!CALL h5tinsert_f(filetype, "Location", 8_size_t, strtype, hdferr)
CALL h5tinsert_f(filetype, "Temperature (F)", INT(8,size_t), &
H5T_IEEE_F64BE, hdferr)
CALL h5tinsert_f(filetype, "Pressure (inHg)", INT(8 + 8, size_t), &
H5T_IEEE_F64BE, hdferr)
!
! Create dataspace. Set the size to be the current size.
!
CALL h5screate_simple_f(rank2, dimParticles, spaceParticles, hdferr)
count1 = (/nparticles/)
CALL h5screate_simple_f(rank1, count1, spaceMemory, hdferr)
!!!!!
! Create the dataset creation property list, and set the chunk size.
CALL h5pcreate_f(H5P_DATASET_CREATE_F, dcplParticles, hdferr)
!CALL h5pset_szip_f(dcplParticles, H5_SZIP_NN_OM_F, pixels_per_block, hdferr)
CALL h5pset_deflate_f(dcplParticles, compression_level, hdferr)
CALL h5pset_chunk_f(dcplParticles, rank2, chunkParticles, hdferr)
!!!!
!
! Create the dataset and write the compound data to it.
!
CALL h5dcreate_f(file, dataset, filetype, spaceParticles, dset, hdferr, dcplParticles)
!CALL h5dcreate_f(file, dataset, filetype, spaceParticles, dset, hdferr)
!
! Write the data to the dataset.
call cpu_time(tic)
DO i = 1,ntsteps
start2(1:2) = (/0,i-1/)
count2(1:2) = (/nParticles,1/)
CALL h5sselect_hyperslab_f (spaceParticles, H5S_SELECT_SET_F, start2, count2, hdferr)
wdata%serial_no = wdata%serial_no +1
call random_number(wdata%temperature)
call random_number(wdata%pressure)
f_ptr = C_LOC(wdata(1))
CALL h5dwrite_f(dset, memtype, f_ptr, hdferr, mem_space_id=spaceMemory, file_space_id=spaceParticles)
ENDDO
call cpu_time(toc)
print "('Completed dummy data output in ', f10.6,' Seconds')", toc - tic
!
! Close and release resources.
!
CALL h5dclose_f(dset, hdferr)
CALL h5sclose_f(spaceParticles, hdferr)
CALL h5sclose_f(spaceMemory, hdferr)
CALL h5tclose_f(filetype, hdferr)
CALL h5fclose_f(file, hdferr)
!
! Now we begin the read section of this example.
!
!
! Open file and dataset.
!
! CALL h5fopen_f(filename, H5F_ACC_RDONLY_F, file, hdferr)
! CALL h5dopen_f(file, dataset, dset, hdferr)
!
! Get dataspace.
!
! CALL h5dget_space_f(dset, space, hdferr)
! CALL h5sget_simple_extent_dims_f(space, dims, ndims, hdferr)
!
! Read the data.
!
! f_ptr = C_LOC(rdata(1))
! CALL h5dread_f(dset, memtype, f_ptr, hdferr)
!
! Output the data to the screen.
!
! DO i = 1, ndims(1)
! WRITE(*,'(A,I1,":")') dataset, i
! WRITE(*,'("Serial number : ", I6)') rdata(i)%serial_no
! WRITE(*,'("Location : ", A)' ) TRIM(rdata(i)%location)
! WRITE(*,'("Temperature (F) : ", f8.2)') rdata(i)%temperature
! WRITE(*,'("Pressure (inHg) : ", f8.2)') rdata(i)%pressure
! END DO
!
! Close and release resources
!
! CALL h5dclose_f(dset, hdferr)
! CALL h5sclose_f(space, hdferr)
! CALL h5tclose_f(strtype, hdferr)
! CALL h5fclose_f(file, hdferr)
END PROGRAM main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment