在python2.7中绘制4D图形

3 投票
1 回答
4702 浏览
提问于 2025-04-17 11:11

我想在三个轴上绘制红色、蓝色和绿色,并且有一个数组用来存储每种颜色组合对应的值,使用的是python2.7。可是当我运行程序时,要么程序变得无响应,整整24小时都没有反应,要么就出现内存错误。以下是我的代码:

import pylab
import math
from itertools import product
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np

N=[]
p=np.zeros((256,256,256))
S=[]
fig=plt.figure()
ax=fig.gca(projection='3d')
X=np.arange(0,256,1) #for one of the features either red, blue or green
Y=np.arange(0,256,1)
X,Y = np.meshgrid(X,Y)
R=np.sqrt(X**2 + Y**2)
Z=R/np.sqrt(2)
N=p.flatten();
N=(p[i,j,k] for k in Z)            
surf=ax.plot_surface(X,Y,Z, rstride=1, cstride=1,
                    facecolors=cm.jet(N),
                    linewidth=0, antialiased=False, shade=False)
plt.show()

请帮帮我。我看过之前的帖子,并且也尝试过那些方法,但还是遇到了内存错误。在这里,p是一个包含红色、绿色和蓝色组合值的数组。为了简单起见,我把它初始化为零……但是它给出了以下错误:colset.append(fcolors[rs][cs]),错误提示是“索引超出范围”。

1 个回答

8

首先,你的程序运行得很慢,因为你在构建 N 时做了很多不必要的工作。你是在一点一点地构建一个70 MB的列表(256*256*256=16,777,216次添加!)。一个更好(更快,内存使用更高效)的方法是使用numpy的数组广播功能,然后重用 p 来生成 N

import numpy as np
a = np.arange(256)
p = a[:,np.newaxis,np.newaxis] * a[np.newaxis,:,np.newaxis] * a[np.newaxis,np.newaxis,:] 
N = p.flatten()

其次,更重要的是,你没有正确使用 plot_surface()。根据文档,X、Y和Z应该是二维数组。X和Y构成一个二维网格,而Z则为这个二维网格上的每个点提供“高度”。如果你想手动设置面颜色,它也应该是一个二维数组。你应该查看文档中的示例,以获取一个有效的例子。

编辑:

我不确定你的图表应该是什么样子,所以我们来看看MPL示例

首先,进行必要的导入,并创建一个坐标轴对象(你的代码在这方面做得很好):

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.gca(projection='3d')

接下来,创建一个X/Y网格和相应的Z。在你的程序中,X、Y和Z都是一维的。它们描述的是三维空间中的一条线,而不是一个表面。

X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)  # <-- returns a 2D grid from initial 1D arrays
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)

让我们先绘制最简单的东西。没有颜色,使用默认的抗锯齿,线条等。

surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1)
plt.show()

enter image description here

现在添加颜色。注意颜色来自Z组件。

surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet)
plt.show()

enter image description here

现在手动控制颜色(MPL灵感)。

colortuple = ('y', 'k')  # only use two colors: yellow and black
xlen, ylen = X.shape  # get length of 
colors = np.empty(X.shape, dtype=str)  # make a 2D array of strings
for i in range(xlen):
    for j in range(ylen):
        index = (i + j) % 2  # alternating 0's and 1's
        colors[i,j] = colortuple[index]
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, 
        facecolors=colors)

enter image description here

如果你想根据其他指标来上色,可以创建自己的颜色映射。有很多问题已经回答了如何做到这一点。

编辑2:

颜色也可以指定为RGB序列。对于你描述的在X上是红色,在Y上是绿色的情况,你可以这样做:

xlen, ylen = X.shape
colors = np.zeros((xlen,ylen,3))
jspan = np.linspace(0., 1., ylen)
ispan = np.linspace(0., 1., xlen)
for i in range(xlen):
    colors[i,:,0] = jspan
for j in range(ylen):
    colors[:,j,1] = ispan

surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, facecolors=colors,)

enter image description here

撰写回答