如何在 python 中将一维 C 数组绘制为曲面
How to plot 1d C array as surface in python
假设我在 C 中有一个大小为 NxN 的一维数组,我认为它是一个二维数组,即每 N 个条目,一个新行开始。
我想将这个数组可视化,将它放在一个平面上,然后将每个条目视为数组在平面上方的高度,从而创建一个表面。
我如何将数据从 C 传输到 Python,以便 Python 可以将其作为二维数组读取,然后在三维中绘制?
更新
按照 barny 的回答和 joao 在评论中的建议,将数据写入 CSV 文件效果很好:
FILE *datafile = fopen("data.csv", "w");
for(int i = 0; i < N; i++) {
for(int j = 0; j < N; j++) {
fprintf(datafile, "%g, ", data[i * N + j]);
}
fprintf(datafile, "\n");
}
将其读入 python 中的列表也很容易:
import csv
data = list(csv.reader(open("data.csv")))
不幸的是,将此数据输出到曲面图中会导致问题。我的 python 脚本读取
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import csv
data = list(csv.reader(open("data.csv")))
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = y = np.arange(0, 1, 1.0/len(data))
X, Y = np.meshgrid(x, y)
data = np.array(data).reshape(Y.size,X.size)
ax.plot_surface(X, Y, data)
plt.show
如果我尝试 运行 它,我会在第 12 行 (data = np.array(data).reshape(Y.size,X.size)
) 上收到一个错误 ValueError: total size of new array must be unchanged
。我也尝试 np.sqrt(len(data))
而不是 len(data)
256
,这恰好是我的 N 的值。但是,错误在每种情况下都存在。
更新 2
最终对我有用的是 Emilie 的建议,即简单地线性写出 C 数组,即
FILE *datafile = fopen("data.dat", "w");
for(int i = 0; i < N; i++)
for(int j = 0; j < N; j++) {
fwrite(&array[i * N + j], sizeof(double), 1, datafile);
}
然后通过
读入
data = np.fromfile('data.dat', dtype=float, count=-1, sep='')
在Python之后是
array = data.reshape((np.sqrt(len(data)), np.sqrt(len(data))))
为数组提供所需的形状。 (注意:如果您的数组长度不是平方数,此步骤可能会出现问题。)
完整的工作绘图脚本是
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
data = np.fromfile('data.dat', dtype=float, count=-1, sep='')
array = data.reshape((np.sqrt(len(data)), np.sqrt(len(data))))
fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')
x = y = np.arange(0, 1, 1.0/np.sqrt(len(data)))
X, Y = np.meshgrid(x, y)
array = np.array(data)
ax.plot_surface(X, Y, array)
plt.show()
您可以将数据打印为 python 表达式,如下所示:
printf( "data2d = [\n" );
for ( y = 0; y < N ; y++ ) {
printf( " [" );
for ( x = 0 ; x < n ; x++ ) {
printf( " %d,", datalist[y*N+x] );
}
printf( " ],\n" );
}
printf( "]\n" );
还没有测试过这个,虽然因为我做了任何 C,但它会是这样的。
(我认为尾随逗号不重要 - 如果重要,请不要在每行的最后一个条目上打印它们)
或者,也许更简单,将其打印为普通 csv 文件 - 数组的每一行一行,值之间有 , 然后使用 csv 模块读取它。
HTH
巴尼
重塑错误的产生是因为当您读取 csv 时,您的 data
已经是一个列表列表,您可以使用 np.array(data)
.
将其简单地转换为一个 numpy 数组
例如,如果我有这个文件:
/tmp$ cat foo.csv
1,2,3
4,5,6
我能做到:
>>> import csv
>>> data = list(csv.reader(open("foo.csv")))
>>> data
[['1', '2', '3'], ['4', '5', '6']]
>>> import numpy as np
>>> np.array(data)
array([['1', '2', '3'],
['4', '5', '6']],
dtype='|S1')
根据您想对这个 numpy 数组执行的操作,您可能还需要更改元素的类型。您也可以线性写入数据,然后使用 np.reshape。我不确定 csv 是最优雅的方式,但可能是一个简单的解决方案。
假设我在 C 中有一个大小为 NxN 的一维数组,我认为它是一个二维数组,即每 N 个条目,一个新行开始。
我想将这个数组可视化,将它放在一个平面上,然后将每个条目视为数组在平面上方的高度,从而创建一个表面。
我如何将数据从 C 传输到 Python,以便 Python 可以将其作为二维数组读取,然后在三维中绘制?
更新
按照 barny 的回答和 joao 在评论中的建议,将数据写入 CSV 文件效果很好:
FILE *datafile = fopen("data.csv", "w");
for(int i = 0; i < N; i++) {
for(int j = 0; j < N; j++) {
fprintf(datafile, "%g, ", data[i * N + j]);
}
fprintf(datafile, "\n");
}
将其读入 python 中的列表也很容易:
import csv
data = list(csv.reader(open("data.csv")))
不幸的是,将此数据输出到曲面图中会导致问题。我的 python 脚本读取
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import csv
data = list(csv.reader(open("data.csv")))
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = y = np.arange(0, 1, 1.0/len(data))
X, Y = np.meshgrid(x, y)
data = np.array(data).reshape(Y.size,X.size)
ax.plot_surface(X, Y, data)
plt.show
如果我尝试 运行 它,我会在第 12 行 (data = np.array(data).reshape(Y.size,X.size)
) 上收到一个错误 ValueError: total size of new array must be unchanged
。我也尝试 np.sqrt(len(data))
而不是 len(data)
256
,这恰好是我的 N 的值。但是,错误在每种情况下都存在。
更新 2
最终对我有用的是 Emilie 的建议,即简单地线性写出 C 数组,即
FILE *datafile = fopen("data.dat", "w");
for(int i = 0; i < N; i++)
for(int j = 0; j < N; j++) {
fwrite(&array[i * N + j], sizeof(double), 1, datafile);
}
然后通过
读入data = np.fromfile('data.dat', dtype=float, count=-1, sep='')
在Python之后是
array = data.reshape((np.sqrt(len(data)), np.sqrt(len(data))))
为数组提供所需的形状。 (注意:如果您的数组长度不是平方数,此步骤可能会出现问题。)
完整的工作绘图脚本是
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
data = np.fromfile('data.dat', dtype=float, count=-1, sep='')
array = data.reshape((np.sqrt(len(data)), np.sqrt(len(data))))
fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')
x = y = np.arange(0, 1, 1.0/np.sqrt(len(data)))
X, Y = np.meshgrid(x, y)
array = np.array(data)
ax.plot_surface(X, Y, array)
plt.show()
您可以将数据打印为 python 表达式,如下所示:
printf( "data2d = [\n" );
for ( y = 0; y < N ; y++ ) {
printf( " [" );
for ( x = 0 ; x < n ; x++ ) {
printf( " %d,", datalist[y*N+x] );
}
printf( " ],\n" );
}
printf( "]\n" );
还没有测试过这个,虽然因为我做了任何 C,但它会是这样的。
(我认为尾随逗号不重要 - 如果重要,请不要在每行的最后一个条目上打印它们)
或者,也许更简单,将其打印为普通 csv 文件 - 数组的每一行一行,值之间有 , 然后使用 csv 模块读取它。
HTH 巴尼
重塑错误的产生是因为当您读取 csv 时,您的 data
已经是一个列表列表,您可以使用 np.array(data)
.
例如,如果我有这个文件:
/tmp$ cat foo.csv
1,2,3
4,5,6
我能做到:
>>> import csv
>>> data = list(csv.reader(open("foo.csv")))
>>> data
[['1', '2', '3'], ['4', '5', '6']]
>>> import numpy as np
>>> np.array(data)
array([['1', '2', '3'],
['4', '5', '6']],
dtype='|S1')
根据您想对这个 numpy 数组执行的操作,您可能还需要更改元素的类型。您也可以线性写入数据,然后使用 np.reshape。我不确定 csv 是最优雅的方式,但可能是一个简单的解决方案。