成信大ENVI_IDL第二周课堂内容:打开HDF4文件并读取文件以及简单的数据处理和保存+详细解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 成信大ENVI_IDL第二周课堂内容:打开HDF4文件并读取文件以及简单的数据处理和保存+详细解析

01 HDF4文件读取示例-数据信息查询

pro week_two_study1
  ; one ————》打开hdf文件以及获取数据集名称以及对应数据集的相关属性
  ; 1. 获取需要打开文件的路径并赋值给变量file_path
  file1_path = 'D:/MYD04_3K.A2018121.0545.061.2018121172155.hdf'
  ; 2. 打开文件————》hdf_sd_start()函数打开hdf4文件, 返回打开文件的id(这里用变量file_id接收)
  file1_id = hdf_sd_start(file1_path, /read)  ; 第一个参数传入文件路径, 第二个参数传入打开方式(/read表示只读, /rdwr表示读写, /create表示创建新文件)
  ; 3. 获取文件的数据集个数以及全局属性个数————》hdf_sd_fileinfo()函数获取文件的数据集以及全局属性个数
  hdf_sd_fileinfo, file1_id, file1_ds_num, file1_attr_num  ; 第一个参数传入文件地址即file1_id, 第二个传入变量file1_ds_num接收数据集个数, 第三个file1_attr_num接收属性个数
  ; 接下来, 由于数据集个数我们已经知道,所以我们可以通过循环获取数据集的信息(名称以及每个数据集的内部属性名称(如果它有内部属性的话))
  ; 4. 循环获取数据集信息
  for file1_ds_i = 0, file1_ds_num - 1 do begin  ; 由于索引是从0开始,所以数据集最大个数是file1_ds_num - 1
    ; file1_ds_i只是数据集的编号, 计算机不认识, 需要通过数据集的编号得到数据集在地层中的内存地址(或者说是id)
    ; 4.1 获取数据集的id————》通过hdf_sd_select()函数获取编号为file1_ds_i的数据集的id
    file1_ds_id = hdf_sd_select(file1_id, file1_ds_i)  ; 这里需要传入两个参数, 第一个就是数据集所在的文件的id(即file1_id), 第二个参数就是数据集的编号(即file1_ds_i)
    ; 4.2 获取数据集的名称以及其内部属性个数————》通过hdf_sd_getinfo函数获取
    hdf_sd_getinfo, file1_ds_id, name=file1_ds_name, natts=file1_ds_attr_num  ; 第一个参数传入数据集的id,后面 name,natts是函数内置的参数, =左边是接收的变量(和一般等号左边是变量不同) 
    ; 4.3 输出数据集名称
    ; 给出提示
    print, '数据集编号为' + strcompress(string(file1_ds_i)) + ':'
    ; 上面的string()函数是将long int型的文件数据集编号(file1_ds_i) 转化为str型, 另外strcompress()函数将多余的空位删掉,只在有效位数前面保留一个空位
    print, file1_ds_name
    ; 4.4 循环输出对应数据集的属性名称
    ; 
    ; 4.4.1 判断对应数据集属性个数是否为0, 如果为0则不进入循环输出
    if file1_ds_attr_num ne 0 then begin
      ; 4.4.2 循环开始进入循环
      for file1_ds_attr_i = 0, file1_ds_attr_num - 1 do begin  ; 类似地, 下标为0, 所以file1_ds_attr_num - 1
        ; 这里不需要根据数据集地属性编号获取数据集地id,因为下面输出属性时需要传入属性所在数据集的id
        ; 4.4.3 获取属性名称————》 hdf_sd_attrinfo函数获取属性的名称(其实还可以指定data=变量获取属性的信息而不只是属性名称)
        hdf_sd_attrinfo, file1_ds_id, file1_ds_attr_i, name=file1_ds_attr_name, data=file1_ds_attr_info
        ; 第一二个参数传入属性所在数据集的id,属性的编号,第三个函数内置参数name=需要接收的变量,第四个函数函数内置参数data=需要接收的变量
        ; 4.4.4 输出属性名称以及属性的内容
        print, file1_ds_attr_name + ':' + strcompress(string(file1_ds_attr_info))  ; 这里的string和strcompress函数和前面的类似就不赘述
      endfor
      ; 提示数据集的属性获取成功
      print, '——————获取数据集(' + file1_ds_name + ')的属性完毕!!!——————'
    endif
    ; 关闭打开的专题数据集,避免占用内存资源以及下次使用出现错误————》使用hdf_sd_endaccess函数关闭需要关闭的数据集
    hdf_sd_endaccess, file1_ds_id  ; 传入需要关闭数据集的内存地址即id(在哪个循环里, 那么哪个循环一开始就会打开该数据集(hdf_sd_select()),那么现在使用完毕就需要关闭该文件)
    ; 提示该数据集的全部信息全部获取成功
    print, '——————获取数据集(' + file1_ds_name + ')相关信息完毕!!!——————'
  endfor
  ; 关闭打开的hdf4文件——————》使用hdf_sd_end函数关闭文件
  hdf_sd_end, file1_id  ; 传入需要关闭文件的内存地址即id
  ; 提示该文件的信息全部获取成功
  print, '——————获取文件的相关信息完毕——————'
end


02 HDF4文件读取示例-目标数据TIFF输出

 

pro week_two_study2
  ; 本次程序需要完成的是: 便捷打开hdf4文件以及读取相关内容并做一些简单的处理输出tif影像
  ; 
  ; 
  ; 打开文件的路径
  modis_load_path = 'D:\IDL编程设计\实验数据\chapter_1\MODIS_2018_mod04_3k\MYD04_3K.A2018121.0545.061.2018121172155.hdf'
  modis_save_path = 'D:\IDL编程设计\实验数据\chapter_1\MODIS_2018_mod04_3k\MYD04_3K.A2018121.0545.061.2018121172155.tif'
  ; 打开文件————》使用hdf_sd_start()函数打开文件
  modis_id = hdf_sd_start(modis_load_path, /read)  ; 传入需要打开文件的路径以及读取的方式(/read, /rewr, /create三种), 返回文件的内存地址即id
  ; 通过HDF explorer读取到hdf4文件的相关内容,所以不再需要循环知道内部具体名字之类的信息了
  ; 读取的需要的数据集的名称
  modis_ds = 'Latitude'
  ; 获取数据集的index————》通过hdf_sd_nametoindex获取数据集的indedx(或者说是数据集的编号, 索引从0开始)
  modis_ds_index = hdf_sd_nametoindex(modis_id, modis_ds)  ; 第一个参数传入该数据集所在文件的内存地址(即id), 第二个参数传入该数据集的名称, 返回该数据集的索引或者说是编号
  ; 获取数据集的内存地址(即id)————》通过hdf_sd_select()函数获取数据集的内存地址
  modis_ds_id = hdf_sd_select(modis_id, modis_ds_index)  ; 第一个参数传入该数据集所在文件的id, 第二个参数传入该数据集的index
  ; 获取该数据集的数据————》通过hdf_sd_getdata() 获取该数据集的相关数据
  hdf_sd_getdata, modis_ds_id, modis_lat_data  ; 第一个参数传入该数据集的内存地址, 第二个传入的是变量, 用来接收该数据集的数据
  ; 类似, 这里还需要读取Longitude数据集、Image_Optical_Depth Land And Ocean数据集, 这里不再详述
  ; 获取Longitude数据集的数据
  modis_ds = 'Longitude'
  modis_ds_indedx = hdf_sd_nametoindex(modis_id, modis_ds)
  modis_ds_id = hdf_sd_select(modis_id, modis_ds_index)
  hdf_sd_getdata, modis_ds_id, modis_lon_data
  ; 获取Image_Optical_Depth Land And Ocean数据集的数据
  modis_ds = 'Image_Optical_Depth Land And Ocean'
  modis_ds_index = hdf_sd_nametoindex(modis_id, modis_ds)
  modis_ds_id = hdf_sd_select(modis_id, modis_ds_index)
  hdf_sd_getdata, modis_ds_id, modis_target_data
  ; 另外,由于对modis_target_data进行处理还需要该数据集下的两个属性
  ; 获取属性内容(这里我们依旧通过HDF explorer软件获取了该数据集下的两个属性的名字)
  ; 获取该数据集下属性scale_factor的索引(或者说是编号)——————》通过函数hdf_sd_attrfind()函数获取该属性的索引
  modis_att_index = hdf_sd_attrfind(modis_ds_id, 'scale_factor')  ; 第一个参数传入该属性所在的数据集的id, 第二个参数传入该属性的名称
  hdf_sd_attrinfo, modis_ds_id, modis_att_index, data=sf  ; 第一个参数传入该属性所在数据集的id, 第二个参数传入该属性的index, 第三个传入的是变量, 用来接收该属性的内容
  ; 另外还要注意的是, 得到的数据一般是数组, 所以这里得到sf也是数组
  ; 类似的,获取属性_FillValue的内容, 这里不再详述
  modis_att_index = hdf_sd_attrfind(modis_ds_id, '_FillValue')
  hdf_sd_attrinfo, modis_ds_id, modis_att_index, data=fv
  ; 使用完毕后需要关闭文件,这是习惯!!
  hdf_sd_endaccess, modis_ds_id  ; hdf_sd_endaccess函数关闭数据集, 传入该数据集的内存地址即可
  hdf_sd_end, modis_id  ; hdf_sd_end函数关闭文件, 传入该文件的内存地址即可
  ; 最后,对取出的modis_target_data, sf, fv进行处理
  modis_target_data = (modis_target_data ne fv[0]) * modis_target_data  * sf[0]
  ; 上面有两个点需要注意, 第一个fv和sf是数组, 虽然它们只有一个数,但是要取第一个数就需要加上[], 不然就会变成数组相乘
  ; 第二个, 这里有modis_targte_data得到是什么反射率还是什么, 有一些是观测时有云层遮挡所以无法观测所以填充的是属性_FillValue的值,
  ; 还有存储的时候由于整数存储相对于浮点数存储节省空间, 所以这里还将反射率(假设我们获取的是反射率, 我没有学, 这个)乘以了某一个数使所有的观测
  ; 数据都为int型或long型, 而这里的scale_factor就是这个数的倒数, 所以我们上面这个等式实际上就是将真实的观测数据计算出来
  ; 这里我们让等于fillvalue的数据等于0
  ; 将计算得到的真实数据保存
  write_tiff, modis_save_path, modis_target_data, /float  ; 另外要注意, 这里我们得到的是float型(因为sf是float型)的,所以保存格式应该指定为/float, 默认是int型
end


03 题外话

3.1 问题的出现

十分遗憾, 我的电脑由于某些原因, 无法运行这两个文件, 已经试过多种方法。

错误原因如下:

HDF_SD_START: Unable to start the HDF-SD interface.

IDL> .compile -v 'E:\IDL_workspace\Study\week_two_study2.pro'
% Compiled module: WEEK_TWO_STUDY2.
IDL> week_two_study2
% Compiled module: WEEK_TWO_STUDY2.
% HDF_SD_START: Unable to start the HDF-SD interface.
% Execution halted at: WEEK_TWO_STUDY2    10 E:\IDL_workspace\Study\week_two_study2.pro
%                      $MAIN$    

如果你的电脑也发生这种情况, 那么请告知我, 谢谢。

3.2 问题的解决

2022-7-6补:

现在已经解决了

<如果你也遇到这个问题,那么有可能该文件下载出现问题或者解压等出现问题导致该文件无法打开>


1. 一开始我以为时中文路径的原因,后来将路径修改后发现不是中文路径的缘故,而且中文路径IDL是可以的

2. 后来我以为是代码的一些拼写错误之类,后来认真检查了,发现不是。

3. 后来我以为是ENVI破解不成功,于是重装了,发现也不是

4. 在后来我以为是自身电脑品牌以及windows版本的缘故,所以我创建了虚拟机,发现不是。

以上总共花费我一个下午以及一个晚上的时间

5.最后发现是bandzip解压我的modis文件时出现了一个失误,第一个modis文件的没解压出来, 只是一个空文件。之前的所有测试都是基于第一个文件进行的。fuck!


目录
相关文章
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
77 2
|
2月前
|
Java
Java“解析时到达文件末尾”解决
在Java编程中,“解析时到达文件末尾”通常指在读取或处理文件时提前遇到了文件结尾,导致程序无法继续读取所需数据。解决方法包括:确保文件路径正确,检查文件是否完整,使用正确的文件读取模式(如文本或二进制),以及确保读取位置正确。合理设置缓冲区大小和循环条件也能避免此类问题。
491 2
|
2月前
|
SQL 关系型数据库 MySQL
数据库导入SQL文件:全面解析与操作指南
在数据库管理中,将SQL文件导入数据库是一个常见且重要的操作。无论是迁移数据、恢复备份,还是测试和开发环境搭建,掌握如何正确导入SQL文件都至关重要。本文将详细介绍数据库导入SQL文件的全过程,包括准备工作、操作步骤以及常见问题解决方案,旨在为数据库管理员和开发者提供全面的操作指南。一、准备工作在导
515 0
|
2月前
|
自然语言处理 数据处理 Python
python操作和解析ppt文件 | python小知识
本文将带你从零开始,了解PPT解析的工具、工作原理以及常用的基本操作,并提供具体的代码示例和必要的说明【10月更文挑战第4天】
499 60
|
1月前
|
消息中间件 存储 Java
RocketMQ文件刷盘机制深度解析与Java模拟实现
【11月更文挑战第22天】在现代分布式系统中,消息队列(Message Queue, MQ)作为一种重要的中间件,扮演着连接不同服务、实现异步通信和消息解耦的关键角色。Apache RocketMQ作为一款高性能的分布式消息中间件,广泛应用于实时数据流处理、日志流处理等场景。为了保证消息的可靠性,RocketMQ引入了一种称为“刷盘”的机制,将消息从内存写入到磁盘中,确保消息持久化。本文将从底层原理、业务场景、概念、功能点等方面深入解析RocketMQ的文件刷盘机制,并使用Java模拟实现类似的功能。
42 3
|
1月前
|
存储
文件太大不能拷贝到U盘怎么办?实用解决方案全解析
当我们试图将一个大文件拷贝到U盘时,却突然跳出提示“对于目标文件系统目标文件过大”。这种情况让人感到迷茫,尤其是在急需备份或传输数据的时候。那么,文件太大为什么会无法拷贝到U盘?又该如何解决?本文将详细分析这背后的原因,并提供几个实用的方法,帮助你顺利将文件传输到U盘。
|
2月前
|
数据安全/隐私保护 流计算 开发者
python知识点100篇系列(18)-解析m3u8文件的下载视频
【10月更文挑战第6天】m3u8是苹果公司推出的一种视频播放标准,采用UTF-8编码,主要用于记录视频的网络地址。HLS(Http Live Streaming)是苹果公司提出的一种基于HTTP的流媒体传输协议,通过m3u8索引文件按序访问ts文件,实现音视频播放。本文介绍了如何通过浏览器找到m3u8文件,解析m3u8文件获取ts文件地址,下载ts文件并解密(如有必要),最后使用ffmpeg合并ts文件为mp4文件。
|
2月前
|
存储 搜索推荐 数据库
运用LangChain赋能企业规章制度制定:深入解析Retrieval-Augmented Generation(RAG)技术如何革新内部管理文件起草流程,实现高效合规与个性化定制的完美结合——实战指南与代码示例全面呈现
【10月更文挑战第3天】构建公司规章制度时,需融合业务实际与管理理论,制定合规且促发展的规则体系。尤其在数字化转型背景下,利用LangChain框架中的RAG技术,可提升规章制定效率与质量。通过Chroma向量数据库存储规章制度文本,并使用OpenAI Embeddings处理文本向量化,将现有文档转换后插入数据库。基于此,构建RAG生成器,根据输入问题检索信息并生成规章制度草案,加快更新速度并确保内容准确,灵活应对法律与业务变化,提高管理效率。此方法结合了先进的人工智能技术,展现了未来规章制度制定的新方向。
50 3
|
2月前
|
存储 机器学习/深度学习 数据可视化
解析exe文件
如何使用`objdump`工具解析exe文件,包括exe文件的组成、`objdump`的用法以及如何查看exe文件的节头信息和完整内容。
107 0
解析exe文件
|
2月前
|
Java 编译器
解析用GraalVm编译的class文件
这篇文章介绍了如何使用`javap`工具反编译由GraalVM编译的`.class`文件,详细展示了`javap`的用法和输出内容,包括类声明、版本信息、访问标志、类层次结构、接口、字段、方法、属性以及常量池等信息。
34 0
解析用GraalVm编译的class文件

热门文章

最新文章

推荐镜像

更多