将numpy数组保存为二进制文件以便从FORTRAN读取

4

我有一系列numpy数组,需要在循环中将这些numpy数组保存为原始二进制float32格式(不包含任何头部信息),这需要从FORTRAN中读取。

import numpy as np
f=open('test.bin','wb+')
for i in range(0,10):
    np_data=np.random.rand(10,5)
    fortran_data=np.asfortranarray(np_data,'float32')
  fortran_data.tofile(f)

f.close()

这是我以正确方式读取由Python创建的二进制文件,以便在FORTRAN中正确读取吗?非常感谢您的建议。


2
netCDF库可能值得一看,http://www.unidata.ucar.edu/software/netcdf/examples/programs/ - J.J. Hakala
2
这段代码能正常工作吗?我认为 tofile 是数组的一个方法,而不是文件。无论如何,在 Fortran 中你肯定可以使用 access=streamform=unformatted 打开文件并读取原始二进制数据。 - agentp
现在我不确定问题是什么。这种简单方法有一些缺点,特别是数据类型/维度没有编码在文件中,因此读取程序需要硬编码以读取10个10x5浮点数组等等。(这不是Fortran的问题,如果您想要读回Python也是一样的)另外,请注意将二进制文件移动到不同系统时可能会出现可移植性问题。 - agentp
2个回答

4
你写的代码几乎正确,但是`.tofile`方法总是按C顺序写入向量。我不知道为什么`np.asfortranarray()`在写入二进制文件时可以避免这个问题,但是我进行了测试,不幸的是我们需要在写入之前转置矩阵以便在Fortran中正确读取而不需要任何其他考虑(这意味着在Fortran中你可以给出实际的矩阵维度而不需要任何转置)。下面的代码是为了说明我所说的,使用一个三维矩阵(我通常需要使用):
a = np.arange(1,10*3*4+1)
b = a.reshape(10,12,order='F')
array([[  1,  11,  21,  31,  41,  51,  61,  71,  81,  91, 101, 111],
   [  2,  12,  22,  32,  42,  52,  62,  72,  82,  92, 102, 112],
   [  3,  13,  23,  33,  43,  53,  63,  73,  83,  93, 103, 113],
   [  4,  14,  24,  34,  44,  54,  64,  74,  84,  94, 104, 114],
   [  5,  15,  25,  35,  45,  55,  65,  75,  85,  95, 105, 115],
   [  6,  16,  26,  36,  46,  56,  66,  76,  86,  96, 106, 116],
   [  7,  17,  27,  37,  47,  57,  67,  77,  87,  97, 107, 117],
   [  8,  18,  28,  38,  48,  58,  68,  78,  88,  98, 108, 118],
   [  9,  19,  29,  39,  49,  59,  69,  79,  89,  99, 109, 119],
   [ 10,  20,  30,  40,  50,  60,  70,  80,  90, 100, 110, 120]])
B已经按照Fortran的顺序排列了
c=b.reshape(10,3,4, order='F')
print(c[:,:,0])
[[ 1 11 21]
 [ 2 12 22]
 [ 3 13 23]
 [ 4 14 24]
 [ 5 15 25]
 [ 6 16 26]
 [ 7 17 27]
 [ 8 18 28]
 [ 9 19 29]
 [10 20 30]]

然后我将矩阵 c 保存到二进制文件中:
c.T.tofile('test_c.bin')

因此,使用这个Fortran代码,我能够按正确的顺序读取二进制数据,然后在Python中创建了c矩阵:

PROGRAM read_saved_python
IMPLICIT NONE

INTEGER(KIND=8),ALLOCATABLE :: matrix(:,:,:)
INTEGER :: Nx, Ny, Nz

Nx = 10
Ny = 3
Nz = 4


ALLOCATE(matrix(Nx, Ny, Nz))


OPEN(33, FILE="/home/victor/test_c.bin",&
     FORM="UNFORMATTED", STATUS="UNKNOWN", ACTION="READ", ACCESS='STREAM')

READ(33) matrix


write(*,*) matrix(:,1,1)


CLOSE(33)
DEALLOCATE(matrix)

END PROGRAM read_saved_python

注意,在Fortran中索引从1开始,并且print按列顺序显示(在这种情况下:先打印第一列,然后是第二列,最后是第三列)。如果您不在此处转置矩阵c.T.tofile('test_c.bin'),当在Fortran中读取时,您会注意到矩阵不是您想要的,即使您使用了函数np.asfortranarray(就像您所做的那样),但是矩阵仍以c顺序写入二进制文件中。

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接