Passed
Pull Request — main (#605)
by
unknown
03:23
created

test.unit.test_loss_util   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 123
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 10
eloc 76
dl 0
loc 123
rs 10
c 0
b 0
f 0

7 Functions

Rating   Name   Duplication   Size   Complexity  
A test_separable_filter() 0 18 1
A test_negative_loss_mixin() 0 16 1
A test_gaussian_kernel1d_sigma() 0 7 1
A test_triangular_kernel1d() 0 10 2
A test_cauchy_kernel1d() 0 7 1
A test_gaussian_kernel1d_size() 0 10 1
A test_rectangular_kernel1d() 0 5 1

2 Methods

Rating   Name   Duplication   Size   Complexity  
A MinusClass.call() 0 2 1
A MinusClass.__init__() 0 3 1
1
# coding=utf-8
2
3
"""
4
Tests for deepreg/model/loss/label.py in
5
pytest style
6
"""
7
8
from test.unit.util import is_equal_tf
9
10
import numpy as np
11
import pytest
12
import tensorflow as tf
13
14
from deepreg.loss.util import (
15
    NegativeLossMixin,
16
    cauchy_kernel1d,
17
    gaussian_kernel1d_sigma,
18
    gaussian_kernel1d_size,
19
    rectangular_kernel1d,
20
    separable_filter,
21
    triangular_kernel1d,
22
)
23
24
25
@pytest.mark.parametrize("sigma", [1, 3, 2.2])
26
def test_gaussian_kernel1d_sigma(sigma):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
27
    tail = int(sigma * 3)
28
    expected = [np.exp(-0.5 * x ** 2 / sigma ** 2) for x in range(-tail, tail + 1)]
29
    expected = expected / np.sum(expected)
30
    got = gaussian_kernel1d_sigma(sigma)
31
    assert is_equal_tf(got, expected)
32
33
34
@pytest.mark.parametrize("sigma", [1, 3, 2.2])
35
def test_cauchy_kernel1d(sigma):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
36
    tail = int(sigma * 5)
37
    expected = [1 / ((x / sigma) ** 2 + 1) for x in range(-tail, tail + 1)]
38
    expected = expected / np.sum(expected)
39
    got = cauchy_kernel1d(sigma)
40
    assert is_equal_tf(got, expected)
41
42
43
@pytest.mark.parametrize("kernel_size", [3, 7, 11])
44
def test_gaussian_kernel1d_size(kernel_size):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
45
    mean = (kernel_size - 1) / 2.0
46
    sigma = kernel_size / 3
47
48
    grid = tf.range(0, kernel_size, dtype=tf.float32)
49
    expected = tf.exp(-tf.square(grid - mean) / (2 * sigma ** 2))
0 ignored issues
show
introduced by
bad operand type for unary -: object
Loading history...
50
51
    got = gaussian_kernel1d_size(kernel_size)
52
    assert is_equal_tf(got, expected)
53
54
55
@pytest.mark.parametrize("kernel_size", [3, 7, 11])
56
def test_rectangular_kernel1d(kernel_size):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
57
    expected = tf.ones(shape=(kernel_size,), dtype=tf.float32)
58
    got = rectangular_kernel1d(kernel_size)
59
    assert is_equal_tf(got, expected)
60
61
62
@pytest.mark.parametrize("kernel_size", [3, 7, 11])
63
def test_triangular_kernel1d(kernel_size):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
64
    expected = np.zeros(shape=(kernel_size,), dtype=np.float32)
65
    expected[kernel_size // 2] = kernel_size // 2 + 1
66
    for it_k in range(kernel_size // 2):
67
        expected[it_k] = it_k + 1
68
        expected[-it_k - 1] = it_k + 1
69
70
    got = triangular_kernel1d(kernel_size)
71
    assert is_equal_tf(got, expected)
72
73
74
def test_separable_filter():
75
    """
76
    Testing separable filter case where non
77
    zero length tensor is passed to the
78
    function.
79
    """
80
    k = np.ones((3, 3, 3, 3, 1), dtype=np.float32)
81
    array_eye = np.identity(3, dtype=np.float32)
82
    tensor_pred = np.zeros((3, 3, 3, 3, 1), dtype=np.float32)
83
    tensor_pred[:, :, 0, 0, 0] = array_eye
84
    tensor_pred = tf.convert_to_tensor(tensor_pred, dtype=tf.float32)
85
    k = tf.convert_to_tensor(k, dtype=tf.float32)
86
87
    expect = np.ones((3, 3, 3, 3, 1), dtype=np.float32)
88
    expect = tf.convert_to_tensor(expect, dtype=tf.float32)
89
90
    get = separable_filter(tensor_pred, k)
91
    assert is_equal_tf(get, expect)
92
93
94
class MinusClass(tf.keras.losses.Loss):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
95
    def __init__(self):
96
        super().__init__()
97
        self.name = "MinusClass"
98
99
    def call(self, y_true, y_pred):
100
        return y_true - y_pred
101
102
103
class MinusClassLoss(NegativeLossMixin, MinusClass):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
104
    pass
105
106
107
@pytest.mark.parametrize("y_true,y_pred,expected", [(1, 2, 1), (2, 1, -1), (0, 0, 0)])
108
def test_negative_loss_mixin(y_true, y_pred, expected):
0 ignored issues
show
introduced by
"expected, y_pred, y_true" missing in parameter documentation
Loading history...
introduced by
"expected, y_pred, y_true" missing in parameter type documentation
Loading history...
109
    """
110
    Testing NegativeLossMixin class that
111
    inverts the sign of any value
112
    returned by a function
113
    """
114
115
    y_true = tf.constant(y_true, dtype=tf.float32)
116
    y_pred = tf.constant(y_pred, dtype=tf.float32)
117
118
    got = MinusClassLoss().call(
119
        y_true,
120
        y_pred,
121
    )
122
    assert is_equal_tf(got, expected)
123