Slicer main UI freezes during python scripted module execution

Hi Slicer developers,

I’m currently developing a python module that performs quite heavy computation over image volumes.

The module computations work as expected giving correct results. However, the main slicer window freezes during execution. When execution finishes, the main UI returns to normal. I would like to retain the UI functionality during execution in order to add a stop button that can halt the exection at user request, and maybe include a progress bar.

I am quite new at slicer developing and I don’t know how to handle this issue. I have already tried to execute the run function of the module logic in a separate thread using the threading library but I couldn get it working and I have read it is not a good approach in Slicer. I have also read that creating a separate cli module is a solution for this, but unfortunately, I very little experience on C++ language apart from some Qt basic knowledge.

Any clues on solving this issue?? or some python code examples I can read???

Thanks in advance for the help!

Miguel

Hi Miguel,

the issue is that Slicer GUI is on the same thread that you will run the computation.
CLI modules work because they use another thread.
I don’t know if there is a simple solution in Python.

But, in the case you feel to experiment with a pure C++ (loadable) module
(or I guess you can convert the code to python),
you may have a look here:

essentially I have a worker class that run the computation on a separate QThread.
The module needs still some cleaning and the widget has many methods for others things,
therefore it can be hard to go through it. However, the methods that you may be interested are (in the widget class):
onApply
onWorkFinished
onMRMLAstroModelingParametersNodeModified
and the init() to check how to setup the worker and the thread.

P.S.: building a CLI module should be easier (and safer) than building your own infrastructure like I did in the link (unless you need more flexibility, like I needed).

You may have a look at the many CLI module in Slicer and check if they satisfy your requirement and start from there. The idea of the CLI module is exactly to give developer an easy way to run heavy computation.

Another option is to use Slicer’s CLI infrastructure to run python code in a separate process. The CLI python process communicates with Slicer through files, like a C++ CLI would do, so it cannot call the running Slicer python API, but this can be okay for many use cases. We’ve been looking at adapting SlicerRadiomics to use this approach.

I guess I will start looking into CLI module developing, as it seems the best solution and I will need it sooner or later.
Thank you very much for your answers, Davide and Steve!

1 Like

I have tried to write a preliminary CLI python module. The GUI loads just fine on Slicer but when clicking the apply button I get some import errors:

BiasCorrection2 standard error:

Traceback (most recent call last):
_ File “/home/miguel/Documentos/Extensiones_3DSlicer/Prueba/PythonScript”, line 6, in _
_ import numpy as np_
_ File “/home/miguel/Slicer-4.8.1-linux-amd64/lib/Python/lib/python2.7/site-packages/numpy/init.py”, line 142, in _
_ from . import add_newdocs_
_ File “/home/miguel/Slicer-4.8.1-linux-amd64/lib/Python/lib/python2.7/site-packages/numpy/add_newdocs.py”, line 13, in _
_ from numpy.lib import add_newdoc_
_ File “/home/miguel/Slicer-4.8.1-linux-amd64/lib/Python/lib/python2.7/site-packages/numpy/lib/init.py”, line 8, in _
_ from .type_check import *_
_ File “/home/miguel/Slicer-4.8.1-linux-amd64/lib/Python/lib/python2.7/site-packages/numpy/lib/type_check.py”, line 11, in _
_ import numpy.core.numeric as nx
_ File “/home/miguel/Slicer-4.8.1-linux-amd64/lib/Python/lib/python2.7/site-packages/numpy/core/init.py”, line 26, in _
_ raise ImportError(msg)_
_ImportError: _
Importing the multiarray numpy extension module failed. Most
likely you are trying to import a failed build of numpy.
If you’re working with a numpy git repo, try git clean -xdf (removes all
files not under version control). Otherwise reinstall numpy.

Original error was: /home/miguel/Slicer-4.8.1-linux-amd64/lib/Python/lib/python2.7/site-packages/numpy/core/multiarray.so: undefined symbol: PyUnicodeUCS2_FromObject

The above error is from trying to import numpy.
I would also like to import some slicer functionality via:

import slicer

But the code seems to break at this line while the GUI says “completed with errors”. Is this what you mean by “it cannot call the running Slicer python API”, @pieper ??.

Importing os and sys works just fine.

Links to the code here:
https://github.com/Milogav/BiasCorrection

PS: I have not found much information about python cli modules and I don’t know if I require more than creating the .xml file, the program file and add the folder to slicer module path settings. Am I missing something else??

Hi @Milogav -

You can have a look at what we did for SlicerRadiomicsCLI - there are some subtleties about setting things up to use the right interpreter and to install correctly cross platform, but you should be able to follow pretty much the same recipe (literally just worked out yesterday):

By “it cannot call the running Slicer python API” I meant that Slicer itself will have a python interpreter instance that is populated with data and hooks to the running application instances. Running a python CLI can import the same packages as slicer but in an independent process so data is only shared by files (or by stdio and exit codes).

-Steve