Question 1: I am trying to highlight particular section from Vispy Surface Plot example in a particular colour somewhat similar to below modified image.
Question 2: Similarly I would like to add an image data as overlay texture to the Vispy surface plot
Can SurfacePlotVisual be used for this? I am unable to find any examples of the SurfacePlotVisual on the internet.
Can anyone please direct me to the efficient way of getting it done using vispy. Thanks
Update 1: Adding Sample code for testing
import sys
import numpy as np
from vispy import app, scene, color
from vispy.util.filter import gaussian_filter
from vispy.visuals.filters import TextureFilter
from vispy.io import imread, load_data_file, read_mesh
canvas = scene.SceneCanvas(keys='interactive', bgcolor='w')
view = canvas.central_widget.add_view()
view.camera = scene.TurntableCamera(up='z', fov=60)
# Simple surface plot example
# x, y values are not specified, so assumed to be 0:50
z = np.random.normal(size=(250, 250), scale=200)
z[100, 100] += 50000
print(z.shape)
z = gaussian_filter(z, (10, 10))
p1 = scene.visuals.SurfacePlot(z=z) # , color=(0.3, 0.3, 1, 1))
p1.transform = scene.transforms.MatrixTransform()
p1.transform.scale([1 / 249., 1 / 249., 1 / 249.])
p1.transform.translate([-0.5, -0.5, 0])
#verts = p1._meshdata.get_vertices()
verts = p1._meshdata.get_vertices()[:, :2]
texcoords = (verts - verts.min()) / (verts.max() - verts.min())
texture = imread('spot.png')
texture = np.flip(texture, 0) // flip added to get correct position of the image
print("spot.shape:", texture.shape)
print("textcoords:", texcoords)
texture_filter = TextureFilter(texture, texcoords)
p1.attach(texture_filter)
view.add(p1)
xax = scene.Axis(pos=[[-0.5, -0.5], [0.5, -0.5]], tick_direction=(0, -1),
font_size=16, axis_color='k', tick_color='k', text_color='k',
parent=view.scene)
xax.transform = scene.STTransform(translate=(0, 0, -0.2))
yax = scene.Axis(pos=[[-0.5, -0.5], [-0.5, 0.5]], tick_direction=(-1, 0),
font_size=16, axis_color='k', tick_color='k', text_color='k',
parent=view.scene)
yax.transform = scene.STTransform(translate=(0, 0, -0.2))
# Add a 3D axis to keep us oriented
axis = scene.visuals.XYZAxis(parent=view.scene)
if __name__ == '__main__':
canvas.show()
if sys.flags.interactive == 0:
app.run()
Update 2:
Have updated above code and output image for reference.
Surface plot output is as above... Would like to remove surface plot shade and instead would like to have same color output for the surface plot output as compared to image....
The set_data
method of the SurfacePlotVisual takes an array of colors:
You should be able to pass whatever colors you want to that as an RGBA array (MxNx4). Note these are colors for the vertices apparently (based on the code I'm seeing) so colors will be interpolated between vertices.
The SurfacePlot is a subclass of the MeshVisual which is able to have a TextureFilter
applied to it. I've never done it, but theoretically you should be able to follow this example to add a texture to your SurfacePlot:
https://vispy.org/gallery/scene/mesh_texture.html
The key parts are the loading of the image data from spot.png
and then creating and attaching the TextureFilter
.
Here's what I get if I change the texcoords line to:
verts = p1._meshdata.get_vertices()[:, :2]
Kind of creepy. The point is that we're just making an array that maps the individual surface plot verticies (the mesh vertices) to points on the image. These coordinates need to be between 0 and 1. So we're cheating and taking the vertex coordinates of the mesh and normalizing them between 0 and 1. This may not be anything like what you want, but the point is we have texcoords
with a shape of (N, 2) where N is the number of mesh vertices and an (x, y) coordinate for each.