从Python

时间:2016-03-31 08:03:04

标签: python binary fortran

我需要读取一个名为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

不幸的是,我不习惯二进制文件...

如何从此文件中获取第二条记录(半小时)?

1 个答案:

答案 0 :(得分:4)

通过阅读dataset description并使用dataset进行测试,很明显该文件是一个(压缩的)Fortran直接访问文件,其中包含2个大小为(9896, 3298)的IR数据记录缩减通过从值中减去75来拟合1个字节。目前尚不清楚结果字节是无符号还是有符号,因为我没有使用GrADS控件定义的经验。

numpy.fromfileeasily reading binary Fortran direct-access files的工具。

使用int8uint8作为 dtype 来构建记录data type object,检查哪一个有意义。对于 例如,如果数据是开尔文的IR温度,则使用uint8 缩放后得到最小值186和最大值330(〜-87°C至56.8°C)。 Upcast到足够大的类型用于升级,在这里使用float可能是 int16int32等。

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)