常用水文气象数据读取及其可视化(二进制、HDF5、NetCDF)--以GLDAS、MODIS、GSMaP为例

前言

地学、水文、气象领域的自然科学数据通常以netcdf、hdf、二进制等方式存储,比如温度、降水、蒸发数据等;学会这些数据格式的读取和可视化是进行地学统计分析计算的关键,python提供了解析nc、hdf等数据格式的库,作者整理了如何利用python进行.nc、.hdf、*.dat格式数据的读取并进行栅格转换,欢迎转载和关注!

arcpy读取二进制文件---以GSMaP降水数据集为例

温度、降水、蒸发等科学数据为了达到压缩文件大小,易于存储和维护等目的,通常在下载后往往以二进制.bin、.dat等方式呈现。因此在进行数据分析和统计计算时需要读取二进制文件进行数据还原。

注意: 读取二进制文件要特别要注意到 二进制文件数据存储的端序问题(字节序),小端序需要进行端序转换!

  • 本地文件夹下存在2018年6月份前10天的日尺度降水数据集,下面利用arcoy脚本将该数据批量转换为tiff栅格影像,并在arcmap中展示。
image

代码展示

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Name   : gsmap2TIFF.py
# Author : zengsk in NanJing
# Created: 2019/8/24 23:26

'''
说明:1.该脚本是读取gsmap小时尺度降水数据,输出为tiff
    2.运行环境需要安装python2 需要arcpy模块
    3.使用arcgis自带的python环境(有arcpy模块)
    4.运行结果可以直接用arcgis打开
'''

# 导入module
import os
import glob
import numpy as np
import arcpy
import warnings

warnings.simplefilter("ignore") # 忽略警告

# 原始降水数据文件夹,可根据自己本地情况修改
sPath = r'H:\test\gsmap'
oDir = r"H:\test\res"

for fileName in glob.glob(sPath+'\*.dat'):
    print("Processing... {0}".format(fileName))
    ds = np.fromfile(fileName, dtype=np.float32)
    ds = np.resize(ds,[1200,3600])
    ds[ds < 0] = -999.00
    ds[np.isnan(ds)] = -999.00 # NODATA_value
    
    # 输出为TIFF(注意:要用到arcpy模块)
    if not os.path.exists(oDir):
        os.makedirs(oDir)
    TiffName = oDir + os.sep + os.path.basename(fileName)[0:-4] + '.tif' # 输出文件名(可根据实际情况改)
    # arcpy.NumPyArrayToRaster()不清楚输入参数可以查看arcpy的官方文档
    # 矩阵转为栅格
    raster = arcpy.NumPyArrayToRaster(ds, arcpy.Point(0, -60.0),
                    x_cell_size=0.1, y_cell_size=0.1, value_to_nodata=-999.00)
    # 添加地理坐标系 GCS_WGS_1984
    spatialRef = arcpy.SpatialReference(4326)
    arcpy.DefineProjection_management(raster, spatialRef)
    raster.save(TiffName)

print("\n++++++ Data Processing Successfully Completed ! ++++++")

处理结果

image

arcmap中展示

image

NetCDF(*.nc)文件转GeoTIFF---以GLDAS路面蒸发数据为例

在地学领域,nc格式的文件可谓随处可见,netCDF文件可以存储多维数字矩阵,同时又封装了自描述信息(例如经纬度、高度层、时间戳、单位等)。nc文件的IO接口也很普及,Python、NCL、Matlab等气象上常用的软件都可以对其进行读写操作。用Python对nc文件的读写操作是使用Python进行气象数据分析最基础的部分之一。

  • 基于Python处理nc数据必要的库是netCDF4,同时如果需要将nc文件转换为tiff文件,还需要osgeo库中的gdal子库和osr子库。**

  • 下面以GLDAS全球陆地蒸发数据为例,展示如何利用python读取nc文件并将数据转换为geotiff文件。

源码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Name   : gldas2tiff.py
# Author : zengsk in NanJing
# Created: 2020/5/13 17:02

"""
Details:   读取GLDAS_NOAH025的蒸发数据(netcdf格式)并转为Tiff栅格影像
"""

import netCDF4 as nc
from osgeo import gdal, osr
import numpy as np


# ('Evap_tavg', <class 'netCDF4._netCDF4.Variable'>
# float32 Evap_tavg(time, lat, lon)
#     units: kg m-2 s-1
#     standard_name: water_evaporation_flux
#     long_name: Evapotranspiration
#     cell_methods: time: mean
#     scale_factor: 1.0
#     add_offset: 0.0
#     missing_value: -9999.0
#     _FillValue: -9999.0
#     vmin: -1.8462154e-06
#     vmax: 7.190982e-05
# unlimited dimensions: time
# current shape = (1, 600, 1440)
# filling off
# )


def nc2tiff(nc_url, var='Evap_tavg', save_name='./nc2tiff.tif'):
    """
    :param nc_url:  netcdf文件的路径
    :param var:   读取nc文件的变量名称, 默认 Evap_tavg
    :param save_name:  输出tiff文件的保存路径
    :return:
    """
    print(nc_url)
    nc_fp = nc.Dataset(nc_url)
    # 查看属性
    print(nc_fp)
    # # 查看变量
    print(nc_fp.variables)
    # 获取var数据集
    evap = nc_fp.variables[var][:]  # 单位转换 kg m-2 s-1
    evap = np.array(evap)
    evap = np.squeeze(evap)
    # missing value 处理
    fillvalue = nc_fp.variables[var].missing_value
    evap[evap == fillvalue] = np.nan
    evap = evap * 3600 * 24 * 30
    array2raster(evap, 0.25, 0.25, [-180, -60], save_name)


# 数据矩阵转tiff文件
def array2raster(array, xsize, ysize, rasterOrigin, newTiffName):
    """
     array: 计算后的栅格数据
     xsize: x方向像元大小
     ysize: y方向像元大小
     rasterOrigin: 原始栅格数据Extent
     newRasterfn: 输出tif路径
    """
    cols = array.shape[1]  # 矩阵列数
    rows = array.shape[0]  # 矩阵行数
    originX = rasterOrigin[0]  # 起始像元经度
    originY = rasterOrigin[1]  # 起始像元纬度
    driver = gdal.GetDriverByName('GTiff')
    outRaster = driver.Create(newTiffName, cols, rows, 1, gdal.GDT_Float32)
    # 设置仿射矩阵参数(左上角X坐标; X方向分辨率; 旋转角度,如果图像北方朝上,该值为0; 左上角Y坐标; 旋转角度; y方向分辨率)
    outRaster.SetGeoTransform((originX, xsize, 0, originY, 0, ysize))
    # 获取数据集第一个波段,是从1开始,不是从0开始
    outband = outRaster.GetRasterBand(1)
    outband.WriteArray(array)
    spatialRef = osr.SpatialReference()
    # 代码4326表示WGS84坐标
    spatialRef.ImportFromEPSG(4326)
    outRaster.SetProjection(spatialRef.ExportToWkt())
    outband.FlushCache()
    outRaster.FlushCache()


# 主函数
if __name__ == '__main__':
    netcdf_url = r'E:\Scripts\Test\GLDAS_NOAH025_M.A200002.021.nc4'
    nc2tiff(netcdf_url, "Evap_tavg", save_name='E:\Scripts\Test\evap2tiff.tif')

    print("\n++++++ Data Processing Successfully Completed ! ++++++")

结果在arcmap中显示

image

读取hdf文件(*.hdf)并转为tif文件---以MODIS地面温度数据为例

HDF文件是地学研究中常用的数据格式,卫星数据的储存格式通常如此。下面以MODIS 16A3 地表温度数据为例,进行LST数据的读取和TIFF格式转换。

  • 利用python读取hdf文件需要用的pyhdf库,lst数据转换为geotiff文件则采用GDAL库

源码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Name   : modis2tiff.py
# Author : zengsk in NanJing
# Created: 2020/5/17 20:28

"""
Details:
"""

from pyhdf import SD
from osgeo import gdal, osr
import numpy as np


def hdf2tiff(hdf_url, variable, save_name="./hdf2tiff.tiff"):
    fp = SD.SD(hdf_url)
    for idx, sds in enumerate(fp.datasets().keys()):
        print(idx, sds)
    # print(fp.select(variable).attributes())
    lst = fp.select(variable).get()
    lst[lst == -9999.0] = np.nan
    lst -= 273.15  # 转换为摄氏度
    array2raster(lst, 1.0, -1.0, [-180, 90], save_name)


def array2raster(array, xsize, ysize, rasterOrigin, newTiffName):
    """
     array: 计算后的栅格数据
     xsize: x方向像元大小
     ysize: y方向像元大小
     rasterOrigin: 原始栅格数据Extent
     newRasterfn: 输出tif路径
    """
    cols = array.shape[1]  # 矩阵列数
    rows = array.shape[0]  # 矩阵行数
    originX = rasterOrigin[0]  # 起始像元经度
    originY = rasterOrigin[1]  # 起始像元纬度
    driver = gdal.GetDriverByName('GTiff')
    outRaster = driver.Create(newTiffName, cols, rows, 1, gdal.GDT_Float32)
    # 设置仿射矩阵参数(左上角X坐标; X方向分辨率; 旋转角度,如果图像北方朝上,该值为0; 左上角Y坐标; 旋转角度; y方向分辨率)
    outRaster.SetGeoTransform((originX, xsize, 0, originY, 0, ysize))
    # 获取数据集第一个波段,是从1开始,不是从0开始
    outband = outRaster.GetRasterBand(1)
    outband.WriteArray(array)
    spatialRef = osr.SpatialReference()
    # 代码4326表示WGS84坐标
    spatialRef.ImportFromEPSG(4326)
    outRaster.SetProjection(spatialRef.ExportToWkt())
    outband.FlushCache()


if __name__ == '__main__':
    hdf_url = r'E:\Scripts\Test\LST\MOD11CM1_v005_day___lst_2000m03.hdf'
    hdf2tiff(hdf_url, "day_lst", save_name=r'E:\Scripts\Test\LST_TIFF2.tif')
    print("\n++++++ Data Processing Successfully Completed ! ++++++")

image

处理结果在arcmap中显示

image
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容