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

"Layout" parameter doesn't work anymore in recent dev version #54

Closed
haesleinhuepf opened this issue Dec 14, 2020 · 12 comments · Fixed by #67
Closed

"Layout" parameter doesn't work anymore in recent dev version #54

haesleinhuepf opened this issue Dec 14, 2020 · 12 comments · Fixed by #67
Labels
bug Something isn't working

Comments

@haesleinhuepf
Copy link
Contributor

Describe the bug
Hi Talley @tlambert03 ,

this is related to our quick try of the recent master branch as discussed in #53 , the magicgui layout='vertical' parameter doesn't work anymore. If this is intentional, no big deal. I can work in the meantime. I just switched back to the former released version.

To Reproduce

Expected behavior
It should not bring an error in the following line

@magicgui(auto_call=True, layout='vertical')
def filter(input1: Image, operation: Filter = Filter.please_select, x: float = 1, y: float = 1, z: float = 0):

However, it crashes with this error:

C:\Users\rober\miniconda3\python.exe C:/structure/code/pyclesperanto_prototype/demo/napari_gui/particle_analyser.py
Traceback (most recent call last):
  File "C:/structure/code/pyclesperanto_prototype/demo/napari_gui/particle_analyser.py", line 65, in <module>
    def filter(input1: Image, operation: Filter = Filter.please_select, x: float = 1, y: float = 1, z: float = 0):
  File "c:\structure\code\magicgui\magicgui\function_gui.py", line 280, in inner_func
    func_gui = FunctionGui(
  File "c:\structure\code\magicgui\magicgui\function_gui.py", line 75, in __init__
    sig = magic_signature(function, gui_options=param_options)
  File "c:\structure\code\magicgui\magicgui\signature.py", line 269, in magic_signature
    raise ValueError(
ValueError: keyword arguments (gui_options) MUST match parameters in the decorated function.
Got extra keys: {'layout'}

Environment (please complete the following information):

  • OS: Windows
  • magicgui version 0.1.7-dev7
  • napari 0.4.3-dev2
  • PtQt5 5.15.1
@haesleinhuepf haesleinhuepf added the bug Something isn't working label Dec 14, 2020
@tlambert03
Copy link
Member

try orientation='vertical'

https://github.com/napari/magicgui/blob/5ee09ae00bfcdf5d8fde4bb82e29f7d939abf1eb/magicgui/function_gui.py#L209-L219

I'll add a better deprecation warning and value pass-through

@haesleinhuepf
Copy link
Contributor Author

try orientation='vertical'

With that the error message goes away. So thanks again!

However, napari crashes without error now. Maybe I'll wait a bit until the recent dev versions become a bit more stable ;-)

napari_crash

@tlambert03
Copy link
Member

huh, that's weird actually... and might be more indicative of an issue with napari's exception handling? can you send me the full script?

@haesleinhuepf
Copy link
Contributor Author

haesleinhuepf commented Dec 14, 2020

I observed the bug with this long script. However, also with this short one, the is crash reproducible:

import napari
from magicgui import magicgui
from napari.layers import Image

@magicgui(auto_call=True)
def process_image(input: Image, sigma: float = 5) -> Image:
    if input:
        return input

# load data
from skimage.io import imread
image = imread('https://samples.fiji.sc/blobs.png')

# start up napari
with napari.gui_qt():
    viewer = napari.Viewer()
    viewer.add_image(image, name='blobs')

    # generate a Graphical User Interface from the function above magically
    gui = process_image.Gui()
    viewer.window.add_dock_widget(gui)

Without the magicgui annotation, it works:

import napari
from magicgui import magicgui
from napari.layers import Image

def process_image(input: Image, sigma: float = 5) -> Image:
    if input:
        return input

# load data
from skimage.io import imread
image = imread('https://samples.fiji.sc/blobs.png')

# start up napari
with napari.gui_qt():
    viewer = napari.Viewer()
    viewer.add_image(image, name='blobs')

    # generate a Graphical User Interface from the function above magically
    gui = magicgui(process_image, auto_call=True)
    viewer.window.add_dock_widget(gui)

@tlambert03
Copy link
Member

tlambert03 commented Dec 14, 2020

Gui() has been removed alltogether, and since the @decorator is just syntactic sugar for calling magicgui on a function, I think the only difference between the two is the way it's being passed to napari. Can you try it without using Gui()?:

import napari
from magicgui import magicgui
from napari.layers import Image

@magicgui(auto_call=True)
def process_image(input: Image, sigma: float = 5) -> Image:
    if input:
        return input

# start up napari
with napari.gui_qt():
    viewer = napari.Viewer()
    viewer.open('https://samples.fiji.sc/blobs.png', name='blobs')

    # don't use Gui() anymore ... just pass the function directly
    # gui = process_image.Gui()
    viewer.window.add_dock_widget(process_image)

@haesleinhuepf
Copy link
Contributor Author

haesleinhuepf commented Dec 14, 2020

That Gui() goes away is super cool and increases the magic. However, if I copy the code you posted, the crash still happens. It's a bit slower crashing though: 😆

napari_crash2

Seems that GIF is broken. The napari windows turns white for 2 seconds before it disappears with no error message.

@tlambert03
Copy link
Member

It's a bit slower crashing though: 😆

lol... ok, will take a look later when I can run the script :) thanks!

@tlambert03
Copy link
Member

tlambert03 commented Dec 15, 2020

aha! figured it out. This is due to the fact that magicgui was called before napari.gui_qt (and therefore creating the Qt app)... but napari.gui_qt only starts applications that napari itself created. So it did nothing.
see napari/napari#2016. for now... putting everything after napari.gui_qt() should do the trick

@haesleinhuepf
Copy link
Contributor Author

haesleinhuepf commented Dec 16, 2020

Hm. I'm confued now 😕 I just pulled recent master of napari and magicgui and ran this code:

import napari
from magicgui import magicgui
from napari.layers import Image

# start up napari
with napari.gui_qt():
    viewer = napari.Viewer()
    viewer.open('https://samples.fiji.sc/blobs.png', name='blobs')


    @magicgui(auto_call=True)
    def process_image(input: Image, sigma: float = 5) -> Image:
        if input:
            return input


    # don't use Gui() anymore ... just pass the function directly
    # gui = process_image.Gui()
    viewer.window.add_dock_widget(process_image)

The result is: napari opens two windows now and throws an error:
image

(napari_dev) C:\structure\code\pyclesperanto_prototype\demo\napari_gui>ipython --gui=qt napari_magicgui.py
ERROR:root:Unhandled exception:
Traceback (most recent call last):
  File "c:\users\rober\miniconda3\lib\site-packages\napari\_qt\event_loop.py", line 79, in gui_qt
    yield app
  File "C:\structure\code\pyclesperanto_prototype\demo\napari_gui\napari_magicgui.py", line 19, in <module>
    viewer.window.add_dock_widget(process_image)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\_qt\qt_main_window.py", line 565, in add_dock_widget
    dock_widget = QtViewerDockWidget(
  File "c:\users\rober\miniconda3\lib\site-packages\napari\_qt\widgets\qt_viewer_dock_widget.py", line 82, in __init__
    self.widget = combine_widgets(
  File "c:\users\rober\miniconda3\lib\site-packages\napari\_qt\utils.py", line 187, in combine_widgets
    raise TypeError('"widget" must be a QWidget or a sequence of QWidgets')
TypeError: "widget" must be a QWidget or a sequence of QWidgets

After closing both napari windows, there is another error and I need to kill ipython using the taskmanager to get my command line back.

WARNING: Traceback (most recent call last):
  File "c:\users\rober\miniconda3\lib\runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\rober\miniconda3\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\rober\miniconda3\Scripts\ipython.exe\__main__.py", line 7, in <module>
    sys.exit(start_ipython())
  File "c:\users\rober\miniconda3\lib\site-packages\IPython\__init__.py", line 126, in start_ipython
    return launch_new_instance(argv=argv, **kwargs)
  File "c:\users\rober\miniconda3\lib\site-packages\traitlets\config\application.py", line 844, in launch_instance
    app.initialize(argv)
  File "c:\users\rober\miniconda3\lib\site-packages\traitlets\config\application.py", line 87, in inner
    return method(app, *args, **kwargs)
  File "c:\users\rober\miniconda3\lib\site-packages\IPython\terminal\ipapp.py", line 323, in initialize
    self.init_code()
  File "c:\users\rober\miniconda3\lib\site-packages\IPython\core\shellapp.py", line 328, in init_code
    self._run_cmd_line_code()
  File "c:\users\rober\miniconda3\lib\site-packages\IPython\core\shellapp.py", line 452, in _run_cmd_line_code
    self._exec_file(fname, shell_futures=True)
  File "c:\users\rober\miniconda3\lib\site-packages\IPython\core\shellapp.py", line 377, in _exec_file
    self.shell.safe_execfile(full_filename,
  File "c:\users\rober\miniconda3\lib\site-packages\IPython\core\interactiveshell.py", line 2740, in safe_execfile
    py3compat.execfile(
  File "c:\users\rober\miniconda3\lib\site-packages\IPython\utils\py3compat.py", line 168, in execfile
    exec(compiler(f.read(), fname, 'exec'), glob, loc)
  File "C:\structure\code\pyclesperanto_prototype\demo\napari_gui\napari_magicgui.py", line 8, in <module>
    viewer.open('https://samples.fiji.sc/blobs.png', name='blobs')
  File "c:\users\rober\miniconda3\lib\site-packages\napari\components\viewer_model.py", line 840, in open
    self._add_layers_with_plugins(
  File "c:\users\rober\miniconda3\lib\site-packages\napari\components\viewer_model.py", line 908, in _add_layers_with_plugins
    new = self._add_layer_from_data(*_data)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\components\viewer_model.py", line 980, in _add_layer_from_data
    layer = add_method(data, **(meta or {}))
  File "c:\users\rober\miniconda3\lib\site-packages\napari\components\viewer_model.py", line 770, in add_image
    return self.add_layer(image_class(data, **kwargs))
  File "c:\users\rober\miniconda3\lib\site-packages\napari\components\viewer_model.py", line 567, in add_layer
    self.layers.append(layer)
  File "c:\users\rober\miniconda3\lib\_collections_abc.py", line 962, in append
    self.insert(len(self), value)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\utils\events\containers\_evented_list.py", line 159, in insert
    self.events.inserted(index=index, value=value)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\utils\events\event.py", line 513, in __call__
    self._invoke_callback(cb, event)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\utils\events\event.py", line 528, in _invoke_callback
    cb(event)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\_qt\qt_viewer.py", line 340, in _on_add_layer_change
    self._add_layer(layer)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\_qt\qt_viewer.py", line 353, in _add_layer
    vispy_layer.node.parent = self.view.scene
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\util\frozen.py", line 17, in __setattr__
    object.__setattr__(self, key, value)
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\scene\node.py", line 198, in parent
    self._set_canvas(parent.canvas)
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\scene\node.py", line 316, in _set_canvas
    self.transforms.canvas_transform = tr.canvas_transform
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\visuals\transforms\transform_system.py", line 315, in canvas_transform
    self._canvas_transform.transforms = tr
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\visuals\transforms\chain.py", line 96, in transforms
    self.update()
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\visuals\transforms\base_transform.py", line 153, in update
    self.changed(*args)
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\util\event.py", line 455, in __call__
    self._invoke_callback(cb, event)
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\util\event.py", line 471, in _invoke_callback
    cb(event)
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\util\event.py", line 455, in __call__
    self._invoke_callback(cb, event)
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\util\event.py", line 473, in _invoke_callback
    _handle_exception(self.ignore_callback_errors,
  << caught exception here: >>
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\util\event.py", line 471, in _invoke_callback
    cb(event)
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\visuals\visual.py", line 265, in _transform_changed
    self.update()
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\scene\node.py", line 333, in update
    c.update(node=self)
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\scene\canvas.py", line 200, in update
    super(SceneCanvas, self).update()
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\app\canvas.py", line 442, in update
    self._backend._vispy_update()
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\app\backends\_qt.py", line 427, in _vispy_update
    self.update()
RuntimeError: wrapped C/C++ object of type CanvasBackendDesktop has been deleted
WARNING:vispy:Traceback (most recent call last):
  File "c:\users\rober\miniconda3\lib\runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\rober\miniconda3\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\rober\miniconda3\Scripts\ipython.exe\__main__.py", line 7, in <module>
    sys.exit(start_ipython())
  File "c:\users\rober\miniconda3\lib\site-packages\IPython\__init__.py", line 126, in start_ipython
    return launch_new_instance(argv=argv, **kwargs)
  File "c:\users\rober\miniconda3\lib\site-packages\traitlets\config\application.py", line 844, in launch_instance
    app.initialize(argv)
  File "c:\users\rober\miniconda3\lib\site-packages\traitlets\config\application.py", line 87, in inner
    return method(app, *args, **kwargs)
  File "c:\users\rober\miniconda3\lib\site-packages\IPython\terminal\ipapp.py", line 323, in initialize
    self.init_code()
  File "c:\users\rober\miniconda3\lib\site-packages\IPython\core\shellapp.py", line 328, in init_code
    self._run_cmd_line_code()
  File "c:\users\rober\miniconda3\lib\site-packages\IPython\core\shellapp.py", line 452, in _run_cmd_line_code
    self._exec_file(fname, shell_futures=True)
  File "c:\users\rober\miniconda3\lib\site-packages\IPython\core\shellapp.py", line 377, in _exec_file
    self.shell.safe_execfile(full_filename,
  File "c:\users\rober\miniconda3\lib\site-packages\IPython\core\interactiveshell.py", line 2740, in safe_execfile
    py3compat.execfile(
  File "c:\users\rober\miniconda3\lib\site-packages\IPython\utils\py3compat.py", line 168, in execfile
    exec(compiler(f.read(), fname, 'exec'), glob, loc)
  File "C:\structure\code\pyclesperanto_prototype\demo\napari_gui\napari_magicgui.py", line 8, in <module>
    viewer.open('https://samples.fiji.sc/blobs.png', name='blobs')
  File "c:\users\rober\miniconda3\lib\site-packages\napari\components\viewer_model.py", line 840, in open
    self._add_layers_with_plugins(
  File "c:\users\rober\miniconda3\lib\site-packages\napari\components\viewer_model.py", line 908, in _add_layers_with_plugins
    new = self._add_layer_from_data(*_data)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\components\viewer_model.py", line 980, in _add_layer_from_data
    layer = add_method(data, **(meta or {}))
  File "c:\users\rober\miniconda3\lib\site-packages\napari\components\viewer_model.py", line 770, in add_image
    return self.add_layer(image_class(data, **kwargs))
  File "c:\users\rober\miniconda3\lib\site-packages\napari\components\viewer_model.py", line 567, in add_layer
    self.layers.append(layer)
  File "c:\users\rober\miniconda3\lib\_collections_abc.py", line 962, in append
    self.insert(len(self), value)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\utils\events\containers\_evented_list.py", line 159, in insert
    self.events.inserted(index=index, value=value)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\utils\events\event.py", line 513, in __call__
    self._invoke_callback(cb, event)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\utils\events\event.py", line 528, in _invoke_callback
    cb(event)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\_qt\qt_viewer.py", line 340, in _on_add_layer_change
    self._add_layer(layer)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\_qt\qt_viewer.py", line 353, in _add_layer
    vispy_layer.node.parent = self.view.scene
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\util\frozen.py", line 17, in __setattr__
    object.__setattr__(self, key, value)
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\scene\node.py", line 198, in parent
    self._set_canvas(parent.canvas)
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\scene\node.py", line 316, in _set_canvas
    self.transforms.canvas_transform = tr.canvas_transform
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\visuals\transforms\transform_system.py", line 315, in canvas_transform
    self._canvas_transform.transforms = tr
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\visuals\transforms\chain.py", line 96, in transforms
    self.update()
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\visuals\transforms\base_transform.py", line 153, in update
    self.changed(*args)
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\util\event.py", line 455, in __call__
    self._invoke_callback(cb, event)
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\util\event.py", line 471, in _invoke_callback
    cb(event)
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\util\event.py", line 455, in __call__
    self._invoke_callback(cb, event)
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\util\event.py", line 473, in _invoke_callback
    _handle_exception(self.ignore_callback_errors,
  << caught exception here: >>
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\util\event.py", line 471, in _invoke_callback
    cb(event)
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\visuals\visual.py", line 265, in _transform_changed
    self.update()
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\scene\node.py", line 333, in update
    c.update(node=self)
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\scene\canvas.py", line 200, in update
    super(SceneCanvas, self).update()
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\app\canvas.py", line 442, in update
    self._backend._vispy_update()
  File "c:\users\rober\miniconda3\lib\site-packages\vispy\app\backends\_qt.py", line 427, in _vispy_update
    self.update()
RuntimeError: wrapped C/C++ object of type CanvasBackendDesktop has been deleted
ERROR: Invoking <bound method BaseVisual._transform_changed of <Image at 0x1af8cc07be0>> for Event
ERROR:vispy:Invoking <bound method BaseVisual._transform_changed of <Image at 0x1af8cc07be0>> for Event
ERROR:root:Unhandled exception:
Traceback (most recent call last):
  File "c:\users\rober\miniconda3\lib\site-packages\napari\_qt\event_loop.py", line 79, in gui_qt
    yield app
  File "C:\structure\code\pyclesperanto_prototype\demo\napari_gui\napari_magicgui.py", line 8, in <module>
    viewer.open('https://samples.fiji.sc/blobs.png', name='blobs')
  File "c:\users\rober\miniconda3\lib\site-packages\napari\components\viewer_model.py", line 840, in open
    self._add_layers_with_plugins(
  File "c:\users\rober\miniconda3\lib\site-packages\napari\components\viewer_model.py", line 908, in _add_layers_with_plugins
    new = self._add_layer_from_data(*_data)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\components\viewer_model.py", line 980, in _add_layer_from_data
    layer = add_method(data, **(meta or {}))
  File "c:\users\rober\miniconda3\lib\site-packages\napari\components\viewer_model.py", line 770, in add_image
    return self.add_layer(image_class(data, **kwargs))
  File "c:\users\rober\miniconda3\lib\site-packages\napari\components\viewer_model.py", line 567, in add_layer
    self.layers.append(layer)
  File "c:\users\rober\miniconda3\lib\_collections_abc.py", line 962, in append
    self.insert(len(self), value)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\utils\events\containers\_evented_list.py", line 159, in insert
    self.events.inserted(index=index, value=value)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\utils\events\event.py", line 513, in __call__
    self._invoke_callback(cb, event)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\utils\events\event.py", line 530, in _invoke_callback
    _handle_exception(
  File "c:\users\rober\miniconda3\lib\site-packages\napari\utils\events\event.py", line 528, in _invoke_callback
    cb(event)
  File "c:\users\rober\miniconda3\lib\site-packages\napari\_qt\widgets\qt_layerlist.py", line 115, in _add
    self.vbox_layout.insertWidget(index, widget)
RuntimeError: wrapped C/C++ object of type QVBoxLayout has been deleted

Let me know if I can help further tracing this issue down. I'm also happy to zoom btw if you can't reproduce that on your machine.

@tlambert03
Copy link
Member

you know... I saw something very similar the other day, and i never got to the bottom of it. I can say it seems to have something to do with the examples folder (moving the napari examples out prevented it) and requires using the viewer.open trick I suggested instead of using viewer.view_image. I think something funny with shadowing is going on in the dev environments... but I don't think it's indicative of a deeper problem. for instance, this works:

conda create -n testenv python=3.8
conda activate testenv
# install recent masters using pip
pip install \
  git+git://github.com/napari/napari \
  git+git://github.com/napari/magicgui \
  pyqt5
python your_script.py

will try to figure it out.

@tlambert03
Copy link
Member

TypeError: "widget" must be a QWidget or a sequence of QWidgets

actually... that error suggests that you don't have napari/napari#1994

sorry about all this 😂 I wouldn't blame you if you wanted to wait a tiny bit for these new versions to actually be released

@tlambert03
Copy link
Member

just a heads up @haesleinhuepf, for container widgets (And for the magicgui decorator itself), this has returned to "layout=" rather than "orientation=" for release 0.2.1

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.

2 participants