GRIB学习笔记:GRIB2要素场转换为图片
目录
Web实时显示气象要素场一般有两种方式:
- 预先生成图片,叠加在底图上
- 加载远程数据,本地绘图
本文主要介绍第二个方法中加载远程数据的一种方法。
概述
GRIB2消息中保存的要素场一般使用JPEG压缩,我们常用的网格是等经纬度网格,数据是一个矩阵形式,因此GRIB2消息中的数据可以看成一张常规的图片。尽管目前尚缺乏有效的解码GRIB2数据的JavaScript库,但我们可以将GRIB2数据转成图片格式传给Web客户端,以图片的方式传递数据。
数据转换
将GRIB2要素场转换为图片,需要考虑如何转换实际数据为图片像素点的颜色值。
我们可以借鉴GRIB2存储数据的方式。为了保证数据的经度,GRIB2的数据段保存的不是实际的数据信息,而是使用一个公式计算后的结果。GRIB2数据的计算公式如下:
$$Y*D^{10}=R+(X1+X2)*2^E$$
其中
- Y:原始值
- D:十进制比例因子,为了获得需要的精确度。有符号十六位整数
- R:参考值,32位浮点数
- X:内部值,每个记录有自己的位数
- E:二进制比例因子,用于变长字长打包,有符号十六位整数
每个数据点只有Y和X值不同,所以数据段只存储X值,其他数值保存在数据描述段。
上面的公式比较复杂,在线绘图一般不需要很高的精度,所以可以将上面的公式简化。为了将数据转换为灰度图,将最大值最小值区间分成256份,每个数据值映射到这256个子区间。简化后的公式如下所示:
$$Y=(M_{2}-M_{1})*X/255+M_{1}$$
其中
- Y:原始值,浮点数
- M1:数据最小值,浮点数
- M2:数据最大值,浮点数
- X:像素点灰度值,整形
使用上述公式,就可以将GRIB2数据转为一张与网格大小相同的灰度图像。为了恢复原始数据,还需要知道M1,M2的值,因此将这些信息写入一个单独的JSON文件,与数据一同发送给客户端,由客户端负责从灰度值恢复原始数据。
实现
使用nuwe_pyeccodes
获取GRIB2要素场。下面代码中message_handler
代表一个要素场。
import numpy as np
left_lon = message_handler.getDouble('longitudeOfFirstGridPointInDegrees')
right_lon = message_handler.getDouble('longitudeOfLastGridPointInDegrees')
lon_step = message_handler.getDouble('iDirectionIncrementInDegrees')
nx = message_handler.getLong('Ni')
top_lat = message_handler.getDouble('latitudeOfFirstGridPointInDegrees')
bottom_lat = message_handler.getDouble('latitudeOfLastGridPointInDegrees')
lat_step = message_handler.getDouble('jDirectionIncrementInDegrees')
ny = message_handler.getLong('Nj')
values = message_handler.getDoubleArray('values')
values = values.reshape(ny, nx)
min_value = np.max(values)
max_value = np.min(values)
values = (values - min_value) / (max_value-min_value) * 255
使用PIL
生成图片文件
from PIL import Image
im = Image.fromarray(values)
im = im.convert("L")
im.save("t.png")
生成对应的JSON描述文件
import json
image_info = {
'min_value': min_value,
'max_value': max_value,
'left_lon': left_lon,
'right_lon': sright_lon,
'lon_step': lon_step,
'nx': nx,
'top_lat': top_lat,
'bottom_lat': bottom_lat,
'lat_step': lat_step,
'ny': ny
}
with open("{t.json"), "w") as f:
json.dump(image_info, f, indent=2)
效果
一个温度场的示例,灰度图像:
描述文件:
{
"min_value": 319.39718750000003,
"max_value": 233.5571875,
"left_lon": 0.0,
"right_lon": 359.75,
"lon_step": 0.25,
"nx": 1440,
"top_lat": 89.875,
"bottom_lat": -89.875,
"lat_step": 0.25,
"ny": 720
}