Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error when using the Add polygons mode for Shapes layer (TypeError: unsupported operand type(s) for +: 'NoneType' and 'int') #6597

Closed
dalthviz opened this issue Jan 17, 2024 · 0 comments · Fixed by #6912
Labels
bug Something isn't working

Comments

@dalthviz
Copy link
Member

🐛 Bug Report

An error is triggered when using the Add polygons mode over a Shapes layer when adding a vertex in the same spot as the last one (while waiting a little bit before trying to add the new one)

💡 Steps to Reproduce

  1. Create a Shapes layer
  2. Select the Add polygons mode
  3. Add a new vertex over the canvas and wait a couple of seconds without moving the mouse from its position
  4. Try to add a new vertex over the same position
  • Behavior preview:

vertex

💡 Expected Behavior

To not see an error message and maybe the previous edge just be removed as when doing the mouse click quickly

🌎 Environment

napari: 0.5.0a2.dev517+g406aa9c8
Platform: Windows-10-10.0.19045-SP0
Python: 3.10.9 | packaged by conda-forge | (main, Jan 11 2023, 15:15:40) [MSC v.1916 64 bit (AMD64)]
Qt: 5.15.2
PyQt5: 5.15.9
NumPy: 1.25.2
SciPy: 1.9.3
Dask: 2023.10.1
VisPy: 0.14.1
magicgui: 0.7.3
superqt: unknown
in-n-out: 0.1.5
app-model: 0.2.2
npe2: 0.7.3

OpenGL:
  - GL version:  4.5.0 - Build 25.20.100.6444
  - MAX_TEXTURE_SIZE: 16384

Screens:
  - screen 1: resolution 1366x768, scale 1.0
  - screen 2: resolution 1536x864, scale 1.0

Settings path:
  - C:\Users\dalth\AppData\Local\napari\napari-dev_4454fdbf170edefe23827a4bf512389a6806af69\settings.yaml
Plugins:
  - napari: 0.5.0a2.dev517+g406aa9c8 (81 contributions)
  - napari-assistant: 0.4.4 (4 contributions)
  - napari-console: 0.0.9 (0 contributions)
  - napari-generic-SIMulator: 0.0.19 (2 contributions)
  - napari-ome-zarr: 0.5.2 (2 contributions)
  - napari-pyclesperanto-assistant: 0.22.1 (51 contributions)
  - napari-skimage-regionprops: 0.10.0 (2 contributions)
  - napari-svg: 0.1.10 (2 contributions)
  - napari-time-slicer: 0.4.9 (2 contributions)
  - napari-tools-menu: 0.1.19 (0 contributions)
  - napari-ui-tracer: 0.2.0.dev0 (2 contributions)

💡 Additional Context

Traceback:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
File ~\anaconda3\envs\napari-dev\lib\site-packages\vispy\app\backends\_qt.py:496, in QtBaseCanvasBackend.mousePressEvent(self=<vispy.app.backends._qt.CanvasBackendDesktop object>, ev=<PyQt5.QtGui.QMouseEvent object>)
    494 if self._vispy_canvas is None:
    495     return
--> 496 self._vispy_mouse_press(
        self = <vispy.app.backends._qt.CanvasBackendDesktop object at 0x000001E3D21793F0>
        ev = <PyQt5.QtGui.QMouseEvent object at 0x000001E3DF404670>
        BUTTONMAP = {0: 0, 1: 1, 2: 2, 4: 3, 8: 4, 16: 5}
    497     native=ev,
    498     pos=_get_event_xy(ev),
    499     button=BUTTONMAP.get(ev.button(), 0),
    500     modifiers=self._modifiers(ev),
    501 )

File ~\anaconda3\envs\napari-dev\lib\site-packages\vispy\app\base.py:184, in BaseCanvasBackend._vispy_mouse_press(self=<vispy.app.backends._qt.CanvasBackendDesktop object>, **kwargs={'button': 1, 'buttons': [], 'last_event': <MouseEvent blocked=False button=1 buttons=[1] d...ces=[] time=1705511204.736266 type=mouse_release>, 'last_mouse_press': None, 'modifiers': (), 'native': <PyQt5.QtGui.QMouseEvent object>, 'pos': (206, 147), 'press_event': None})
    181 def _vispy_mouse_press(self, **kwargs):
    182     # default method for delivering mouse press events to the canvas
    183     kwargs.update(self._vispy_mouse_data)
--> 184     ev = self._vispy_canvas.events.mouse_press(**kwargs)
        self._vispy_canvas.events.mouse_press = <vispy.util.event.EventEmitter object at 0x000001E3D2177DF0>
        kwargs = {'native': <PyQt5.QtGui.QMouseEvent object at 0x000001E3DF404670>, 'pos': (206, 147), 'button': 1, 'modifiers': (), 'buttons': [], 'press_event': None, 'last_event': <MouseEvent blocked=False button=1 buttons=[1] delta=[0. 0.] handled=False is_dragging=True last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000001E3DF404670> pos=[206 147] press_event=MouseEvent source=None sources=[] time=1705511204.736266 type=mouse_release>, 'last_mouse_press': None}
        self = <vispy.app.backends._qt.CanvasBackendDesktop object at 0x000001E3D21793F0>
        self._vispy_canvas.events = <vispy.util.event.EmitterGroup object at 0x000001E3D2177D30>
        self._vispy_canvas = <NapariSceneCanvas (PyQt5) at 0x1e3d2175bd0>
    185     if self._vispy_mouse_data['press_event'] is None:
    186         self._vispy_mouse_data['press_event'] = ev

File ~\anaconda3\envs\napari-dev\lib\site-packages\vispy\util\event.py:453, in EventEmitter.__call__(self=<vispy.util.event.EventEmitter object>, *args=(), **kwargs={'button': 1, 'buttons': [], 'last_event': <MouseEvent blocked=False button=1 buttons=[1] d...ces=[] time=1705511204.736266 type=mouse_release>, 'last_mouse_press': None, 'modifiers': (), 'native': <PyQt5.QtGui.QMouseEvent object>, 'pos': (206, 147), 'press_event': None})
    450 if self._emitting > 1:
    451     raise RuntimeError('EventEmitter loop detected!')
--> 453 self._invoke_callback(cb, event)
        event = <MouseEvent blocked=False button=1 buttons=[1] delta=[0. 0.] handled=False is_dragging=False last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000001E3DF404670> pos=[206 147] press_event=None source=None sources=[] time=1705511205.706028 type=mouse_press>
        self = <vispy.util.event.EventEmitter object at 0x000001E3D2177DF0>
        cb = <bound method VispyCanvas._on_mouse_press of <napari._vispy.canvas.VispyCanvas object at 0x000001E3D2175BA0>>
    454 if event.blocked:
    455     break

File ~\anaconda3\envs\napari-dev\lib\site-packages\vispy\util\event.py:471, in EventEmitter._invoke_callback(self=<vispy.util.event.EventEmitter object>, cb=<bound method VispyCanvas._on_mouse_press of <napari._vispy.canvas.VispyCanvas object>>, event=<MouseEvent blocked=False button=1 buttons=[1] d...urces=[] time=1705511205.706028 type=mouse_press>)
    469     cb(event)
    470 except Exception:
--> 471     _handle_exception(self.ignore_callback_errors,
        self = <vispy.util.event.EventEmitter object at 0x000001E3D2177DF0>
        cb = <bound method VispyCanvas._on_mouse_press of <napari._vispy.canvas.VispyCanvas object at 0x000001E3D2175BA0>>
        event = <MouseEvent blocked=False button=1 buttons=[1] delta=[0. 0.] handled=False is_dragging=False last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000001E3DF404670> pos=[206 147] press_event=None source=None sources=[] time=1705511205.706028 type=mouse_press>
        (cb, event) = (<bound method VispyCanvas._on_mouse_press of <napari._vispy.canvas.VispyCanvas object at 0x000001E3D2175BA0>>, <MouseEvent blocked=False button=1 buttons=[1] delta=[0. 0.] handled=False is_dragging=False last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000001E3DF404670> pos=[206 147] press_event=None source=None sources=[] time=1705511205.706028 type=mouse_press>)
    472                       self.print_callback_errors,
    473                       self, cb_event=(cb, event))

File ~\anaconda3\envs\napari-dev\lib\site-packages\vispy\util\event.py:469, in EventEmitter._invoke_callback(self=<vispy.util.event.EventEmitter object>, cb=<bound method VispyCanvas._on_mouse_press of <napari._vispy.canvas.VispyCanvas object>>, event=<MouseEvent blocked=False button=1 buttons=[1] d...urces=[] time=1705511205.706028 type=mouse_press>)
    467 def _invoke_callback(self, cb, event):
    468     try:
--> 469         cb(event)
        cb = <bound method VispyCanvas._on_mouse_press of <napari._vispy.canvas.VispyCanvas object at 0x000001E3D2175BA0>>
        event = <MouseEvent blocked=False button=1 buttons=[1] delta=[0. 0.] handled=False is_dragging=False last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000001E3DF404670> pos=[206 147] press_event=None source=None sources=[] time=1705511205.706028 type=mouse_press>
    470     except Exception:
    471         _handle_exception(self.ignore_callback_errors,
    472                           self.print_callback_errors,
    473                           self, cb_event=(cb, event))

File E:\Acer\Documentos\Quansight\Napari\napari\napari\_vispy\canvas.py:461, in VispyCanvas._on_mouse_press(self=<napari._vispy.canvas.VispyCanvas object>, event=<MouseEvent blocked=False button=1 buttons=[1] d...urces=[] time=1705511205.706028 type=mouse_press>)
    449 def _on_mouse_press(self, event: MouseEvent) -> None:
    450     """Called whenever mouse pressed in canvas.
    451
    452     Parameters
   (...)
    459     None
    460     """
--> 461     self._process_mouse_event(mouse_press_callbacks, event)
        event = <MouseEvent blocked=False button=1 buttons=[1] delta=[0. 0.] handled=False is_dragging=False last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000001E3DF404670> pos=[206 147] press_event=None source=None sources=[] time=1705511205.706028 type=mouse_press>
        self = <napari._vispy.canvas.VispyCanvas object at 0x000001E3D2175BA0>

File E:\Acer\Documentos\Quansight\Napari\napari\napari\_vispy\canvas.py:408, in VispyCanvas._process_mouse_event(self=<napari._vispy.canvas.VispyCanvas object>, mouse_callbacks=<function mouse_press_callbacks>, event=<ReadOnlyWrapper at 0x000001E3DF98B140 for MouseEvent>)
    406 layer = self.viewer.layers.selection.active
    407 if layer is not None:
--> 408     mouse_callbacks(layer, event)
        event = <ReadOnlyWrapper at 0x000001E3DF98B140 for MouseEvent at 0x000001E3D3FB9270>
        layer = <Shapes layer 'Shapes' at 0x1e3dd74f4f0>
        mouse_callbacks = <function mouse_press_callbacks at 0x000001E3CC438670>

File E:\Acer\Documentos\Quansight\Napari\napari\napari\utils\interactions.py:126, in mouse_press_callbacks(obj=<Shapes layer 'Shapes'>, event=<ReadOnlyWrapper at 0x000001E3DF98B140 for MouseEvent>)
    123 # iterate through drag callback functions
    124 for mouse_drag_func in obj.mouse_drag_callbacks:
    125     # execute function to run press event code
--> 126     gen = mouse_drag_func(obj, event)
        mouse_drag_func = <function add_path_polygon at 0x000001E3CE60D090>
        obj = <Shapes layer 'Shapes' at 0x1e3dd74f4f0>
        event = <ReadOnlyWrapper at 0x000001E3DF98B140 for MouseEvent at 0x000001E3D3FB9270>
    127     # if function returns a generator then try to iterate it
    128     if inspect.isgenerator(gen):

File E:\Acer\Documentos\Quansight\Napari\napari\napari\layers\shapes\_shapes_mouse_bindings.py:445, in add_path_polygon(layer=<Shapes layer 'Shapes'>, event=<ReadOnlyWrapper at 0x000001E3DF98B140 for MouseEvent>)
    443 index = layer._moving_value[0]
    444 new_type = Polygon if layer._mode == Mode.ADD_POLYGON else None
--> 445 add_vertex_to_path(layer, event, index, coordinates, new_type)
        coordinates = <class 'numpy.ndarray'> (2,) float64
        index = 0
        new_type = <class 'napari.layers.shapes._shapes_models.polygon.Polygon'>
        layer = <Shapes layer 'Shapes' at 0x1e3dd74f4f0>
        event = <ReadOnlyWrapper at 0x000001E3DF98B140 for MouseEvent at 0x000001E3D3FB9270>

File E:\Acer\Documentos\Quansight\Napari\napari\napari\layers\shapes\_shapes_mouse_bindings.py:383, in add_vertex_to_path(layer=<Shapes layer 'Shapes'>, event=<ReadOnlyWrapper at 0x000001E3DF98B140 for MouseEvent>, index=0, coordinates=<class 'numpy.ndarray'> (2,) float64, new_type=<class 'napari.layers.shapes._shapes_models.polygon.Polygon'>)
    381 vertices = np.concatenate((vertices, [coordinates]), axis=0)
    382 value = layer.get_value(event.position, world=True)
--> 383 layer._value = (value[0], value[1] + 1)
        value = (None, None)
        layer._value = (None, None)
        layer = <Shapes layer 'Shapes' at 0x1e3dd74f4f0>
        value[0] = None
        value[1] = None
    384 layer._moving_value = copy(layer._value)
    385 layer._data_view.edit(index, vertices, new_type=new_type)

TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
@dalthviz dalthviz added the bug Something isn't working label Jan 17, 2024
psobolewskiPhD pushed a commit that referenced this issue May 24, 2024
…6912)

# References and relevant issues

Closes #6597 

# Description

Enable proper handling of mouse bindings (single and double click) with
unfinished/invalid shapes definitions (not enough vertices to close the
shape or trying to add the same vertex multiple times. With the changes:

* Ignore addition of a vertex (mouse single click) if it has the same
position as the last vertex added (fix for #6597)
* Trying to finish the drawing (mouse double click) of an invalid shape
causes the in progress shape to be removed (fix for
#6912 (comment))

Preview:


![invalid_shapes](https://github.com/napari/napari/assets/16781833/8002862b-4cb6-4b13-80e2-366b0c4f4d03)
andy-sweet pushed a commit to andy-sweet/napari that referenced this issue May 28, 2024
…apari#6912)

# References and relevant issues

Closes napari#6597 

# Description

Enable proper handling of mouse bindings (single and double click) with
unfinished/invalid shapes definitions (not enough vertices to close the
shape or trying to add the same vertex multiple times. With the changes:

* Ignore addition of a vertex (mouse single click) if it has the same
position as the last vertex added (fix for napari#6597)
* Trying to finish the drawing (mouse double click) of an invalid shape
causes the in progress shape to be removed (fix for
napari#6912 (comment))

Preview:


![invalid_shapes](https://github.com/napari/napari/assets/16781833/8002862b-4cb6-4b13-80e2-366b0c4f4d03)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant