Line data Source code
1 : /**
2 : * @file test_SoftThresholding.cpp
3 : *
4 : * @brief Tests for the SoftThresholding class
5 : *
6 : * @author Andi Braimllari
7 : */
8 :
9 : #include "Error.h"
10 : #include "SoftThresholding.h"
11 : #include "VolumeDescriptor.h"
12 :
13 : #include "doctest/doctest.h"
14 : #include <testHelpers.h>
15 :
16 : using namespace elsa;
17 : using namespace doctest;
18 :
19 : TEST_SUITE_BEGIN("proximity_operators");
20 :
21 28 : TEST_CASE_TEMPLATE("SoftThresholding: Testing construction", data_t, float, double)
22 : {
23 8 : GIVEN("a DataDescriptor")
24 : {
25 8 : IndexVector_t numCoeff(3);
26 4 : numCoeff << 45, 11, 7;
27 8 : VolumeDescriptor volDescr(numCoeff);
28 :
29 6 : WHEN("instantiating a SoftThresholding operator")
30 : {
31 4 : SoftThresholding<data_t> sThrOp(volDescr);
32 :
33 4 : THEN("the DataDescriptors are equal")
34 : {
35 2 : REQUIRE_EQ(sThrOp.getRangeDescriptor(), volDescr);
36 : }
37 : }
38 :
39 6 : WHEN("cloning a SoftThresholding operator")
40 : {
41 4 : SoftThresholding<data_t> sThrOp(volDescr);
42 4 : auto sThrOpClone = sThrOp.clone();
43 :
44 4 : THEN("cloned SoftThresholding operator equals original SoftThresholding operator")
45 : {
46 2 : REQUIRE_NE(sThrOpClone.get(), &sThrOp);
47 2 : REQUIRE_EQ(*sThrOpClone, sThrOp);
48 : }
49 : }
50 : }
51 4 : }
52 :
53 26 : TEST_CASE_TEMPLATE("SoftThresholding: Testing in 1D", data_t, float, double)
54 : {
55 4 : GIVEN("a DataDescriptor")
56 : {
57 4 : IndexVector_t numCoeff(1);
58 2 : numCoeff << 8;
59 4 : VolumeDescriptor volDescr(numCoeff);
60 :
61 4 : WHEN("Using SoftThresholding operator in 1D")
62 : {
63 4 : SoftThresholding<data_t> sThrOp(volDescr);
64 :
65 4 : THEN("Values under threshold=4 are 0 and values above are sign(v) * (abs(v) - t)")
66 : {
67 4 : Vector_t<data_t> data(volDescr.getNumberOfCoefficients());
68 2 : data << -2, 3, 4, -7, 7, 8, 8, 3;
69 4 : DataContainer<data_t> dataCont(volDescr, data);
70 :
71 4 : Vector_t<data_t> expectedRes(sThrOp.getRangeDescriptor().getNumberOfCoefficients());
72 2 : expectedRes << 0, 0, 0, -3, 3, 4, 4, 0;
73 2 : DataContainer<data_t> dCRes(sThrOp.getRangeDescriptor(), expectedRes);
74 :
75 2 : REQUIRE_UNARY(
76 : isApprox(dCRes, sThrOp.apply(dataCont, geometry::Threshold<data_t>{4})));
77 : }
78 : }
79 : }
80 2 : }
81 :
82 26 : TEST_CASE_TEMPLATE("SoftThresholding: Testing in 3D", data_t, float, double)
83 : {
84 4 : GIVEN("a DataDescriptor")
85 : {
86 4 : IndexVector_t numCoeff(3);
87 2 : numCoeff << 3, 2, 3;
88 4 : VolumeDescriptor volDescr(numCoeff);
89 :
90 4 : WHEN("Using SoftThresholding operator in 3D")
91 : {
92 4 : SoftThresholding<data_t> sThrOp(volDescr);
93 :
94 4 : THEN("Values under threshold=5 are 0 and values above are sign(v) * (abs(v) - t)")
95 : {
96 4 : Vector_t<data_t> data(volDescr.getNumberOfCoefficients());
97 2 : data << 2, 1, 6, 6, 1, 4, 2, -9, 7, 7, 7, 3, 1, 2, 8, 9, -4, 5;
98 4 : DataContainer<data_t> dataCont(volDescr, data);
99 :
100 4 : Vector_t<data_t> expectedRes(sThrOp.getRangeDescriptor().getNumberOfCoefficients());
101 2 : expectedRes << 0, 0, 1, 1, 0, 0, 0, -4, 2, 2, 2, 0, 0, 0, 3, 4, 0, 0;
102 2 : DataContainer<data_t> dCRes(sThrOp.getRangeDescriptor(), expectedRes);
103 :
104 2 : REQUIRE_UNARY(
105 : isApprox(dCRes, sThrOp.apply(dataCont, geometry::Threshold<data_t>{5})));
106 : }
107 : }
108 : }
109 2 : }
110 :
111 32 : TEST_CASE_TEMPLATE("SoftThresholding: Testing general behaviour", data_t, float, double)
112 : {
113 16 : GIVEN("a DataDescriptor")
114 : {
115 16 : IndexVector_t numCoeff(1);
116 8 : numCoeff << 8;
117 16 : VolumeDescriptor volDescr(numCoeff);
118 :
119 16 : WHEN("Using SoftThresholding operator")
120 : {
121 16 : SoftThresholding<data_t> sThrOp(volDescr);
122 :
123 10 : THEN("The zero vector is returned when the zero vector is given")
124 : {
125 4 : Vector_t<data_t> data(volDescr.getNumberOfCoefficients());
126 2 : data << 0, 0, 0, 0, 0, 0, 0, 0;
127 4 : DataContainer<data_t> dataCont(volDescr, data);
128 :
129 4 : Vector_t<data_t> expectedRes(sThrOp.getRangeDescriptor().getNumberOfCoefficients());
130 2 : expectedRes << 0, 0, 0, 0, 0, 0, 0, 0;
131 2 : DataContainer<data_t> dCRes(sThrOp.getRangeDescriptor(), expectedRes);
132 :
133 2 : REQUIRE_UNARY(
134 : isApprox(dCRes, sThrOp.apply(dataCont, geometry::Threshold<data_t>{4})));
135 : }
136 :
137 10 : THEN("SoftThresholding operator throws exception for t = 0")
138 : {
139 4 : Vector_t<data_t> data(volDescr.getNumberOfCoefficients());
140 2 : data << 0, 0, 0, 0, 0, 0, 0, 0;
141 4 : DataContainer<data_t> dC(volDescr, data);
142 :
143 : // actually the geometry::Threshold throws this
144 4 : REQUIRE_THROWS_AS(sThrOp.apply(dC, geometry::Threshold<data_t>{0}),
145 : InvalidArgumentError);
146 : }
147 :
148 10 : THEN("SoftThresholding operator throws exception for t < 0")
149 : {
150 4 : Vector_t<data_t> data(volDescr.getNumberOfCoefficients());
151 2 : data << 0, 0, 0, 0, 0, 0, 0, 0;
152 4 : DataContainer<data_t> dataCont(volDescr, data);
153 :
154 : // actually the geometry::Threshold throws this
155 4 : REQUIRE_THROWS_AS(sThrOp.apply(dataCont, geometry::Threshold<data_t>{-1}),
156 : InvalidArgumentError);
157 : }
158 :
159 10 : THEN("SoftThresholding operator throws exception for differently sized v and prox")
160 : {
161 4 : Vector_t<data_t> data(volDescr.getNumberOfCoefficients());
162 2 : data << 0, 0, 0, 0, 0, 0, 0, 0;
163 4 : DataContainer<data_t> dC(volDescr, data);
164 :
165 4 : IndexVector_t numCoeff1(1);
166 2 : numCoeff1 << 9;
167 4 : VolumeDescriptor volDescr1(numCoeff1);
168 4 : Vector_t<data_t> data1(volDescr1.getNumberOfCoefficients());
169 2 : data1 << 0, 0, 0, 0, 0, 0, 0, 0, 0;
170 4 : DataContainer<data_t> dC1(volDescr1, data1);
171 :
172 4 : REQUIRE_THROWS_AS(sThrOp.apply(dC, geometry::Threshold<data_t>{1}, dC1),
173 : LogicError);
174 : }
175 : }
176 : }
177 8 : }
178 :
179 : TEST_SUITE_END();
|