linop.NoncartesianSense#
- class bartorch.linop.NoncartesianSense#
Bases:
LinearOperatorNon-Cartesian SENSE encoding operator.
The forward model is
\[A = W \, \mathrm{NUFFT} \, S\]with \(S\) multiplication by the coil sensitivities, \(\mathrm{NUFFT}\) the type-2 non-uniform Fourier transform along
traj, and \(W\) the diagonal density weighting given byweights, the identity when none is given. The transform carries the weighting itself, applying it on the forward pass and its conjugate on the adjoint, because the Toeplitz normal is built over it.With a temporal basis the optimization variable holds subspace coefficients, which the basis maps to the acquired frames on the k-space side of the transform, as for
CartesianSense().Coils are processed
coil_batchat a time, so memory held – including the doubled grid the Toeplitz normal convolves on – scales withcoil_batchrather than with the number of coils.For Cartesian sampling use
CartesianSense(), which is this operator over an FFT.- Parameters:
sensitivities (tensor) – Coil sensitivities
([batch, sets,] coils, [z,] y, x), or their k-space kernels withkernels=True. The image carries the sets and the samples do not, so several sets encode asy[c] = sum_m S[m, c] x[m]; a batch is carried by both.image_shape (tuple of int) – Image shape
(*batches, [batch,] [sets,] *encoding, [z,] y, x): the batches, then the axis the sensitivities vary along and their sets, then the trajectory’s encoding axes – with a basis, its coefficients in place of the last – then the spatial axes.traj (tensor, default=None) – Trajectory
(*encoding, shots, samples, ndim)in grid units,kx, kyorkx, ky, kz, asbartorch.tools.traj()produces. It carries no batch axis, being shared across the batch.kspace_shape (tuple of int, default=None) – Sample shape; by default
(*batches, coils, *encoding, shots, samples), and on a grid(*batches, coils, *encoding, [z,] y, x).kernels (bool, default=False) – Read
sensitivitiesas k-space kernels rather than maps. The operator then applies the maps band-limited to the kernel;bartorch.maps_to_kernels()andbartorch.kernels_to_maps()convert between the two.toeplitz (bool, default=True) – Apply the normal in closed form rather than as the forward and adjoint applications: a convolution with a point spread function.
modulated (bool, default=False) – On a grid, answer in BART’s uncentred sample convention rather than the centred one. The two differ by an
fftmodon the sample axes; the centred convention is the default and is the onebartorch.fft()produces. Rejected off a grid, where there is only one convention, and withkernels, the modulation belonging to the whole grid.weights (tensor, default=None) – Diagonal in k-space, broadcast over
(*encoding, shots, samples), applied on the forward pass and conjugated on the adjoint.basis (tensor, default=None) – Temporal subspace basis
(coeffs, frames)over the last encoding axis.device (device, default=None) – Where the operator is built and does its arithmetic; by default where the trajectory is, or the sensitivities on a grid.
coil_batch (int, default=1) – Coils applied at once; 0 applies every coil together. A batch that does not divide the coils is reduced to one that does. It changes residency and speed, not the result.
fold_maps (bool, default=True) – Apply the sensitivities inside the normal’s transform, saving two coil images per slab. Takes effect only where the transform works one coefficient at a time.
ndim (int, default=None) – Number of spatial axes, where the sensitivities and the image do not determine it; off a grid the trajectory does.
Notes
A trajectory lying on the image’s own z grid –
zblocks of shots atkz = j - z // 2, each with the same in-plane trajectory and weights – is applied as an FFT along z over two-dimensional transforms, givencoil_batch=1and one set;plan.cartesianreports it. Encoding axes the image also carries become items, each with its own trajectory and normal kernel under one coil loop, whichplan.itemsreports.With the operator on a card its operands may stay on the host: the image crosses once each way per application, the samples and a kernel bank a slab at a time, and between applications the card holds the operator alone.
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.