簡體   English   中英

將FORTRAN90文件生成的數據讀入NUMPY數組

[英]Reading data generated from FORTRAN90 file into NUMPY array

我有一個要讀入Python的二進制文件。 該文件由三部分組成:波數列表,溫度列表以及不透明度列表,它們是溫度和壓力的函數。 我想將其中的前兩個作為向量a和b導入,將第三個作為2D數組c導入,使得c [x,y]對應於a [x]和b [y]。

現有的FORTRAN90代碼能夠實現以下目的:

integer   nS, nT
parameter (nS = 3000)
parameter (nT = 9)

real(8) wn_arr(nS)      ! wavenumber [cm^-1]
real(8) temp_arr(nT)    ! temperature [K]
real(8) abs_arr(nS,nT)  ! absorption coefficient [cm^-1 / amagat^2]

open(33,file=trim(datadir)//'CO2_dimer_data',form='unformatted')
read(33) wn_arr
read(33) temp_arr
read(33) abs_arr
close(33)

我嘗試了以下python代碼:

f=scipy.io.FortranFile('file', 'r')
a_ref=f.read_reals(np.float64) #wavenumber (cm**-1)
b=f.read_reals(np.float64) #temperature (K)
c=f.read_reals(np.float64).reshape((3000,9))

但是,這會產生不正確的結果。 我懷疑這是因為Fortran以與Python不同的順序將數組寫入文件。 但是,僅將order ='F'添加到reshape命令不起作用。 我懷疑這是因為讀入時,abscoeff_ref已被拉平。

有什么想法嗎?

為了讓您了解我在第二條評論中的意思,我進行了模擬:

用gfortran 4.8.4編譯的testwrite.f90:它基本上是編寫一個未格式化的順序文件,該文件具有您指定的數組(大小要小得多,以便能夠通過肉眼比較它們),並填充有任意數據。 它還打印陣列。

implicit none
integer   nS, nT, i ,j
parameter (nS = 10)
parameter (nT = 3)

real(8) wn_arr(nS)      ! wavenumber [cm^-1]
real(8) temp_arr(nT)    ! temperature [K]
real(8) abs_arr(nS,nT)  ! absorption coefficient [cm^-1 / amagat^2]

wn_arr = (/ (i, i=1,nS) /)
temp_arr = (/ (270+i, i=1,nT) /)
abs_arr = reshape( (/ ((10*j+i, i=1,nS), j=1,nT) /), (/nS, nT/))

print*, wn_arr
print*, '-----------------'
print*, temp_arr
print*, '-----------------'
print*, abs_arr
print*, '-----------------'
print*, 'abs_arr(5,3) = ', abs_arr(5,3)

open(33,file='test.out',form='unformatted')
write(33) wn_arr
write(33) temp_arr
write(33) abs_arr
close(33)

end

使用Python 2.7.6進行測試的testread.py,然后讀取上面編寫的文件並打印數組。 對我來說,這兩個程序的輸出是相同的。 因人而異。

import numpy as np

rec_delim = 4  # This value depends on the Fortran compiler
nS = 10
nT = 3

with open('test.out', 'rb') as infile:
    infile.seek(rec_delim, 1)  # begin record
    wn_arr = np.fromfile(file=infile, dtype=np.float64, count=nS)
    infile.seek(rec_delim, 1)  # end record
    infile.seek(rec_delim, 1)  # begin record
    temp_arr = np.fromfile(file=infile, dtype=np.float64, count=nT)
    infile.seek(rec_delim, 1)  # end record
    infile.seek(rec_delim, 1)  # begin record
    abs_arr = np.fromfile(file=infile,
                        dtype=np.float64).reshape((nS, nT), order='F')
    infile.seek(rec_delim, 1)  # end record

print(wn_arr)
print(temp_arr)
print(abs_arr)
# The array has the same shape, but Fortran starts index (per default at least)
# at 1 and Python at 0:
print('abs_arr(5,3) = ' + str(abs_arr[4,2]))

簡短說明:我在with塊中打開文件(Python的一種很好的做法),然后使用關於文件編寫方式的知識逐步瀏覽文件。 這使其不可攜帶。 infile.seek(4,1)將Python的讀取指針從當前位置(選項1)向前移4個字節,因為我知道文件以4字節長的開始記錄標記開頭(gfortran) 。

然后,我使用numpy.fromfile讀取count = 10個float64值,它是wavenumber數組。

接下來,我必須跳過結束記錄和開始記錄標記。 當然,這也可以通過infile.seel(8,1)完成。

然后,我讀取溫度陣列,再次跳過結束記錄和開始記錄標記,然后讀取2D陣列。 文件中的數據不知道它是2D的,因此我需要使用Fortran順序對其進行重塑。 最后一個.seek()是虛假的,我只是想強調結構。

我再次強烈建議您不要在這樣的代碼上構建更大的系統。 一次過就可以了,但是對於您必須再次使用或共享的東西卻很糟糕。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM