Source code for ewoksndreg.transformation.base
from typing import Any
from typing import Optional
from typing import Sequence
from typing import Type
import numpy
from ..registry import Registered
from .types import TransformationType
[docs]
class Transformation(Registered, register=False):
def __init__(self, transfo_type: TransformationType) -> None:
if isinstance(transfo_type, str):
transfo_type = TransformationType(transfo_type)
self._transfo_type = transfo_type
self._active_matrix: Optional[numpy.ndarray] = None
@property
def transformation_type(self) -> TransformationType:
return self._transfo_type
[docs]
def as_type(self, cls: Type["Transformation"]) -> "Transformation":
if isinstance(self, cls):
return self
raise TypeError(f"cannot convert '{type(self).__name__}' to '{cls.__name__}'")
[docs]
def is_homography(self):
return self._transfo_type in [
"identity",
"translation",
"rigid",
"similarity",
"affine",
"projective",
]
[docs]
def apply_coordinates(self, coord: Sequence[numpy.ndarray]) -> numpy.ndarray:
"""
:param coord: shape `(N, M)`
:returns: shape `(N, M)`
"""
raise NotImplementedError
[docs]
def apply_data(
self,
data: numpy.ndarray,
offset: Optional[numpy.ndarray] = None,
shape: Optional[numpy.ndarray] = None,
cval=numpy.nan,
interpolation_order: int = 1,
) -> numpy.ndarray:
"""
:param data: shape `(N1, N2, ..., M1, M2, ...)` with `len((N1, N2, ...)) = N`
:param offset: shape `(N,)`
:param shape: shape `(N,) = [N1', N2', ...]`
:param cval: missing value
:param interpolation_order: order of interpolation: 0 is nearest neighbor, 1 is bilinear,...
:returns: shape `(N1', N2', ..., M1, M2, ...)`
"""
raise NotImplementedError
def __matmul__(self, other: "Transformation") -> "Transformation":
"""When appyling the transformation, `other` comes after `self`"""
raise NotImplementedError
@property
def passive_matrix(self) -> numpy.ndarray:
raise AttributeError("Transformation does not have a matrix representation")
@property
def active_matrix(self) -> numpy.ndarray:
if self._active_matrix is None:
self._active_matrix = numpy.linalg.inv(self.passive_matrix)
return self._active_matrix
def __eq__(self, other: Any) -> bool:
if not isinstance(other, Transformation):
return False
try:
passive_matrix = self.passive_matrix
other_passive_matrix = other.passive_matrix
except AttributeError:
pass
else:
if passive_matrix.shape != other_passive_matrix.shape:
return False
return numpy.allclose(passive_matrix, other_passive_matrix)
return id(self) == id(other)