在四维 matplotlib 曲面中更改 Facecolors

Changing Facecolors in four dimensional matplotlib surface

我想绘制一个 4 维的 matplotlib 曲面图。最初,我会将数据放在:

[(X, Y, Z, P)]

所以我想要一个 3D 表面,但是有一个颜色图,由 P.

的值表示

我看到了一个很好的解决方案 here

所以我将我的数据分成两个数据集:

 1. [(X, Y, Z)] (called data in my code) and
 2. [(X, Y, P)] (called shade in my code)

并尝试实施 Oliver W. 在他的回答末尾建议的内容。不幸的是我收到以下错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "c:\Python27\lib\lib-tk\Tkinter.py", line 1532, in __call__
    return self.func(*args)
  File "c:\Python27\lib\lib-tk\Tkinter.py", line 583, in callit
    func(*args)
  File "C:\Users\Raphael\Documents\NetBeansProjects\GammaVolaFund\src\GUI.py", line 413, in repeat
    self.a2.plot_surface(grid_x, grid_y, grid_z, facecolors=fc, rstride=1, cstride=1, linewidth=0, antialiased=False, shade=False)
  File "c:\Python27\lib\site-packages\mpl_toolkits\mplot3d\axes3d.py", line 1625, in plot_surface
    colset.append(fcolors[rs][cs])
IndexError: index 4 is out of bounds for axis 0 with size 4

这是我的代码:

if "surface" in val:
                self.a2.cla() #<-- this is the existing axis
                data = val['surface']['surface']
                shade = np.array(val['surface']['shade'])

                x, y, z = zip(*shade)
                z = map(float, z)
                grid_x, grid_y = np.mgrid[min(x):max(x):100j, min(y):max(y):100j]
                grid_z = griddata((x, y), z, (grid_x, grid_y), method='cubic')
                grid_z = np.nan_to_num(grid_z)
                grid_z /= grid_z.max()

                surf = self.a2.plot_surface(grid_x, grid_y, grid_z, rstride=1, cstride=1, cmap='jet',  linewidth=0, antialiased=False, shade=False)
                self.canvas2.draw() #<- this has to be here to be able to use .get_facecolors()
                fc = surf.get_facecolors()

                self.a2.cla()

                x, y, z = zip(*data)
                z = map(float, z)
                grid_x, grid_y = np.mgrid[min(x):max(x):100j, min(y):max(y):100j]
                grid_z = griddata((x, y), z, (grid_x, grid_y), method='cubic')
                grid_z = np.nan_to_num(grid_z)

                self.a2.plot_surface(grid_x, grid_y, grid_z, facecolors=fc, rstride=1, cstride=1, linewidth=0, antialiased=False, shade=False)

                self.canvas2.draw()

我从队列中获取值,这就是它可能有点不同寻常的原因。从队列中收到数据后,我想如上所述更新我的情节。不幸的是,我的数据长度与宽度不同,否则我可以使用 Olivers 的第一部分。

有人知道如何以优雅的方式解决这个问题吗?


更新:这里是数据集:

这是两个数据集:

data:
[(7.0, 2025.0, 0.14473006433340618), (7.0, 2030.0, 0.14062607337060892), (7.0, 2020.0, 0.1472362005164195), (7.0, 2040.0, 0.1319299850069502), (7.0, 2050.0, 0.12497732155598347), (38.0, 2040.0, 0.13013012553239645), (38.0, 2050.0, 0.12603323962393054), (38.0, 2020.0, 0.13923258922827567), (38.0, 2025.0, 0.1371105447700807), (38.0, 2030.0, 0.13509217383084055), (7.0, 2035.0, 0.13590798149865668), (7.0, 2055.0, 0.12122832793319385), (38.0, 2045.0, 0.1283033928063951), (38.0, 2055.0, 0.12376727418426803), (7.0, 2045.0, 0.12747859242231532), (38.0, 2035.0, 0.13268757208364956), (28.0, 2040.0, 0.1336849736130551), (28.0, 2045.0, 0.1304881237751081), (28.0, 2050.0, 0.12838196945626767), (28.0, 2055.0, 0.12594690413524617), (28.0, 2020.0, 0.1426266123329183), (28.0, 2025.0, 0.14105151195673143), (28.0, 2030.0, 0.1373925658286551), (28.0, 2035.0, 0.13591663964396278), (0.0, 2040.0, 0.13520161504277875), (0.0, 2045.0, 0.12954944890882458), (0.0, 2050.0, 0.12265378802459166), (0.0, 2055.0, 0.11829387116926045), (0.0, 2020.0, 0.15941121559558222), (0.0, 2025.0, 0.15264786078400508), (0.0, 2030.0, 0.14752256519025417), (0.0, 2035.0, 0.1410671600261568), (14.0, 2055.0, 0.12290037442735217), (14.0, 2050.0, 0.12609729724766153), (14.0, 2045.0, 0.12957885633601618), (14.0, 2040.0, 0.13191236031636167), (14.0, 2035.0, 0.13486885042437866), (14.0, 2030.0, 0.13735387420193756), (14.0, 2025.0, 0.14117139286403094), (14.0, 2020.0, 0.14410654811736545), (21.0, 2040.0, 0), (21.0, 2045.0, 0.1280055085205311), (21.0, 2050.0, 0.1253472936767727), (21.0, 2055.0, 0.12311151990554384), (21.0, 2020.0, 0.14150097628342895), (21.0, 2025.0, 0.13862160845657018), (21.0, 2030.0, 0.1357506086172204), (21.0, 2035.0, 0.1334635475535782), (35.0, 2040.0, 0), (35.0, 2045.0, 0.12909917255032188), (35.0, 2050.0, 0.12671861528494266), (35.0, 2055.0, 0.12432370882456634), (35.0, 2020.0, 0.14029296457584772), (35.0, 2025.0, 0.13813227231612185), (35.0, 2030.0, 0.13606666884642726), (35.0, 2035.0, 0)]
shape:
[(7.0, 2025.0, 1162), (7.0, 2030.0, 381), (7.0, 2020.0, 944), (7.0, 2040.0, 3074), (7.0, 2050.0, 2141), (38.0, 2040.0, 514), (38.0, 2050.0, 393), (38.0, 2020.0, 15), (38.0, 2025.0, 7), (38.0, 2030.0, 30), (7.0, 2035.0, 63), (7.0, 2055.0, 1676), (38.0, 2045.0, 123), (38.0, 2055.0, 2), (7.0, 2045.0, 3924), (38.0, 2035.0, 23), (28.0, 2040.0, 7238), (28.0, 2045.0, 3908), (28.0, 2050.0, 16383), (28.0, 2055.0, 2835), (28.0, 2020.0, 2058), (28.0, 2025.0, 1481), (28.0, 2030.0, 831), (28.0, 2035.0, 1386), (0.0, 2040.0, 9437), (0.0, 2045.0, 0), (0.0, 2050.0, 0), (0.0, 2055.0, 0), (0.0, 2020.0, 0), (0.0, 2025.0, 901), (0.0, 2030.0, 0), (0.0, 2035.0, 0), (14.0, 2055.0, 384), (14.0, 2050.0, 1482), (14.0, 2045.0, 928), (14.0, 2040.0, 800), (14.0, 2035.0, 0), (14.0, 2030.0, 21), (14.0, 2025.0, 124), (14.0, 2020.0, 400), (21.0, 2040.0, 598), (21.0, 2045.0, 385), (21.0, 2050.0, 397), (21.0, 2055.0, 817), (21.0, 2020.0, 40), (21.0, 2025.0, 13), (21.0, 2030.0, 26), (21.0, 2035.0, 24), (35.0, 2040.0, 141), (35.0, 2045.0, 365), (35.0, 2050.0, 324), (35.0, 2055.0, 49), (35.0, 2020.0, 294), (35.0, 2025.0, 422), (35.0, 2030.0, 112), (35.0, 2035.0, 22)]

解决方法: 我找到了解决问题的方法:

self.a2.cla()
data = np.array(val['surface']['surface'])
x, y, z, colors = data[:,0], data[:,1], data[:,2], data[:,3],
grid_x, grid_y = np.mgrid[min(x):max(x):50j, min(y):max(y):50j]
z = griddata((x, y), z, (grid_x, grid_y), method='cubic')
colors = griddata((x, y), colors, (grid_x, grid_y), method='cubic')
y, x = grid_y.ravel(), grid_x.ravel()

y_coords, x_coords = np.unique(y), np.unique(x)
y_centers, x_centers = [ arr[:-1] + np.diff(arr)/2 for arr in (y_coords, x_coords)]

# Convert back to a 2D grid, required for plot_surface:
Y = y.reshape(y_coords.size, -1)
X = x.reshape(-1, x_coords.size)
Z = z.reshape(X.shape)
C = colors.reshape(X.shape)

#Normalize the colors to fit in the range 0-1, ready for using in the colormap:
Z -= Z.min()
Z /= Z.max()

C -= C.min()
C /= C.max()

interp_func = RectBivariateSpline(x_coords, y_coords, C.T, kx=1, ky=1) # the kx, ky define the order of interpolation. Keep it simple, use linear interpolation.

self.a2.plot_surface(X,Y,Z, facecolors=cm.hot(interp_func(x_centers, y_centers).T), rstride=1,  cstride=1, linewidth=1, antialiased=False, shade=False) # only added because of this very limited dataset

self.canvas2.draw()

这并不能解决 get_facecolors 的问题,但如果它能正常工作的话。对我来说还好。

这是它的样子: