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.
Files changed (112) hide show
  1. mrsiprep-0.1.0/LICENSE +57 -0
  2. mrsiprep-0.1.0/PKG-INFO +135 -0
  3. mrsiprep-0.1.0/README.md +99 -0
  4. mrsiprep-0.1.0/mrsiprep/cli/parser.py +294 -0
  5. mrsiprep-0.1.0/mrsiprep/cli/run.py +48 -0
  6. mrsiprep-0.1.0/mrsiprep/config/defaults.py +22 -0
  7. mrsiprep-0.1.0/mrsiprep/config/settings.py +212 -0
  8. mrsiprep-0.1.0/mrsiprep/connectivity/connectivity.py +228 -0
  9. mrsiprep-0.1.0/mrsiprep/connectivity/edges.py +17 -0
  10. mrsiprep-0.1.0/mrsiprep/connectivity/export.py +92 -0
  11. mrsiprep-0.1.0/mrsiprep/connectivity/nodes.py +22 -0
  12. mrsiprep-0.1.0/mrsiprep/data/atlas/README.md +12 -0
  13. mrsiprep-0.1.0/mrsiprep/data/atlas/chimera-LFMIHIFIS-2/chimera-LFMIHIFIS-2.nii.gz +0 -0
  14. mrsiprep-0.1.0/mrsiprep/data/atlas/chimera-LFMIHIFIS-2/chimera-LFMIHIFIS-2.tsv +689 -0
  15. mrsiprep-0.1.0/mrsiprep/data/atlas/chimera-LFMIHIFIS-3/chimera-LFMIHIFIS-3.nii.gz +0 -0
  16. mrsiprep-0.1.0/mrsiprep/data/atlas/chimera-LFMIHIFIS-3/chimera-LFMIHIFIS-3.tsv +277 -0
  17. mrsiprep-0.1.0/mrsiprep/data/atlas/chimera-LFMIHISIFF-3/chimera-LFMIHISIFF-3.nii.gz +0 -0
  18. mrsiprep-0.1.0/mrsiprep/data/atlas/chimera-LFMIHISIFF-3/chimera-LFMIHISIFF-3.tsv +538 -0
  19. mrsiprep-0.1.0/mrsiprep/interfaces/ants.py +362 -0
  20. mrsiprep-0.1.0/mrsiprep/interfaces/bids_import.py +268 -0
  21. mrsiprep-0.1.0/mrsiprep/interfaces/bids_import_gui.py +41 -0
  22. mrsiprep-0.1.0/mrsiprep/interfaces/chimera.py +112 -0
  23. mrsiprep-0.1.0/mrsiprep/interfaces/freesurfer.py +96 -0
  24. mrsiprep-0.1.0/mrsiprep/interfaces/fsl.py +185 -0
  25. mrsiprep-0.1.0/mrsiprep/io/bids.py +308 -0
  26. mrsiprep-0.1.0/mrsiprep/io/derivatives.py +26 -0
  27. mrsiprep-0.1.0/mrsiprep/io/loaders.py +34 -0
  28. mrsiprep-0.1.0/mrsiprep/io/naming.py +163 -0
  29. mrsiprep-0.1.0/mrsiprep/io/validators.py +76 -0
  30. mrsiprep-0.1.0/mrsiprep/mrsi/filtering.py +97 -0
  31. mrsiprep-0.1.0/mrsiprep/mrsi/masks.py +32 -0
  32. mrsiprep-0.1.0/mrsiprep/mrsi/pvc.py +63 -0
  33. mrsiprep-0.1.0/mrsiprep/mrsi/quality.py +63 -0
  34. mrsiprep-0.1.0/mrsiprep/mrsi/reference.py +31 -0
  35. mrsiprep-0.1.0/mrsiprep/mrsi/resampling.py +92 -0
  36. mrsiprep-0.1.0/mrsiprep/parcellation/atlas_registry.py +97 -0
  37. mrsiprep-0.1.0/mrsiprep/parcellation/base.py +18 -0
  38. mrsiprep-0.1.0/mrsiprep/parcellation/chimera_native.py +73 -0
  39. mrsiprep-0.1.0/mrsiprep/parcellation/extraction.py +95 -0
  40. mrsiprep-0.1.0/mrsiprep/parcellation/labels.py +65 -0
  41. mrsiprep-0.1.0/mrsiprep/parcellation/metprofiles.py +97 -0
  42. mrsiprep-0.1.0/mrsiprep/parcellation/mni_atlas.py +32 -0
  43. mrsiprep-0.1.0/mrsiprep/parcellation/parcel_fractions.py +18 -0
  44. mrsiprep-0.1.0/mrsiprep/parcellation/synthseg.py +112 -0
  45. mrsiprep-0.1.0/mrsiprep/parcellation/tissue_regression.py +174 -0
  46. mrsiprep-0.1.0/mrsiprep/registration/mrsi_to_t1.py +87 -0
  47. mrsiprep-0.1.0/mrsiprep/registration/subject_template.py +148 -0
  48. mrsiprep-0.1.0/mrsiprep/registration/t1_to_mni.py +82 -0
  49. mrsiprep-0.1.0/mrsiprep/registration/transforms.py +73 -0
  50. mrsiprep-0.1.0/mrsiprep/reports/connectivity_overview.py +44 -0
  51. mrsiprep-0.1.0/mrsiprep/reports/coverage.py +12 -0
  52. mrsiprep-0.1.0/mrsiprep/reports/figures.py +13 -0
  53. mrsiprep-0.1.0/mrsiprep/reports/html.py +87 -0
  54. mrsiprep-0.1.0/mrsiprep/reports/mrsi_preproc.py +64 -0
  55. mrsiprep-0.1.0/mrsiprep/reports/parcel_figures.py +145 -0
  56. mrsiprep-0.1.0/mrsiprep/reports/parcel_qc.py +111 -0
  57. mrsiprep-0.1.0/mrsiprep/reports/parcellation_overview.py +43 -0
  58. mrsiprep-0.1.0/mrsiprep/reports/qc_combine.py +46 -0
  59. mrsiprep-0.1.0/mrsiprep/reports/registration_overview.py +85 -0
  60. mrsiprep-0.1.0/mrsiprep/reports/slices.py +113 -0
  61. mrsiprep-0.1.0/mrsiprep/reports/spectra_qc.py +11 -0
  62. mrsiprep-0.1.0/mrsiprep/reports/tissue.py +52 -0
  63. mrsiprep-0.1.0/mrsiprep/tissue/correction.py +14 -0
  64. mrsiprep-0.1.0/mrsiprep/tissue/fractions.py +49 -0
  65. mrsiprep-0.1.0/mrsiprep/tissue/fuzzy_cmeans.py +132 -0
  66. mrsiprep-0.1.0/mrsiprep/tissue/psf.py +168 -0
  67. mrsiprep-0.1.0/mrsiprep/tissue/synthseg_fast.py +262 -0
  68. mrsiprep-0.1.0/mrsiprep/utils/banner.py +18 -0
  69. mrsiprep-0.1.0/mrsiprep/utils/debug.py +309 -0
  70. mrsiprep-0.1.0/mrsiprep/utils/images.py +116 -0
  71. mrsiprep-0.1.0/mrsiprep/utils/logging.py +50 -0
  72. mrsiprep-0.1.0/mrsiprep/utils/misc.py +107 -0
  73. mrsiprep-0.1.0/mrsiprep/utils/provenance.py +142 -0
  74. mrsiprep-0.1.0/mrsiprep/utils/subprocess_utils.py +40 -0
  75. mrsiprep-0.1.0/mrsiprep/utils/tables.py +25 -0
  76. mrsiprep-0.1.0/mrsiprep/workflows/anatomical.py +111 -0
  77. mrsiprep-0.1.0/mrsiprep/workflows/base.py +10 -0
  78. mrsiprep-0.1.0/mrsiprep/workflows/connectivity.py +23 -0
  79. mrsiprep-0.1.0/mrsiprep/workflows/mrsi.py +128 -0
  80. mrsiprep-0.1.0/mrsiprep/workflows/nipype_engine/__init__.py +14 -0
  81. mrsiprep-0.1.0/mrsiprep/workflows/nipype_engine/adapters.py +52 -0
  82. mrsiprep-0.1.0/mrsiprep/workflows/nipype_engine/build.py +75 -0
  83. mrsiprep-0.1.0/mrsiprep/workflows/nipype_engine/nodes.py +264 -0
  84. mrsiprep-0.1.0/mrsiprep/workflows/nipype_engine/run.py +264 -0
  85. mrsiprep-0.1.0/mrsiprep/workflows/parcellation.py +38 -0
  86. mrsiprep-0.1.0/mrsiprep/workflows/participant.py +625 -0
  87. mrsiprep-0.1.0/mrsiprep/workflows/registration.py +42 -0
  88. mrsiprep-0.1.0/mrsiprep/workflows/reports.py +9 -0
  89. mrsiprep-0.1.0/mrsiprep/workflows/tissue.py +68 -0
  90. mrsiprep-0.1.0/mrsiprep.egg-info/PKG-INFO +135 -0
  91. mrsiprep-0.1.0/mrsiprep.egg-info/SOURCES.txt +110 -0
  92. mrsiprep-0.1.0/mrsiprep.egg-info/dependency_links.txt +1 -0
  93. mrsiprep-0.1.0/mrsiprep.egg-info/entry_points.txt +4 -0
  94. mrsiprep-0.1.0/mrsiprep.egg-info/requires.txt +26 -0
  95. mrsiprep-0.1.0/mrsiprep.egg-info/top_level.txt +1 -0
  96. mrsiprep-0.1.0/pyproject.toml +63 -0
  97. mrsiprep-0.1.0/setup.cfg +4 -0
  98. mrsiprep-0.1.0/tests/test_bids_inputs.py +139 -0
  99. mrsiprep-0.1.0/tests/test_cli.py +127 -0
  100. mrsiprep-0.1.0/tests/test_connectivity.py +258 -0
  101. mrsiprep-0.1.0/tests/test_derivative_names.py +81 -0
  102. mrsiprep-0.1.0/tests/test_fuzzy_cmeans.py +48 -0
  103. mrsiprep-0.1.0/tests/test_nipype_engine.py +142 -0
  104. mrsiprep-0.1.0/tests/test_processing_modes.py +129 -0
  105. mrsiprep-0.1.0/tests/test_provenance.py +51 -0
  106. mrsiprep-0.1.0/tests/test_psf.py +54 -0
  107. mrsiprep-0.1.0/tests/test_pvc.py +61 -0
  108. mrsiprep-0.1.0/tests/test_qc_reports.py +238 -0
  109. mrsiprep-0.1.0/tests/test_resampling.py +64 -0
  110. mrsiprep-0.1.0/tests/test_synthmrsi_project_e2e.py +113 -0
  111. mrsiprep-0.1.0/tests/test_synthseg_fast.py +134 -0
  112. 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.
@@ -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
+ ![version](https://img.shields.io/badge/version-v0.1.0-blue)
42
+ [![e2e](https://img.shields.io/github/actions/workflow/status/MRSI-Psychosis-UP/MRSIPrep/e2e-synthmrsi-project.yml?label=tested%20on%20SynthMRSI-Project&color=success)](https://github.com/MRSI-Psychosis-UP/MRSIPrep/actions/workflows/e2e-synthmrsi-project.yml)
43
+ [![docs](https://app.readthedocs.org/projects/mrsiprep/badge/?version=stable)](https://mrsiprep.readthedocs.io/en/stable/)
44
+ [![test dataset doi](https://img.shields.io/badge/test%20dataset%20doi-10.5281%2Fzenodo.21477047-blue)](https://doi.org/10.5281/zenodo.21477047)
45
+ [![docker](https://img.shields.io/badge/docker-mrsiup%2Fmrsiprep-blue?logo=docker&logoColor=white)](https://hub.docker.com/r/mrsiup/mrsiprep)
46
+ [![pypi](https://img.shields.io/pypi/v/mrsiprep-docker?logo=pypi&logoColor=white)](https://pypi.org/project/mrsiprep-docker/)
47
+ [![license](https://img.shields.io/badge/license-academic--non--commercial-lightgrey)](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
+ ![MRSIPrep pipeline schematic](docs/figures/pipeline_schematic.png)
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.
@@ -0,0 +1,99 @@
1
+ # *MRSIPrep*: A Robust Preprocessing Pipeline for Whole-Brain MRSI Data
2
+
3
+
4
+
5
+ ![version](https://img.shields.io/badge/version-v0.1.0-blue)
6
+ [![e2e](https://img.shields.io/github/actions/workflow/status/MRSI-Psychosis-UP/MRSIPrep/e2e-synthmrsi-project.yml?label=tested%20on%20SynthMRSI-Project&color=success)](https://github.com/MRSI-Psychosis-UP/MRSIPrep/actions/workflows/e2e-synthmrsi-project.yml)
7
+ [![docs](https://app.readthedocs.org/projects/mrsiprep/badge/?version=stable)](https://mrsiprep.readthedocs.io/en/stable/)
8
+ [![test dataset doi](https://img.shields.io/badge/test%20dataset%20doi-10.5281%2Fzenodo.21477047-blue)](https://doi.org/10.5281/zenodo.21477047)
9
+ [![docker](https://img.shields.io/badge/docker-mrsiup%2Fmrsiprep-blue?logo=docker&logoColor=white)](https://hub.docker.com/r/mrsiup/mrsiprep)
10
+ [![pypi](https://img.shields.io/pypi/v/mrsiprep-docker?logo=pypi&logoColor=white)](https://pypi.org/project/mrsiprep-docker/)
11
+ [![license](https://img.shields.io/badge/license-academic--non--commercial-lightgrey)](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
+ ![MRSIPrep pipeline schematic](docs/figures/pipeline_schematic.png)
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}