读取二进制数据并在网格文件Python中分发数据

时间:2016-04-17 20:04:43

标签: python matlab numpy matplotlib binary

我正在尝试读取流数据并将数据分发到网格文件中以进行最终绘图。我有一个用于处理的MATLAB代码,它运行成功。我需要将此代码转移到Python中,但我是初学者。在调试时它总是崩溃,谁能告诉我我做错了什么?提前致谢!

数据文件(总共约100mb):

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

MATLAB代码

$db = new PDO('mysql:host=#YOUR HOST#;dbname=#YOUR DB#;charset=utf8', '#YOUR LOGIN#', '#YOUR PASSWORD#');
$query = $db->query('SELECT COUNT(*) AS count FROM articles');
$countq = $query->fetch();
$query->closeCursor();
echo $countq['count'];

Python代码:

%% 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

1 个答案:

答案 0 :(得分: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中,你以float形式读取它,但在python中你以整数形式读取它。但更重要的是,您正在阅读aa个数字,但[0]仅保留第一个数字。在MATLAB中,你保留所有这些。

下一步:

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

unpack返回一个元组,它本身就是一维的。它没有reshape方法,这是numpy数组所具有的,但不是python列表或元组。您需要使用xx等内容将yyxx = np.array(xx).reshape([Nx, Ny])转换为numpy数组,或者更好地使用numpy的fromfile,例如xx = np.fromfile(fid, dtype='float', count=aa)。这会直接将数据读取为numpy数组。

事实上,我建议你到处使用它。您获得NxNyNz的部分可以简化为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)

首先,您在MATLAB中执行pcolor,但在Python中执行plot。这些是完全不同的。 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()