## Where communities thrive

• Join over 1.5M+ people
• Join over 100K+ communities
• Free without limits
• Create your own community
##### Activity
• Jan 31 2019 16:26
kmuehlbauer commented #1568
• Jan 31 2019 16:15
kmuehlbauer commented #1568
• Jan 31 2019 15:53
djhoese commented #1568
• Jan 31 2019 15:46
kmuehlbauer edited #1568
• Jan 31 2019 15:44
kmuehlbauer opened #1568
• Jan 31 2019 15:32
djhoese commented #1566
• Jan 31 2019 15:30
djhoese commented #1567
• Jan 31 2019 14:18
GuillaumeFavelier commented #1561
• Jan 31 2019 14:15
GuillaumeFavelier commented #1561
• Jan 31 2019 12:46
opekar synchronize #1130
• Jan 31 2019 09:54
kmuehlbauer commented #1567
• Jan 31 2019 09:53
kmuehlbauer synchronize #1567
• Jan 31 2019 09:37
kmuehlbauer labeled #1567
• Jan 31 2019 09:37
kmuehlbauer labeled #1567
• Jan 31 2019 09:37
kmuehlbauer labeled #1563
• Jan 31 2019 09:36
kmuehlbauer labeled #1563
• Jan 31 2019 09:28
kmuehlbauer commented #1567
• Jan 31 2019 09:27
kmuehlbauer synchronize #1567
• Jan 31 2019 09:19
kmuehlbauer assigned #1563
• Jan 31 2019 09:17
kmuehlbauer opened #1567
cgharib
@cgharib

Hi everyone !

So I'm trying to change two vertices coordinates over time in python and then send this information to OpenGL. I was able to do it in glumpy using :

x = .5*np.cos(totalTime)
program['position'] = np.array([(x, 0.), (-x, 0.)])

In vispy however it has been more complicated. I looked a bit in the code and finally managed to do it using :

x = .5*np.cos(totalTime)
newPos = np.array([(x, 0.), (-x, 0.)])
self.program['position'].base.set_subdata(newPos.astype(np.float32))

So this works but I was wondering about why this is so different and wether it's really the simplest way to do that. Does anyone have an idea ? Thank you !

(I think my variables are quite clear but if not I would be happy to send a more complete source.)

David Hoese
@djhoese
@cgharib It is hard to tell based on what you've provided so far. Something like what you have in glumpy should have worked in vispy. If not then I would have expected self.program['position'][:] = np.array(...) to work. What kind of error, if any, are you getting?
cgharib
@cgharib

Hey. Thanks for your answer.

With :

self.program['position'][:] = np.array([(x, 0.), (-x, 0.)]) #even with .astype(np.float32)

I get the following error :

File "/home/.../vispy/gloo/buffer.py", line 400, in __setitem__
raise RuntimeError("Cannot set data on Buffer view")
RuntimeError: Cannot set data on Buffer view

Looking in buffer.py I concluded that I had to access to the DataBuffer that is associated with this DataBufferView. Therefore I added .base. Then I found the method set_subdata in DataBuffer. Finally I had to convert my np.float64 x to a np.float32 (because of line 426 in buffer.py).

The relevant variables are instantiated that way (in the __init__ method):

self.program = gloo.Program(vertex, fragment, count=2)
self.program['position'] = [(.5, 0), (-.5, 0)]

And I'm updating the position this way :

class MyCanvas(app.Canvas):
def __init__....
...
self.timer = app.Timer('auto', self.on_timer)
self.timer.start()
def on_timer(self, event):
totalTime = self.timer.elapsed
x =...
newPos =...
self.program['position'].base.set_subdata(newPos.astype(np.float32))
self.update()
Kai MÃ¼hlbauer
@kmuehlbauer
@cgharib I would have a look into this too. Would you mind creating a minimal reproducible example we could run?
David Hoese
@djhoese
Ok so that error makes sense now that I think about it with [:]. But what do you get with self.program['position'] = np.array(...)?
cgharib
@cgharib
Thanks. So here's the code that works :
from vispy import app, gloo
import numpy as np

vertex = """
attribute vec2 position;

void main() {
gl_Position = vec4(position, 0., 1.);
}
"""

fragment = """
void main() {
gl_FragColor = vec4(1., 0., 0., 1.);
}
"""

class MyCanvas(app.Canvas):
def __init__(self):
app.Canvas.__init__(self)

self.program = gloo.Program(vertex, fragment, count=2)
self.program['position']= [(.5, 0), (-.5, 0)]

self.timer = app.Timer("auto", self.on_timer)
self.timer.start()

self.show()

def on_timer(self, event):
totalTime = self.timer.elapsed
x = .5*np.cos(totalTime)
newPos = np.array([(x, 0), (-x, 0)])
self.program['position'].base.set_subdata(newPos.astype(np.float32))
self.update()

def on_draw(self, event):
gloo.clear()
self.program.draw("lines")

c = MyCanvas()
app.run()

And with

self.program['position'] = newPos

I get the following error :

File "testVispy.py", line 34, in on_timer
self.program['position'] = newPos
File "/home/chams/.local/lib/python3.6/site-packages/vispy/gloo/program.py", line 409, in __setitem__
vbo.set_data(data)
File "/home/chams/.local/lib/python3.6/site-packages/vispy/gloo/buffer.py", line 381, in set_data
raise RuntimeError("Cannot set data on buffer view.")
RuntimeError: Cannot set data on buffer view.
David Hoese
@djhoese
@cgharib This is definitely a surprise to me, but I don't have the historic context for why it is this way. A workaround is to reuse a VertexBuffer (or other buffer type) yourself, update the data, then reset that buffer. Like this with _pos:
class MyCanvas(app.Canvas):
def __init__(self):
app.Canvas.__init__(self)

self.program = gloo.Program(vertex, fragment, count=2)
self._pos = gloo.VertexBuffer()
self.program['position'] = np.array([[.5, 0], [-.5, 0]], dtype=np.float32)

self.timer = app.Timer("auto", self.on_timer)
self.timer.start()

self.show()

def on_timer(self, event):
totalTime = self.timer.elapsed
x = .5*np.cos(totalTime)
newPos = np.array([(x, 0), (-x, 0)])
self._pos.set_data(newPos.astype(np.float32))
self.program['position'] = self._pos
self.update()
David Hoese
@djhoese

@almarklein @rougier Any memory why gloo.Program creates a View for each of the buffers? Meaning self.program['position'] is a DataBufferView when the program is created?

@cgharib Actually if you set the VertexBuffer in the __init__ and then do self.program['position'] = newPos.astype(np.float32) then it seems to work. The main problem seems to be that the gloo.Program creation defaults to creating a View. I'm not exactly sure why the original self.program['position'] = works as that should be a View too.

Nicolas P. Rougier
@rougier
Not sure, but maybe this is for handling the case where buffers are only one structured buffer (for example mixing position and color) and the view offers a consistent view...
Almar Klein
@almarklein
No idea ...
cgharib
@cgharib

Hey. Thanks for all your answers. So here's how I would write it based on @djhoese 's code.

import numpy as np
from vispy import app, gloo

vertex = """
attribute vec2 position;

void main() {
gl_Position = vec4(position, 0., 1.);
}
"""

fragment = """
void main() {
gl_FragColor = vec4(1.,0.,0.,1.);
}
"""

class MyCanvas(app.Canvas):
def __init__(self):
app.Canvas.__init__(self)
self.program = gloo.Program(vertex, fragment, count=2)

self.vertexBuffer = gloo.VertexBuffer(np.array([(.5, 0), (-.5, 0)], dtype=np.float32))
self.program['position'] = self.vertexBuffer

self.timer = app.Timer('auto', self.on_timer)
self.timer.start()

self.show()

def on_draw(self, event):
gloo.clear()
self.program.draw('lines')

def on_timer(self, event):
totalTime = self.timer.elapsed
x = .5*np.cos(totalTime)
newPos = np.array([(x, 0), (-x, 0)], dtype=np.float32)
self.vertexBuffer.set_data(newPos)
self.update()

c = MyCanvas()
app.run()

Does it seem idiomatic to you ? Thanks a lot !

David Hoese
@djhoese
@cgharib I personally would change your timer handler to do self.program['position'] = newPos. It feels more future-proof and avoids the possibility of the VertexBuffer being copied inside the Program and your set_data not having an effect. Hopefully that makes sense. Either way should work so do what feels good to you.
cgharib
@cgharib
I understand. Thanks !
Thomas Doman
@tjjdoman_gitlab
Hello all, I am trying to specify a z position of an EllipseVisual's center so that I can layer it on image visuals, but it seems as if that is not allowed as only the first 2 elements of the passed center are used to create the vertices of the ellipse. Is there something I am missing or does this require an edit?
David Hoese
@djhoese
@tjjdoman_gitlab It looks like you are right that the center point is only 2D. You could try using an STTransform to force the Z position by doing ellipse.transform = STTransform(translate=(0, 0, some_z_shift)). You may also run into issues with drawing order between the Image and Ellipse where you may need to do something like ellipse.order = -5, but see if the Z position works well enough first.
IsolatedSushi2
@IsolatedSushi2
Hey, quick question. Im working with a 3d point cloud. I can't find how to make the camera rotate around a specific point (not the center perse). How can this be done?
David Hoese
@djhoese
@IsolatedSushi2 What camera are you using? And if the point isn't the center, then what is it as far as the camera thinks of it? Or how is it related to the center of the view?
IsolatedSushi2
@IsolatedSushi2
@djhoese I'm using the turntable camera with the vispy.scene. I have a bunch of points in 3d space, and would like to have the camera rotate around its center of mass instead of the origin point
David Hoese
@djhoese
@IsolatedSushi2 Does doing something like camera.center = (x, y, z) work? If not, why not? You will need to calculate the center of mass to become this origin point but otherwise looking at the code this should "just work"
Thomas Doman
@tjjdoman_gitlab
@djhoese Thanks, your advice helped! Have not needed to specify the order yet, but will keep that in mind.
Omicron91
@Omicron91

Hello guys. I'm developing a software to visualize thickness maps by using PyQt as Desktop Framework, however, I'm experiencing some problems. The central widget is a grid layout with multiple scatter plots, in a sub grid each, When i minimize and maximize the window multiple times the layout tends to collapse, then i get the following error

WARNING: Traceback (most recent call last):
File ".\src\CrushingApp.py", line 324, in <module>
sys.exit(app.exec_())
File "C:\Users\site-packages\vispy\app\backends\_qt.py", line 508, in event
out = super(QtBaseCanvasBackend, self).event(ev)
File "C:\Users\site-packages\vispy\app\backends\_qt.py", line 825, in paintGL
self._vispy_canvas.events.draw(region=None)
File "C:\Users\\site-packages\vispy\util\event.py", line 455, in __call__
self._invoke_callback(cb, event)
File "C:\Users\site-packages\vispy\util\event.py", line 475, in _invoke_callback
self, cb_event=(cb, event))
<< caught exception here: >>
File "C:\Users\site-packages\vispy\util\event.py", line 471, in _invoke_callback
cb(event)
File "C:\Users\site-packages\vispy\scene\canvas.py", line 217, in on_draw
self._draw_scene()
File "C:\Users\site-packages\vispy\scene\canvas.py", line 266, in _draw_scene
self.draw_visual(self.scene)
File "C:\Users\site-packages\vispy\scene\canvas.py", line 304, in draw_visual
self.add_with_artificial_variable(expr)
File "C:\Users\site-packages\vispy\ext\_bundled\cassowary\simplex_solver.py", line 381, in
add_with_artificial_variable
raise RequiredFailure()
vispy.ext._bundled.cassowary.error.RequiredFailure
ERROR: Invoking <bound method SceneCanvas.on_draw of <CanvasMapaEspesores (PyQt5) at 0x149ed69fe08>> for DrawEvent

is there a way to avoi

avoid/fix* this
Omicron91
@Omicron91
sometimes collapse the entire layout
David Hoese
@djhoese
@Omicron91 What version of vispy are you using? We no longer use cassowary as our grid solver. Could you try this with the most recent release of vispy?
Omicron91
@Omicron91
I'm using 0.6.4, i'll try. The team had been working for a while with this version, so i don't know if it could cause problems
David Hoese
@djhoese
It might. Depending on what you/they were using, but it will be hard for us to help with cassowary issues as it has been deprecated for quite a few releases now
Omicron91
@Omicron91
Now i got the last version and It is working as expected by the moment. Now i have another problem. I need to put some annotations in a view with a turntable camera, I'm using vispy.scene.visuals.Text which is a 2D Text which follows the camera rotation, i would like to set a background and i tried by creating a plane, set transform properties then copy the rotation of the camera, but the roll angle is not working on turntable. Is there another way to set a background rectangle for a vispy.scene.visuals.Text?
David Hoese
@djhoese
@Omicron91 Could you make a minimal example? It is hard to guess the best way forward going on just your description
Omicron91
@Omicron91
this is that i want
self.t2 = scene.visuals.Text('Test Text', parent=self.view.scene, color='green')
self.t2.font_size = 14

self.plane = scene.visuals.Plane(
width=1000,
height=300,
parent=self.t2
)

self.plane.transform = vispy.visuals.transforms.STTransform(translate=(0, 0, 0),
scale=(1., 1., 1.)).as_matrix()

def on_mouse_move(self, event):
if event.button == 1 and event.is_dragging:
self.plane.transform.reset()

self.plane.transform.rotate(self.view.camera.azimuth, (0, 0, 1))
self.plane.transform.rotate(90 - self.view.camera.elevation, (0, 1, 0))
self.plane.transform.rotate(self.view.camera.roll, (1, 0, 0))
This is what i tried
in the code of vispy the roll camera angle appears as 'not implemented' :(
David Hoese
@djhoese
And if you don't do any of that custom self.plane.transform stuff (not even setting it) then what happens? The Plane rotates with the camera but the text stays "2D"?
Omicron91
@Omicron91
The text is ok, always i can seen when i move the camera, the main problem is with the plane, I can't achieve to follow the text rotation, so it could look like a frame
David Hoese
@djhoese
And you say that self.view.camera.roll raises a not implemented error?
Omicron91
@Omicron91
nop, but in the code is there a comment that says that roll is not yet implemented. Is there any easy way to give a background color for a text? i need to visualize the text as the expected image in any angle, like a nameplate's player in a MMORPG game
David Hoese
@djhoese
I understand what you're going for. I just don't understand what is going wrong. I don't have a lot of experience with the TurntableCamera but if you could provide me an end to end example (a small example that I can copy/paste and run locally) then I might have some ideas. So far I'm not really sure exactly how it is wrong since I haven't played with it myself
Omicron91
@Omicron91
import numpy as np
import vispy.scene
from vispy.scene import visuals
from vispy.visuals import text

class CustomCanvas(vispy.scene.SceneCanvas):

def __init__(self):
super(CustomCanvas, self).__init__(keys='interactive', show=True)

self.unfreeze()

self.view = self.central_widget.add_view()

self.xyz_top = None
self.textLabelMax = None
self.backgroundLabelMax = None

self.events.mouse_move.connect(self.on_mouse_move)

self.freeze()

def on_mouse_move(self, event):

if(event.button == 1 and event.is_dragging):

self.backgroundLabelMax.transform.reset()

self.backgroundLabelMax.transform.rotate(self.view.camera.azimuth, (0, 0, 1))
self.backgroundLabelMax.transform.rotate(90 - self.view.camera.elevation, (1, 0, 0))

self.backgroundLabelMax.transform.translate(self.xyz_top)

def draw_cloud_points(self):

pos = np.random.normal(size=(100000, 3), scale=0.2)
# one could stop here for the data generation, the rest is just to make the
# data look more interesting. Copied over from magnify.py
centers = np.random.normal(size=(50, 3))
indexes = np.random.normal(size=100000, loc=centers.shape[0]/2.,
scale=centers.shape[0]/3.)
indexes = np.clip(indexes, 0, centers.shape[0]-1).astype(int)
scales = 10**(np.linspace(-2, 0.5, centers.shape[0]))[indexes][:, np.newaxis]
pos *= scales
pos += centers[indexes]

# create scatter object and fill in the data
scatter = visuals.Markers()
scatter.set_data(pos, edge_color=None, face_color=(1, 1, 1, .5), size=5)
self.view.add(scatter)

# Adding text label at center / top (Z axis)

self.xyz_top = (pos[:,0].max(), pos[:,1].max(), pos[:,2].max())
self.textLabelMax = visuals.Text(pos=self.xyz_top, text="Test_Label_Max", font_size=24, color="white", parent=self.view.scene)

# Adding plane as background for texts
self.backgroundLabelMax = visuals.Plane(width=5, height = 1, color=(1, 0, 0, 0.4), parent=self.view.scene)
self.backgroundLabelMax.transform = vispy.scene.transforms.STTransform(
scale=(1, 1, 1),
translate=self.xyz_top
).as_matrix()

# Adding turntable with ortographic view
self.view.camera = vispy.scene.TurntableCamera(fov=0, azimuth=0, elevation=90, roll=0)

# Auto focus
self.view.camera.set_range()

def main():
custom_canvas = CustomCanvas()
custom_canvas.draw_cloud_points()

if __name__ == '__main__':
import sys
if sys.flags.interactive != 1:
main()
vispy.app.run()
David Hoese
@djhoese
although that isn't accurate, it is kind of a cool effect
I'll try to find time to look into this more today or sometime this week
David Hoese
@djhoese
There has to be math operation (np.dot or something) but it isn't coming to me.
Surprisingly doing self.backgroundLabelMax.transform.matrix = self.view.camera.transform.matrix and self.backgroundLabelMax.transform.translate(self.xyz_top) gets it pretty close...somehow
Omicron91
@Omicron91
Oh nice, that's what I was looking for. This should be enough. Thanks for helping!
Omicron91
@Omicron91
Now it's working. I think this is very usefull when u want to visualize annotations over 3D things
import numpy as np
import vispy.scene
from vispy.scene import visuals
from vispy.visuals import text

class CustomCanvas(vispy.scene.SceneCanvas):

def __init__(self):
super(CustomCanvas, self).__init__(keys='interactive', show=True)

self.unfreeze()

self.view = self.central_widget.add_view()

self.xyz_top = None
self.textLabelMax = None
self.backgroundLabelMax = None
self.bgScale = [1, 1, 1]
self.events.mouse_move.connect(self.on_mouse_move)
self.events.mouse_wheel.connect(self.on_mouse_wheel)

self.freeze()

def on_mouse_move(self, event):

if(event.button == 1 and event.is_dragging):
self.backgroundLabelMax.transform.reset()
self.backgroundLabelMax.transform.matrix = self.view.camera.transform.matrix
self.backgroundLabelMax.transform.translate(self.xyz_top)

def on_mouse_wheel(self, event):
pass
"""
self.backgroundLabelMax.transform.reset()
delta = event.delta[1]

if(delta < 0):
print(delta)
if self.view.camera.scale_factor >= 30:
self.view.camera.scale_factor = 30

else:

if self.view.camera.scale_factor <= 10:
self.view.camera.scale_factor = 10

self.backgroundLabelMax.transform.matrix = self.view.camera.transform.matrix
self.backgroundLabelMax.transform.scale(self.bgScale)
self.backgroundLabelMax.transform.translate(self.xyz_top)
"""

def draw_cloud_points(self):

pos = np.random.normal(size=(100000, 3), scale=0.2)
# one could stop here for the data generation, the rest is just to make the
# data look more interesting. Copied over from magnify.py
centers = np.random.normal(size=(50, 3))
indexes = np.random.normal(size=100000, loc=centers.shape[0]/2.,
scale=centers.shape[0]/3.)
indexes = np.clip(indexes, 0, centers.shape[0]-1).astype(int)
scales = 10**(np.linspace(-2, 0.5, centers.shape[0]))[indexes][:, np.newaxis]
pos *= scales
pos += centers[indexes]

# create scatter object and fill in the data
scatter = visuals.Markers()
scatter.set_data(pos, edge_color=None, face_color=(1, 1, 1, .5), size=5)
self.view.add(scatter)

# Adding turntable with ortographic view
self.view.camera = vispy.scene.TurntableCamera(fov=0)

# Adding plane as background for texts
self.backgroundLabelMax = visuals.Rectangle(center = (0, 0, 0), width=3.5, height = 1, color=(1, 0, 0, 0.4), radius=0.3, parent=self.view.scene)
# Adding text label at center / top (Z axis)

self.xyz_top = (pos[:,0].max(), pos[:,1].max(), pos[:,2].max())
self.textLabelMax = visuals.Text(pos=(0, 0, 0), text="Test_Label_Max", font_size=18, color="white", parent=self.backgroundLabelMax)

self.backgroundLabelMax.transform = vispy.scene.transforms.STTransform(
scale=(1, 1, 1),
translate=(0, 0, 0)
).as_matrix()
self.backgroundLabelMax.transform.matrix = self.view.camera.transform.matrix
self.backgroundLabelMax.transform.translate(self.xyz_top)
# Auto focus
self.view.camera.set_range()

def main():
custom_canvas = CustomCanvas()
custom_canvas.draw_cloud_points()

if __name__ == '__main__':
import sys
if sys.flags.interactive != 1:
main()
vispy.app.run()
m3atwad
@m3atwad
Do we have to build the documentation like this example recommends?