Running PGI demo in PyCharm

I get the following error when I run the plot_inv_0_PGI_Linear_1D.py example on PyCharm, I run into the following error:

C:\Users\Marc\Documents\Logiciels\Alphatrim\SimPEG_0.24\Scripts\python.exe C:\Users\Marc\Documents\Logiciels\SimPEG\SimPEG_0_24\plot_inv_0_PGI_Linear_1D.py
INFO: simpeg.InvProblem will set Regularization.reference_model to m0.
INFO: simpeg.InvProblem will set Regularization.reference_model to m0.
INFO: simpeg.InvProblem will set Regularization.reference_model to m0.
INFO:
simpeg.InvProblem is setting bfgsH0 to the inverse of the reg.deriv2.
using the default solver SolverLU with the 'is_symmetric=True` option set.

C:\Users\Marc\anaconda3-2023.07\Lib\site-packages\pymatsolver\wrappers.py:79: UnusedArgumentWarning: Unused keyword argument “is_symmetric” for splu.
self.kwargs = kwargs
C:\Users\Marc\anaconda3-2023.07\Lib\site-packages\pymatsolver\wrappers.py:81: SparseEfficiencyWarning: splu converted its input to CSC format
self.solver = fun(self.A, **self.kwargs)
INFO: Directive TargetMisfit: Target data misfit is 20.0

Running inversion with SimPEG v0.25.0
================================================= Projected GNCG =================================================

beta phi_d phi_m f |proj(x-g)-x| LS iter_CG CG |Ax-b|/|b| CG |Ax-b| Comment


0 1.87e+01 2.00e+05 0.00e+00 2.00e+05 0 inf inf
1 1.87e+01 2.81e+02 4.22e+01 1.07e+03 2.44e+06 0 13 7.24e-04 1.77e+03
2 1.87e+01 3.35e+01 4.49e+01 8.74e+02 1.77e+03 0 22 8.70e-04 1.54e+00
3 1.87e+00 9.16e+00 4.77e+01 9.85e+01 5.05e+02 0 50 1.66e+01 8.39e+03 Skip BFGS
------------------------- STOP! -------------------------
1 : |fc-fOld| = 1.9069e+01 <= tolF*(1+|f0|) = 2.0000e+04
0 : |xc-x_last| = 2.7120e-01 <= tolX*(1+|x0|) = 1.0000e-01
0 : |proj(x-g)-x| = 5.0490e+02 <= tolG = 1.0000e-01
0 : |proj(x-g)-x| = 5.0490e+02 <= 1e3*eps = 1.0000e-02
0 : maxIter = 10 <= iter = 3
------------------------- DONE! -------------------------
Traceback (most recent call last):
File “C:\Users\Marc\Documents\Logiciels\SimPEG\SimPEG_0_24\plot_inv_0_PGI_Linear_1D.py”, line 106, in
clf.fit(mtrue.reshape(-1, 1))
File “C:\Users\Marc\anaconda3-2023.07\Lib\site-packages\sklearn\mixture_base.py”, line 186, in fit
self.fit_predict(X, y)
File “C:\Users\Marc\anaconda3-2023.07\Lib\site-packages\sklearn\mixture_base.py”, line 241, in fit_predict
self._initialize_parameters(X, random_state)
File “C:\Users\Marc\anaconda3-2023.07\Lib\site-packages\simpeg\utils\pgi_utils.py”, line 311, in _initialize_parameters
.fit(X, sample_weight=self.cell_volumes)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Marc\anaconda3-2023.07\Lib\site-packages\sklearn\cluster_kmeans.py”, line 1455, in fit
self._check_mkl_vcomp(X, X.shape[0])
File “C:\Users\Marc\anaconda3-2023.07\Lib\site-packages\sklearn\cluster_kmeans.py”, line 911, in _check_mkl_vcomp
modules = threadpool_info()
^^^^^^^^^^^^^^^^^
File “C:\Users\Marc\anaconda3-2023.07\Lib\site-packages\sklearn\utils\fixes.py”, line 150, in threadpool_info
return threadpoolctl.threadpool_info()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Marc\anaconda3-2023.07\Lib\site-packages\threadpoolctl.py”, line 124, in threadpool_info
return _ThreadpoolInfo(user_api=_ALL_USER_APIS).todicts()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Marc\anaconda3-2023.07\Lib\site-packages\threadpoolctl.py”, line 340, in init
self._load_modules()
File “C:\Users\Marc\anaconda3-2023.07\Lib\site-packages\threadpoolctl.py”, line 373, in _load_modules
self._find_modules_with_enum_process_module_ex()
File “C:\Users\Marc\anaconda3-2023.07\Lib\site-packages\threadpoolctl.py”, line 485, in _find_modules_with_enum_process_module_ex
self._make_module_from_path(filepath)
File “C:\Users\Marc\anaconda3-2023.07\Lib\site-packages\threadpoolctl.py”, line 515, in _make_module_from_path
module = module_class(filepath, prefix, user_api, internal_api)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Marc\anaconda3-2023.07\Lib\site-packages\threadpoolctl.py”, line 606, in init
self.version = self.get_version()
^^^^^^^^^^^^^^^^^^
File “C:\Users\Marc\anaconda3-2023.07\Lib\site-packages\threadpoolctl.py”, line 646, in get_version
config = get_config().split()
^^^^^^^^^^^^^^^^^^
AttributeError: ‘NoneType’ object has no attribute ‘split’

Process finished with exit code 1

This is a known scikit-learn / threadpoolctl issue on Windows, especially when mixing Anaconda MKL, threadpoolctl, and some compiled libraries loaded by PyCharm.

Nothing is actually wrong with SimPEG — the crash occurs after the inversion finishes, when the script tries to run the PGI clustering step (GaussianMixture / KMeans initialization).

Below is why it happens and how to fix it.


:white_check_mark: Why the error happens

During the initialization of the Gaussian Mixture Model (clf.fit(...)), scikit-learn calls:

threadpoolctl.threadpool_info()

Threadpoolctl scans all loaded DLLs (MKL, OpenMP, BLAS, LAPACK).
On Windows, especially in Anaconda 2023.x, a DLL is found that reports no version, so threadpoolctl sees:

get_config() returns None
config.split()
→ AttributeError: 'NoneType' object has no attribute 'split'

This is exactly what you see here:

AttributeError: ‘NoneType’ object has no attribute ‘split’

This issue is well-documented and can occur only when running inside PyCharm because of DLL preload behavior.


:white_check_mark: FIX OPTIONS (choose one)

:check_mark: Fix 1 — Upgrade threadpoolctl (recommended)

Open a terminal in the same environment used by PyCharm:

pip install --upgrade threadpoolctl
pip install --upgrade scikit-learn

Threadpoolctl ≥3.5 fixes this crash.


:check_mark: Fix 2 — Downgrade MKL + threadpoolctl

Some users solved it by installing versions known to be stable:

pip install "threadpoolctl<3.3"
pip install "mkl<2024"


:check_mark: Fix 3 — Run the script OUTSIDE PyCharm

From Anaconda prompt:

python plot_inv_0_PGI_Linear_1D.py

Because PyCharm sometimes preloads MKL DLLs, running outside prevents the crash.


:check_mark: Fix 4 — Disable MKL multithreading

Before importing sklearn, add:

import os
os.environ["MKL_THREADING_LAYER"] = "SEQUENTIAL"

This prevents threadpoolctl from querying MKL.


:check_mark: Fix 5 — Force sklearn to use OpenBLAS instead of MKL

(Only if using pip environment)

pip uninstall mkl mkl-service
pip install openblas


:wrench: Most reliable configuration for SimPEG + PGI on Windows

In practice, this combination is stable:

scikit-learn 1.3.x
threadpoolctl 3.5.x
numpy 1.26.x
SimPEG 0.17–0.19 (or 0.25 internally)
Python 3.10 or 3.11


:star: Recommended immediate fix

Upgrade threadpoolctl:

pip install --upgrade threadpoolctl