【问题标题】:Reading binary data and Distribute the data in grid file Python读取二进制数据并将数据分布在网格文件 Python 中
【发布时间】:2016-08-09 11:01:36
【问题描述】:

我正在尝试读取流量数据并将数据分发到最终绘图的网格文件中。我有一个用于处理的 MATLAB 代码,它可以成功运行。我需要将此代码转移到 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)

【问题讨论】:

  • 欢迎来到 Stack Overflow。目前我认为不可能回答这个问题,因为你没有提供你正在阅读的文件结构的例子——你能以某种方式提供一个摘录吗? Python 代码中的分号让我觉得你在这些方面很挣扎(它们不是必需的,所以我认为它们来自 Matlab)而且它似乎也比它需要的更冗长
  • @roganjosh 提前非常感谢! MATLAB 是一种方便的工程工具。但我必须为特定项目运行 Python 脚本。
  • 欢迎来到 Stack Overflow。看看minimal reproducible example,下载一个100MB的文件并不理想,除非真的无法避免。
  • @roganjosh 以我使用 Python 的方式编写它很难还是我做错了什么?无论如何感谢您的帮助。
  • @roadrunner66 感谢您的评论。其实我不认为下载是必要的。由于代码是从 MATLAB 转过来的,由于 MATLAB 和 Python 之间的命令不同,似乎出现了一些结构错误。

标签: python matlab numpy matplotlib binary


【解决方案1】:

如果没有具体的错误信息,就很难分辨。但是,我看到了一系列可能的问题。

第一:

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 列表或元组。您需要使用xx = np.array(xx).reshape([Nx, Ny]) 之类的东西将xxyy 转换为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 有 pcolor 和 MATLAB 一样,所以使用它。

其次,没有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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-10
    • 2010-12-08
    • 1970-01-01
    • 1970-01-01
    • 2013-03-23
    • 2013-07-15
    • 2014-07-25
    • 1970-01-01
    相关资源
    最近更新 更多