napari-plot-profile
napari-plot-profile copied to clipboard
WIP use mouse_drag_callbacks instead of timer
This will replace the QTimer with a callback sent by the shapes layer...
This doesn't work at the moment, because the callback doesn't pass "self" as parameter...
Error log:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
c:\users\rober\miniconda3\envs\bio1\lib\site-packages\vispy\app\backends\_qt.py in mousePressEvent(self=<vispy.app.backends._qt.CanvasBackendDesktop object>, ev=<PyQt5.QtGui.QMouseEvent object>)
454 if self._vispy_canvas is None:
455 return
--> 456 self._vispy_mouse_press(
self._vispy_mouse_press = <bound method BaseCanvasBackend._vispy_mouse_press of <vispy.app.backends._qt.CanvasBackendDesktop object at 0x000002C531FD5550>>
global native = undefined
ev = <PyQt5.QtGui.QMouseEvent object at 0x000002C55BAC7CA0>
global pos = undefined
ev.pos.x = undefined
ev.pos.y = undefined
global button = undefined
global BUTTONMAP.get = <built-in method get of dict object at 0x000002C52A20DE80>
ev.button = <built-in method button of QMouseEvent object at 0x000002C55BAC7CA0>
global modifiers = undefined
self._modifiers = <bound method QtBaseCanvasBackend._modifiers of <vispy.app.backends._qt.CanvasBackendDesktop object at 0x000002C531FD5550>>
457 native=ev,
458 pos=(ev.pos().x(), ev.pos().y()),
c:\users\rober\miniconda3\envs\bio1\lib\site-packages\vispy\app\base.py in _vispy_mouse_press(self=<vispy.app.backends._qt.CanvasBackendDesktop object>, **kwargs={'button': 1, 'buttons': [], 'last_event': <MouseEvent blocked=False button=None buttons=[]...urces=[] time=1629919884.9780061 type=mouse_move>, 'last_mouse_press': None, 'modifiers': (), 'native': <PyQt5.QtGui.QMouseEvent object>, 'pos': (71, 341), 'press_event': None})
179 # default method for delivering mouse press events to the canvas
180 kwargs.update(self._vispy_mouse_data)
--> 181 ev = self._vispy_canvas.events.mouse_press(**kwargs)
ev = undefined
self._vispy_canvas.events.mouse_press = <vispy.util.event.EventEmitter object at 0x000002C531FD1E80>
kwargs = {'native': <PyQt5.QtGui.QMouseEvent object at 0x000002C55BAC7CA0>, 'pos': (71, 341), 'button': 1, 'modifiers': (), 'buttons': [], 'press_event': None, 'last_event': <MouseEvent blocked=False button=None buttons=[] delta=[0. 0.] handled=False is_dragging=False last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000002C55BAC7CA0> pos=[ 71 341] press_event=None source=None sources=[] time=1629919884.9780061 type=mouse_move>, 'last_mouse_press': None}
182 if self._vispy_mouse_data['press_event'] is None:
183 self._vispy_mouse_data['press_event'] = ev
c:\users\rober\miniconda3\envs\bio1\lib\site-packages\vispy\util\event.py in __call__(self=<vispy.util.event.EventEmitter object>, *args=(), **kwargs={'button': 1, 'buttons': [], 'last_event': <MouseEvent blocked=False button=None buttons=[]...urces=[] time=1629919884.9780061 type=mouse_move>, 'last_mouse_press': None, 'modifiers': (), 'native': <PyQt5.QtGui.QMouseEvent object>, 'pos': (71, 341), 'press_event': None})
451 raise RuntimeError('EventEmitter loop detected!')
452
--> 453 self._invoke_callback(cb, event)
self._invoke_callback = <bound method EventEmitter._invoke_callback of <vispy.util.event.EventEmitter object at 0x000002C531FD1E80>>
cb = <bound method QtViewer.on_mouse_press of <napari._qt.qt_viewer.QtViewer object at 0x000002C52E8381F0>>
event = <MouseEvent blocked=False button=1 buttons=[] delta=[0. 0.] handled=False is_dragging=False last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000002C55BAC7CA0> pos=[ 71 341] press_event=None source=None sources=[] time=1629919884.9996626 type=mouse_press>
454 if event.blocked:
455 break
c:\users\rober\miniconda3\envs\bio1\lib\site-packages\vispy\util\event.py in _invoke_callback(self=<vispy.util.event.EventEmitter object>, cb=<bound method QtViewer.on_mouse_press of <napari._qt.qt_viewer.QtViewer object>>, event=<MouseEvent blocked=False button=1 buttons=[] de...rces=[] time=1629919884.9996626 type=mouse_press>)
469 cb(event)
470 except Exception:
--> 471 _handle_exception(self.ignore_callback_errors,
global _handle_exception = <function _handle_exception at 0x000002C526D14550>
self.ignore_callback_errors = False
self.print_callback_errors = 'reminders'
self = <vispy.util.event.EventEmitter object at 0x000002C531FD1E80>
global cb_event = undefined
cb = <bound method QtViewer.on_mouse_press of <napari._qt.qt_viewer.QtViewer object at 0x000002C52E8381F0>>
event = <MouseEvent blocked=False button=1 buttons=[] delta=[0. 0.] handled=False is_dragging=False last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000002C55BAC7CA0> pos=[ 71 341] press_event=None source=None sources=[] time=1629919884.9996626 type=mouse_press>
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
c:\users\rober\miniconda3\envs\bio1\lib\site-packages\vispy\util\event.py in _invoke_callback(self=<vispy.util.event.EventEmitter object>, cb=<bound method QtViewer.on_mouse_press of <napari._qt.qt_viewer.QtViewer object>>, event=<MouseEvent blocked=False button=1 buttons=[] de...rces=[] time=1629919884.9996626 type=mouse_press>)
467 def _invoke_callback(self, cb, event):
468 try:
--> 469 cb(event)
cb = <bound method QtViewer.on_mouse_press of <napari._qt.qt_viewer.QtViewer object at 0x000002C52E8381F0>>
event = <MouseEvent blocked=False button=1 buttons=[] delta=[0. 0.] handled=False is_dragging=False last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000002C55BAC7CA0> pos=[ 71 341] press_event=None source=None sources=[] time=1629919884.9996626 type=mouse_press>
470 except Exception:
471 _handle_exception(self.ignore_callback_errors,
c:\users\rober\miniconda3\envs\bio1\lib\site-packages\napari\_qt\qt_viewer.py in on_mouse_press(self=<napari._qt.qt_viewer.QtViewer object>, event=<MouseEvent blocked=False button=1 buttons=[] de...rces=[] time=1629919884.9996626 type=mouse_press>)
890 The vispy event that triggered this method.
891 """
--> 892 self._process_mouse_event(mouse_press_callbacks, event)
self._process_mouse_event = <bound method QtViewer._process_mouse_event of <napari._qt.qt_viewer.QtViewer object at 0x000002C52E8381F0>>
global mouse_press_callbacks = <function mouse_press_callbacks at 0x000002C52D9AC550>
event = <MouseEvent blocked=False button=1 buttons=[] delta=[0. 0.] handled=False is_dragging=False last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000002C55BAC7CA0> pos=[ 71 341] press_event=None source=None sources=[] time=1629919884.9996626 type=mouse_press>
893
894 def on_mouse_move(self, event):
c:\users\rober\miniconda3\envs\bio1\lib\site-packages\napari\_qt\qt_viewer.py in _process_mouse_event(self=<napari._qt.qt_viewer.QtViewer object>, mouse_callbacks=<function mouse_press_callbacks>, event=<ReadOnlyWrapper at 0x2c55eeaeac0 for MouseEvent>)
849 layer = self.viewer.layers.selection.active
850 if layer is not None:
--> 851 mouse_callbacks(layer, event)
mouse_callbacks = <function mouse_press_callbacks at 0x000002C52D9AC550>
layer = <Shapes layer 'Shapes' at 0x2c55bacdeb0>
event = <ReadOnlyWrapper at 0x2c55eeaeac0 for MouseEvent at 0x2c55eee5d30>
852
853 def on_mouse_wheel(self, event):
c:\users\rober\miniconda3\envs\bio1\lib\site-packages\napari\utils\interactions.py in mouse_press_callbacks(obj=<Shapes layer 'Shapes'>, event=<ReadOnlyWrapper at 0x2c55eeaeac0 for MouseEvent>)
146 if inspect.isgenerator(gen):
147 try:
--> 148 next(gen)
global next = undefined
gen = <generator object add_line at 0x000002C55EEAD040>
149 # now store iterated genenerator
150 obj._mouse_drag_gen[mouse_drag_func] = gen
c:\users\rober\miniconda3\envs\bio1\lib\site-packages\napari\layers\shapes\_shapes_mouse_bindings.py in add_line(layer=<Shapes layer 'Shapes'>, event=<ReadOnlyWrapper at 0x2c55eeaeac0 for MouseEvent>)
96 corner = np.array(coordinates)
97 data = np.array([corner, corner + full_size])
---> 98 yield from _add_line_rectangle_ellipse(
global _add_line_rectangle_ellipse = <function _add_line_rectangle_ellipse at 0x000002C52DFF4B80>
layer = <Shapes layer 'Shapes' at 0x2c55bacdeb0>
event = <ReadOnlyWrapper at 0x2c55eeaeac0 for MouseEvent at 0x2c55eee5d30>
data = <class 'numpy.ndarray'> (2, 2) float64
global shape_type = undefined
99 layer, event, data=data, shape_type='line'
100 )
c:\users\rober\miniconda3\envs\bio1\lib\site-packages\napari\layers\shapes\_shapes_mouse_bindings.py in _add_line_rectangle_ellipse(layer=<Shapes layer 'Shapes'>, event=<ReadOnlyWrapper at 0x2c55eeaeac0 for MouseEvent>, data=<class 'numpy.ndarray'> (2, 2) float64, shape_type='line')
143 # on press
144 # Start drawing rectangle / ellipse / line
--> 145 layer.add(data, shape_type=shape_type)
layer.add = <bound method Shapes.add of <Shapes layer 'Shapes' at 0x2c55bacdeb0>>
data = <class 'numpy.ndarray'> (2, 2) float64
shape_type = 'line'
146 layer.selected_data = {layer.nshapes - 1}
147 layer._value = (layer.nshapes - 1, 4)
c:\users\rober\miniconda3\envs\bio1\lib\site-packages\napari\layers\shapes\shapes.py in add(self=<Shapes layer 'Shapes'>, data=<class 'numpy.ndarray'> (2, 2) float64, shape_type='line', edge_width=1, edge_color=<class 'numpy.ndarray'> (1, 4) float32, face_color=<class 'numpy.ndarray'> (1, 4) float32, z_index=0)
1995 z_index=z_index,
1996 )
-> 1997 self.events.data(value=self.data)
self.events.data = <napari.utils.events.event.EventEmitter object at 0x000002C55EE38460>
global value = undefined
self.data = [<class 'numpy.ndarray'> (2, 2) float64]
1998
1999 def _init_shapes(
c:\users\rober\miniconda3\envs\bio1\lib\site-packages\napari\utils\events\event.py in __call__(self=<napari.utils.events.event.EventEmitter object>, *args=(), **kwargs={'value': [<class 'numpy.ndarray'> (2, 2) float64]})
573 continue
574
--> 575 self._invoke_callback(cb, event)
self._invoke_callback = <bound method EventEmitter._invoke_callback of <napari.utils.events.event.EventEmitter object at 0x000002C55EE38460>>
cb = <bound method PlotProfile._data_changed_event of <napari_plot_profile._dock_widget.PlotProfile object at 0x000002C55AC1A820>>
event = <Event blocked=False handled=False native=None source=None sources=[] type='data'>
576 if event.blocked:
577 break
c:\users\rober\miniconda3\envs\bio1\lib\site-packages\napari\utils\events\event.py in _invoke_callback(self=<napari.utils.events.event.EventEmitter object>, cb=<bound method PlotProfile._data_changed_event of...ri_plot_profile._dock_widget.PlotProfile object>>, event=<Event blocked=False handled=False native=None source=None sources=[] type='data'>)
605 self.disconnect(cb)
606 return
--> 607 _handle_exception(
global _handle_exception = <function _handle_exception at 0x000002C526D14550>
self.ignore_callback_errors = False
self.print_callback_errors = 'reminders'
self = <napari.utils.events.event.EventEmitter object at 0x000002C55EE38460>
global cb_event = undefined
cb = <bound method PlotProfile._data_changed_event of <napari_plot_profile._dock_widget.PlotProfile object at 0x000002C55AC1A820>>
event = <Event blocked=False handled=False native=None source=None sources=[] type='data'>
608 self.ignore_callback_errors,
609 self.print_callback_errors,
c:\users\rober\miniconda3\envs\bio1\lib\site-packages\napari\utils\events\event.py in _invoke_callback(self=<napari.utils.events.event.EventEmitter object>, cb=<bound method PlotProfile._data_changed_event of...ri_plot_profile._dock_widget.PlotProfile object>>, event=<Event blocked=False handled=False native=None source=None sources=[] type='data'>)
594 def _invoke_callback(self, cb: Callback, event: Event):
595 try:
--> 596 cb(event)
cb = <bound method PlotProfile._data_changed_event of <napari_plot_profile._dock_widget.PlotProfile object at 0x000002C55AC1A820>>
event = <Event blocked=False handled=False native=None source=None sources=[] type='data'>
597 except Exception as e:
598 # dead Qt object with living python pointer. not importing Qt
TypeError: _data_changed_event() missing 1 required positional argument: 'event'
Not sure if it's the QTimer or what, but the live refresh seems quite slow on my end. The updating is slow and my line adjustment is laggy, like it stalls and skips, rather than fluid. If I close the plugin window manipulating the line is buttery smooth again. Alas, I don't have an older version of the plugin to compare.
Hi @psobolewskiPhD, it will become smoother as soon as this PR gets merged. Therefore I need to make it work with lines and paths 😉