mrsuite 0.0.1__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 (116) hide show
  1. mrsuite-0.0.1/LICENSE +21 -0
  2. mrsuite-0.0.1/PKG-INFO +161 -0
  3. mrsuite-0.0.1/README.md +121 -0
  4. mrsuite-0.0.1/mrsuite/__init__.py +54 -0
  5. mrsuite-0.0.1/mrsuite/basic_driver.py +112 -0
  6. mrsuite-0.0.1/mrsuite/benchmark/__init__.py +24 -0
  7. mrsuite-0.0.1/mrsuite/benchmark/radar.py +247 -0
  8. mrsuite-0.0.1/mrsuite/benchmark/scoring.py +554 -0
  9. mrsuite-0.0.1/mrsuite/bridges/__init__.py +21 -0
  10. mrsuite-0.0.1/mrsuite/bridges/augmentrum.py +165 -0
  11. mrsuite-0.0.1/mrsuite/bridges/base.py +349 -0
  12. mrsuite-0.0.1/mrsuite/bridges/fid_a.py +861 -0
  13. mrsuite-0.0.1/mrsuite/bridges/fsl_mrs.py +604 -0
  14. mrsuite-0.0.1/mrsuite/bridges/lcmodel.py +177 -0
  15. mrsuite-0.0.1/mrsuite/bridges/mrspeclab.py +386 -0
  16. mrsuite-0.0.1/mrsuite/bridges/mrspeclab_driver.py +141 -0
  17. mrsuite-0.0.1/mrsuite/bridges/nifti_mrs.py +99 -0
  18. mrsuite-0.0.1/mrsuite/bridges/osprey.py +558 -0
  19. mrsuite-0.0.1/mrsuite/bridges/pyamares.py +315 -0
  20. mrsuite-0.0.1/mrsuite/bridges/spant.py +383 -0
  21. mrsuite-0.0.1/mrsuite/bridges/suspect.py +331 -0
  22. mrsuite-0.0.1/mrsuite/bridges/tarquin.py +211 -0
  23. mrsuite-0.0.1/mrsuite/bridges/vespa.py +259 -0
  24. mrsuite-0.0.1/mrsuite/collect.py +364 -0
  25. mrsuite-0.0.1/mrsuite/core/__init__.py +0 -0
  26. mrsuite-0.0.1/mrsuite/core/basis.py +230 -0
  27. mrsuite-0.0.1/mrsuite/core/method.py +370 -0
  28. mrsuite-0.0.1/mrsuite/core/parallel.py +158 -0
  29. mrsuite-0.0.1/mrsuite/core/pipeline.py +613 -0
  30. mrsuite-0.0.1/mrsuite/core/provenance.py +226 -0
  31. mrsuite-0.0.1/mrsuite/core/result.py +243 -0
  32. mrsuite-0.0.1/mrsuite/datasets/__init__.py +13 -0
  33. mrsuite-0.0.1/mrsuite/datasets/agnostic.py +126 -0
  34. mrsuite-0.0.1/mrsuite/datasets/challenge2016.py +501 -0
  35. mrsuite-0.0.1/mrsuite/datasets/mr_science_lab.py +149 -0
  36. mrsuite-0.0.1/mrsuite/datasets/mrsi_challenge.py +624 -0
  37. mrsuite-0.0.1/mrsuite/datasets/openneuro.py +195 -0
  38. mrsuite-0.0.1/mrsuite/externals.py +236 -0
  39. mrsuite-0.0.1/mrsuite/gui/__init__.py +13 -0
  40. mrsuite-0.0.1/mrsuite/gui/__main__.py +107 -0
  41. mrsuite-0.0.1/mrsuite/gui/app.py +1872 -0
  42. mrsuite-0.0.1/mrsuite/gui/blocks.py +947 -0
  43. mrsuite-0.0.1/mrsuite/gui/canvas.js +183 -0
  44. mrsuite-0.0.1/mrsuite/gui/canvas.py +134 -0
  45. mrsuite-0.0.1/mrsuite/gui/catalog.py +203 -0
  46. mrsuite-0.0.1/mrsuite/gui/files.py +135 -0
  47. mrsuite-0.0.1/mrsuite/gui/graph.py +1257 -0
  48. mrsuite-0.0.1/mrsuite/gui/static/logo.png +0 -0
  49. mrsuite-0.0.1/mrsuite/gui/static/mrsuite.css +237 -0
  50. mrsuite-0.0.1/mrsuite/gui/vendor/vue-flow-background/LICENSE +20 -0
  51. mrsuite-0.0.1/mrsuite/gui/vendor/vue-flow-background/index.js +126 -0
  52. mrsuite-0.0.1/mrsuite/gui/vendor/vue-flow-core/LICENSE +20 -0
  53. mrsuite-0.0.1/mrsuite/gui/vendor/vue-flow-core/index.js +10186 -0
  54. mrsuite-0.0.1/mrsuite/gui/vendor/vue-flow-core/style.css +248 -0
  55. mrsuite-0.0.1/mrsuite/gui/vendor/vue-flow-core/theme-default.css +143 -0
  56. mrsuite-0.0.1/mrsuite/io.py +426 -0
  57. mrsuite-0.0.1/mrsuite/models/__init__.py +97 -0
  58. mrsuite-0.0.1/mrsuite/models/base.py +515 -0
  59. mrsuite-0.0.1/mrsuite/models/convert.py +109 -0
  60. mrsuite-0.0.1/mrsuite/models/mlp.py +223 -0
  61. mrsuite-0.0.1/mrsuite/models/pytorch.py +89 -0
  62. mrsuite-0.0.1/mrsuite/models/reference.py +116 -0
  63. mrsuite-0.0.1/mrsuite/models/wand.py +263 -0
  64. mrsuite-0.0.1/mrsuite/mrsi.py +167 -0
  65. mrsuite-0.0.1/mrsuite/octave/__init__.py +285 -0
  66. mrsuite-0.0.1/mrsuite/octave/docker.py +194 -0
  67. mrsuite-0.0.1/mrsuite/octave/dockerfile +42 -0
  68. mrsuite-0.0.1/mrsuite/octave/matlab.py +172 -0
  69. mrsuite-0.0.1/mrsuite/octave/sessions.py +91 -0
  70. mrsuite-0.0.1/mrsuite/octave/shims/contains.m +42 -0
  71. mrsuite-0.0.1/mrsuite/octave/shims/fftshift.m +52 -0
  72. mrsuite-0.0.1/mrsuite/octave/shims/hilbert.m +42 -0
  73. mrsuite-0.0.1/mrsuite/octave/shims/lbfgsb.m +200 -0
  74. mrsuite-0.0.1/mrsuite/octave/shims/lsqcurvefit.m +22 -0
  75. mrsuite-0.0.1/mrsuite/octave/shims/lsqnonlin.m +45 -0
  76. mrsuite-0.0.1/mrsuite/octave/shims/mrsuite_lm.m +99 -0
  77. mrsuite-0.0.1/mrsuite/octave/shims/nanmedian.m +16 -0
  78. mrsuite-0.0.1/mrsuite/octave/shims/nlinfit.m +132 -0
  79. mrsuite-0.0.1/mrsuite/octave/shims/optimoptions.m +11 -0
  80. mrsuite-0.0.1/mrsuite/octave/shims/optimset.m +39 -0
  81. mrsuite-0.0.1/mrsuite/octave/shims/padarray.m +47 -0
  82. mrsuite-0.0.1/mrsuite/octave/shims/sscanf.m +59 -0
  83. mrsuite-0.0.1/mrsuite/octave/shims/statset.m +56 -0
  84. mrsuite-0.0.1/mrsuite/octave/src/lbfgsb_quadratic.c +208 -0
  85. mrsuite-0.0.1/mrsuite/r/__init__.py +135 -0
  86. mrsuite-0.0.1/mrsuite/r/dockerfile +22 -0
  87. mrsuite-0.0.1/mrsuite/r/driver.R +135 -0
  88. mrsuite-0.0.1/mrsuite/simulators/__init__.py +13 -0
  89. mrsuite-0.0.1/mrsuite/simulators/bases.py +251 -0
  90. mrsuite-0.0.1/mrsuite/simulators/digital_phantom.py +111 -0
  91. mrsuite-0.0.1/mrsuite/simulators/digital_phantom_driver.py +60 -0
  92. mrsuite-0.0.1/mrsuite/simulators/mrs_sim.py +636 -0
  93. mrsuite-0.0.1/mrsuite/simulators/mrs_sim_driver.py +202 -0
  94. mrsuite-0.0.1/mrsuite/simulators/mrsandbox.py +426 -0
  95. mrsuite-0.0.1/mrsuite/simulators/pulses.py +86 -0
  96. mrsuite-0.0.1/mrsuite/simulators/synthetic.py +143 -0
  97. mrsuite-0.0.1/mrsuite/testing.py +217 -0
  98. mrsuite-0.0.1/mrsuite/training/__init__.py +21 -0
  99. mrsuite-0.0.1/mrsuite/training/loop.py +177 -0
  100. mrsuite-0.0.1/mrsuite/training/recipe.py +198 -0
  101. mrsuite-0.0.1/mrsuite/training/source.py +151 -0
  102. mrsuite-0.0.1/mrsuite.egg-info/PKG-INFO +161 -0
  103. mrsuite-0.0.1/mrsuite.egg-info/SOURCES.txt +114 -0
  104. mrsuite-0.0.1/mrsuite.egg-info/dependency_links.txt +1 -0
  105. mrsuite-0.0.1/mrsuite.egg-info/entry_points.txt +2 -0
  106. mrsuite-0.0.1/mrsuite.egg-info/requires.txt +24 -0
  107. mrsuite-0.0.1/mrsuite.egg-info/top_level.txt +1 -0
  108. mrsuite-0.0.1/pyproject.toml +70 -0
  109. mrsuite-0.0.1/setup.cfg +4 -0
  110. mrsuite-0.0.1/tests/test_benchmark_run.py +476 -0
  111. mrsuite-0.0.1/tests/test_collect.py +273 -0
  112. mrsuite-0.0.1/tests/test_conformance.py +173 -0
  113. mrsuite-0.0.1/tests/test_externals.py +297 -0
  114. mrsuite-0.0.1/tests/test_io.py +699 -0
  115. mrsuite-0.0.1/tests/test_mrsi.py +77 -0
  116. mrsuite-0.0.1/tests/test_optional.py +98 -0
mrsuite-0.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Julian P. Merkofer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
mrsuite-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,161 @@
1
+ Metadata-Version: 2.4
2
+ Name: mrsuite
3
+ Version: 0.0.1
4
+ Summary: MRS Processing, Analysis, AI Model Integration, and Benchmarking
5
+ Author-email: "Julian P. Merkofer" <j.p.merkofer@tue.nl>
6
+ License-Expression: MIT
7
+ Project-URL: Repository, https://github.com/julianmer/MRSuite
8
+ Keywords: MRS,magnetic resonance spectroscopy,NIfTI-MRS,fitting
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
13
+ Requires-Python: >=3.11
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: numpy
17
+ Requires-Dist: pandas
18
+ Requires-Dist: openpyxl
19
+ Requires-Dist: nifti-mrs
20
+ Requires-Dist: nifti-mrs-plus>=0.2.0
21
+ Requires-Dist: spec2nii
22
+ Requires-Dist: oct2py
23
+ Requires-Dist: lcmodel-wrapper>=0.3
24
+ Requires-Dist: tarquin-wrapper>=0.1
25
+ Requires-Dist: h5py
26
+ Requires-Dist: torch
27
+ Requires-Dist: huggingface_hub
28
+ Requires-Dist: safetensors
29
+ Requires-Dist: ssqueezepy>=0.6.6
30
+ Requires-Dist: keras>=3.0
31
+ Requires-Dist: nicegui[native,plotly]<4,>=3.17
32
+ Requires-Dist: suspect
33
+ Requires-Dist: pyAMARES
34
+ Requires-Dist: pypulseq
35
+ Requires-Dist: mrsandbox>=0.1.0
36
+ Requires-Dist: augmentrum>=0.0.3
37
+ Provides-Extra: dev
38
+ Requires-Dist: pytest; extra == "dev"
39
+ Dynamic: license-file
40
+
41
+ <div align="center">
42
+ <img src="https://raw.githubusercontent.com/julianmer/MRSuite/main/assets/logo/logo.png" alt="MRSuite Logo" width="130" style="margin-bottom: -5px;"/>
43
+ <h1 style="margin-top: 5px; margin-bottom: 5px;">MRSuite</h1>
44
+ <p style="margin-top: 0px;"><em>MRS Processing, Analysis, AI Model Integration, and Benchmarking</em></p>
45
+
46
+ [![Python](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/)
47
+ </div>
48
+
49
+ ---
50
+
51
+ The MRSuite project is an open-source, modular framework for magnetic resonance spectroscopy (MRS) that brings together tools for data handling, signal processing, machine learning, and reproducible reporting in a modular and extensible ecosystem.
52
+
53
+ ---
54
+
55
+ ## Overview
56
+
57
+ MRSuite is designed to support the full MRS workflow, from raw data processing to advanced analysis. It is built around the following core principles:
58
+ - **Modularity**: Each processing and analysis step is encapsulated in reusable, interchangeable modules.
59
+ - **Flexibility**: Custom algorithms, models, and external-language tools can be easily integrated.
60
+ - **Scalability**: Capable of handling large datasets and computationally intensive workflows.
61
+ - **Extensibility**: New modules and features can be added by following a consistent interface.
62
+ - **Reproducibility**: Standardized interfaces and reporting tools ensure transparent, consistent documentation.
63
+ - **Benchmarking**: Built-in tools allow for systematic evaluation across datasets and methods.
64
+ - **Community-Driven**: Open-source development encourages contributions and collaboration.
65
+
66
+
67
+ ## Installation
68
+
69
+ MRSuite needs Python 3.11 or newer:
70
+
71
+ ```bash
72
+ pip install mrsuite
73
+ ```
74
+
75
+ The toolboxes MRSuite drives come in as you use them: what pip cannot install (Octave or
76
+ MATLAB, R, FSL-MRS) is named when a step first needs it, and everything else is fetched on
77
+ first use, each under its own licence (FSL-MRS, for one, is for non-commercial use only).
78
+
79
+
80
+ ## Python
81
+
82
+ ```python
83
+ from mrsuite import fsl_mrs, io, lcmodel
84
+ from mrsuite.benchmark import scoring
85
+ from mrsuite.core.pipeline import Pipeline
86
+ from mrsuite.datasets import challenge2016
87
+
88
+ spectra, water, truth = challenge2016.load() # fetched on first use
89
+ basis = io.basis(challenge2016.BASIS)
90
+ fits = {"LCModel": Pipeline([lcmodel.step.fit(basis=basis)]).run(spectra),
91
+ "FSL-MRS": Pipeline([fsl_mrs.step.fit(basis=basis)]).run(spectra)}
92
+ scores = scoring.score(fits, truth, references=["optimal"], metrics={"mosae": scoring.mae})
93
+ ```
94
+
95
+ A step is any toolbox's function: `fid_a.step.op_alignAverages(0.2, 'n')`,
96
+ `spant.step.hsvd_filt()`, `osprey.step.op_eccKlose(water)`. Swap one for another and the
97
+ rest of the chain stands. Scoring runs on
98
+ [MRSValidate](https://github.com/JohnLaMaster/MRSValidate), which is not on PyPI yet:
99
+ `pip install git+https://github.com/JohnLaMaster/MRSValidate.git`.
100
+
101
+
102
+ ## Key Components
103
+
104
+ ### Processing Pipeline
105
+ A modular pipeline for preprocessing MRS data, including:
106
+ - **Data Import**: Load data from various formats.
107
+ - **Processing**: Choose from a collection of processing steps or add your own.
108
+ - **Provenance**: Every step is recorded in the data's own processing history (NIfTI-MRS): the
109
+ toolbox, its exact version and every argument.
110
+
111
+ ### AI Model Zoo
112
+ A collection of (pre-trained) AI models for MRS analysis, including:
113
+ - **Interface**: A standardized interface for integrating AI models into the processing pipeline.
114
+ - **Training**: Train or retrain a model in MRSuite (`model.learn`, one Keras 3 loop, on the CPU,
115
+ CUDA or Apple's MPS), its recipe recorded with it.
116
+ - **Sharing**: Push a model to the Hugging Face Hub and load anyone's by its name.
117
+
118
+ ### Benchmarking Suite
119
+ A suite of tools for benchmarking MRS processing and analysis methods, including:
120
+ - **Accuracy and agreement**: MRSuite's own errors (MAE, MOSAE) and every analysis of
121
+ [MRSValidate](https://github.com/JohnLaMaster/MRSValidate) that compares fits with the truth:
122
+ errors, Lin's CCC, regression, Bland-Altman, normality; per metabolite and pooled.
123
+ - **Comparative Analysis**: Compare different methods and configurations on the same data.
124
+ - **Score tables**: One table per measure, by method, reference and metabolite.
125
+ - **Visualization**: A radar of the methods, a corner per aspect, and MRSValidate's plots.
126
+
127
+ ### Graphical Interface
128
+
129
+ ```bash
130
+ mrsuite-gui
131
+ ```
132
+
133
+ Wire blocks on a canvas. One block per step, each offering every toolbox that does it, and
134
+ every function of every toolbox besides. Each block shows what it made, exports it, and
135
+ reads out its NIfTI-MRS header and history. The graph is written out as the Python that
136
+ makes it again.
137
+
138
+ ![In vivo processing: an OpenNeuro dataset through FSL-MRS, FID-A, spant and Osprey into LCModel](https://raw.githubusercontent.com/julianmer/MRSuite/main/assets/gui/processing.png)
139
+
140
+ *In vivo processing: coils, alignment, outliers, averaging, eddy currents, water, referencing
141
+ and phasing by four toolboxes, then LCModel with the water reference.*
142
+
143
+ ![A benchmark: the 2016 fitting challenge into LCModel, FSL-MRS, spant and WAND, scored on five aspects](https://raw.githubusercontent.com/julianmer/MRSuite/main/assets/gui/benchmark.png)
144
+
145
+ *A benchmark: the 2016 fitting challenge into four fitters, scored on five aspects against
146
+ the truth and drawn on a radar.*
147
+
148
+ ![The same processing as the Python it writes](https://raw.githubusercontent.com/julianmer/MRSuite/main/assets/gui/script.png)
149
+
150
+ *The same processing as the Python it writes.*
151
+
152
+ ### Reporting Standards
153
+ A set of standards for generating reproducible reports, including:
154
+ - **Documentation**: Each step of the processing pipeline is documented automatically, in the
155
+ data's history.
156
+ - **Training recipes**: A trained model carries how its training spectra were made, reported as
157
+ the MRSsynMRS minimum standard for synthetic data.
158
+ - **Contribution Guidelines**:
159
+ [CONTRIBUTING.md](https://github.com/julianmer/MRSuite/blob/main/CONTRIBUTING.md) says how to
160
+ add a method, check it, and share a trained model.
161
+
@@ -0,0 +1,121 @@
1
+ <div align="center">
2
+ <img src="https://raw.githubusercontent.com/julianmer/MRSuite/main/assets/logo/logo.png" alt="MRSuite Logo" width="130" style="margin-bottom: -5px;"/>
3
+ <h1 style="margin-top: 5px; margin-bottom: 5px;">MRSuite</h1>
4
+ <p style="margin-top: 0px;"><em>MRS Processing, Analysis, AI Model Integration, and Benchmarking</em></p>
5
+
6
+ [![Python](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/)
7
+ </div>
8
+
9
+ ---
10
+
11
+ The MRSuite project is an open-source, modular framework for magnetic resonance spectroscopy (MRS) that brings together tools for data handling, signal processing, machine learning, and reproducible reporting in a modular and extensible ecosystem.
12
+
13
+ ---
14
+
15
+ ## Overview
16
+
17
+ MRSuite is designed to support the full MRS workflow, from raw data processing to advanced analysis. It is built around the following core principles:
18
+ - **Modularity**: Each processing and analysis step is encapsulated in reusable, interchangeable modules.
19
+ - **Flexibility**: Custom algorithms, models, and external-language tools can be easily integrated.
20
+ - **Scalability**: Capable of handling large datasets and computationally intensive workflows.
21
+ - **Extensibility**: New modules and features can be added by following a consistent interface.
22
+ - **Reproducibility**: Standardized interfaces and reporting tools ensure transparent, consistent documentation.
23
+ - **Benchmarking**: Built-in tools allow for systematic evaluation across datasets and methods.
24
+ - **Community-Driven**: Open-source development encourages contributions and collaboration.
25
+
26
+
27
+ ## Installation
28
+
29
+ MRSuite needs Python 3.11 or newer:
30
+
31
+ ```bash
32
+ pip install mrsuite
33
+ ```
34
+
35
+ The toolboxes MRSuite drives come in as you use them: what pip cannot install (Octave or
36
+ MATLAB, R, FSL-MRS) is named when a step first needs it, and everything else is fetched on
37
+ first use, each under its own licence (FSL-MRS, for one, is for non-commercial use only).
38
+
39
+
40
+ ## Python
41
+
42
+ ```python
43
+ from mrsuite import fsl_mrs, io, lcmodel
44
+ from mrsuite.benchmark import scoring
45
+ from mrsuite.core.pipeline import Pipeline
46
+ from mrsuite.datasets import challenge2016
47
+
48
+ spectra, water, truth = challenge2016.load() # fetched on first use
49
+ basis = io.basis(challenge2016.BASIS)
50
+ fits = {"LCModel": Pipeline([lcmodel.step.fit(basis=basis)]).run(spectra),
51
+ "FSL-MRS": Pipeline([fsl_mrs.step.fit(basis=basis)]).run(spectra)}
52
+ scores = scoring.score(fits, truth, references=["optimal"], metrics={"mosae": scoring.mae})
53
+ ```
54
+
55
+ A step is any toolbox's function: `fid_a.step.op_alignAverages(0.2, 'n')`,
56
+ `spant.step.hsvd_filt()`, `osprey.step.op_eccKlose(water)`. Swap one for another and the
57
+ rest of the chain stands. Scoring runs on
58
+ [MRSValidate](https://github.com/JohnLaMaster/MRSValidate), which is not on PyPI yet:
59
+ `pip install git+https://github.com/JohnLaMaster/MRSValidate.git`.
60
+
61
+
62
+ ## Key Components
63
+
64
+ ### Processing Pipeline
65
+ A modular pipeline for preprocessing MRS data, including:
66
+ - **Data Import**: Load data from various formats.
67
+ - **Processing**: Choose from a collection of processing steps or add your own.
68
+ - **Provenance**: Every step is recorded in the data's own processing history (NIfTI-MRS): the
69
+ toolbox, its exact version and every argument.
70
+
71
+ ### AI Model Zoo
72
+ A collection of (pre-trained) AI models for MRS analysis, including:
73
+ - **Interface**: A standardized interface for integrating AI models into the processing pipeline.
74
+ - **Training**: Train or retrain a model in MRSuite (`model.learn`, one Keras 3 loop, on the CPU,
75
+ CUDA or Apple's MPS), its recipe recorded with it.
76
+ - **Sharing**: Push a model to the Hugging Face Hub and load anyone's by its name.
77
+
78
+ ### Benchmarking Suite
79
+ A suite of tools for benchmarking MRS processing and analysis methods, including:
80
+ - **Accuracy and agreement**: MRSuite's own errors (MAE, MOSAE) and every analysis of
81
+ [MRSValidate](https://github.com/JohnLaMaster/MRSValidate) that compares fits with the truth:
82
+ errors, Lin's CCC, regression, Bland-Altman, normality; per metabolite and pooled.
83
+ - **Comparative Analysis**: Compare different methods and configurations on the same data.
84
+ - **Score tables**: One table per measure, by method, reference and metabolite.
85
+ - **Visualization**: A radar of the methods, a corner per aspect, and MRSValidate's plots.
86
+
87
+ ### Graphical Interface
88
+
89
+ ```bash
90
+ mrsuite-gui
91
+ ```
92
+
93
+ Wire blocks on a canvas. One block per step, each offering every toolbox that does it, and
94
+ every function of every toolbox besides. Each block shows what it made, exports it, and
95
+ reads out its NIfTI-MRS header and history. The graph is written out as the Python that
96
+ makes it again.
97
+
98
+ ![In vivo processing: an OpenNeuro dataset through FSL-MRS, FID-A, spant and Osprey into LCModel](https://raw.githubusercontent.com/julianmer/MRSuite/main/assets/gui/processing.png)
99
+
100
+ *In vivo processing: coils, alignment, outliers, averaging, eddy currents, water, referencing
101
+ and phasing by four toolboxes, then LCModel with the water reference.*
102
+
103
+ ![A benchmark: the 2016 fitting challenge into LCModel, FSL-MRS, spant and WAND, scored on five aspects](https://raw.githubusercontent.com/julianmer/MRSuite/main/assets/gui/benchmark.png)
104
+
105
+ *A benchmark: the 2016 fitting challenge into four fitters, scored on five aspects against
106
+ the truth and drawn on a radar.*
107
+
108
+ ![The same processing as the Python it writes](https://raw.githubusercontent.com/julianmer/MRSuite/main/assets/gui/script.png)
109
+
110
+ *The same processing as the Python it writes.*
111
+
112
+ ### Reporting Standards
113
+ A set of standards for generating reproducible reports, including:
114
+ - **Documentation**: Each step of the processing pipeline is documented automatically, in the
115
+ data's history.
116
+ - **Training recipes**: A trained model carries how its training spectra were made, reported as
117
+ the MRSsynMRS minimum standard for synthetic data.
118
+ - **Contribution Guidelines**:
119
+ [CONTRIBUTING.md](https://github.com/julianmer/MRSuite/blob/main/CONTRIBUTING.md) says how to
120
+ add a method, check it, and share a trained model.
121
+
@@ -0,0 +1,54 @@
1
+ ####################################################################################################
2
+ # __init__.py #
3
+ ####################################################################################################
4
+ # #
5
+ # Authors: J. P. Merkofer (j.p.merkofer@tue.nl) #
6
+ # #
7
+ # Created: 2026-08-08 #
8
+ # #
9
+ # Purpose: Package entry point. Exposes the toolbox bridges directly (mrsuite.fid_a, #
10
+ # mrsuite.fsl_mrs, mrsuite.osprey, mrsuite.lcmodel) and mrsuite.method, which makes #
11
+ # a function of your own a method, and stamps the shared NIfTI-MRS+ provenance. #
12
+ # Bridges are imported lazily: resolving an Octave-backed one would start a #
13
+ # session, and the FSL-MRS one pulls in the whole FSL-MRS stack, neither of which #
14
+ # a caller who only wants the pipeline should pay for. #
15
+ # #
16
+ ####################################################################################################
17
+
18
+
19
+ #*************#
20
+ # imports #
21
+ #*************#
22
+ import importlib
23
+ from typing import Any
24
+
25
+ import nifti_mrs_plus
26
+
27
+ from mrsuite.core.method import Method, method
28
+
29
+ __version__ = "0.0.1"
30
+
31
+ # Same pattern as Augmentrum: stamp the shared wrapper's provenance metadata so
32
+ # processed data records which toolbox touched it.
33
+ nifti_mrs_plus.set_provenance("MRSuite", __version__)
34
+
35
+ _BRIDGES = {"augmentrum", "fid_a", "fsl_mrs", "lcmodel", "mrspeclab", "nifti_mrs", "osprey",
36
+ "pyamares", "spant", "suspect", "tarquin", "vespa"}
37
+
38
+ __all__ = ["__version__", "Method", "method", *sorted(_BRIDGES)]
39
+
40
+
41
+ #*************#
42
+ # getattr #
43
+ #*************#
44
+ def __getattr__(name: str) -> Any:
45
+ if name in _BRIDGES:
46
+ return importlib.import_module(f"mrsuite.bridges.{name}")
47
+ raise AttributeError(f"module 'mrsuite' has no attribute '{name}'")
48
+
49
+
50
+ #*********#
51
+ # dir #
52
+ #*********#
53
+ def __dir__():
54
+ return sorted(set(globals()) | _BRIDGES)
@@ -0,0 +1,112 @@
1
+ ####################################################################################################
2
+ # basic_driver.py #
3
+ ####################################################################################################
4
+ # #
5
+ # Authors: J. P. Merkofer (j.p.merkofer@tue.nl) #
6
+ # #
7
+ # Created: 2026-10-09 #
8
+ # #
9
+ # Purpose: Reads and writes basis sets with BasiC, for mrsuite.io. Not imported by MRSuite: BasiC #
10
+ # is a folder of scripts importing each other as top-level modules (core, readers, #
11
+ # writers), so it runs in a process of its own. FIDs come and go as .npz; what BasiC #
12
+ # prints goes to stderr; the job's answer goes to stdout, as JSON; a failure ends it #
13
+ # with one line saying why. #
14
+ # #
15
+ # Usage: python basic_driver.py '<job as JSON>' #
16
+ # #
17
+ ####################################################################################################
18
+
19
+
20
+ #*************#
21
+ # imports #
22
+ #*************#
23
+ import contextlib
24
+ import json
25
+ import sys
26
+
27
+ import numpy as np
28
+
29
+
30
+ #**********#
31
+ # fail #
32
+ #**********#
33
+ def fail(message):
34
+ sys.exit(" ".join(str(message).split()))
35
+
36
+
37
+ #**********#
38
+ # read #
39
+ #**********#
40
+ def read(job):
41
+ """The files in the format given or detected, with the parameters given where they state
42
+ none, as one array of FIDs (to ``result``) and what is said of them; the echo time and
43
+ sequence as the basis functions hold them (a reader gives 0 for an echo time not
44
+ stated), else as given."""
45
+ from core.detect import detect_format
46
+ from core.load import fill_missing, load_basis
47
+
48
+ found = detect_format(job["files"])
49
+ fmt = job["format"]
50
+ if fmt == "auto":
51
+ if found["status"] == "ambiguous":
52
+ fail(f"{found['message']} Choose one as format: "
53
+ + ", ".join(map(repr, found["ambiguous_options"])))
54
+ if found["status"] == "failed":
55
+ fail(found["message"])
56
+ fmt = found["format"]
57
+ stated = found["data"]
58
+ given = {k: job[k] for k in ("sw", "sf", "te")}
59
+ basis = load_basis(job["files"], fmt, sw=stated.get("sw") or given["sw"],
60
+ sf=stated.get("sf") or given["sf"])
61
+ if not basis:
62
+ fail("it found no basis functions in the files")
63
+ fill_missing(basis, given)
64
+ lacking = [k for k in ("sw", "sf") if not all(b.get(k) for b in basis)]
65
+ if lacking:
66
+ fail(f"the files do not state {' or '.join(lacking)}: give "
67
+ + ", ".join(f"{k}=" for k in lacking))
68
+ if len({len(np.ravel(b["fid"])) for b in basis}) > 1:
69
+ fail("its basis functions differ in length")
70
+ np.savez(job["result"], fids=np.array([np.ravel(b["fid"]) for b in basis]))
71
+ first = basis[0]
72
+ return {"names": [b["name"] for b in basis], "bandwidth": float(first["sw"]),
73
+ "frequency": float(first["sf"]), "centre": first.get("centerFreq"),
74
+ "te": first.get("te") or given["te"], "seq": first.get("seq"), "format": fmt}
75
+
76
+
77
+ #***********#
78
+ # write #
79
+ #***********#
80
+ def write(job):
81
+ """The job's basis set (FIDs from ``fids``) written for a tool BasiC writes for; the
82
+ files written."""
83
+ from core.formats import ALL_TOOLS
84
+ from core.write import write_basis
85
+
86
+ tools = {t["id"]: [f["id"] for f in t["formats"]] for t in ALL_TOOLS if not t["dimmed"]}
87
+ if job["tool"] not in tools:
88
+ fail(f"no tool {job['tool']!r}; one of: {', '.join(tools)}")
89
+ outputs = tools[job["tool"]]
90
+ if job["output"] != "default" and job["output"] not in outputs:
91
+ fail(f"{job['tool']} writes output 'default'"
92
+ + "".join(f", {o!r}" for o in outputs) + f", not {job['output']!r}")
93
+ fids = np.load(job["fids"])["fids"]
94
+ basis = [{"fid": fid, "name": name, "n": len(fid), "sw": job["bandwidth"],
95
+ "sf": job["frequency"], "centerFreq": job["centre"], "te": job["te"],
96
+ "seq": job["seq"]} for name, fid in zip(job["names"], fids)]
97
+ written = write_basis(basis, job["tool"], job["output"], job["folder"], te=job["te"],
98
+ seq=job["seq"])
99
+ if not written: # its writers go on without what they fail
100
+ fail("it wrote nothing")
101
+ return written
102
+
103
+
104
+ if __name__ == "__main__":
105
+ try:
106
+ with contextlib.redirect_stdout(sys.stderr):
107
+ job = json.loads(sys.argv[1])
108
+ sys.path.insert(0, job["root"])
109
+ answer = {"read": read, "write": write}[job["task"]](job)
110
+ except Exception as err: # noqa: BLE001 - said, in one line
111
+ fail(f"{type(err).__name__}: {err}")
112
+ print(json.dumps(answer))
@@ -0,0 +1,24 @@
1
+ ####################################################################################################
2
+ # __init__.py #
3
+ ####################################################################################################
4
+ # #
5
+ # Authors: J. P. Merkofer (j.p.merkofer@tue.nl) #
6
+ # #
7
+ # Created: 2026-10-01 #
8
+ # #
9
+ # Purpose: Benchmarking on MRSValidate. Fits and ground truth become its ObservationSets on a #
10
+ # reference the caller names (water, tCr, the optimal scale or none), every metric runs #
11
+ # as a step of its analysis plan, and radar draws the resulting scores. #
12
+ # #
13
+ ####################################################################################################
14
+
15
+
16
+ #*************#
17
+ # imports #
18
+ #*************#
19
+ from mrsuite.benchmark.radar import plot_scores, radar
20
+ from mrsuite.benchmark.scoring import (REFERENCES, analyses, bias, coverage, figure, mae,
21
+ observations, optimal_scale, score)
22
+
23
+ __all__ = ["REFERENCES", "observations", "optimal_scale", "score", "analyses", "figure",
24
+ "coverage", "mae", "bias", "radar", "plot_scores"]