我需要读取一个名为merg_2015041312_4km-pixel.Z
(来自here)的python的Fortran二进制文件,它被压缩;未压缩文件的结构定义为here。定义说
每个文件包含2条记录:第1小时为"小时"图像(":00")和第二个#34;半小时"图像(":30")。
和
每条记录都是9896 x 3298 Fortran红外线亮度温度阵列,通过减去" 75"来缩放到1字节。来自每个数据。
GrADS .ctl文件说明:
DSET merg_1999042012_4km-pixel
OPTIONS yrev little_endian template
UNDEF 330
TITLE globally merged IR data
XDEF 9896 LINEAR 0.0182 0.036378335
YDEF 3298 LINEAR -59.982 0.036383683
ZDEF 01 LEVELS 1
TDEF 99999 LINEAR 12z04Apr1999 30mn
VARS 1
ch4 1 -1,40,1,-1 IR BT (add '75' to this value)
ENDVARS
我尝试编写一些python代码:
>>> import struct
>>> file = open("merg_2015041312_4km-pixel", 'rb')
>>> data = struct.unpack('>h', file.read())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
struct.error: unpack requires a string argument of length 2
不幸的是,我不习惯二进制文件...
如何从此文件中获取第二条记录(半小时)?
答案 0 :(得分:4)
通过阅读dataset description并使用dataset进行测试,很明显该文件是一个(压缩的)Fortran直接访问文件,其中包含2个大小为(9896, 3298)
的IR数据记录缩减通过从值中减去75来拟合1个字节。目前尚不清楚结果字节是无符号还是有符号,因为我没有使用GrADS控件定义的经验。
numpy.fromfile
是easily reading binary Fortran direct-access files的工具。
使用int8
或uint8
作为 dtype 来构建记录data type object,检查哪一个有意义。对于
例如,如果数据是开尔文的IR温度,则使用uint8
缩放后得到最小值186和最大值330(〜-87°C至56.8°C)。
Upcast到足够大的类型用于升级,在这里使用float
可能是
int16
,int32
等。
H = 9896
W = 3298
Record = np.dtype(('uint8', H*W))
A = np.fromfile('merg_2015041312_4km-pixel',
dtype=Record, count=2).astype('float') + 75
必须将生成的1d阵列重新整形以校正尺寸和形状。数据类型对象将支持子数组,但它们是always read in C-contiguous memory layout。
I_on_the_hour = A[0].reshape((H, W), order='F') # Fortran data order
I_on_the_half_hour = A[1].reshape((H, W), order='F')
检查结果是否合理(ipython --pylab
)
plt.imshow(I_on_the_half_hour)