需要用Fortran读取HDF5格式的GPM IMERG卫星降水文件,在已经安装HDF5库(参见VS2019+ Intel Fortran (oneAPI)+HDF5库的安装+测试 - chinagod - 博客园)的基础上,实现了上述功能。

下面是简要步骤:

环境:

Windows10 64位

Visual Studio 2019 Community Edition

Intel oneAPI 2021

HDF5-1.12.2

1. 读取HDF5 文件之前,需要先了解HDF5文件的结构,这里使用h5ls命令行工具

  1. C:\Users\jiangleads>h5ls -r Z:\data\GPM\30m\2021\01\3B-HHR.MS.MRG.3IMERG.20210101-S000000-E002959.0000.V06B.HDF5
  2. / Group
  3. /Grid Group
  4. /Grid/HQobservationTime Dataset {1/Inf, 3600, 1800}
  5. /Grid/HQprecipSource Dataset {1/Inf, 3600, 1800}
  6. /Grid/HQprecipitation Dataset {1/Inf, 3600, 1800}
  7. /Grid/IRkalmanFilterWeight Dataset {1/Inf, 3600, 1800}
  8. /Grid/IRprecipitation Dataset {1/Inf, 3600, 1800}
  9. /Grid/lat Dataset {1800}
  10. /Grid/lat_bnds Dataset {1800, 2}
  11. /Grid/latv Dataset {2}
  12. /Grid/lon Dataset {3600}
  13. /Grid/lon_bnds Dataset {3600, 2}
  14. /Grid/lonv Dataset {2}
  15. /Grid/nv Dataset {2}
  16. /Grid/precipitationCal Dataset {1/Inf, 3600, 1800}
  17. /Grid/precipitationQualityIndex Dataset {1/Inf, 3600, 1800}
  18. /Grid/precipitationUncal Dataset {1/Inf, 3600, 1800}
  19. /Grid/probabilityLiquidPrecipitation Dataset {1/Inf, 3600, 1800}
  20. /Grid/randomError Dataset {1/Inf, 3600, 1800}
  21. /Grid/time Dataset {1/Inf}
  22. /Grid/time_bnds Dataset {1/Inf, 2}

其中-r表示递归遍历所有的group(参考https://www.cnblogs.com/jiangleads/p/15606798.html相关部分)

2. 因为我们主要需要的是 /Grid/precipitationCal 这个变量,所以需要查看这个变量的主要信息。

使用h5dump工具来查看文件信息

  1. C:\Users\jiangleads>h5dump -H Z:\data\GPM\30m\2021\01\3B-HHR.MS.MRG.3IMERG.20210101-S040000-E042959.0240.V06B.HDF5
  2. HDF5 "Z:\data\GPM\30m\2021\01\3B-HHR.MS.MRG.3IMERG.20210101-S040000-E042959.0240.V06B.HDF5" {
  3. GROUP "/" {
  4. ...
  5. DATASET "precipitationCal" {
  6. DATATYPE H5T_IEEE_F32LE
  7. DATASPACE SIMPLE { ( 1, 3600, 1800 ) / ( H5S_UNLIMITED, 3600, 1800 ) }
  8. ATTRIBUTE "CodeMissingValue" {
  9. DATATYPE H5T_STRING {
  10. STRSIZE 8;
  11. STRPAD H5T_STR_NULLTERM;
  12. CSET H5T_CSET_ASCII;
  13. CTYPE H5T_C_S1;
  14. }
  15. DATASPACE SCALAR
  16. }
  17. ...
  18. }
  19. }
  20. }

可以看到precipitationCal变量的类型是H5T_IEEE_F32LE,这将在后面读取文件时候用到

3. 编写代码,读取变量。

示例代码:参考自 使用Fortran+HDF扩展进行HDF文件读写 | Herrera Space

  1. 1 program test
  2. 2 USE HDF5 ! This module contains all necessary modules
  3. 3 implicit none
  4. 4
  5. 5 CHARACTER filename*100
  6. 6
  7. 7 ! CHARACTER(LEN=8), PARAMETER :: filename = "dsetf.h5" ! File name
  8. 8 CHARACTER(LEN=3) dsetname ! Dataset name
  9. 9
  10. 10 INTEGER(HID_T) :: file_id ! File identifier 文件句柄
  11. 11 INTEGER(HID_T) :: dset_id ! Dataset identifier 变量句柄
  12. 12 INTEGER(HID_T) :: grp_id ! Dataset identifier group句柄
  13. 13 INTEGER(HID_T) :: dspace_id ! Dataset identifier 只可意会,和维数和大小相关
  14. 14 INTEGER :: error ! Error flag - success0
  15. 15
  16. 16 real, DIMENSION(:,:,:),allocatable :: prcp_out ! Data buffers 本例中对于大小不定的数据使用可变数组
  17. 17
  18. 18 INTEGER(HSIZE_T), DIMENSION(3) :: prcp_dims,maxdims
  19. 19
  20. 20
  21. 21
  22. 22 filename="Z:/data/GPM/30m/2021/01/3B-HHR.MS.MRG.3IMERG.20210101-S000000-E002959.0000.V06B.HDF5"
  23. 23
  24. 24 CALL h5open_f(error) ! Initialize FORTRAN interface.
  25. 25
  26. 26 CALL h5fopen_f (filename, H5F_ACC_RDONLY_F, file_id, error) ! Open an existing file.
  27. 27
  28. 28 CALL h5gopen_f (file_id, "Grid", grp_id, error) ! Open an existing group.
  29. 29
  30. 30 CALL h5dopen_f(grp_id, "precipitationCal", dset_id, error) !open dataset 就是变量
  31. 31
  32. 32 CALL h5dget_space_f(dset_id,dspace_id,error) ! Get the dataspace ID
  33. 33
  34. 34 CALL h5sget_simple_extent_dims_f(dspace_id, prcp_dims, maxdims, error)
  35. 35
  36. 36 ! Allocate memory for the array.
  37. 37 ALLOCATE(prcp_out(prcp_dims(1),prcp_dims(2),prcp_dims(3)))
  38. 38
  39. 39 ! Read the dataset.
  40. 40 CALL h5dread_f(dset_id, H5T_IEEE_F32LE, prcp_out, prcp_dims, error)
  41. 41
  42. 42 !! do something
  43. 43 !PRINT*,prcp_out(1,1)
  44. 44
  45. 45 CALL h5dclose_f(dset_id, error) ! Close the dataset.
  46. 46 DEALLOCATE(prcp_out)
  47. 47
  48. 48 CALL h5fclose_f(file_id, error) ! Close the file.
  49. 49 CALL h5close_f(error) ! Close FORTRAN interface.
  50. 50
  51. 51 end program

main.f90

代码说明,HDF5文件变量读取步骤:

1. 调用h5open_f函数,Fortran接口初始化

2. 调用h5fopen_f函数,打开文件,返回file_id

3. 调用h5gopen_f函数,从已有的file_id中,打开的指定名称的Group,返回grp_id

4. 调用h5dopen_f函数,从已有的grp_id中,打开指定名称的Dataset,返回dset_id

5. 调用h5dget_space_f函数,从已有的dset_id中,获取dataspace的ID

6. 调用h5sget_simple_extent_dims_f函数,返回变量的维度大小到prcp数组

7. 根据返回的变量维度分配数组内存

8. 调用h5dread_f函数,读取变量。其中要输入的参数有,dset_id,变量类型(这个在前面用h5dump -H命令输出的DATATYPE中已返回),变量维度,错误码等。

...进行其他步骤

9.完成其他操作后,按顺序依次调用h5dclose_f,h5fclose_f,h5close_f函数,依次关闭dataset,file,和fortran接口。

注意:HDF5有两种存储方式,数据集(Dataset)和数组(Array),如果要读取的变量存放在Array而不是Dataset中,则使用h5a前缀的函数进行操作。

后记:使用HDF5-fortran处理文件时,如果进程处理过的文件(包括已经关闭了的文件)数目超过默认系统限制(在Linux系统中一般是1024个)时,则会报错(Windows系统上也有类似错误):

  1. HDF5-DIAG: Error detected in HDF5 (1.12.0) thread 0:
  2. #000: H5F.c line 793 in H5Fopen(): unable to open file
  3. major: File accessibility
  4. minor: Unable to open file
  5. #001: H5VLcallback.c line 3500 in H5VL_file_open(): open failed
  6. major: Virtual Object Layer
  7. minor: Can't open object
  8. #002: H5VLcallback.c line 3465 in H5VL__file_open(): open failed
  9. major: Virtual Object Layer
  10. minor: Can't open object
  11. #003: H5VLnative_file.c line 100 in H5VL__native_file_open(): unable to open file
  12. major: File accessibility
  13. minor: Unable to open file
  14. #004: H5Fint.c line 1564 in H5F_open(): unable to open file: name = '/data/GPM/30m/2019/04/3B-HHR.MS.MRG.3IMERG.20190422-S083000-E085959.0510.V06B.HDF5', tent_flags = 0
  15. major: File accessibility
  16. minor: Unable to open file
  17. #005: H5FD.c line 741 in H5FD_open(): open failed
  18. major: Virtual File Layer
  19. minor: Unable to initialize object #006: H5FDsec2.c line 346 in H5FD_sec2_open(): unable to open file: name = '/data/GPM/30m/2019/04/3B-HHR.MS.MRG.3IMERG.20190422-S083000-E085959.0510.V06B.HDF5', errno = 24, error message = 'Too many open files', flags = 0, o_flags = 0 major: File accessibility
  20. minor: Unable to open file

这个是一个Bug。参见:Virtual datasets and open file limit - HDF5 - HDF Forum,netcdf貌似也有类似的错误(Re: [netcdf-hdf] 'Too many open files' What causes this?)(#20220912更新 用eccodes打开grib文件也有类似错误。 解决办法 ulimit -n 文件数)

这时候,需要设置ulimit的值,将其调大。参见How to fix 'Too Many Open Files' in LinuxLinux - ulimit命令详解与修改不生效_Yonself的博客-CSDN博客_修改ulimit 未生效

由此可见,从HDF5文件中读取变量和从GRIBnetCDF文件中读取变量的过程十分类似,基本都遵循“打开文件,获得文件句柄” => “调用函数,选定特定的变量,获取变量句柄/索引" => "调用函数,读取变量" => "依次关闭变量句柄、文件句柄" 这个流程。

Windows下使用Fortran读取HDF5文件的更多相关文章

  1. windows下Perl如何读取大文件的最后一行(总结)

    Perl中读取文件最后一行的方法很多,比如 (1)将文件读入数组,取最后一个元素 open (FILE,"file.txt") or die "$!"; my ...

  2. [django]windows下用Django,静态文件请求失败,出现UnicodeDecodeError

    问题:windows下用Django,静态文件请求失败,出现UnicodeDecodeError:'utf-8' codec can't decode byte 0xb0 in position 1: ...

  3. 转 windows下安装pycharm并连接Linux的python环境 以及 windows 下notepad ++编辑 linux 的文件

    ######sample 1:windows下安装pycharm并连接Linux的python环境 https://www.cnblogs.com/junxun/p/8287998.html wind ...

  4. windows下如何打开.sketch的文件

    1 .sketch的文件只能在苹果mac上支持的一种文件格式,现在越来越多的设计师喜欢用.sketch 2 windows下如果想打开.sketch文件,去Microsoft store 找一个Lun ...

  5. Windows下C++/Fortran调用.exe可执行文件

    目录 软件环境 Windows下CMake编译配置 设置项目的generator Command Line CMake GUI PreLoad.cmake 设置make 示例程序 CMake 设置Fo ...

  6. windows下python的tar.gz文件安装

    windows下下载了django,PIL,web.py发现都是tar.gz格式的文件,网上查找也非常系统的方法,总结一下其他大神的方法,归纳于此. 首先下载tar.gz文件,比如web.py,下载后 ...

  7. Linux如何下解压windows下的.zip和.rar文件

    Linux自带的unzip命令可以解压windows下的zip格式的压缩文件. 如何unzip没安装,可以yum 安装下: yum -y install unzip unzip命令 语法:unzip ...

  8. 转:Windows下用sftp自动下载文件

    远程服务器是Linux操作系统,没有ftp服务,可以ssh,数据库每天2:00会自动创建一个备份文件,本地计算机是windows操作系统,希望用sftp每天3:00下载远程服务器上的备份文件.本地系统 ...

  9. windows下使用 fdfs_client 上传文件

    在上一篇中介绍了使用 FastDFS 与 Nginx 在 Linux 系统上实现分布式图片服务器,现在介绍在 windows 系统下使用该分布式图片服务器. 需要安装 fdfs_client 模块和配 ...

  10. Windows下pipenv将虚环境文件的位置设置在项目根目录下

    在windows下使用pipenv shell时,虚拟环境文件夹会在C:\Users\Administrator\.virtualenvs\目录下默认创建,为了方便管理,将这个虚环境的文件的位置更改一 ...

随机推荐

  1. Java第三讲动手动脑

    1 以上代码无法通过编译主要是由于在Foo类中自定义了有参的构造函数,系统不在提供默认的构造函数(无参),而在上述的引用中并没有提供参数导致无法通过编译. 2. 运行结果 由运行结果分析可知,在运行时 ...

  2. Occlusion(遮挡剔除)

    Occlusion 1.视锥体剔除(Frustum Culling) 根据摄像机的视见体的范围对场景模型进行剔除操作,在视见体以外的物体不被渲染,但是在视见体中的物体会以离摄像机最远的物体开始渲染,逐 ...

  3. VSCode 自动编译 typescript 为 javascript

    1.我们默认你已经安装了node.js通过npm安装typescript npm install -g typescript 2.VSCode 里,点击"终端" "新建终 ...

  4. virtualbox装配fedora时,安装增强功能包时会报错解决

    virtualbox安装fedora时,安装增强功能包时会报错解决 Building the main GuestAdditions module [失败]安装前需要先安装下面几个包才可以避免这个问题 ...

  5. python-异常/文件/时间/随机数

    python-异常/文件/时间/随机数 def exception_test(): try: x = float(input("请输入被除数:")) y = float(input ...

  6. jquery实现多图片上传

    在做后台管理的时候,遇到这样一个需求,实现多张图片上传并按选中的顺序显示.PS:图片上传的时候是即时上传到服务器,后台返回图片在服务器上的地址,在最后点击提交按钮的时候,把地址传给后端写入数据库即可. ...

  7. win10多用户

    到https://github.com/stascorp/rdpwrap/releases下载 最新版文件(已经停更了,最新的版本是 v1.6.2) 下载后解压到 C:\Program Files\R ...

  8. java 实现Excel导入导出功能

    本文记录 首先需要准备一个导入模板的实体类 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn ...

  9. 【力扣】:N字型

    1 class Solution { 2 public String convert(String s, int numRows) { 3 String resultS = ""; ...

  10. 解决使用mapstruct过程中的一次编译报错问题_Internal error in the mapping processor

    说明 mapstruct版本:1.2.0.Final 开发工具:IntelliJ IDEA 2021.3.1 (Ultimate Edition) 报错现象 java: Internal error ...