unimri 0.0.1a1__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 (83) hide show
  1. unimri-0.0.1a1/.gitignore +66 -0
  2. unimri-0.0.1a1/CHANGELOG.md +76 -0
  3. unimri-0.0.1a1/CITATION.cff +26 -0
  4. unimri-0.0.1a1/LICENSE +21 -0
  5. unimri-0.0.1a1/PKG-INFO +187 -0
  6. unimri-0.0.1a1/README.md +119 -0
  7. unimri-0.0.1a1/docs/acknowledgments.md +109 -0
  8. unimri-0.0.1a1/docs/architecture.md +138 -0
  9. unimri-0.0.1a1/docs/data-model.md +144 -0
  10. unimri-0.0.1a1/docs/index.md +57 -0
  11. unimri-0.0.1a1/docs/io-format-support.md +81 -0
  12. unimri-0.0.1a1/docs/prior-art.md +95 -0
  13. unimri-0.0.1a1/docs/reference/calibration.md +3 -0
  14. unimri-0.0.1a1/docs/reference/data-model.md +25 -0
  15. unimri-0.0.1a1/docs/reference/index.md +18 -0
  16. unimri-0.0.1a1/docs/reference/io.md +13 -0
  17. unimri-0.0.1a1/docs/reference/operators.md +21 -0
  18. unimri-0.0.1a1/docs/reference/optimization.md +3 -0
  19. unimri-0.0.1a1/docs/reference/reconstruction.md +16 -0
  20. unimri-0.0.1a1/docs/reference/testing.md +16 -0
  21. unimri-0.0.1a1/docs/roadmap.md +127 -0
  22. unimri-0.0.1a1/examples/01_data_model.py +67 -0
  23. unimri-0.0.1a1/examples/02_synthetic_datasets.py +29 -0
  24. unimri-0.0.1a1/examples/03_operator_algebra.py +83 -0
  25. unimri-0.0.1a1/examples/04_reference_reconstruction.py +71 -0
  26. unimri-0.0.1a1/examples/05_custom_reader.py +74 -0
  27. unimri-0.0.1a1/examples/06_multinuclear.py +31 -0
  28. unimri-0.0.1a1/examples/07_cg_sense.py +77 -0
  29. unimri-0.0.1a1/examples/99_aspirational_api.py +48 -0
  30. unimri-0.0.1a1/examples/README.md +33 -0
  31. unimri-0.0.1a1/examples/sodium_radial.py +155 -0
  32. unimri-0.0.1a1/pyproject.toml +103 -0
  33. unimri-0.0.1a1/src/unimri/__init__.py +100 -0
  34. unimri-0.0.1a1/src/unimri/_typing.py +30 -0
  35. unimri-0.0.1a1/src/unimri/backend.py +54 -0
  36. unimri-0.0.1a1/src/unimri/calibration/__init__.py +15 -0
  37. unimri-0.0.1a1/src/unimri/calibration/sensitivity.py +48 -0
  38. unimri-0.0.1a1/src/unimri/config.py +30 -0
  39. unimri-0.0.1a1/src/unimri/data/__init__.py +35 -0
  40. unimri-0.0.1a1/src/unimri/data/acquisition.py +70 -0
  41. unimri-0.0.1a1/src/unimri/data/encoding.py +85 -0
  42. unimri-0.0.1a1/src/unimri/data/metadata.py +82 -0
  43. unimri-0.0.1a1/src/unimri/data/mri_data.py +210 -0
  44. unimri-0.0.1a1/src/unimri/data/trajectory.py +71 -0
  45. unimri-0.0.1a1/src/unimri/exceptions.py +31 -0
  46. unimri-0.0.1a1/src/unimri/io/__init__.py +29 -0
  47. unimri-0.0.1a1/src/unimri/io/base.py +41 -0
  48. unimri-0.0.1a1/src/unimri/io/hdf5.py +37 -0
  49. unimri-0.0.1a1/src/unimri/io/ismrmrd.py +55 -0
  50. unimri-0.0.1a1/src/unimri/io/registry.py +77 -0
  51. unimri-0.0.1a1/src/unimri/io/twix.py +39 -0
  52. unimri-0.0.1a1/src/unimri/metrics/__init__.py +11 -0
  53. unimri-0.0.1a1/src/unimri/operators/__init__.py +35 -0
  54. unimri-0.0.1a1/src/unimri/operators/base.py +266 -0
  55. unimri-0.0.1a1/src/unimri/operators/coil.py +49 -0
  56. unimri-0.0.1a1/src/unimri/operators/fourier.py +74 -0
  57. unimri-0.0.1a1/src/unimri/operators/nufft.py +149 -0
  58. unimri-0.0.1a1/src/unimri/operators/sampling.py +17 -0
  59. unimri-0.0.1a1/src/unimri/optimization/__init__.py +16 -0
  60. unimri-0.0.1a1/src/unimri/optimization/cg.py +79 -0
  61. unimri-0.0.1a1/src/unimri/pipeline/__init__.py +7 -0
  62. unimri-0.0.1a1/src/unimri/pipeline/pipeline.py +62 -0
  63. unimri-0.0.1a1/src/unimri/preprocessing/__init__.py +13 -0
  64. unimri-0.0.1a1/src/unimri/py.typed +0 -0
  65. unimri-0.0.1a1/src/unimri/reconstruction/__init__.py +27 -0
  66. unimri-0.0.1a1/src/unimri/reconstruction/methods.py +170 -0
  67. unimri-0.0.1a1/src/unimri/testing/__init__.py +29 -0
  68. unimri-0.0.1a1/src/unimri/testing/datasets.py +143 -0
  69. unimri-0.0.1a1/src/unimri/testing/ndft.py +60 -0
  70. unimri-0.0.1a1/src/unimri/testing/phantoms.py +54 -0
  71. unimri-0.0.1a1/src/unimri/testing/trajectories.py +86 -0
  72. unimri-0.0.1a1/src/unimri/visualization/__init__.py +10 -0
  73. unimri-0.0.1a1/tests/conftest.py +73 -0
  74. unimri-0.0.1a1/tests/test_calibration.py +41 -0
  75. unimri-0.0.1a1/tests/test_data_model.py +124 -0
  76. unimri-0.0.1a1/tests/test_examples.py +31 -0
  77. unimri-0.0.1a1/tests/test_metadata_consistency.py +43 -0
  78. unimri-0.0.1a1/tests/test_operator_base.py +125 -0
  79. unimri-0.0.1a1/tests/test_optimization.py +82 -0
  80. unimri-0.0.1a1/tests/test_package.py +31 -0
  81. unimri-0.0.1a1/tests/test_reconstruction.py +173 -0
  82. unimri-0.0.1a1/tests/test_registry.py +81 -0
  83. unimri-0.0.1a1/tests/test_synthetic.py +102 -0
@@ -0,0 +1,66 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+
7
+ # Distribution / packaging
8
+ .Python
9
+ build/
10
+ dist/
11
+ downloads/
12
+ *.egg-info/
13
+ .installed.cfg
14
+ *.egg
15
+ pip-wheel-metadata/
16
+
17
+ # Virtual environments
18
+ .venv/
19
+ venv/
20
+ env/
21
+ ENV/
22
+
23
+ # Test / coverage
24
+ .pytest_cache/
25
+ .coverage
26
+ .coverage.*
27
+ htmlcov/
28
+ .tox/
29
+ .nox/
30
+ .mypy_cache/
31
+ .ruff_cache/
32
+ .hypothesis/
33
+
34
+ # Docs
35
+ site/
36
+
37
+ # Editors / OS
38
+ .vscode/
39
+ .idea/
40
+ *.swp
41
+ .DS_Store
42
+ Thumbs.db
43
+
44
+ # MRI data (do not commit patient / raw data)
45
+ *.dat
46
+ *.h5
47
+ *.hdf5
48
+ *.mrd
49
+ *.ismrmrd
50
+ *.mat
51
+ *.npy
52
+ *.npz
53
+ *.7
54
+ *.nii
55
+ *.nii.gz
56
+ *.cfl
57
+ *.cfl.hdr
58
+ # Anchored to repo root: unimri's own src/unimri/data/ package must not match.
59
+ /data/
60
+ /scratch/
61
+
62
+ # Output images/arrays written by running the examples from the repo root
63
+ # (tracked images belong in assets/, not the root)
64
+ /*.png
65
+ /*.npy
66
+ /coverage.xml
@@ -0,0 +1,76 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format is based on
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
5
+ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.0.1a1] - 2026-09-14
10
+
11
+ First alpha release.
12
+
13
+ ### Added
14
+ - Initial project scaffold: packaging, CI, documentation skeleton.
15
+ - Design specification (`docs/architecture.md`, `docs/data-model.md`).
16
+ - Public interfaces: `MRIData` and its components, `Reader` + reader registry,
17
+ `LinearOperator` with `IdentityOperator` / `ScaledOperator` /
18
+ `CompositeOperator` and an adjoint dot-test.
19
+ - Contract test suite for the data model, operator algebra, and reader registry.
20
+ - `unimri.testing`: analytic phantoms, trajectory generators (2D/3D radial,
21
+ stack-of-stars, Cartesian), a brute-force reference NDFT, and
22
+ `synthetic_dataset(pattern)` returning one valid `MRIData` per
23
+ `SamplingPattern` with known ground truth.
24
+ - `examples/` — six runnable examples (data model, synthetic datasets, operator
25
+ algebra, reference radial reconstruction, custom reader, multinuclear) plus
26
+ the aspirational end-to-end API; `test_examples.py` runs them in CI.
27
+ - `docs/acknowledgments.md` — credit for every library, standard, and method
28
+ UniMRI uses or is built to use, with licenses.
29
+ - Project logo, architecture diagram, and README status badges.
30
+ - API reference pages (`docs/reference/`, mkdocstrings) in the docs nav.
31
+ - `SECURITY.md`, `RELEASING.md`, `.editorconfig`, `.github/dependabot.yml`,
32
+ `.github/ISSUE_TEMPLATE/config.yml`.
33
+ - Version single-sourced from `src/unimri/__init__.py` via `hatch.version`;
34
+ a test keeps `CITATION.cff` in sync.
35
+ - CI now runs on Linux/Windows/macOS, builds and `twine check`s the wheel, and
36
+ installs it in a clean env; a coverage floor of 80% is enforced.
37
+ - Workflows: `docs.yml` deploys the MkDocs site to GitHub Pages; `release.yml`
38
+ publishes to PyPI via Trusted Publishing on a `v*` tag.
39
+ - `NUFFTOperator` — FINUFFT-backed non-uniform FFT (2-D and 3-D), passes the
40
+ adjoint dot-test and matches the reference NDFT. Optional `nufft` extra.
41
+ - `unimri.reconstruct(data, method="adjoint")` — centered inverse FFT for
42
+ Cartesian data, density-compensated NUFFT gridding for non-Cartesian, with
43
+ RSS / sum / no coil combination.
44
+ - `examples/sodium_radial.py` — end-to-end reconstruction of real 3-D
45
+ density-adapted radial ²³Na data; `04` now uses `unimri.reconstruct`.
46
+ - Trajectory axis convention pinned: `coords` row `d` pairs with image axis `d`
47
+ (`(kz, ky, kx)` for 3-D). `unimri.testing` trajectories and the docs updated.
48
+ - `viz` extra (matplotlib) for the plotting examples.
49
+ - `FourierOperator` (Cartesian, unnormalized/exact-adjoint convention matching
50
+ `NUFFTOperator` and the reference NDFT) and `SensitivityOperator` (coils),
51
+ both composable via `@`; `UncheckedOperator`/`unchecked()` for batched
52
+ (multi-coil) use through operators declared for a single instance.
53
+ - `unimri.calibration.estimate_sensitivity(method="rss")` — RSS-normalized
54
+ coil sensitivity baseline.
55
+ - `unimri.optimization.conjugate_gradient` — CG for `(AᴴA + l2·I)x = Aᴴy`.
56
+ - `unimri.reconstruct(data, method="cg")` — CG-SENSE, trajectory-agnostic;
57
+ beats `"adjoint"` on undersampled/noisy radial data.
58
+ - `examples/07_cg_sense.py`; `99_aspirational_api.py` trimmed to just the
59
+ still-missing reader half.
60
+ - Fixed: `FourierOperator` previously used a unitary ("ortho") FFT convention
61
+ inconsistent with `NUFFTOperator`/`ndft`'s unnormalized convention -- caught
62
+ while wiring `reconstruct(method="cg")` to swap between them transparently.
63
+ - Fixed: an unanchored `data/` pattern in `.gitignore` matched `src/unimri/data/`
64
+ (the `MRIData` data model) as well as the intended top-level scratch
65
+ directory, so it had never actually been committed -- every CI job and a
66
+ real wheel install failed on import. Anchored the pattern to the repo root.
67
+
68
+ ### Not yet implemented
69
+ - All vendor readers (`ismrmrd`, `twix`, `hdf5`) — interfaces only.
70
+ - All operators beyond the algebraic base (`fourier`, `nufft`, `sampling`,
71
+ `coil`) — docstring stubs only.
72
+ - All reconstruction, calibration, preprocessing, optimization, pipeline stages.
73
+
74
+ ## [0.0.0]
75
+
76
+ - Reserved for the first tagged scaffold commit.
@@ -0,0 +1,26 @@
1
+ cff-version: 1.2.0
2
+ title: "UniMRI: A Unified Python Framework for MRI Raw Data Processing and Reconstruction"
3
+ message: "If you use this software, please cite it using these metadata."
4
+ type: software
5
+ authors:
6
+ - given-names: Istiyak Amin
7
+ family-names: Santo
8
+ alias: istiyakamin
9
+ repository-code: "https://github.com/istiyakamin/UniMRI"
10
+ url: "https://github.com/istiyakamin/UniMRI"
11
+ abstract: >-
12
+ UniMRI is an open-source Python framework that provides a common data model and
13
+ computational abstraction layer for MRI raw data acquired from different
14
+ scanners, vendors, and acquisition strategies (Cartesian and non-Cartesian),
15
+ enabling reconstruction algorithms to operate independently of the original
16
+ vendor format.
17
+ keywords:
18
+ - MRI
19
+ - image reconstruction
20
+ - k-space
21
+ - ISMRMRD
22
+ - non-Cartesian
23
+ - NUFFT
24
+ license: MIT
25
+ version: 0.0.1a1
26
+ date-released: "2026-09-14"
unimri-0.0.1a1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Istiyak Amin Santo
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.
@@ -0,0 +1,187 @@
1
+ Metadata-Version: 2.5
2
+ Name: unimri
3
+ Version: 0.0.1a1
4
+ Summary: A unified Python framework for MRI raw-data processing and reconstruction
5
+ Project-URL: Homepage, https://github.com/istiyakamin/UniMRI
6
+ Project-URL: Repository, https://github.com/istiyakamin/UniMRI
7
+ Project-URL: Documentation, https://istiyakamin.github.io/UniMRI/
8
+ Project-URL: Changelog, https://github.com/istiyakamin/UniMRI/blob/main/CHANGELOG.md
9
+ Project-URL: Issues, https://github.com/istiyakamin/UniMRI/issues
10
+ Author: Istiyak Amin Santo
11
+ License: MIT License
12
+
13
+ Copyright (c) 2026 Istiyak Amin Santo
14
+
15
+ Permission is hereby granted, free of charge, to any person obtaining a copy
16
+ of this software and associated documentation files (the "Software"), to deal
17
+ in the Software without restriction, including without limitation the rights
18
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19
+ copies of the Software, and to permit persons to whom the Software is
20
+ furnished to do so, subject to the following conditions:
21
+
22
+ The above copyright notice and this permission notice shall be included in all
23
+ copies or substantial portions of the Software.
24
+
25
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
+ SOFTWARE.
32
+ License-File: LICENSE
33
+ Keywords: ismrmrd,k-space,mri,non-cartesian,nufft,reconstruction,twix
34
+ Classifier: Development Status :: 2 - Pre-Alpha
35
+ Classifier: Intended Audience :: Science/Research
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Programming Language :: Python :: 3 :: Only
38
+ Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
39
+ Classifier: Topic :: Scientific/Engineering :: Physics
40
+ Classifier: Typing :: Typed
41
+ Requires-Python: >=3.10
42
+ Requires-Dist: h5py>=3.8
43
+ Requires-Dist: numpy>=1.24
44
+ Requires-Dist: scipy>=1.10
45
+ Provides-Extra: dev
46
+ Requires-Dist: build>=1.2; extra == 'dev'
47
+ Requires-Dist: finufft>=2.2; extra == 'dev'
48
+ Requires-Dist: matplotlib>=3.7; extra == 'dev'
49
+ Requires-Dist: mypy>=1.11; extra == 'dev'
50
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
51
+ Requires-Dist: pytest>=8.0; extra == 'dev'
52
+ Requires-Dist: ruff>=0.6; extra == 'dev'
53
+ Requires-Dist: tomli>=2.0; (python_version < '3.11') and extra == 'dev'
54
+ Provides-Extra: docs
55
+ Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
56
+ Requires-Dist: mkdocstrings[python]>=0.26; extra == 'docs'
57
+ Provides-Extra: gpu
58
+ Requires-Dist: cupy-cuda12x>=13.0; extra == 'gpu'
59
+ Provides-Extra: ismrmrd
60
+ Requires-Dist: ismrmrd>=1.14; extra == 'ismrmrd'
61
+ Provides-Extra: nufft
62
+ Requires-Dist: finufft>=2.2; extra == 'nufft'
63
+ Provides-Extra: torch
64
+ Requires-Dist: torch>=2.1; extra == 'torch'
65
+ Provides-Extra: viz
66
+ Requires-Dist: matplotlib>=3.7; extra == 'viz'
67
+ Description-Content-Type: text/markdown
68
+
69
+ <p align="center">
70
+ <img src="assets/logo.png" alt="UniMRI — one interface for MRI raw data" width="380">
71
+ </p>
72
+
73
+ <h1 align="center">UniMRI</h1>
74
+
75
+ <p align="center"><strong>One interface for MRI raw data.</strong></p>
76
+
77
+ <p align="center">
78
+ <a href="https://github.com/istiyakamin/UniMRI/actions/workflows/ci.yml"><img src="https://github.com/istiyakamin/UniMRI/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
79
+ <img src="https://img.shields.io/badge/status-pre--alpha-orange.svg" alt="Status: pre-alpha">
80
+ <img src="https://img.shields.io/badge/python-3.10%2B-blue.svg" alt="Python 3.10+">
81
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a>
82
+ <a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff"></a>
83
+ <img src="https://img.shields.io/badge/types-typed-brightgreen.svg" alt="Typed">
84
+ <a href="https://istiyakamin.github.io/UniMRI/"><img src="https://img.shields.io/badge/docs-mkdocs-blue.svg" alt="Docs"></a>
85
+ </p>
86
+
87
+ <!-- Enable once the package is actually on PyPI (after the first `v0.0.1a1` tag publishes):
88
+ <a href="https://pypi.org/project/unimri/"><img src="https://img.shields.io/pypi/v/unimri.svg" alt="PyPI"></a>
89
+ <a href="https://pypi.org/project/unimri/"><img src="https://img.shields.io/pypi/dm/unimri.svg?label=PyPI%20downloads" alt="PyPI downloads"></a>
90
+ <a href="https://doi.org/PLACEHOLDER"><img src="https://img.shields.io/badge/DOI-PLACEHOLDER-blue.svg" alt="DOI"></a>
91
+ <a href="https://securityscorecards.dev/viewer/?uri=github.com/istiyakamin/UniMRI"><img src="https://api.securityscorecards.dev/projects/github.com/istiyakamin/UniMRI/badge" alt="OpenSSF Scorecard"></a>
92
+ -->
93
+
94
+ UniMRI is an open-source Python framework that provides a common computational
95
+ interface for MRI raw data across scanners, vendors, and acquisition strategies —
96
+ Cartesian, radial, spiral, and other non-Cartesian trajectories — so that
97
+ reconstruction algorithms can be written once and run on data from anywhere.
98
+
99
+ > **Status: pre-alpha (v0.0.1a1).** The data model (`MRIData`), the operator
100
+ > algebra, `FourierOperator`/`NUFFTOperator`/`SensitivityOperator`, and
101
+ > `reconstruct(method="adjoint"|"cg")` — single-pass gridding and CG-SENSE, the
102
+ > same code for Cartesian and non-Cartesian data — all work, validated on real
103
+ > 3-D radial ²³Na data. The vendor readers (`unimri.read`) are still stubs. See
104
+ > the [roadmap](docs/roadmap.md).
105
+
106
+ > **Name caveat:** `UniMRI` / `unimri` is a provisional working name. A full
107
+ > PyPI / GitHub / trademark clearance is still pending before any public release
108
+ > or PyPI upload.
109
+
110
+ ## The idea
111
+
112
+ The core problem is fragmentation: every vendor format has its own loader, and
113
+ every reconstruction toolbox has its own data model. UniMRI normalizes vendor
114
+ raw data into one representation, then reconstructs from that.
115
+
116
+ <p align="center">
117
+ <img src="assets/idea.png" alt="UniMRI pipeline: raw data from any vendor (Siemens TWIX, GE P-file, Philips RAW, ISMRMRD, HDF5) flows through the I/O layer (format detection + reader registry), into the unified MRIData model (k-space, trajectory, encoding, coils, metadata, provenance), through the operator layer (reconstruction as an inverse problem, y = P F S x), through reconstruction (FFT, SENSE, GRAPPA, CG-SENSE, compressed sensing), to an MRI image — vendor- and trajectory-independent." width="560">
118
+ </p>
119
+
120
+ ## Aspirational API
121
+
122
+ ```python
123
+ import unimri
124
+
125
+ raw = unimri.read("measurement.dat") # vendor-agnostic -- NOT YET (docs/roadmap.md, M2)
126
+ image = unimri.reconstruct(raw, method="cg") # trajectory-agnostic -- WORKS TODAY
127
+ ```
128
+
129
+ ```python
130
+ # advanced: reconstruction as an inverse problem -- WORKS TODAY (see examples/07_cg_sense.py)
131
+ from unimri.calibration import estimate_sensitivity
132
+ from unimri.operators import FourierOperator, NUFFTOperator, SensitivityOperator, unchecked
133
+ from unimri.optimization import conjugate_gradient
134
+
135
+ maps = estimate_sensitivity(raw)
136
+ F = (
137
+ NUFFTOperator(raw.trajectory, image_shape)
138
+ if not raw.is_cartesian
139
+ else FourierOperator(image_shape)
140
+ )
141
+ A = unchecked(F @ SensitivityOperator(maps))
142
+ image = conjugate_gradient(A, raw.kspace, n_iter=30)
143
+ ```
144
+
145
+ The reconstruction half works today (see `examples/`); `unimri.read` for vendor
146
+ formats does not yet.
147
+
148
+ ## Installation (development)
149
+
150
+ ```bash
151
+ git clone https://github.com/istiyakamin/UniMRI
152
+ cd UniMRI
153
+ python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
154
+ pip install -e ".[dev]"
155
+ pytest
156
+ ```
157
+
158
+ GPU and vendor-specific support are optional extras: `pip install -e ".[gpu]"`,
159
+ `".[torch]"`, `".[ismrmrd]"`.
160
+
161
+ ## Documentation
162
+
163
+ - [Architecture](docs/architecture.md) — the layered design and the operator model
164
+ - [Data model](docs/data-model.md) — `MRIData` schema and unit conventions
165
+ - [I/O & format support](docs/io-format-support.md)
166
+ - [Roadmap](docs/roadmap.md)
167
+ - [Prior art](docs/prior-art.md) — how UniMRI relates to `mrpro`, `mri-nufft`,
168
+ `sigpy`, BART, ISMRMRD/Gadgetron, and others
169
+ - [Acknowledgments](docs/acknowledgments.md) — every library, standard, and
170
+ method UniMRI uses, with credit
171
+
172
+ ## Contributing
173
+
174
+ UniMRI is meant to grow as a community project. See
175
+ [CONTRIBUTING.md](CONTRIBUTING.md) and the
176
+ [good first issues](https://github.com/istiyakamin/UniMRI/labels/good%20first%20issue).
177
+
178
+ ## Acknowledgments
179
+
180
+ UniMRI builds on the open-source scientific Python ecosystem — NumPy, SciPy,
181
+ h5py, and (as it grows) ISMRMRD, MRI-NUFFT, SigPy, BART, twixtools, PyTorch, and
182
+ others, plus published reconstruction methods credited to their originators. The
183
+ full list with licenses is in [docs/acknowledgments.md](docs/acknowledgments.md).
184
+
185
+ ## License
186
+
187
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,119 @@
1
+ <p align="center">
2
+ <img src="assets/logo.png" alt="UniMRI — one interface for MRI raw data" width="380">
3
+ </p>
4
+
5
+ <h1 align="center">UniMRI</h1>
6
+
7
+ <p align="center"><strong>One interface for MRI raw data.</strong></p>
8
+
9
+ <p align="center">
10
+ <a href="https://github.com/istiyakamin/UniMRI/actions/workflows/ci.yml"><img src="https://github.com/istiyakamin/UniMRI/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
11
+ <img src="https://img.shields.io/badge/status-pre--alpha-orange.svg" alt="Status: pre-alpha">
12
+ <img src="https://img.shields.io/badge/python-3.10%2B-blue.svg" alt="Python 3.10+">
13
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a>
14
+ <a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff"></a>
15
+ <img src="https://img.shields.io/badge/types-typed-brightgreen.svg" alt="Typed">
16
+ <a href="https://istiyakamin.github.io/UniMRI/"><img src="https://img.shields.io/badge/docs-mkdocs-blue.svg" alt="Docs"></a>
17
+ </p>
18
+
19
+ <!-- Enable once the package is actually on PyPI (after the first `v0.0.1a1` tag publishes):
20
+ <a href="https://pypi.org/project/unimri/"><img src="https://img.shields.io/pypi/v/unimri.svg" alt="PyPI"></a>
21
+ <a href="https://pypi.org/project/unimri/"><img src="https://img.shields.io/pypi/dm/unimri.svg?label=PyPI%20downloads" alt="PyPI downloads"></a>
22
+ <a href="https://doi.org/PLACEHOLDER"><img src="https://img.shields.io/badge/DOI-PLACEHOLDER-blue.svg" alt="DOI"></a>
23
+ <a href="https://securityscorecards.dev/viewer/?uri=github.com/istiyakamin/UniMRI"><img src="https://api.securityscorecards.dev/projects/github.com/istiyakamin/UniMRI/badge" alt="OpenSSF Scorecard"></a>
24
+ -->
25
+
26
+ UniMRI is an open-source Python framework that provides a common computational
27
+ interface for MRI raw data across scanners, vendors, and acquisition strategies —
28
+ Cartesian, radial, spiral, and other non-Cartesian trajectories — so that
29
+ reconstruction algorithms can be written once and run on data from anywhere.
30
+
31
+ > **Status: pre-alpha (v0.0.1a1).** The data model (`MRIData`), the operator
32
+ > algebra, `FourierOperator`/`NUFFTOperator`/`SensitivityOperator`, and
33
+ > `reconstruct(method="adjoint"|"cg")` — single-pass gridding and CG-SENSE, the
34
+ > same code for Cartesian and non-Cartesian data — all work, validated on real
35
+ > 3-D radial ²³Na data. The vendor readers (`unimri.read`) are still stubs. See
36
+ > the [roadmap](docs/roadmap.md).
37
+
38
+ > **Name caveat:** `UniMRI` / `unimri` is a provisional working name. A full
39
+ > PyPI / GitHub / trademark clearance is still pending before any public release
40
+ > or PyPI upload.
41
+
42
+ ## The idea
43
+
44
+ The core problem is fragmentation: every vendor format has its own loader, and
45
+ every reconstruction toolbox has its own data model. UniMRI normalizes vendor
46
+ raw data into one representation, then reconstructs from that.
47
+
48
+ <p align="center">
49
+ <img src="assets/idea.png" alt="UniMRI pipeline: raw data from any vendor (Siemens TWIX, GE P-file, Philips RAW, ISMRMRD, HDF5) flows through the I/O layer (format detection + reader registry), into the unified MRIData model (k-space, trajectory, encoding, coils, metadata, provenance), through the operator layer (reconstruction as an inverse problem, y = P F S x), through reconstruction (FFT, SENSE, GRAPPA, CG-SENSE, compressed sensing), to an MRI image — vendor- and trajectory-independent." width="560">
50
+ </p>
51
+
52
+ ## Aspirational API
53
+
54
+ ```python
55
+ import unimri
56
+
57
+ raw = unimri.read("measurement.dat") # vendor-agnostic -- NOT YET (docs/roadmap.md, M2)
58
+ image = unimri.reconstruct(raw, method="cg") # trajectory-agnostic -- WORKS TODAY
59
+ ```
60
+
61
+ ```python
62
+ # advanced: reconstruction as an inverse problem -- WORKS TODAY (see examples/07_cg_sense.py)
63
+ from unimri.calibration import estimate_sensitivity
64
+ from unimri.operators import FourierOperator, NUFFTOperator, SensitivityOperator, unchecked
65
+ from unimri.optimization import conjugate_gradient
66
+
67
+ maps = estimate_sensitivity(raw)
68
+ F = (
69
+ NUFFTOperator(raw.trajectory, image_shape)
70
+ if not raw.is_cartesian
71
+ else FourierOperator(image_shape)
72
+ )
73
+ A = unchecked(F @ SensitivityOperator(maps))
74
+ image = conjugate_gradient(A, raw.kspace, n_iter=30)
75
+ ```
76
+
77
+ The reconstruction half works today (see `examples/`); `unimri.read` for vendor
78
+ formats does not yet.
79
+
80
+ ## Installation (development)
81
+
82
+ ```bash
83
+ git clone https://github.com/istiyakamin/UniMRI
84
+ cd UniMRI
85
+ python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
86
+ pip install -e ".[dev]"
87
+ pytest
88
+ ```
89
+
90
+ GPU and vendor-specific support are optional extras: `pip install -e ".[gpu]"`,
91
+ `".[torch]"`, `".[ismrmrd]"`.
92
+
93
+ ## Documentation
94
+
95
+ - [Architecture](docs/architecture.md) — the layered design and the operator model
96
+ - [Data model](docs/data-model.md) — `MRIData` schema and unit conventions
97
+ - [I/O & format support](docs/io-format-support.md)
98
+ - [Roadmap](docs/roadmap.md)
99
+ - [Prior art](docs/prior-art.md) — how UniMRI relates to `mrpro`, `mri-nufft`,
100
+ `sigpy`, BART, ISMRMRD/Gadgetron, and others
101
+ - [Acknowledgments](docs/acknowledgments.md) — every library, standard, and
102
+ method UniMRI uses, with credit
103
+
104
+ ## Contributing
105
+
106
+ UniMRI is meant to grow as a community project. See
107
+ [CONTRIBUTING.md](CONTRIBUTING.md) and the
108
+ [good first issues](https://github.com/istiyakamin/UniMRI/labels/good%20first%20issue).
109
+
110
+ ## Acknowledgments
111
+
112
+ UniMRI builds on the open-source scientific Python ecosystem — NumPy, SciPy,
113
+ h5py, and (as it grows) ISMRMRD, MRI-NUFFT, SigPy, BART, twixtools, PyTorch, and
114
+ others, plus published reconstruction methods credited to their originators. The
115
+ full list with licenses is in [docs/acknowledgments.md](docs/acknowledgments.md).
116
+
117
+ ## License
118
+
119
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,109 @@
1
+ # Acknowledgments
2
+
3
+ UniMRI stands on a large body of open-source scientific software. This page
4
+ credits every library, standard, and method the project uses or is built to use.
5
+ Licenses are noted where known; consult each project for the authoritative terms.
6
+
7
+ ## Runtime dependencies
8
+
9
+ Libraries imported by the UniMRI core (`pip install unimri`):
10
+
11
+ | Library | Used for | License |
12
+ | --- | --- | --- |
13
+ | [NumPy](https://numpy.org) | n-dimensional arrays; the default compute backend | BSD-3-Clause |
14
+ | [SciPy](https://scipy.org) | signal processing, linear algebra, spatial transforms | BSD-3-Clause |
15
+ | [h5py](https://www.h5py.org) | reading/writing HDF5 (ISMRMRD, UniMRI's cache format) | BSD-3-Clause |
16
+
17
+ UniMRI targets the [Python Array API standard](https://data-apis.org/array-api/)
18
+ so that operators can run on NumPy, CuPy, or PyTorch arrays unchanged.
19
+
20
+ ## Optional integrations
21
+
22
+ Enabled through extras (`pip install "unimri[...]"`):
23
+
24
+ | Library | Extra | Used for | License |
25
+ | --- | --- | --- | --- |
26
+ | [FINUFFT](https://github.com/flatironinstitute/finufft) | `nufft` | the non-uniform FFT behind `NUFFTOperator` and non-Cartesian reconstruction | Apache-2.0 |
27
+ | [Matplotlib](https://matplotlib.org) | `viz` | plotting in the examples | Matplotlib (BSD-style) |
28
+ | [ISMRMRD (Python)](https://github.com/ismrmrd/ismrmrd-python) | `ismrmrd` | reading ISMRMRD raw data | permissive (see project) |
29
+ | [PyTorch](https://pytorch.org) | `torch` | GPU / autograd array backend; unrolled-network reconstruction later | BSD-3-Clause |
30
+ | [CuPy](https://cupy.dev) | `gpu` | CUDA array backend | MIT |
31
+
32
+ ## Planned dependencies
33
+
34
+ These will be wrapped behind UniMRI interfaces as the corresponding milestones
35
+ land (see the [roadmap](roadmap.md)); UniMRI does not reimplement them.
36
+
37
+ | Library | Will be used for | License |
38
+ | --- | --- | --- |
39
+ | [twixtools](https://github.com/pehses/twixtools) (P. Ehses) | parsing Siemens TWIX `.dat` files | MIT |
40
+ | [MRI-NUFFT](https://github.com/mind-inria/mri-nufft) | broader NUFFT backend (GPU, more kernels) behind the same `NUFFTOperator` interface | BSD-3-Clause |
41
+ | [cufinufft](https://github.com/flatironinstitute/finufft) | GPU NUFFT backend | Apache-2.0 |
42
+ | [gpuNUFFT](https://github.com/andyschwarzl/gpuNUFFT) | GPU gridding backend (via MRI-NUFFT) | MIT |
43
+ | [torchkbnufft](https://github.com/mmuckley/torchkbnufft) (M. Muckley) | differentiable Kaiser–Bessel NUFFT (via MRI-NUFFT) | MIT |
44
+ | [SigPy](https://github.com/mikgroup/sigpy) | reference parallel-imaging / compressed-sensing recon, ESPIRiT | BSD-3-Clause |
45
+ | [BART](https://mrirecon.github.io/bart/) | optional reference calibration & iterative reconstruction | BSD-3-Clause |
46
+ | [array-api-compat](https://github.com/data-apis/array-api-compat) | array-backend compatibility, if a full shim becomes necessary | MIT |
47
+
48
+ ## Development and documentation tooling
49
+
50
+ | Tool | Role | License |
51
+ | --- | --- | --- |
52
+ | [Hatch / hatchling](https://hatch.pypa.io) | build backend | MIT |
53
+ | [pytest](https://pytest.org) + [pytest-cov](https://github.com/pytest-dev/pytest-cov) | test runner and coverage | MIT |
54
+ | [Ruff](https://docs.astral.sh/ruff/) | linter and formatter | MIT |
55
+ | [mypy](https://mypy-lang.org) | static type checking | MIT |
56
+ | [MkDocs](https://www.mkdocs.org) + [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) | documentation site | BSD-2-Clause / MIT |
57
+ | [mkdocstrings](https://mkdocstrings.github.io) | API docs from docstrings | ISC |
58
+ | [pre-commit](https://pre-commit.com) | git hook management | MIT |
59
+ | [GitHub Actions](https://github.com/features/actions) | continuous integration | — |
60
+
61
+ ## Standards and community templates
62
+
63
+ - [ISMRMRD](https://ismrmrd.github.io) — the raw-data interchange format UniMRI
64
+ interoperates with (Inati et al., *Magn Reson Med* 2017).
65
+ - [Python Array API standard](https://data-apis.org/array-api/) — the backend
66
+ abstraction contract.
67
+ - [Contributor Covenant](https://www.contributor-covenant.org) — the Code of
68
+ Conduct.
69
+ - [Keep a Changelog](https://keepachangelog.com) and
70
+ [Semantic Versioning](https://semver.org) — changelog and version scheme.
71
+ - [Citation File Format](https://citation-file-format.github.io) — `CITATION.cff`.
72
+
73
+ ## Methods and algorithms
74
+
75
+ UniMRI implements or will implement the following published methods; credit is to
76
+ their originators, with full citations added alongside each implementation:
77
+
78
+ - **Shepp–Logan phantom** — Shepp & Logan (1974); the modified (Toft) variant
79
+ used by `unimri.testing.phantoms`.
80
+ - **Golden-angle radial sampling** — Winkelmann et al. (2007).
81
+ - **Density-adapted 3D projection reconstruction** — Nagel et al. (2009); the
82
+ primary non-Cartesian / X-nuclei target.
83
+ - **Sampling density compensation (iterative)** — Pipe & Menon (1999).
84
+ - **ESPIRiT** coil-sensitivity calibration — Uecker et al. (2014).
85
+ - **POCS / homodyne** partial-Fourier reconstruction — Haacke et al.; Noll et al.
86
+ - **CG-SENSE** — Pruessmann et al. (2001).
87
+
88
+ ## Inspiration and prior art
89
+
90
+ UniMRI's unified-data-model + operator-based design follows earlier work,
91
+ discussed in detail in [Prior art](prior-art.md):
92
+
93
+ - [MRIReco.jl](https://github.com/MagneticResonanceImaging/MRIReco.jl) — the same
94
+ thesis, in Julia (Knopp & Grosser, *Magn Reson Med* 2021).
95
+ - [mrpro](https://github.com/PTB-MR/mrpro) — a PyTorch MR reconstruction
96
+ framework with a closely related architecture.
97
+ - [Gadgetron](https://github.com/gadgetron/gadgetron) — streaming reconstruction
98
+ and vendor converters (Hansen & Sørensen, *Magn Reson Med* 2013).
99
+ - [fastMRI](https://github.com/facebookresearch/fastMRI),
100
+ [PyQMRI](https://github.com/IMTtugraz/PyQMRI),
101
+ [DIRECT](https://github.com/NKI-AI/direct) — adjacent toolkits.
102
+ - [mapVBVD](https://github.com/CIC-methods/FID-A) / pymapVBVD — Siemens raw
103
+ reading, the lineage `twixtools` comes from.
104
+
105
+ ## Getting credit right
106
+
107
+ If your library or method is used by UniMRI and is missing, mis-licensed, or
108
+ mis-attributed here, please open an issue or pull request — corrections are
109
+ welcome and appreciated.