2012-05-07 54 views
5

我完全不熟悉Python,并且正在从头开始编写我的可视化代码(避免使用IDL等昂贵的专有程序)。直到现在我已经使用IDL和gnuplot。我想要做的是这样的:在Python中读取直接访问fortran未格式化文件

我使用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代码中使用的“时间片”的值。我到目前为止的代码是:

#!/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() 

我想要的高清readslice能够在第i个地方,如果时间片等于我读的记录。为此,我尝试使用f.seek,但它似乎不起作用。 numpy.fromfile似乎开始从第一个记录本身读取。如何使numpy.fromfile从文件中的特定点读取?

我仍然试图习惯Python风格和挖掘文档。任何帮助和指针将不胜感激。

+1

不确定你做了什么可视化,但要注意VTK。 – Anycorn

+1

我经常这样做(Fortran直接访问+ python文件seek + numpy.fromfile)。你的代码看起来正确。尝试从Fortran程序中读取数据作为完整性检查。另外,发布用于写入数据的Fortran代码片段。确保您写入/读取的数据是相同的精度/数据类型。你说你在做什么似乎不工作。你能否包含一个数据应该是什么样子以及你实际得到什么的例子? – milancurcic

+0

IRO-bot,你可以分享一下你阅读这些文件的代码片段吗?这段代码似乎始终从第一条记录开始。 np.fromfile的文档似乎没有关于数据读取起点的关键字。 – toylas

回答

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中的字段参数是多余的。希望这可以帮助。

+0

非常感谢IRO-bot!最终,这是我的愚蠢的错误!感谢您指出!现在一切正常! – toylas

+0

@toylas当然,我很高兴这有帮助。 – milancurcic

+0

完成!我正在尝试对其进行+1,但未被允许,因为我还没有“声誉”:-点击复选标记。我对这个网站还很陌生。 – toylas

1

我不认为所有的FORTRAN运行时都是一样的;一些帧记录,有些不记录,我不确信那些记录帧的记录都会以相同的方式进行记录。他们通常可以读回由他们自己编写的记录,但是从一个FORTRAN运行时到另一个FORTRAN运行时的交互可能不在那里。

您可能应该在您选择的FORTRAN中编写一个小测试程序,写一些类似于您的生产代码的记录,然后使用您最喜爱的二进制文件编辑器分离结果 - 我喜欢bpe,但有很多的可用。

然后,当你明白什么是真正被写入的时候,使用Python结构模块或类似的东西拉回来。

BPE:http://sourceforge.net/projects/bpe/

+1

感谢您的回答,但正如IRO-bot在上面指出的那样,直接访问文件没有任何记录信息。我一直在IDL中读取这些文件。这与编译器无关。 我确实尝试了结构模块,但我不太了解python。所以我无法实现它。除了寻找问题之外,上面的numpy.fromfile是最接近的实现。 – toylas

相关问题