nlop.NonlinearOperator#

class bartorch.nlop.NonlinearOperator#

Bases: Operator

Nonlinear operator between tensor shapes, with a derivative and its adjoint.

F(x) applies the operator and, for a tensor that requires a gradient, records the application; the backward pass is the adjoint of the derivative at x. a @ b composes, applying b first, and either side may be a LinearOperator. partial() fixes one input to a value, and linearize() gives the derivative at a point as a linear operator.

An operator may take more than one input and return more than one output; ishapes and oshapes are the shape of each, and ishape and oshape are the whole of it when there is one of each. An operator is defined in Python by from_callbacks() or by TorchOperator.

ishapes, oshapes

The shape of each input and of each output, C order.

Type:

tuple of tuple of int

ishape, oshape

Domain and codomain, for an operator with one input and one output.

Type:

tuple of int

Examples

>>> M = nlop.MultiEcho([10.0, 20.0, 40.0], (64, 64))    # echo times in ms
>>> theta = M.initial(T2=80.0)
>>> M(theta).shape
torch.Size([3, 64, 64])
>>> D = M.linearize(theta)            # the derivative at theta, a LinearOperator
>>> E = linop.FFT(M.oshape, axes=(-1, -2)) @ M    # still a NonlinearOperator
property ishape#

The domain, for an operator with one input.

property oshape#

The codomain, for an operator with one output.

forward()#

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

Takes one tensor per input and returns one per output, or the tensor itself when there is a single output.

classmethod from_callbacks()#

An operator from Python functions, applied through BART.

forward fixes the point derivative and adjoint are taken at, until the next forward. A sequence of shapes makes that many outputs or inputs; then forward(*xs) returns one tensor per output, and derivative(o, i, dx) and adjoint(o, i, dy) take output o by input i.

linearize()#

The derivative at x, as a LinearOperator.

xs is one tensor per input. input selects the input the derivative is taken by, the others held at their values; None takes it by all of them laid end to end, as a Gauss-Newton step does, and the result’s domain is then one vector. output selects the output.

The result holds x: it answers the same whatever is evaluated afterwards, and is differentiable by x. An operator that does not supply its derivative as a function of the point answers at the last evaluated point instead.

__call__()#

F(x), recorded for autograd when an input requires a gradient.

partial()#

Fix one input to value; the input goes away.

nlop_set_input_const. What a model’s fixed quantities are – an echo time, a sampling pattern – once the operator that takes them has been built. BART copies the tensor, so the one passed in is free afterwards.