0

我对编程非常陌生,正在将 fortran90 代码转换为 python 2.7。到目前为止,我在这方面做得相当好,但遇到了一个困难的地方。我需要用 Python 编写这个子例程,但我不理解 fortran 表示法,也找不到任何关于 Read(1,*) 行的 Python 等效项的信息。

任何帮助都将不胜感激。

SUBROUTINE ReadBCoutput(filenameBC,count,timeArray,MbolArray,uArray,gArray,rArray,iArray,zArray)

! read Bruzual & Charlot (2003) stellar population synthesis models into arrays

CHARACTER*500,INTENT(IN):: filenameBC
INTEGER,INTENT(OUT):: count
REAL,DIMENSION(:),ALLOCATABLE,INTENT(OUT):: timeArray,MbolArray,uArray,gArray,rArray,iArray,zArray

REAL:: logTime,Mbol,g,uMg,gMr,gMi,gMz
REAL,DIMENSION(:),ALLOCATABLE:: timeArrayLocal,MbolArrayLocal,uArrayLocal,gArrayLocal,rArrayLocal,iArrayLocal,zArrayLocal

! open file and read off unnecessary 29 lines of comments
OPEN(1,FILE=TRIM(filenameBC),RECL=2000)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)
READ(1,*)

! now read arrays
count=0
ALLOCATE(timeArray(count))
ALLOCATE(MbolArray(count))
ALLOCATE(uArray(count))
ALLOCATE(gArray(count))
ALLOCATE(rArray(count))
ALLOCATE(iArray(count))
ALLOCATE(zArray(count))
IOEnd=0
DO WHILE(IOEnd>-1)
 READ(1,*,IOSTAT=IOEnd) logTime,Mbol,g,uMg,gMr,gMi,gMz
!print*,'filename is',filenameBC
   IF (IOEnd>-1) THEN ! not at end of file yet
     ! add new element to list
    count=count+1
    ALLOCATE(timeArrayLocal(count-1))
    ALLOCATE(MbolArrayLocal(count-1))
    ALLOCATE(uArrayLocal(count-1))
    ALLOCATE(gArrayLocal(count-1))
    ALLOCATE(rArrayLocal(count-1))
    ALLOCATE(iArrayLocal(count-1))
    ALLOCATE(zArrayLocal(count-1))
    DO countInside=1,count-1
       timeArrayLocal(countInside)=timeArray(countInside)
       MbolArrayLocal(countInside)=MbolArray(countInside)
       uArrayLocal(countInside)=uArray(countInside)
       gArrayLocal(countInside)=gArray(countInside)
       rArrayLocal(countInside)=rArray(countInside)
       iArrayLocal(countInside)=iArray(countInside)
       zArrayLocal(countInside)=zArray(countInside)
    END DO
    DEALLOCATE(timeArray)
    DEALLOCATE(MbolArray)
    DEALLOCATE(uArray)
    DEALLOCATE(gArray)
    DEALLOCATE(rArray)
    DEALLOCATE(iArray)
    DEALLOCATE(zArray)
    ALLOCATE(timeArray(count))
    ALLOCATE(MbolArray(count))
    ALLOCATE(uArray(count))
    ALLOCATE(gArray(count))
    ALLOCATE(rArray(count))
    ALLOCATE(iArray(count))
    ALLOCATE(zArray(count))
    DO countInside=1,count-1
       timeArray(countInside)=timeArrayLocal(countInside)
       MbolArray(countInside)=MbolArrayLocal(countInside)
       uArray(countInside)=uArrayLocal(countInside)
       gArray(countInside)=gArrayLocal(countInside)
       rArray(countInside)=rArrayLocal(countInside)
       iArray(countInside)=iArrayLocal(countInside)
       zArray(countInside)=zArrayLocal(countInside)
    END DO
    timeArray(count)=10**logTime
    MbolArray(count)=Mbol
    gArray(count)=g
    uArray(count)=uMg+g
    rArray(count)=g-gMr
    iArray(count)=g-gMi
    zArray(count)=g-gMz
    DEALLOCATE(uArrayLocal)
    DEALLOCATE(gArrayLocal)
    DEALLOCATE(rArrayLocal)
    DEALLOCATE(iArrayLocal)
    DEALLOCATE(zArrayLocal)
    DEALLOCATE(MbolArrayLocal)
    DEALLOCATE(timeArrayLocal)
 END IF
END DO
CLOSE(1)

END SUBROUTINE ReadBCoutput

我不希望任何人为我转换整个事情 - 我只想清楚这实际上在做什么以及在 Python 中做什么/不需要做什么。我有能力自己搜索,但我有点被这里要找的东西所震撼。

非常感谢!

4

2 回答 2

4

在 fortran 中,open(1,FILE=TRIM(filenameBC),RECL=2000)打开具有 name 的文件filenameBC。该TRIM部分是不必要的,因为 fortran 运行时库会为您执行此操作(它与 python 等效的是filenameBC.rstrip())。这里的RECL=2000部分也有点可疑。我不认为它在这里做任何事情——实际上,我认为使用它是未定义的行为,因为你的文件应该被连接以进行"sequential"访问。根据fortran77 标准第 12.10.1 节,

记录 = rl

rl 是一个整数表达式,其值必须为正数。它指定为直接访问而连接的文件中每条记录的长度。如果正在连接文件以进行格式化输入/输出,则长度是字符数。如果正在连接文件以进行未格式化的输入/输出,则长度以处理器相关单位测量。对于现有文件,rl 的值必须包含在文件的允许记录长度集中(12.2.2)。对于新文件,处理器创建具有一组允许记录长度的文件,其中包括指定的值。当连接文件以进行直接访问时,必须给出此说明符;否则,必须省略。

这可能在标准的更新版本中发生了变化——如果是这样,我相信它指定了最大行长度。

Fortran 文件句柄只是整数。所以,虽然在 python 中你会说:

filehandle = open('file')
line = filehandle.readline()  #or better, `next(filehandle)` :)

在 fortran 中,这与以下内容大致相同:

integer filehandle
filehandle = 1       ! pick an integer any positive one 
                     ! will do that we haven't used already,
                     ! but it's best to avoid 0,5,6 as those 
                     ! usually mean `stderr`,`stdin` and `stdout`.
open(filehandle,file='file')
read(filehandle,*) line

基本上让你从文件中*读取一行。


请注意,这个 fortran 代码有一点问题,而且效率极低。例如IF (IOEnd>-1) THEN,在不是文件结尾的任何条件下检查都会成功(例如,奇怪的错误将被屏蔽,类似于exceptpython 中的一个bare)。在 python 中,您可以将这些信息打包到一个列表中并动态增长列表——python 将处理您需要执行的所有重新分配。最后,您可以选择将列表转换为 numpy ndarray

在伪 python 代码中,这大致翻译为:

data_list = []
with open(filenameBC.rstrip()) as fin:
    for _ in range(29): #throw away first 29 lines (I think I counted right ...)
        next(fin)
    
    for line in fin:
        data_list.append([float(x) for x in line.strip()])
    
timeArray,MbolArray,uArray,gArray,rArray,iArray,zArray = zip(*data_list)
于 2013-03-19T13:13:20.607 回答
0

READ(1,*)正在读取....从您的文件中读取的内容,而不是存储它,即只是将其扔掉。所有这些READ(1,*)语句只是一种滚动文件的方式,直到您获得实际需要的数据。(顺便说一句,这不是最紧凑的编码方式。编写这个 FORTRAN 代码的人可能在许多方面都非常聪明,但不是一个非常好的程序员。或者他们可能很着急。)一个 python 等价物只是是

>>> infile.readline()

请注意,FORTRAN 可以整数、浮点数等形式读取数据,但是 python 只会将所有内容都读取为文本,然后您必须将其转换为所需的任何数字形式。

但是,如果您想查看NumPy,它有几个可以将数据读取为数字的例程:loadtxtgenfromtxt. 也许还有其他几个,但这些是我发现最有帮助的。

于 2013-03-19T18:37:12.243 回答