Passed
Push — master ( 53ab14...c2608f )
by Fernando
01:07
created

tests.utils.TorchioTestCase.get_image_path()   B

Complexity

Conditions 6

Size

Total Lines 25
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 24
nop 8
dl 0
loc 25
rs 8.3706
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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 numpy.testing import assert_array_equal, assert_raises
12
from torchio.datasets import IXITiny
13
from torchio import DATA, AFFINE, ScalarImage, LabelMap, SubjectsDataset, Subject
14
15
16
class TorchioTestCase(unittest.TestCase):
17
18
    def setUp(self):
19
        """Set up test fixtures, if any."""
20
        self.dir = Path(tempfile.gettempdir()) / '.torchio_tests'
21
        self.dir.mkdir(exist_ok=True)
22
        random.seed(42)
23
        np.random.seed(42)
24
25
        registration_matrix = np.array([
26
            [1, 0, 0, 10],
27
            [0, 1, 0, 0],
28
            [0, 0, 1.2, 0],
29
            [0, 0, 0, 1]
30
        ])
31
32
        subject_a = Subject(
33
            t1=ScalarImage(self.get_image_path('t1_a')),
34
        )
35
        subject_b = Subject(
36
            t1=ScalarImage(self.get_image_path('t1_b')),
37
            label=LabelMap(self.get_image_path('label_b', binary=True)),
38
        )
39
        subject_c = Subject(
40
            label=LabelMap(self.get_image_path('label_c', binary=True)),
41
        )
42
        subject_d = Subject(
43
            t1=ScalarImage(
44
                self.get_image_path('t1_d'),
45
                pre_affine=registration_matrix,
46
            ),
47
            t2=ScalarImage(self.get_image_path('t2_d')),
48
            label=LabelMap(self.get_image_path('label_d', binary=True)),
49
        )
50
        subject_a4 = Subject(
51
            t1=ScalarImage(self.get_image_path('t1_a'), components=2),
52
        )
53
        self.subjects_list = [
54
            subject_a,
55
            subject_a4,
56
            subject_b,
57
            subject_c,
58
            subject_d,
59
        ]
60
        self.dataset = SubjectsDataset(self.subjects_list)
61
        self.sample = self.dataset[-1]  # subject_d
62
63
    def make_2d(self, sample):
64
        sample = copy.deepcopy(sample)
65
        for image in sample.get_images(intensity_only=False):
66
            image[DATA] = image[DATA][..., :1]
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable DATA does not seem to be defined.
Loading history...
67
        return sample
68
69
    def make_4d(self, sample):
70
        sample = copy.deepcopy(sample)
71
        for image in sample.get_images(intensity_only=False):
72
            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...
73
        return sample
74
75
    def flip_affine_x(self, sample):
76
        sample = copy.deepcopy(sample)
77
        for image in sample.get_images(intensity_only=False):
78
            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...
79
        return sample
80
81
    def get_inconsistent_sample(self):
82
        """Return a sample containing images of different shape."""
83
        subject = Subject(
84
            t1=ScalarImage(self.get_image_path('t1_inc')),
85
            t2=ScalarImage(
86
                self.get_image_path('t2_inc', shape=(10, 20, 31))),
87
            label=LabelMap(
88
                self.get_image_path(
89
                    'label_inc',
90
                    shape=(8, 17, 25),
91
                    binary=True,
92
                ),
93
            ),
94
            label2=LabelMap(
95
                self.get_image_path(
96
                    'label2_inc',
97
                    shape=(18, 17, 25),
98
                    binary=True,
99
                ),
100
            ),
101
        )
102
        return subject
103
104
    def get_reference_image_and_path(self):
105
        """Return a reference image and its path"""
106
        path = self.get_image_path('ref', shape=(10, 20, 31), spacing=(1, 1, 2))
107
        image = ScalarImage(path)
108
        return image, path
109
110
    def get_sample_with_partial_volume_label_map(self, components=1):
111
        """Return a sample with a partial-volume label map."""
112
        return Subject(
113
            t1=ScalarImage(
114
                self.get_image_path('t1_d'),
115
            ),
116
            label=LabelMap(
117
                self.get_image_path(
118
                    'label_d2', binary=False, components=components
119
                )
120
            ),
121
        )
122
123
    def tearDown(self):
124
        """Tear down test fixtures, if any."""
125
        shutil.rmtree(self.dir)
126
127
    def get_ixi_tiny(self):
128
        root_dir = Path(tempfile.gettempdir()) / 'torchio' / 'ixi_tiny'
129
        return IXITiny(root_dir, download=True)
130
131
    def get_image_path(
132
            self,
133
            stem,
134
            binary=False,
135
            shape=(10, 20, 30),
136
            spacing=(1, 1, 1),
137
            components=1,
138
            add_nans=False,
139
            suffix=None,
140
            ):
141
        shape = (*shape, 1) if len(shape) == 2 else shape
142
        data = np.random.rand(components, *shape)
143
        if binary:
144
            data = (data > 0.5).astype(np.uint8)
145
        if add_nans:
146
            data[:] = np.nan
147
        affine = np.diag((*spacing, 1))
148
        if suffix is None:
149
            suffix = random.choice(('.nii.gz', '.nii', '.nrrd', '.img'))
150
        path = self.dir / f'{stem}{suffix}'
151
        if np.random.rand() > 0.5:
152
            path = str(path)
153
        image = ScalarImage(tensor=data, affine=affine, check_nans=not add_nans)
154
        image.save(path)
155
        return path
156
157
    def assertTensorNotEqual(self, *args, **kwargs):
158
        assert_raises(AssertionError, assert_array_equal, *args, **kwargs)
159
160
    def assertTensorEqual(self, *args, **kwargs):
161
        assert_array_equal(*args, **kwargs)
162