Cannot import gmsh Python package

Hi Andras,
Slicer exit abnormally
when I try to initialize gmsh in an extension but it did work with the built version of slicer but not with the executable version of slicer. could you please help to resolve?

Python console user input: import gmsh
Python console user input: gmsh.initialize()
error: [/media/useradmin/Disk2/Slicer-5.3.0-2023-01-21-linux-amd64/bin/SlicerApp-real] exit abnormally - Report the problem.

regards,
Saima

This is happening with the latest (5.2.2) stable version of Slicer as well:

Python console user input: import gmsh
Python console user input: gmsh.initialize()
error: [/opt/slicer/Slicer-5.2.2-linux-amd64/bin/SlicerApp-real] exit abnormally - Report the problem.

Here is the output from GDB:

ben@p1:~$ gdb --pid 618067
GNU gdb (Debian 13.1-2) 13.1
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word".
Attaching to process 618067
[New LWP 618068]
[New LWP 618069]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007f6783f1afff in poll () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) continue
Continuing.
[New Thread 0x7f6723bff6c0 (LWP 618123)]
[New Thread 0x7f67233fe6c0 (LWP 618124)]
[New Thread 0x7f66fc5ff6c0 (LWP 618126)]
[New Thread 0x7f66f9dfe6c0 (LWP 618127)]
[New Thread 0x7f66f75fd6c0 (LWP 618128)]
[New Thread 0x7f66f4dfc6c0 (LWP 618129)]
[New Thread 0x7f66f45fb6c0 (LWP 618130)]
[New Thread 0x7f66f1dfa6c0 (LWP 618131)]
[New Thread 0x7f66ef5f96c0 (LWP 618132)]
[New Thread 0x7f66eadf86c0 (LWP 618133)]
[New Thread 0x7f66ea5f76c0 (LWP 618134)]
[New Thread 0x7f66e5df66c0 (LWP 618135)]
[New Thread 0x7f66e55f56c0 (LWP 618136)]
[New Thread 0x7f66dd5ff6c0 (LWP 618137)]
[New Thread 0x7f66dcdfe6c0 (LWP 618138)]
[New Thread 0x7f66d7fff6c0 (LWP 618139)]
[New Thread 0x7f669882b6c0 (LWP 618142)]
[New Thread 0x7f669802a6c0 (LWP 618143)]
[New Thread 0x7f66978296c0 (LWP 618144)]
[New Thread 0x7f66970286c0 (LWP 618145)]
[New Thread 0x7f66968276c0 (LWP 618146)]
[New Thread 0x7f66960266c0 (LWP 618147)]
[New Thread 0x7f66958256c0 (LWP 618148)]
[New Thread 0x7f66950246c0 (LWP 618149)]
[New Thread 0x7f66948236c0 (LWP 618150)]
[New Thread 0x7f666ffff6c0 (LWP 618151)]
[New Thread 0x7f666f7fe6c0 (LWP 618152)]
[New Thread 0x7f666effd6c0 (LWP 618153)]
[New Thread 0x7f664dbff6c0 (LWP 618154)]
[New Thread 0x7f664d3fe6c0 (LWP 618155)]
[Thread 0x7f669802a6c0 (LWP 618143) exited]
[Thread 0x7f66968276c0 (LWP 618146) exited]
[Thread 0x7f669882b6c0 (LWP 618142) exited]
[Thread 0x7f66948236c0 (LWP 618150) exited]
[Thread 0x7f666f7fe6c0 (LWP 618152) exited]
[Thread 0x7f66958256c0 (LWP 618148) exited]
[Thread 0x7f66960266c0 (LWP 618147) exited]
[Thread 0x7f666ffff6c0 (LWP 618151) exited]
[Thread 0x7f66950246c0 (LWP 618149) exited]
[Thread 0x7f66978296c0 (LWP 618144) exited]
[Thread 0x7f666effd6c0 (LWP 618153) exited]
[Thread 0x7f66970286c0 (LWP 618145) exited]
[New Thread 0x7f66970286c0 (LWP 618157)]
[New Thread 0x7f666effd6c0 (LWP 618158)]
[New Thread 0x7f66950246c0 (LWP 618159)]
[New Thread 0x7f66978296c0 (LWP 618160)]
[New Thread 0x7f669882b6c0 (LWP 618161)]
[New Thread 0x7f669802a6c0 (LWP 618162)]
[New Thread 0x7f66968276c0 (LWP 618163)]
[New Thread 0x7f66960266c0 (LWP 618164)]
[New Thread 0x7f66958256c0 (LWP 618165)]
[New Thread 0x7f66948236c0 (LWP 618166)]
[New Thread 0x7f666ffff6c0 (LWP 618167)]

Thread 1 "SlicerApp-real" received signal SIGABRT, Aborted.
0x00007f6783ea9ccc in ?? () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) backtrace
#0  0x00007f6783ea9ccc in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00007f6783e5aef2 in raise () from /lib/x86_64-linux-gnu/libc.so.6
#2  0x00007f6783e45472 in abort () from /lib/x86_64-linux-gnu/libc.so.6
#3  0x00007f6783e9e2d0 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#4  0x00007f6783eb364a in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#5  0x00007f6783eb53d4 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#6  0x00007f6783eb7d2f in free () from /lib/x86_64-linux-gnu/libc.so.6
#7  0x00007f663791b09f in std::__detail::_Compiler<std::__cxx11::regex_traits<char> >::_Compiler(char const*, char const*, std::locale const&, std::regex_constants::syntax_option_type) ()
   from /opt/slicer/Slicer-5.2.2-linux-amd64/lib/Python/lib/libgmsh.so.4.11
#8  0x00007f663791b158 in std::enable_if<std::__detail::__is_contiguous_normal_iter<char const*>::value, std::shared_ptr<std::__detail::_NFA<std::__cxx11::regex_traits<char> > const> >::type std::__detail::__compile_nfa<char const*, std::__cxx11::regex_traits<char> >(char const*, char const*, std::__cxx11::regex_traits<char>::locale_type const&, std::regex_constants::syntax_option_type) () from /opt/slicer/Slicer-5.2.2-linux-amd64/lib/Python/lib/libgmsh.so.4.11
#9  0x00007f6637909bcb in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/lib/Python/lib/libgmsh.so.4.11
#10 0x00007f6637909d53 in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/lib/Python/lib/libgmsh.so.4.11
#11 0x00007f66378e1b1e in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/lib/Python/lib/libgmsh.so.4.11
#12 0x00007f66378bee91 in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/lib/Python/lib/libgmsh.so.4.11
#13 0x00007f66378df65a in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/lib/Python/lib/libgmsh.so.4.11
#14 0x00007f663789dcae in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/lib/Python/lib/libgmsh.so.4.11
#15 0x00007f6637933205 in gmsh::initialize(int, char**, bool, bool) () from /opt/slicer/Slicer-5.2.2-linux-amd64/lib/Python/lib/libgmsh.so.4.11
#16 0x00007f663857a1d5 in gmshInitialize () from /opt/slicer/Slicer-5.2.2-linux-amd64/lib/Python/lib/libgmsh.so.4.11
#17 0x00007f674a4be052 in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#18 0x00007f674a4bb64e in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#19 0x00007f674a4b199d in _ctypes_callproc () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#20 0x00007f674a4aaa76 in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#21 0x00007f674a297e5a in _PyObject_MakeTpCall () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#22 0x00007f674a2765fb in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#23 0x00007f674a27d070 in _PyEval_EvalFrameDefault () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#24 0x00007f674a27542b in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#25 0x00007f674a276597 in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#26 0x00007f674a27d070 in _PyEval_EvalFrameDefault () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#27 0x00007f674a3c0b37 in _PyEval_EvalCode () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#28 0x00007f674a3c0ed2 in _PyEval_EvalCodeWithName () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#29 0x00007f674a3c0f1e in PyEval_EvalCodeEx () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#30 0x00007f674a3c0f4b in PyEval_EvalCode () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#31 0x00007f674a3bbd41 in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#32 0x00007f674a302f15 in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#33 0x00007f674a27c101 in _PyEval_EvalFrameDefault () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#34 0x00007f674a27542b in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#35 0x00007f674a276597 in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#36 0x00007f674a277fa2 in _PyEval_EvalFrameDefault () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#37 0x00007f674a3c0b37 in _PyEval_EvalCode () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#38 0x00007f674a297c41 in _PyFunction_Vectorcall () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#39 0x00007f674a276597 in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#40 0x00007f674a277fa2 in _PyEval_EvalFrameDefault () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#41 0x00007f674a27542b in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#42 0x00007f674a2b0586 in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#43 0x00007f674a29a19c in PyObject_CallMethod () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#44 0x00007f6783c083ea in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libCTKScriptingPythonWidgets.so.0.1
#45 0x00007f6783c08b51 in ctkPythonConsole::executeCommand(QString const&) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libCTKScriptingPythonWidgets.so.0.1
#46 0x00007f67832cd359 in ctkConsolePrivate::internalExecuteCommand() () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libCTKWidgets.so.0.1
#47 0x00007f67832ce941 in ctkConsolePrivate::keyPressEvent(QKeyEvent*) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libCTKWidgets.so.0.1
#48 0x00007f67821a20a7 in QWidget::event(QEvent*) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Widgets.so.5
#49 0x00007f678224a21e in QFrame::event(QEvent*) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Widgets.so.5
#50 0x00007f678224cef3 in QAbstractScrollArea::event(QEvent*) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Widgets.so.5
--Type <RET> for more, q to quit, c to continue without paging--c
#51 0x00007f6782318f7a in QTextEdit::event(QEvent*) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Widgets.so.5
#52 0x00007f678216343c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Widgets.so.5
#53 0x00007f678216ab55 in QApplication::notify(QObject*, QEvent*) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Widgets.so.5
#54 0x00007f6784e8b3b6 in qSlicerApplication::notify(QObject*, QEvent*) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libqSlicerBaseQTGUI.so
#55 0x00007f678109d808 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Core.so.5
#56 0x00007f67821bdd0b in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Widgets.so.5
#57 0x00007f678216343c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Widgets.so.5
#58 0x00007f6782169f20 in QApplication::notify(QObject*, QEvent*) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Widgets.so.5
#59 0x00007f6784e8b3b6 in qSlicerApplication::notify(QObject*, QEvent*) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libqSlicerBaseQTGUI.so
#60 0x00007f678109d808 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Core.so.5
#61 0x00007f678176be1b in QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent*) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Gui.so.5
#62 0x00007f6781770935 in QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Gui.so.5
#63 0x00007f678174c8ab in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Gui.so.5
#64 0x00007f673466569a in ?? () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5XcbQpa.so.5
#65 0x00007f678571c7a9 in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#66 0x00007f678571ca38 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#67 0x00007f678571cacc in g_main_context_iteration () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#68 0x00007f67810f91cc in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Core.so.5
#69 0x00007f678109c21a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Core.so.5
#70 0x00007f67810a51d3 in QCoreApplication::exec() () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libQt5Core.so.5
#71 0x00007f6782a5361a in qSlicerCoreApplication::exec() () from /opt/slicer/Slicer-5.2.2-linux-amd64/bin/../lib/Slicer-5.2/libqSlicerBaseQTCore.so
#72 0x0000000000404a77 in ?? ()
#73 0x00007f6783e4618a in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#74 0x00007f6783e46245 in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
#75 0x0000000000404b6c in ?? ()
(gdb) 

Probably something is messed up in what/how C runtime libraries are linked into the gmsh shared library. Gmsh uses non-permissive (GPL) license, so I would not recommend ever using it as a library.

Instead, you can use fTetWild. I haven’t used it myself but many people told it worked well for them. If you don’t find a Python distribution for it then you could add it to SegmentMesher extension.

We have quite a complicated meshing workflow already implemented in Gmsh, and I don’t think it will be feasible to switch to something like fTetWild. Do you have any suggestions on how we could fix the issue with loading Gmsh in Slicer?

Do you have any suggestions on how we could fix the issue with loading Gmsh in Slicer?

Analysis

The library libgmsh.so.4.11 shipped in the gmsh wheel references std::__cxx11::basic_string

See details
$ readelf -W -s ~/Downloads/gmsh-4.11.1-py2.py3-none-manylinux1_x86_64/gmsh-4.11.1.data/data/lib/libgmsh.so.4.11 | \
  cut -c60- | c++filt | ack "::basic_string" | head -n1
std::__cxx11::basic_string<char, std::char_traits, std::allocator >::assign(char const*)@GLIBCXX_3.4.21 (5)

cxx11::basic_string

$ readelf -W -s ~/Downloads/gmsh-4.11.1-py2.py3-none-manylinux1_x86_64/gmsh-4.11.1.data/data/lib/libgmsh.so.4.11 |
cut -c60- | c++filt | ack “cxx11::basic_string” | wc -l
364

std::basic_string

$ readelf -W -s ~/Downloads/gmsh-4.11.1-py2.py3-none-manylinux1_x86_64/gmsh-4.11.1.data/data/lib/libgmsh.so.4.11 |
cut -c60- | c++filt | ack “std::basic_string” | wc -l
0

whereas the libraries associated with the Slicer release references std::basic_string

See details
$ readelf -W -s ~/Downloads/Slicer-5.2.2-linux-amd64/lib/Slicer-5.2/libMRMLCore.so | \
  cut -c60- | c++filt | ack "::basic_string" | head -n1
slicer_itk::ProcessObject::RemoveInput(std::basic_string<char, std::char_traits, std::allocator > const&)

cxx11::basic_string

$ readelf -W -s ./bin/libMRMLCore.so |
cut -c60- | c++filt | ack “cxx11::basic_string” | wc -l
1310

std::basic_string

$ readelf -W -s ./bin/libMRMLCore.so |
cut -c60- | c++filt | ack “std::basic_string” | wc -l
0

I suspect this is due to incompatibility associated with the Dual ABI introduced in gcc 5[1][2].

[…] since GCC 5 there are two implementations of std::string available in libstdc++. The two implementations are not link-compatible (they have different mangled names, so can’t be linked together) but can co-exist in the same binary (they have different mangled names, so don’t conflict if one object uses std::string and the other uses std::__cxx11::string). If your objects use std::string then usually they should all be compiled with the same string implementation. Compile with -D_GLIBCXX_USE_CXX11_ABI=0 to select the original gcc4-compatible implementation, or -D_GLIBCXX_USE_CXX11_ABI=1 to select the new cxx11 implementation (don’t be fooled by the name, it can be used in C++03 too, it’s called cxx11 because it conforms to the C++11 requirements).

Source: https://stackoverflow.com/questions/46746878/is-it-safe-to-link-c17-c14-and-c11-objects/49119902#49119902

Aren’t manylinux1 wheels suppose to use _GLIBCXX_USE_CXX11_ABI=0 ?

Yes, there are suppose to be compatible.

The problem is that the process to generate the gmsh wheels does not seem to be compliant as it is re-packaging its SDK.

Source: https://gitlab.onelab.info/gmsh/gmsh/-/blob/master/.gitlab-ci.yml#L436

Does this mean initializing the library on Slicer compiled a newer system compiler work ?

Yes, assuming this is the only issue, this should indeed work.

See details

That said, attempting to initialize the library still lead to a segfault.

There are likely additional symbol clashes to be investigated.

Path forward

As mentioned by @lassoan , considering that the library is distributed under the term of a copyleft (non-permissive) license[1:1], I suggest you consider reaching out to one of the commercial partner listed here.

The steps would be to revamp the build-system of gmsh to build compliant wheels (e.g by leveraging https://scikit-build.org & relevant manylinux docker image)


  1. Permissive software license - Wikipedia ↩︎ ↩︎

  2. API Evolution and Deprecation History ↩︎

2 Likes

Thanks for the detailed analysis @jcfr

I’ve contacted the Gmsh developers here: https://gitlab.onelab.info/gmsh/gmsh/-/issues/2474

Are there any plans for Slicer to migrate to the modern C++11 ABI at some point?

Using manylinux wheels allows to fulfill our goal of making Slicer compatible with computers that are bought in the past 5 years. I don’t think we would compromise on this for an incorrectly packaged GPL/commercial library. Also, based on what Jc described above, flipping the cxx11 abi flag might not solve all problems.

I would recommend to get/build gmsh binary and launch it in Slicer in the startup environment instead of trying to install it as a Python package in Slicer’s virtual Python environment.

Or - even better in the long term - use open solutions, such as fTetWild or Cleaver.

1 Like

Thanks for the explanation. There’s an interesting discussion on pytorch where they have the opposite problem (trying to link to pytorch Python packages in a project that uses _GLIBCXX_USE_CXX11_ABI=1):

I guess there is also the fact that Slicer requires at least C++17. It seems there isn’t really a clear solution for this at the moment.

This sounds like a good idea, but it will require us to change a lot of the code and won’t allow interactive use of Gmsh within Slicer (although this probably doesn’t matter too much at the moment). I’ll try first to compile Gmsh from source and import the library that way.

Unfortunately, all the free options apart from Gmsh that I have seen do not have the features that we need to create body-conforming meshes with multiple parts, but I will keep looking.

Just for our information (to know what to keep or eye on), could you tell more about the missing features? Maybe also include 1-2 pictures to illustrate.

The main feature we require is to be able to create meshes from multiple surfaces that conform at the interfaces defined by the surfaces. The volume mesh should use exactly the same triangles as those of the surfaces (although sometimes we remesh the surface to match the element size of the volume elements depending on the application). The surfaces define a change in material or contact between different parts. Here is an example from BioPARR of an abdominal aortic aneurysm (AAA) with intraluminal thrombus (ILT).

These are the three surfaces (AAA exterior surface in blue, interior surface in yellow and ILT surface in red):

image

This is the generated tetrahedral mesh (wall in blue and ILT in red):

image

For many applications, we need to use hexahedral meshes with multiple parts and material interfaces, which is more difficult to generate and often requires commercial meshing software such as HyperMesh or Cubit.

The only free option which has tetrahedral and hexahedral meshers that compares to the commercial software that I have found is SALOME. This has more features than Gmsh but is a much bigger software (it actually includes Gmsh as a plugin). It would be nice to add 3D Slicer as a module within SALOME, similar to what they did with ParaView in their PARAVIS module. This would enable a complete numerical simulation framework for medical images in a single application.

Thanks for the additional information, it is very interesting and useful.

If SALOME’s built-in SMESH meshing tool can do all what you need (without using Gmsh) then it could be a good solution. To get a complete numerical simulation framework for medical images in a single application, SALOME could be used directly via Slicer’s GUI, executing SALOME functions using Python scripting. Or a bridge could be built between Slicer and SALOME to synchronize the scene content between the two applications in real-time (both applications are Python-scriptable, so it would not be hard to implement it at all).

1 Like

I now have Gmsh Python working inside 3D Slicer by recompiling Gmsh using the _GLIBCXX_USE_CXX11_ABI=0 flag.

Full details can be found here: Cannot import gmsh Python package · Issue #41 · SlicerCBM/SlicerCBM · GitHub

Is there any way to automate this so that Gmsh (or other similar dependencies) is compiled when a user installs an extension?

Your can build the extension as part of your extension and bundle it with your extension, as it is done in some other extensions.

@jcfr what do you think? Can you suggest extensions that can serve as example?