I'm using VisPy
to plot a surface, but the function scene.visuals.SurfacePlot
only has the parameter color
,without the parameter colormap
. Does anyone know how to use colormap
in surface plotting?
2 Answers
One must set the colors on a per vertex basis ie vertex_colors. One way this can be accomplished is as follows;
import vispy.plot as vp
from vispy import color
from vispy.util.filter import gaussian_filter
import numpy as np
z = np.random.normal(size=(250, 250), scale=200)
z[100, 100] += 50000
z = gaussian_filter(z, (10, 10))
fig = vp.Fig(show=False)
cnorm = z / abs(np.amax(z))
c = color.get_colormap("hsl").map(cnorm).reshape(z.shape + (-1,))
c = c.flatten().tolist()
c=list(map(lambda x,y,z,w:(x,y,z,w), c[0::4],c[1::4],c[2::4],c[3::4]))
#p1 = fig[0, 0].surface(z, vertex_colors=c) # why doesn't vertex_colors=c work?
p1 = fig[0, 0].surface(z)
p1.mesh_data.set_vertex_colors(c) # but explicitly setting vertex colors does work?
fig.show()
Note the use of the explicit setter set_vertex_colors worked fine. Unfortunately (a bug possibly) when passing c
to surface(z, vertex_colors=c)
ran without error but did not change the per vertex colors. Conclusion: use explicit set_vertex_colors
.
Currently, there appears to be a bug that's keeping the colors
parameter of SurfacePlot from working. Giving the surface anything but a solid color would probably have to go down that path. So it may not be possible at this time without altering the source code.
For what it's worth, I believe the following would work if this bug wasn't present:
import vispy.plot as vp
from vispy import color
fig = vp.Fig(show=False)
cnorm = z / abs(np.amax(z))
colors = color.get_colormap("hsl").map(cnorm).reshape(z.shape + (-1,))
fig[0, 0].surface(z, x=x, y=y, colors=colors)
Basically, you normalize the data to be between 0 and 1, and then map those values to a colormap. This will return a 3D array of RGB colors that you can pass to SurfacePlot's colors
parameter.

- 2,644
- 3
- 20
- 29
-
I've tried this way,but I got an error said `colors must be 2D if indexed is None` Do you mean I should add this script to my code? Here is my code: `fig = vp.Fig(show=False) cnorm = z / abs(amax(z)) colors = color.get_colormap("cool").map(cnorm).reshape(z.shape + (-1,)) p1 = scene.visuals.SurfacePlot(z=solver0(I, f, c, bc, Lx, Ly, nx, ny, dt, 0,user_action=None),shading='smooth',colors=colors)` – Richard.L May 17 '16 at 07:39
-
Right. You've run into the bug that I've mentioned. The documentation says that the color array must be 2D, but the code requires it to be 3D. But if you flatten the array to be 2D, you'll run into a bug where it tries to access an underlying structure that hasn't been initialized yet. So, like I said. you'll probably have to wait for it be fixed, or fix it yourself. You might try the Volume object in vispy.scene, which takes a cmap argument – orodbhen May 17 '16 at 11:39