Passed
Pull Request — master (#246)
by Fernando
01:46
created

tests.utils.TorchioTestCase.flip_affine_x()   A

Complexity

Conditions 2

Size

Total Lines 5
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nop 2
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
import copy
2
import shutil
3
import random
4
import tempfile
5
import unittest
6
from pathlib import Path
7
8
import torch
9
import numpy as np
10
import nibabel as nib
11
from torchio.datasets import IXITiny
12
from torchio import DATA, AFFINE, ScalarImage, LabelMap, ImagesDataset, Subject
13
14
15
class TorchioTestCase(unittest.TestCase):
16
17
    def setUp(self):
18
        """Set up test fixtures, if any."""
19
        self.dir = Path(tempfile.gettempdir()) / '.torchio_tests'
20
        self.dir.mkdir(exist_ok=True)
21
        random.seed(42)
22
        np.random.seed(42)
23
24
        registration_matrix = np.array([
25
            [1, 0, 0, 10],
26
            [0, 1, 0, 0],
27
            [0, 0, 1.2, 0],
28
            [0, 0, 0, 1]
29
        ])
30
31
        subject_a = Subject(
32
            t1=ScalarImage(self.get_image_path('t1_a')),
33
        )
34
        subject_b = Subject(
35
            t1=ScalarImage(self.get_image_path('t1_b')),
36
            label=LabelMap(self.get_image_path('label_b', binary=True)),
37
        )
38
        subject_c = Subject(
39
            label=LabelMap(self.get_image_path('label_c', binary=True)),
40
        )
41
        subject_d = Subject(
42
            t1=ScalarImage(
43
                self.get_image_path('t1_d'),
44
                pre_affine=registration_matrix,
45
            ),
46
            t2=ScalarImage(self.get_image_path('t2_d')),
47
            label=LabelMap(self.get_image_path('label_d', binary=True)),
48
        )
49
        subject_a4 = Subject(
50
            t1=ScalarImage(self.get_image_path('t1_a'), components=2),
51
        )
52
        self.subjects_list = [
53
            subject_a,
54
            subject_a4,
55
            subject_b,
56
            subject_c,
57
            subject_d,
58
        ]
59
        self.dataset = ImagesDataset(self.subjects_list)
60
        self.sample = self.dataset[-1]  # subject_d
61
62
    def make_2d(self, sample):
63
        sample = copy.deepcopy(sample)
64
        for image in sample.get_images(intensity_only=False):
65
            image[DATA] = image[DATA][:, 0:1, ...]
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable DATA does not seem to be defined.
Loading history...
66
        return sample
67
68
    def make_4d(self, sample):
69
        sample = copy.deepcopy(sample)
70
        for image in sample.get_images(intensity_only=False):
71
            image[DATA] = torch.cat(4 * (image[DATA],))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable DATA does not seem to be defined.
Loading history...
72
        return sample
73
74
    def flip_affine_x(self, sample):
75
        sample = copy.deepcopy(sample)
76
        for image in sample.get_images(intensity_only=False):
77
            image[AFFINE] = np.diag((-1, 1, 1, 1)) @ image[AFFINE]
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable AFFINE does not seem to be defined.
Loading history...
78
        return sample
79
80
    def get_inconsistent_sample(self):
81
        """Return a sample containing images of different shape."""
82
        subject = Subject(
83
            t1=ScalarImage(self.get_image_path('t1_inc')),
84
            t2=ScalarImage(
85
                self.get_image_path('t2_inc', shape=(10, 20, 31))),
86
            label=LabelMap(
87
                self.get_image_path(
88
                    'label_inc',
89
                    shape=(8, 17, 25),
90
                    binary=True,
91
                ),
92
            ),
93
            label2=LabelMap(
94
                self.get_image_path(
95
                    'label2_inc',
96
                    shape=(18, 17, 25),
97
                    binary=True,
98
                ),
99
            ),
100
        )
101
        return subject
102
103
    def get_reference_image_and_path(self):
104
        """Return a reference image and its path"""
105
        path = self.get_image_path('ref', shape=(10, 20, 31), spacing=(1, 1, 2))
106
        image = ScalarImage(path)
107
        return image, path
108
109
    def tearDown(self):
110
        """Tear down test fixtures, if any."""
111
        shutil.rmtree(self.dir)
112
113
    def get_ixi_tiny(self):
114
        root_dir = Path(tempfile.gettempdir()) / 'torchio' / 'ixi_tiny'
115
        return IXITiny(root_dir, download=True)
116
117
    def get_image_path(
118
            self,
119
            stem,
120
            binary=False,
121
            shape=(10, 20, 30),
122
            spacing=(1, 1, 1),
123
            components=1,
124
            ):
125
        data = np.random.rand(components, *shape)
126
        if binary:
127
            data = (data > 0.5).astype(np.uint8)
128
        affine = np.diag((*spacing, 1))
129
        suffix = random.choice(('.nii.gz', '.nii', '.nrrd', '.img'))
130
        path = self.dir / f'{stem}{suffix}'
131
        if np.random.rand() > 0.5:
132
            path = str(path)
133
        image = ScalarImage(tensor=data, affine=affine)
134
        image.save(path)
135
        return path
136
137
    def assertTensorNotEqual(self, a, b, message=None):
138
        if a.shape != b.shape:
139
            return
140
        # There must be better ways to do this
141
        if message is None:
142
            assert not torch.all(torch.eq(a, b))
143
        else:
144
            assert not torch.all(torch.eq(a, b)), message
145