2016-04-17 47 views
0

我正在嘗試讀取流數據並將數據分發到網格文件中以獲得最終繪圖。我有一個用於處理的MATLAB代碼,並且它可以成功運行。我需要將這些代碼轉換爲Python,但我是初學者。調試時總是崩潰,任何人都可以告訴我我做錯了什麼?提前致謝!讀取二進制數據並在網格文件中分發數據Python

數據文件(大約總共100MB):

https://www.dropbox.com/sh/3gtsmatq56pm0gc/AADUnNLjdrELjvdUy4wtDiiBa?dl=0

MATLAB代碼

%% Read Grid grid file is used as a guide for the positon where data is put 
fid = fopen('FLOW_phys_GRID_1.xyz', 'r'); 

a = fread(fid, 3, 'int'); 

Nx = a(1); % number of points in x direction 
Ny = a(2); % number of points in y direction 
Nz = a(3); % numebr of points in z direction 

xx = fread(fid, Nx*Ny*Nz, 'float'); 
yy = fread(fid, Nx*Ny*Nz, 'float'); 

xx = reshape(xx, [Nx, Ny]); 
yy = reshape(yy, [Nx, Ny]); 

fclose(fid); 

x = squeeze(xx(:,1)); 
y = squeeze(yy(1,:)); 

%% Read Data 

fid = fopen('FLOW_phys.raw', 'r'); %flow data in binary format 

a = fread(fid, 3, 'int'); 

Nx = a(1); % number of points in x direction 
Ny = a(2); % number of points in y direction 
Nz = a(3); % number of points in z direction 

Ma = fread(fid, 1, 'float'); 
some_num = fread(fid, 1, 'float'); 
Re = fread(fid, 1, 'float'); 
time = fread(fid, 1, 'float'); 

xx1 = fread(fid, 2*Nx*Ny*Nz, 'float'); 
xx1 = reshape(xx1, [Nx, 2*Ny, Nz]); 

fclose(fid); 

[XX, YY] = meshgrid(x, y); 

% plot (squeeze(xx1(2,:,1))); 
h = pcolor(XX, YY, squeeze(xx1)'); 
set(h, 'EdgeColor', 'none'); 
colorbar 

Python代碼:

import struct 
import numpy 
import matplotlib 

unpackformat_int = '<i' 
unpackformat_flo = '<f' 


fid = open('FLOW_phys_GRID_1.xyz', 'r+') 

Nx = struct.unpack(unpackformat_int,fid.read(4))[0] 
Ny = struct.unpack(unpackformat_int,fid.read(4))[0] 
Nz = struct.unpack(unpackformat_int,fid.read(4))[0] 

aa = Nx*Ny*Nz 

xx = struct.unpack('i'*aa, fid.read(aa*4))[0] 
yy = struct.unpack('i'*aa, fid.read(aa*4))[0] 

xx = xx.reshape([Nx, Ny]) 
yy = yy.reshape([Nx, Ny]) 

fid.close() 

fid = open('FLOW_phys.raw', 'r+') 

Nx = struct.unpack(unpackformat_int,fid.read(4))[0] 
Ny = struct.unpack(unpackformat_int,fid.read(4))[0] 
Nz = struct.unpack(unpackformat_int,fid.read(4))[0] 

Ma = struct.unpack(unpackformat_flo, fid.read(4))[0] 
some = struct.unpack(unpackformat_flo, fid.read(4))[0] 
Re = struct.unpack(unpackformat_flo, fid.read(4))[0] 
time = struct.unpack(unpackformat_flo, fid.read(4))[0] 

bb = Nx*Ny*Nz 

xx1 = struct.unpack('f'*bb, fid.read(bb*4))[0] 
xx2 = struct.unpack('f'*bb, fid.read(bb*4))[0] 

xx1 = xx1.reshape([Nx, Ny, Nz]) 
xx2 = xx2.reshape ([Nx, Ny, Nz]) 


fid.close() 

[XX, YY] = numpy.meshgrid(xx, yy) 

matplotlib.plot(XX,YY,xx2) 
+0

歡迎使用堆棧溢出。目前我認爲不可能回答這個問題,因爲你沒有提供你正在閱讀的文件結構的例子 - 你能否以某種方式提供摘錄? Python代碼中的分號讓我覺得你在這些點上掙扎(它們不是必需的,所以我認爲它們來自Matlab)並且它似乎比它需要的更加冗長 – roganjosh

+0

@roganjosh非常感謝! MATLAB對於工程人員來說是一個方便的工具。但我必須爲特定項目運行Python腳本。 – Max

+0

歡迎來到Stack Overflow。退房[mcve],下載一個100 MB的文件並不理想,除非真的無法避免。 – roadrunner66

回答

2

如果沒有一個具體的錯誤消息,很難告訴。但是,我看到一系列可能的問題。

第一:

fid = open('FLOW_phys_GRID_1.xyz', 'r+') 

這應該是'rb',這意味着 「讀二進制」。這是一個二進制文件,而不是文本文件。 'r+'的意思是「讀寫」,但你不寫。此外,您應該始終使用with open('FLOW_phys_GRID_1.xyz', 'r+') as fid:,因爲這會在完成後自動關閉文件。

另外,在MATLAB中,打開的文件由用於向MATLAB解釋器識別文件的特殊數字表示。然而,在Python中,它們是不同的對象,爲了更好地保持這一點,可以使用fobj而不是fid作爲變量名稱。

下一頁:

xx = struct.unpack('i'*aa, fid.read(aa*4))[0] 
yy = struct.unpack('i'*aa, fid.read(aa*4))[0] 

在MATLAB中,你讀到這篇文章中的浮動,但是在Python你讀它作爲一個整數。更重要的是,儘管如此,您正在閱讀aa號碼,但[0]僅保留第一個號碼。在MATLAB中,你保留所有這些。

下一頁:

xx = xx.reshape([Nx, Ny]) 
yy = yy.reshape([Nx, Ny]) 

unpack返回一個元組,這是固有的一維的。它沒有reshape方法,這是numpy數組有的東西,但不是python列表或元組。您需要將xxyy轉換爲numpy陣列,使用類似xx = np.array(xx).reshape([Nx, Ny])的東西,或者更好地使用numpy的fromfile,例如xx = np.fromfile(fid, dtype='float', count=aa)。這將直接讀取數據作爲numpy數組。

事實上,我會建議你到處使用。您可以將Nx,NyNz的部分簡化爲Nx, Ny, Nz = np.fromfile(fid, dtype='i', count=3)。該語法實際上也適用於unpack,但使用文件時,numpy方法更簡單一些。

此外,在numpy和MATLAB中,維的順序是不同的。 numpy(默認情況下)使用從C編程語言的數組派生的順序,而MATLAB專門使用Fortran編程語言的順序。因此,爲了在Python中獲得與MATLAB相同的陣列形狀,您需要將第一個反轉到軸,因此reshape([Ny, Nx])或更高版本的reshape([Ny, Nx, Nz])

此外,只有當Nz始終爲1時才能工作。如果它是任何其他數字,即使在MATLAB中也會失敗。

接下來,從MATLAB代碼:

x = squeeze(xx(:,1)); 
y = squeeze(yy(1,:)); 

你從來沒有在Python做到這一點。這也意味着在Python下面的部分是不同於你在MATLAB做:

[XX, YY] = numpy.meshgrid(xx, yy) 

下一頁:

bb = Nx*Ny*Nz 

xx1 = struct.unpack('f'*bb, fid.read(bb*4))[0] 
xx2 = struct.unpack('f'*bb, fid.read(bb*4))[0] 

在MATLAB中,你讀到2*Nx*Ny*Nz,但在Python閱讀Nx*Ny*Nz成兩個不同的陣列,你永遠不會把它合併成一個。這意味着你在Python中繪製的東西與你在MATLAB中的不同。你也從來沒有squeeze或轉置numpy陣列。

最後:

matplotlib.plot(XX,YY,XX2)

首先,你是在Python中的MATLAB pcolorplot。這些完全不同。 matplotlib像MATLAB一樣有pcolor,所以使用它。

其次,沒有這樣的東西,如matplotlib.plot。你需要做一些像from matplotlib import pyplot然後pyplot.plot。然後你需要做pyplot.show()才能真正顯示劇情。但是,通常會採用import matplotlib.pyplot as plt(和import numpy as np)將事情縮短。

如果您以交互方式執行此操作,而不是腳本,則可以執行plt.ion()以使繪圖立即顯示(或更好地使用IPython shell並使用%matplotlib)。但是在腳本中,您需要在完成所有格式化後調用plt.show()

所以這裏是我將如何(大致)實現你在做什麼。我沒有要測試的示例文件,所以它可能無法正常工作,但希望它足以讓您開始:

import numpy as np 
import matplotlib.pyplot as plt 


with open('FLOW_phys_GRID_1.xyz', 'rb') as fobj: 
    Nx, Ny, Nz = np.fromfile(fobj, 'int32', 3) 
    x = np.fromfile(fobj, 'float32', Nx*Ny*Nz).reshape(Ny, Nx, Nz)[:, 0, 0]) 
    y = np.fromfile(fobj, 'float32', Nx*Ny*Nz).reshape(Ny, Nx, Nz)[0, :, 0] 

with open('FLOW_phys.raw', 'rb') as fobj: 
    Nx, Ny, Nz = np.fromfile(fobj, 'int32', 3) 
    xx1 = np.fromfile(fobj, 'float32', 2*Nx*Ny*Nz).reshape(2*Ny, Nx, Nz).squeeze().T 

plt.pcolor(*np.meshgrid(x, y), xx1) 
plt.show()