mrzerocore 0.3.2__cp37-abi3-win_amd64.whl → 0.4.2__cp37-abi3-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. mrzerocore/_prepass.pyd +0 -0
  2. {MRzeroCore-0.3.2.dist-info → mrzerocore-0.4.2.dist-info}/METADATA +47 -14
  3. mrzerocore-0.4.2.dist-info/RECORD +5 -0
  4. {MRzeroCore-0.3.2.dist-info → mrzerocore-0.4.2.dist-info}/WHEEL +1 -1
  5. MRzeroCore/__init__.py +0 -19
  6. MRzeroCore/_prepass.pyd +0 -0
  7. MRzeroCore/phantom/brainweb/__init__.py +0 -171
  8. MRzeroCore/phantom/brainweb/brainweb_data.json +0 -93
  9. MRzeroCore/phantom/brainweb/brainweb_data_sources.txt +0 -74
  10. MRzeroCore/phantom/brainweb/output/.gitkeep +0 -0
  11. MRzeroCore/phantom/custom_voxel_phantom.py +0 -267
  12. MRzeroCore/phantom/sim_data.py +0 -202
  13. MRzeroCore/phantom/voxel_grid_phantom.py +0 -582
  14. MRzeroCore/pulseq/exporter.py +0 -374
  15. MRzeroCore/pulseq/exporter_v2.py +0 -650
  16. MRzeroCore/pulseq/helpers.py +0 -228
  17. MRzeroCore/pulseq/pulseq_exporter.py +0 -553
  18. MRzeroCore/pulseq/pulseq_loader/__init__.py +0 -66
  19. MRzeroCore/pulseq/pulseq_loader/adc.py +0 -48
  20. MRzeroCore/pulseq/pulseq_loader/helpers.py +0 -75
  21. MRzeroCore/pulseq/pulseq_loader/pulse.py +0 -80
  22. MRzeroCore/pulseq/pulseq_loader/pulseq_file/__init__.py +0 -235
  23. MRzeroCore/pulseq/pulseq_loader/pulseq_file/adc.py +0 -68
  24. MRzeroCore/pulseq/pulseq_loader/pulseq_file/block.py +0 -98
  25. MRzeroCore/pulseq/pulseq_loader/pulseq_file/definitons.py +0 -68
  26. MRzeroCore/pulseq/pulseq_loader/pulseq_file/gradient.py +0 -70
  27. MRzeroCore/pulseq/pulseq_loader/pulseq_file/helpers.py +0 -156
  28. MRzeroCore/pulseq/pulseq_loader/pulseq_file/rf.py +0 -91
  29. MRzeroCore/pulseq/pulseq_loader/pulseq_file/trap.py +0 -69
  30. MRzeroCore/pulseq/pulseq_loader/spoiler.py +0 -33
  31. MRzeroCore/reconstruction.py +0 -104
  32. MRzeroCore/sequence.py +0 -726
  33. MRzeroCore/simulation/isochromat_sim.py +0 -254
  34. MRzeroCore/simulation/main_pass.py +0 -292
  35. MRzeroCore/simulation/pre_pass.py +0 -159
  36. MRzeroCore/util.py +0 -415
  37. MRzeroCore-0.3.2.dist-info/RECORD +0 -36
  38. {MRzeroCore-0.3.2.dist-info → mrzerocore-0.4.2.dist-info}/licenses/LICENSE +0 -0
Binary file
@@ -1,28 +1,32 @@
1
- Metadata-Version: 2.3
2
- Name: MRzeroCore
3
- Version: 0.3.2
1
+ Metadata-Version: 2.4
2
+ Name: mrzerocore
3
+ Version: 0.4.2
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
7
7
  Classifier: License :: OSI Approved :: GNU Affero General Public License v3
8
- Requires-Dist: torch >=1.12
8
+ Requires-Dist: ismrmrd
9
+ Requires-Dist: matplotlib>=3.5
10
+ Requires-Dist: pydisseqt>=0.1.13
9
11
  Requires-Dist: pypulseq
10
- Requires-Dist: matplotlib >=3.5
11
- Requires-Dist: scipy >=1.7
12
- Requires-Dist: requests >=2.20
12
+ Requires-Dist: requests>=2.20
13
13
  Requires-Dist: scikit-image
14
+ Requires-Dist: scipy>=1.7
14
15
  Requires-Dist: torchkbnufft
15
- Requires-Dist: pydisseqt >=0.1.4
16
+ Requires-Dist: torch>=1.12
17
+ Requires-Dist: tqdm
18
+ Requires-Dist: nibabel
16
19
  License-File: LICENSE
17
20
  Summary: Core functionality of MRzero
18
21
  Author-email: Jonathan Endres <jonathan.endres@uk-erlangen.de>
19
22
  Requires-Python: >=3.9
20
23
  Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
21
- Project-URL: Repository, https://github.com/MRsources/MRzero-Core
22
- Project-URL: Documentation, https://mrzero-core.readthedocs.io/
24
+ Project-URL: Documentation, https://mrsources.github.io/MRzero-Core/
23
25
  Project-URL: MRzero-Paper, https://arxiv.org/abs/2002.04265
26
+ Project-URL: Repository, https://github.com/MRsources/MRzero-Core
24
27
 
25
28
  [![Documentation Status](https://readthedocs.org/projects/mrzero-core/badge/?version=latest)](https://mrzero-core.readthedocs.io/en/latest/?badge=latest)
29
+ ![PyPI - Version](https://img.shields.io/pypi/v/MRzeroCore)
26
30
 
27
31
  # MRzero Core
28
32
 
@@ -43,7 +47,29 @@ The typical way of using it is like the following:
43
47
  import MRzeroCore as mr0
44
48
  ```
45
49
 
46
- Examples on how to use can be found in the [Playground](https://mrzero-core.readthedocs.io/en/latest/playground_mr0/overview.html).
50
+ Examples on how to use MR-zero can be found in the [Playground](https://mrzero-core.readthedocs.io/en/latest/playground_mr0/overview.html).
51
+
52
+ ## Pulseq Integration
53
+
54
+ **MRzero Core makes Pulseq simulation incredibly easy** - simulate any .seq file in just one line:
55
+
56
+ ```python
57
+ import MRzeroCore as mr0
58
+
59
+ # Simulate any Pulseq file
60
+ seq = mr0.Sequence.import_file("your_sequence.seq")
61
+ signal = mr0.util.simulate(seq) # That's it!
62
+ ```
63
+
64
+ ### Key Features:
65
+ - **One-line simulation** of any Pulseq .seq file
66
+ - **PyPulseq integration** - write sequences in Python, simulate with MR-zero
67
+ - **Google Colab ready** - [13+ ready-to-run examples](https://mrzero-core.readthedocs.io/en/latest/playground_mr0/overview.html#code-and-simulate-pypulseq)
68
+ - **MATLAB ↔ Python workflow** - create in MATLAB Pulseq, simulate in Python
69
+ - **No dependencies** - fully self-contained Pulseq parser included
70
+ - **Scanner-ready export** - export MR-zero sequences as .seq files
71
+
72
+ Try it now: [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/MRsources/MRzero-Core/blob/main/documentation/playground_mr0/mr0_upload_seq.ipynb)
47
73
 
48
74
  ## Links
49
75
 
@@ -69,11 +95,18 @@ maturin build --interpreter python
69
95
  docker run --rm -v <path-to-repo>/MRzero-Core:/io ghcr.io/pyo3/maturin build
70
96
  ```
71
97
 
72
- To **build the documentation**, run
98
+ **Building the documentation**
99
+
100
+ Install newest (beta) version of mdBook:
101
+ ```bash
102
+ cargo install --git https://github.com/rust-lang/mdBook.git mdbook
73
103
  ```
74
- jupyter-book build documentation/
104
+
105
+ Run a live-preview server:
106
+ ```bash
107
+ # in the root directory:
108
+ mdbook serve documentation
75
109
  ```
76
- in the root folder of this project. This requires jupyter-book as well as MRzeroCore itself to be installed.
77
110
 
78
111
 
79
112
  ## Official builds
@@ -0,0 +1,5 @@
1
+ mrzerocore\_prepass.pyd,sha256=UOjZB6opacbWy2UamRQ9dWFmo8R9SBVReCuUN_knEss,401408
2
+ mrzerocore-0.4.2.dist-info\METADATA,sha256=t_KUGUHRYRiEfLDikcp_SEcaAmciBFIQ72PYwHKjHws,5049
3
+ mrzerocore-0.4.2.dist-info\WHEEL,sha256=wIaq5kKGufyzCzRkK9cVMZbLF09Wr1z6BXtkxRsuBGs,95
4
+ mrzerocore-0.4.2.dist-info\licenses\LICENSE,sha256=rd_IFJ484uAluv8CigP2CpXg4l2GJLLKENqB6-RXPp4,35112
5
+ mrzerocore-0.4.2.dist-info\RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: maturin (1.7.1)
2
+ Generator: maturin (1.11.5)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp37-abi3-win_amd64
MRzeroCore/__init__.py DELETED
@@ -1,19 +0,0 @@
1
- import numpy
2
- if not hasattr(numpy, "int"):
3
- numpy.int = int
4
- if not hasattr(numpy, "float"):
5
- numpy.float = float
6
- if not hasattr(numpy, "complex"):
7
- numpy.complex = complex
8
-
9
- from .sequence import PulseUsage, Pulse, Repetition, Sequence, chain
10
- from .phantom.voxel_grid_phantom import VoxelGridPhantom
11
- from .phantom.custom_voxel_phantom import CustomVoxelPhantom
12
- from .phantom.sim_data import SimData
13
- from .phantom.brainweb import generate_brainweb_phantoms
14
- from .simulation.isochromat_sim import isochromat_sim
15
- from .simulation.pre_pass import compute_graph, compute_graph_ext, Graph
16
- from .simulation.main_pass import execute_graph
17
- from .reconstruction import reco_adjoint
18
- from .pulseq.exporter import pulseq_write_cartesian
19
- from . import util
MRzeroCore/_prepass.pyd DELETED
Binary file
@@ -1,171 +0,0 @@
1
- from typing import Literal
2
- import json
3
- import gzip
4
- import requests
5
- import os
6
- import numpy as np
7
-
8
-
9
- # Load the brainweb data file that contains info about tissues, subjects, ...
10
- brainweb_data_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
11
- "brainweb_data.json")
12
- brainweb_data = json.load(open(brainweb_data_path))
13
-
14
-
15
- def load_tissue(subject: int, alias: str, cache_dir: str) -> np.ndarray:
16
- download_alias = f"subject{subject:02d}_{alias}"
17
- file_name = download_alias + ".i8.gz" # 8 bit signed int, gnuzip
18
- file_path = os.path.join(cache_dir, file_name)
19
-
20
- # Download and cache file if it doesn't exist yet
21
- if not os.path.exists(file_path):
22
- print(f"Downloading '{download_alias}'", end="", flush=True)
23
- response = requests.post(
24
- "https://brainweb.bic.mni.mcgill.ca/cgi/brainweb1",
25
- data={
26
- "do_download_alias": download_alias,
27
- "format_value": "raw_byte",
28
- "zip_value": "gnuzip"
29
- }
30
- )
31
- with open(file_path, "wb") as f:
32
- f.write(response.content)
33
- print(" - ", end="")
34
-
35
- # Load the raw BrainWeb data and add it to the return array
36
- with gzip.open(file_path) as f:
37
- print(f"Loading {os.path.basename(file_path)}", end="", flush=True)
38
- # BrainWeb says this data is unsigned, which is a lie
39
- tmp = np.frombuffer(f.read(), np.uint8) + 128
40
-
41
- # Vessel bugfix: most of background is 1 instead of zero
42
- if alias == "ves":
43
- tmp[tmp == 1] = 0
44
- data = tmp.reshape(362, 434, 362).swapaxes(0, 2).astype(np.float32)
45
-
46
- print(" - done")
47
- return data / 255.0
48
-
49
-
50
- def gen_noise(range: float, res: np.ndarray) -> np.ndarray:
51
- if range == 0:
52
- return 1
53
- else:
54
- freq = 20
55
- padded_res = (res + freq - 1) // freq * freq
56
- try:
57
- from perlin_numpy import generate_perlin_noise_3d
58
- noise = generate_perlin_noise_3d(padded_res, (freq, freq, freq))
59
- except:
60
- print("perlin_numpy@git+https://github.com/pvigier/perlin-numpy")
61
- print("is not installed, falling back to numpy.random.random()")
62
- noise = np.random.random(padded_res)
63
- return 1 + range * noise[:res[0], :res[1], :res[2]]
64
-
65
-
66
- def downsample(array: np.ndarray, factor: int) -> np.ndarray:
67
- # crop array to multiple of factor
68
- shape = (np.array(array.shape) // factor) * factor
69
- array = array[:shape[0], :shape[1], :shape[2]]
70
-
71
- tmp = np.zeros(shape // factor)
72
- for x in range(factor):
73
- for y in range(factor):
74
- for z in range(factor):
75
- tmp += array[x::factor, y::factor, z::factor]
76
-
77
- return tmp / factor**3
78
-
79
-
80
- def generate_brainweb_phantoms(
81
- output_dir: str,
82
- config: Literal["3T", "7T-noise", "3T-highres-fat"] = "3T"):
83
- """Generate BrainWeb phantom maps for the selected configuration.
84
-
85
- Raw tissue segmentation data is provided by the BrainWeb Database:
86
- http://www.bic.mni.mcgill.ca/brainweb/
87
-
88
- All tissue data etc. are stored in [brainweb_data.json](https://github.com/MRsources/MRzero-Core/blob/main/python/MRzeroCore/phantom/brainweb/brainweb_data.json).
89
- To ensure consistent configurations and reproducible results, available
90
- configs are stored in this file as well. They specify which field strength
91
- to use, which tissues to include, and the downsampling and noise levels.
92
-
93
- The emitted files are compressed numpy files, which can be loaded with
94
- ``np.load(file_name)``. They contain the following arrays:
95
-
96
- - `PD_map`: Proton Density [a.u.]
97
- - `T1_map`: T1 relaxation time [s]
98
- - `T2_map`: T2 relaxation time [s]
99
- - `T2dash_map`: T2' relaxation time [s]
100
- - `D_map`: Isotropic Diffusion coefficient [10^-3 mm² / s]
101
- - `tissue_XY`: Tissue segmentation for all included tissues
102
-
103
- Parameters
104
- ----------
105
- output_dir: str
106
- The directory where the generated phantoms will be stored to. In
107
- addition, a `cache` folder will be generated there too, which contains
108
- all the data downloaded from BrainWeb to avoid repeating the download
109
- for all configurations or when generating phantoms again.
110
- config: ["3T", "7T-noise", "3T-highres-fat"]
111
- The configuration for which the maps are generated.
112
- """
113
- config_data = brainweb_data["configs"][config]
114
- cache_dir = os.path.join(output_dir, "cache")
115
-
116
- try:
117
- os.makedirs(cache_dir)
118
- except FileExistsError:
119
- pass
120
-
121
- # Map resolution:
122
- res = np.array([362, 434, 362]) // config_data["downsample"]
123
-
124
- def noise() -> np.ndarray:
125
- return gen_noise(config_data["noise"], res)
126
-
127
- for subject in brainweb_data["subjects"]:
128
- print(f"Generating '{config}', subject {subject}")
129
- maps = {
130
- "FOV": np.array([0.181, 0.217, 0.181]),
131
- "PD_map": np.zeros(res, dtype=np.float32),
132
- "T1_map": np.zeros(res, dtype=np.float32),
133
- "T2_map": np.zeros(res, dtype=np.float32),
134
- "T2dash_map": np.zeros(res, dtype=np.float32),
135
- "D_map": np.zeros(res, dtype=np.float32),
136
- }
137
-
138
- for tissue in config_data["tissues"]:
139
- tissue_map = sum([
140
- load_tissue(subject, alias, cache_dir)
141
- for alias in brainweb_data["download-aliases"][tissue]
142
- ])
143
- tissue_map = downsample(tissue_map, config_data["downsample"])
144
- maps["tissue_" + tissue] = tissue_map
145
-
146
- field_strength = config_data["field-strength"]
147
- tissue_data = brainweb_data["tissues"][field_strength][tissue]
148
-
149
- # Separate noise maps is slower but uncorrelated.
150
- # Might be better for training or worse - could be configurable
151
- print("Adding tissue to phantom", end="", flush=True)
152
- maps["PD_map"] += tissue_data["PD"] * tissue_map * noise()
153
- maps["T1_map"] += tissue_data["T1"] * tissue_map * noise()
154
- maps["T2_map"] += tissue_data["T2"] * tissue_map * noise()
155
- maps["T2dash_map"] += tissue_data["T2'"] * tissue_map * noise()
156
- maps["D_map"] += tissue_data["D"] * tissue_map * noise()
157
- print(" - done")
158
-
159
- file = os.path.join(output_dir, f"subject{subject:02d}_{config}.npz")
160
- print(f"Saving to '{os.path.basename(file)}'", end="", flush=True)
161
- np.savez_compressed(file, **maps)
162
- print(" - done\n")
163
-
164
-
165
- if __name__ == "__main__":
166
- print("This is for testing only, use generate_brainweb_phantoms directly!")
167
- file_dir = os.path.dirname(os.path.realpath(__file__))
168
- output_dir = os.path.join(file_dir, "output")
169
-
170
- for config in brainweb_data["configs"].keys():
171
- generate_brainweb_phantoms(output_dir, config)
@@ -1,93 +0,0 @@
1
- {
2
- "configs": {
3
- "3T": {
4
- "field-strength": "3T",
5
- "tissues": ["gm", "wm", "csf"],
6
- "downsample": 3,
7
- "noise": 0
8
- },
9
- "7T-noise": {
10
- "field-strength": "7T",
11
- "tissues": ["gm", "wm", "csf"],
12
- "downsample": 3,
13
- "noise": 0.2
14
- },
15
- "3T-highres-fat": {
16
- "field-strength": "3T",
17
- "tissues": ["gm", "wm", "csf", "fat"],
18
- "downsample": 1,
19
- "noise": 0
20
- }
21
- },
22
- "subjects": [
23
- 4, 5, 6, 18, 20, 38, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54
24
- ],
25
- "download-aliases": {
26
- "gm": ["gry"],
27
- "wm": ["wht"],
28
- "csf": ["csf", "ves"],
29
- "fat": ["fat", "mus", "m-s", "dura", "fat2"]
30
- },
31
- "tissues": {
32
- "3T": {
33
- "gm": {
34
- "PD": 0.8,
35
- "T1": 1.56,
36
- "T2": 0.083,
37
- "T2'": 0.32,
38
- "D": 0.83
39
- },
40
- "wm": {
41
- "PD": 0.7,
42
- "T1": 0.83,
43
- "T2": 0.075,
44
- "T2'": 0.18,
45
- "D": 0.65
46
- },
47
- "csf": {
48
- "PD": 1,
49
- "T1": 4.16,
50
- "T2": 1.65,
51
- "T2'": 0.059,
52
- "D": 3.19
53
- },
54
- "fat": {
55
- "PD": 1,
56
- "T1": 0.37,
57
- "T2": 0.125,
58
- "T2'": 0.012,
59
- "D": 0.1
60
- }
61
- },
62
- "7T": {
63
- "gm": {
64
- "PD": 0.8,
65
- "T1": 1.67,
66
- "T2": 0.043,
67
- "T2'": 0.82,
68
- "D": 0.83
69
- },
70
- "wm": {
71
- "PD": 0.7,
72
- "T1": 1.22,
73
- "T2": 0.037,
74
- "T2'": 0.65,
75
- "D": 0.65
76
- },
77
- "csf": {
78
- "PD": 1,
79
- "T1": 4.0,
80
- "T2": 0.8,
81
- "T2'": 0.204,
82
- "D": 3.19
83
- },
84
- "fat": {
85
- "PD": 1,
86
- "T1": 0.374,
87
- "T2": 0.125,
88
- "T2'": 0.0117,
89
- "D": 0.1
90
- }
91
- }
92
- }
93
- }
@@ -1,74 +0,0 @@
1
- ! NOTE
2
- 7T maps are not checked as thrououghly. Only source so far:
3
- https://cds.ismrm.org/protected/14MProceedings/PDFfiles/3208.pdf
4
-
5
-
6
- # T1 and T2 times, taken from:
7
- # https://mri-q.com/uploads/3/4/5/7/34572113/normal_relaxation_times_at_3t.pdf
8
- # Value taken from paper with most participants (draw: closest to mean of all)
9
- # Studies that are outliers are ignored (WM T2 time)
10
-
11
- # T2' calculated from T2 and T2*, taken from:
12
- # https://www.sciencedirect.com/science/article/pii/S0730725X07001701?via%3Dihub
13
-
14
- # Water / Fat T2': https://link.springer.com/article/10.1007/s00723-015-0737-5 (4.7 T)
15
-
16
- # Errors are uncertenties of studies, not data on variation in one measurement
17
-
18
- Brainweb Tissues:
19
- - CSF
20
- T1: 4163 ± 263
21
- T2: 1650 (approx, taken from https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5973950/)
22
- T2*: 57.1 -> T2': 59.1
23
-
24
- - Gray Matter
25
- T1: 1558 ± 88
26
- T2: 83 ± 4
27
- T2*: 66.0 ± 1.4 -> T2': 322
28
-
29
- - White Matter
30
- T1: 830 ± 0
31
- T2: 75 ± 3
32
- T2*: 53.2 ± 1.2 -> T2': 183
33
- T2': 56 ± 1
34
-
35
- - Fat
36
- T1: 374 ± 45
37
- T2: 125
38
- T2* = 10.7 -> T2': 11.7
39
-
40
- # The following values are not used for phantom generation
41
-
42
- - Muscle
43
- T1: 1100 ± 59
44
- T2: 40
45
-
46
- - Muscle/Skin
47
-
48
- - Skull
49
- Probably similar to Bone marrow, but they don't overlap in the images
50
-
51
- - Blood vessels
52
- Probably similar to CSF (mostly water)
53
-
54
- - Connective (region around fat)
55
- Overlaps nearly fully with Fat
56
-
57
- - Dura matter
58
- Very little volume, probably not noticable at lower resolutions
59
-
60
- - Bone marrow
61
- T1: 586 ± 73
62
- T2: 127
63
-
64
-
65
- Diffusion:
66
- Values taken from https://onlinelibrary.wiley.com/doi/10.1002/jmri.1076
67
- 10^-3 mm² / s
68
- CSF: 3.19 ± 0.10
69
- WM: 0.65 ± 0.03
70
- GM: 0.83 ± 0.05
71
-
72
- No great source for fat, https://onlinelibrary.wiley.com/doi/10.1002/mrm.24535
73
- says it barely diffuses
74
- FAT: ~0.1
File without changes