numpy - 用 Python 读取 Fortran 二进制文件

标签 numpy io scipy fortran binaryfiles

我在 Python 中读取未格式化的 F77 二进制文件时遇到问题。
我试过 SciPy.io.FortraFile方法和 NumPy.fromfile方法,都无济于事。我还阅读了 IDL 中的文件,该文件有效,因此我有一个关于数据应该是什么样子的基准。我希望有人能指出我的一个愚蠢的错误——没有什么比度过一个白痴时刻然后洗手更好的了……

数据 bcube1 的尺寸为 101x101x101x3,并且是 r*8 类型。共有 3090903 个条目。它们是使用以下语句编写的(不是我的代码,从源代码复制)。

open (unit=21, file=bendnm, status='new'
.     ,form='unformatted')
write (21) bcube1
close (unit=21)

我可以使用以下内容在 IDL 中成功读取它(也不是我的代码,从同事那里复制的):
bcube=dblarr(101,101,101,3)
openr,lun,'bcube.0000000',/get_lun,/f77_unformatted,/swap_if_little_endian
readu,lun,bcube
free_lun,lun

返回的数据 (bcube) 是 double 的,尺寸为 101x101x101x3,因此文件的标题信息知道其尺寸(不是扁平化)。

现在我尝试使用 Python 获得相同的效果,但没有运气。我尝试了以下方法。
In [30]: f = scipy.io.FortranFile('bcube.0000000', header_dtype='uint32')
In [31]: b = f.read_record(dtype='float64')

返回错误 Size obtained (3092150529) is not a multiple of the dtypes given (8) .更改 dtype 会更改获得的大小,但它仍然不能被 8 整除。

或者,使用 fromfile结果没有错误,但返回数组中的另一个值(也许是页脚?),并且单个数组值非常错误(都应该是统一的)。
In [38]: f = np.fromfile('bcube.0000000')
In [39]: f.shape
Out[39]: (3090904,)
In [42]: f
Out[42]: array([ -3.09179121e-030,   4.97284231e-020,  -1.06514594e+299, ...,
         8.97359707e-029,   6.79921640e-316,  -1.79102266e-037])

我试过使用 byteswap 来查看这是否使浮点值更合理,但事实并非如此。

在我看来,np.fromfile方法非常接近工作,但它读取标题信息的方式一定有问题。任何人都可以建议我如何找出头文件中允许 IDL 了解数组维度和数据类型的内容吗?有没有办法将标题信息传递给 fromfile以便它知道如何对待领先的条目?

最佳答案

我玩了一下,我想我有一个想法。

Fortran 存储未格式化数据的方式没有标准化,因此您必须尝试一下,但您需要三条信息:

  • 数据的格式。您建议使用 64 位实数,或 Python 中的“f8”。
  • header 的类型。这是一个无符号整数,但您需要以字节为单位的长度。如果不确定,请尝试 4。

    头部通常以字节为单位存储记录的长度,并在末尾重复。

    再说一次,它不是标准化的,所以没有保证。
  • 字节序,或大或小。

    从技术上讲,对于标题和值,但我认为它们是相同的。

    Python 默认为 little endian,所以如果这是您数据的正确设置,我想您已经解决了。

  • 当您使用 scipy.io.FortranFile 打开文件时,你需要给出头部的数据类型。因此,如果数据存储为 big_endian,并且您有一个 4 字节的无符号整数 header ,则您需要:
    from scipy.io import FortranFile
    ff = FortranFile('data.dat', 'r', '>u4')
    

    读取数据时,需要值的数据类型。同样,假设 big_endian,您需要输入 >f8 :
    vals = ff.read_reals('>f8')
    

    here用于数据类型语法的描述。

    如果您可以控制写入数据的程序,我强烈建议您将它们写入数据流中,这样 Python 更容易读取。

    关于numpy - 用 Python 读取 Fortran 二进制文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53639058/

    相关文章:

    python - 如何在 scipy.integrate.simps 或 numpy.trapz 之间做出选择?

    python-3.x - 按降序对两列最频繁的组合进行排序

    java - 将数据文件的内容读入内存中适当的对象数组中

    c - 用模数在 C 中移动字符,输出到文件在一个输入上产生不受支持的文件格式,在另一个输入上产生 txt 文件

    python - 奇怪的 "symbolic boolean expression has no truth value"错误 - 这是 SymPy 中的错误吗?

    python - 用于计算向量在不同点拆分的方差的向量化

    python - 从函数式语言访问 numpy 数组

    c - 在 C 中写入、读取和拆分文件

    python - scipy,对数正态分布 - 参数

    python - 将级别值存储在等值线图中