mvpure-py 2.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. mvpure_py-2.3.2/.github/workflows/pypi_release.yml +66 -0
  2. mvpure_py-2.3.2/.gitignore +10 -0
  3. mvpure_py-2.3.2/LICENSE +28 -0
  4. mvpure_py-2.3.2/PKG-INFO +143 -0
  5. mvpure_py-2.3.2/README.md +111 -0
  6. mvpure_py-2.3.2/mvpure_py/__init__.py +3 -0
  7. mvpure_py-2.3.2/mvpure_py/_version.py +24 -0
  8. mvpure_py-2.3.2/mvpure_py/localizer/__init__.py +21 -0
  9. mvpure_py-2.3.2/mvpure_py/localizer/_utils.py +178 -0
  10. mvpure_py-2.3.2/mvpure_py/localizer/localizer_utils.py +345 -0
  11. mvpure_py-2.3.2/mvpure_py/localizer/mvpure_localizer.py +783 -0
  12. mvpure_py-2.3.2/mvpure_py/simulation/__init__.py +16 -0
  13. mvpure_py-2.3.2/mvpure_py/simulation/simulate.py +722 -0
  14. mvpure_py-2.3.2/mvpure_py/simulation/validate.py +487 -0
  15. mvpure_py-2.3.2/mvpure_py/tests/__init__.py +0 -0
  16. mvpure_py-2.3.2/mvpure_py/tests/test_algebra.py +65 -0
  17. mvpure_py-2.3.2/mvpure_py/tests/test_forward_subset.py +229 -0
  18. mvpure_py-2.3.2/mvpure_py/tests/test_helper.py +82 -0
  19. mvpure_py-2.3.2/mvpure_py/tests/test_translation.py +155 -0
  20. mvpure_py-2.3.2/mvpure_py/tests/test_utils.py +53 -0
  21. mvpure_py-2.3.2/mvpure_py/utils/__init__.py +18 -0
  22. mvpure_py-2.3.2/mvpure_py/utils/_helper.py +36 -0
  23. mvpure_py-2.3.2/mvpure_py/utils/_utils.py +68 -0
  24. mvpure_py-2.3.2/mvpure_py/utils/algebra.py +14 -0
  25. mvpure_py-2.3.2/mvpure_py/utils/translation.py +503 -0
  26. mvpure_py-2.3.2/mvpure_py/viz/__init__.py +19 -0
  27. mvpure_py-2.3.2/mvpure_py/viz/group_viz.py +201 -0
  28. mvpure_py-2.3.2/mvpure_py/viz/viz.py +219 -0
  29. mvpure_py-2.3.2/mvpure_py.egg-info/PKG-INFO +143 -0
  30. mvpure_py-2.3.2/mvpure_py.egg-info/SOURCES.txt +40 -0
  31. mvpure_py-2.3.2/mvpure_py.egg-info/dependency_links.txt +1 -0
  32. mvpure_py-2.3.2/mvpure_py.egg-info/requires.txt +14 -0
  33. mvpure_py-2.3.2/mvpure_py.egg-info/scm_file_list.json +36 -0
  34. mvpure_py-2.3.2/mvpure_py.egg-info/scm_version.json +8 -0
  35. mvpure_py-2.3.2/mvpure_py.egg-info/top_level.txt +1 -0
  36. mvpure_py-2.3.2/pyproject.toml +55 -0
  37. mvpure_py-2.3.2/setup.cfg +4 -0
  38. mvpure_py-2.3.2/tutorials/Preprocessing data from oddball paradigm.ipynb +909 -0
  39. mvpure_py-2.3.2/tutorials/Simulating and Localizing Multi-Source EEG Activity with MVPURE_py.ipynb +1094 -0
  40. mvpure_py-2.3.2/tutorials/Simulating and Localizing Multi-Source EEG Activity /342/200/223 Multiple Runs.ipynb" +2425 -0
  41. mvpure_py-2.3.2/tutorials/Source localization and reconstruction on data from oddball paradigm.ipynb +1696 -0
  42. mvpure_py-2.3.2/tutorials/preprocessing_utils.py +298 -0
@@ -0,0 +1,66 @@
1
+
2
+ name: Publish to PyPI
3
+
4
+ on:
5
+ release:
6
+ types: [published]
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ build:
13
+ name: Build package
14
+ runs-on: ubuntu-latest
15
+
16
+ steps:
17
+ - name: Check out repository
18
+ uses: actions/checkout@v6
19
+ with:
20
+ fetch-depth: 0
21
+ persist-credentials: false
22
+
23
+ - name: Set up Python
24
+ uses: actions/setup-python@v6
25
+ with:
26
+ python-version: "3.12"
27
+
28
+ - name: Install build tools
29
+ run: python -m pip install --upgrade build
30
+
31
+ - name: Build distributions
32
+ run: python -m build
33
+
34
+ - name: Check distributions
35
+ run: |
36
+ python -m pip install --upgrade twine
37
+ python -m twine check dist/*
38
+
39
+ - name: Upload build artifacts
40
+ uses: actions/upload-artifact@v5
41
+ with:
42
+ name: python-package-distributions
43
+ path: dist/
44
+ if-no-files-found: error
45
+
46
+ publish:
47
+ name: Publish to PyPI
48
+ needs: build
49
+ runs-on: ubuntu-latest
50
+
51
+ environment:
52
+ name: pypi
53
+ url: https://pypi.org/project/mvpure-py/
54
+
55
+ permissions:
56
+ id-token: write
57
+
58
+ steps:
59
+ - name: Download build artifacts
60
+ uses: actions/download-artifact@v6
61
+ with:
62
+ name: python-package-distributions
63
+ path: dist/
64
+
65
+ - name: Publish distributions
66
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,10 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .pytest_cache/
5
+ .coverage
6
+ build/
7
+ dist/
8
+ .venv/
9
+ entorno/
10
+ /docs/
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Julia Jurkowska
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,143 @@
1
+ Metadata-Version: 2.4
2
+ Name: mvpure-py
3
+ Version: 2.3.2
4
+ Summary: EEG/MEG multi-source spatial filters and source localization tools
5
+ Author: Julia Jurkowska
6
+ License-Expression: BSD-3-Clause
7
+ Project-URL: Homepage, https://github.com/julia-jurkowska/mvpure-tools
8
+ Project-URL: Repository, https://github.com/julia-jurkowska/mvpure-tools
9
+ Project-URL: Documentation, https://julia-jurkowska.github.io/mvpure-tools/
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Scientific/Engineering
14
+ Classifier: Topic :: Software Development
15
+ Requires-Python: >=3.13
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: joblib==1.5.1
19
+ Requires-Dist: matplotlib==3.11.2
20
+ Requires-Dist: mne==1.13.2
21
+ Requires-Dist: numpy==2.5.4
22
+ Requires-Dist: pandas==3.1.0
23
+ Requires-Dist: scikit-learn==1.9.1
24
+ Requires-Dist: scipy==1.18.1
25
+ Requires-Dist: termcolor==3.3.0
26
+ Requires-Dist: tqdm==4.67.1
27
+ Requires-Dist: nibabel==5.4.2
28
+ Requires-Dist: PyQt5==5.15.11
29
+ Provides-Extra: test
30
+ Requires-Dist: pytest==9.1.1; extra == "test"
31
+ Dynamic: license-file
32
+
33
+ # MVPURE-PY package
34
+ <div style="text-align: center;">
35
+ <img width="256" height="256" alt="mvpure_py logo" src="https://github.com/user-attachments/assets/ee880cfc-bb19-486b-be65-8c59f61c9e87" />
36
+ </div>
37
+
38
+ EEG/MEG Multi-Source Localizers with **mvpure-py**
39
+ Extends **MNE-Python** with multi-source neural activity indices and spatial filters.
40
+ Based on *“Multi-Source Neural Activity Indices for EEG/MEG Localization: A Two-Stage Spatial Filtering Framework and Extension to MNE-Python”*.
41
+
42
+ **Repository:** [GitHub](https://github.com/julia-jurkowska/mvpure-tools) \
43
+ **Tutorial & online docs:** [mvpure_py documentation](https://julia-jurkowska.github.io/mvpure-tools)
44
+
45
+ ---
46
+
47
+ ## Table of Contents
48
+
49
+ 1. [Overview](#overview)
50
+ 2. [Features](#features)
51
+ 3. [Dependencies](#dependencies)
52
+ 4. [Installation](#installation)
53
+ - From source
54
+ 5. [Tutorial & Examples](#tutorial--examples)
55
+ 6. [Citation](#citation)
56
+ ---
57
+ ## Overview
58
+
59
+ The **mvpure-tools** package implements multi-source neural activity indices for EEG / MEG source localization, extending MNE-Python’s API. It enables improved reconstruction when sources may be correlated, overcoming limitations of single-source beamforming methods (e.g. LCMV) in certain settings.
60
+
61
+ Key contributions include:
62
+
63
+ - Algebraic, compact forms for multi-source neural activity indices
64
+ - Seamless integration into MNE-Python workflows (covariance, forward/inverse handling, visualization)
65
+ - A step-by-step tutorial using real EEG data (oddball paradigm, synthetic data)
66
+
67
+ ---
68
+
69
+ ## Features
70
+
71
+ - Neural activity indices (MAI_MVP) in the multi-source setting
72
+ - Iterative localization algorithms compatible with large candidate source sets
73
+ - Built on top of MNE-Python, so you can combine it with standard EEG / MEG toolchains
74
+ - Tutorial and example scripts included
75
+
76
+ ---
77
+ ## Dependencies
78
+
79
+ Before installing, make sure you have:
80
+
81
+ - Python
82
+ - **MNE-Python**
83
+ - NumPy, SciPy
84
+ - (Other dependencies listed in `requirements.txt`)
85
+
86
+ ---
87
+
88
+ ## Installation
89
+ ### From Source (recommended)
90
+ To install from GitHub:
91
+
92
+ 1. Clone the repository
93
+ ```bash
94
+ git clone https://github.com/julia-jurkowska/mvpure-tools.git
95
+ cd mvpure-tools
96
+ ```
97
+ 2. (Optional) create a virtual environment
98
+
99
+ ```bash
100
+ python3 -m venv venv
101
+ source venv/bin/activate
102
+ ```
103
+
104
+ 3. Install dependencies
105
+ ```bash
106
+ pip install -r requirements.txt
107
+ ```
108
+
109
+ 4. Install the package
110
+ ```bash
111
+ pip install .
112
+ ```
113
+ or for development mode:
114
+ ```bash
115
+ pip install -e .
116
+ ```
117
+
118
+ 5. Verify installation:
119
+
120
+ ```python
121
+ import mvpure_py
122
+ from mvpure_py import localizer
123
+ ```
124
+ ---
125
+ ## Tutorial & Examples
126
+ See tutorials on documentation site: [documentation](https://julia-jurkowska.github.io/mvpure-tools).
127
+
128
+ The tutorials walk you through:
129
+
130
+ 1. Preprocessing (filtering, artifact rejection, ICA, epoching)
131
+ 2. Estimation of number of sources and rank
132
+ 3. Localization of sources using neural activity indices
133
+ 4. Reconstruction of time courses
134
+ 5. Visualization of estimated sources
135
+ ---
136
+
137
+ ## Citation
138
+
139
+ If you use **mvpure_py** in your work, please cite:
140
+
141
+ > Jurkowska, J., Dreszer, J., Lewandowska, M., Tolpa, K., Piotrowski, T.,
142
+ > *Multi-source neural activity indices for EEG/MEG localization: A two-stage spatial filtering framework and extension to MNE-Python*, NeuroImage, Volume 339, 2026, 122126, <https://doi.org/10.1016/j.neuroimage.2026.122126>.
143
+
@@ -0,0 +1,111 @@
1
+ # MVPURE-PY package
2
+ <div style="text-align: center;">
3
+ <img width="256" height="256" alt="mvpure_py logo" src="https://github.com/user-attachments/assets/ee880cfc-bb19-486b-be65-8c59f61c9e87" />
4
+ </div>
5
+
6
+ EEG/MEG Multi-Source Localizers with **mvpure-py**
7
+ Extends **MNE-Python** with multi-source neural activity indices and spatial filters.
8
+ Based on *“Multi-Source Neural Activity Indices for EEG/MEG Localization: A Two-Stage Spatial Filtering Framework and Extension to MNE-Python”*.
9
+
10
+ **Repository:** [GitHub](https://github.com/julia-jurkowska/mvpure-tools) \
11
+ **Tutorial & online docs:** [mvpure_py documentation](https://julia-jurkowska.github.io/mvpure-tools)
12
+
13
+ ---
14
+
15
+ ## Table of Contents
16
+
17
+ 1. [Overview](#overview)
18
+ 2. [Features](#features)
19
+ 3. [Dependencies](#dependencies)
20
+ 4. [Installation](#installation)
21
+ - From source
22
+ 5. [Tutorial & Examples](#tutorial--examples)
23
+ 6. [Citation](#citation)
24
+ ---
25
+ ## Overview
26
+
27
+ The **mvpure-tools** package implements multi-source neural activity indices for EEG / MEG source localization, extending MNE-Python’s API. It enables improved reconstruction when sources may be correlated, overcoming limitations of single-source beamforming methods (e.g. LCMV) in certain settings.
28
+
29
+ Key contributions include:
30
+
31
+ - Algebraic, compact forms for multi-source neural activity indices
32
+ - Seamless integration into MNE-Python workflows (covariance, forward/inverse handling, visualization)
33
+ - A step-by-step tutorial using real EEG data (oddball paradigm, synthetic data)
34
+
35
+ ---
36
+
37
+ ## Features
38
+
39
+ - Neural activity indices (MAI_MVP) in the multi-source setting
40
+ - Iterative localization algorithms compatible with large candidate source sets
41
+ - Built on top of MNE-Python, so you can combine it with standard EEG / MEG toolchains
42
+ - Tutorial and example scripts included
43
+
44
+ ---
45
+ ## Dependencies
46
+
47
+ Before installing, make sure you have:
48
+
49
+ - Python
50
+ - **MNE-Python**
51
+ - NumPy, SciPy
52
+ - (Other dependencies listed in `requirements.txt`)
53
+
54
+ ---
55
+
56
+ ## Installation
57
+ ### From Source (recommended)
58
+ To install from GitHub:
59
+
60
+ 1. Clone the repository
61
+ ```bash
62
+ git clone https://github.com/julia-jurkowska/mvpure-tools.git
63
+ cd mvpure-tools
64
+ ```
65
+ 2. (Optional) create a virtual environment
66
+
67
+ ```bash
68
+ python3 -m venv venv
69
+ source venv/bin/activate
70
+ ```
71
+
72
+ 3. Install dependencies
73
+ ```bash
74
+ pip install -r requirements.txt
75
+ ```
76
+
77
+ 4. Install the package
78
+ ```bash
79
+ pip install .
80
+ ```
81
+ or for development mode:
82
+ ```bash
83
+ pip install -e .
84
+ ```
85
+
86
+ 5. Verify installation:
87
+
88
+ ```python
89
+ import mvpure_py
90
+ from mvpure_py import localizer
91
+ ```
92
+ ---
93
+ ## Tutorial & Examples
94
+ See tutorials on documentation site: [documentation](https://julia-jurkowska.github.io/mvpure-tools).
95
+
96
+ The tutorials walk you through:
97
+
98
+ 1. Preprocessing (filtering, artifact rejection, ICA, epoching)
99
+ 2. Estimation of number of sources and rank
100
+ 3. Localization of sources using neural activity indices
101
+ 4. Reconstruction of time courses
102
+ 5. Visualization of estimated sources
103
+ ---
104
+
105
+ ## Citation
106
+
107
+ If you use **mvpure_py** in your work, please cite:
108
+
109
+ > Jurkowska, J., Dreszer, J., Lewandowska, M., Tolpa, K., Piotrowski, T.,
110
+ > *Multi-source neural activity indices for EEG/MEG localization: A two-stage spatial filtering framework and extension to MNE-Python*, NeuroImage, Volume 339, 2026, 122126, <https://doi.org/10.1016/j.neuroimage.2026.122126>.
111
+
@@ -0,0 +1,3 @@
1
+ from ._version import __version__
2
+
3
+ __all__ = ["__version__"]
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '2.3.2'
22
+ __version_tuple__ = version_tuple = (2, 3, 2)
23
+
24
+ __commit_id__ = commit_id = 'g8b490f09b'
@@ -0,0 +1,21 @@
1
+ """
2
+ References
3
+ ----------
4
+ .. [1] Jurkowska, J., Dreszer, J., Lewandowska, M., Tolpa, K., & Piotrowski, T. J. (2025).
5
+ Multi-Source Neural Activity Indices and Spatial Filters for EEG/MEG Inverse Problem: An Extension to MNE-Python. bioRxiv, 2025-09.
6
+ """
7
+ from .mvpure_localizer import (
8
+ localize,
9
+ Localized,
10
+ read_localized
11
+ )
12
+ from .localizer_utils import (
13
+ get_activity_index,
14
+ )
15
+
16
+ from ._utils import (
17
+ _check_localize_params,
18
+ _prepare_localize_params,
19
+ _check_vertices_and_indices,
20
+ _check_n_sources_param
21
+ )
@@ -0,0 +1,178 @@
1
+ from ..utils import _check_hemi_param
2
+
3
+ import mne
4
+ import numpy as np
5
+ from termcolor import colored
6
+ import logging
7
+ logging.basicConfig(
8
+ level=logging.WARNING,
9
+ format='[%(levelname)s] %(message)s'
10
+ )
11
+
12
+
13
+ def _check_localize_params(
14
+ forward: mne.Forward,
15
+ leadfield: np.array) -> None:
16
+ """
17
+ Checking user input for mvpure_py.localizer.localize() function.
18
+ """
19
+ if forward is None and leadfield is None:
20
+ raise ValueError("One of the parameters 'forward' and 'leadfield' should not be None")
21
+
22
+ if forward is not None and leadfield is not None:
23
+ if np.array_equal(forward['sol']['data'], leadfield):
24
+ raise ValueError("Both parameters 'forward' and 'leadfield' were specified. "
25
+ "They should be equal, but they are not.")
26
+
27
+
28
+ def _prepare_localize_params(
29
+ forward: mne.Forward,
30
+ leadfield: np.array) -> np.array:
31
+ """
32
+ Adjusting input parameters in mvpure_py.localizer.localize() function.
33
+ Handling forward/leadfield options.
34
+ """
35
+ if forward is not None:
36
+ leadfield = forward["sol"]["data"]
37
+
38
+ return leadfield
39
+
40
+
41
+ def _check_n_sources_param(n_sources: int) -> None:
42
+ """
43
+ Checks type of 'n_sources_to_localize' from mvpure_py.localizer.localize() function.
44
+ Should be an integer.
45
+ """
46
+ if not isinstance(n_sources, (int, np.integer)):
47
+ raise TypeError(f"Parameter 'n_sources_to_localize' should be an integer. Got type: {type(n_sources)} instead.")
48
+
49
+
50
+ def _check_rank(
51
+ r: int | str | float | list,
52
+ n_sources_to_localize: int):
53
+ """
54
+ Checking correctness of rank optimization ('r') parameter.
55
+ """
56
+ if not isinstance(r, (int, np.integer, str, float, np.floating, list)):
57
+ raise ValueError(f"Optimization parameter 'r' (set to: {r}) should be of type: int, float, string or list. "
58
+ f"Got {type(r)} instead.")
59
+
60
+ # if 'r' is a list, it should contain integers / floats
61
+ # and all elements should be equal or less to n_sources_to_localize,
62
+ if isinstance(r, list):
63
+ if not all(
64
+ isinstance(x, (int, np.integer, float, np.floating)) and
65
+ n_sources_to_localize >= x >= 1
66
+ for x in r
67
+ ):
68
+ raise ValueError("If `r` is a list, all elements should be int or float"
69
+ " and equal or less than number of sources to localize.")
70
+
71
+ # 'r' should be less or equal to number of sources to localize
72
+ if isinstance(r, (int, np.integer)) and r > n_sources_to_localize:
73
+ raise ValueError(f"Optimization parameter 'r' (set to {r}) should be equal or less than"
74
+ f" number of sources to localize ('n_sources_to_localize' set to {n_sources_to_localize}).")
75
+
76
+ # only option for 'r' as string is 'full'
77
+ if isinstance(r, str) and r not in ["full"]:
78
+ raise ValueError(f"If parameter 'r' is a string it should be set to 'full'. "
79
+ f"Got {r} instead.")
80
+
81
+ # if 'r' == 0, use full rank
82
+ if isinstance(r, (int, np.integer)) and r == 0:
83
+ return "full"
84
+
85
+ # if 'r' is smaller than zero, take n_sources_to_localize - abs(r)
86
+ if isinstance(r, (int, np.integer)) and r < 0 and (n_sources_to_localize - abs(r)) > 0:
87
+ adjusted_value = n_sources_to_localize - abs(r)
88
+ logging.warning(
89
+ f"Got rank lower than zero. Taking n_sources_to_localize - {abs(r)} = {adjusted_value} instead."
90
+ )
91
+ return adjusted_value
92
+
93
+ # if 'r' is smaller than zero and n_sources_to_localize - abs(r) == 0, use full rank
94
+ if isinstance(r, (int, np.integer)) and r < 0 and (n_sources_to_localize - abs(r)) == 0:
95
+ return "full"
96
+
97
+ # if 'r' is smaller than zero and n_sources_to_localize - abs(r) == 0, raise error
98
+ if isinstance(r, (int, np.integer)) and r < 0 and (n_sources_to_localize - abs(r)) < 0:
99
+ raise ValueError(f"Optimization parameter 'r' (set to {r}) should be equal or higher than 0.")
100
+
101
+ # if using float and float can not be converted to integer - raise error
102
+ if isinstance(r, (float, np.floating)) and int(r) != r:
103
+ raise TypeError(f"Parameter 'r' should be type an integer (if numeric). Got float instead.")
104
+
105
+
106
+ def _prepare_localizer_to_use(localizer_to_use: str | list[str]):
107
+ """
108
+ Checking and adjusting 'localizer_to_use' parameter from mvpure_py.localizer.localize() function.
109
+ """
110
+ # list of all localizers options
111
+ all_localizers = ['mai', 'mai_mvp']
112
+ # if localizer_to_use is a string
113
+ if isinstance(localizer_to_use, str):
114
+ # if localizer_to_use == 'all' use all localizers
115
+ if localizer_to_use == 'all':
116
+ param_localizer_to_use = all_localizers
117
+ # can be single name of localizers
118
+ elif localizer_to_use in all_localizers:
119
+ param_localizer_to_use = [localizer_to_use]
120
+ # otherwise raise ValueError
121
+ else:
122
+ raise ValueError(f"If 'localizer_to_use' is a string it should be either 'all' or "
123
+ f"name of one of the localizers to use. Possible options are: {all_localizers}. "
124
+ f"Got '{localizer_to_use}' instead.")
125
+ elif isinstance(localizer_to_use, list):
126
+ param_localizer_to_use = [loc for loc in localizer_to_use if loc in all_localizers]
127
+ if len(param_localizer_to_use) < len(localizer_to_use):
128
+ print(colored(
129
+ f"WARNING: One or more of localizers' names are not valid."
130
+ f" Possible options are: {all_localizers}, got {localizer_to_use}.",
131
+ "yellow"
132
+ ))
133
+ if len(param_localizer_to_use) == 0:
134
+ raise ValueError(f"None of the localizers' name are valid."
135
+ f" Possible options are: {all_localizers}, got {localizer_to_use}")
136
+ else:
137
+ raise ValueError(f"'localizer_to_use' should be either list of valid localizers' names "
138
+ f"or string with single localizer name")
139
+ return param_localizer_to_use
140
+
141
+
142
+ def _define_hemi_based_on_vertices(localized) -> str:
143
+ """
144
+ Define hemi (`both`, `rh`, `lh`) based on vertices stored in `localized` object.
145
+ """
146
+ if hasattr(localized['stc'], 'lh_vertno') and hasattr(localized['stc'], 'rh_vertno'):
147
+ hemi = "both"
148
+ elif hasattr(localized['stc'], 'lh_vertno'):
149
+ hemi = "lh"
150
+ elif hasattr(localized['stc'], 'rh_vertno'):
151
+ hemi = "rh"
152
+
153
+ return hemi
154
+
155
+
156
+ def _check_norm_param(norm):
157
+ if norm not in ["max", "sum"]:
158
+ raise ValueError(f"'norm' can be equal to one of the following: "
159
+ f" 'max' (max normalization), 'sum' (L1 normalization. "
160
+ f"Got {norm} instead.")
161
+
162
+
163
+ def _check_vertices_and_indices(lh_vertices: list, lh_indices: list, rh_vertices: list, rh_indices: list):
164
+ if (lh_indices is not None and lh_vertices is None) or (lh_indices is None and lh_vertices is not None):
165
+ raise ValueError(f"Both 'lh_vertices' and 'lh_indices' should be specified. "
166
+ f"Got lh_vertices={lh_vertices} and lh_indices={lh_indices}.")
167
+
168
+ if (rh_indices is not None and rh_vertices is None) or (rh_indices is None and rh_vertices is not None):
169
+ raise ValueError(f"Both 'rh_vertices' and 'rh_indices' should be specified. "
170
+ f"Got rh_vertices={rh_vertices} and rh_indices={rh_indices}.")
171
+
172
+ if lh_vertices is not None and lh_indices is not None and len(lh_vertices) != len(lh_indices):
173
+ raise ValueError(f"Can not add vertices to Localized object because length of vertices list ({len(lh_vertices)})"
174
+ f"does not match length of indices list ({len(lh_indices)}).")
175
+
176
+ if rh_vertices is not None and rh_indices is not None and len(rh_vertices) != len(rh_indices):
177
+ raise ValueError(f"Can not add vertices to Localized object because length of vertices list ({len(rh_vertices)})"
178
+ f"does not match length of indices list ({len(rh_indices)}).")