Markers
(for example), you can do that with Compound._subvisuals[3].size
(3 is the index of the Markers
subvisual`)
@dvsphanindra Here it is: https://stackoverflow.com/questions/70193398/vispy-2d-coordinate-x-y-of-a-point-of-an-image-inside-a-scenecanvas
See my comment there, but please respond here (unless that was your question)
import numpy as np
import sys
from vispy import scene
def ImageOnClickRelease(event):
if event.button == 1:
print("Position: ", event.pos)
print(view.camera.center, view.camera.get_state(), "map= ", transform.map(event.pos))
canvas = scene.SceneCanvas(keys='interactive', bgcolor='white', size=(800, 600), show=True)
view = canvas.central_widget.add_view()
Set 2D camera (the camera will scale to the contents in the scene)
view.camera = scene.PanZoomCamera()
view.camera.flip = (0, 1, 0) # Y-Axis should be flipped for displaying images
canvas.events.mouse_release.connect(ImageOnClickRelease)
img_data = np.zeros((100,100))
points=np.random.randint(100,size=(30,2))
print(points)
for p in points:
img_data[p[0],p[1]] = 0.5
image_visual = scene.visuals.Image(img_data, cmap='grays', clim=(0,1), parent=view.scene)
view.camera.set_range(margin=0)
transform = image_visual.transforms.get_transform()
if name == 'main' and sys.flags.interactive == 0:
canvas.app.run()
get_transform()
pass map_to="canvas"
and then .imap(event.pos)
will give you the correct X/Y coordinate on the image. So that solves the mouse click -> image location problem, but you say you want to know where the bright pixels are. Are you the user supposed to click on the bright pixels? What is your end goal? I'm confused because couldn't you check the image data without the clicking to find the bright spots?
map()
and imap()
. I have noticed that the pixel info is in the first two coordinates returned by imap()
. What are the remaining two coordinates?
@dvsphanindra The transforms are going between coordinate systems. On your screen you have a 2D set of pixels, but in a Visual you could have a 3D coordinate system (ex. Volumes, Meshes, etc), but your ImageVisual is just 2D so the third z coordinate doesn't mean anything regarding that. The pan/zoom camera is kind of 3D because you are zooming in and out, but it is still a 2D view. I don't remember off the top of my head how the pan/zoom camera internally implements that, but same kind of point.
Typically the 4th dimension is a normalization value. Let me see if I can find the documentation on that, but for your application don't worry too much about it
https://en.wikipedia.org/wiki/Homogeneous_coordinates
Don't ask me any questions about it though. I only ever know as much as I need to when I need to
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.)
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()
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.
_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()
@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.
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 !
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.
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.
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