mapmanager / napari-tracing

A Napari plugin to perform brightest path tracing.
GNU General Public License v3.0
5 stars 1 forks source link

Error when starting the tracing widget #15

Open haesleinhuepf opened 11 months ago

haesleinhuepf commented 11 months ago

Hi all,

I just tried to test the napari-tracing plugin and retrieve an error message RuntimeError: Failed to import command at 'napari_tracing._widget:TracerWidget': DLL load failed while importing reciprocal_transonic: A dynamic link library (DLL) initialization routine failed. when starting Tracer Widget (napari-tracing) from the Plugins menu.

That's how I installed it:

mamba create --name nc1 python=3.9 napari=0.4.18 -c conda-forge
mamba activate nc1
pip install napari-tracing

Hint: I'm using Window 10.

Full error log:

---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
File ~\mambaforge\envs\nc1\lib\site-packages\npe2\_command_registry.py:32, in CommandHandler.resolve(self=CommandHandler(id='napari-tracing.make_qwidget',...ython_name='napari_tracing._widget:TracerWidget'))
     31 try:
---> 32     self.function = utils.import_python_name(self.python_name)
        self.function = None
        self.python_name = 'napari_tracing._widget:TracerWidget'
        self = CommandHandler(id='napari-tracing.make_qwidget', function=None, python_name='napari_tracing._widget:TracerWidget')
        utils = <module 'npe2.manifest.utils' from 'C:\\Users\\haase\\mambaforge\\envs\\nc1\\lib\\site-packages\\npe2\\manifest\\utils.py'>
     33 except Exception as e:

File ~\mambaforge\envs\nc1\lib\site-packages\npe2\manifest\utils.py:256, in import_python_name(python_name='napari_tracing._widget:TracerWidget')
    254 module_name, funcname = match.groups()  # type: ignore [union-attr]
--> 256 mod = import_module(module_name)
        module_name = 'napari_tracing._widget'
    257 return getattr(mod, funcname)

File ~\mambaforge\envs\nc1\lib\importlib\__init__.py:127, in import_module(name='napari_tracing._widget', package=None)
    126         level += 1
--> 127 return _bootstrap._gcd_import(name[level:], package, level)
        level = 0
        name = 'napari_tracing._widget'
        name[level:] = 'napari_tracing._widget'
        package = None
        _bootstrap = <module 'importlib._bootstrap' (frozen)>

File <frozen importlib._bootstrap>:1030, in _gcd_import(name='napari_tracing._widget', package=None, level=0)

File <frozen importlib._bootstrap>:1007, in _find_and_load(name='napari_tracing._widget', import_=<function _gcd_import>)

File <frozen importlib._bootstrap>:972, in _find_and_load_unlocked(name='napari_tracing._widget', import_=<function _gcd_import>)

File <frozen importlib._bootstrap>:228, in _call_with_frames_removed(f=<function _gcd_import>, *args=('napari_tracing',), **kwds={})

File <frozen importlib._bootstrap>:1030, in _gcd_import(name='napari_tracing', package=None, level=0)

File <frozen importlib._bootstrap>:1007, in _find_and_load(name='napari_tracing', import_=<function _gcd_import>)

File <frozen importlib._bootstrap>:986, in _find_and_load_unlocked(name='napari_tracing', import_=<function _gcd_import>)

File <frozen importlib._bootstrap>:680, in _load_unlocked(spec=ModuleSpec(name='napari_tracing', loader=<_froze...\envs\\nc1\\lib\\site-packages\\napari_tracing']))

File <frozen importlib._bootstrap_external>:850, in exec_module(self=<_frozen_importlib_external.SourceFileLoader object>, module=<module 'napari_tracing' from 'C:\\Users\\haase\...lib\\site-packages\\napari_tracing\\__init__.py'>)

File <frozen importlib._bootstrap>:228, in _call_with_frames_removed(f=<built-in function exec>, *args=(<code object <module> at 0x0000015EF6E10B30, fil...ite-packages\napari_tracing\__init__.py", line 1>, {'__builtins__': {'ArithmeticError': <class 'ArithmeticError'>, 'AssertionError': <class 'AssertionError'>, 'AttributeError': <class 'AttributeError'>, 'BaseException': <class 'BaseException'>, 'BlockingIOError': <class 'BlockingIOError'>, 'BrokenPipeError': <class 'BrokenPipeError'>, 'BufferError': <class 'BufferError'>, 'BytesWarning': <class 'BytesWarning'>, 'ChildProcessError': <class 'ChildProcessError'>, 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, ...}, '__cached__': r'C:\Users\haase\mambaforge\envs\nc1\lib\site-pack...apari_tracing\__pycache__\__init__.cpython-39.pyc', '__doc__': None, '__file__': r'C:\Users\haase\mambaforge\envs\nc1\lib\site-packages\napari_tracing\__init__.py', '__loader__': <_frozen_importlib_external.SourceFileLoader object>, '__name__': 'napari_tracing', '__package__': 'napari_tracing', '__path__': [r'C:\Users\haase\mambaforge\envs\nc1\lib\site-packages\napari_tracing'], '__spec__': ModuleSpec(name='napari_tracing', loader=<_froze...\envs\\nc1\\lib\\site-packages\\napari_tracing']), '__version__': '0.0.1'}), **kwds={})

File ~\mambaforge\envs\nc1\lib\site-packages\napari_tracing\__init__.py:2
      1 __version__ = "0.0.1"
----> 2 from ._widget import TracerWidget
      4 __all__ = ("TracerWidget",)

File ~\mambaforge\envs\nc1\lib\site-packages\napari_tracing\_widget.py:34
     33 import numpy as np  # noqa
---> 34 from brightest_path_lib.algorithm import AStarSearch, NBAStarSearch  # noqa
     35 from napari.layers import Layer  # noqa

File ~\mambaforge\envs\nc1\lib\site-packages\brightest_path_lib\algorithm\__init__.py:1
----> 1 from .astar import AStarSearch
      2 from .nbastar import NBAStarSearch

File ~\mambaforge\envs\nc1\lib\site-packages\brightest_path_lib\algorithm\astar.py:34
     33 from typing import List, Tuple
---> 34 from brightest_path_lib.cost import ReciprocalTransonic
     35 from brightest_path_lib.heuristic import EuclideanTransonic

File ~\mambaforge\envs\nc1\lib\site-packages\brightest_path_lib\cost\__init__.py:3
      2 from .reciprocal import Reciprocal
----> 3 from .reciprocal_transonic import ReciprocalTransonic

File ~\mambaforge\envs\nc1\lib\site-packages\brightest_path_lib\cost\reciprocal_transonic.py:6
      3 from brightest_path_lib.cost import Cost
      5 @boost
----> 6 class ReciprocalTransonic(Cost):
        Cost = <class 'brightest_path_lib.cost.cost.Cost'>
      7     """Uses the reciprocal of pixel/voxel intensity to compute the cost of moving
      8     to a neighboring point
      9
   (...)
     25
     26     """

File ~\mambaforge\envs\nc1\lib\site-packages\brightest_path_lib\cost\reciprocal_transonic.py:48, in ReciprocalTransonic()
     44     self._min_step_cost = 1.0 / self.RECIPROCAL_MAX
     47 @boost
---> 48 def cost_of_moving_to(self, intensity_at_new_point: float) -> float:
     49     """calculates the cost of moving to a point
     50
     51     Parameters
   (...)
     65
     66     """

File ~\mambaforge\envs\nc1\lib\site-packages\transonic\aheadoftime.py:116, in boost(obj=<function ReciprocalTransonic.cost_of_moving_to>, backend=None, inline=False, boundscheck=True, wraparound=True, cdivision=False, nonecheck=True, nogil=False)
    114     raise TypeError
--> 116 ts = _get_transonic_calling_module(backend_name=backend)
        backend = None
    118 decor = ts.boost(
    119     inline=inline,
    120     nogil=nogil,
   (...)
    124     nonecheck=nonecheck,
    125 )

File ~\mambaforge\envs\nc1\lib\site-packages\transonic\aheadoftime.py:90, in _get_transonic_calling_module(backend_name='pythran')
     89 else:
---> 90     ts = Transonic(frame=frame, reuse=False, backend=backend_name)
        frame = <frame at 0x0000015EF6E3BB80, file 'C:\\Users\\haase\\mambaforge\\envs\\nc1\\lib\\site-packages\\brightest_path_lib\\cost\\reciprocal_transonic.py', line 48, code ReciprocalTransonic>
        backend_name = 'pythran'
     92 return ts

File ~\mambaforge\envs\nc1\lib\site-packages\transonic\aheadoftime.py:316, in Transonic.__init__(self=<transonic.aheadoftime.Transonic object>, use_transonified=True, frame=<frame at 0x0000015EF6E3BB80, file 'C:\\Users\\h...transonic.py', line 48, code ReciprocalTransonic>, reuse=False, backend=<transonic.backends.pythran.PythranBackend object>)
    314         self.path_extension = path_ext = path_ext_alt
--> 316 self.reload_module_backend(module_backend_name)
        module_backend_name = 'brightest_path_lib.cost.__pythran__.reciprocal_transonic'
        self = <transonic.aheadoftime.Transonic object at 0x0000015EF6E4A4C0>
    318 if not self.is_transpiled:

File ~\mambaforge\envs\nc1\lib\site-packages\transonic\aheadoftime.py:344, in Transonic.reload_module_backend(self=<transonic.aheadoftime.Transonic object>, module_backend_name='brightest_path_lib.cost.__pythran__.reciprocal_transonic')
    343 if self.path_extension.exists() and not self.is_compiling:
--> 344     self.module_backend = import_from_path(
        self = <transonic.aheadoftime.Transonic object at 0x0000015EF6E4A4C0>
        module_backend_name = 'brightest_path_lib.cost.__pythran__.reciprocal_transonic'
        self.path_extension = WindowsPath('C:/Users/haase/mambaforge/envs/nc1/lib/site-packages/brightest_path_lib/cost/__pythran__/reciprocal_transonic.cp39-win_amd64.pyd')
    345         self.path_extension, module_backend_name
    346     )
    347 elif self.path_backend.exists():

File ~\mambaforge\envs\nc1\lib\site-packages\transonic\util.py:369, in import_from_path(path=WindowsPath('C:/Users/haase/mambaforge/envs/nc1/...thran__/reciprocal_transonic.cp39-win_amd64.pyd'), module_name='brightest_path_lib.cost.__pythran__.reciprocal_transonic')
    368 sys.path.insert(0, str(path.parent))
--> 369 module = importlib.util.module_from_spec(spec)
        spec = ModuleSpec(name='brightest_path_lib.cost.__pythran__.reciprocal_transonic', loader=<_frozen_importlib_external.ExtensionFileLoader object at 0x0000015EF6E4A790>, origin='C:\\Users\\haase\\mambaforge\\envs\\nc1\\lib\\site-packages\\brightest_path_lib\\cost\\__pythran__\\reciprocal_transonic.cp39-win_amd64.pyd')
        importlib.util = <module 'importlib.util' from 'C:\\Users\\haase\\mambaforge\\envs\\nc1\\lib\\importlib\\util.py'>
    370 spec.loader.exec_module(module)

ImportError: DLL load failed while importing reciprocal_transonic: A dynamic link library (DLL) initialization routine failed.

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File ~\mambaforge\envs\nc1\lib\site-packages\napari\_qt\menus\plugins_menu.py:105, in PluginsMenu._add_plugin_actions.<locals>._add_toggle_widget(key=('napari-tracing', 'Tracer Widget'), hook_type='dock')
    102     return
    104 if hook_type == 'dock':
--> 105     self._win.add_plugin_dock_widget(*key)
        key = ('napari-tracing', 'Tracer Widget')
        self._win = <napari._qt.qt_main_window.Window object at 0x0000015EE9145520>
        self = <napari._qt.menus.plugins_menu.PluginsMenu object at 0x0000015EF6D9A0D0>
    106 else:
    107     self._win._add_plugin_function_widget(*key)

File ~\mambaforge\envs\nc1\lib\site-packages\napari\_qt\qt_main_window.py:790, in Window.add_plugin_dock_widget(self=<napari._qt.qt_main_window.Window object>, plugin_name='napari-tracing', widget_name='Tracer Widget', tabify=False)
    787 Widget = None
    788 dock_kwargs = {}
--> 790 if result := _npe2.get_widget_contribution(plugin_name, widget_name):
        widget_name = 'Tracer Widget'
        plugin_name = 'napari-tracing'
        _npe2 = <module 'napari.plugins._npe2' from 'C:\\Users\\haase\\mambaforge\\envs\\nc1\\lib\\site-packages\\napari\\plugins\\_npe2.py'>
    791     Widget, widget_name = result
    793 if Widget is None:

File ~\mambaforge\envs\nc1\lib\site-packages\napari\plugins\_npe2.py:136, in get_widget_contribution(plugin_name='napari-tracing', widget_name='Tracer Widget')
    134     if contrib.plugin_name == plugin_name:
    135         if not widget_name or contrib.display_name == widget_name:
--> 136             return contrib.get_callable(), contrib.display_name
        contrib = WidgetContribution(command='napari-tracing.make_qwidget', display_name='Tracer Widget', autogenerate=False)
        contrib.display_name = 'Tracer Widget'
    137         widgets_seen.add(contrib.display_name)
    138 if widget_name and widgets_seen:

File ~\mambaforge\envs\nc1\lib\site-packages\npe2\manifest\contributions\_widgets.py:50, in WidgetContribution.get_callable(self=WidgetContribution(command='napari-tracing.make_...display_name='Tracer Widget', autogenerate=False), _registry=None)
     47 def get_callable(
     48     self, _registry: Optional[CommandRegistry] = None
     49 ) -> Callable[..., Widget]:
---> 50     func = super().get_callable()
     51     if self.autogenerate:
     52         try:

File ~\mambaforge\envs\nc1\lib\site-packages\npe2\manifest\utils.py:73, in Executable.get_callable(self=WidgetContribution(command='napari-tracing.make_...display_name='Tracer Widget', autogenerate=False), _registry=<npe2._command_registry.CommandRegistry object>)
     70     from npe2._plugin_manager import PluginManager
     72     _registry = PluginManager.instance().commands
---> 73 return _registry.get(self.command)
        _registry = <npe2._command_registry.CommandRegistry object at 0x0000015EE63431F0>
        self.command = 'napari-tracing.make_qwidget'
        self = WidgetContribution(command='napari-tracing.make_qwidget', display_name='Tracer Widget', autogenerate=False)

File ~\mambaforge\envs\nc1\lib\site-packages\npe2\_command_registry.py:131, in CommandRegistry.get(self=<npe2._command_registry.CommandRegistry object>, id='napari-tracing.make_qwidget')
    129     if id not in self._commands:  # sourcery skip
    130         raise KeyError(f"command {id!r} not registered")
--> 131 return self._commands[id].resolve()
        id = 'napari-tracing.make_qwidget'
        self._commands = {'napari-tracing.make_qwidget': CommandHandler(id='napari-tracing.make_qwidget', function=None, python_name='napari_tracing._widget:TracerWidget')}
        self = <npe2._command_registry.CommandRegistry object at 0x0000015EE63431F0>
        self._commands[id] = CommandHandler(id='napari-tracing.make_qwidget', function=None, python_name='napari_tracing._widget:TracerWidget')

File ~\mambaforge\envs\nc1\lib\site-packages\npe2\_command_registry.py:34, in CommandHandler.resolve(self=CommandHandler(id='napari-tracing.make_qwidget',...ython_name='napari_tracing._widget:TracerWidget'))
     32     self.function = utils.import_python_name(self.python_name)
     33 except Exception as e:
---> 34     raise RuntimeError(
     35         f"Failed to import command at {self.python_name!r}: {e}"
     36     ) from e
     38 return self.function

RuntimeError: Failed to import command at 'napari_tracing._widget:TracerWidget': DLL load failed while importing reciprocal_transonic: A dynamic link library (DLL) initialization routine failed.
cudmore commented 7 months ago

Hi @haesleinhuepf, thanks for your feedback and sorry for our late response. We finally have a Windows machine and will followup with an answer this week!

cudmore commented 7 months ago

I can reproduce your error on Windows 11, the traceback is very different but ends the same with:

RuntimeError: Failed to import command at 'napari_tracing._widget:TracerWidget': DLL load failed while importing reciprocal_transonic: A dynamic link library (DLL) initialization routine failed.

This is a problem with our brightest-path-lib package to do the tracing. There, we are using Transonic to compile the Python code and make it faster. Problem is it greatly complicates the pip install setup.py. It does work on macOS but currently not on Windows.

Roadmap to fix this 1) Make a vanilla brightest-path tracking install that does not use Transonic. 2) Debug getting the brightest-path-lib working on Windows with Transonic

Thanks for your feedback! Much appreciated.