Every concrete transformation stores its parameter as one array, data,
together with the encoding flags that say what that array holds. What a
transformation means is read through named, read-only views, which are
always the map, as values, whatever the flags:
| Class | data holds |
Flags | Views |
|---|---|---|---|
DisplacementField |
the values, or their spline coefficients | coeff, degree, bound, log |
field |
CoordinatesField |
the values, or their spline coefficients | coeff, degree, bound |
field |
Affine |
the (No, Ni + 1) matrix |
log |
matrix, homogeneous_matrix |
Linear, Rotation |
the (No, Ni) matrix |
log |
matrix |
Scaling |
the scaling factors | log |
scale |
Translation |
the translation vector | translation |
|
Permutation |
the permutation vector | permutation |
|
CartesianField |
the grid, derived from shape |
coeff, degree, bound |
field |
Identity |
nothing: always None |
A field whose coeff flag is set stores the coefficients of the spline
of degree degree (with boundary condition bound) that interpolates
its values. Its field view decodes them, once, and caches the result
on the instance, so code that reads a field never has to know how it is
stored. Any other encoding is reached by conversion, never by a view:
the coefficients of a field are t.to(coeff=True).data, and its values
are t.field (or t.to(coeff=False).data).
A CartesianField stores its shape rather than an array, and derives
its data from it, encoded under its flags. A lazy inverse, such as an
InverseDisplacementField, derives its data from the transformation
it inverts, in that transformation's encoding.
Inverting a field is approximate
The inverse of a displacement or coordinates field is computed from
the field's values at its grid nodes only: they define a
piecewise-affine map, which is inverted exactly (Ashburner's mesh
inversion), and the result is interpolated with the field's
degree. A field of degree 3 is therefore inverted as its
piecewise-linear interpolant, about as accurately as a field of
degree 1. On smooth fields of a few voxels' amplitude,
fwd(inv(x)) - x is typically a few hundredths of a voxel in the
interior and a few tenths near the border.
A StationaryVelocityField is the exception: its inverse is
exp(-v), exact in the tangent, and integrated as accurately as the
field itself; no mesh is inverted.
Constructors take data (positionally, as the first argument) and the
flags. The view's name is also a keyword, a convenience meaning "the
map, as values". One rule holds everywhere: a convenience keyword is the
map, as values, and the flags describe how it is stored.
DisplacementField(u) # u is displacement values
DisplacementField(field=u) # the same
DisplacementField(data=c, degree=3, coeff=True) # c is coefficients
DisplacementField(field=u, degree=3, coeff=True) # stores u's coefficients
Affine(m), Affine(data=m), Affine(matrix=m) # the same affine, thrice
So DisplacementField(field=u, degree=3, coeff=True) holds the same
data as DisplacementField(field=u, degree=3).to(coeff=True): the
constructor encodes u the way .to(...) does. A convenience keyword
cannot be combined with data=, which already is the stored array.
data and the flags can be assigned in place (t.data = d,
t.coeff = True, t.steps = 6). A cached view (field, or the
matrix and scale of a tangent) is cleared when they are, so the next
read reflects them. log selects the class, which an assignment cannot
change: a class that holds the map refuses log = True. Such an assignment stores what it
is given: t.coeff = True says that the array already in data holds
coefficients, and reinterprets it. To change the map of an existing
transformation, or how it is stored, use .to(...). Within
a type, it re-encodes rather than reinterprets: t.to(field=u) stores
u in the encoding of t, t.to(coeff=True) fits coefficients to the
values, and t.to(degree=3) on a field of coefficients refits them.
Passing data= to .to(...) stores the array as given, under the flags
of the result. bagof.magic.replace is not the way to do it: it carries
data over, so a convenience keyword passed through it (as in
replace(t, field=u)) meets that data and raises whenever t has
one, and a flag passed
through it (as in replace(t, coeff=True)) reinterprets the stored
array instead of re-encoding it.
Transformations compare, and hash, by identity: a == b is a is b,
so two distinct transformations are never equal, whatever their data
and flags (see Comparing transformations and
images).
The same map stored as values and as coefficients is two different
objects either way. To test whether two transformations are the same
map, use is_identity((a.inverse() @ b).compute(), compute=True); to
compare how they are stored, compare their data and flags explicitly.
Tangents: the log flag
The log flag says which function data describes: the map itself, or
its tangent about the identity, whose exponential is the map. A tangent
is always about the identity, so unset or zero data is the identity
whatever the flag. log=True builds a subclass whose views read data
as a tangent:
| Class | data holds, with log=True |
Views |
|---|---|---|
StationaryVelocityField(DisplacementField) |
the velocity: values, or coefficients | field: the displacement of its flow at time one |
AffineExponential(Affine) |
the (N, N + 1) tangent [L, l] |
matrix: expm([[L, l], [0, ..., 0]])[:-1] |
LinearExponential(Linear) |
the (N, N) tangent L |
matrix: expm(L) |
RotationExponential(Rotation) |
the antisymmetric (N, N) tangent L |
matrix: expm(L) |
ScalingExponential(Scaling) |
the logarithms s of the factors |
scale: exp(s) |
So DisplacementField(data=v, log=True) and
StationaryVelocityField(data=v) are one object, and so are
Affine(data=L, log=True) and AffineExponential(data=L). A tangent is
never a matrix: LinearExponential(data=I) is the scaling by e, not
the identity. Translation, Permutation, CoordinatesField,
CartesianField and Identity take no log flag. A convenience
keyword is still the map: Affine(matrix=M, log=True) stores the
principal logarithm of M, while DisplacementField(field=u, log=True)
raises, since a field has no logarithm that brainhops computes.
A field has the two flags, which combine; data is decoded from
coefficients first, and integrated second:
log |
coeff |
data holds |
|---|---|---|
False |
False |
the displacement, as values |
False |
True |
the displacement's spline coefficients |
True |
False |
the velocity, as values |
True |
True |
the velocity's spline coefficients (NiftyReg -vel -cpp) |
The field view of a StationaryVelocityField is always the
displacement, as values. The velocity is integrated by scaling and
squaring: it is divided by 2 ** steps, which is its own flow to first
order, and composed with itself steps times. steps exists only on a
StationaryVelocityField; left None, it is the smallest number for
which the first step moves no point by more than an eighth of a voxel.
A velocity of coefficients is refitted at each step. Any other encoding
is reached by conversion: the velocity's coefficients are
t.to(coeff=True).data, and its displacement is t.to(log=False).
The encoding changes with .to(log=...):
.to(log=True)takes the principal logarithm of a matrix (of the scaling factors), and raisesDomainErrorwhen it has an eigenvalue on the closed negative real axis (a factor that is not positive). A field has no logarithm that brainhops computes: it raisesNotImplementedError, unless the field is unset..to(log=False)builds the base class (Affine,DisplacementField, ...) from the exponential: the matrix, or the integrated displacement, which keeps itscoeff,degreeandbound.- The flags combine:
.to(coeff=False)on a velocity decodes its coefficients and keepslog, and.to(log=False)keepscoeff. - A
SubspaceTransformationconverts its inner transformation (the axes it does not act on are the identity, whose tangent is zero). - A
Sequenceconverts the transformation it reduces to: a chain that simplifies to one transformation; the middle of a change of coordinates[P, *X, P^-1], whose ends are kept (the flow commutes with them, so a velocity read between a world-to-voxel affine and its inverse becomes its displacement exactly); or the affine a chain of affines composes to. Any other chain is refused before anything is computed.
A tangent makes some operations exact: inverse() is a lazy Inverse
whose data is the negated tangent, which still cancels against its
forward in a Sequence; sqrt() halves the tangent (a velocity
integrates with one squaring fewer), and square() doubles it.
brainhops.datamodel.transformations
Attributes
is_kind
module-attribute
Public membership predicate, that dispatches on its input types.
ModeLike
module-attribute
Possible input to the mode argument of [compute()][].
UNARY_OPERATORS
module-attribute
UNARY_OPERATORS: Mapping[
str, Callable[[Transformation], Transformation]
] = MappingProxyType(
{
name: methodcaller(name)
for name in ("inverse", "square", "sqrt")
}
)
The unary operators of a transformation, by name.
Each value takes a transformation and returns the result of the method of the same name, with its defaults: a lazy result where there is one. It is the table an expression parser looks names up in, so that the operators it accepts are exactly the ones a transformation implements.
SimplifyLike
module-attribute
SimplifyLike = (
PolicyLike
| FamilyLike
| tx.Iterable[FamilyLike]
| tx.Mapping[FamilyLike, PolicyLike]
)
Possible input to the simplify argument of [compute()][].
Classes
Transformation
magic
Transformation(
data_fields: ClassVar[tuple[str, ...]] = (),
metadata_fields: ClassVar[tuple[str, ...]] = (),
derived_fields: ClassVar[tuple[str, ...]] = (),
*,
_input: CoordinateSystem | None = None,
_output: CoordinateSystem | None = None,
)
Bases: IdentityComparison, DataModelBase
A transformation between coordinate systems.
It maps coordinates from an input coordinate system to an output coordinate system. Transformations can be applied and/or composed using different syntaxes:
-
Functional:
t(x)applies the transformtto coordinatesx, andt2(t1)composes the transformt1with the transformt2(i.e., appliest1first, thent2). -
Matrix-like:
t @ xapplies the transformtto coordinatesx, andt2 @ t1composes the transformt1with the transformt2.
This abuses the matrix multiplication operator @ because linear
and affine transformations can be represented as matrices, and are
typically applied to coordinates using matrix multiplication, with
the input space "on the right" and the output space "on the left".
Direction of transformation
This mapping direction is the opposite of the direction that is
typically used to transform images. For example, a transformation
that deforms an image from space A to space B, will actually
map coordinates from space B to space A. In our model, this
transformation would be represented as Transform(input=B, output=A).
Transformations compare by identity
t1 == t2 is t1 is t2: two distinct transformations are never
equal, even when they hold the same parameters in the same
systems, and == never raises. A transformation hashes by
identity too, so it can be put in a set or used as a dictionary
key. Whether two transformations represent the same map has no
single answer, so none is picked. To test whether two map
coordinates the same way, check that one composed with the
inverse of the other is the identity --
is_identity((t1.inverse() @ t2).compute(), compute=True) -- and
compare their input/output systems explicitly.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance of the class from an instance of a similar class.
Only attributes of the other instance that match keyword-like
fields of this class will be used. An attribute that is None
is unset, and leaves the default of this class in place.
Additional positional and/or keyword arguments can be provided, and will take precedence over the attributes in the instance.
Unless the other instance is already an instance of this class,
an attribute naming a field that this class fixes (a field that
cannot be passed to its constructor) is checked instead of used:
an instance that sets it to anything other than None or the
value of this class is refused with a ValueError. A
generic Axis whose orientation is right-to-left, for example,
cannot be read as a LeftToRightAxis.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Self
Compute the transformation, if it is not already fully defined.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
[list of] name or type
|
Which kinds of transformations to materialize.
|
True
|
simplify
|
SimplifyLike
|
|
"analytic"
|
What
|
Whether to simplify the transformation prior if possible,
and how hard to try to simplify them.
* |
required | |
factor
|
bool
|
Whether to rewrite the transformation into its axis-group
normal form, splitting it into independent factors that each
act on a group of axes that transform together. Off by default,
so a plain |
False
|
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
inverse
Return the inverse of this transformation.
Some classes of transformations return a lazy inverse by default,
which is only evaluated when the compute() method is called.
This allows for efficient composition of transformations.
Or the inverse can be computed immediately by setting compute=True.
The inverse can also be obtained using the __invert__ operator:
T.inverse() is equivalent to ~T.
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
sqrt
sqrt(compute: bool = False, **kwargs) -> Transformation
Return the principal square root of this transformation.
The square root S of T is the transformation with
S @ S == T, the half-transformation. The principal one, whose
linear part has its eigenvalues in the open right half-plane, is
unique, and it is of the same kind as T: the square root of a
rotation is a rotation, of a translation a translation, of a
scaling a scaling, of an affine an affine. The square root of a
permutation is a Linear transformation.
The square root is lazy: an Sqrt wrapper is returned, and
computed when it is applied, computed or converted. A transformation
that needs no wrapper (an identity) is returned as is. A
Sequence is reduced first (see Sequence.sqrt).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself, or, when the result is computed, if its linear part has an eigenvalue on the closed negative real axis (a reflection, a rotation by a half turn, a singular matrix), so that it has no real principal square root. |
NotImplementedError
|
If brainhops does not compute the square root of this kind of
transformation. A displacement field has one only when it is a
stationary velocity field ( |
to
to(
cls: Type[Self] | None = None,
*,
lossy: bool = False,
error: Type[Exception] | Exception | bool = True,
**kwargs,
) -> Self
Convert this transformation to a different type.
Conversion can be
- between type:
linear.to(Affine); or - within type:
displacement.to(coeff=True); or - both:
coords.to(DisplacementField, coeff=True).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The type to convert to. If |
None
|
lossy
|
bool
|
Whether to allow lossy conversions. |
False
|
error
|
bool or Exception
|
Whether to raise an error if the conversion fails:
|
True
|
**kwargs
|
dict
|
Attributes to override in the converted transform.
This allows transformations to be modified within their type.
For example, a |
{}
|
Returns:
| Type | Description |
|---|---|
Transformation
|
The converted transformation. |
Affine
magic
Affine(
_data: npmatrix[Real] | None = None,
*,
_log: bool = False,
_matrix: InitVar[npmatrix[Real] | None] = None,
)
Bases: ConcreteTransformation
An affine transformation.
data holds its (No, Ni + 1) matrix. log=True builds an
AffineExponential, whose data is the tangent of the map about
the identity instead.
Attributes
matrix
property
The affine matrix, of shape (No, Ni + 1), whose last column is
the translation component.
homogeneous_matrix
property
The homogeneous matrix of the affine transformation, of shape
(No + 1, Ni + 1). The last row of the homogeneous matrix is
[0, 0, ..., 1].
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Self
Compute the transformation, downcasting it to the cheapest compatible kind.
A concrete transformation holds a parameter, so it simplifies to
the simplest compatible kind, whose compatibility can be detected
with (almost) no overhead. For example, a transformation whose
parameter is set to None is treated as an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
[list of] name or type
|
Ignored on a leaf. |
True
|
simplify
|
simplify policy
|
How hard this leaf may be looked at. The resolved
|
"analytic"
|
factor
|
bool
|
Whether to factor this leaf into its axis-group normal form. A leaf factors by wrapping itself in a one-element sequence, so a diagonal affine (say) splits into its per-axis blocks. Off by default. |
False
|
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
to
to(
cls: Type[Self] | None = None,
*,
lossy: bool = False,
error: Type[Exception] | Exception | bool = True,
**kwargs,
) -> Self
Convert this transformation to a different type.
Conversion can be
- between type:
linear.to(Affine); or - within type:
displacement.to(coeff=True); or - both:
coords.to(DisplacementField, coeff=True).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The type to convert to. If |
None
|
lossy
|
bool
|
Whether to allow lossy conversions. |
False
|
error
|
bool or Exception
|
Whether to raise an error if the conversion fails:
|
True
|
**kwargs
|
dict
|
Attributes to override in the converted transform.
This allows transformations to be modified within their type.
For example, a |
{}
|
Returns:
| Type | Description |
|---|---|
Transformation
|
The converted transformation. |
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of an Affine is copied through
its matrix view, not its stored data, which a lazy wrapper
derives and a tangent (log=True) stores as its logarithm. A
tangent is copied into a tangent through its data.
AffineExponential
AffineExponential(
_data: npmatrix[Real] | None = None,
*,
_log: bool = False,
_matrix: InitVar[npmatrix[Real] | None] = None,
)
Bases: Affine
An affine transformation stored as its tangent (log=True).
data is the (N, N + 1) tangent [L, l] of the map about the
identity, and the map is its exponential: matrix is the top N
rows of expm([[L, l], [0, ..., 0]]), computed once, then cached.
L may be singular -- a translation has the tangent [0, t]. Unset or
zero data is the identity, and AffineExponential(data=I) is the
scaling by e, not the identity: a tangent is never a matrix.
The exponential of a real tangent has a positive determinant, so it is
a PositiveAffine. Its inverse, square root and square are exact: the
tangent negated, halved and doubled. .to(log=False) gives the plain
Affine of matrix, and Affine.to(log=True) takes the principal
logarithm of a matrix, which is refused (DomainError) when its
linear part has an eigenvalue on the closed negative real axis.
Attributes
homogeneous_matrix
property
The homogeneous matrix of the affine transformation, of shape
(No + 1, Ni + 1). The last row of the homogeneous matrix is
[0, 0, ..., 1].
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of an Affine is copied through
its matrix view, not its stored data, which a lazy wrapper
derives and a tangent (log=True) stores as its logarithm. A
tangent is copied into a tangent through its data.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Self
Compute the transformation, downcasting it to the cheapest compatible kind.
A concrete transformation holds a parameter, so it simplifies to
the simplest compatible kind, whose compatibility can be detected
with (almost) no overhead. For example, a transformation whose
parameter is set to None is treated as an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
[list of] name or type
|
Ignored on a leaf. |
True
|
simplify
|
simplify policy
|
How hard this leaf may be looked at. The resolved
|
"analytic"
|
factor
|
bool
|
Whether to factor this leaf into its axis-group normal form. A leaf factors by wrapping itself in a one-element sequence, so a diagonal affine (say) splits into its per-axis blocks. Off by default. |
False
|
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
CartesianField
magic
CartesianField(_shape: tuple[int, ...] | None = None, _data: Deactivated[ArrayProtocol | None], _field: Deactivated[ArrayProtocol | None])
Bases: CoordinatesField
An identity transform over a regular grid of coordinates.
Both the input and output spaces correspond to the underlying grid.
It stores the shape of the grid rather than an array. Its field
(the coordinates of the grid points) and its data (the same
coordinates, encoded under the flags) are generated on demand, and
cached until shape or a flag is assigned.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. A lazy wrapper derives its data and its
flags, so they are read through their public names.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Self
Compute the transformation, downcasting it to the cheapest compatible kind.
A concrete transformation holds a parameter, so it simplifies to
the simplest compatible kind, whose compatibility can be detected
with (almost) no overhead. For example, a transformation whose
parameter is set to None is treated as an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
[list of] name or type
|
Ignored on a leaf. |
True
|
simplify
|
simplify policy
|
How hard this leaf may be looked at. The resolved
|
"analytic"
|
factor
|
bool
|
Whether to factor this leaf into its axis-group normal form. A leaf factors by wrapping itself in a one-element sequence, so a diagonal affine (say) splits into its per-axis blocks. Off by default. |
False
|
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
to
to(
cls: Type[Self] | None = None,
*,
lossy: bool = False,
error: Type[Exception] | Exception | bool = True,
**kwargs,
) -> Self
Convert this transformation to a different type.
Conversion can be
- between type:
linear.to(Affine); or - within type:
displacement.to(coeff=True); or - both:
coords.to(DisplacementField, coeff=True).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The type to convert to. If |
None
|
lossy
|
bool
|
Whether to allow lossy conversions. |
False
|
error
|
bool or Exception
|
Whether to raise an error if the conversion fails:
|
True
|
**kwargs
|
dict
|
Attributes to override in the converted transform.
This allows transformations to be modified within their type.
For example, a |
{}
|
Returns:
| Type | Description |
|---|---|
Transformation
|
The converted transformation. |
field
The coordinates of the grid points, of shape (*shape, ndim).
They are real coordinates, so they are built in the backend's
default floating dtype (float64 with NumPy), and so are their
spline coefficients in data.
CoordinatesField
CoordinatesField(
_data: ArrayProtocol | None = None,
_degree: InterpolationOrder = linear,
_bound: BoundaryCondition | float = nearest,
_coeff: bool = False,
*,
_field: InitVar[ArrayProtocol | None] = None,
)
Bases: TransformationField
A field of coordinates defined on a regular grid.
The input space corresponds to the regular grid on which the coordinates are defined.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Self
Compute the transformation, downcasting it to the cheapest compatible kind.
A concrete transformation holds a parameter, so it simplifies to
the simplest compatible kind, whose compatibility can be detected
with (almost) no overhead. For example, a transformation whose
parameter is set to None is treated as an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
[list of] name or type
|
Ignored on a leaf. |
True
|
simplify
|
simplify policy
|
How hard this leaf may be looked at. The resolved
|
"analytic"
|
factor
|
bool
|
Whether to factor this leaf into its axis-group normal form. A leaf factors by wrapping itself in a one-element sequence, so a diagonal affine (say) splits into its per-axis blocks. Off by default. |
False
|
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
to
to(
cls: Type[Self] | None = None,
*,
lossy: bool = False,
error: Type[Exception] | Exception | bool = True,
**kwargs,
) -> Self
Convert this transformation to a different type.
Conversion can be
- between type:
linear.to(Affine); or - within type:
displacement.to(coeff=True); or - both:
coords.to(DisplacementField, coeff=True).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The type to convert to. If |
None
|
lossy
|
bool
|
Whether to allow lossy conversions. |
False
|
error
|
bool or Exception
|
Whether to raise an error if the conversion fails:
|
True
|
**kwargs
|
dict
|
Attributes to override in the converted transform.
This allows transformations to be modified within their type.
For example, a |
{}
|
Returns:
| Type | Description |
|---|---|
Transformation
|
The converted transformation. |
field
The field, as values: an array of shape (*shape, ndim).
It is data itself when coeff is false, and data decoded
from spline coefficients (once, then cached) when it is true.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. A lazy wrapper derives its data and its
flags, so they are read through their public names.
DisplacementField
magic
DisplacementField(*, _log: bool = False)
Bases: TransformationField
A field of displacements defined on a regular grid.
Both the input and output spaces correspond to the underlying grid.
The log flag says which function data describes: the displacement
itself, or, when log is true, the stationary velocity whose flow at
time one is the map. log=True builds a
StationaryVelocityField, whose field view integrates that
velocity; a plain DisplacementField always holds displacements.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Self
Compute the transformation, downcasting it to the cheapest compatible kind.
A concrete transformation holds a parameter, so it simplifies to
the simplest compatible kind, whose compatibility can be detected
with (almost) no overhead. For example, a transformation whose
parameter is set to None is treated as an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
[list of] name or type
|
Ignored on a leaf. |
True
|
simplify
|
simplify policy
|
How hard this leaf may be looked at. The resolved
|
"analytic"
|
factor
|
bool
|
Whether to factor this leaf into its axis-group normal form. A leaf factors by wrapping itself in a one-element sequence, so a diagonal affine (say) splits into its per-axis blocks. Off by default. |
False
|
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
to
to(
cls: Type[Self] | None = None,
*,
lossy: bool = False,
error: Type[Exception] | Exception | bool = True,
**kwargs,
) -> Self
Convert this transformation to a different type.
Conversion can be
- between type:
linear.to(Affine); or - within type:
displacement.to(coeff=True); or - both:
coords.to(DisplacementField, coeff=True).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The type to convert to. If |
None
|
lossy
|
bool
|
Whether to allow lossy conversions. |
False
|
error
|
bool or Exception
|
Whether to raise an error if the conversion fails:
|
True
|
**kwargs
|
dict
|
Attributes to override in the converted transform.
This allows transformations to be modified within their type.
For example, a |
{}
|
Returns:
| Type | Description |
|---|---|
Transformation
|
The converted transformation. |
field
The field, as values: an array of shape (*shape, ndim).
It is data itself when coeff is false, and data decoded
from spline coefficients (once, then cached) when it is true.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. A lazy wrapper derives its data and its
flags, so they are read through their public names. A field that
holds its displacement is copied as its displacement: a velocity
(log=True) is integrated, unless the copy is a velocity too.
Identity
Identity(
data_fields: ClassVar[tuple[str, ...]] = (),
metadata_fields: ClassVar[tuple[str, ...]] = (),
derived_fields: ClassVar[tuple[str, ...]] = (),
*,
_input: CoordinateSystem | None = None,
_output: CoordinateSystem | None = None,
)
Bases: ConcreteTransformation
An identity transformation.
If the input and output coordinate systems are different, it maps
the input axes to the output axes, while preserving their orders.
It has no parameter: its data is always None, and is not a
constructor argument.
Attributes
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance of the class from an instance of a similar class.
Only attributes of the other instance that match keyword-like
fields of this class will be used. An attribute that is None
is unset, and leaves the default of this class in place.
Additional positional and/or keyword arguments can be provided, and will take precedence over the attributes in the instance.
Unless the other instance is already an instance of this class,
an attribute naming a field that this class fixes (a field that
cannot be passed to its constructor) is checked instead of used:
an instance that sets it to anything other than None or the
value of this class is refused with a ValueError. A
generic Axis whose orientation is right-to-left, for example,
cannot be read as a LeftToRightAxis.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Self
Compute the transformation, downcasting it to the cheapest compatible kind.
A concrete transformation holds a parameter, so it simplifies to
the simplest compatible kind, whose compatibility can be detected
with (almost) no overhead. For example, a transformation whose
parameter is set to None is treated as an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
[list of] name or type
|
Ignored on a leaf. |
True
|
simplify
|
simplify policy
|
How hard this leaf may be looked at. The resolved
|
"analytic"
|
factor
|
bool
|
Whether to factor this leaf into its axis-group normal form. A leaf factors by wrapping itself in a one-element sequence, so a diagonal affine (say) splits into its per-axis blocks. Off by default. |
False
|
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
to
to(
cls: Type[Self] | None = None,
*,
lossy: bool = False,
error: Type[Exception] | Exception | bool = True,
**kwargs,
) -> Self
Convert this transformation to a different type.
Conversion can be
- between type:
linear.to(Affine); or - within type:
displacement.to(coeff=True); or - both:
coords.to(DisplacementField, coeff=True).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The type to convert to. If |
None
|
lossy
|
bool
|
Whether to allow lossy conversions. |
False
|
error
|
bool or Exception
|
Whether to raise an error if the conversion fails:
|
True
|
**kwargs
|
dict
|
Attributes to override in the converted transform.
This allows transformations to be modified within their type.
For example, a |
{}
|
Returns:
| Type | Description |
|---|---|
Transformation
|
The converted transformation. |
Linear
magic
Linear(
_data: npmatrix[Real] | None = None,
*,
_log: bool = False,
_matrix: InitVar[npmatrix[Real] | None] = None,
)
Bases: ConcreteTransformation
A linear transformation.
data holds its (No, Ni) matrix. log=True builds a
LinearExponential, whose data is the tangent of the map about
the identity instead.
Attributes
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Self
Compute the transformation, downcasting it to the cheapest compatible kind.
A concrete transformation holds a parameter, so it simplifies to
the simplest compatible kind, whose compatibility can be detected
with (almost) no overhead. For example, a transformation whose
parameter is set to None is treated as an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
[list of] name or type
|
Ignored on a leaf. |
True
|
simplify
|
simplify policy
|
How hard this leaf may be looked at. The resolved
|
"analytic"
|
factor
|
bool
|
Whether to factor this leaf into its axis-group normal form. A leaf factors by wrapping itself in a one-element sequence, so a diagonal affine (say) splits into its per-axis blocks. Off by default. |
False
|
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
to
to(
cls: Type[Self] | None = None,
*,
lossy: bool = False,
error: Type[Exception] | Exception | bool = True,
**kwargs,
) -> Self
Convert this transformation to a different type.
Conversion can be
- between type:
linear.to(Affine); or - within type:
displacement.to(coeff=True); or - both:
coords.to(DisplacementField, coeff=True).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The type to convert to. If |
None
|
lossy
|
bool
|
Whether to allow lossy conversions. |
False
|
error
|
bool or Exception
|
Whether to raise an error if the conversion fails:
|
True
|
**kwargs
|
dict
|
Attributes to override in the converted transform.
This allows transformations to be modified within their type.
For example, a |
{}
|
Returns:
| Type | Description |
|---|---|
Transformation
|
The converted transformation. |
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of a Linear is copied through
its matrix view, not its stored data, which a lazy wrapper
derives and a tangent (log=True) stores as its logarithm. A
tangent is copied into a tangent through its data.
LinearExponential
LinearExponential(
_data: npmatrix[Real] | None = None,
*,
_log: bool = False,
_matrix: InitVar[npmatrix[Real] | None] = None,
)
Bases: Linear
A linear transformation stored as its tangent (log=True).
data is the (N, N) tangent L of the map about the identity, and
the map is its exponential: matrix is expm(L), computed once, then
cached. Unset or zero data is the identity, and
LinearExponential(data=I) is the scaling by e.
The exponential of a real tangent has a positive determinant, so it is
a PositiveLinear. Its inverse, square root and square are exact: the
tangent negated, halved and doubled. .to(log=False) gives the plain
Linear of matrix, and Linear.to(log=True) takes the principal
logarithm of a matrix, which is refused (DomainError) when it has an
eigenvalue on the closed negative real axis.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of a Linear is copied through
its matrix view, not its stored data, which a lazy wrapper
derives and a tangent (log=True) stores as its logarithm. A
tangent is copied into a tangent through its data.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Self
Compute the transformation, downcasting it to the cheapest compatible kind.
A concrete transformation holds a parameter, so it simplifies to
the simplest compatible kind, whose compatibility can be detected
with (almost) no overhead. For example, a transformation whose
parameter is set to None is treated as an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
[list of] name or type
|
Ignored on a leaf. |
True
|
simplify
|
simplify policy
|
How hard this leaf may be looked at. The resolved
|
"analytic"
|
factor
|
bool
|
Whether to factor this leaf into its axis-group normal form. A leaf factors by wrapping itself in a one-element sequence, so a diagonal affine (say) splits into its per-axis blocks. Off by default. |
False
|
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
Permutation
magic
Permutation(
_data: npvector[Integral] | None = None,
*,
_permutation: InitVar[npvector[Integral] | None] = None,
)
Bases: ConcreteTransformation
A permutation of axes.
Attributes
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Self
Compute the transformation, downcasting it to the cheapest compatible kind.
A concrete transformation holds a parameter, so it simplifies to
the simplest compatible kind, whose compatibility can be detected
with (almost) no overhead. For example, a transformation whose
parameter is set to None is treated as an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
[list of] name or type
|
Ignored on a leaf. |
True
|
simplify
|
simplify policy
|
How hard this leaf may be looked at. The resolved
|
"analytic"
|
factor
|
bool
|
Whether to factor this leaf into its axis-group normal form. A leaf factors by wrapping itself in a one-element sequence, so a diagonal affine (say) splits into its per-axis blocks. Off by default. |
False
|
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
to
to(
cls: Type[Self] | None = None,
*,
lossy: bool = False,
error: Type[Exception] | Exception | bool = True,
**kwargs,
) -> Self
Convert this transformation to a different type.
Conversion can be
- between type:
linear.to(Affine); or - within type:
displacement.to(coeff=True); or - both:
coords.to(DisplacementField, coeff=True).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The type to convert to. If |
None
|
lossy
|
bool
|
Whether to allow lossy conversions. |
False
|
error
|
bool or Exception
|
Whether to raise an error if the conversion fails:
|
True
|
**kwargs
|
dict
|
Attributes to override in the converted transform.
This allows transformations to be modified within their type.
For example, a |
{}
|
Returns:
| Type | Description |
|---|---|
Transformation
|
The converted transformation. |
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of a Permutation is copied
through its permutation view, not its stored data, which a lazy
wrapper derives.
Rotation
magic
Bases: Linear
An orthogonal transformation with determinant 1, i.e., a rotation.
data holds its (N, N) matrix. log=True builds a
RotationExponential, whose data is the tangent of the map about
the identity instead.
Attributes
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of a Linear is copied through
its matrix view, not its stored data, which a lazy wrapper
derives and a tangent (log=True) stores as its logarithm. A
tangent is copied into a tangent through its data.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Self
Compute the transformation, downcasting it to the cheapest compatible kind.
A concrete transformation holds a parameter, so it simplifies to
the simplest compatible kind, whose compatibility can be detected
with (almost) no overhead. For example, a transformation whose
parameter is set to None is treated as an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
[list of] name or type
|
Ignored on a leaf. |
True
|
simplify
|
simplify policy
|
How hard this leaf may be looked at. The resolved
|
"analytic"
|
factor
|
bool
|
Whether to factor this leaf into its axis-group normal form. A leaf factors by wrapping itself in a one-element sequence, so a diagonal affine (say) splits into its per-axis blocks. Off by default. |
False
|
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
to
to(
cls: Type[Self] | None = None,
*,
lossy: bool = False,
error: Type[Exception] | Exception | bool = True,
**kwargs,
) -> Self
Convert this transformation to a different type.
Conversion can be
- between type:
linear.to(Affine); or - within type:
displacement.to(coeff=True); or - both:
coords.to(DisplacementField, coeff=True).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The type to convert to. If |
None
|
lossy
|
bool
|
Whether to allow lossy conversions. |
False
|
error
|
bool or Exception
|
Whether to raise an error if the conversion fails:
|
True
|
**kwargs
|
dict
|
Attributes to override in the converted transform.
This allows transformations to be modified within their type.
For example, a |
{}
|
Returns:
| Type | Description |
|---|---|
Transformation
|
The converted transformation. |
RotationExponential
Bases: Rotation
A rotation stored as its tangent (log=True).
data is the (N, N) antisymmetric tangent L of the rotation about
the identity -- its axis and angle -- and the map is its exponential:
matrix is expm(L), computed once, then cached. Unset or zero data
is the identity.
Its inverse, square root and square are exact: the tangent negated,
halved and doubled. .to(log=False) gives the plain Rotation of
matrix, and Rotation.to(log=True) takes the principal logarithm of
a rotation, which is refused (DomainError) for a rotation by a half
turn, whose logarithm is not unique.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of a Linear is copied through
its matrix view, not its stored data, which a lazy wrapper
derives and a tangent (log=True) stores as its logarithm. A
tangent is copied into a tangent through its data.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Self
Compute the transformation, downcasting it to the cheapest compatible kind.
A concrete transformation holds a parameter, so it simplifies to
the simplest compatible kind, whose compatibility can be detected
with (almost) no overhead. For example, a transformation whose
parameter is set to None is treated as an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
[list of] name or type
|
Ignored on a leaf. |
True
|
simplify
|
simplify policy
|
How hard this leaf may be looked at. The resolved
|
"analytic"
|
factor
|
bool
|
Whether to factor this leaf into its axis-group normal form. A leaf factors by wrapping itself in a one-element sequence, so a diagonal affine (say) splits into its per-axis blocks. Off by default. |
False
|
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
Scaling
magic
Scaling(
_data: npvector[Real] | None = None,
*,
_log: bool = False,
_scale: InitVar[npvector[Real] | None] = None,
)
Bases: ConcreteTransformation
A scaling of axes.
data holds its scaling factors. log=True builds a
ScalingExponential, whose data is their logarithm instead.
Attributes
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Self
Compute the transformation, downcasting it to the cheapest compatible kind.
A concrete transformation holds a parameter, so it simplifies to
the simplest compatible kind, whose compatibility can be detected
with (almost) no overhead. For example, a transformation whose
parameter is set to None is treated as an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
[list of] name or type
|
Ignored on a leaf. |
True
|
simplify
|
simplify policy
|
How hard this leaf may be looked at. The resolved
|
"analytic"
|
factor
|
bool
|
Whether to factor this leaf into its axis-group normal form. A leaf factors by wrapping itself in a one-element sequence, so a diagonal affine (say) splits into its per-axis blocks. Off by default. |
False
|
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
to
to(
cls: Type[Self] | None = None,
*,
lossy: bool = False,
error: Type[Exception] | Exception | bool = True,
**kwargs,
) -> Self
Convert this transformation to a different type.
Conversion can be
- between type:
linear.to(Affine); or - within type:
displacement.to(coeff=True); or - both:
coords.to(DisplacementField, coeff=True).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The type to convert to. If |
None
|
lossy
|
bool
|
Whether to allow lossy conversions. |
False
|
error
|
bool or Exception
|
Whether to raise an error if the conversion fails:
|
True
|
**kwargs
|
dict
|
Attributes to override in the converted transform.
This allows transformations to be modified within their type.
For example, a |
{}
|
Returns:
| Type | Description |
|---|---|
Transformation
|
The converted transformation. |
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of a Scaling is copied through
its scale view, not its stored data, which a lazy wrapper
derives and a tangent (log=True) stores as its logarithm. A
tangent is copied into a tangent through its data.
ScalingExponential
ScalingExponential(
_data: npvector[Real] | None = None,
*,
_log: bool = False,
_scale: InitVar[npvector[Real] | None] = None,
)
Bases: Scaling
A scaling stored as the logarithm of its factors (log=True).
data is the tangent s of the map about the identity, and scale
is exp(s), computed once, then cached: the factors are positive, so
it is a PositiveDiagonal. Unset or zero data is the identity.
Its inverse, square root and square are exact: the tangent negated,
halved and doubled. .to(log=False) gives the plain Scaling of
scale, and Scaling.to(log=True) takes the logarithm of the factors,
which is refused (DomainError) unless they are all positive.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of a Scaling is copied through
its scale view, not its stored data, which a lazy wrapper
derives and a tangent (log=True) stores as its logarithm. A
tangent is copied into a tangent through its data.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Self
Compute the transformation, downcasting it to the cheapest compatible kind.
A concrete transformation holds a parameter, so it simplifies to
the simplest compatible kind, whose compatibility can be detected
with (almost) no overhead. For example, a transformation whose
parameter is set to None is treated as an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
[list of] name or type
|
Ignored on a leaf. |
True
|
simplify
|
simplify policy
|
How hard this leaf may be looked at. The resolved
|
"analytic"
|
factor
|
bool
|
Whether to factor this leaf into its axis-group normal form. A leaf factors by wrapping itself in a one-element sequence, so a diagonal affine (say) splits into its per-axis blocks. Off by default. |
False
|
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
StationaryVelocityField
magic
StationaryVelocityField(*, _steps: int | None = None)
Bases: DisplacementField
A displacement field stored as its stationary velocity (log=True).
data holds the velocity v, the tangent of the map about the
identity: its values, or their spline coefficients when coeff is
true (as NiftyReg's -vel -cpp grids and torch-diffeo store it). The
map is the flow of v at time one, exp(v), and the field view is
always its displacement, as values. It is integrated by scaling and
squaring: v is divided by 2 ** steps, which is its own flow to
first order, and composed with itself steps times, with the field
composition and the field's own degree and bound. A field of
coefficients is refitted at each step, so its squaring stays in
coefficients. The displacements are in the voxels of the field's own
grid, as for any DisplacementField.
Squaring on the knot grid
A field of coefficients is squared on its own grid: the grid of
its knots. NiftyReg evaluates a velocity grid (-vel -cpp) onto
the dense reference grid first, and squares there, so the two do
not match reg_transform -def exactly, although both converge to
the same flow.
DisplacementField(data=v, log=True), d.to(log=True) (for an unset
d) and StationaryVelocityField(data=v) build the same object.
Unset or zero data is the identity.
The tangent makes some operations exact: the inverse is exp(-v), the
square root exp(v / 2) and the square exp(2 v). A displacement has
no logarithm that brainhops computes, so .to(log=True) refuses a
DisplacementField that holds one; .to(log=False) integrates a
velocity into a plain DisplacementField.
Attributes
squarings
property
squarings: int | None
The number of squaring steps the field view integrates with:
steps, or the number the default rule picks when it is None.
None when data is unset.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. A lazy wrapper derives its data and its
flags, so they are read through their public names. A field that
holds its displacement is copied as its displacement: a velocity
(log=True) is integrated, unless the copy is a velocity too.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Self
Compute the transformation, downcasting it to the cheapest compatible kind.
A concrete transformation holds a parameter, so it simplifies to
the simplest compatible kind, whose compatibility can be detected
with (almost) no overhead. For example, a transformation whose
parameter is set to None is treated as an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
[list of] name or type
|
Ignored on a leaf. |
True
|
simplify
|
simplify policy
|
How hard this leaf may be looked at. The resolved
|
"analytic"
|
factor
|
bool
|
Whether to factor this leaf into its axis-group normal form. A leaf factors by wrapping itself in a one-element sequence, so a diagonal affine (say) splits into its per-axis blocks. Off by default. |
False
|
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
Translation
magic
Translation(
_data: npvector[Real] | None = None,
*,
_translation: InitVar[npvector[Real] | None] = None,
)
Bases: ConcreteTransformation
A translation.
Attributes
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Self
Compute the transformation, downcasting it to the cheapest compatible kind.
A concrete transformation holds a parameter, so it simplifies to
the simplest compatible kind, whose compatibility can be detected
with (almost) no overhead. For example, a transformation whose
parameter is set to None is treated as an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
[list of] name or type
|
Ignored on a leaf. |
True
|
simplify
|
simplify policy
|
How hard this leaf may be looked at. The resolved
|
"analytic"
|
factor
|
bool
|
Whether to factor this leaf into its axis-group normal form. A leaf factors by wrapping itself in a one-element sequence, so a diagonal affine (say) splits into its per-axis blocks. Off by default. |
False
|
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
to
to(
cls: Type[Self] | None = None,
*,
lossy: bool = False,
error: Type[Exception] | Exception | bool = True,
**kwargs,
) -> Self
Convert this transformation to a different type.
Conversion can be
- between type:
linear.to(Affine); or - within type:
displacement.to(coeff=True); or - both:
coords.to(DisplacementField, coeff=True).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The type to convert to. If |
None
|
lossy
|
bool
|
Whether to allow lossy conversions. |
False
|
error
|
bool or Exception
|
Whether to raise an error if the conversion fails:
|
True
|
**kwargs
|
dict
|
Attributes to override in the converted transform.
This allows transformations to be modified within their type.
For example, a |
{}
|
Returns:
| Type | Description |
|---|---|
Transformation
|
The converted transformation. |
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of a Translation is copied
through its translation view, not its stored data, which a lazy
wrapper derives.
AdaptationError
Bases: TypeError
Raised when one coordinate system cannot be adapted to another.
Adaptation reorders, rescales, and flips the axes that two coordinate systems share, so it succeeds only when every axis of one system corresponds to an axis of the other. This error is raised when an axis that must be matched has no correspondence, or when two matched axes carry incompatible units. Its message names the two systems and the axes that could not be reconciled.
CompositionError
Bases: TypeError
Raised when two transformations cannot be composed.
ConversionError
Bases: TypeError
Raised when a transformation cannot be converted to another type.
DomainError
Bases: ValueError
Raised when a transformation lies outside the domain of an operator.
The square and the square root of a transformation (see
Transformation.square and Transformation.sqrt) are defined
only for a transformation that maps a space to itself. The principal
square root, and the principal logarithm that .to(log=True) takes of
a matrix, also need the linear part to have no eigenvalue on the
closed negative real axis: a singular matrix, a reflection and a
rotation by a half turn have neither. Rather than return a complex, a
non-principal or an approximate result, the operation raises this
error, whose message names it and the reason.
A transformation the operator is defined for, but that brainhops does
not know how to compute it for, raises NotImplementedError instead.
LossyConversionError
LossyConversionError(
*args, result: Transformation | None = None, **kwargs
)
Bases: ConversionError
Raised when a conversion would discard information.
This error is raised by Transformation.to when a conversion is
only possible at the cost of losing information, and the conversion
was not explicitly allowed to be lossy. The result attribute holds
the transformation that the conversion would have produced.
Inverse
magic
Inverse(forward: Transformation | None = None)
Bases: Transformation, Generic[TRANSFORMATION]
The inverse of a transformation, resolved on demand.
An Inverse holds a forward transformation and represents its
inverse. The inverse is not computed when the wrapper is built. It is
computed only when the wrapper is applied, computed, or converted to a
concrete type. Placed next to its forward transformation in a
Sequence, the two cancel to the identity, and no inverse is ever
computed.
Constructing Inverse(forward=t) represents the inverse of any
transformation t. Each family of transformations also has its own
typed inverse, such as InverseAffine or
InverseDisplacementField, which a transformation returns from its
inverse() method. A typed inverse remains an instance of the family
it inverts, so composition and the kind checks treat it exactly like a
forward transformation of that family.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance of the class from an instance of a similar class.
Only attributes of the other instance that match keyword-like
fields of this class will be used. An attribute that is None
is unset, and leaves the default of this class in place.
Additional positional and/or keyword arguments can be provided, and will take precedence over the attributes in the instance.
Unless the other instance is already an instance of this class,
an attribute naming a field that this class fixes (a field that
cannot be passed to its constructor) is checked instead of used:
an instance that sets it to anything other than None or the
value of this class is refused with a ValueError. A
generic Axis whose orientation is right-to-left, for example,
cannot be read as a LeftToRightAxis.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
sqrt
sqrt(compute: bool = False, **kwargs) -> Transformation
Return the principal square root of this transformation.
The square root S of T is the transformation with
S @ S == T, the half-transformation. The principal one, whose
linear part has its eigenvalues in the open right half-plane, is
unique, and it is of the same kind as T: the square root of a
rotation is a rotation, of a translation a translation, of a
scaling a scaling, of an affine an affine. The square root of a
permutation is a Linear transformation.
The square root is lazy: an Sqrt wrapper is returned, and
computed when it is applied, computed or converted. A transformation
that needs no wrapper (an identity) is returned as is. A
Sequence is reduced first (see Sequence.sqrt).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself, or, when the result is computed, if its linear part has an eigenvalue on the closed negative real axis (a reflection, a rotation by a half turn, a singular matrix), so that it has no real principal square root. |
NotImplementedError
|
If brainhops does not compute the square root of this kind of
transformation. A displacement field has one only when it is a
stationary velocity field ( |
inverse
inverse(compute: bool = False, **kwargs) -> Transformation
Return the forward transformation, with the endpoints restored.
The inverse of an inverse is the original forward transformation.
An endpoint edit made on the wrapper is carried onto it. With
compute, the other keywords are passed on to compute().
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Resolve the inverse, if the mode admits it.
Materializing an inverse is the one thing this wrapper exists to
put off, so it happens here and nowhere else: never in a
simplifier, which may only rewrite for free. The compose mode is
the gate -- a mode that does not admit this wrapper leaves it lazy,
so an adjacent pair can still cancel in a sequence -- and
simplify then still downcasts what it wraps. factor is forwarded
to the materialized result.
InverseAffine
magic
InverseAffine(forward: Affine | None = None, _data: Derived[npmatrix[Real] | None], _log: Derived[bool], _matrix: Deactivated[None])
Bases: Inverse[Affine], Affine
The inverse of an Affine transformation, resolved on demand.
Attributes
matrix
property
The affine matrix, of shape (No, Ni + 1), whose last column is
the translation component.
homogeneous_matrix
property
The homogeneous matrix of the affine transformation, of shape
(No + 1, Ni + 1). The last row of the homogeneous matrix is
[0, 0, ..., 1].
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of an Affine is copied through
its matrix view, not its stored data, which a lazy wrapper
derives and a tangent (log=True) stores as its logarithm. A
tangent is copied into a tangent through its data.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Resolve the inverse, if the mode admits it.
Materializing an inverse is the one thing this wrapper exists to
put off, so it happens here and nowhere else: never in a
simplifier, which may only rewrite for free. The compose mode is
the gate -- a mode that does not admit this wrapper leaves it lazy,
so an adjacent pair can still cancel in a sequence -- and
simplify then still downcasts what it wraps. factor is forwarded
to the materialized result.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
inverse
inverse(compute: bool = False, **kwargs) -> Transformation
Return the forward transformation, with the endpoints restored.
The inverse of an inverse is the original forward transformation.
An endpoint edit made on the wrapper is carried onto it. With
compute, the other keywords are passed on to compute().
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
InverseAffineExponential
magic
InverseAffineExponential(forward: AffineExponential | None = None, _data: Derived[npmatrix[Real] | None], _log: Derived[bool], _matrix: Deactivated[None])
Bases: Inverse[AffineExponential], AffineExponential
The inverse of an AffineExponential: the tangent negated.
Attributes
homogeneous_matrix
property
The homogeneous matrix of the affine transformation, of shape
(No + 1, Ni + 1). The last row of the homogeneous matrix is
[0, 0, ..., 1].
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of an Affine is copied through
its matrix view, not its stored data, which a lazy wrapper
derives and a tangent (log=True) stores as its logarithm. A
tangent is copied into a tangent through its data.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Resolve the inverse, if the mode admits it.
Materializing an inverse is the one thing this wrapper exists to
put off, so it happens here and nowhere else: never in a
simplifier, which may only rewrite for free. The compose mode is
the gate -- a mode that does not admit this wrapper leaves it lazy,
so an adjacent pair can still cancel in a sequence -- and
simplify then still downcasts what it wraps. factor is forwarded
to the materialized result.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
inverse
inverse(compute: bool = False, **kwargs) -> Transformation
Return the forward transformation, with the endpoints restored.
The inverse of an inverse is the original forward transformation.
An endpoint edit made on the wrapper is carried onto it. With
compute, the other keywords are passed on to compute().
InverseCoordinatesField
magic
InverseCoordinatesField(forward: CoordinatesField | None = None, _data: Derived[ArrayProtocol | None], _degree: Derived[InterpolationOrder], _bound: Derived[BoundaryCondition | float], _coeff: Derived[bool], _field: Deactivated[None])
Bases: Inverse[CoordinatesField], CoordinatesField
The inverse of a CoordinatesField, resolved on demand.
The wrapper reports the degree, bound and coeff of the forward
field, and its data is the inverse field in that same encoding: the
forward field's values are inverted, and the result is fitted back to
spline coefficients when the forward field holds coefficients. Its
field view is the inverse field, as values, either way.
Accuracy
As for InverseDisplacementField, the inversion only sees
the forward field's values at the grid nodes and inverts the
piecewise-affine map they define, whatever the forward's
degree; the result is approximate between nodes, and more so
near the border.
Placed next to the field it inverts in a Sequence, the two cancel
and nothing is computed. That is the cheap path, and the one worth
reaching for: a coordinate field has no closed-form inverse, so
materializing this wrapper runs a mesh inversion.
The coordinates must live on the grid they are sampled on
A coordinate field is inverted by reading it as the identity grid plus a displacement, inverting that displacement, and adding the grid back. The mesh inversion therefore assumes the coordinates are expressed in the units of the grid they are sampled on -- voxels, in practice. A field whose coordinates are in world units is inverted as though they were voxel coordinates, and the result, while well defined, falls outside the output lattice and is of little use. Compose the world-to-voxel affine into the field first.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. A lazy wrapper derives its data and its
flags, so they are read through their public names.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Resolve the inverse, if the mode admits it.
Materializing an inverse is the one thing this wrapper exists to
put off, so it happens here and nowhere else: never in a
simplifier, which may only rewrite for free. The compose mode is
the gate -- a mode that does not admit this wrapper leaves it lazy,
so an adjacent pair can still cancel in a sequence -- and
simplify then still downcasts what it wraps. factor is forwarded
to the materialized result.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
inverse
inverse(compute: bool = False, **kwargs) -> Transformation
Return the forward transformation, with the endpoints restored.
The inverse of an inverse is the original forward transformation.
An endpoint edit made on the wrapper is carried onto it. With
compute, the other keywords are passed on to compute().
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
InverseDisplacementField
magic
InverseDisplacementField(forward: DisplacementField | None = None, _data: Derived[ArrayProtocol | None], _degree: Derived[InterpolationOrder], _bound: Derived[BoundaryCondition | float], _coeff: Derived[bool], _log: Derived[bool], _field: Deactivated[None])
Bases: Inverse[DisplacementField], DisplacementField
The inverse of a DisplacementField, resolved on demand.
The wrapper reports the degree, bound and coeff of the forward
field, and its data is the inverse field in that same encoding: the
forward field's values are inverted, and the result is fitted back to
spline coefficients when the forward field holds coefficients. Its
field view is the inverse field, as values, either way.
Accuracy
The inversion only sees the forward field's values at the grid
nodes: it inverts the piecewise-affine map they define (see
brainhops._ext.invfield.inverse), whatever the forward's
degree. The inverse is then interpolated with that degree. It
is exact at the level of that piecewise-affine map only, so a
cubic field is inverted about as accurately as a linear one,
and the error grows near the border. On smooth fields of a few
voxels' amplitude, fwd(inv(x)) - x is typically a few
hundredths of a voxel in the interior, and a few tenths near
the border.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. A lazy wrapper derives its data and its
flags, so they are read through their public names. A field that
holds its displacement is copied as its displacement: a velocity
(log=True) is integrated, unless the copy is a velocity too.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Resolve the inverse, if the mode admits it.
Materializing an inverse is the one thing this wrapper exists to
put off, so it happens here and nowhere else: never in a
simplifier, which may only rewrite for free. The compose mode is
the gate -- a mode that does not admit this wrapper leaves it lazy,
so an adjacent pair can still cancel in a sequence -- and
simplify then still downcasts what it wraps. factor is forwarded
to the materialized result.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
inverse
inverse(compute: bool = False, **kwargs) -> Transformation
Return the forward transformation, with the endpoints restored.
The inverse of an inverse is the original forward transformation.
An endpoint edit made on the wrapper is carried onto it. With
compute, the other keywords are passed on to compute().
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
InverseLinear
magic
InverseLinear(forward: Linear | None = None, _data: Derived[npmatrix[Real] | None], _log: Derived[bool], _matrix: Deactivated[None])
Bases: Inverse[Linear], Linear
The inverse of a Linear transformation, resolved on demand.
Attributes
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of a Linear is copied through
its matrix view, not its stored data, which a lazy wrapper
derives and a tangent (log=True) stores as its logarithm. A
tangent is copied into a tangent through its data.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Resolve the inverse, if the mode admits it.
Materializing an inverse is the one thing this wrapper exists to
put off, so it happens here and nowhere else: never in a
simplifier, which may only rewrite for free. The compose mode is
the gate -- a mode that does not admit this wrapper leaves it lazy,
so an adjacent pair can still cancel in a sequence -- and
simplify then still downcasts what it wraps. factor is forwarded
to the materialized result.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
inverse
inverse(compute: bool = False, **kwargs) -> Transformation
Return the forward transformation, with the endpoints restored.
The inverse of an inverse is the original forward transformation.
An endpoint edit made on the wrapper is carried onto it. With
compute, the other keywords are passed on to compute().
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
InverseLinearExponential
magic
InverseLinearExponential(forward: LinearExponential | None = None, _data: Derived[npmatrix[Real] | None], _log: Derived[bool], _matrix: Deactivated[None])
Bases: Inverse[LinearExponential], LinearExponential
The inverse of a LinearExponential: the tangent negated.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of a Linear is copied through
its matrix view, not its stored data, which a lazy wrapper
derives and a tangent (log=True) stores as its logarithm. A
tangent is copied into a tangent through its data.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Resolve the inverse, if the mode admits it.
Materializing an inverse is the one thing this wrapper exists to
put off, so it happens here and nowhere else: never in a
simplifier, which may only rewrite for free. The compose mode is
the gate -- a mode that does not admit this wrapper leaves it lazy,
so an adjacent pair can still cancel in a sequence -- and
simplify then still downcasts what it wraps. factor is forwarded
to the materialized result.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
inverse
inverse(compute: bool = False, **kwargs) -> Transformation
Return the forward transformation, with the endpoints restored.
The inverse of an inverse is the original forward transformation.
An endpoint edit made on the wrapper is carried onto it. With
compute, the other keywords are passed on to compute().
InversePermutation
magic
InversePermutation(forward: Permutation | None = None, _data: Derived[npvector[Integral] | None], _permutation: Deactivated[None])
Bases: Inverse, Permutation
The inverse of a Permutation, resolved on demand.
Attributes
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of a Permutation is copied
through its permutation view, not its stored data, which a lazy
wrapper derives.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Resolve the inverse, if the mode admits it.
Materializing an inverse is the one thing this wrapper exists to
put off, so it happens here and nowhere else: never in a
simplifier, which may only rewrite for free. The compose mode is
the gate -- a mode that does not admit this wrapper leaves it lazy,
so an adjacent pair can still cancel in a sequence -- and
simplify then still downcasts what it wraps. factor is forwarded
to the materialized result.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
inverse
inverse(compute: bool = False, **kwargs) -> Transformation
Return the forward transformation, with the endpoints restored.
The inverse of an inverse is the original forward transformation.
An endpoint edit made on the wrapper is carried onto it. With
compute, the other keywords are passed on to compute().
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
InverseRotation
magic
InverseRotation(forward: Rotation | None = None, _data: Derived[npmatrix[Real] | None], _log: Derived[bool], _matrix: Deactivated[None])
Bases: Inverse[Rotation], Rotation
The inverse of a Rotation, resolved on demand.
Attributes
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of a Linear is copied through
its matrix view, not its stored data, which a lazy wrapper
derives and a tangent (log=True) stores as its logarithm. A
tangent is copied into a tangent through its data.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Resolve the inverse, if the mode admits it.
Materializing an inverse is the one thing this wrapper exists to
put off, so it happens here and nowhere else: never in a
simplifier, which may only rewrite for free. The compose mode is
the gate -- a mode that does not admit this wrapper leaves it lazy,
so an adjacent pair can still cancel in a sequence -- and
simplify then still downcasts what it wraps. factor is forwarded
to the materialized result.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
inverse
inverse(compute: bool = False, **kwargs) -> Transformation
Return the forward transformation, with the endpoints restored.
The inverse of an inverse is the original forward transformation.
An endpoint edit made on the wrapper is carried onto it. With
compute, the other keywords are passed on to compute().
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
InverseRotationExponential
magic
InverseRotationExponential(forward: RotationExponential | None = None, _data: Derived[npmatrix[Real] | None], _log: Derived[bool], _matrix: Deactivated[None])
Bases: Inverse[RotationExponential], RotationExponential
The inverse of a RotationExponential: the tangent negated.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of a Linear is copied through
its matrix view, not its stored data, which a lazy wrapper
derives and a tangent (log=True) stores as its logarithm. A
tangent is copied into a tangent through its data.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Resolve the inverse, if the mode admits it.
Materializing an inverse is the one thing this wrapper exists to
put off, so it happens here and nowhere else: never in a
simplifier, which may only rewrite for free. The compose mode is
the gate -- a mode that does not admit this wrapper leaves it lazy,
so an adjacent pair can still cancel in a sequence -- and
simplify then still downcasts what it wraps. factor is forwarded
to the materialized result.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
inverse
inverse(compute: bool = False, **kwargs) -> Transformation
Return the forward transformation, with the endpoints restored.
The inverse of an inverse is the original forward transformation.
An endpoint edit made on the wrapper is carried onto it. With
compute, the other keywords are passed on to compute().
InverseScaling
magic
InverseScaling(forward: Scaling | None = None, _data: Derived[npvector[Real] | None], _log: Derived[bool], _scale: Deactivated[None])
The inverse of a Scaling, resolved on demand.
Attributes
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of a Scaling is copied through
its scale view, not its stored data, which a lazy wrapper
derives and a tangent (log=True) stores as its logarithm. A
tangent is copied into a tangent through its data.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Resolve the inverse, if the mode admits it.
Materializing an inverse is the one thing this wrapper exists to
put off, so it happens here and nowhere else: never in a
simplifier, which may only rewrite for free. The compose mode is
the gate -- a mode that does not admit this wrapper leaves it lazy,
so an adjacent pair can still cancel in a sequence -- and
simplify then still downcasts what it wraps. factor is forwarded
to the materialized result.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
inverse
inverse(compute: bool = False, **kwargs) -> Transformation
Return the forward transformation, with the endpoints restored.
The inverse of an inverse is the original forward transformation.
An endpoint edit made on the wrapper is carried onto it. With
compute, the other keywords are passed on to compute().
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
InverseScalingExponential
magic
InverseScalingExponential(forward: ScalingExponential | None = None, _data: Derived[npvector[Real] | None], _log: Derived[bool], _scale: Deactivated[None])
Bases: Inverse[ScalingExponential], ScalingExponential
The inverse of a ScalingExponential: the tangent negated.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of a Scaling is copied through
its scale view, not its stored data, which a lazy wrapper
derives and a tangent (log=True) stores as its logarithm. A
tangent is copied into a tangent through its data.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Resolve the inverse, if the mode admits it.
Materializing an inverse is the one thing this wrapper exists to
put off, so it happens here and nowhere else: never in a
simplifier, which may only rewrite for free. The compose mode is
the gate -- a mode that does not admit this wrapper leaves it lazy,
so an adjacent pair can still cancel in a sequence -- and
simplify then still downcasts what it wraps. factor is forwarded
to the materialized result.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
inverse
inverse(compute: bool = False, **kwargs) -> Transformation
Return the forward transformation, with the endpoints restored.
The inverse of an inverse is the original forward transformation.
An endpoint edit made on the wrapper is carried onto it. With
compute, the other keywords are passed on to compute().
InverseStationaryVelocityField
magic
InverseStationaryVelocityField(forward: StationaryVelocityField | None = None, _data: Derived[ArrayProtocol | None], _degree: Derived[InterpolationOrder], _bound: Derived[BoundaryCondition | float], _coeff: Derived[bool], _log: Derived[bool], _steps: Derived[int | None], _field: Deactivated[None])
Bases: Inverse[StationaryVelocityField], StationaryVelocityField
The inverse of a StationaryVelocityField: exp(-v).
Its data is the negated velocity, in the encoding of the forward
field, whose flags (steps included) it reports. Its field view
integrates that velocity -- exactly as the forward integrates its own,
rather than by inverting the forward's displacement. The accuracy
note of InverseDisplacementField does not apply: no mesh is
inverted, the inverse is exact in the tangent, and exp(-v) is
integrated as accurately as exp(v) is.
Attributes
squarings
property
squarings: int | None
The number of squaring steps the field view integrates with:
steps, or the number the default rule picks when it is None.
None when data is unset.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. A lazy wrapper derives its data and its
flags, so they are read through their public names. A field that
holds its displacement is copied as its displacement: a velocity
(log=True) is integrated, unless the copy is a velocity too.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Resolve the inverse, if the mode admits it.
Materializing an inverse is the one thing this wrapper exists to
put off, so it happens here and nowhere else: never in a
simplifier, which may only rewrite for free. The compose mode is
the gate -- a mode that does not admit this wrapper leaves it lazy,
so an adjacent pair can still cancel in a sequence -- and
simplify then still downcasts what it wraps. factor is forwarded
to the materialized result.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
inverse
inverse(compute: bool = False, **kwargs) -> Transformation
Return the forward transformation, with the endpoints restored.
The inverse of an inverse is the original forward transformation.
An endpoint edit made on the wrapper is carried onto it. With
compute, the other keywords are passed on to compute().
InverseTranslation
magic
InverseTranslation(forward: Translation | None = None, _data: Derived[npvector[Real] | None], _translation: Deactivated[None])
Bases: Inverse[Translation], Translation
The inverse of a Translation, resolved on demand.
Attributes
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance from an instance of a similar class.
See DataModelBase.from_instance. The map of a Translation is copied
through its translation view, not its stored data, which a lazy
wrapper derives.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Resolve the inverse, if the mode admits it.
Materializing an inverse is the one thing this wrapper exists to
put off, so it happens here and nowhere else: never in a
simplifier, which may only rewrite for free. The compose mode is
the gate -- a mode that does not admit this wrapper leaves it lazy,
so an adjacent pair can still cancel in a sequence -- and
simplify then still downcasts what it wraps. factor is forwarded
to the materialized result.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
inverse
inverse(compute: bool = False, **kwargs) -> Transformation
Return the forward transformation, with the endpoints restored.
The inverse of an inverse is the original forward transformation.
An endpoint edit made on the wrapper is carried onto it. With
compute, the other keywords are passed on to compute().
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
Bijection
magic
Bases: MetaTransformation, Generic[TRANSFORMATION]
A transformation whose inverse is explicitly defined.
Generic in the forward transformation type: Bijection[TRANSFORMATION]
wraps a TRANSFORMATION. Declared bijective; a checker registered in
checkers refines its membership from the forward map.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance of the class from an instance of a similar class.
Only attributes of the other instance that match keyword-like
fields of this class will be used. An attribute that is None
is unset, and leaves the default of this class in place.
Additional positional and/or keyword arguments can be provided, and will take precedence over the attributes in the instance.
Unless the other instance is already an instance of this class,
an attribute naming a field that this class fixes (a field that
cannot be passed to its constructor) is checked instead of used:
an instance that sets it to anything other than None or the
value of this class is refused with a ValueError. A
generic Axis whose orientation is right-to-left, for example,
cannot be read as a LeftToRightAxis.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
to
to(
cls: Type[Self] | None = None,
*,
lossy: bool = False,
error: Type[Exception] | Exception | bool = True,
**kwargs,
) -> Self
Convert this transformation to a different type.
Conversion can be
- between type:
linear.to(Affine); or - within type:
displacement.to(coeff=True); or - both:
coords.to(DisplacementField, coeff=True).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The type to convert to. If |
None
|
lossy
|
bool
|
Whether to allow lossy conversions. |
False
|
error
|
bool or Exception
|
Whether to raise an error if the conversion fails:
|
True
|
**kwargs
|
dict
|
Attributes to override in the converted transform.
This allows transformations to be modified within their type.
For example, a |
{}
|
Returns:
| Type | Description |
|---|---|
Transformation
|
The converted transformation. |
Projection
magic
Bases: MetaTransformation
A transformation that acts as a projection from a higher dimensional space to a lower-dimensional space by removing one or more axes.
Or its inverse (i.e., an embedding) that adds one or more axes to a lower-dimensional space.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance of the class from an instance of a similar class.
Only attributes of the other instance that match keyword-like
fields of this class will be used. An attribute that is None
is unset, and leaves the default of this class in place.
Additional positional and/or keyword arguments can be provided, and will take precedence over the attributes in the instance.
Unless the other instance is already an instance of this class,
an attribute naming a field that this class fixes (a field that
cannot be passed to its constructor) is checked instead of used:
an instance that sets it to anything other than None or the
value of this class is refused with a ValueError. A
generic Axis whose orientation is right-to-left, for example,
cannot be read as a LeftToRightAxis.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
sqrt
sqrt(compute: bool = False, **kwargs) -> Transformation
Return the principal square root of this transformation.
The square root S of T is the transformation with
S @ S == T, the half-transformation. The principal one, whose
linear part has its eigenvalues in the open right half-plane, is
unique, and it is of the same kind as T: the square root of a
rotation is a rotation, of a translation a translation, of a
scaling a scaling, of an affine an affine. The square root of a
permutation is a Linear transformation.
The square root is lazy: an Sqrt wrapper is returned, and
computed when it is applied, computed or converted. A transformation
that needs no wrapper (an identity) is returned as is. A
Sequence is reduced first (see Sequence.sqrt).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself, or, when the result is computed, if its linear part has an eigenvalue on the closed negative real axis (a reflection, a rotation by a half turn, a singular matrix), so that it has no real principal square root. |
NotImplementedError
|
If brainhops does not compute the square root of this kind of
transformation. A displacement field has one only when it is a
stationary velocity field ( |
to
to(
cls: Type[Self] | None = None,
*,
lossy: bool = False,
error: Type[Exception] | Exception | bool = True,
**kwargs,
) -> Self
Convert this transformation to a different type.
Conversion can be
- between type:
linear.to(Affine); or - within type:
displacement.to(coeff=True); or - both:
coords.to(DisplacementField, coeff=True).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The type to convert to. If |
None
|
lossy
|
bool
|
Whether to allow lossy conversions. |
False
|
error
|
bool or Exception
|
Whether to raise an error if the conversion fails:
|
True
|
**kwargs
|
dict
|
Attributes to override in the converted transform.
This allows transformations to be modified within their type.
For example, a |
{}
|
Returns:
| Type | Description |
|---|---|
Transformation
|
The converted transformation. |
SubspaceTransformation
magic
SubspaceTransformation(
transformation: TRANSFORMATION | None = None,
input_axes: npvector[Integral] | None = None,
output_axes: npvector[Integral] | None = None,
)
Bases: MetaTransformation, Generic[TRANSFORMATION]
A transformation that is applied to a subset of the input and output axes.
The transformation acts on the axes named by input_axes and
output_axes, and leaves every other axis unchanged. The
dimensionality of the space is preserved. An axis that is not named
passes through as the identity. This embeds a transformation defined
over a few axes, such as a spatial transformation over (x, y, z),
into a larger space, such as (x, y, z, t), where it acts on the
spatial axes and leaves time untouched.
Generic in the wrapped transformation type:
SubspaceTransformation[TRANSFORMATION] embeds a TRANSFORMATION. Its
membership is decided by a checker registered in checkers that recurses
into the wrapped transform.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance of the class from an instance of a similar class.
Only attributes of the other instance that match keyword-like
fields of this class will be used. An attribute that is None
is unset, and leaves the default of this class in place.
Additional positional and/or keyword arguments can be provided, and will take precedence over the attributes in the instance.
Unless the other instance is already an instance of this class,
an attribute naming a field that this class fixes (a field that
cannot be passed to its constructor) is checked instead of used:
an instance that sets it to anything other than None or the
value of this class is refused with a ValueError. A
generic Axis whose orientation is right-to-left, for example,
cannot be read as a LeftToRightAxis.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
to
to(
cls: Type[Self] | None = None,
*,
lossy: bool = False,
error: Type[Exception] | Exception | bool = True,
**kwargs,
) -> Self
Convert this transformation to a different type.
Conversion can be
- between type:
linear.to(Affine); or - within type:
displacement.to(coeff=True); or - both:
coords.to(DisplacementField, coeff=True).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The type to convert to. If |
None
|
lossy
|
bool
|
Whether to allow lossy conversions. |
False
|
error
|
bool or Exception
|
Whether to raise an error if the conversion fails:
|
True
|
**kwargs
|
dict
|
Attributes to override in the converted transform.
This allows transformations to be modified within their type.
For example, a |
{}
|
Returns:
| Type | Description |
|---|---|
Transformation
|
The converted transformation. |
Multiscale
magic
Multiscale(scales: list[Any] = ())
Bases: DataModelBase, Generic[SINGLE_SCALE]
A pyramid of resolution scales, ordered from finest to coarsest.
This mixin gives a transformation a list of scales and the operations that select one of them. The scales are ordered from finest to coarsest, so the first scale is the highest resolution one.
The mixin does not say what a scale is. A subclass supplies the scales
and, through the _level_resolution hook, the physical grid size of
each one. With those, _nearest_level picks the scale whose
resolution is closest to a target grid.
Attributes
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance of the class from an instance of a similar class.
Only attributes of the other instance that match keyword-like
fields of this class will be used. An attribute that is None
is unset, and leaves the default of this class in place.
Additional positional and/or keyword arguments can be provided, and will take precedence over the attributes in the instance.
Unless the other instance is already an instance of this class,
an attribute naming a field that this class fixes (a field that
cannot be passed to its constructor) is checked instead of used:
an instance that sets it to anything other than None or the
value of this class is refused with a ValueError. A
generic Axis whose orientation is right-to-left, for example,
cannot be read as a LeftToRightAxis.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
MultiscaleField
magic
MultiscaleField(scales: list[Sequence] = ())
Bases: Multiscale[Sequence], ImmutableSequence
A field of coordinates or displacements at several resolutions.
Each scale is a Sequence that maps the multiscale's input space
to its output space, sampled on that scale's grid. A coordinate scale
is a two-element sequence of a world-to-voxel affine and a field of
coordinates. A displacement scale is a three-element sequence of a
world-to-voxel affine, a field of displacements in voxel units, and
the voxel-to-world affine. The container treats a scale as a plain
sequence, so the same class carries both kinds.
A MultiscaleField behaves as its finest scale. It composes with
other transformations exactly as the finest scale would, and reduces
to the finest scale when it is computed. The finest scale is the one
used unless a scale is selected with to_singlescale.
The scales replace this class as the unit that is edited. A scale is
selected with to_singlescale, and the returned sequence is edited in
place. The container itself does not support item assignment,
insertion, or deletion.
Attributes
transformations
property
writable
transformations: tuple[Transformation, ...]
The transformations of the finest scale.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance of the class from an instance of a similar class.
Only attributes of the other instance that match keyword-like
fields of this class will be used. An attribute that is None
is unset, and leaves the default of this class in place.
Additional positional and/or keyword arguments can be provided, and will take precedence over the attributes in the instance.
Unless the other instance is already an instance of this class,
an attribute naming a field that this class fixes (a field that
cannot be passed to its constructor) is checked instead of used:
an instance that sets it to anything other than None or the
value of this class is refused with a ValueError. A
generic Axis whose orientation is right-to-left, for example,
cannot be read as a LeftToRightAxis.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
sqrt
sqrt(compute: bool = False, **kwargs) -> Transformation
Return the principal square root of this chain.
The chain is first simplified, which costs nothing. A chain
[P, *X, P^-1], where P^-1 is the lazy inverse of P, or both
are affines whose product is exactly the identity, is a change of
coordinates around X, and its square root is
[P, sqrt(X), P^-1]: a field stored in voxels between a
world-to-voxel affine and its lazy inverse keeps that form. Any
other chain is composed now, and the square root of the
transformation it composes to is returned.
Raises:
| Type | Description |
|---|---|
DomainError
|
If the chain does not map a space to itself, or if the square root of what it reduces to is not defined. |
NotImplementedError
|
If the chain does not compose to a single transformation. |
to
to(
cls: Type[Transformation] | None = None, **kwargs
) -> Transformation
Convert this chain to a different type or encoding.
See Transformation.to. A chain has no tangent of its own -- the tangent of a
composition is not the sum of the tangents -- so log= re-encodes
the transformation it reduces to, and anything else is refused
before it is computed:
- a chain that simplifies to one transformation is that one;
- a change of coordinates
[P, *X, P^-1](seesqrt) keeps its ends, and re-encodesX: the flow of a velocity commutes with the conjugation, so this is exact. A velocity read between a world-to-voxel affine and its inverse (|svf) is turned into its displacement that way; - a chain of affines is composed, which is cheap and exact.
Any other chain -- one with a field, between ends that do not undo
each other -- raises ConversionError.
to_singlescale
Return the resolution scale at a given index.
Index 0 is the finest scale. The scale is returned as it is
stored, so for a field it is the plain transformation of that
scale rather than the multiscale field.
compute
compute(
mode: ModeLike | None = None,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Compute the field as a plain transformation.
The finest scale is composed and returned. The result is an ordinary transformation, with no pyramid, so it computes exactly as the finest scale would on its own.
Sqrt
Sqrt(forward: Transformation | None = None)
Bases: Operation
The principal square root of a transformation, resolved on demand.
The square root S of T is the transformation with S @ S == T --
the half-transformation. Among the many square roots a map may have,
the principal one is the one whose linear part has its eigenvalues in
the open right half-plane. It exists, and is real, when the linear part
of T has no eigenvalue on the closed negative real axis; otherwise the
wrapper raises DomainError when it is resolved. A field has a
square root here only when it is stored as its velocity (a
StationaryVelocityField), whose square root halves the velocity
and needs no wrapper.
Build it with Transformation.sqrt. Constructing Sqrt(forward=t)
builds the typed wrapper of t's family, and refuses a family that has
none.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance of the class from an instance of a similar class.
Only attributes of the other instance that match keyword-like
fields of this class will be used. An attribute that is None
is unset, and leaves the default of this class in place.
Additional positional and/or keyword arguments can be provided, and will take precedence over the attributes in the instance.
Unless the other instance is already an instance of this class,
an attribute naming a field that this class fixes (a field that
cannot be passed to its constructor) is checked instead of used:
an instance that sets it to anything other than None or the
value of this class is refused with a ValueError. A
generic Axis whose orientation is right-to-left, for example,
cannot be read as a LeftToRightAxis.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Resolve the operator, if the mode admits it.
As for Inverse.compute, the compose mode is the gate: a mode
that does not admit the wrapper leaves it unresolved, and
simplify then still simplifies what it wraps. factor is
forwarded to the materialized result.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
inverse
Return the inverse of this transformation.
Some classes of transformations return a lazy inverse by default,
which is only evaluated when the compute() method is called.
This allows for efficient composition of transformations.
Or the inverse can be computed immediately by setting compute=True.
The inverse can also be obtained using the __invert__ operator:
T.inverse() is equivalent to ~T.
sqrt
sqrt(compute: bool = False, **kwargs) -> Transformation
Return the principal square root of this transformation.
The square root S of T is the transformation with
S @ S == T, the half-transformation. The principal one, whose
linear part has its eigenvalues in the open right half-plane, is
unique, and it is of the same kind as T: the square root of a
rotation is a rotation, of a translation a translation, of a
scaling a scaling, of an affine an affine. The square root of a
permutation is a Linear transformation.
The square root is lazy: an Sqrt wrapper is returned, and
computed when it is applied, computed or converted. A transformation
that needs no wrapper (an identity) is returned as is. A
Sequence is reduced first (see Sequence.sqrt).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself, or, when the result is computed, if its linear part has an eigenvalue on the closed negative real axis (a reflection, a rotation by a half turn, a singular matrix), so that it has no real principal square root. |
NotImplementedError
|
If brainhops does not compute the square root of this kind of
transformation. A displacement field has one only when it is a
stationary velocity field ( |
square
square(compute: bool = False, **kwargs) -> Transformation
Return the forward transformation: sqrt(T) squared is T.
ImmutableSequence
magic
ImmutableSequence(
_transformations: tuple[Transformation, ...]
| None = None,
)
Bases: Sequence
A Sequence whose contents cannot be edited in place.
Every in-place edit -- item assignment, deletion, insertion -- raises
TypeError.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance of the class from an instance of a similar class.
Only attributes of the other instance that match keyword-like
fields of this class will be used. An attribute that is None
is unset, and leaves the default of this class in place.
Additional positional and/or keyword arguments can be provided, and will take precedence over the attributes in the instance.
Unless the other instance is already an instance of this class,
an attribute naming a field that this class fixes (a field that
cannot be passed to its constructor) is checked instead of used:
an instance that sets it to anything other than None or the
value of this class is refused with a ValueError. A
generic Axis whose orientation is right-to-left, for example,
cannot be read as a LeftToRightAxis.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Compute the resulting transform of the sequence of transformations.
Assuming that mode=True:
-
If all transformations in the sequence are affine-like transformations,
compute()returns an affine-like transform. -
If the first (= rightmost) transform in the sequence is a coordinate field,
compute()returns a coordinate field. -
If the first (= rightmost) transform in the sequence is an affine-like transform, and the sequence contains at least one non-affine-like transform,
compute()returns a sequence of two transformations: -
the composition of all affine-like transformations that appear before the first non-affine-like transform in the sequence, and
- the composition of all transformations in the sequence, starting from the first non-affine-like transform in the sequence.
Parameters
mode : [list of] name or type, optional
Kinds of transformations to compose.
* If True (default): compose every kind in the sequence.
* If False: compose nothing (simplify-only).
* If a (list of) transformation type(s): compose only pairs
of transformations of these kinds.
simplify : simplify policy, default="analytic"
Whether to simplify sub-transformations prior to composition,
and how hard to try to simplify them.
* "analytic" (the default) looks at the type structure only;
* "numeric" looks at the numeric values of the transformation;
* False/"none"/None disables simplification.
factor : bool, default=False
Whether to rewrite the sequence into its axis-group normal
form [grid?, F_1..F_m, Pi_perm?]: a leading grid (if any),
one axis-preserving subspace factor per group of axes that
transform together, and a trailing reindex permutation. Off
by default, so the result is byte-for-byte the plain
compute() result. Nothing is ever composed across groups;
mode still decides whether the restricted pieces inside a
group compose. A chain that creates or drops axes is left
unfactored. With mode=False nothing is computed, so
factor has nothing to act on and is ignored.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
sqrt
sqrt(compute: bool = False, **kwargs) -> Transformation
Return the principal square root of this chain.
The chain is first simplified, which costs nothing. A chain
[P, *X, P^-1], where P^-1 is the lazy inverse of P, or both
are affines whose product is exactly the identity, is a change of
coordinates around X, and its square root is
[P, sqrt(X), P^-1]: a field stored in voxels between a
world-to-voxel affine and its lazy inverse keeps that form. Any
other chain is composed now, and the square root of the
transformation it composes to is returned.
Raises:
| Type | Description |
|---|---|
DomainError
|
If the chain does not map a space to itself, or if the square root of what it reduces to is not defined. |
NotImplementedError
|
If the chain does not compose to a single transformation. |
to
to(
cls: Type[Transformation] | None = None, **kwargs
) -> Transformation
Convert this chain to a different type or encoding.
See Transformation.to. A chain has no tangent of its own -- the tangent of a
composition is not the sum of the tangents -- so log= re-encodes
the transformation it reduces to, and anything else is refused
before it is computed:
- a chain that simplifies to one transformation is that one;
- a change of coordinates
[P, *X, P^-1](seesqrt) keeps its ends, and re-encodesX: the flow of a velocity commutes with the conjugation, so this is exact. A velocity read between a world-to-voxel affine and its inverse (|svf) is turned into its displacement that way; - a chain of affines is composed, which is cheap and exact.
Any other chain -- one with a field, between ends that do not undo
each other -- raises ConversionError.
MutableSequence
magic
MutableSequence(
_transformations: list[Transformation] | None = None,
)
Bases: MutableSequenceMixin, Sequence
A sequence of transformations.
Note
Transformations in a sequence are listed in the order in which they are applied. It reads as the opposite order to function composition (or matrix multiplication), which may be confusing.
Sequence([t1, t2, t3])(x)is equivalent tot3(t2(t1(x))).Sequence([t1, t2, t3]) @ xis equivalent tot3 @ t2 @ t1 @ x.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance of the class from an instance of a similar class.
Only attributes of the other instance that match keyword-like
fields of this class will be used. An attribute that is None
is unset, and leaves the default of this class in place.
Additional positional and/or keyword arguments can be provided, and will take precedence over the attributes in the instance.
Unless the other instance is already an instance of this class,
an attribute naming a field that this class fixes (a field that
cannot be passed to its constructor) is checked instead of used:
an instance that sets it to anything other than None or the
value of this class is refused with a ValueError. A
generic Axis whose orientation is right-to-left, for example,
cannot be read as a LeftToRightAxis.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Compute the resulting transform of the sequence of transformations.
Assuming that mode=True:
-
If all transformations in the sequence are affine-like transformations,
compute()returns an affine-like transform. -
If the first (= rightmost) transform in the sequence is a coordinate field,
compute()returns a coordinate field. -
If the first (= rightmost) transform in the sequence is an affine-like transform, and the sequence contains at least one non-affine-like transform,
compute()returns a sequence of two transformations: -
the composition of all affine-like transformations that appear before the first non-affine-like transform in the sequence, and
- the composition of all transformations in the sequence, starting from the first non-affine-like transform in the sequence.
Parameters
mode : [list of] name or type, optional
Kinds of transformations to compose.
* If True (default): compose every kind in the sequence.
* If False: compose nothing (simplify-only).
* If a (list of) transformation type(s): compose only pairs
of transformations of these kinds.
simplify : simplify policy, default="analytic"
Whether to simplify sub-transformations prior to composition,
and how hard to try to simplify them.
* "analytic" (the default) looks at the type structure only;
* "numeric" looks at the numeric values of the transformation;
* False/"none"/None disables simplification.
factor : bool, default=False
Whether to rewrite the sequence into its axis-group normal
form [grid?, F_1..F_m, Pi_perm?]: a leading grid (if any),
one axis-preserving subspace factor per group of axes that
transform together, and a trailing reindex permutation. Off
by default, so the result is byte-for-byte the plain
compute() result. Nothing is ever composed across groups;
mode still decides whether the restricted pieces inside a
group compose. A chain that creates or drops axes is left
unfactored. With mode=False nothing is computed, so
factor has nothing to act on and is ignored.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
sqrt
sqrt(compute: bool = False, **kwargs) -> Transformation
Return the principal square root of this chain.
The chain is first simplified, which costs nothing. A chain
[P, *X, P^-1], where P^-1 is the lazy inverse of P, or both
are affines whose product is exactly the identity, is a change of
coordinates around X, and its square root is
[P, sqrt(X), P^-1]: a field stored in voxels between a
world-to-voxel affine and its lazy inverse keeps that form. Any
other chain is composed now, and the square root of the
transformation it composes to is returned.
Raises:
| Type | Description |
|---|---|
DomainError
|
If the chain does not map a space to itself, or if the square root of what it reduces to is not defined. |
NotImplementedError
|
If the chain does not compose to a single transformation. |
to
to(
cls: Type[Transformation] | None = None, **kwargs
) -> Transformation
Convert this chain to a different type or encoding.
See Transformation.to. A chain has no tangent of its own -- the tangent of a
composition is not the sum of the tangents -- so log= re-encodes
the transformation it reduces to, and anything else is refused
before it is computed:
- a chain that simplifies to one transformation is that one;
- a change of coordinates
[P, *X, P^-1](seesqrt) keeps its ends, and re-encodesX: the flow of a velocity commutes with the conjugation, so this is exact. A velocity read between a world-to-voxel affine and its inverse (|svf) is turned into its displacement that way; - a chain of affines is composed, which is cheap and exact.
Any other chain -- one with a field, between ends that do not undo
each other -- raises ConversionError.
Sequence
magic
Sequence(
_transformations: Sequence[Transformation]
| None = None,
)
Bases: SequenceMixin, Transformation
A sequence of transformations.
This is a base class shared by mutable and immutable sequences.
It can also be used as a factory itself, in which case it returns
a MutableSequence.
Note
Transformations in a sequence are listed in the order in which they are applied. It reads as the opposite order to function composition (or matrix multiplication), which may be confusing.
Sequence([t1, t2, t3])(x)is equivalent tot3(t2(t1(x))).Sequence([t1, t2, t3]) @ xis equivalent tot3 @ t2 @ t1 @ x.
Methods:
from_dict
classmethod
Create an instance of the class from a dictionary-like object.
Only keys in the dictionary that match keyword-like fields of
this class, or the keywords its constructor takes without
storing them (its InitVars, such as the matrix= of an
Affine), will be used. Other keys are ignored, but see
from_other,
which refuses them.
Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.
A key naming a field that this class fixes (a field that cannot
be passed to its constructor) is checked instead of used: a
dictionary that sets it to anything other than None or the
value of this class is refused with a ValueError.
from_instance
classmethod
Create an instance of the class from an instance of a similar class.
Only attributes of the other instance that match keyword-like
fields of this class will be used. An attribute that is None
is unset, and leaves the default of this class in place.
Additional positional and/or keyword arguments can be provided, and will take precedence over the attributes in the instance.
Unless the other instance is already an instance of this class,
an attribute naming a field that this class fixes (a field that
cannot be passed to its constructor) is checked instead of used:
an instance that sets it to anything other than None or the
value of this class is refused with a ValueError. A
generic Axis whose orientation is right-to-left, for example,
cannot be read as a LeftToRightAxis.
from_other
classmethod
Create an instance of the class from any object that can be interpreted as a dictionary, or an instance of a similar class, or an arguments to be passed to the constructor.
A similar class is this class or one of its parents within the
data model, or another member of a polymorphic family this class
belongs to: calling a polymorphic class such as Axis builds the
subclass its arguments select, so a "generic" axis is usually an
instance of a sibling (a RightToLeftAxis, a TimeAxis) rather
than of a parent. Any other object, including an instance of a
parent that is not a data model (such as a plain object), is
passed to the constructor.
Unlike from_dict,
a dictionary with a key that matches no field of this class is
refused with a TypeError naming the keys, so that a
misspelt key is not silently dropped.
simplify
simplify(
policy: SimplifyLike = "analytic",
*,
compute: ModeLike | bool | None = False,
) -> Self
Simplify this transformation under a per-kind policy.
Convenience sugar for
compute: t.simplify(policy, compute=mode) is
t.compute(mode, simplify=policy).
By default simplify() does no computation at all: compute=False
maps to mode=False, which composes nothing (no matrices multiplied,
no fields sampled, no lazy inverse materialized). It only downcasts
each leaf under policy (analytic by default). Pass an explicit
compute=<mode> to also compose that kind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
simplify policy
|
The simplify policy, in the grammar |
"analytic"
|
compute
|
[list of] name or type
|
The compose mode. The default, |
False
|
square
square(compute: bool = False, **kwargs) -> Transformation
Return the square of this transformation, self @ self.
The square is the sequence [self, self], which composes when it
is computed. It is defined for a transformation that maps a space
to itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compute
|
bool
|
Whether to compute the result now rather than return it lazily. |
False
|
**kwargs
|
Passed to |
{}
|
Raises:
| Type | Description |
|---|---|
DomainError
|
If the transformation does not map a space to itself. |
sqrt
sqrt(compute: bool = False, **kwargs) -> Transformation
Return the principal square root of this chain.
The chain is first simplified, which costs nothing. A chain
[P, *X, P^-1], where P^-1 is the lazy inverse of P, or both
are affines whose product is exactly the identity, is a change of
coordinates around X, and its square root is
[P, sqrt(X), P^-1]: a field stored in voxels between a
world-to-voxel affine and its lazy inverse keeps that form. Any
other chain is composed now, and the square root of the
transformation it composes to is returned.
Raises:
| Type | Description |
|---|---|
DomainError
|
If the chain does not map a space to itself, or if the square root of what it reduces to is not defined. |
NotImplementedError
|
If the chain does not compose to a single transformation. |
to
to(
cls: Type[Transformation] | None = None, **kwargs
) -> Transformation
Convert this chain to a different type or encoding.
See Transformation.to. A chain has no tangent of its own -- the tangent of a
composition is not the sum of the tangents -- so log= re-encodes
the transformation it reduces to, and anything else is refused
before it is computed:
- a chain that simplifies to one transformation is that one;
- a change of coordinates
[P, *X, P^-1](seesqrt) keeps its ends, and re-encodesX: the flow of a velocity commutes with the conjugation, so this is exact. A velocity read between a world-to-voxel affine and its inverse (|svf) is turned into its displacement that way; - a chain of affines is composed, which is cheap and exact.
Any other chain -- one with a field, between ends that do not undo
each other -- raises ConversionError.
compute
compute(
mode: ModeLike = True,
*,
simplify: SimplifyLike = "analytic",
factor: bool = False,
) -> Transformation
Compute the resulting transform of the sequence of transformations.
Assuming that mode=True:
-
If all transformations in the sequence are affine-like transformations,
compute()returns an affine-like transform. -
If the first (= rightmost) transform in the sequence is a coordinate field,
compute()returns a coordinate field. -
If the first (= rightmost) transform in the sequence is an affine-like transform, and the sequence contains at least one non-affine-like transform,
compute()returns a sequence of two transformations: -
the composition of all affine-like transformations that appear before the first non-affine-like transform in the sequence, and
- the composition of all transformations in the sequence, starting from the first non-affine-like transform in the sequence.
Parameters
mode : [list of] name or type, optional
Kinds of transformations to compose.
* If True (default): compose every kind in the sequence.
* If False: compose nothing (simplify-only).
* If a (list of) transformation type(s): compose only pairs
of transformations of these kinds.
simplify : simplify policy, default="analytic"
Whether to simplify sub-transformations prior to composition,
and how hard to try to simplify them.
* "analytic" (the default) looks at the type structure only;
* "numeric" looks at the numeric values of the transformation;
* False/"none"/None disables simplification.
factor : bool, default=False
Whether to rewrite the sequence into its axis-group normal
form [grid?, F_1..F_m, Pi_perm?]: a leading grid (if any),
one axis-preserving subspace factor per group of axes that
transform together, and a trailing reindex permutation. Off
by default, so the result is byte-for-byte the plain
compute() result. Nothing is ever composed across groups;
mode still decides whether the restricted pieces inside a
group compose. A chain that creates or drops axes is left
unfactored. With mode=False nothing is computed, so
factor has nothing to act on and is ignored.
SimplifyPolicy
Bases: StrEnum
How hard a transformation may be looked at, and therefore how far it may be simplified.
none-- declared type only: nothing is inspected, nothing is rewritten.analytic-- structure only:Noneparameters, array shapes, axis lists and wrapper contents are read; no value is read and no lazy inverse is materialized. Invertibility, injectivity and surjectivity of a matrix transformation are assumed from its shape at this level (a square matrix is presumed invertible, a wide one surjective, a tall one injective).numeric-- values too: zero tests, diagonality, orthogonality, rank; a typed inverse may be materialized when a leaf is downcast. Rank replaces the analytic shape assumption, so a square singular matrix is not invertible here.
SimplifyTable
Bases: dict
A Dict[TransformationFamily, SimplifyPolicy] mapping.
The None key holds the fallback policy, used for a transform that
matches no other entry.
Methods:
from_like
classmethod
from_like(value: SimplifyLike) -> Self
Normalize any accepted simplify= input into a simplify table.
| Input | Output |
|---|---|
None |
{None: none} |
False |
{None: none} |
True |
{None: numeric} |
"none" |
{None: none} |
"analytic" |
{None: analytic} |
"numeric" |
{None: numeric} |
a policy: SimplifyPolicy |
{None: policy} |
a key: str | type |
{None: none, lowered(key): analytic} |
a Iterable[key: str] |
{None: none, lowered(key): analytic, ...} |
a Dict[key: str, policy: SimplifyPolicy} |
{None: <fallback>, lowered(key): policy, ...} |
from_families
classmethod
from_families(value: SimplifyLike) -> Self
Build a table from one family key, or an iterable of them.
from_mapping
classmethod
Build a table from a {family: policy} mapping.
resolve
resolve(*transformations: Transformation) -> SimplifyPolicy
Resolve the simplify policy for one transform, or the policy shared by several.
Every entry whose family admits the transform applies, and the
safest of them wins; when none does, the None fallback applies.
Given several transforms, the safest of their policies wins, so a
pair is only rewritten as hard as its most protected member allows.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*transformations
|
Transformation
|
The transforms to resolve. |
()
|
Returns:
| Type | Description |
|---|---|
SimplifyPolicy
|
The resolved policy. |
Functions:
is_identity
is_identity(
xform: Transformation, /, compute: bool = False
) -> bool
Return whether a transformation is the identity.
A transformation is recognized as the identity when its parameters
are unset, or when it is an instance of Identity. When
compute is true, the parameters of a transformation such as
Translation, Scaling, Permutation, Linear,
Affine, or DisplacementField are also inspected, so that
a transformation whose parameters happen to encode the identity is
recognized as such even though it is not stored as one.
A CartesianField is a regular grid of coordinates, which is the
identity map over its grid by construction. When compute is true, a
CartesianField is therefore recognized as the identity. When
compute is false, a CartesianField that carries a grid is not
recognized as the identity, because its shape parameter is set. A
CartesianField with no grid has an unset shape parameter and
is recognized as the identity by the parameter check under either
value of compute. The shape is read, never the derived field, so
the meshgrid is not built by a structural check.
Recognizing a grid as the identity does not mean a grid may be dropped on sight. A grid also defines the sampling domain onto which data is resampled. The decision to factor a grid away is made by the sequence simplifier, which only does so for a grid that sits strictly between two other transformations.
is_linear
is_linear(
xform: Transformation, /, compute: bool = False
) -> bool
Return whether a transformation is linear, without a translation.
A transformation is recognized as linear when it is an instance of
kinds.Linear, or when is_identity
recognizes it as the identity, which is itself linear.
When compute is true, the matrix of an Affine transformation
is also inspected for a zero translation component.
is_permutation
is_permutation(
xform: Transformation, /, compute: bool = False
) -> bool
Return whether a transformation is a pure permutation of axes.
A transformation is recognized as a permutation when it is an
instance of kinds.Permutation, or when is_identity
recognizes it as the identity, which is itself a trivial permutation.
When compute is true, the matrix of a Linear or Affine
transformation is also inspected for a binary, one-per-row and
one-per-column structure.
is_rotation
is_rotation(
xform: Transformation, /, compute: bool = False
) -> bool
Return whether a transformation is a pure rotation.
A transformation is recognized as a rotation when it is an instance
of kinds.SpecialOrthogonal, or when
is_identity recognizes it as the identity, which is itself a
rotation by zero.
When compute is true, the matrix of a Linear or Affine
transformation is also inspected for orthogonality and a positive
determinant.
is_scaling
is_scaling(
xform: Transformation, /, compute: bool = False
) -> bool
Return whether a transformation is a pure scaling.
A transformation is recognized as a scaling when it is an instance
of kinds.Diagonal, or when is_identity
recognizes it as the identity, which is itself a scaling by one.
When compute is true, the matrix of a Linear or Affine
transformation is also inspected for a diagonal structure.
is_translation
is_translation(
xform: Transformation, /, compute: bool = False
) -> bool
Return whether a transformation is a pure translation.
A transformation is recognized as a translation when it is an
instance of kinds.Translation, or when is_identity
recognizes it as the identity, which is itself a translation by zero.
When compute is true, the matrix of an Affine transformation
is also inspected for a linear part equal to the identity.