Source code for mrinufft.extras.data
"""Data generator module."""
import numpy as np
from collections.abc import Sequence
[docs]
def get_brainweb_map(sub_id: int) -> np.ndarray:
"""
Get M0, T1 and T2 parametric maps from a brainweb crisp segmentation.
Output maps have the same shape as the tissue segmentation.
Parameters
----------
sub_id : int
Subject ID.
Raises
------
ImportError
If brainweb-dl is not installed.
Returns
-------
M0 : np.ndarray
Proton Density map. For sub_id > 0,
it is a binary mask.
T1 : np.ndarray
T1 map map in [ms].
T2 : np.ndarray
T2 map map in [ms].
"""
try:
import brainweb_dl
except ImportError as err:
raise ImportError(
"The brainweb-dl module is not available. Please install it using "
"the following command: pip install brainweb-dl"
) from err
# get segmentation
segmentation = brainweb_dl.get_mri(sub_id, "crisp") / 455
segmentation = segmentation.astype(int)
# get properties
model = brainweb_dl._brainweb.BrainWebTissueMap
if sub_id == 0:
properties = brainweb_dl._brainweb._load_tissue_map(model.v1)
else:
properties = brainweb_dl._brainweb._load_tissue_map(model.v2)
# initialize maps
if sub_id == 0:
M0 = np.zeros_like(segmentation, dtype=np.float32)
T1 = np.zeros_like(segmentation, dtype=np.float32)
T2 = np.zeros_like(segmentation, dtype=np.float32)
# fill maps
for tissue in properties:
idx = segmentation == int(tissue["Label"])
if sub_id == 0:
M0 += float(tissue["PD (ms)"]) * idx
T1 += float(tissue["T1 (ms)"]) * idx
T2 += float(tissue["T2 (ms)"]) * idx
if sub_id != 0:
M0 = (segmentation != 0).astype(np.float32)
# pad to square
pad_width = segmentation.shape[1] - segmentation.shape[2]
pad = ((0, 0), (0, 0), (int(pad_width // 2), int(pad_width // 2)))
M0 = np.pad(M0, pad)
T1 = np.pad(T1, pad)
T2 = np.pad(T2, pad)
return M0, T1, T2
[docs]
def fse_simulation(
M0: np.ndarray,
T1: np.ndarray,
T2: np.ndarray,
TE: float | Sequence[float],
TR: float | Sequence[float],
) -> np.ndarray:
"""Perform simple analytical Fast Spin Echo simulation.
Assume that refocusing angles are 180° and
k-space center is sampled for each echo in the Echo Train
(e.g., as in spiral or radial imaging).
Parameters
----------
M0 : np.ndarray
Input equilibrium magnetization.
T1 : np.ndarray
Input T1 in [ms].
T2 : np.ndarray
Input T2 in [ms].
TE : float | Sequence[float]
Sequence Echo Time in [ms].
TR : float | Sequence[float]
Sequence Repetition Time in [ms].
Returns
-------
signal : np.ndarray
Simulated signal of shape (nTE*nTR, *M0).
"""
# preprocess sequence parameters
TE, TR = np.broadcast_arrays(np.atleast_1d(TE), np.atleast_1d(TR)[:, None])
TE, TR = TE.ravel().astype(np.float32), TR.ravel().astype(np.float32)
# preprocess tissue parameters
M0, T1, T2 = np.atleast_1d(M0), np.atleast_1d(T1), np.atleast_1d(T2)
M0, T1, T2 = M0[..., None], T1[..., None], T2[..., None]
T1 += 1e-9
T2 += 1e-9
# compute signal
signal = M0 * (1 - np.exp(-(TR - TE) / T1)) * np.exp(-TE / T2)
# post process
signal = signal[None, ...].swapaxes(0, -1)[..., 0]
signal = signal.squeeze()
if signal.size == 1:
signal = signal.item()
return signal