MNutils 1.2.0__py3-none-any.whl
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.
- mnutils/GEExam.py +495 -0
- mnutils/GESeries.py +1578 -0
- mnutils/__init__.py +54 -0
- mnutils/_scripts.py +177 -0
- mnutils/fitting/AMARES.py +831 -0
- mnutils/fitting/__init__.py +5 -0
- mnutils/matlab/__init__.py +13 -0
- mnutils/matlab/setup_matlab.py +116 -0
- mnutils/plotting/__init__.py +38 -0
- mnutils/plotting/_widgets/__init__.py +5 -0
- mnutils/plotting/_widgets/_html.py +34 -0
- mnutils/plotting/_widgets/_shared/__init__.py +50 -0
- mnutils/plotting/_widgets/_shared/dom.js +124 -0
- mnutils/plotting/_widgets/_shared/theme.css +140 -0
- mnutils/plotting/_widgets/image_grid.css +202 -0
- mnutils/plotting/_widgets/image_grid.js +212 -0
- mnutils/plotting/_widgets/image_grid.py +86 -0
- mnutils/plotting/_widgets/mrsi_inspector.css +376 -0
- mnutils/plotting/_widgets/mrsi_inspector.js +681 -0
- mnutils/plotting/_widgets/mrsi_inspector.py +70 -0
- mnutils/plotting/_widgets/slice_viewer.css +38 -0
- mnutils/plotting/_widgets/slice_viewer.js +41 -0
- mnutils/plotting/_widgets/slice_viewer.py +35 -0
- mnutils/plotting/images.py +1399 -0
- mnutils/plotting/saving.py +138 -0
- mnutils/plotting/spectra.py +357 -0
- mnutils/py.typed +0 -0
- mnutils/testing/__init__.py +3 -0
- mnutils/testing/_spectra.py +338 -0
- mnutils/testing/synthetic.py +373 -0
- mnutils/utils/__init__.py +25 -0
- mnutils/utils/data_loaders.py +218 -0
- mnutils/utils/file_helpers.py +708 -0
- mnutils/utils/images.py +202 -0
- mnutils/utils/nifti.py +379 -0
- mnutils/utils/spectra.py +149 -0
- mnutils-1.2.0.dist-info/METADATA +161 -0
- mnutils-1.2.0.dist-info/RECORD +41 -0
- mnutils-1.2.0.dist-info/WHEEL +4 -0
- mnutils-1.2.0.dist-info/entry_points.txt +7 -0
- mnutils-1.2.0.dist-info/licenses/LICENSE +28 -0
mnutils/utils/spectra.py
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import numpy.typing as npt
|
|
3
|
+
from loguru import logger
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def calculate_hz_axis(
|
|
7
|
+
spectral_width: float | None = None,
|
|
8
|
+
npts: int | None = None,
|
|
9
|
+
header: dict | None = None,
|
|
10
|
+
) -> npt.NDArray[np.float64]:
|
|
11
|
+
"""Calculate the frequency (Hz) axis for a spectrum.
|
|
12
|
+
|
|
13
|
+
Parameters
|
|
14
|
+
----------
|
|
15
|
+
spectral_width : float, optional
|
|
16
|
+
Spectral width in Hz. Read from `header` if not given.
|
|
17
|
+
npts : int, optional
|
|
18
|
+
Number of spectral points. Read from `header` if not given.
|
|
19
|
+
header : dict, optional
|
|
20
|
+
Raw header dict to fall back on for `spectral_width`/`npts`.
|
|
21
|
+
|
|
22
|
+
Returns
|
|
23
|
+
-------
|
|
24
|
+
npt.NDArray[np.float64]
|
|
25
|
+
Frequency axis in Hz, centered on zero.
|
|
26
|
+
"""
|
|
27
|
+
_sw = spectral_width
|
|
28
|
+
_npts = npts
|
|
29
|
+
|
|
30
|
+
if header is not None:
|
|
31
|
+
rdb_hdr = header.get("rdb_hdr", {})
|
|
32
|
+
if isinstance(rdb_hdr, dict):
|
|
33
|
+
if _sw is None:
|
|
34
|
+
_sw = rdb_hdr.get("spectral_width", None)
|
|
35
|
+
if _npts is None:
|
|
36
|
+
_npts = rdb_hdr.get("user1", None)
|
|
37
|
+
|
|
38
|
+
if _sw is None:
|
|
39
|
+
raise ValueError(
|
|
40
|
+
"Spectral width information is required to calculate frequency axis. "
|
|
41
|
+
"Please provide spectral width or ensure it is present in the header."
|
|
42
|
+
)
|
|
43
|
+
if _npts is None:
|
|
44
|
+
raise ValueError(
|
|
45
|
+
"Number of points information is required to calculate frequency axis. "
|
|
46
|
+
"Please provide number of points or ensure it is present in the header."
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
return np.linspace(-_sw / 2, _sw / 2, int(_npts))
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def calculate_ppm_axis(
|
|
53
|
+
spectral_width: float | None = None,
|
|
54
|
+
frequency: float | None = None,
|
|
55
|
+
carrier_ppm: float | None = None,
|
|
56
|
+
nucleus: int | str | None = None,
|
|
57
|
+
npts: int | None = None,
|
|
58
|
+
header: dict | None = None,
|
|
59
|
+
) -> npt.NDArray[np.float64]:
|
|
60
|
+
"""Calculate the chemical shift (ppm) axis for a spectrum.
|
|
61
|
+
|
|
62
|
+
Parameters
|
|
63
|
+
----------
|
|
64
|
+
spectral_width : float, optional
|
|
65
|
+
Spectral width in Hz. Read from `header` if not given.
|
|
66
|
+
frequency : float, optional
|
|
67
|
+
Spectrometer frequency in MHz. Read from `header` if not given.
|
|
68
|
+
carrier_ppm : float, optional
|
|
69
|
+
Carrier frequency offset in ppm. Derived from `nucleus` if not given.
|
|
70
|
+
nucleus : int or str, optional
|
|
71
|
+
Nucleus identifier (e.g. `"1H"` or `1`) used to derive `carrier_ppm`
|
|
72
|
+
when it is not provided directly.
|
|
73
|
+
npts : int, optional
|
|
74
|
+
Number of spectral points. Read from `header` if not given.
|
|
75
|
+
header : dict, optional
|
|
76
|
+
Raw header dict to fall back on for the other parameters.
|
|
77
|
+
|
|
78
|
+
Returns
|
|
79
|
+
-------
|
|
80
|
+
npt.NDArray[np.float64]
|
|
81
|
+
Chemical shift axis in ppm.
|
|
82
|
+
"""
|
|
83
|
+
hz_axis = calculate_hz_axis(
|
|
84
|
+
spectral_width=spectral_width,
|
|
85
|
+
npts=npts,
|
|
86
|
+
header=header,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
_freq = None
|
|
90
|
+
_carrier_ppm = None
|
|
91
|
+
_nuc = None
|
|
92
|
+
|
|
93
|
+
if frequency is not None:
|
|
94
|
+
_freq = frequency
|
|
95
|
+
|
|
96
|
+
if header is not None:
|
|
97
|
+
rdb_hdr = header.get("rdb_hdr", {})
|
|
98
|
+
if isinstance(rdb_hdr, dict):
|
|
99
|
+
if _freq is None:
|
|
100
|
+
_freq = rdb_hdr.get("ps_mps_freq", None)
|
|
101
|
+
if _freq is not None:
|
|
102
|
+
_freq = np.double(_freq / 1e7) # Convert to MHz
|
|
103
|
+
image_hdr = header.get("image", {})
|
|
104
|
+
if isinstance(image_hdr, dict):
|
|
105
|
+
_nuc = image_hdr.get("specnuc", None)
|
|
106
|
+
|
|
107
|
+
if _freq is None:
|
|
108
|
+
raise ValueError(
|
|
109
|
+
"Frequency information is required to calculate ppm axis. "
|
|
110
|
+
"Please provide frequency or ensure it is present in the header."
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
if nucleus is not None:
|
|
114
|
+
# Convert nucleus to integer if provided as string (e.g., '1H' -> 1) by
|
|
115
|
+
# extracting 1 to 3 digits from the string
|
|
116
|
+
if isinstance(nucleus, str):
|
|
117
|
+
import re
|
|
118
|
+
|
|
119
|
+
match = re.search(r"\d{1,3}", nucleus)
|
|
120
|
+
if match:
|
|
121
|
+
_nuc = int(match.group(0))
|
|
122
|
+
else:
|
|
123
|
+
logger.warning(
|
|
124
|
+
f"Could not parse nucleus from string '{nucleus}'. Defaulting to 1H. "
|
|
125
|
+
"This will offset ppm by 4.68!"
|
|
126
|
+
)
|
|
127
|
+
_nuc = 1
|
|
128
|
+
else:
|
|
129
|
+
_nuc = nucleus
|
|
130
|
+
|
|
131
|
+
if _nuc is not None and carrier_ppm is not None:
|
|
132
|
+
logger.warning(
|
|
133
|
+
"Both nucleus and carrier_ppm provided. Carrier ppm will be used for ppm "
|
|
134
|
+
"axis calculation."
|
|
135
|
+
)
|
|
136
|
+
_carrier_ppm = carrier_ppm
|
|
137
|
+
elif carrier_ppm is not None:
|
|
138
|
+
_carrier_ppm = carrier_ppm
|
|
139
|
+
elif _nuc is not None:
|
|
140
|
+
_carrier_ppm = 4.68 if _nuc in [1, 2] else 0.0
|
|
141
|
+
else:
|
|
142
|
+
logger.warning(
|
|
143
|
+
"Neither nucleus nor carrier_ppm provided. Defaulting to 1H with carrier ppm of "
|
|
144
|
+
"4.68. This will offset ppm by 4.68!"
|
|
145
|
+
)
|
|
146
|
+
_carrier_ppm = 4.68
|
|
147
|
+
|
|
148
|
+
ppm = (hz_axis / _freq) + _carrier_ppm
|
|
149
|
+
return ppm.astype(np.float64)
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: MNutils
|
|
3
|
+
Version: 1.2.0
|
|
4
|
+
Summary: Utility functions for multinuclear MR data processing
|
|
5
|
+
Keywords: mri,mrs,xarray,spectroscopy,nmr
|
|
6
|
+
Author: Sebastian Bauer
|
|
7
|
+
Author-email: Sebastian Bauer <28663646+bastigw@users.noreply.github.com>
|
|
8
|
+
License-Expression: BSD-3-Clause
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
|
15
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Framework :: Jupyter
|
|
18
|
+
Requires-Dist: dcm2niiw>=0.1.5
|
|
19
|
+
Requires-Dist: ipython>=8.0
|
|
20
|
+
Requires-Dist: loguru>=0.7.3
|
|
21
|
+
Requires-Dist: mat73
|
|
22
|
+
Requires-Dist: matplotlib>=3.10.7
|
|
23
|
+
Requires-Dist: nibabel>=5.3.2
|
|
24
|
+
Requires-Dist: nmrglue>=0.11
|
|
25
|
+
Requires-Dist: pillow>=12.3.0
|
|
26
|
+
Requires-Dist: scipy>=1.15.3
|
|
27
|
+
Requires-Dist: seaborn>=0.13.2
|
|
28
|
+
Requires-Dist: xmris[fitting]
|
|
29
|
+
Requires-Dist: matlabengine==25.1.* ; extra == '2025a'
|
|
30
|
+
Requires-Dist: hd-bet>=2.0.1 ; extra == 'bet'
|
|
31
|
+
Requires-Dist: torch>=2.10.0 ; extra == 'bet'
|
|
32
|
+
Requires-Python: >=3.12
|
|
33
|
+
Project-URL: Homepage, https://github.com/bastigw/mnutils
|
|
34
|
+
Project-URL: Documentation, https://bastigw.github.io/mnutils/
|
|
35
|
+
Project-URL: Repository, https://github.com/bastigw/mnutils
|
|
36
|
+
Project-URL: Issues, https://github.com/bastigw/mnutils/issues
|
|
37
|
+
Provides-Extra: 2025a
|
|
38
|
+
Provides-Extra: bet
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
|
|
41
|
+
<p align="center">
|
|
42
|
+
<picture>
|
|
43
|
+
<source media="(prefers-color-scheme: dark)"
|
|
44
|
+
srcset="docs/assets/logo/mnutils-banner-dark.svg">
|
|
45
|
+
<img src="docs/assets/logo/mnutils-banner-light.svg" alt="MNUtils" width="420">
|
|
46
|
+
</picture>
|
|
47
|
+
</p>
|
|
48
|
+
|
|
49
|
+
[](https://github.com/bastigw/mnutils/actions/workflows/ci-fast.yml)
|
|
50
|
+
[](https://bastigw.github.io/mnutils/)
|
|
51
|
+
[](LICENSE)
|
|
52
|
+
|
|
53
|
+
MNUtils is a collection of utility functions for working with multi-nuclear MR data from our GE
|
|
54
|
+
scanners.
|
|
55
|
+
|
|
56
|
+
## Features
|
|
57
|
+
|
|
58
|
+
- **Data loading** — read GE raw/reconstructed data via `GEExam`/`GESeries`.
|
|
59
|
+
- **NIfTI/DICOM conversion** — convert scanner output to NIfTI.
|
|
60
|
+
- **Plotting** — spectral and slice plotting utilities.
|
|
61
|
+
- **Spectral fitting** — AMARES fitting delegated to [`xmris`](https://github.com/andrewendlinger/xmris)
|
|
62
|
+
(`xmris[fitting]`, which wraps pyAMARES).
|
|
63
|
+
|
|
64
|
+
See the [documentation](https://bastigw.github.io/mnutils/) for the full basics, data model,
|
|
65
|
+
plotting, fitting, NIfTI, and MATLAB-bridge guides.
|
|
66
|
+
|
|
67
|
+
## Installation
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
uv add git+https://github.com/bastigw/mnutils.git
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Optional extras:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
uv add "mnutils[bet] @ git+https://github.com/bastigw/mnutils.git" # brain extraction (hd-bet, torch)
|
|
77
|
+
uv add "mnutils[2025a] @ git+https://github.com/bastigw/mnutils.git" # MATLAB Engine pinned to MATLAB 2025a
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`2025a` pins `matlabengine==25.1.*`. If your local MATLAB install is a different version, install
|
|
81
|
+
the matching `matlabengine` release yourself instead (see [MATLAB Engine
|
|
82
|
+
Dependency](#matlab-engine-dependency) below) — there's no way to pin one version project-wide
|
|
83
|
+
across contributors' machines.
|
|
84
|
+
|
|
85
|
+
## Usage
|
|
86
|
+
|
|
87
|
+
The main entry point is `ExamBase`: point it at a GE exam's data folder and it classifies every
|
|
88
|
+
series for you — no need to know in advance which folder is an anatomical scan and which is a
|
|
89
|
+
spectrum.
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from mnutils.GEExam import ExamBase
|
|
93
|
+
|
|
94
|
+
exam = ExamBase("data/HeVo-11") # prints an overview of every series it found
|
|
95
|
+
|
|
96
|
+
exam.exam_overview.head() # same overview as a DataFrame
|
|
97
|
+
exam.series_dict[6] # the GESeries subclass ExamBase picked for series 6 — nothing loaded yet
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Load the series you actually need and analyse it — everything about it (spectrum, header fields,
|
|
101
|
+
scan time) lives on the returned object:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
exam.load_series(6)
|
|
105
|
+
mrs = exam[6]
|
|
106
|
+
|
|
107
|
+
print(mrs.protocol_name, mrs.spec.dims, mrs.spec.shape)
|
|
108
|
+
avg = mrs.avg_spec # average over repetitions
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`load_series` also takes a list, and `load_all` loads everything `ExamBase` classified. If you
|
|
112
|
+
already know a series's type, construct it directly (e.g. `MRSSeries(DATA_FOLDER, 6)`) and skip
|
|
113
|
+
the exam-level overview entirely.
|
|
114
|
+
|
|
115
|
+
From there, spectral fitting is handled by [**xmris**](https://github.com/andrewendlinger/xmris)
|
|
116
|
+
— MNUtils deliberately doesn't reimplement fitting, it wraps xmris's AMARES implementation
|
|
117
|
+
(itself built on pyAMARES) so a series's spectrum can go straight into a fit:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
uv add "xmris[fitting]"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
See the [fitting docs](https://bastigw.github.io/mnutils/fitting/) for the full workflow, and the
|
|
124
|
+
[loading data](https://bastigw.github.io/mnutils/basics/loading_data/) and
|
|
125
|
+
[GEExam](https://bastigw.github.io/mnutils/data-model/geexam/) tutorials for more on exams and
|
|
126
|
+
series. Need a raw `.mat` file's path directly instead of a loaded object?
|
|
127
|
+
`mnutils.utils.file_helpers.get_mat_data_from_series(base_folder, series_id)` returns it.
|
|
128
|
+
|
|
129
|
+
## Requirements
|
|
130
|
+
|
|
131
|
+
- Python 3.12+
|
|
132
|
+
|
|
133
|
+
## MATLAB Engine Dependency
|
|
134
|
+
|
|
135
|
+
To use MNUtils, you need to install the MATLAB Engine for Python. The version of the MATLAB Engine
|
|
136
|
+
you require depends on your local MATLAB version. Ensure you install the correct version that
|
|
137
|
+
matches your MATLAB installation.
|
|
138
|
+
|
|
139
|
+
You can find the appropriate MATLAB Engine version for your setup here: [MATLAB Engine for
|
|
140
|
+
Python](https://pypi.org/project/matlabengine/#history).
|
|
141
|
+
|
|
142
|
+
To install the MATLAB Engine in your project, use the following command, replacing `<version>`
|
|
143
|
+
with the correct version for your MATLAB:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
uv add "matlabengine==<version>"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Development
|
|
150
|
+
|
|
151
|
+
See [`CONTRIBUTING.md`](CONTRIBUTING.md) and the [contributor docs](docs/contribute/) for setup,
|
|
152
|
+
tests, docs, and lint workflow.
|
|
153
|
+
|
|
154
|
+
## Contributions and Suggestions
|
|
155
|
+
|
|
156
|
+
I'm very open to suggestions and improvements! If you have ideas or want to share your own
|
|
157
|
+
utilities, feel free to reach out or submit a pull request.
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
BSD-3-Clause — see [`LICENSE`](LICENSE).
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
mnutils/GEExam.py,sha256=-76gvH23SiS_Tlbf8GBqtRCeaYXyvq1MFdUKNim8I8Y,20077
|
|
2
|
+
mnutils/GESeries.py,sha256=EXtTdSQAfK8lvRyLHwH0yFSOmtpAMMLNbAKiwV_6ato,61404
|
|
3
|
+
mnutils/__init__.py,sha256=zw-6KymGUR7pvGeLaFR5idgaGuPgM6B444HvitP1tnw,1302
|
|
4
|
+
mnutils/_scripts.py,sha256=1K1iCkVjuIoEDihLbG3O9NJ9CeYM2Tu_pI2bfvfHcMo,6716
|
|
5
|
+
mnutils/fitting/AMARES.py,sha256=qAPV_hadASrlBVr6Ss9wOfZJGUP0MahrC3WhqZkaPTM,30042
|
|
6
|
+
mnutils/fitting/__init__.py,sha256=o10Q9_phhEpwEtLNv56Muv7YjO2sZSl8vTjiIi2wdY0,114
|
|
7
|
+
mnutils/matlab/__init__.py,sha256=YA4s6D3pdfjgi89qLtB3uQiOCb46iob3hGCRF39K08c,273
|
|
8
|
+
mnutils/matlab/setup_matlab.py,sha256=Pk9UvPfY-QjCPAicKK1glH5qA4oor4QlYOavY_AiWgY,4411
|
|
9
|
+
mnutils/plotting/__init__.py,sha256=SZyoLuhCIWfRotzrNSWdbE5lK6qQ4CnTbZgOWOTJTXU,926
|
|
10
|
+
mnutils/plotting/_widgets/__init__.py,sha256=Dl4holZEoUKVK-8kK2IXZNny_QHCyqD2OzF7Dd0KC5E,217
|
|
11
|
+
mnutils/plotting/_widgets/_html.py,sha256=_xWvz137-Ty4_uhZUJz4H_HlgoU3zOss9NbsIQdHCC8,1522
|
|
12
|
+
mnutils/plotting/_widgets/_shared/__init__.py,sha256=O-_I4G_rJ8B4fF9LPMkheoWmbjiwzWs58iAuptZgf40,1673
|
|
13
|
+
mnutils/plotting/_widgets/_shared/dom.js,sha256=tnjXuLTqj2Susq91XhntWo1SGKQFs2XdS8cw8QCj95k,4259
|
|
14
|
+
mnutils/plotting/_widgets/_shared/theme.css,sha256=e6m2dmMUmvbJ9VQ9K2ZnwJk9Th6daL38O0kuLO4uvYs,3286
|
|
15
|
+
mnutils/plotting/_widgets/image_grid.css,sha256=Qwwrwwjf6k6y97GtEPlUWHEirigtXRBdJZXDo5Pc8Jo,7404
|
|
16
|
+
mnutils/plotting/_widgets/image_grid.js,sha256=aTIwG6isaMO4dGmcWj_mCTK5huDtxVmppgvA3V--yLc,7643
|
|
17
|
+
mnutils/plotting/_widgets/image_grid.py,sha256=3PNy00lreYe4p8iO-yyVBRSNarwKwA2SD77imDDzRqQ,3365
|
|
18
|
+
mnutils/plotting/_widgets/mrsi_inspector.css,sha256=pCxVPeXTRUB-qRLWsrzNLczsuOhWfYw9Fgv5XaB4pU0,12325
|
|
19
|
+
mnutils/plotting/_widgets/mrsi_inspector.js,sha256=phwBT6PtuEXY3qpfQOOrZNRnfwc1CCyzvodMHrs06fA,26595
|
|
20
|
+
mnutils/plotting/_widgets/mrsi_inspector.py,sha256=R0y6ENnicAEXoTwQqIBZwoW6b5aFl4dr9Ck0NvhMU0g,2579
|
|
21
|
+
mnutils/plotting/_widgets/slice_viewer.css,sha256=HwQSjbxVPCfMOtHMdcRRCNIrBJVAG0tUjyfWFPmCbq4,686
|
|
22
|
+
mnutils/plotting/_widgets/slice_viewer.js,sha256=9JAo0NHYFdn8PMIQIshRbbBdHtP_SpkAIsrpIAdMi4I,1072
|
|
23
|
+
mnutils/plotting/_widgets/slice_viewer.py,sha256=L8LB91Fwqlh2zgVJnD2GQCXY2lVFENl2YgarRMjd2ic,1039
|
|
24
|
+
mnutils/plotting/images.py,sha256=6Sxe-Dshk3bBpsgyCDU7UCYlS8YHtriuUPqj7r2wtwY,55585
|
|
25
|
+
mnutils/plotting/saving.py,sha256=wk7yrlCcWcGW4bxwUNyCn7-vEUqlxluHeS6L0yhsUfg,3936
|
|
26
|
+
mnutils/plotting/spectra.py,sha256=WsaQ5zsc5zgBsNucp2dAAT7VVyWTSZZeX3xA4BylAGs,11564
|
|
27
|
+
mnutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
|
+
mnutils/testing/__init__.py,sha256=riccXHSgG6yMJV3hIM0QZHCtwXrRilz_b9WHyW_xAyk,70
|
|
29
|
+
mnutils/testing/_spectra.py,sha256=tWn5ixg0y3iq7J8v1pOBAgHNrzC0xpF6mICz9nu_YQs,15460
|
|
30
|
+
mnutils/testing/synthetic.py,sha256=wktyXHzThPfdxdgcer8R7Dk2oROiojElJumTzExNeMQ,12729
|
|
31
|
+
mnutils/utils/__init__.py,sha256=GZMY9BwBLFdGPQyNdY7XViGP3Kr9ioZGoQCt0nEsrWw,589
|
|
32
|
+
mnutils/utils/data_loaders.py,sha256=F4feHhCgthhmvIJ2TQgaYF9MkY6OhBiTb57t7F-3wQY,7785
|
|
33
|
+
mnutils/utils/file_helpers.py,sha256=tBQRoObr2Yfn7BK96Mcp9Z_rE8dTC-NBZJmUPD_BBQY,23649
|
|
34
|
+
mnutils/utils/images.py,sha256=Kq2Y-_oCIGMNh5ev5msR2kGJTxiYN7HndtuL3J4Yaj4,7278
|
|
35
|
+
mnutils/utils/nifti.py,sha256=G3y_PospnZmfqxLjwtH4lWcBIS2Ikhyc4_9rdxwjNx4,14805
|
|
36
|
+
mnutils/utils/spectra.py,sha256=P7fiBwacifh_6xxYa4FTq22z4VeLQoKnGxKJ-c0qGW0,4990
|
|
37
|
+
mnutils-1.2.0.dist-info/licenses/LICENSE,sha256=74rhSzSkSwSeBsl16Rv-JlTy-XQvWxj5K-v80ouR_Fs,1507
|
|
38
|
+
mnutils-1.2.0.dist-info/WHEEL,sha256=4OL6Foqnnp3xRY5wMkjgc25_i5YJC6dKsC6LPcjqEoU,80
|
|
39
|
+
mnutils-1.2.0.dist-info/entry_points.txt,sha256=Mqz92Hi3-LREpPdJVQqyb_YKlt_Zcu-8N8yTIjMtxtc,264
|
|
40
|
+
mnutils-1.2.0.dist-info/METADATA,sha256=X-9Jue90WLtsrs5Tzft_ihz74SN2pj_ty18vW-fo444,6169
|
|
41
|
+
mnutils-1.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
[console_scripts]
|
|
2
|
+
docs-mnutils = mnutils._scripts:docs_all
|
|
3
|
+
docs-mnutils-api = mnutils._scripts:docs_api
|
|
4
|
+
docs-mnutils-notebooks = mnutils._scripts:docs_notebooks
|
|
5
|
+
test-mnutils = mnutils._scripts:run_tests
|
|
6
|
+
test-mnutils-gen = mnutils._scripts:generate_test_notebooks
|
|
7
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026, Sebastian Bauer
|
|
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.
|