Line data Source code
1 : /**
2 : * @file test_VolumeDescriptor.cpp
3 : *
4 : * @brief Tests for VolumeDescriptor class
5 : *
6 : * @author Matthias Wieczorek - initial code
7 : * @author David Frank - rewrite to use doctest and BDD
8 : * @author Tobias Lasser - rewrite and added code coverage
9 : * @author Nikola Dinev - tests for automatic descriptor generation
10 : */
11 :
12 : #include "doctest/doctest.h"
13 : #include "Error.h"
14 : #include "VolumeDescriptor.h"
15 : #include "PartitionDescriptor.h"
16 : #include "DescriptorUtils.h"
17 : #include <stdexcept>
18 :
19 : using namespace elsa;
20 : using namespace doctest;
21 :
22 : TEST_SUITE_BEGIN("core");
23 :
24 : TEST_CASE("VolumeDescriptor: Constructing VolumeDescriptors")
25 21 : {
26 21 : GIVEN("various 1D descriptor sizes")
27 21 : {
28 : // Double {{ and }} needed!
29 7 : IndexVector_t validNumCoeff{{20}};
30 7 : RealVector_t validSpacing{{2.5}};
31 7 : RealVector_t invalidSpacing{{3.5, 1.5}};
32 7 : IndexVector_t invalidNumCoeff{{-10}};
33 :
34 7 : WHEN("using a valid number of coefficients and no spacing")
35 7 : {
36 : // Origin of volume
37 2 : const RealVector_t origin = 0.5 * (validNumCoeff.cast<real_t>().array());
38 :
39 2 : const VolumeDescriptor dd(validNumCoeff);
40 :
41 2 : THEN("everything is set correctly")
42 2 : {
43 1 : REQUIRE_EQ(dd.getNumberOfDimensions(), validNumCoeff.size());
44 1 : REQUIRE_EQ(dd.getNumberOfCoefficients(), validNumCoeff.prod());
45 1 : REQUIRE_EQ(dd.getNumberOfCoefficientsPerDimension(), validNumCoeff);
46 1 : REQUIRE_EQ(dd.getSpacingPerDimension(), RealVector_t::Ones(1));
47 1 : REQUIRE_EQ(dd.getLocationOfOrigin(), origin);
48 1 : }
49 :
50 2 : const VolumeDescriptor dd1({20});
51 :
52 2 : THEN("everything is set correctly")
53 2 : {
54 1 : REQUIRE_EQ(dd.getNumberOfDimensions(), validNumCoeff.size());
55 1 : REQUIRE_EQ(dd.getNumberOfCoefficients(), validNumCoeff.prod());
56 1 : REQUIRE_EQ(dd.getNumberOfCoefficientsPerDimension(), validNumCoeff);
57 1 : REQUIRE_EQ(dd.getSpacingPerDimension(), RealVector_t::Ones(1));
58 1 : REQUIRE_EQ(dd.getLocationOfOrigin(), origin);
59 1 : }
60 2 : }
61 :
62 7 : WHEN("using an invalid number of coefficients and no spacing")
63 7 : {
64 1 : THEN("an exception is thrown")
65 1 : {
66 1 : REQUIRE_THROWS_AS(VolumeDescriptor({-10}), InvalidArgumentError);
67 1 : }
68 1 : }
69 :
70 7 : WHEN("using an invalid number of coefficients and valid spacing")
71 7 : {
72 1 : THEN("an exception is thrown")
73 1 : {
74 : // Try all possible combinations of constructors with initializer list
75 1 : REQUIRE_THROWS_AS(VolumeDescriptor(invalidNumCoeff, validSpacing),
76 1 : InvalidArgumentError);
77 1 : REQUIRE_THROWS_AS(VolumeDescriptor({-10}, {2.5}), InvalidArgumentError);
78 1 : }
79 1 : }
80 :
81 7 : WHEN("using a valid number of coefficients and spacing")
82 7 : {
83 : // Origin of volume
84 2 : RealVector_t origin =
85 2 : 0.5 * (validNumCoeff.cast<real_t>().array() * validSpacing.array());
86 :
87 2 : const VolumeDescriptor dd1(validNumCoeff, validSpacing);
88 :
89 2 : THEN("everything is set correctly")
90 2 : {
91 1 : REQUIRE_EQ(dd1.getNumberOfDimensions(), validNumCoeff.size());
92 1 : REQUIRE_EQ(dd1.getNumberOfCoefficients(), validNumCoeff.prod());
93 1 : REQUIRE_EQ(dd1.getNumberOfCoefficientsPerDimension(), validNumCoeff);
94 1 : REQUIRE_EQ(dd1.getSpacingPerDimension(), validSpacing);
95 1 : REQUIRE_EQ(dd1.getLocationOfOrigin(), origin);
96 1 : }
97 :
98 2 : const VolumeDescriptor dd2({20}, {2.5});
99 :
100 2 : THEN("everything is set correctly")
101 2 : {
102 1 : REQUIRE_EQ(dd2.getNumberOfDimensions(), validNumCoeff.size());
103 1 : REQUIRE_EQ(dd2.getNumberOfCoefficients(), validNumCoeff.prod());
104 1 : REQUIRE_EQ(dd2.getNumberOfCoefficientsPerDimension(), validNumCoeff);
105 1 : REQUIRE_EQ(dd2.getSpacingPerDimension(), validSpacing);
106 1 : REQUIRE_EQ(dd2.getLocationOfOrigin(), origin);
107 1 : }
108 2 : }
109 :
110 7 : WHEN("using a valid number of coefficients and mismatched spacing")
111 7 : {
112 1 : THEN("an exception is thrown")
113 1 : {
114 : // Try all possible combinations of constructors
115 1 : REQUIRE_THROWS_AS(VolumeDescriptor(validNumCoeff, invalidSpacing),
116 1 : InvalidArgumentError);
117 1 : REQUIRE_THROWS_AS(VolumeDescriptor({20}, {3.5, 1.5}), InvalidArgumentError);
118 1 : REQUIRE_THROWS_AS(VolumeDescriptor({20}, {-3.5}), InvalidArgumentError);
119 1 : }
120 1 : }
121 7 : }
122 :
123 21 : GIVEN("various 2D descriptor sizes")
124 21 : {
125 7 : IndexVector_t validNumCoeff{{12, 15}};
126 7 : RealVector_t validSpacing{{1.5, 2.5}};
127 7 : RealVector_t invalidSpacing{{1.5}};
128 7 : IndexVector_t invalidNumCoeff{{12, -1, 18}};
129 :
130 7 : WHEN("using a valid number of coefficients and no spacing")
131 7 : {
132 : // Origin of volume
133 2 : RealVector_t origin = 0.5 * (validNumCoeff.cast<real_t>().array());
134 :
135 2 : const VolumeDescriptor dd1(validNumCoeff);
136 :
137 2 : THEN("everything is set correctly")
138 2 : {
139 1 : REQUIRE_EQ(dd1.getNumberOfDimensions(), validNumCoeff.size());
140 1 : REQUIRE_EQ(dd1.getNumberOfCoefficients(), validNumCoeff.prod());
141 1 : REQUIRE_EQ(dd1.getNumberOfCoefficientsPerDimension(), validNumCoeff);
142 1 : REQUIRE_EQ(dd1.getSpacingPerDimension(), RealVector_t::Ones(2));
143 1 : REQUIRE_EQ(dd1.getLocationOfOrigin(), origin);
144 1 : }
145 :
146 2 : const VolumeDescriptor dd2({12, 15});
147 :
148 2 : THEN("everything is set correctly")
149 2 : {
150 1 : REQUIRE_EQ(dd2.getNumberOfDimensions(), validNumCoeff.size());
151 1 : REQUIRE_EQ(dd2.getNumberOfCoefficients(), validNumCoeff.prod());
152 1 : REQUIRE_EQ(dd2.getNumberOfCoefficientsPerDimension(), validNumCoeff);
153 1 : REQUIRE_EQ(dd2.getSpacingPerDimension(), RealVector_t::Ones(2));
154 1 : REQUIRE_EQ(dd2.getLocationOfOrigin(), origin);
155 1 : }
156 2 : }
157 :
158 7 : WHEN("using an invalid number of coefficients and no spacing")
159 7 : {
160 1 : THEN("an exception is thrown")
161 1 : {
162 1 : REQUIRE_THROWS_AS(VolumeDescriptor({12, -1, 18}), InvalidArgumentError);
163 1 : REQUIRE_THROWS_AS(VolumeDescriptor({12, -1}), InvalidArgumentError);
164 1 : }
165 1 : }
166 :
167 7 : WHEN("using an invalid number of coefficients and valid spacing")
168 7 : {
169 1 : IndexVector_t invalidNumCoeff2 = validNumCoeff;
170 1 : invalidNumCoeff2[0] = -1;
171 :
172 1 : THEN("an exception is thrown")
173 1 : {
174 1 : REQUIRE_THROWS_AS(VolumeDescriptor(invalidNumCoeff2, validSpacing),
175 1 : InvalidArgumentError);
176 :
177 1 : REQUIRE_THROWS_AS(VolumeDescriptor({12, -1}, {1.5, 2.5}), InvalidArgumentError);
178 1 : }
179 1 : }
180 :
181 7 : WHEN("using a valid number of coefficients and spacing")
182 7 : {
183 : // Origin of volume
184 2 : RealVector_t origin =
185 2 : 0.5 * (validNumCoeff.cast<real_t>().array() * validSpacing.array());
186 :
187 2 : const VolumeDescriptor dd1(validNumCoeff, validSpacing);
188 :
189 2 : THEN("everything is set correctly")
190 2 : {
191 1 : REQUIRE_EQ(dd1.getNumberOfDimensions(), validNumCoeff.size());
192 1 : REQUIRE_EQ(dd1.getNumberOfCoefficients(), validNumCoeff.prod());
193 1 : REQUIRE_EQ(dd1.getNumberOfCoefficientsPerDimension(), validNumCoeff);
194 1 : REQUIRE_EQ(dd1.getSpacingPerDimension(), validSpacing);
195 1 : REQUIRE_EQ(dd1.getLocationOfOrigin(), origin);
196 1 : }
197 :
198 2 : const VolumeDescriptor dd2({12, 15}, {1.5, 2.5});
199 :
200 2 : THEN("everything is set correctly")
201 2 : {
202 1 : REQUIRE_EQ(dd2.getNumberOfDimensions(), validNumCoeff.size());
203 1 : REQUIRE_EQ(dd2.getNumberOfCoefficients(), validNumCoeff.prod());
204 1 : REQUIRE_EQ(dd2.getNumberOfCoefficientsPerDimension(), validNumCoeff);
205 1 : REQUIRE_EQ(dd2.getSpacingPerDimension(), validSpacing);
206 1 : REQUIRE_EQ(dd2.getLocationOfOrigin(), origin);
207 1 : }
208 2 : }
209 :
210 7 : WHEN("using a valid number of coefficients and mismatched spacing")
211 7 : {
212 1 : THEN("an exception is thrown")
213 1 : {
214 1 : REQUIRE_THROWS_AS(VolumeDescriptor(validNumCoeff, invalidSpacing),
215 1 : InvalidArgumentError);
216 1 : REQUIRE_THROWS_AS(VolumeDescriptor({12, 15}, {-1.5, 2.0}), InvalidArgumentError);
217 1 : REQUIRE_THROWS_AS(VolumeDescriptor({12, 15}, {1.5, 2.0, 3.5}),
218 1 : InvalidArgumentError);
219 1 : }
220 1 : }
221 7 : }
222 :
223 21 : GIVEN("various 3D descriptor sizes")
224 21 : {
225 7 : IndexVector_t validNumCoeff{{12, 15, 25}};
226 7 : RealVector_t validSpacing{{1.5, 2.5, 4.5}};
227 7 : RealVector_t invalidSpacing{{1.5, 2.5}};
228 7 : IndexVector_t invalidNumCoeff{{12, 15, -1}};
229 :
230 7 : WHEN("using a valid number of coefficients and no spacing")
231 7 : {
232 2 : RealVector_t origin = 0.5 * (validNumCoeff.cast<real_t>().array());
233 :
234 2 : const VolumeDescriptor dd1(validNumCoeff);
235 :
236 2 : THEN("everything is set correctly")
237 2 : {
238 1 : REQUIRE_EQ(dd1.getNumberOfDimensions(), validNumCoeff.size());
239 1 : REQUIRE_EQ(dd1.getNumberOfCoefficients(), validNumCoeff.prod());
240 1 : REQUIRE_EQ(dd1.getNumberOfCoefficientsPerDimension(), validNumCoeff);
241 1 : REQUIRE_EQ(dd1.getSpacingPerDimension(), RealVector_t::Ones(3));
242 1 : REQUIRE_EQ(dd1.getLocationOfOrigin(), origin);
243 1 : }
244 :
245 2 : const VolumeDescriptor dd2({12, 15, 25});
246 :
247 2 : THEN("everything is set correctly")
248 2 : {
249 1 : REQUIRE_EQ(dd2.getNumberOfDimensions(), validNumCoeff.size());
250 1 : REQUIRE_EQ(dd2.getNumberOfCoefficients(), validNumCoeff.prod());
251 1 : REQUIRE_EQ(dd2.getNumberOfCoefficientsPerDimension(), validNumCoeff);
252 1 : REQUIRE_EQ(dd2.getSpacingPerDimension(), RealVector_t::Ones(3));
253 1 : REQUIRE_EQ(dd2.getLocationOfOrigin(), origin);
254 1 : }
255 2 : }
256 :
257 7 : WHEN("using an invalid number of coefficients and no spacing")
258 7 : {
259 1 : THEN("an exception is thrown")
260 1 : {
261 1 : REQUIRE_THROWS_AS(VolumeDescriptor({12, 15, -1}), InvalidArgumentError);
262 1 : }
263 1 : }
264 :
265 7 : WHEN("using an invalid number of coefficients and valid spacing")
266 7 : {
267 1 : THEN("an exception is thrown")
268 1 : {
269 1 : REQUIRE_THROWS_AS(VolumeDescriptor(invalidNumCoeff, validSpacing),
270 1 : InvalidArgumentError);
271 1 : REQUIRE_THROWS_AS(VolumeDescriptor({12, 15, -1}, {1.5, 2.5, 4.5}),
272 1 : InvalidArgumentError);
273 1 : REQUIRE_THROWS_AS(VolumeDescriptor({12, 15}, {1.5, 2.5, 4.5}),
274 1 : InvalidArgumentError);
275 1 : }
276 1 : }
277 :
278 7 : WHEN("using a valid number of coefficients and spacing")
279 7 : {
280 2 : RealVector_t origin =
281 2 : 0.5 * (validNumCoeff.cast<real_t>().array() * validSpacing.array());
282 :
283 2 : const VolumeDescriptor dd1(validNumCoeff, validSpacing);
284 :
285 2 : THEN("everything is set correctly")
286 2 : {
287 1 : REQUIRE_EQ(dd1.getNumberOfDimensions(), validNumCoeff.size());
288 1 : REQUIRE_EQ(dd1.getNumberOfCoefficients(), validNumCoeff.prod());
289 1 : REQUIRE_EQ(dd1.getNumberOfCoefficientsPerDimension(), validNumCoeff);
290 1 : REQUIRE_EQ(dd1.getSpacingPerDimension(), validSpacing);
291 1 : REQUIRE_EQ(dd1.getLocationOfOrigin(), origin);
292 1 : }
293 :
294 2 : const VolumeDescriptor dd2({12, 15, 25}, {1.5, 2.5, 4.5});
295 :
296 2 : THEN("everything is set correctly")
297 2 : {
298 1 : REQUIRE_EQ(dd2.getNumberOfDimensions(), validNumCoeff.size());
299 1 : REQUIRE_EQ(dd2.getNumberOfCoefficients(), validNumCoeff.prod());
300 1 : REQUIRE_EQ(dd2.getNumberOfCoefficientsPerDimension(), validNumCoeff);
301 1 : REQUIRE_EQ(dd2.getSpacingPerDimension(), validSpacing);
302 1 : REQUIRE_EQ(dd2.getLocationOfOrigin(), origin);
303 1 : }
304 2 : }
305 :
306 7 : WHEN("using a valid number of coefficients and mismatched spacing")
307 7 : {
308 1 : THEN("an exception is thrown")
309 1 : {
310 1 : REQUIRE_THROWS_AS(VolumeDescriptor(validNumCoeff, invalidSpacing),
311 1 : InvalidArgumentError);
312 1 : REQUIRE_THROWS_AS(VolumeDescriptor({12, 15, 25}, {1.5, 2.5}), InvalidArgumentError);
313 1 : REQUIRE_THROWS_AS(VolumeDescriptor({12, 15, 25}, {1.5, 2.5, -4.5}),
314 1 : InvalidArgumentError);
315 1 : }
316 1 : }
317 7 : }
318 21 : }
319 :
320 : TEST_CASE("VolumeDescriptor: Testing clone()")
321 3 : {
322 3 : GIVEN("1D descriptors")
323 3 : {
324 1 : VolumeDescriptor dd({1, 17});
325 1 : VolumeDescriptor ddWithSpacing({1, 17}, {1, 2.75});
326 :
327 1 : WHEN("cloning the VolumeDescriptor")
328 1 : {
329 1 : auto ddClone = dd.clone();
330 1 : auto ddWithSpacingClone = ddWithSpacing.clone();
331 :
332 1 : THEN("everything matches")
333 1 : {
334 1 : REQUIRE_NE(ddClone.get(), &dd);
335 1 : REQUIRE_EQ(*ddClone, dd);
336 :
337 1 : REQUIRE_NE(ddWithSpacingClone.get(), &ddWithSpacing);
338 1 : REQUIRE_EQ(*ddWithSpacingClone, ddWithSpacing);
339 1 : }
340 1 : }
341 1 : }
342 :
343 3 : GIVEN("2D descriptors")
344 3 : {
345 1 : VolumeDescriptor dd({20, 25});
346 1 : VolumeDescriptor ddWithSpacing({20, 25}, {1.5, 3.5});
347 :
348 1 : WHEN("cloning the VolumeDescriptor")
349 1 : {
350 1 : auto ddClone = dd.clone();
351 1 : auto ddWithSpacingClone = ddWithSpacing.clone();
352 :
353 1 : THEN("everything matches")
354 1 : {
355 1 : REQUIRE_NE(ddClone.get(), &dd);
356 1 : REQUIRE_EQ(*ddClone, dd);
357 :
358 1 : REQUIRE_NE(ddWithSpacingClone.get(), &ddWithSpacing);
359 1 : REQUIRE_EQ(*ddWithSpacingClone, ddWithSpacing);
360 1 : }
361 1 : }
362 1 : }
363 :
364 3 : GIVEN("3D descriptors")
365 3 : {
366 1 : VolumeDescriptor dd({20, 25, 30});
367 1 : VolumeDescriptor ddWithSpacing({20, 25, 30}, {1.5, 3.5, 5.5});
368 :
369 1 : WHEN("cloning the VolumeDescriptor")
370 1 : {
371 1 : auto ddClone = dd.clone();
372 1 : auto ddWithSpacingClone = ddWithSpacing.clone();
373 :
374 1 : THEN("everything matches")
375 1 : {
376 1 : REQUIRE_NE(ddClone.get(), &dd);
377 1 : REQUIRE_EQ(*ddClone, dd);
378 :
379 1 : REQUIRE_NE(ddWithSpacingClone.get(), &ddWithSpacing);
380 1 : REQUIRE_EQ(*ddWithSpacingClone, ddWithSpacing);
381 1 : }
382 1 : }
383 1 : }
384 3 : }
385 :
386 : TEST_CASE("VolumeDescriptor: Testing calculation of Coordinates and indices")
387 6 : {
388 6 : GIVEN("1D descriptors")
389 6 : {
390 2 : IndexVector_t numCoeffs{{11}};
391 :
392 2 : VolumeDescriptor dd(numCoeffs);
393 :
394 2 : WHEN("converting coordinates to indices")
395 2 : {
396 1 : IndexVector_t coordinate1(1);
397 1 : coordinate1 << 0;
398 1 : IndexVector_t coordinate2(1);
399 1 : coordinate2 << numCoeffs(0) - 1;
400 :
401 1 : IndexVector_t coordinateInvalid(2);
402 1 : coordinateInvalid << 2, 1;
403 :
404 1 : THEN("the index is correct")
405 1 : {
406 1 : REQUIRE_EQ(dd.getIndexFromCoordinate(coordinate1), 0);
407 1 : REQUIRE_EQ(dd.getIndexFromCoordinate(coordinate2), numCoeffs(0) - 1);
408 1 : REQUIRE_THROWS_AS(dd.getIndexFromCoordinate(coordinateInvalid),
409 1 : InvalidArgumentError);
410 1 : }
411 1 : }
412 :
413 2 : WHEN("converting indices to coordinates")
414 2 : {
415 1 : index_t index1 = 0;
416 1 : index_t index2 = numCoeffs(0) - 1;
417 1 : index_t indexInvalid1 = -2;
418 1 : index_t indexInvalid2 = numCoeffs(0);
419 :
420 1 : THEN("the coordinate is correct")
421 1 : {
422 1 : REQUIRE_EQ(dd.getCoordinateFromIndex(index1), IndexVector_t::Constant(1, 0));
423 1 : REQUIRE_EQ(dd.getCoordinateFromIndex(index2),
424 1 : IndexVector_t::Constant(1, numCoeffs(0) - 1));
425 1 : REQUIRE_THROWS_AS(dd.getCoordinateFromIndex(indexInvalid1), InvalidArgumentError);
426 1 : REQUIRE_THROWS_AS(dd.getCoordinateFromIndex(indexInvalid2), InvalidArgumentError);
427 1 : }
428 1 : }
429 2 : }
430 :
431 6 : GIVEN("2D descriptors")
432 6 : {
433 2 : IndexVector_t numCoeffs{{11, 15}};
434 2 : VolumeDescriptor dd(numCoeffs);
435 :
436 2 : WHEN("converting coordinates to indices")
437 2 : {
438 1 : IndexVector_t coordinate1(2);
439 1 : coordinate1 << 0, 0;
440 1 : IndexVector_t coordinate2(2);
441 1 : coordinate2 << 0, numCoeffs(1) - 1;
442 1 : IndexVector_t coordinate3(2);
443 1 : coordinate3 << numCoeffs(0) - 1, numCoeffs(1) - 1;
444 :
445 1 : IndexVector_t coordinateInvalid(1);
446 1 : coordinateInvalid << 5;
447 :
448 1 : THEN("the index is correct")
449 1 : {
450 1 : REQUIRE_EQ(dd.getIndexFromCoordinate(coordinate1), 0);
451 1 : REQUIRE_EQ(dd.getIndexFromCoordinate(coordinate2),
452 1 : numCoeffs(0) * (numCoeffs(1) - 1));
453 1 : REQUIRE_EQ(dd.getIndexFromCoordinate(coordinate3),
454 1 : numCoeffs(0) - 1 + numCoeffs(0) * (numCoeffs(1) - 1));
455 1 : REQUIRE_THROWS_AS(dd.getIndexFromCoordinate(coordinateInvalid),
456 1 : InvalidArgumentError);
457 1 : }
458 1 : }
459 :
460 2 : WHEN("converting indices to coordinates")
461 2 : {
462 1 : index_t index1 = 0;
463 1 : index_t index2 = numCoeffs(0) - 1;
464 1 : index_t index3 = numCoeffs(0) * (numCoeffs(1) - 1) + (numCoeffs(0) - 3);
465 1 : index_t indexInvalid1 = -1;
466 1 : index_t indexInvalid2 = numCoeffs(0) * numCoeffs(1);
467 :
468 1 : THEN("the coordinate is correct")
469 1 : {
470 1 : IndexVector_t coordinate1(2);
471 1 : coordinate1 << 0, 0;
472 1 : REQUIRE_EQ(dd.getCoordinateFromIndex(index1), coordinate1);
473 :
474 1 : IndexVector_t coordinate2(2);
475 1 : coordinate2 << numCoeffs(0) - 1, 0;
476 1 : REQUIRE_EQ(dd.getCoordinateFromIndex(index2), coordinate2);
477 :
478 1 : IndexVector_t coordinate3(2);
479 1 : coordinate3 << numCoeffs(0) - 3, numCoeffs(1) - 1;
480 1 : REQUIRE_EQ(dd.getCoordinateFromIndex(index3), coordinate3);
481 :
482 1 : REQUIRE_THROWS_AS(dd.getCoordinateFromIndex(indexInvalid1), InvalidArgumentError);
483 1 : REQUIRE_THROWS_AS(dd.getCoordinateFromIndex(indexInvalid2), InvalidArgumentError);
484 1 : }
485 1 : }
486 2 : }
487 :
488 6 : GIVEN("3D descriptors")
489 6 : {
490 2 : IndexVector_t numCoeffs{{9, 13, 17}};
491 2 : VolumeDescriptor dd(numCoeffs);
492 :
493 2 : WHEN("converting coordinates to indices")
494 2 : {
495 1 : IndexVector_t coordinate1(3);
496 1 : coordinate1 << 0, 0, 0;
497 1 : IndexVector_t coordinate2(3);
498 1 : coordinate2 << numCoeffs(0) - 2, 0, 0;
499 1 : IndexVector_t coordinate3(3);
500 1 : coordinate3 << numCoeffs(0) - 5, numCoeffs(1) - 3, 0;
501 1 : IndexVector_t coordinate4(3);
502 1 : coordinate4 << numCoeffs(0) - 4, numCoeffs(1) - 2, numCoeffs(2) - 1;
503 :
504 1 : IndexVector_t coordinateInvalid(2);
505 1 : coordinateInvalid << 2, 2;
506 :
507 1 : THEN("the index is correct")
508 1 : {
509 1 : REQUIRE_EQ(dd.getIndexFromCoordinate(coordinate1), 0);
510 1 : REQUIRE_EQ(dd.getIndexFromCoordinate(coordinate2), numCoeffs(0) - 2);
511 1 : REQUIRE_EQ(dd.getIndexFromCoordinate(coordinate3),
512 1 : numCoeffs(0) - 5 + numCoeffs(0) * (numCoeffs(1) - 3));
513 1 : REQUIRE_EQ(dd.getIndexFromCoordinate(coordinate4),
514 1 : numCoeffs(0) - 4 + numCoeffs(0) * (numCoeffs(1) - 2)
515 1 : + numCoeffs(0) * numCoeffs(1) * (numCoeffs(2) - 1));
516 1 : REQUIRE_THROWS_AS(dd.getIndexFromCoordinate(coordinateInvalid),
517 1 : InvalidArgumentError);
518 1 : }
519 1 : }
520 :
521 2 : WHEN("converting indices to coordinates")
522 2 : {
523 1 : index_t index1 = 0;
524 1 : index_t index2 = numCoeffs(0) - 7;
525 1 : index_t index3 = numCoeffs(0) - 6 + numCoeffs(0) * (numCoeffs(1) - 8);
526 1 : index_t index4 = numCoeffs(0) - 5 + numCoeffs(0) * (numCoeffs(1) - 7)
527 1 : + numCoeffs(0) * numCoeffs(1) * (numCoeffs(2) - 3);
528 1 : index_t indexInvalid1 = -3;
529 1 : index_t indexInvalid2 = numCoeffs(0) * numCoeffs(1) * numCoeffs(2);
530 :
531 1 : THEN("the coordinate is correct")
532 1 : {
533 1 : IndexVector_t coordinate1(3);
534 1 : coordinate1 << 0, 0, 0;
535 1 : REQUIRE_EQ(dd.getCoordinateFromIndex(index1), coordinate1);
536 :
537 1 : IndexVector_t coordinate2(3);
538 1 : coordinate2 << numCoeffs(0) - 7, 0, 0;
539 1 : REQUIRE_EQ(dd.getCoordinateFromIndex(index2), coordinate2);
540 :
541 1 : IndexVector_t coordinate3(3);
542 1 : coordinate3 << numCoeffs(0) - 6, numCoeffs(1) - 8, 0;
543 1 : REQUIRE_EQ(dd.getCoordinateFromIndex(index3), coordinate3);
544 :
545 1 : IndexVector_t coordinate4(3);
546 1 : coordinate4 << numCoeffs(0) - 5, numCoeffs(1) - 7, numCoeffs(2) - 3;
547 1 : REQUIRE_EQ(dd.getCoordinateFromIndex(index4), coordinate4);
548 :
549 1 : REQUIRE_THROWS_AS(dd.getCoordinateFromIndex(indexInvalid1), InvalidArgumentError);
550 1 : REQUIRE_THROWS_AS(dd.getCoordinateFromIndex(indexInvalid2), InvalidArgumentError);
551 1 : }
552 1 : }
553 2 : }
554 6 : }
555 :
556 : TEST_CASE("VolumeDescriptor: Finding the best common descriptor")
557 10 : {
558 10 : IndexVector_t numCoeffs{{9, 13, 17}};
559 10 : VolumeDescriptor dd{numCoeffs};
560 :
561 10 : GIVEN("an empty descriptor list")
562 10 : {
563 1 : THEN("trying to determine the best common descriptor throws an error")
564 1 : {
565 1 : REQUIRE_THROWS_AS(bestCommon(std::vector<const DataDescriptor*>{}),
566 1 : InvalidArgumentError);
567 1 : }
568 1 : }
569 :
570 10 : GIVEN("a single descriptor")
571 10 : {
572 1 : PartitionDescriptor pd{dd, 5};
573 1 : THEN("the best common descriptor is the descriptor itself")
574 1 : {
575 1 : auto common1 = bestCommon(dd);
576 1 : auto common2 = bestCommon(pd);
577 :
578 1 : REQUIRE_EQ(*common1, dd);
579 1 : REQUIRE_EQ(*common2, pd);
580 1 : }
581 1 : }
582 :
583 10 : GIVEN("two equal PartitionDescriptors")
584 10 : {
585 1 : PartitionDescriptor pd1{dd, 5};
586 1 : PartitionDescriptor pd2{dd, 5};
587 :
588 1 : THEN("the best common descriptor is the same as the input descriptors")
589 1 : {
590 1 : auto common = bestCommon(pd1, pd2);
591 1 : REQUIRE_EQ(pd1, *common);
592 1 : REQUIRE_EQ(pd2, *common);
593 1 : }
594 1 : }
595 :
596 10 : GIVEN("a PartitionDescriptor and its base")
597 10 : {
598 1 : PartitionDescriptor pd{dd, 5};
599 :
600 1 : THEN("the best common descriptor is the base descriptor")
601 1 : {
602 1 : auto common1 = bestCommon(pd, dd);
603 1 : auto common2 = bestCommon(dd, pd);
604 :
605 1 : REQUIRE_EQ(*common1, dd);
606 1 : REQUIRE_EQ(*common2, dd);
607 1 : }
608 1 : }
609 :
610 10 : GIVEN("a PartitionDescriptor and its base but with different spacing")
611 10 : {
612 1 : VolumeDescriptor dds2{numCoeffs, dd.getSpacingPerDimension() * 2};
613 1 : PartitionDescriptor pd{dd, 5};
614 1 : PartitionDescriptor pds2{dds2, 5};
615 :
616 1 : THEN("the best common descriptor is the base descriptor with default spacing")
617 1 : {
618 1 : auto common1 = bestCommon(pd, dds2);
619 1 : auto common2 = bestCommon(dds2, pd);
620 1 : auto common3 = bestCommon(pds2, dd);
621 1 : auto common4 = bestCommon(dd, pds2);
622 :
623 1 : REQUIRE_EQ(*common1, dd);
624 1 : REQUIRE_EQ(*common2, dd);
625 1 : REQUIRE_EQ(*common3, dd);
626 1 : REQUIRE_EQ(*common4, dd);
627 1 : }
628 1 : }
629 :
630 10 : GIVEN("two equal non-block descriptors")
631 10 : {
632 1 : VolumeDescriptor dd2{numCoeffs};
633 :
634 1 : THEN("the best common descriptor is the same as the input descriptors")
635 1 : {
636 1 : auto common = bestCommon(dd, dd2);
637 :
638 1 : REQUIRE_EQ(*common, dd);
639 1 : }
640 1 : }
641 :
642 10 : GIVEN("two non-block descriptors that differ only in spacing")
643 10 : {
644 1 : VolumeDescriptor dds2{numCoeffs, dd.getSpacingPerDimension() * 2};
645 1 : VolumeDescriptor dds3{numCoeffs, dd.getSpacingPerDimension() * 3};
646 :
647 1 : THEN("the best common descriptor is the base descriptor with default spacing")
648 1 : {
649 1 : auto common1 = bestCommon(dds2, dds3);
650 1 : auto common2 = bestCommon(dds3, dds2);
651 :
652 1 : REQUIRE_EQ(*common1, dd);
653 1 : REQUIRE_EQ(*common2, dd);
654 1 : }
655 1 : }
656 :
657 10 : GIVEN("two descriptors with same number of dimensions and size but different number of "
658 10 : "coefficients per dimensions")
659 10 : {
660 1 : IndexVector_t numCoeffs2 = numCoeffs.reverse();
661 :
662 1 : VolumeDescriptor dd2{numCoeffs2};
663 1 : VolumeDescriptor dds2{numCoeffs, dd.getSpacingPerDimension() * 2};
664 1 : VolumeDescriptor dd2s2{numCoeffs2, dd2.getSpacingPerDimension() * 2};
665 :
666 1 : THEN("the best common descriptor is the linearized descriptor with default spacing")
667 1 : {
668 1 : auto common1 = bestCommon(dd2, dd);
669 1 : auto common2 = bestCommon(dd, dd2);
670 1 : auto common3 = bestCommon(dds2, dd2s2);
671 1 : auto common4 = bestCommon(dd2s2, dds2);
672 :
673 1 : VolumeDescriptor expected{IndexVector_t::Constant(1, dd.getNumberOfCoefficients())};
674 1 : REQUIRE_EQ(*common1, expected);
675 1 : REQUIRE_EQ(*common2, expected);
676 1 : REQUIRE_EQ(*common3, expected);
677 1 : REQUIRE_EQ(*common4, expected);
678 1 : }
679 1 : }
680 :
681 10 : GIVEN("two descriptors with different number of dimensions but same size")
682 10 : {
683 1 : IndexVector_t numCoeffs2 = numCoeffs.head(numCoeffs.size() - 1);
684 1 : numCoeffs2[numCoeffs2.size() - 1] *= numCoeffs[numCoeffs.size() - 1];
685 1 : VolumeDescriptor dd2{numCoeffs2};
686 :
687 1 : THEN("the best common descriptor is the linearized descriptor with default spacing")
688 1 : {
689 1 : auto common1 = bestCommon(dd2, dd);
690 1 : auto common2 = bestCommon(dd, dd2);
691 :
692 1 : VolumeDescriptor expected{IndexVector_t::Constant(1, dd.getNumberOfCoefficients())};
693 1 : REQUIRE_EQ(*common1, expected);
694 1 : REQUIRE_EQ(*common2, expected);
695 1 : }
696 1 : }
697 :
698 10 : GIVEN("two descriptors with different sizes")
699 10 : {
700 1 : IndexVector_t numCoeffs2 = numCoeffs;
701 1 : numCoeffs2[0] += 1;
702 1 : VolumeDescriptor dd2{numCoeffs2};
703 :
704 1 : THEN("trying to determine the best common descriptor throws an error")
705 1 : {
706 1 : REQUIRE_THROWS_AS(bestCommon(dd2, dd), InvalidArgumentError);
707 1 : REQUIRE_THROWS_AS(bestCommon(dd, dd2), InvalidArgumentError);
708 1 : }
709 1 : }
710 10 : }
711 :
712 : TEST_SUITE_END();
|