Bases: SpatialTransform
Copy the affine matrix from one image to all others.
This is useful when slight numerical differences between affine
matrices cause downstream errors (e.g., in
Resample). NIfTI stores affines in
single precision, so saving and reloading can introduce
rounding errors.
Parameters:
| Name |
Type |
Description |
Default |
target
|
str
|
Name of the image whose affine will be copied to
all other images in the subject.
|
required
|
**kwargs
|
Any
|
|
{}
|
Examples:
>>> import torchio as tio
>>> transform = tio.CopyAffine(target="t1")
Source code in src/torchio/transforms/spatial/copy_affine.py
| class CopyAffine(SpatialTransform):
"""Copy the affine matrix from one image to all others.
This is useful when slight numerical differences between affine
matrices cause downstream errors (e.g., in
[`Resample`][torchio.Resample]). NIfTI stores affines in
single precision, so saving and reloading can introduce
rounding errors.
Args:
target: Name of the image whose affine will be copied to
all other images in the subject.
**kwargs: See [`Transform`][torchio.Transform].
Examples:
>>> import torchio as tio
>>> transform = tio.CopyAffine(target="t1")
"""
def __init__(self, target: str, **kwargs: Any) -> None:
super().__init__(**kwargs)
self.target = target
def make_params(self, batch: SubjectsBatch) -> dict[str, Any]:
"""No random parameters."""
return {}
def apply_transform(
self,
batch: SubjectsBatch,
params: dict[str, Any],
) -> SubjectsBatch:
"""Copy the reference affine to all other images."""
if self.target not in batch.images:
msg = (
f"Reference image '{self.target}' not found. "
f"Available: {list(batch.images.keys())}"
)
raise KeyError(msg)
ref_affines = batch.images[self.target].affines
for name, img_batch in batch.images.items():
if name == self.target:
continue
for i, affine in enumerate(img_batch.affines):
affine._matrix = copy.deepcopy(ref_affines[i]._matrix)
return batch
|
invertible
property
Whether this transform can be inverted.
forward(data)
forward(data: Subject) -> Subject
forward(data: Image) -> Image
forward(data: Tensor) -> Tensor
forward(data: np.ndarray) -> np.ndarray
forward(data: sitk.Image) -> sitk.Image
forward(data: nib.Nifti1Image) -> nib.Nifti1Image
forward(data: dict) -> dict
forward(data: ImagesBatch) -> ImagesBatch
forward(data: SubjectsBatch) -> SubjectsBatch
Apply the transform.
The output type always matches the input type.
Parameters:
| Name |
Type |
Description |
Default |
data
|
Any
|
|
required
|
Source code in src/torchio/transforms/transform.py
| def forward(self, data: Any) -> Any:
"""Apply the transform.
The output type always matches the input type.
Args:
data: Input data to transform.
"""
if self.copy:
data = _copy.deepcopy(data)
batch, unwrap = self._wrap(data)
if torch.rand(1).item() > self.p:
return unwrap(batch)
params = self.make_params(batch)
batch = self.apply_transform(batch, params)
# Record history on the batch
trace = AppliedTransform(name=type(self).__name__, params=params)
if not hasattr(batch, "applied_transforms"):
batch.applied_transforms = []
batch.applied_transforms.append(trace)
result = unwrap(batch)
# Propagate history to outputs that can carry it
if (
hasattr(batch, "applied_transforms")
and not isinstance(result, (SubjectsBatch, Tensor, np.ndarray))
and not isinstance(result, dict)
):
with contextlib.suppress(AttributeError):
result.applied_transforms = list(batch.applied_transforms)
return result
|
inverse(params)
Return a transform that undoes this one.
Override in invertible subclasses. The returned transform,
when applied, reverses the effect of the forward pass with
the given parameters.
Parameters:
| Name |
Type |
Description |
Default |
params
|
dict[str, Any]
|
The parameters recorded in the forward pass.
|
required
|
Returns:
| Type |
Description |
Transform
|
A new Transform instance that inverts this one.
|
Source code in src/torchio/transforms/transform.py
| def inverse(self, params: dict[str, Any]) -> Transform:
"""Return a transform that undoes this one.
Override in invertible subclasses. The returned transform,
when applied, reverses the effect of the forward pass with
the given parameters.
Args:
params: The parameters recorded in the forward pass.
Returns:
A new `Transform` instance that inverts this one.
"""
msg = f"{type(self).__name__} is not invertible"
raise NotImplementedError(msg)
|
to_hydra()
Export as a Hydra-compatible config dict.
Returns a dict with _target_ set to the fully qualified
class name and only non-default field values included.
Returns:
| Type |
Description |
dict[str, Any]
|
Dict suitable for hydra.utils.instantiate().
|
Source code in src/torchio/transforms/transform.py
| def to_hydra(self) -> dict[str, Any]:
"""Export as a Hydra-compatible config dict.
Returns a dict with `_target_` set to the fully qualified
class name and only non-default field values included.
Returns:
Dict suitable for `hydra.utils.instantiate()`.
"""
from .parameter_range import _ParameterRange
cls = type(self)
target = f"torchio.{cls.__qualname__}"
cfg: dict[str, Any] = {"_target_": target}
for name, default in _collect_init_params(cls).items():
value = getattr(self, name, default)
if isinstance(value, _ParameterRange):
if value._original == default:
continue
value = _hydra_value(value._original)
elif value == default:
continue
else:
value = _hydra_value(value)
cfg[name] = value
return cfg
|
make_params(batch)
No random parameters.
Source code in src/torchio/transforms/spatial/copy_affine.py
| def make_params(self, batch: SubjectsBatch) -> dict[str, Any]:
"""No random parameters."""
return {}
|
Copy the reference affine to all other images.
Source code in src/torchio/transforms/spatial/copy_affine.py
| def apply_transform(
self,
batch: SubjectsBatch,
params: dict[str, Any],
) -> SubjectsBatch:
"""Copy the reference affine to all other images."""
if self.target not in batch.images:
msg = (
f"Reference image '{self.target}' not found. "
f"Available: {list(batch.images.keys())}"
)
raise KeyError(msg)
ref_affines = batch.images[self.target].affines
for name, img_batch in batch.images.items():
if name == self.target:
continue
for i, affine in enumerate(img_batch.affines):
affine._matrix = copy.deepcopy(ref_affines[i]._matrix)
return batch
|