linop.NoncartesianSense

linop.NoncartesianSense#

class bartorch.linop.NoncartesianSense#

Bases: LinearOperator

Non-Cartesian SENSE encoding operator.

\[A = W \, \mathrm{NUFFT} \, S\]

with \(S\) the coil sensitivities, \(\mathrm{NUFFT}\) the type-2 non-uniform Fourier transform along traj (as NUFFT) and \(W\) the k-space weighting weights, conjugated on the adjoint. With a subspace basis the image holds coefficients, which the basis maps to frames on the k-space side of the transform. Coils are processed coil_batch at a time, so memory, including the doubled grid of the Toeplitz normal, scales with coil_batch rather than the coil count. Without traj the transform is the centred unitary FFT, which is CartesianSense()’s form.

Parameters:
  • sensitivities (tensor) – Coil sensitivities ([batch, sets,] coils, [z,] y, x), or k-space kernels with kernels=True. The image carries sets, summed as y[c] = sum_m S[m, c] x[m]; both image and samples carry batch, which is written with its sets axis even for one set.

  • image_shape (tuple of int) – (*batches, [batch,] [sets,] *encoding, [z,] y, x); with a basis, the last encoding axis holds the coefficients.

  • traj (tensor, default=None) – Trajectory (*encoding, shots, samples, ndim) in grid units (kx, ky[, kz]), as bartorch.tools.traj() returns, shared across all batch axes. Required unless built through CartesianSense().

  • kspace_shape (tuple of int, default=None) – Sample shape, which must be (*batches, [batch,] coils, *encoding, shots, samples), or (*batches, [batch,] coils, *encoding, [z,] y, x) on a grid; None takes it.

  • kernels (bool, default=False) – Read sensitivities as k-space kernels; the maps applied are then band-limited to the kernel support. See bartorch.maps_to_kernels() and bartorch.kernels_to_maps().

  • toeplitz (bool, default=True) – Apply the normal as a convolution with a point spread function rather than as the forward and adjoint transforms.

  • modulated (bool, default=False) – On a grid, use BART’s uncentred sample convention (an fftmod on the sample axes) instead of the centred one bartorch.fft() produces. Rejected with traj and with kernels.

  • weights (tensor, default=None) – k-space weighting, broadcast over (*encoding, shots, samples).

  • basis (tensor, default=None) – Temporal subspace basis (coeffs, frames) over the last encoding axis.

  • device (torch.device or str, default=None) – Device the operator is built and computes on; None takes the trajectory’s, or the sensitivities’ on a grid.

  • coil_batch (int, default=1) – Coils per slab; 0 applies all coils at once as BART’s own chain, which is refused with encoding axes. A value that does not divide the coil count is reduced to the largest divisor of the coil count below it. Changes memory and speed, not the result.

  • fold_maps (bool, default=True) – Apply the sensitivities inside the normal’s transform where it works one coefficient at a time, saving two coil images per slab.

  • ndim (int, default=None) – Number of spatial axes (2 or 3) where the trajectory, the sensitivities and the image do not determine it.

Raises:

ValueError – When the arguments are inconsistent with each other or with the layouts above.

Notes

A stack of shots on the image’s z grid – blocks at whole kz = j - z // 2 with the same in-plane trajectory and weights – is applied as an FFT along z over two-dimensional transforms when coil_batch=1 and there is one set; plan.cartesian reports it. Encoding axes the image also carries (no basis contracting them) become items, each with its own transform and normal kernel under one coil loop; plan.items reports them.

With the operator on a card, image, samples and sensitivities may stay on the host: the image crosses once each way per application, the samples and sensitivities a slab at a time, and between applications the card holds only the operator.

Examples

>>> traj = bartorch.tools.traj(readout=64, spokes=64, radial=True, golden=True)
>>> A = NoncartesianSense(maps, (64, 64), traj=traj)        # maps (4, 64, 64)
>>> A.oshape                                                # (coils, spokes, readout)
(4, 64, 64)
>>> A.plan.normal                                           # A^H A as a convolution
'kernel'
>>> x = bartorch.optim.CG(lambda_=0.01, maxiter=20)(kspace, A)

Also has the methods and properties of LinearOperator.

Examples using NoncartesianSense#

8. Radial SENSE

8. Radial SENSE

Off-resonance correction of spiral imaging

Off-resonance correction of spiral imaging

Dynamic golden-angle radial MRI

Dynamic golden-angle radial MRI

Subspace-constrained T1 mapping

Subspace-constrained T1 mapping