deepmr.rosette_stack#
- deepmr.rosette_stack(shape, nviews=None, accel=1, bending_factor=1.0, **kwargs)[source]#
Design a stack-of-rosettes trajectory.
As in the 2D rosette case, petals are rotated by a pseudo golden angle with period 377 interelaves. Rotations are performed both along
view
andcontrast
dimensions. Acquisition is assumed to traverse thecontrast
dimension first and then theview
, i.e., all the contrasts are acquired before moving to the second view. If multiple echoes are specified, final contrast dimensions will have lengthncontrasts * nechoes
.- Parameters:
shape (Iterable[int]) – Matrix shape
(in-plane, slices=1, contrasts=1, echoes=1)
.nviews (int, optional) – Number of spokes. The default is
$\pi$ * shape[0]
ifshape[1] == 1
, otherwise it is1
.accel (int, optional) – Slice acceleration factor. Ranges from
1
(fully sampled) tonslices
. The default is1
.bending_factor (float, optional) – This is
0.0
for radial-like trajectory; increase for maximum coverage per shot. In real world, must account for hardware and safety limitations. The default is1.0
.
- Keyword Arguments:
acs_shape (int) – Matrix size for inner (coil sensitivity estimation) region along slice encoding direction. The default is
None
.- Returns:
head – Acquisition header corresponding to the generated sampling pattern.
- Return type:
Header
Example
>>> import deepmr
We can create a Nyquist-sampled stack-of-rosettes trajectory for a
(128, 128, 120)
voxels matrix by:>>> head = deepmr.rosette_stack((128, 120))
An undersampled trajectory can be generated by specifying the
nviews
argument:>>> head = deepmr.rosette_stack((128, 120), nviews=64)
Slice acceleration can be specified using the
accel
argument. For example, the following>>> head = deepmr.rosette_stack((128, 120), accel=2)
will generate the following trajectory:
>>> head.traj.shape torch.Size([1, 24120, 128, 3])
i.e., a Nyquist-sampled stack-of-rosettes trajectory with a slice acceleration of 2 (i.e., 60 encodings).
Parallel imaging calibration region can be specified using
acs_shape
argument:>>> head = deepmr.rosette_stack((128, 120), accel=2, acs_shape=32)
The generated stack will have an inner
32
-wide fully sampled k-space region.Petals bending can be modified via
bending_factor
:>>> head = deepmr.rosette_stack(128, bending_factor=1.0) # radial-like trajectory
Multiple contrasts with different sampling (e.g., for MR Fingerprinting) can be achieved by providing a tuple of ints as the
shape
argument:>>> head = deepmr.rosette_stack((128, 120, 420)) >>> head.traj.shape torch.Size([420, 120, 128, 3])
corresponding to 420 different contrasts, each sampled with a single petal of 128 points, repeated for 120 slice encodings. Similarly, multiple echoes (with fixed sampling) can be specified as:
>>> head = deepmr.rosette_stack((128, 120, 1, 8)) >>> head.traj.shape torch.Size([8, 48240, 128, 3])
corresponding to a 8-echoes fully sampled k-spaces, e.g., for QSM and T2* mapping.
Notes
The returned
head
(deepmr.Header()
) is a structure with the following fields:- shape (torch.Tensor):
This is the expected image size of shape
(nz, ny, nx)
.
- t (torch.Tensor):
This is the readout sampling time
(0, t_read)
inms
. with shape(nsamples,)
.
- traj (torch.Tensor):
This is the k-space trajectory normalized as
(-0.5 * shape, 0.5 * shape)
with shape(ncontrasts, nviews, nsamples, 2)
.
- dcf (torch.Tensor):
This is the k-space sampling density compensation factor with shape
(ncontrasts, nviews, nsamples)
.
- TE (torch.Tensor):
This is the Echo Times array.