mrzerocore 0.2.10__tar.gz → 0.2.12__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.
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/CHANGELOG.md +6 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/Cargo.lock +1 -1
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/Cargo.toml +1 -1
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/PKG-INFO +2 -2
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/_toc.yml +1 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/phantom/brainweb/__init__.py +1 -1
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/phantom/brainweb/brainweb_data.json +1 -1
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/phantom/voxel_grid_phantom.py +4 -5
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/simulation/main_pass.py +21 -8
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/src/lib.rs +1 -1
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/src/pre_pass.rs +33 -17
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/.github/workflows/pypi_publish.yml +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/.gitignore +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/.readthedocs.yaml +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/EULA.txt +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/LICENSE +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/README.md +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/_config.yml +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/api/phantom.md +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/api/reco.md +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/api/sequence.md +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/api/simulation/isochromat_sim.md +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/api/simulation/pdg_sim.md +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/api/simulation.md +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/api/util.md +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/api.md +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/intro.md +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/logo.png +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/phantom_generation.md +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/AdjDataUser2gB0_transversal_0.08moving_average.mat +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/flash.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/flash_DWI.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr00_FLASH_2D_ernstAngle_opt.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_CS_cartesian_seq.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_CS_radial_seq.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_DREAM_STE_seq.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_DREAM_STID_seq.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_DWI_GRE_2D_seq.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_EPI_2D_seq.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_FID_seq.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_FLASH_2D_seq.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_GRE_to_FLASH.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_RARE_2D_seq.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_SE_CPMG_seq.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_STE_3pulses_5echoes_seq.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_bSSFP_2D_seq.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_burst_TSE.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_opt_FLASH_2D_IR_Fit_T1.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_opt_FLASH_2D_IR_voxelNN_T1.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_pypulseq_exmpls_seq.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_upload_seq.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/numerical_brain_cropped.mat +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/overview.md +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/ptx_phantom.p +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/pulseq_flash.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/pulseq_rf_shim.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/pulseq_sim_pTx.ipynb +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/seqs/flash pTx CP.seq +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/seqs/flash pTx EP.seq +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/seqs/flash pTx QM.seq +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/subject05.npz +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/requirements.txt +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/resources/logo.blend +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/resources/logo.png +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/resources/studio_small_09_2k.hdr +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/pyproject.toml +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/__init__.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/phantom/brainweb/brainweb_data_sources.txt +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/phantom/brainweb/output/.gitkeep +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/phantom/custom_voxel_phantom.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/phantom/sim_data.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/exporter.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/exporter_v2.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/helpers.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_exporter.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/__init__.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/adc.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/helpers.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/pulse.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/pulseq_file/__init__.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/pulseq_file/adc.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/pulseq_file/block.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/pulseq_file/definitons.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/pulseq_file/gradient.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/pulseq_file/helpers.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/pulseq_file/rf.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/pulseq_file/trap.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/spoiler.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/reconstruction.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/sequence.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/simulation/isochromat_sim.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/simulation/pre_pass.py +0 -0
- {MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/util.py +0 -0
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
- 0.2.12
|
|
2
|
+
- Fixed Brainweb phantom loading and generation
|
|
3
|
+
- Switched pre-pass kt precision from f32 to f64
|
|
4
|
+
- Made pre-pass state merging relative to sequence gradient moment and event time sizes
|
|
5
|
+
- 0.2.11
|
|
6
|
+
- (re-)introduced return_mag_z parameter in pdg simulation
|
|
1
7
|
- 0.2.10
|
|
2
8
|
- change default FOV in all notebooks to phantom size (200 mm)
|
|
3
9
|
- Use Open in Colab badges in the playground instead of links
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: MRzeroCore
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.12
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
6
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
@@ -18,9 +18,9 @@ Summary: Core functionality of MRzero
|
|
|
18
18
|
Author-email: Jonathan Endres <jonathan.endres@uk-erlangen.de>
|
|
19
19
|
Requires-Python: >=3.9
|
|
20
20
|
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
21
|
+
Project-URL: MRzero-Paper, https://arxiv.org/abs/2002.04265
|
|
21
22
|
Project-URL: Documentation, https://mrzero-core.readthedocs.io/
|
|
22
23
|
Project-URL: Repository, https://github.com/MRsources/MRzero-Core
|
|
23
|
-
Project-URL: MRzero-Paper, https://arxiv.org/abs/2002.04265
|
|
24
24
|
|
|
25
25
|
[](https://mrzero-core.readthedocs.io/en/latest/?badge=latest)
|
|
26
26
|
|
|
@@ -151,7 +151,7 @@ def generate_brainweb_phantoms(
|
|
|
151
151
|
print("Adding tissue to phantom", end="", flush=True)
|
|
152
152
|
maps["PD_map"] += tissue_data["PD"] * tissue_map * noise()
|
|
153
153
|
maps["T1_map"] += tissue_data["T1"] * tissue_map * noise()
|
|
154
|
-
maps["T2_map"] += tissue_data["T2"] * noise()
|
|
154
|
+
maps["T2_map"] += tissue_data["T2"] * tissue_map * noise()
|
|
155
155
|
maps["T2dash_map"] += tissue_data["T2'"] * tissue_map * noise()
|
|
156
156
|
maps["D_map"] += tissue_data["D"] * tissue_map * noise()
|
|
157
157
|
print(" - done")
|
|
@@ -157,6 +157,10 @@ class VoxelGridPhantom:
|
|
|
157
157
|
T2dash = torch.tensor(data['T2dash_map'])
|
|
158
158
|
PD = torch.tensor(data['PD_map'])
|
|
159
159
|
D = torch.tensor(data['D_map'])
|
|
160
|
+
try:
|
|
161
|
+
size = torch.tensor(data['FOV'])
|
|
162
|
+
except KeyError:
|
|
163
|
+
size = torch.tensor([0.192, 0.192, 0.192])
|
|
160
164
|
|
|
161
165
|
# Generate a somewhat plausible B0 and B1 map.
|
|
162
166
|
# Visually fitted to look similar to the numerical_brain_cropped
|
|
@@ -174,11 +178,6 @@ class VoxelGridPhantom:
|
|
|
174
178
|
B0 -= (B0 * weight).sum()
|
|
175
179
|
B1 /= (B1 * weight).sum()
|
|
176
180
|
|
|
177
|
-
try:
|
|
178
|
-
size = torch.tensor(data['FOV'])
|
|
179
|
-
except KeyError:
|
|
180
|
-
size = torch.tensor([0.192, 0.192, 0.192])
|
|
181
|
-
|
|
182
181
|
return cls(
|
|
183
182
|
PD, T1, T2, T2dash, D, B0, B1[None, ...],
|
|
184
183
|
torch.ones(1, *PD.shape), size,
|
|
@@ -18,12 +18,9 @@ def execute_graph(graph: Graph,
|
|
|
18
18
|
min_emitted_signal: float = 1e-2,
|
|
19
19
|
min_latent_signal: float = 1e-2,
|
|
20
20
|
print_progress: bool = True,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
This function can optionally return the + or z magnetisation and the
|
|
25
|
-
encoding of all states, if requested. The encoding consists of the signal
|
|
26
|
-
of a distribution and its k-t space trajectory.
|
|
21
|
+
return_mag_z: int | bool | None = None,
|
|
22
|
+
) -> torch.Tensor | list:
|
|
23
|
+
"""Calculate the signal of the sequence by executing the phase graph.
|
|
27
24
|
|
|
28
25
|
Parameters
|
|
29
26
|
----------
|
|
@@ -40,11 +37,18 @@ def execute_graph(graph: Graph,
|
|
|
40
37
|
Should be <= than min_emitted_signal.
|
|
41
38
|
print_progress : bool
|
|
42
39
|
If true, the current repetition is printed while simulating.
|
|
40
|
+
return_mag_z : int or bool, optional
|
|
41
|
+
If set, returns the longitudinal magnetisation of either the given
|
|
42
|
+
repetition (int) or all repetitions (``True``).
|
|
43
|
+
|
|
43
44
|
|
|
44
45
|
Returns
|
|
45
46
|
-------
|
|
46
47
|
signal : torch.Tensor
|
|
47
48
|
The simulated signal of the sequence.
|
|
49
|
+
mag_z : torch.Tensor | list[torch.Tensor]
|
|
50
|
+
The longitudinal magnetisation of the specified or all repetition(s).
|
|
51
|
+
|
|
48
52
|
"""
|
|
49
53
|
if seq.normalized_grads:
|
|
50
54
|
grad_scale = 1 / data.size
|
|
@@ -67,6 +71,7 @@ def execute_graph(graph: Graph,
|
|
|
67
71
|
# Calculate kt_vec ourselves for autograd
|
|
68
72
|
graph[0][0].kt_vec = torch.zeros(4, device=data.device)
|
|
69
73
|
|
|
74
|
+
mag_z = []
|
|
70
75
|
for i, (dists, rep) in enumerate(zip(graph[1:], seq)):
|
|
71
76
|
if print_progress:
|
|
72
77
|
print(f"\rCalculating repetition {i+1} / {len(seq)}", end='')
|
|
@@ -129,7 +134,8 @@ def execute_graph(graph: Graph,
|
|
|
129
134
|
# Use the same adc phase for all coils
|
|
130
135
|
adc_rot = torch.exp(1j * rep.adc_phase).unsqueeze(1)
|
|
131
136
|
|
|
132
|
-
|
|
137
|
+
mag_z_rep = []
|
|
138
|
+
mag_z.append(mag_z_rep)
|
|
133
139
|
for dist in dists:
|
|
134
140
|
# Create a list only containing ancestors that were simulated
|
|
135
141
|
ancestors = list(filter(
|
|
@@ -142,6 +148,9 @@ def execute_graph(graph: Graph,
|
|
|
142
148
|
continue # skip dists for which no ancestors were simulated
|
|
143
149
|
|
|
144
150
|
dist.mag = sum([calc_mag(ancestor) for ancestor in ancestors])
|
|
151
|
+
if dist.dist_type in ['z0', 'z'] and return_mag_z in [i, True]:
|
|
152
|
+
mag_z_rep.append(dist.mag)
|
|
153
|
+
|
|
145
154
|
# The pre_pass already calculates kt_vec, but that does not
|
|
146
155
|
# work with autograd -> we need to calculate it with torch
|
|
147
156
|
if dist.dist_type == 'z0':
|
|
@@ -224,6 +233,10 @@ def execute_graph(graph: Graph,
|
|
|
224
233
|
print(" - done")
|
|
225
234
|
|
|
226
235
|
# Only return measured samples
|
|
227
|
-
|
|
236
|
+
measured = torch.cat([
|
|
228
237
|
sig[rep.adc_usage > 0, :] for sig, rep in zip(signal, seq)
|
|
229
238
|
])
|
|
239
|
+
if return_mag_z is not None:
|
|
240
|
+
return measured, mag_z
|
|
241
|
+
else:
|
|
242
|
+
return measured
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
use num_complex::Complex32;
|
|
1
|
+
use num_complex::{Complex32, ComplexFloat};
|
|
2
2
|
use std::cell::RefCell;
|
|
3
3
|
use std::collections::HashMap;
|
|
4
|
-
use std::f32::consts::TAU;
|
|
5
4
|
use std::iter;
|
|
6
5
|
use std::rc::Rc;
|
|
7
6
|
|
|
@@ -42,7 +41,7 @@ pub struct Distribution {
|
|
|
42
41
|
pub regrown_mag: f32, // Don't propagate to ancestors if its the own mag
|
|
43
42
|
pub signal: f32,
|
|
44
43
|
pub emitted_signal: f32, // relative to the strongest dist in the repetition
|
|
45
|
-
pub kt_vec: [
|
|
44
|
+
pub kt_vec: [f64; 4],
|
|
46
45
|
pub dist_type: DistType,
|
|
47
46
|
pub ancestors: Vec<Edge>,
|
|
48
47
|
/// latent_signal metric: if you want to measure states with a minimum signal of x,
|
|
@@ -53,17 +52,17 @@ pub struct Distribution {
|
|
|
53
52
|
impl Distribution {
|
|
54
53
|
fn measure(&mut self, t2dash: f32, nyquist: [f32; 3]) {
|
|
55
54
|
let sigmoid = |x: f32| 1.0 / (1.0 + (-x).exp());
|
|
56
|
-
let tmp = |nyq: f32, k:
|
|
55
|
+
let tmp = |nyq: f32, k: f64| sigmoid((nyq - k.abs() as f32 + 0.5) * 100.0);
|
|
57
56
|
let dephasing = tmp(nyquist[0], self.kt_vec[0])
|
|
58
57
|
* tmp(nyquist[1], self.kt_vec[1])
|
|
59
58
|
* tmp(nyquist[2], self.kt_vec[2]);
|
|
60
59
|
|
|
61
|
-
let norm = |x:
|
|
60
|
+
let norm = |x: f64, y: f64, z: f64| (x * x + y * y + z * z).sqrt() as f32;
|
|
62
61
|
let k_len = norm(self.kt_vec[0], self.kt_vec[1], self.kt_vec[2]);
|
|
63
62
|
|
|
64
63
|
// Empirical signal drop-off is roughly estimated by x^(-2.2)
|
|
65
64
|
self.signal += self.mag.norm()
|
|
66
|
-
* (-(self.kt_vec[3] / t2dash).abs()).exp()
|
|
65
|
+
* (-(self.kt_vec[3] as f32 / t2dash).abs()).exp()
|
|
67
66
|
* (1.0 + k_len).powf(-2.2)
|
|
68
67
|
* dephasing;
|
|
69
68
|
}
|
|
@@ -90,6 +89,20 @@ pub fn comp_graph(
|
|
|
90
89
|
grad_scale: [f32; 3], // scale gradients to SI if they are normalized
|
|
91
90
|
avg_b1_trig: &[[f32; 3]],
|
|
92
91
|
) -> Vec<Vec<RcDist>> {
|
|
92
|
+
// Make precision of state merging dependent on the units used in the seq.
|
|
93
|
+
// For this, we use a fraction of the smallest used step.
|
|
94
|
+
let min_kt_step = [
|
|
95
|
+
seq.iter().flat_map(|r| r.gradm_event.iter().map(|g| g[0].abs() as f64)).filter(|x| *x > 1e-3).min_by(f64::total_cmp),
|
|
96
|
+
seq.iter().flat_map(|r| r.gradm_event.iter().map(|g| g[1].abs() as f64)).filter(|x| *x > 1e-3).min_by(f64::total_cmp),
|
|
97
|
+
seq.iter().flat_map(|r| r.gradm_event.iter().map(|g| g[2].abs() as f64)).filter(|x| *x > 1e-3).min_by(f64::total_cmp),
|
|
98
|
+
seq.iter().flat_map(|r| r.event_time.iter().map(|t| *t as f64)).filter(|x| *x > 1e-6).min_by(f64::total_cmp)
|
|
99
|
+
];
|
|
100
|
+
let inv_kt_grid = [
|
|
101
|
+
1.0 / (0.1 * min_kt_step[0].unwrap_or(1.0)).clamp(1e-6, 1.0),
|
|
102
|
+
1.0 / (0.1 * min_kt_step[1].unwrap_or(1.0)).clamp(1e-6, 1.0),
|
|
103
|
+
1.0 / (0.1 * min_kt_step[2].unwrap_or(1.0)).clamp(1e-6, 1.0),
|
|
104
|
+
1.0 / (0.1 * min_kt_step[3].unwrap_or(1e-3)).clamp(1e-9, 1e-3),
|
|
105
|
+
];
|
|
93
106
|
let mut graph: Vec<Vec<RcDist>> = Vec::new();
|
|
94
107
|
|
|
95
108
|
let mut dists_p = DistVec::new();
|
|
@@ -112,6 +125,7 @@ pub fn comp_graph(
|
|
|
112
125
|
max_dist_count,
|
|
113
126
|
min_dist_mag,
|
|
114
127
|
avg_b1_trig,
|
|
128
|
+
inv_kt_grid
|
|
115
129
|
);
|
|
116
130
|
dists_p = _dists_p;
|
|
117
131
|
dists_z = _dists_z;
|
|
@@ -136,10 +150,10 @@ pub fn comp_graph(
|
|
|
136
150
|
.zip(&rep.adc_mask)
|
|
137
151
|
{
|
|
138
152
|
let k1 = dist.kt_vec;
|
|
139
|
-
dist.kt_vec[0] += gradm[0] * grad_scale[0];
|
|
140
|
-
dist.kt_vec[1] += gradm[1] * grad_scale[1];
|
|
141
|
-
dist.kt_vec[2] += gradm[2] * grad_scale[2];
|
|
142
|
-
dist.kt_vec[3] += dt;
|
|
153
|
+
dist.kt_vec[0] += gradm[0] as f64 * grad_scale[0] as f64;
|
|
154
|
+
dist.kt_vec[1] += gradm[1] as f64 * grad_scale[1] as f64;
|
|
155
|
+
dist.kt_vec[2] += gradm[2] as f64 * grad_scale[2] as f64;
|
|
156
|
+
dist.kt_vec[3] += *dt as f64;
|
|
143
157
|
let k2 = dist.kt_vec;
|
|
144
158
|
|
|
145
159
|
// Integrating (dt omitted) over k²(t) = ((1-x)*k1 + x*k2)^2
|
|
@@ -148,7 +162,8 @@ pub fn comp_graph(
|
|
|
148
162
|
* dt
|
|
149
163
|
* ((k1[0] * k1[0] + k1[0] * k2[0] + k2[0] * k2[0])
|
|
150
164
|
+ (k1[1] * k1[1] + k1[1] * k2[1] + k2[1] * k2[1])
|
|
151
|
-
+ (k1[2] * k1[2] + k1[2] * k2[2] + k2[2] * k2[2]))
|
|
165
|
+
+ (k1[2] * k1[2] + k1[2] * k2[2] + k2[2] * k2[2]))
|
|
166
|
+
as f32;
|
|
152
167
|
|
|
153
168
|
dist.mag *= r2 * (-b * d).exp();
|
|
154
169
|
if *adc {
|
|
@@ -165,7 +180,7 @@ pub fn comp_graph(
|
|
|
165
180
|
let sqr = |x| x * x;
|
|
166
181
|
let k2 = sqr(dist.kt_vec[0]) + sqr(dist.kt_vec[1]) + sqr(dist.kt_vec[2]);
|
|
167
182
|
|
|
168
|
-
dist.mag *= r1 * (-d * rep_time * k2).exp();
|
|
183
|
+
dist.mag *= r1 * (-d * rep_time * k2 as f32).exp();
|
|
169
184
|
}
|
|
170
185
|
// Z0 has no diffusion because it's not dephased
|
|
171
186
|
dist_z0.borrow_mut().mag *= r1;
|
|
@@ -183,22 +198,23 @@ fn apply_pulse(
|
|
|
183
198
|
max_dist_count: usize,
|
|
184
199
|
min_dist_mag: f32,
|
|
185
200
|
avg_b1_trig: &[[f32; 3]],
|
|
201
|
+
inv_kt_grid: [f64; 4],
|
|
186
202
|
) -> (DistVec, DistVec, RcDist) {
|
|
187
203
|
let rot_mat = RotMat::new(rep.pulse_angle, rep.pulse_phase, avg_b1_trig);
|
|
188
204
|
|
|
189
205
|
let mut dist_dict_p: DistMap = HashMap::new();
|
|
190
206
|
let mut dist_dict_z: DistMap = HashMap::new();
|
|
191
207
|
|
|
192
|
-
let mut add_dist = |kt_vec: [
|
|
208
|
+
let mut add_dist = |kt_vec: [f64; 4],
|
|
193
209
|
mag: Complex32,
|
|
194
210
|
rot_mat_factor: Complex32,
|
|
195
211
|
relation: DistRelation,
|
|
196
212
|
ancestor: &RcDist| {
|
|
197
213
|
let key = [
|
|
198
|
-
(kt_vec[0] *
|
|
199
|
-
(kt_vec[1] *
|
|
200
|
-
(kt_vec[2] *
|
|
201
|
-
(kt_vec[3] *
|
|
214
|
+
(kt_vec[0] * inv_kt_grid[0]).round() as i32,
|
|
215
|
+
(kt_vec[1] * inv_kt_grid[1]).round() as i32,
|
|
216
|
+
(kt_vec[2] * inv_kt_grid[2]).round() as i32,
|
|
217
|
+
(kt_vec[3] * inv_kt_grid[3]).round() as i32,
|
|
202
218
|
];
|
|
203
219
|
let dist_type = match relation {
|
|
204
220
|
DistRelation::PP | DistRelation::MP | DistRelation::ZP => DistType::P,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_CS_cartesian_seq.ipynb
RENAMED
|
File without changes
|
{MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_CS_radial_seq.ipynb
RENAMED
|
File without changes
|
{MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_DREAM_STE_seq.ipynb
RENAMED
|
File without changes
|
{MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_DREAM_STID_seq.ipynb
RENAMED
|
File without changes
|
{MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_DWI_GRE_2D_seq.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/mr0_pypulseq_exmpls_seq.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
{MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/documentation/playground_mr0/numerical_brain_cropped.mat
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/phantom/brainweb/brainweb_data_sources.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/pulseq_file/adc.py
RENAMED
|
File without changes
|
{MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/pulseq_file/block.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/pulseq_file/rf.py
RENAMED
|
File without changes
|
{MRzeroCore-0.2.10 → MRzeroCore-0.2.12}/python/MRzeroCore/pulseq/pulseq_loader/pulseq_file/trap.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|