我是Python的新手,我正在从头开始用Python编写可视化代码(以避免使用昂贵的专有程序,如IDL)。到目前为止,我已经使用过IDL和gnuplot。我想要做的是:
我使用fortran将二维数组写入未格式化的直接访问文件,我希望能够在python中读取。确切的测试代码如下。实际代码是一个巨大的并行代码,但数据输出几乎完全相同的格式。
program binary_out
implicit none
integer :: i,j,t,rec_array
double precision, dimension(100,100) :: fn
double precision, parameter :: p=2*3.1415929
INQUIRE(IOLENGTH=rec_array) fn
open(unit=10,file='test',status='new',form='unformatted',access='direct',recl=rec_array)
fn=0
write(10,rec=1) fn
do t=1,3
do i=1,100
do j=1,100
fn(i,j)=sin(i*p*t/100)*cos(j*p*t/100)
enddo
enddo
write(10,rec=t+1) fn
enddo
close(10)
end program binary_out
该程序应该给我t = 1的零和增加“岛”的数量以增加t的值。但是当我使用下面给出的python代码读取它时,我只是得到了零。如果我删除第一个零的写语句,我只是得到第一次切片,而不管我在python代码中使用的“timeslice”的值。我到目前为止的代码是:
#!/usr/bin/env python
import scipy
import glob
import numpy as np
import matplotlib.pyplot as plt
import os, sys
from pylab import *
def readslice(inputfilename,field,nx,ny,timeslice):
f=open(inputfilename,'r')
f.seek(timeslice*nx*ny)
field=np.fromfile(inputfilename,dtype='d',count=nx*ny)
field=np.reshape(field,(nx,ny))
return field
a=np.dtype('d')
a=readslice('test',a,100,100,2)
im=plt.imshow(a)
plt.show()
如果时间片等于i,我希望def readlice能够在第i个位置读取记录。为此,我试图使用f.seek,但它似乎不起作用。 numpy.fromfile似乎开始从第一个记录本身读取。如何让numpy.fromfile从文件中的特定点读取?
我仍然在尝试熟悉Python风格并深入研究文档。任何帮助和指示将不胜感激。
答案 0 :(得分:6)
这是一个适合你的python代码:
def readslice(inputfilename,nx,ny,timeslice):
f = open(inputfilename,'rb')
f.seek(8*timeslice*nx*ny)
field = np.fromfile(f,dtype='float64',count=nx*ny)
field = np.reshape(field,(nx,ny))
f.close()
return field
在原始代码中,您将文件名作为第一个参数传递给np.fromfile
而不是文件对象f
。因此,np.fromfile
创建了一个新的文件对象,而不是使用您想要的文件对象。这就是为什么它一直从文件的开头读取的原因。另外,f.seek
将字节数作为参数,而不是元素的数量。我将其硬编码为8以适合您的数据,但如果您愿意,可以将其设为通用。此外,readslice
中的字段参数是多余的。希望这会有所帮助。
答案 1 :(得分:1)
我不认为所有FORTRAN运行时都是一样的;一些帧记录,有些没有,我不相信记录帧的记录将以同样的方式完成。他们当然可以回读他们自己编写的记录,但是从一个FORTRAN运行时到另一个运行时间可能不存在。
您可能应该在您选择的FORTRAN中编写一个小测试程序,编写一些类似于您的生产代码的记录,然后使用您喜欢的二进制文件编辑器分离结果 - 我喜欢bpe,但有很多他们可以。
然后,在了解了正在编写的内容后,请使用Python结构模块或类似内容重新开始。