mrsiprep 0.1.0__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.
- mrsiprep-0.1.0/LICENSE +57 -0
- mrsiprep-0.1.0/PKG-INFO +135 -0
- mrsiprep-0.1.0/README.md +99 -0
- mrsiprep-0.1.0/mrsiprep/cli/parser.py +294 -0
- mrsiprep-0.1.0/mrsiprep/cli/run.py +48 -0
- mrsiprep-0.1.0/mrsiprep/config/defaults.py +22 -0
- mrsiprep-0.1.0/mrsiprep/config/settings.py +212 -0
- mrsiprep-0.1.0/mrsiprep/connectivity/connectivity.py +228 -0
- mrsiprep-0.1.0/mrsiprep/connectivity/edges.py +17 -0
- mrsiprep-0.1.0/mrsiprep/connectivity/export.py +92 -0
- mrsiprep-0.1.0/mrsiprep/connectivity/nodes.py +22 -0
- mrsiprep-0.1.0/mrsiprep/data/atlas/README.md +12 -0
- mrsiprep-0.1.0/mrsiprep/data/atlas/chimera-LFMIHIFIS-2/chimera-LFMIHIFIS-2.nii.gz +0 -0
- mrsiprep-0.1.0/mrsiprep/data/atlas/chimera-LFMIHIFIS-2/chimera-LFMIHIFIS-2.tsv +689 -0
- mrsiprep-0.1.0/mrsiprep/data/atlas/chimera-LFMIHIFIS-3/chimera-LFMIHIFIS-3.nii.gz +0 -0
- mrsiprep-0.1.0/mrsiprep/data/atlas/chimera-LFMIHIFIS-3/chimera-LFMIHIFIS-3.tsv +277 -0
- mrsiprep-0.1.0/mrsiprep/data/atlas/chimera-LFMIHISIFF-3/chimera-LFMIHISIFF-3.nii.gz +0 -0
- mrsiprep-0.1.0/mrsiprep/data/atlas/chimera-LFMIHISIFF-3/chimera-LFMIHISIFF-3.tsv +538 -0
- mrsiprep-0.1.0/mrsiprep/interfaces/ants.py +362 -0
- mrsiprep-0.1.0/mrsiprep/interfaces/bids_import.py +268 -0
- mrsiprep-0.1.0/mrsiprep/interfaces/bids_import_gui.py +41 -0
- mrsiprep-0.1.0/mrsiprep/interfaces/chimera.py +112 -0
- mrsiprep-0.1.0/mrsiprep/interfaces/freesurfer.py +96 -0
- mrsiprep-0.1.0/mrsiprep/interfaces/fsl.py +185 -0
- mrsiprep-0.1.0/mrsiprep/io/bids.py +308 -0
- mrsiprep-0.1.0/mrsiprep/io/derivatives.py +26 -0
- mrsiprep-0.1.0/mrsiprep/io/loaders.py +34 -0
- mrsiprep-0.1.0/mrsiprep/io/naming.py +163 -0
- mrsiprep-0.1.0/mrsiprep/io/validators.py +76 -0
- mrsiprep-0.1.0/mrsiprep/mrsi/filtering.py +97 -0
- mrsiprep-0.1.0/mrsiprep/mrsi/masks.py +32 -0
- mrsiprep-0.1.0/mrsiprep/mrsi/pvc.py +63 -0
- mrsiprep-0.1.0/mrsiprep/mrsi/quality.py +63 -0
- mrsiprep-0.1.0/mrsiprep/mrsi/reference.py +31 -0
- mrsiprep-0.1.0/mrsiprep/mrsi/resampling.py +92 -0
- mrsiprep-0.1.0/mrsiprep/parcellation/atlas_registry.py +97 -0
- mrsiprep-0.1.0/mrsiprep/parcellation/base.py +18 -0
- mrsiprep-0.1.0/mrsiprep/parcellation/chimera_native.py +73 -0
- mrsiprep-0.1.0/mrsiprep/parcellation/extraction.py +95 -0
- mrsiprep-0.1.0/mrsiprep/parcellation/labels.py +65 -0
- mrsiprep-0.1.0/mrsiprep/parcellation/metprofiles.py +97 -0
- mrsiprep-0.1.0/mrsiprep/parcellation/mni_atlas.py +32 -0
- mrsiprep-0.1.0/mrsiprep/parcellation/parcel_fractions.py +18 -0
- mrsiprep-0.1.0/mrsiprep/parcellation/synthseg.py +112 -0
- mrsiprep-0.1.0/mrsiprep/parcellation/tissue_regression.py +174 -0
- mrsiprep-0.1.0/mrsiprep/registration/mrsi_to_t1.py +87 -0
- mrsiprep-0.1.0/mrsiprep/registration/subject_template.py +148 -0
- mrsiprep-0.1.0/mrsiprep/registration/t1_to_mni.py +82 -0
- mrsiprep-0.1.0/mrsiprep/registration/transforms.py +73 -0
- mrsiprep-0.1.0/mrsiprep/reports/connectivity_overview.py +44 -0
- mrsiprep-0.1.0/mrsiprep/reports/coverage.py +12 -0
- mrsiprep-0.1.0/mrsiprep/reports/figures.py +13 -0
- mrsiprep-0.1.0/mrsiprep/reports/html.py +87 -0
- mrsiprep-0.1.0/mrsiprep/reports/mrsi_preproc.py +64 -0
- mrsiprep-0.1.0/mrsiprep/reports/parcel_figures.py +145 -0
- mrsiprep-0.1.0/mrsiprep/reports/parcel_qc.py +111 -0
- mrsiprep-0.1.0/mrsiprep/reports/parcellation_overview.py +43 -0
- mrsiprep-0.1.0/mrsiprep/reports/qc_combine.py +46 -0
- mrsiprep-0.1.0/mrsiprep/reports/registration_overview.py +85 -0
- mrsiprep-0.1.0/mrsiprep/reports/slices.py +113 -0
- mrsiprep-0.1.0/mrsiprep/reports/spectra_qc.py +11 -0
- mrsiprep-0.1.0/mrsiprep/reports/tissue.py +52 -0
- mrsiprep-0.1.0/mrsiprep/tissue/correction.py +14 -0
- mrsiprep-0.1.0/mrsiprep/tissue/fractions.py +49 -0
- mrsiprep-0.1.0/mrsiprep/tissue/fuzzy_cmeans.py +132 -0
- mrsiprep-0.1.0/mrsiprep/tissue/psf.py +168 -0
- mrsiprep-0.1.0/mrsiprep/tissue/synthseg_fast.py +262 -0
- mrsiprep-0.1.0/mrsiprep/utils/banner.py +18 -0
- mrsiprep-0.1.0/mrsiprep/utils/debug.py +309 -0
- mrsiprep-0.1.0/mrsiprep/utils/images.py +116 -0
- mrsiprep-0.1.0/mrsiprep/utils/logging.py +50 -0
- mrsiprep-0.1.0/mrsiprep/utils/misc.py +107 -0
- mrsiprep-0.1.0/mrsiprep/utils/provenance.py +142 -0
- mrsiprep-0.1.0/mrsiprep/utils/subprocess_utils.py +40 -0
- mrsiprep-0.1.0/mrsiprep/utils/tables.py +25 -0
- mrsiprep-0.1.0/mrsiprep/workflows/anatomical.py +111 -0
- mrsiprep-0.1.0/mrsiprep/workflows/base.py +10 -0
- mrsiprep-0.1.0/mrsiprep/workflows/connectivity.py +23 -0
- mrsiprep-0.1.0/mrsiprep/workflows/mrsi.py +128 -0
- mrsiprep-0.1.0/mrsiprep/workflows/nipype_engine/__init__.py +14 -0
- mrsiprep-0.1.0/mrsiprep/workflows/nipype_engine/adapters.py +52 -0
- mrsiprep-0.1.0/mrsiprep/workflows/nipype_engine/build.py +75 -0
- mrsiprep-0.1.0/mrsiprep/workflows/nipype_engine/nodes.py +264 -0
- mrsiprep-0.1.0/mrsiprep/workflows/nipype_engine/run.py +264 -0
- mrsiprep-0.1.0/mrsiprep/workflows/parcellation.py +38 -0
- mrsiprep-0.1.0/mrsiprep/workflows/participant.py +625 -0
- mrsiprep-0.1.0/mrsiprep/workflows/registration.py +42 -0
- mrsiprep-0.1.0/mrsiprep/workflows/reports.py +9 -0
- mrsiprep-0.1.0/mrsiprep/workflows/tissue.py +68 -0
- mrsiprep-0.1.0/mrsiprep.egg-info/PKG-INFO +135 -0
- mrsiprep-0.1.0/mrsiprep.egg-info/SOURCES.txt +110 -0
- mrsiprep-0.1.0/mrsiprep.egg-info/dependency_links.txt +1 -0
- mrsiprep-0.1.0/mrsiprep.egg-info/entry_points.txt +4 -0
- mrsiprep-0.1.0/mrsiprep.egg-info/requires.txt +26 -0
- mrsiprep-0.1.0/mrsiprep.egg-info/top_level.txt +1 -0
- mrsiprep-0.1.0/pyproject.toml +63 -0
- mrsiprep-0.1.0/setup.cfg +4 -0
- mrsiprep-0.1.0/tests/test_bids_inputs.py +139 -0
- mrsiprep-0.1.0/tests/test_cli.py +127 -0
- mrsiprep-0.1.0/tests/test_connectivity.py +258 -0
- mrsiprep-0.1.0/tests/test_derivative_names.py +81 -0
- mrsiprep-0.1.0/tests/test_fuzzy_cmeans.py +48 -0
- mrsiprep-0.1.0/tests/test_nipype_engine.py +142 -0
- mrsiprep-0.1.0/tests/test_processing_modes.py +129 -0
- mrsiprep-0.1.0/tests/test_provenance.py +51 -0
- mrsiprep-0.1.0/tests/test_psf.py +54 -0
- mrsiprep-0.1.0/tests/test_pvc.py +61 -0
- mrsiprep-0.1.0/tests/test_qc_reports.py +238 -0
- mrsiprep-0.1.0/tests/test_resampling.py +64 -0
- mrsiprep-0.1.0/tests/test_synthmrsi_project_e2e.py +113 -0
- mrsiprep-0.1.0/tests/test_synthseg_fast.py +134 -0
- mrsiprep-0.1.0/tests/test_tissue_regression.py +89 -0
mrsiprep-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
SOFTWARE LICENSE AGREEMENT FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY
|
|
2
|
+
|
|
3
|
+
Between CHUV (hereby described as “LICENSOR”) and LICENSEE
|
|
4
|
+
|
|
5
|
+
Effective at the date the downloading is completed (“EFFECTIVE DATE”).
|
|
6
|
+
|
|
7
|
+
1. LICENSE
|
|
8
|
+
|
|
9
|
+
1.1 Grant
|
|
10
|
+
|
|
11
|
+
Subject to the terms of this Agreement, LICENSOR hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, compile, execute, display and utilize the PROGRAM and (b) create bug fixes and modify the PROGRAM.
|
|
12
|
+
|
|
13
|
+
LICENSEE hereby automatically grants to LICENSOR a non-exclusive, royalty-free, irrevocable license to any LICENSEE bug fixes or modifications to the PROGRAM with rights to sublicense and/or distribute. LICENSEE agrees to provide any such modifications and bug fixes to LICENSOR promptly upon their creation.
|
|
14
|
+
|
|
15
|
+
1.2 No Sublicensing or Additional Rights
|
|
16
|
+
|
|
17
|
+
LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from LICENSOR.
|
|
18
|
+
|
|
19
|
+
LICENSEE shall ensure that all of its users agree to the terms of this Agreement.
|
|
20
|
+
|
|
21
|
+
LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this Agreement.
|
|
22
|
+
|
|
23
|
+
1.3 License Limitations
|
|
24
|
+
|
|
25
|
+
Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of LICENSOR, or of any other entity, except as expressly granted herein.
|
|
26
|
+
|
|
27
|
+
LICENSEE agrees that the PROGRAM, in whole or part, shall be used only for academic purposes excluding any use for any commercial purposes, including without limitation, as the basis of a commercial software or hardware product or to provide services.
|
|
28
|
+
|
|
29
|
+
LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM.
|
|
30
|
+
|
|
31
|
+
2. OWNERSHIP OF INTELLECTUAL PROPERTY
|
|
32
|
+
|
|
33
|
+
LICENSEE acknowledges that title to the PROGRAM shall remain with LICENSOR. The PROGRAM shall be marked with the notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate acknowledgements if any results obtained from use of the PROGRAM are included in any publication.
|
|
34
|
+
|
|
35
|
+
LICENSEE shall not use any trademark or trade name of LICENSOR, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of LICENSOR except as states above for acknowledgements purposes.
|
|
36
|
+
|
|
37
|
+
3. INDEMNIFICATION
|
|
38
|
+
|
|
39
|
+
LICENSEE shall indemnify, defend, and hold harmless LICENSOR, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorney fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement.
|
|
40
|
+
|
|
41
|
+
4. NO REPRESENTATIONS OR WARRANTIES
|
|
42
|
+
|
|
43
|
+
The program is delivered “AS IS”. Licensor makes no representations or warranties of any kind concerning the program, express or implied, including, without limitation, warranties of merchantability, fitness for a particular purpose, non-infringement, or the absence of latent or other defects, whether or not discoverable. Licensor extends no warranties of any kind as to program conformity with whatever user manuals or other literature may be issued from time to time.
|
|
44
|
+
|
|
45
|
+
In no event shall licensor or its respective directors, officers, employees, affiliated investigators and affiliates be liable for incidental or consequential damages of any kind, including, without limitation, economic damages or injury to property and lost profits, regardless of whether licensor shall be advised, shall have other reason to know, or in fact shall know of the possibility of the foregoing.
|
|
46
|
+
|
|
47
|
+
5. ASSIGNMENT
|
|
48
|
+
|
|
49
|
+
This License is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of LICENSOR shall be null and void.
|
|
50
|
+
|
|
51
|
+
6. TERMINATION
|
|
52
|
+
|
|
53
|
+
LICENSEE shall have the right to terminate this license for any reason. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, LICENSOR may terminate this license immediately. Upon termination, LICENSEE shall delete the PROGRAM the original and all copies, except that, upon prior written authorization from LICENSOR, LICENSEE may retain a copy for archive purposes.
|
|
54
|
+
|
|
55
|
+
7. GOVERNING LAW
|
|
56
|
+
|
|
57
|
+
This license is governed by the laws of Switzerland and the jurisdiction of the Canton of Vaud.
|
mrsiprep-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mrsiprep
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: BIDS-like preprocessing pipeline for quantified whole-brain MRSI derivatives
|
|
5
|
+
Author-email: Federico Lucchetti <federico.lucchetti@unil.ch>
|
|
6
|
+
License: CHUV academic non-commercial research license
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Intended Audience :: Science/Research
|
|
9
|
+
Classifier: License :: Other/Proprietary License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: numpy
|
|
15
|
+
Requires-Dist: scipy
|
|
16
|
+
Requires-Dist: pandas
|
|
17
|
+
Requires-Dist: nibabel
|
|
18
|
+
Requires-Dist: nilearn
|
|
19
|
+
Requires-Dist: matplotlib
|
|
20
|
+
Requires-Dist: scikit-image
|
|
21
|
+
Requires-Dist: rich
|
|
22
|
+
Requires-Dist: nipype>=1.8
|
|
23
|
+
Provides-Extra: ants
|
|
24
|
+
Requires-Dist: antspyx; extra == "ants"
|
|
25
|
+
Provides-Extra: gui
|
|
26
|
+
Requires-Dist: PyQt6; extra == "gui"
|
|
27
|
+
Provides-Extra: all
|
|
28
|
+
Requires-Dist: antspyx; extra == "all"
|
|
29
|
+
Requires-Dist: PyQt6; extra == "all"
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
33
|
+
Provides-Extra: test-e2e
|
|
34
|
+
Requires-Dist: requests; extra == "test-e2e"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# *MRSIPrep*: A Robust Preprocessing Pipeline for Whole-Brain MRSI Data
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+

|
|
42
|
+
[](https://github.com/MRSI-Psychosis-UP/MRSIPrep/actions/workflows/e2e-synthmrsi-project.yml)
|
|
43
|
+
[](https://mrsiprep.readthedocs.io/en/stable/)
|
|
44
|
+
[](https://doi.org/10.5281/zenodo.21477047)
|
|
45
|
+
[](https://hub.docker.com/r/mrsiup/mrsiprep)
|
|
46
|
+
[](https://pypi.org/project/mrsiprep-docker/)
|
|
47
|
+
[](LICENSE)
|
|
48
|
+
|
|
49
|
+
## About
|
|
50
|
+
|
|
51
|
+
*MRSIPrep* is a preprocessing and derivative-generation pipeline for already
|
|
52
|
+
quantified whole-brain MRSI maps, run as a BIDS App via Docker. Its default
|
|
53
|
+
`mni-norm` mode normalizes MRSI maps to a specified template for
|
|
54
|
+
[voxel-based analysis](https://github.com/MRSI-Psychosis-UP/VLAD).
|
|
55
|
+
`parc-con` mode adds SynthSeg+FAST tissue maps, PETPVC, and Chimera/MNI-atlas
|
|
56
|
+
regional profile extraction for metabolic connectivity computation. MRSIPrep
|
|
57
|
+
creates a quality-control report for each run.
|
|
58
|
+
|
|
59
|
+
**Full documentation, installation, and usage instructions are on
|
|
60
|
+
[Read the Docs](https://mrsiprep.readthedocs.io/en/stable/).**
|
|
61
|
+
|
|
62
|
+

|
|
63
|
+
|
|
64
|
+
## Design Principles
|
|
65
|
+
|
|
66
|
+
MRSIPrep was designed according to four main principles:
|
|
67
|
+
|
|
68
|
+
- **Reproducibility** — distributed as open-source software, executed in
|
|
69
|
+
containerized environments to minimize differences across computing
|
|
70
|
+
platforms.
|
|
71
|
+
- **Modularity** — each processing stage is an independent module, so users
|
|
72
|
+
can enable, disable, or replace specific steps according to their
|
|
73
|
+
acquisition protocol and scientific question.
|
|
74
|
+
- **Transparency** — automated quality-control reports summarize spatial
|
|
75
|
+
registration, metabolite coverage, voxel-level quality metrics, tissue
|
|
76
|
+
composition, and atlas projection.
|
|
77
|
+
- **Analysis agnosticism** — MRSIPrep does not impose a specific downstream
|
|
78
|
+
analysis; it generates standardized derivatives usable for voxelwise
|
|
79
|
+
analyses, regional analyses, metabolic connectomics, gradient mapping, or
|
|
80
|
+
machine-learning workflows.
|
|
81
|
+
|
|
82
|
+
See [Read the Docs](https://mrsiprep.readthedocs.io/en/stable/) for the full
|
|
83
|
+
workflow architecture and quality-control framework.
|
|
84
|
+
|
|
85
|
+
## Test Dataset
|
|
86
|
+
|
|
87
|
+
A small, public, synthetic MRSI dataset — **SynthMRSI-Project** — is
|
|
88
|
+
available for anyone to download and run through MRSIPrep themselves,
|
|
89
|
+
without needing access to real MRSI acquisitions. It pairs real T1w
|
|
90
|
+
anatomical images (subsetted from two CC0 OpenNeuro datasets) with
|
|
91
|
+
model-synthesized MRSI signal and empirical CRLB/SNR/FWHM quality maps,
|
|
92
|
+
following MRSIPrep's own raw-MRSI-input convention.
|
|
93
|
+
|
|
94
|
+
- Published on Zenodo: [10.5281/zenodo.21477047](https://doi.org/10.5281/zenodo.21477047) (CC0)
|
|
95
|
+
- Full download and usage instructions: [PUBLIC_DATASET.md](PUBLIC_DATASET.md)
|
|
96
|
+
- Used as the fixture for this repo's automated end-to-end pipeline test (see
|
|
97
|
+
the "tested on SynthMRSI-Project" badge above)
|
|
98
|
+
|
|
99
|
+
## Use Cases
|
|
100
|
+
|
|
101
|
+
Code derived from this pipeline has been used in the following peer-reviewed
|
|
102
|
+
publications:
|
|
103
|
+
|
|
104
|
+
- Lucchetti, F., Céléreau, E., Steullet, P., Alemán-Gómez, Y., Hagmann, P.,
|
|
105
|
+
Klauser, A., & Klauser, P. (2025). Constructing the human brain metabolic
|
|
106
|
+
connectome with MR spectroscopic imaging reveals cerebral biochemical
|
|
107
|
+
organization. *Nature Communications*, 16.
|
|
108
|
+
[doi:10.1038/s41467-025-66124-w](https://doi.org/10.1038/s41467-025-66124-w)
|
|
109
|
+
- Céléreau, E., Lucchetti, F., Alemán-Gómez, Y., Dwir, D., Cleusix, M.,
|
|
110
|
+
Ledoux, J.-B., Jenni, R., Conchon, C., Bach Cuadra, M., Schilliger, Z.,
|
|
111
|
+
Solida, A., Armando, M., Plessen, K. J., Hagmann, P., Conus, P., Klauser,
|
|
112
|
+
A., & Klauser, P. (2026). High-resolution whole-brain magnetic resonance
|
|
113
|
+
spectroscopic imaging in youth at risk for psychosis. *Imaging
|
|
114
|
+
Neuroscience*, 4.
|
|
115
|
+
[doi:10.1162/imag.a.1276](https://doi.org/10.1162/imag.a.1276)
|
|
116
|
+
- Céléreau, E., Lucchetti, F., Steullet, P., Schilliger, Z., Alemán-Gómez,
|
|
117
|
+
Y., Jenni, R., Petrova, T., Forrer, S., Delavari, F., Ledoux, J.-B., et al.
|
|
118
|
+
(2026). Sex differences in brain metabolism assessed with whole-brain
|
|
119
|
+
magnetic resonance spectroscopic imaging. *bioRxiv*, 2026-06.
|
|
120
|
+
[doi:10.64898/2026.06.30.735476](https://doi.org/10.64898/2026.06.30.735476)
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
MRSIPrep is distributed under the CHUV academic non-commercial research
|
|
125
|
+
license; see [LICENSE](LICENSE) for the full text.
|
|
126
|
+
|
|
127
|
+
## Attribution
|
|
128
|
+
|
|
129
|
+
Substantial implementation logic is cropped and refactored by Federico Lucchetti and Edgar Céléreau. The original
|
|
130
|
+
license is included in `LICENSE`.
|
|
131
|
+
|
|
132
|
+
## Acknowledgments
|
|
133
|
+
|
|
134
|
+
MRSIPrep builds on the work of the ANTs, FreeSurfer, FSL, PETPVC, Chimera,
|
|
135
|
+
and TemplateFlow projects.
|
mrsiprep-0.1.0/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# *MRSIPrep*: A Robust Preprocessing Pipeline for Whole-Brain MRSI Data
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
[](https://github.com/MRSI-Psychosis-UP/MRSIPrep/actions/workflows/e2e-synthmrsi-project.yml)
|
|
7
|
+
[](https://mrsiprep.readthedocs.io/en/stable/)
|
|
8
|
+
[](https://doi.org/10.5281/zenodo.21477047)
|
|
9
|
+
[](https://hub.docker.com/r/mrsiup/mrsiprep)
|
|
10
|
+
[](https://pypi.org/project/mrsiprep-docker/)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+
|
|
13
|
+
## About
|
|
14
|
+
|
|
15
|
+
*MRSIPrep* is a preprocessing and derivative-generation pipeline for already
|
|
16
|
+
quantified whole-brain MRSI maps, run as a BIDS App via Docker. Its default
|
|
17
|
+
`mni-norm` mode normalizes MRSI maps to a specified template for
|
|
18
|
+
[voxel-based analysis](https://github.com/MRSI-Psychosis-UP/VLAD).
|
|
19
|
+
`parc-con` mode adds SynthSeg+FAST tissue maps, PETPVC, and Chimera/MNI-atlas
|
|
20
|
+
regional profile extraction for metabolic connectivity computation. MRSIPrep
|
|
21
|
+
creates a quality-control report for each run.
|
|
22
|
+
|
|
23
|
+
**Full documentation, installation, and usage instructions are on
|
|
24
|
+
[Read the Docs](https://mrsiprep.readthedocs.io/en/stable/).**
|
|
25
|
+
|
|
26
|
+

|
|
27
|
+
|
|
28
|
+
## Design Principles
|
|
29
|
+
|
|
30
|
+
MRSIPrep was designed according to four main principles:
|
|
31
|
+
|
|
32
|
+
- **Reproducibility** — distributed as open-source software, executed in
|
|
33
|
+
containerized environments to minimize differences across computing
|
|
34
|
+
platforms.
|
|
35
|
+
- **Modularity** — each processing stage is an independent module, so users
|
|
36
|
+
can enable, disable, or replace specific steps according to their
|
|
37
|
+
acquisition protocol and scientific question.
|
|
38
|
+
- **Transparency** — automated quality-control reports summarize spatial
|
|
39
|
+
registration, metabolite coverage, voxel-level quality metrics, tissue
|
|
40
|
+
composition, and atlas projection.
|
|
41
|
+
- **Analysis agnosticism** — MRSIPrep does not impose a specific downstream
|
|
42
|
+
analysis; it generates standardized derivatives usable for voxelwise
|
|
43
|
+
analyses, regional analyses, metabolic connectomics, gradient mapping, or
|
|
44
|
+
machine-learning workflows.
|
|
45
|
+
|
|
46
|
+
See [Read the Docs](https://mrsiprep.readthedocs.io/en/stable/) for the full
|
|
47
|
+
workflow architecture and quality-control framework.
|
|
48
|
+
|
|
49
|
+
## Test Dataset
|
|
50
|
+
|
|
51
|
+
A small, public, synthetic MRSI dataset — **SynthMRSI-Project** — is
|
|
52
|
+
available for anyone to download and run through MRSIPrep themselves,
|
|
53
|
+
without needing access to real MRSI acquisitions. It pairs real T1w
|
|
54
|
+
anatomical images (subsetted from two CC0 OpenNeuro datasets) with
|
|
55
|
+
model-synthesized MRSI signal and empirical CRLB/SNR/FWHM quality maps,
|
|
56
|
+
following MRSIPrep's own raw-MRSI-input convention.
|
|
57
|
+
|
|
58
|
+
- Published on Zenodo: [10.5281/zenodo.21477047](https://doi.org/10.5281/zenodo.21477047) (CC0)
|
|
59
|
+
- Full download and usage instructions: [PUBLIC_DATASET.md](PUBLIC_DATASET.md)
|
|
60
|
+
- Used as the fixture for this repo's automated end-to-end pipeline test (see
|
|
61
|
+
the "tested on SynthMRSI-Project" badge above)
|
|
62
|
+
|
|
63
|
+
## Use Cases
|
|
64
|
+
|
|
65
|
+
Code derived from this pipeline has been used in the following peer-reviewed
|
|
66
|
+
publications:
|
|
67
|
+
|
|
68
|
+
- Lucchetti, F., Céléreau, E., Steullet, P., Alemán-Gómez, Y., Hagmann, P.,
|
|
69
|
+
Klauser, A., & Klauser, P. (2025). Constructing the human brain metabolic
|
|
70
|
+
connectome with MR spectroscopic imaging reveals cerebral biochemical
|
|
71
|
+
organization. *Nature Communications*, 16.
|
|
72
|
+
[doi:10.1038/s41467-025-66124-w](https://doi.org/10.1038/s41467-025-66124-w)
|
|
73
|
+
- Céléreau, E., Lucchetti, F., Alemán-Gómez, Y., Dwir, D., Cleusix, M.,
|
|
74
|
+
Ledoux, J.-B., Jenni, R., Conchon, C., Bach Cuadra, M., Schilliger, Z.,
|
|
75
|
+
Solida, A., Armando, M., Plessen, K. J., Hagmann, P., Conus, P., Klauser,
|
|
76
|
+
A., & Klauser, P. (2026). High-resolution whole-brain magnetic resonance
|
|
77
|
+
spectroscopic imaging in youth at risk for psychosis. *Imaging
|
|
78
|
+
Neuroscience*, 4.
|
|
79
|
+
[doi:10.1162/imag.a.1276](https://doi.org/10.1162/imag.a.1276)
|
|
80
|
+
- Céléreau, E., Lucchetti, F., Steullet, P., Schilliger, Z., Alemán-Gómez,
|
|
81
|
+
Y., Jenni, R., Petrova, T., Forrer, S., Delavari, F., Ledoux, J.-B., et al.
|
|
82
|
+
(2026). Sex differences in brain metabolism assessed with whole-brain
|
|
83
|
+
magnetic resonance spectroscopic imaging. *bioRxiv*, 2026-06.
|
|
84
|
+
[doi:10.64898/2026.06.30.735476](https://doi.org/10.64898/2026.06.30.735476)
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
MRSIPrep is distributed under the CHUV academic non-commercial research
|
|
89
|
+
license; see [LICENSE](LICENSE) for the full text.
|
|
90
|
+
|
|
91
|
+
## Attribution
|
|
92
|
+
|
|
93
|
+
Substantial implementation logic is cropped and refactored by Federico Lucchetti and Edgar Céléreau. The original
|
|
94
|
+
license is included in `LICENSE`.
|
|
95
|
+
|
|
96
|
+
## Acknowledgments
|
|
97
|
+
|
|
98
|
+
MRSIPrep builds on the work of the ANTs, FreeSurfer, FSL, PETPVC, Chimera,
|
|
99
|
+
and TemplateFlow projects.
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
"""CLI parser for MRSIPrep."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from mrsiprep.config.defaults import QUALITY_DEFAULTS
|
|
9
|
+
from mrsiprep.config.settings import MRSIPrepConfig
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
13
|
+
parser = argparse.ArgumentParser(prog="mrsiprep", description="Preprocess quantified whole-brain MRSI derivatives.")
|
|
14
|
+
parser.add_argument("bids_dir", type=Path, help="The root folder of a BIDS valid dataset (sub-XXXXX folders at the top level).")
|
|
15
|
+
parser.add_argument("output_dir", type=Path, help="The output path for MRSIPrep derivatives and reports.")
|
|
16
|
+
parser.add_argument(
|
|
17
|
+
"analysis_level",
|
|
18
|
+
choices=["participant"],
|
|
19
|
+
help="Processing stage to be run, only 'participant' in the case of MRSIPrep (see BIDS-Apps specification).",
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
selection = parser.add_argument_group("Options for filtering BIDS queries")
|
|
23
|
+
selection.add_argument("--participant-label", nargs="+", default=[])
|
|
24
|
+
selection.add_argument("--session-label", nargs="+", default=[])
|
|
25
|
+
selection.add_argument("--participants", type=Path, default=None, help="TSV/CSV subject-session list.")
|
|
26
|
+
selection.add_argument(
|
|
27
|
+
"--bids-filter-file",
|
|
28
|
+
type=Path,
|
|
29
|
+
default=None,
|
|
30
|
+
help="Path to a JSON file of PyBIDS-style entity filters used to select among ambiguous input candidates, "
|
|
31
|
+
"e.g. {\"t1w\": {\"acquisition\": \"memprage\", \"run\": \"01\"}} to force a specific T1w acquisition/run "
|
|
32
|
+
"when a session has more than one. Only the \"t1w\" key is currently supported.",
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
quality = parser.add_argument_group("quality thresholds")
|
|
36
|
+
quality.add_argument(
|
|
37
|
+
"--metabolites",
|
|
38
|
+
type=_parse_comma_list,
|
|
39
|
+
required=True,
|
|
40
|
+
help="Comma-separated metabolite names to process, e.g. 'CrPCr,GluGln,GPCPCh,NAANAAG,Ins'.",
|
|
41
|
+
)
|
|
42
|
+
quality.add_argument("--quality-metrics", nargs="+", default=["snr", "linewidth", "crlb"])
|
|
43
|
+
quality.add_argument("--snr-min", type=float, default=QUALITY_DEFAULTS["snr_min"])
|
|
44
|
+
quality.add_argument("--linewidth-max", type=float, default=QUALITY_DEFAULTS["linewidth_max"])
|
|
45
|
+
quality.add_argument("--crlb-max", type=float, default=QUALITY_DEFAULTS["crlb_max"])
|
|
46
|
+
|
|
47
|
+
processing = parser.add_argument_group("Options for performing only a subset of the workflow")
|
|
48
|
+
processing.add_argument(
|
|
49
|
+
"--mode",
|
|
50
|
+
"--processing-mode",
|
|
51
|
+
dest="processing_mode",
|
|
52
|
+
choices=["mni-norm", "parc-con", "midas"],
|
|
53
|
+
default="mni-norm",
|
|
54
|
+
help="Processing mode. 'midas' runs a MIDAS-faithful pipeline (Maudsley et al. 2006): fuzzy c-means "
|
|
55
|
+
"tissue segmentation, PSF-convolved tissue fractions, rigid MRSI->T1 registration, and per-parcel "
|
|
56
|
+
"Eq. 4 pure-GM/pure-WM regression instead of PETPVC.",
|
|
57
|
+
)
|
|
58
|
+
processing.add_argument(
|
|
59
|
+
"--tissue-backend",
|
|
60
|
+
choices=["synthseg-fast", "existing", "none"],
|
|
61
|
+
default="synthseg-fast",
|
|
62
|
+
help="Tissue segmentation backend for PVC. 'none' disables tissue segmentation and PVC entirely. "
|
|
63
|
+
"Ignored in --mode midas, which always uses its own fuzzy c-means segmentation.",
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
registration = parser.add_argument_group("Specific options for registrations")
|
|
67
|
+
registration.add_argument(
|
|
68
|
+
"--registration-backend",
|
|
69
|
+
choices=["ants", "fsl", "flirt-fnirt", "flirt_fnirt", "flirt/fnirt"],
|
|
70
|
+
default="ants",
|
|
71
|
+
help="Registration toolchain. 'ants' is the default; 'fsl'/'flirt-fnirt' uses FLIRT affine registration "
|
|
72
|
+
"(no deformable stage -- FNIRT is not implemented).",
|
|
73
|
+
)
|
|
74
|
+
registration.add_argument(
|
|
75
|
+
"--ants-mrsi-to-t1-transform",
|
|
76
|
+
default="sr",
|
|
77
|
+
help="ANTs transform preset/code for MRSI-to-T1w registration. Default matches the previous implementation: 'sr'.",
|
|
78
|
+
)
|
|
79
|
+
registration.add_argument(
|
|
80
|
+
"--ants-t1-to-mni-transform",
|
|
81
|
+
default="s",
|
|
82
|
+
help="ANTs transform preset/code for T1w-to-MNI registration. Default matches the previous implementation: 's'.",
|
|
83
|
+
)
|
|
84
|
+
registration.add_argument("--fsl-mrsi-to-t1-dof", type=int, choices=[6, 7, 9, 12], default=6)
|
|
85
|
+
registration.add_argument(
|
|
86
|
+
"--fsl-mrsi-to-t1-init",
|
|
87
|
+
choices=["flirt", "usesqform"],
|
|
88
|
+
default="flirt",
|
|
89
|
+
help="FSL MRSI-to-T1w initialization. 'usesqform' applies the NIfTI qform/sform geometry with FLIRT.",
|
|
90
|
+
)
|
|
91
|
+
registration.add_argument("--fsl-t1-to-mni-dof", type=int, choices=[6, 7, 9, 12], default=12)
|
|
92
|
+
registration.add_argument("--fsl-cost", default="mutualinfo", help="FLIRT cost function for FSL registrations.")
|
|
93
|
+
registration.add_argument("--normalization", choices=["simple", "ants-syn", "existing"], default="simple")
|
|
94
|
+
registration.add_argument("--output-spaces", nargs="+", default=["MNI152NLin2009cAsym"])
|
|
95
|
+
registration.add_argument(
|
|
96
|
+
"--output-mrsi-t1w",
|
|
97
|
+
action="store_true",
|
|
98
|
+
help="Also resample all metabolite (and CRLB/SNR/FWHM/spikemask) maps into T1w space as permanent "
|
|
99
|
+
"derivatives (mrsi-t1w/). Off by default; the registration-overview report generates its own single "
|
|
100
|
+
"reference-metabolite T1w map in the work directory regardless of this flag.",
|
|
101
|
+
)
|
|
102
|
+
registration.add_argument(
|
|
103
|
+
"--mni-resolution",
|
|
104
|
+
default="t1wres",
|
|
105
|
+
help="MNI template resolution: 'origres' (MRSI native), 't1wres' (T1w native), or '<N>mm' (e.g. '2mm').",
|
|
106
|
+
)
|
|
107
|
+
registration.add_argument("--registration-t1-target", choices=["brain-csf", "brain", "raw"], default=None)
|
|
108
|
+
registration.add_argument("--csf-pv-threshold", type=float, default=0.95)
|
|
109
|
+
registration.add_argument(
|
|
110
|
+
"--ref-met",
|
|
111
|
+
required=True,
|
|
112
|
+
help="Reference metabolite map used to build the MRSI registration target, e.g. 'CrPCr'.",
|
|
113
|
+
)
|
|
114
|
+
registration.add_argument("--t1", dest="t1_pattern", default="desc-brain_T1w")
|
|
115
|
+
|
|
116
|
+
parcellation = parser.add_argument_group("parcellation")
|
|
117
|
+
parcellation.add_argument("--parcellation-mode", choices=["synthseg", "chimera", "mni"], default=None)
|
|
118
|
+
parcellation.add_argument("--synthseg-mode", choices=["fast", "standard", "robust"], default="robust")
|
|
119
|
+
parcellation.add_argument("--chimera-scheme", default="LFMIHIFIFF")
|
|
120
|
+
parcellation.add_argument("--chimera-scale", type=_parse_scale, default=3)
|
|
121
|
+
parcellation.add_argument("--chimera-grow", type=int, default=2)
|
|
122
|
+
parcellation.add_argument("--atlas", default="chimera-LFMIHIFIS-3")
|
|
123
|
+
parcellation.add_argument("--custom-atlas", type=Path, default=None)
|
|
124
|
+
parcellation.add_argument("--custom-atlas-lut", type=Path, default=None)
|
|
125
|
+
parcellation.add_argument("--fs-subjects-dir", type=Path, default=None)
|
|
126
|
+
|
|
127
|
+
connectivity = parser.add_argument_group("connectivity")
|
|
128
|
+
connectivity.add_argument("--write-connectivity", action="store_true")
|
|
129
|
+
connectivity.add_argument("--connectivity-method", choices=["pearson", "spearman", "cosine", "euclidean_distance"], default="spearman")
|
|
130
|
+
connectivity.add_argument("--connectivity-space", choices=["MRSI", "T1w", "MNI"], default="MRSI")
|
|
131
|
+
connectivity.add_argument("--connectivity-n-perturbations", type=int, default=50, help="Number of CRLB-scaled noise perturbations per metabolite used to build the connectivity similarity matrix.")
|
|
132
|
+
connectivity.add_argument("--connectivity-sigma-scale", type=float, default=2.0, help="Scale factor applied to the CRLB-derived noise sigma when perturbing metabolite maps for connectivity.")
|
|
133
|
+
connectivity.add_argument(
|
|
134
|
+
"--connectivity-exclude-parcels",
|
|
135
|
+
default=None,
|
|
136
|
+
help="Comma-separated substrings; parcels whose name contains any of them are excluded from the connectivity matrix (e.g. 'wm-lh,cer-').",
|
|
137
|
+
)
|
|
138
|
+
connectivity.add_argument(
|
|
139
|
+
"--connectivity-max-parcel-id",
|
|
140
|
+
type=int,
|
|
141
|
+
default=None,
|
|
142
|
+
help="Exclude parcels whose label/ID is greater than or equal to this value from the connectivity matrix.",
|
|
143
|
+
)
|
|
144
|
+
connectivity.add_argument("--regional-summary", choices=["mean", "median", "weighted_mean"], default="mean")
|
|
145
|
+
|
|
146
|
+
processing_control = parser.add_argument_group("Workflow configuration")
|
|
147
|
+
processing_control.add_argument("--transform", default="", help="Legacy output transform override; prefer --output-spaces.")
|
|
148
|
+
processing_control.add_argument("--no-filter", action="store_true", help="Disable biharmonic spike filtering (enabled by default in every processing mode).")
|
|
149
|
+
processing_control.add_argument(
|
|
150
|
+
"--filter-fwhm-mm",
|
|
151
|
+
type=float,
|
|
152
|
+
default=None,
|
|
153
|
+
help="Smoothing FWHM (mm) used when splicing repaired biharmonic-filter voxels back in. "
|
|
154
|
+
"Default: derived from the native MRSI voxel size (mean voxel dimension x sqrt(2)).",
|
|
155
|
+
)
|
|
156
|
+
processing_control.add_argument("--spikepc", type=float, default=99.0)
|
|
157
|
+
processing_control.add_argument("--no-pvc", action="store_true")
|
|
158
|
+
processing_control.add_argument(
|
|
159
|
+
"--longitudinal",
|
|
160
|
+
action="store_true",
|
|
161
|
+
help="Build one unbiased ANTs template across a subject's sessions and register it to MNI once, "
|
|
162
|
+
"composing (session-to-template)+(template-to-MNI) instead of registering each session directly to MNI. "
|
|
163
|
+
"No-op for subjects with a single session. Requires --registration-backend ants.",
|
|
164
|
+
)
|
|
165
|
+
processing_control.add_argument("--transform-spikemask", action="store_true", help="Also transform per-metabolite spike masks into T1w/MNI space.")
|
|
166
|
+
processing_control.add_argument("--nthreads", type=int, default=16, help="ANTs/ITK thread count per subject/session process.")
|
|
167
|
+
processing_control.add_argument(
|
|
168
|
+
"--nproc",
|
|
169
|
+
type=int,
|
|
170
|
+
default=1,
|
|
171
|
+
help="Number of subject/session recordings to process in parallel. Each parallel process gets --nthreads threads; "
|
|
172
|
+
"if nproc*nthreads exceeds the available CPU count, --nthreads is coerced down and a warning is shown at startup.",
|
|
173
|
+
)
|
|
174
|
+
processing_control.add_argument("--work-dir", "-w", type=Path, default=None)
|
|
175
|
+
|
|
176
|
+
overwrite = parser.add_argument_group("overwrite/recompute")
|
|
177
|
+
overwrite.add_argument("--overwrite", action="store_true")
|
|
178
|
+
overwrite.add_argument("--overwrite-filt", action="store_true")
|
|
179
|
+
overwrite.add_argument("--overwrite-seg", action="store_true", help="Force recompute of tissue segmentation (SynthSeg brain extraction + dseg/probseg), even if cached outputs exist.")
|
|
180
|
+
overwrite.add_argument("--overwrite-pve", action="store_true")
|
|
181
|
+
overwrite.add_argument("--overwrite-t1-reg", action="store_true")
|
|
182
|
+
overwrite.add_argument("--overwrite-mni-reg", action="store_true")
|
|
183
|
+
overwrite.add_argument("--overwrite-transform", action="store_true")
|
|
184
|
+
overwrite.add_argument("--overwrite-chimera", action="store_true", help="Force re-run Chimera parcellation even if the output dseg file already exists.")
|
|
185
|
+
|
|
186
|
+
runtime = parser.add_argument_group("Other options")
|
|
187
|
+
runtime.add_argument("--validate-only", action="store_true", help="Check selected subject/session inputs and exit without running preprocessing.")
|
|
188
|
+
runtime.add_argument(
|
|
189
|
+
"--skip-file-integrity-check",
|
|
190
|
+
action="store_true",
|
|
191
|
+
help="Skip forcing a full read of T1w/MRSI input files during preflight validation (existence-only checks instead). "
|
|
192
|
+
"By default every run force-reads these files first and skips any recording with a missing or corrupt/truncated input.",
|
|
193
|
+
)
|
|
194
|
+
runtime.add_argument("--check-external-libs", action="store_true", help="Verify required external binaries are available and exit.")
|
|
195
|
+
runtime.add_argument(
|
|
196
|
+
"--stop-on-first-crash",
|
|
197
|
+
action="store_true",
|
|
198
|
+
help="Abort the whole run immediately on the first recording failure, instead of logging it and continuing with the rest of the batch.",
|
|
199
|
+
)
|
|
200
|
+
runtime.add_argument(
|
|
201
|
+
"--verbose",
|
|
202
|
+
"-v",
|
|
203
|
+
type=int,
|
|
204
|
+
choices=[0, 1, 2, 3],
|
|
205
|
+
default=1,
|
|
206
|
+
help="0=subject start/finish only, 1=+processing steps, 2=+step details, 3=+raw ANTs/recon-all/mri_synthseg output.",
|
|
207
|
+
)
|
|
208
|
+
return parser
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def parse_args(argv: list[str] | None = None) -> MRSIPrepConfig:
|
|
212
|
+
args = build_parser().parse_args(argv)
|
|
213
|
+
return MRSIPrepConfig(
|
|
214
|
+
bids_dir=args.bids_dir,
|
|
215
|
+
output_dir=args.output_dir,
|
|
216
|
+
analysis_level=args.analysis_level,
|
|
217
|
+
participant_label=args.participant_label,
|
|
218
|
+
session_label=args.session_label,
|
|
219
|
+
participants_file=args.participants,
|
|
220
|
+
bids_filter_file=args.bids_filter_file,
|
|
221
|
+
metabolites=args.metabolites,
|
|
222
|
+
quality_metrics=args.quality_metrics,
|
|
223
|
+
snr_min=args.snr_min,
|
|
224
|
+
linewidth_max=args.linewidth_max,
|
|
225
|
+
crlb_max=args.crlb_max,
|
|
226
|
+
processing_mode=args.processing_mode,
|
|
227
|
+
tissue_backend=args.tissue_backend,
|
|
228
|
+
registration_backend=args.registration_backend,
|
|
229
|
+
ants_mrsi_to_t1_transform=args.ants_mrsi_to_t1_transform,
|
|
230
|
+
ants_t1_to_mni_transform=args.ants_t1_to_mni_transform,
|
|
231
|
+
fsl_mrsi_to_t1_dof=args.fsl_mrsi_to_t1_dof,
|
|
232
|
+
fsl_mrsi_to_t1_init=args.fsl_mrsi_to_t1_init,
|
|
233
|
+
fsl_t1_to_mni_dof=args.fsl_t1_to_mni_dof,
|
|
234
|
+
fsl_cost=args.fsl_cost,
|
|
235
|
+
normalization=args.normalization,
|
|
236
|
+
output_spaces=args.output_spaces,
|
|
237
|
+
output_mrsi_t1w=args.output_mrsi_t1w,
|
|
238
|
+
mni_resolution=args.mni_resolution,
|
|
239
|
+
registration_t1_target=args.registration_t1_target,
|
|
240
|
+
csf_pv_threshold=args.csf_pv_threshold,
|
|
241
|
+
ref_met=args.ref_met,
|
|
242
|
+
t1_pattern=args.t1_pattern,
|
|
243
|
+
parcellation_mode=args.parcellation_mode,
|
|
244
|
+
synthseg_mode=args.synthseg_mode,
|
|
245
|
+
chimera_scheme=args.chimera_scheme,
|
|
246
|
+
chimera_scale=args.chimera_scale,
|
|
247
|
+
chimera_grow=args.chimera_grow,
|
|
248
|
+
atlas=args.atlas,
|
|
249
|
+
custom_atlas=args.custom_atlas,
|
|
250
|
+
custom_atlas_lut=args.custom_atlas_lut,
|
|
251
|
+
fs_subjects_dir=args.fs_subjects_dir,
|
|
252
|
+
write_connectivity=args.write_connectivity,
|
|
253
|
+
connectivity_method=args.connectivity_method,
|
|
254
|
+
connectivity_space=args.connectivity_space,
|
|
255
|
+
connectivity_n_perturbations=args.connectivity_n_perturbations,
|
|
256
|
+
connectivity_sigma_scale=args.connectivity_sigma_scale,
|
|
257
|
+
connectivity_exclude_parcels=args.connectivity_exclude_parcels,
|
|
258
|
+
connectivity_max_parcel_id=args.connectivity_max_parcel_id,
|
|
259
|
+
regional_summary=args.regional_summary,
|
|
260
|
+
transform=args.transform,
|
|
261
|
+
filter_biharmonic=not args.no_filter,
|
|
262
|
+
filter_fwhm_mm=args.filter_fwhm_mm,
|
|
263
|
+
spike_percentile=args.spikepc,
|
|
264
|
+
no_pvc=args.no_pvc,
|
|
265
|
+
longitudinal=args.longitudinal,
|
|
266
|
+
transform_spikemask=args.transform_spikemask,
|
|
267
|
+
nthreads=args.nthreads,
|
|
268
|
+
nproc=args.nproc,
|
|
269
|
+
work_dir=args.work_dir,
|
|
270
|
+
overwrite=args.overwrite,
|
|
271
|
+
overwrite_filt=args.overwrite_filt,
|
|
272
|
+
overwrite_seg=args.overwrite_seg,
|
|
273
|
+
overwrite_pve=args.overwrite_pve,
|
|
274
|
+
overwrite_t1_reg=args.overwrite_t1_reg,
|
|
275
|
+
overwrite_mni_reg=args.overwrite_mni_reg,
|
|
276
|
+
overwrite_transform=args.overwrite_transform,
|
|
277
|
+
overwrite_chimera=args.overwrite_chimera,
|
|
278
|
+
validate_only=args.validate_only,
|
|
279
|
+
skip_file_integrity_check=args.skip_file_integrity_check,
|
|
280
|
+
check_external_libs=args.check_external_libs,
|
|
281
|
+
stop_on_first_crash=args.stop_on_first_crash,
|
|
282
|
+
verbose=args.verbose,
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def _parse_comma_list(value: str) -> list[str]:
|
|
287
|
+
return [item.strip() for item in str(value).split(",") if item.strip()]
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def _parse_scale(value) -> int:
|
|
291
|
+
text = str(value)
|
|
292
|
+
if text.startswith("scale"):
|
|
293
|
+
text = text[len("scale") :]
|
|
294
|
+
return int(text)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""MRSIPrep command entry point."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
from mrsiprep.cli.parser import parse_args
|
|
8
|
+
from mrsiprep.utils.banner import print_banner
|
|
9
|
+
from mrsiprep.utils.debug import Debug
|
|
10
|
+
from mrsiprep.utils.logging import setup_logging
|
|
11
|
+
from mrsiprep.utils.provenance import check_external_software
|
|
12
|
+
from mrsiprep.workflows.participant import run_participant_workflow, validate_participant_inputs
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def main(argv: list[str] | None = None) -> int:
|
|
16
|
+
print_banner()
|
|
17
|
+
config = parse_args(argv)
|
|
18
|
+
logger = setup_logging(config.verbose, log_dir=config.logs_dir)
|
|
19
|
+
nproc, nthreads, cpu_warning = config.resolve_cpu_budget()
|
|
20
|
+
if cpu_warning:
|
|
21
|
+
logger.warning(cpu_warning)
|
|
22
|
+
config.nproc, config.nthreads = nproc, nthreads
|
|
23
|
+
if config.analysis_level != "participant":
|
|
24
|
+
logger.error("Only participant analysis level is currently supported.")
|
|
25
|
+
return 2
|
|
26
|
+
if config.check_external_libs:
|
|
27
|
+
debug = Debug(verbose=config.verbose)
|
|
28
|
+
ok = check_external_software(debug, config)
|
|
29
|
+
return 0 if ok else 1
|
|
30
|
+
if config.validate_only:
|
|
31
|
+
statuses = validate_participant_inputs(config)
|
|
32
|
+
failed = [status for status in statuses if status.status != "success"]
|
|
33
|
+
succeeded = [status for status in statuses if status.status == "success"]
|
|
34
|
+
logger.info("MRSIPrep input validation finished: %d valid, %d invalid", len(succeeded), len(failed))
|
|
35
|
+
for status in failed:
|
|
36
|
+
logger.error("INVALID sub-%s%s: %s", status.subject, f" ses-{status.session}" if status.session else "", status.error)
|
|
37
|
+
return 1 if failed else 0
|
|
38
|
+
statuses = run_participant_workflow(config)
|
|
39
|
+
failed = [status for status in statuses if status.status != "success"]
|
|
40
|
+
succeeded = [status for status in statuses if status.status == "success"]
|
|
41
|
+
logger.info("MRSIPrep finished: %d succeeded, %d failed", len(succeeded), len(failed))
|
|
42
|
+
for status in failed:
|
|
43
|
+
logger.error("FAILED sub-%s%s: %s", status.subject, f" ses-{status.session}" if status.session else "", status.error)
|
|
44
|
+
return 1 if failed and not succeeded else 0
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
if __name__ == "__main__":
|
|
48
|
+
raise SystemExit(main(sys.argv[1:]))
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Default values for MRSIPrep."""
|
|
2
|
+
|
|
3
|
+
METABOLITE_ALIASES = {
|
|
4
|
+
"Glx": ["GluGln", "Glx"],
|
|
5
|
+
"GluGln": ["GluGln", "Glx"],
|
|
6
|
+
"NAA": ["NAA", "NAANAAG"],
|
|
7
|
+
"tNAA": ["NAANAAG", "tNAA", "NAA"],
|
|
8
|
+
"NAANAAG": ["NAANAAG", "tNAA", "NAA"],
|
|
9
|
+
"Cho": ["GPCPCh", "Cho"],
|
|
10
|
+
"GPCPCh": ["GPCPCh", "Cho"],
|
|
11
|
+
"tCr": ["CrPCr", "tCr"],
|
|
12
|
+
"CrPCr": ["CrPCr", "tCr"],
|
|
13
|
+
"Ins": ["Ins"],
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
QUALITY_DEFAULTS = {
|
|
17
|
+
"snr_min": 4.0,
|
|
18
|
+
"linewidth_max": 0.1,
|
|
19
|
+
"crlb_max": 20.0,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
CHIMERA_SCALES = {"scale1": 1, "scale2": 2, "scale3": 3, "scale4": 4, "scale5": 5}
|