linop.LinearOperator#
- class bartorch.linop.LinearOperator#
Bases:
OperatorA linear map between two C-order shapes, with an adjoint.
A subclass is defined either by
_create(), which builds one of BART’s operators, or in Python byforward()andadjoint(), andnormal()where a cheaper form exists. BART reaches a Python-defined operator through callbacks, one crossing into Python per application.Both kinds compose into a single BART operator, are solved by
bartorch.optim, and differentiate in torch. The backward pass ofA(x)isA.adjoint, which for complex tensors is the conjugate Wirtinger gradient torch expects, not the transpose.- ishape, oshape
Domain and codomain, C order.
- Type:
tuple of int
- device#
Where the operator does its arithmetic, when that is not where its operands are.
- Type:
torch.device or None
Examples
An operator defined in Python, composed with a BART operator into one:
>>> class Phase(linop.LinearOperator): ... def __init__(self, phase): ... self.phase = phase ... self.ishape = self.oshape = tuple(phase.shape) ... super().__init__() ... def forward(self, x, out=None): ... return x * self.phase ... def adjoint(self, y, out=None): ... return y * self.phase.conj() >>> A = linop.FFT((64, 64), axes=(-1, -2)) @ Phase(torch.exp(1j * torch.rand(64, 64))) >>> y = A(x) # recorded for autograd when x requires a gradient >>> z = A.H(y) # the adjoint; A.gram() is the normal operator A^H A
- forward()#
Apply
A xwithout recording for autograd.- Parameters:
x (tensor, shape ishape) – Input.
out (tensor, shape oshape, default=None) – Written in place when given. For a BART-backed operator, a contiguous complex64 tensor on the input’s device.
- Returns:
outwhen given.- Return type:
tensor, shape oshape
- adjoint()#
Apply
A^H ywithout recording for autograd.- Parameters:
y (tensor, shape oshape) – Input.
out (tensor, shape ishape, default=None) – Written in place when given, as for
forward().
- Return type:
tensor, shape ishape
- normal()#
Apply
A^H A x.A BART-backed operator applies BART’s normal, which for an encoding built with
toeplitz=Trueis a convolution with a point spread function; a Python-defined one computesadjoint(forward(x)).- Parameters:
x (tensor, shape ishape) – Input.
out (tensor, shape ishape, default=None) – Written in place when given, as for
forward().
- Return type:
tensor, shape ishape
- classmethod from_callbacks()#
Build a BART operator from Python functions.
Each function receives a view of BART’s buffer, without a copy, and returns a tensor; every application calls back into Python.
- Parameters:
oshape (tuple of int) – Codomain and domain, C order.
ishape (tuple of int) – Codomain and domain, C order.
forward (callable) –
x -> A x, fromishapetooshape.adjoint (callable) –
y -> A^H y, fromoshapetoishape.normal (callable, default=None) –
x -> A^H A xin one function;Nonechainsadjointontoforward.
- Return type:
- property plan#
The encoding form this operator was lowered into, or
None.An MRI encoding reports the transform, the element-wise factors on each side of it, the contraction, what is streamed, how the normal is applied and which executor built it. A composition containing exactly one encoding reports that encoding’s plan; any other operator has none.
plan.fusedis false where the coil-slab loop could not take the form or a sum of terms was left as a chain: the same result, computed more slowly.plan.executoris read back from the library after the build. Reading the property on a composition builds it.- Return type:
bartorch.linop._form.Plan or None
Examples
>>> A = linop.CartesianSense(maps, (64, 64), pattern=mask) >>> A.plan.transform, A.plan.normal, A.plan.executor ('fft', 'kernel', 'slab') >>> A.plan.fused True
- property H#
A^H, from BART’s adjoint constructor.The result is a BART operator:
A.H @ Bis one operator, and the normal ofA.HisA A^H.
- property T#
A^T, the adjoint without the conjugation, asconj(A).H.
- conj()#
conj(A): conjugate the input, apply, conjugate the output.
- gram()#
A^H Aas an operator.BART’s normal: for an encoding built with
toeplitz=True, the convolution with a point spread function.
- cogram()#
A A^Has an operator.
- opnorm()#
Estimate the spectral norm by BART’s power iteration on
A^H A.The starting vector comes from BART’s process-global generator, so repeated calls differ slightly. Accurate enough for a step size or a Lipschitz constant, not an exact singular value.
- Return type:
float
- Raises:
BartError – When the power iteration does not converge.
- __call__()#
Apply
A x, recorded for autograd whenxrequires a gradient.The backward pass applies
adjoint().- Parameters:
x (tensor, shape ishape) – Input.
out (tensor, shape oshape, default=None) – Contiguous complex64 tensor written in place.
- Return type:
tensor, shape oshape
- Raises:
ValueError – When
outis given andxrequires a gradient.
- property dim_shape#
The domain, under pyxu’s name for it; the same as
ishape.
- property codim_shape#
The codomain, under pyxu’s name for it; the same as
oshape.
- property dim_size#
Number of elements in the domain.
- property codim_size#
Number of elements in the codomain.
- property dim_rank#
Number of axes of the domain.
- property codim_rank#
Number of axes of the codomain.
- to_nonlinear()#
The same operator as a
NonlinearOperator.
- pinv()#
Solve
(A^H A + damp I) x = A^H y, the damped least-squares problem.ScaledSumis solved by BART’s closed-form pseudo-inverse; every other operator, including compositions, byCG.- Parameters:
y (tensor, shape oshape) – Data.
damp (float, default=0.0) – Tikhonov weight,
CG’slambda_.**kwargs – Passed to
CG;x0is the warm start.
- Return type:
tensor, shape ishape
- Raises:
TypeError – When
kwargsare given and the closed form applies.
Notes
BART attaches a closed form (
norm_inv) only inlinops/sum.c, and it is correct forlinop_scaled_sumalone: for the plain sum it solves a differently scaled problem.Sumtherefore takes the solver.