bartorch.nlop.NonlinearSense

bartorch.nlop.NonlinearSense#

class bartorch.nlop.NonlinearSense(image_shape, pattern=None, trajectory=None, *, kspace_shape=None, coil_shape=None, coefficient_shape=None, weights=None, basis=None, mask=None, sobolev=(220.0, 32.0), c=1.0, real=False, sos=False, oversampling_coils=None, oversampled_coils=False, toeplitz=True, optimized=False)#

BART’s noir model: the image and the coil profiles fitted together.

The operator takes two inputs – the image, and the coils as k-space coefficients – and returns data. Its Jacobian by either one is a linear operator (jacobian()), which is what a Gauss-Newton step solves over.

The coils are unknown as coefficients, not as maps: BART carries the Sobolev weighting (1 + a |k|^2)^(-b/2) that keeps them smooth inside the model, so the quantity being fitted is already regularised. coils is the operator that turns fitted coefficients into sensitivities.

Off the grid the model is asymmetric, as BART builds it: it returns gridded coil images rather than samples, so a measurement has to be gridded to match. prepare() does that, and does nothing on a grid, where the model returns k-space directly.

Parameters:
  • image_shape (tuple of int) – Coil-image shape, (coils, *spatial), C order – the same shape the linear encodings take. The image itself is this with one coil.

  • pattern (tensor, optional) – On a grid: ones where a sample was taken, zeros where it was not. Without one the acquisition is taken to be fully sampled, which is what nlinv estimates from a complete measurement.

  • trajectory (tensor, optional) – Off the grid: the trajectory, (..., samples, 3) in grid units, as bartorch.linop.NUFFT takes it. Giving one makes the non-Cartesian model.

  • kspace_shape (tuple of int, optional) – Sample shape. Off the grid it defaults to the trajectory’s with the image’s coil axes in front, as the NUFFT’s does; on the grid it is the coil-image shape.

  • coil_shape (tuple of int, optional) – Where the sensitivities live and where their coefficients do; both default to the coil-image shape.

  • coefficient_shape (tuple of int, optional) – Where the sensitivities live and where their coefficients do; both default to the coil-image shape.

  • weights (tensor, optional) – Density compensation, off the grid.

  • basis (tensor, optional) – Temporal subspace basis, off the grid. BART’s Cartesian model refuses one.

  • mask (tensor, optional) – A support the image is restricted to – nlinv’s restrict-fov.

  • sobolev (tuple of float) – (a, b) of the coil weighting, BART’s 220, 32.

  • c (float) – The exponent’s scaling, BART’s 1.

  • real (bool) – Constrain the image to be real, nlinv -g’s rvc.

  • sos (bool) – BART’s sum-of-squares variant of the coil weighting.

  • oversampling_coils (float, optional) – Fit the coils on a finer grid than the image. By default whichever nlinv uses: two off the grid, one on it.

  • oversampled_coils (bool) – Return them on that grid rather than on the image’s.

  • toeplitz (bool) – Off the grid, apply the NUFFT’s normal as a convolution.

  • optimized (bool) – BART’s noir2_noncart_optimized_create, off the grid.

Examples

>>> F = NonlinearSense((8, 128, 128), pattern=mask)
>>> F.ishapes
((1, 128, 128), (8, 128, 128))
>>> image, coefficients = optim.IRGNM()(F.prepare(kspace), F.flatten(), ...)
__init__(image_shape, pattern=None, trajectory=None, *, kspace_shape=None, coil_shape=None, coefficient_shape=None, weights=None, basis=None, mask=None, sobolev=(220.0, 32.0), c=1.0, real=False, sos=False, oversampling_coils=None, oversampled_coils=False, toeplitz=True, optimized=False)#

Methods

__init__(image_shape[, pattern, trajectory, ...])

adjoint(dy)

DF(x)^H dy at the last evaluated point, for one input and one output.

chain(other, *[, output, input])

Output output of self into input input of other.

combine(other)

self and other side by side, sharing nothing.

del_out([output])

Drop an output, and everything computed only for it.

derivative(dx)

DF(x) dx at the last evaluated point, for one input and one output.

dup([a, b])

Make two inputs of the same shape one input, kept at a.

flatten([inputs_only])

Every input as one flat vector, and every output as another.

forward(*xs)

F(x), which also fixes where every derivative is taken.

jacobian([output, input])

DF/dx_input of one output, as a LinearOperator.

linearize(*xs)

The derivative at x, as a LinearOperator.

link([output, input])

Tie an output back into an input; both arguments go away.

permute_inputs(perm)

Reorder the inputs: the new input i is the old perm[i].

permute_outputs(perm)

Reorder the outputs: the new output o is the old perm[o].

pin(input, value)

Fix one input to value; the input goes away.

prepare(kspace)

The measurement in the shape the model returns.

reshape_input(input, shape)

This operator with one input's shape written differently.

reshape_output(output, shape)

This operator with one output's shape written differently.

shift_input(new, old)

Move one input to another position, the rest closing up behind it.

shift_output(new, old)

Move one output to another position, the rest closing up behind it.

stack_inputs(a, b, axis)

Make two inputs one, concatenated along a C-order axis.

stack_outputs(a, b, axis)

Make two outputs one, concatenated along a C-order axis.

Attributes

coils

the Sobolev weighting and the transform.

data

From what the model returns to the measurement.

device

image

The image's own linear part -- the mask, and the real constraint if asked for.

ishape

The domain, for an operator with one input.

ishapes

The shape of each argument, outputs and inputs kept apart.

oshape

The codomain, for an operator with one output.

oshapes

transform

The transform from coil images to k-space, without the model in front of it.