Passed
Push — master ( ee7d65...860ded )
by Fernando
01:26
created

Resize.apply_transform()   A

Complexity

Conditions 2

Size

Total Lines 21
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 21
rs 9.6
c 0
b 0
f 0
cc 2
nop 2
1
import warnings
2
3
import numpy as np
4
5
from ....utils import to_tuple
6
from ....data.subject import Subject
7
from ....typing import TypeSpatialShape
8
from ... import SpatialTransform
9
from .resample import Resample
10
from .crop_or_pad import CropOrPad
11
12
13
class Resize(SpatialTransform):
14
    """Resample images so the output shape matches the given target shape.
15
16
    The field of view remains the same.
17
18
    Args:
19
        target_shape: Tuple :math:`(W, H, D)`. If a single value :math:`N` is
20
            provided, then :math:`W = H = D = N`.
21
        image_interpolation: See :ref:`Interpolation`.
22
    """
23
    def __init__(
24
            self,
25
            target_shape: TypeSpatialShape,
26
            image_interpolation: str = 'linear',
27
            **kwargs
28
            ):
29
        super().__init__(**kwargs)
30
        self.target_shape = np.asarray(to_tuple(target_shape, length=3))
31
        self.image_interpolation = self.parse_interpolation(
32
            image_interpolation)
33
        self.args_names = (
34
            'target_shape',
35
            'image_interpolation',
36
        )
37
38
    def apply_transform(self, subject: Subject) -> Subject:
39
        shape_in = np.asarray(subject.spatial_shape)
40
        shape_out = self.target_shape
41
        spacing_in = np.asarray(subject.spacing)
42
        spacing_out = shape_in / shape_out * spacing_in
43
        resample = Resample(
44
            spacing_out,
45
            image_interpolation=self.image_interpolation,
46
        )
47
        resampled = resample(subject)
48
        # Sometimes, the output shape is one voxel too large
49
        # Probably because Resample uses np.ceil to compute the shape
50
        if not resampled.spatial_shape == tuple(shape_out):
51
            message = (
52
                f'Output shape {resampled.spatial_shape}'
53
                f' != target shape {tuple(shape_out)}. Fixing with CropOrPad'
54
            )
55
            warnings.warn(message)
56
            crop_pad = CropOrPad(shape_out)
57
            resampled = crop_pad(resampled)
58
        return resampled
59