Line data Source code
1 : /**
2 : * @file test_RandomBlocksDescriptor.cpp
3 : *
4 : * @brief Tests for RandomBlocksDescriptor class
5 : *
6 : * @author Nikola Dinev
7 : */
8 :
9 : #include "doctest/doctest.h"
10 : #include "RandomBlocksDescriptor.h"
11 : #include "VolumeDescriptor.h"
12 : #include "TypeCasts.hpp"
13 :
14 : #include <stdexcept>
15 :
16 : using namespace elsa;
17 : using namespace doctest;
18 :
19 : TEST_SUITE_BEGIN("core");
20 :
21 27 : TEST_CASE("RandomBlocksDescriptors: Testing constructions")
22 : {
23 28 : GIVEN("0 an empty descriptor list")
24 : {
25 2 : THEN("construction of a RandomBlocksDescriptor fails")
26 : {
27 4 : REQUIRE_THROWS(RandomBlocksDescriptor(std::vector<std::unique_ptr<DataDescriptor>>(0)));
28 : }
29 : }
30 35 : GIVEN("five 1D descriptors")
31 : {
32 8 : index_t blocks = 5;
33 16 : std::vector<std::unique_ptr<DataDescriptor>> descriptors(0);
34 :
35 8 : index_t size = 0;
36 16 : IndexVector_t offsets(blocks);
37 8 : offsets[0] = 0;
38 48 : for (index_t i = 0; i < blocks; i++) {
39 40 : index_t n = 1 + std::rand() % 100;
40 : descriptors.emplace_back(
41 40 : std::make_unique<VolumeDescriptor>(IndexVector_t::Constant(1, n)));
42 40 : size += n;
43 40 : if (i != blocks - 1)
44 32 : offsets[i + 1] = offsets[i] + n;
45 : }
46 :
47 13 : WHEN("creating a RandomBlocksDescriptor containing these descriptors")
48 : {
49 10 : RandomBlocksDescriptor bd(descriptors);
50 :
51 6 : THEN("there are 5 blocks of the correct size")
52 : {
53 1 : REQUIRE_EQ(bd.getNumberOfBlocks(), blocks);
54 :
55 6 : for (index_t i = 0; i < blocks; ++i)
56 5 : REQUIRE_EQ(bd.getDescriptorOfBlock(i),
57 : *descriptors[static_cast<std::size_t>(i)]);
58 :
59 2 : REQUIRE_THROWS(bd.getDescriptorOfBlock(blocks));
60 : }
61 :
62 6 : THEN("the new RandomBlocksDescriptor has the correct sizes")
63 : {
64 1 : REQUIRE_EQ(bd.getNumberOfDimensions(), 1);
65 :
66 1 : IndexVector_t correctSize = IndexVector_t::Constant(1, size);
67 1 : REQUIRE_EQ(bd.getNumberOfCoefficientsPerDimension(), correctSize);
68 1 : REQUIRE_EQ(bd.getNumberOfCoefficients(), correctSize.prod());
69 :
70 1 : REQUIRE_EQ(bd.getSpacingPerDimension().size(), 1);
71 1 : REQUIRE_EQ(bd.getSpacingPerDimension()[0], 1.0);
72 : }
73 :
74 6 : THEN("the block offsets are correct")
75 : {
76 6 : for (index_t i = 0; i < blocks; ++i)
77 5 : REQUIRE_EQ(bd.getOffsetOfBlock(i), offsets[i]);
78 :
79 2 : REQUIRE_THROWS(bd.getOffsetOfBlock(blocks));
80 : }
81 :
82 6 : THEN("the block descriptor is different from a monolithic descriptor with the same "
83 : "dimensions")
84 : {
85 2 : IndexVector_t size = IndexVector_t::Constant(1, bd.getNumberOfCoefficients());
86 2 : VolumeDescriptor dd(size);
87 1 : REQUIRE_NE(bd, dd);
88 1 : REQUIRE_NE(dd, bd);
89 : }
90 :
91 6 : THEN("the block descriptor is different from a RandomBlocksDescriptor with the same "
92 : "size but a different number of blocks")
93 : {
94 2 : IndexVector_t size = IndexVector_t::Constant(1, bd.getNumberOfCoefficients());
95 2 : VolumeDescriptor dd(size);
96 2 : std::vector<std::unique_ptr<DataDescriptor>> vec;
97 1 : vec.push_back(dd.clone());
98 2 : RandomBlocksDescriptor bd2(vec);
99 1 : REQUIRE_NE(bd, bd2);
100 1 : REQUIRE_NE(bd2, bd);
101 : }
102 : }
103 :
104 11 : WHEN("creating a RandomBlocksDescriptor containing these descriptors by moving")
105 : {
106 6 : std::vector<std::unique_ptr<DataDescriptor>> tmp(0);
107 18 : for (const auto& desc : descriptors)
108 15 : tmp.push_back(desc->clone());
109 :
110 6 : RandomBlocksDescriptor bd(std::move(tmp));
111 :
112 4 : THEN("there are 5 blocks of the correct size")
113 : {
114 1 : REQUIRE_EQ(bd.getNumberOfBlocks(), blocks);
115 :
116 6 : for (index_t i = 0; i < blocks; ++i)
117 5 : REQUIRE_EQ(bd.getDescriptorOfBlock(i),
118 : *descriptors[static_cast<std::size_t>(i)]);
119 :
120 2 : REQUIRE_THROWS(bd.getDescriptorOfBlock(blocks));
121 : }
122 :
123 4 : THEN("the new RandomBlocksDescriptor has the correct sizes")
124 : {
125 1 : REQUIRE_EQ(bd.getNumberOfDimensions(), 1);
126 :
127 1 : IndexVector_t correctSize = IndexVector_t::Constant(1, size);
128 1 : REQUIRE_EQ(bd.getNumberOfCoefficientsPerDimension(), correctSize);
129 1 : REQUIRE_EQ(bd.getNumberOfCoefficients(), correctSize.prod());
130 :
131 1 : REQUIRE_EQ(bd.getSpacingPerDimension().size(), 1);
132 1 : REQUIRE_EQ(bd.getSpacingPerDimension()[0], 1.0);
133 : }
134 :
135 4 : THEN("the block offsets are correct")
136 : {
137 6 : for (index_t i = 0; i < blocks; ++i)
138 5 : REQUIRE_EQ(bd.getOffsetOfBlock(i), offsets[i]);
139 :
140 2 : REQUIRE_THROWS(bd.getOffsetOfBlock(blocks));
141 : }
142 : }
143 : }
144 :
145 36 : GIVEN("ten 2D descriptors")
146 : {
147 9 : index_t blocks = 10;
148 18 : std::vector<std::unique_ptr<DataDescriptor>> descriptors(0);
149 :
150 9 : index_t size = 0;
151 18 : IndexVector_t offsets(blocks);
152 9 : offsets[0] = 0;
153 99 : for (index_t i = 0; i < blocks; i++) {
154 180 : IndexVector_t coeffs(2);
155 90 : coeffs << 1 + std::rand() % 100, 1 + std::rand() % 100;
156 90 : descriptors.emplace_back(std::make_unique<VolumeDescriptor>(coeffs));
157 90 : size += coeffs.prod();
158 90 : if (i != blocks - 1)
159 81 : offsets[i + 1] = offsets[i] + coeffs.prod();
160 : }
161 :
162 15 : WHEN("creating a RandomBlocksDescriptor containing these descriptors")
163 : {
164 12 : RandomBlocksDescriptor bd(descriptors);
165 :
166 7 : THEN("there are 10 blocks of the correct size")
167 : {
168 1 : REQUIRE_EQ(bd.getNumberOfBlocks(), blocks);
169 :
170 11 : for (index_t i = 0; i < blocks; ++i)
171 10 : REQUIRE_EQ(bd.getDescriptorOfBlock(i),
172 : *descriptors[static_cast<std::size_t>(i)]);
173 :
174 2 : REQUIRE_THROWS(bd.getDescriptorOfBlock(blocks));
175 : }
176 :
177 7 : THEN("the new RandomBlocksDescriptor has the correct sizes")
178 : {
179 1 : REQUIRE_EQ(bd.getNumberOfDimensions(), 1);
180 :
181 1 : IndexVector_t correctSize = IndexVector_t::Constant(1, size);
182 1 : REQUIRE_EQ(bd.getNumberOfCoefficientsPerDimension(), correctSize);
183 1 : REQUIRE_EQ(bd.getNumberOfCoefficients(), correctSize.prod());
184 :
185 1 : REQUIRE_EQ(bd.getSpacingPerDimension().size(), 1);
186 1 : REQUIRE_EQ(bd.getSpacingPerDimension()[0], 1.0);
187 : }
188 :
189 7 : THEN("the block offsets are correct")
190 : {
191 11 : for (index_t i = 0; i < blocks; ++i)
192 10 : REQUIRE_EQ(bd.getOffsetOfBlock(i), offsets[i]);
193 :
194 2 : REQUIRE_THROWS(bd.getOffsetOfBlock(blocks));
195 : }
196 :
197 7 : THEN("the block descriptor is different from a monolithic descriptor with the same "
198 : "dimensions")
199 : {
200 2 : IndexVector_t size = IndexVector_t::Constant(1, bd.getNumberOfCoefficients());
201 2 : VolumeDescriptor dd(size);
202 1 : REQUIRE_NE(bd, dd);
203 1 : REQUIRE_NE(dd, bd);
204 : }
205 :
206 7 : THEN("the block descriptor is different from a RandomBlocksDescriptor with the same "
207 : "size but a different number of blocks")
208 : {
209 2 : IndexVector_t size = IndexVector_t::Constant(1, bd.getNumberOfCoefficients());
210 2 : VolumeDescriptor dd(size);
211 2 : std::vector<std::unique_ptr<DataDescriptor>> vec;
212 1 : vec.push_back(dd.clone());
213 2 : RandomBlocksDescriptor bd2(vec);
214 1 : REQUIRE_NE(bd, bd2);
215 1 : REQUIRE_NE(bd2, bd);
216 : }
217 :
218 7 : THEN("the block descriptor is different from a RandomBlocksDescriptor with the same "
219 : "size and number of blocks but different individual block descriptors")
220 : {
221 2 : std::vector<std::unique_ptr<DataDescriptor>> descriptors2;
222 11 : for (const auto& desc : descriptors) {
223 : auto linearized = std::make_unique<VolumeDescriptor>(
224 10 : IndexVector_t::Constant(1, desc->getNumberOfCoefficients()));
225 10 : descriptors2.push_back(std::move(linearized));
226 : }
227 :
228 2 : RandomBlocksDescriptor bd2(descriptors2);
229 1 : REQUIRE_NE(bd, bd2);
230 1 : REQUIRE_NE(bd2, bd);
231 : }
232 : }
233 :
234 12 : WHEN("creating a RandomBlocksDescriptor containing these descriptors by moving")
235 : {
236 6 : std::vector<std::unique_ptr<DataDescriptor>> tmp(0);
237 33 : for (const auto& desc : descriptors)
238 30 : tmp.push_back(desc->clone());
239 :
240 6 : RandomBlocksDescriptor bd(std::move(tmp));
241 :
242 4 : THEN("there are 10 blocks of the correct size")
243 : {
244 1 : REQUIRE_EQ(bd.getNumberOfBlocks(), blocks);
245 :
246 11 : for (index_t i = 0; i < blocks; ++i)
247 10 : REQUIRE_EQ(bd.getDescriptorOfBlock(i),
248 : *descriptors[static_cast<std::size_t>(i)]);
249 :
250 2 : REQUIRE_THROWS(bd.getDescriptorOfBlock(blocks));
251 : }
252 :
253 4 : THEN("the new RandomBlocksDescriptor has the correct sizes")
254 : {
255 1 : REQUIRE_EQ(bd.getNumberOfDimensions(), 1);
256 :
257 1 : IndexVector_t correctSize = IndexVector_t::Constant(1, size);
258 1 : REQUIRE_EQ(bd.getNumberOfCoefficientsPerDimension(), correctSize);
259 1 : REQUIRE_EQ(bd.getNumberOfCoefficients(), correctSize.prod());
260 :
261 1 : REQUIRE_EQ(bd.getSpacingPerDimension().size(), 1);
262 1 : REQUIRE_EQ(bd.getSpacingPerDimension()[0], 1.0);
263 : }
264 :
265 4 : THEN("the block offsets are correct")
266 : {
267 11 : for (index_t i = 0; i < blocks; ++i)
268 10 : REQUIRE_EQ(bd.getOffsetOfBlock(i), offsets[i]);
269 :
270 2 : REQUIRE_THROWS(bd.getOffsetOfBlock(blocks));
271 : }
272 : }
273 : }
274 :
275 36 : GIVEN("25 descriptors with arbitrary dimensions")
276 : {
277 9 : index_t blocks = 25;
278 18 : std::vector<std::unique_ptr<DataDescriptor>> descriptors(0);
279 :
280 9 : index_t size = 0;
281 18 : IndexVector_t offsets(blocks);
282 9 : offsets[0] = 0;
283 234 : for (index_t i = 0; i < blocks; i++) {
284 450 : IndexVector_t coeffs(2 + std::rand() % 4);
285 225 : coeffs.setRandom();
286 1000 : for (int j = 0; j < coeffs.size(); j++)
287 775 : coeffs[j] = 1 + std::abs(coeffs[j]) % 100;
288 :
289 225 : descriptors.emplace_back(std::make_unique<VolumeDescriptor>(coeffs));
290 225 : size += coeffs.prod();
291 :
292 225 : if (i != blocks - 1)
293 216 : offsets[i + 1] = offsets[i] + coeffs.prod();
294 : }
295 :
296 15 : WHEN("creating a RandomBlocksDescriptor containing these descriptors")
297 : {
298 12 : RandomBlocksDescriptor bd(descriptors);
299 :
300 7 : THEN("there are 10 blocks of the correct size")
301 : {
302 1 : REQUIRE_EQ(bd.getNumberOfBlocks(), blocks);
303 :
304 26 : for (index_t i = 0; i < blocks; ++i)
305 25 : REQUIRE_EQ(bd.getDescriptorOfBlock(i),
306 : *descriptors[static_cast<std::size_t>(i)]);
307 :
308 2 : REQUIRE_THROWS(bd.getDescriptorOfBlock(blocks));
309 : }
310 :
311 7 : THEN("the new RandomBlocksDescriptor has the correct sizes")
312 : {
313 1 : REQUIRE_EQ(bd.getNumberOfDimensions(), 1);
314 :
315 1 : IndexVector_t correctSize = IndexVector_t::Constant(1, size);
316 1 : REQUIRE_EQ(bd.getNumberOfCoefficientsPerDimension(), correctSize);
317 1 : REQUIRE_EQ(bd.getNumberOfCoefficients(), correctSize.prod());
318 :
319 1 : REQUIRE_EQ(bd.getSpacingPerDimension().size(), 1);
320 1 : REQUIRE_EQ(bd.getSpacingPerDimension()[0], 1.0);
321 : }
322 :
323 7 : THEN("the block offsets are correct")
324 : {
325 26 : for (index_t i = 0; i < blocks; ++i)
326 25 : REQUIRE_EQ(bd.getOffsetOfBlock(i), offsets[i]);
327 :
328 2 : REQUIRE_THROWS(bd.getDescriptorOfBlock(blocks));
329 : }
330 :
331 7 : THEN("the block descriptor is different from a monolithic descriptor with the same "
332 : "dimensions")
333 : {
334 2 : IndexVector_t size = IndexVector_t::Constant(1, bd.getNumberOfCoefficients());
335 2 : VolumeDescriptor dd(size);
336 1 : REQUIRE_NE(bd, dd);
337 1 : REQUIRE_NE(dd, bd);
338 : }
339 :
340 7 : THEN("the block descriptor is different from a RandomBlocksDescriptor with the same "
341 : "size but a different number of blocks")
342 : {
343 2 : IndexVector_t size = IndexVector_t::Constant(1, bd.getNumberOfCoefficients());
344 2 : VolumeDescriptor dd(size);
345 2 : std::vector<std::unique_ptr<DataDescriptor>> vec;
346 1 : vec.push_back(dd.clone());
347 2 : RandomBlocksDescriptor bd2(vec);
348 1 : REQUIRE_NE(bd, bd2);
349 1 : REQUIRE_NE(bd2, bd);
350 : }
351 :
352 7 : THEN("the block descriptor is different from a RandomBlocksDescriptor with the same "
353 : "size and number of blocks but different individual block descriptors")
354 : {
355 2 : std::vector<std::unique_ptr<DataDescriptor>> descriptors2;
356 26 : for (const auto& desc : descriptors) {
357 : auto linearized = std::make_unique<VolumeDescriptor>(
358 25 : IndexVector_t::Constant(1, desc->getNumberOfCoefficients()));
359 25 : descriptors2.push_back(std::move(linearized));
360 : }
361 :
362 2 : RandomBlocksDescriptor bd2(descriptors2);
363 1 : REQUIRE_NE(bd, bd2);
364 1 : REQUIRE_NE(bd2, bd);
365 : }
366 : }
367 :
368 12 : WHEN("creating a RandomBlocksDescriptor containing these descriptors by moving")
369 : {
370 6 : std::vector<std::unique_ptr<DataDescriptor>> tmp(0);
371 78 : for (const auto& desc : descriptors)
372 75 : tmp.push_back(desc->clone());
373 :
374 6 : RandomBlocksDescriptor bd(std::move(tmp));
375 :
376 4 : THEN("there are 10 blocks of the correct size")
377 : {
378 1 : REQUIRE_EQ(bd.getNumberOfBlocks(), blocks);
379 :
380 26 : for (index_t i = 0; i < blocks; ++i)
381 25 : REQUIRE_EQ(bd.getDescriptorOfBlock(i),
382 : *descriptors[static_cast<std::size_t>(i)]);
383 :
384 2 : REQUIRE_THROWS(bd.getDescriptorOfBlock(blocks));
385 : }
386 :
387 4 : THEN("the new RandomBlocksDescriptor has the correct sizes")
388 : {
389 1 : REQUIRE_EQ(bd.getNumberOfDimensions(), 1);
390 :
391 1 : IndexVector_t correctSize = IndexVector_t::Constant(1, size);
392 1 : REQUIRE_EQ(bd.getNumberOfCoefficientsPerDimension(), correctSize);
393 1 : REQUIRE_EQ(bd.getNumberOfCoefficients(), correctSize.prod());
394 :
395 1 : REQUIRE_EQ(bd.getSpacingPerDimension().size(), 1);
396 1 : REQUIRE_EQ(bd.getSpacingPerDimension()[0], 1.0);
397 : }
398 :
399 4 : THEN("the block offsets are correct")
400 : {
401 26 : for (index_t i = 0; i < blocks; ++i)
402 25 : REQUIRE_EQ(bd.getOffsetOfBlock(i), offsets[i]);
403 :
404 2 : REQUIRE_THROWS(bd.getDescriptorOfBlock(blocks));
405 : }
406 : }
407 : }
408 27 : }
409 :
410 3 : TEST_CASE("RandomBlocksDescriptor: Testing clone()")
411 : {
412 4 : GIVEN("a RandomBlocksDescriptor of 1D descriptors")
413 : {
414 1 : index_t blocks = 21;
415 2 : std::vector<std::unique_ptr<DataDescriptor>> descriptors(0);
416 :
417 2 : IndexVector_t offsets(blocks);
418 1 : offsets[0] = 0;
419 22 : for (index_t i = 0; i < blocks; i++) {
420 21 : index_t n = 1 + std::rand() % 100;
421 : descriptors.emplace_back(
422 21 : std::make_unique<VolumeDescriptor>(IndexVector_t::Constant(1, n)));
423 21 : if (i != blocks - 1)
424 20 : offsets[i + 1] = offsets[i] + n;
425 : }
426 :
427 2 : RandomBlocksDescriptor bd(descriptors);
428 2 : WHEN("cloning the descriptor")
429 : {
430 2 : auto bdClone = bd.clone();
431 :
432 2 : THEN("it's a real clone")
433 : {
434 1 : REQUIRE_NE(bdClone.get(), &bd);
435 1 : REQUIRE_UNARY(is<RandomBlocksDescriptor>(bdClone.get()));
436 1 : REQUIRE_EQ(*bdClone, bd);
437 : }
438 : }
439 : }
440 :
441 4 : GIVEN("a RandomBlocksDescriptor of 2D descriptors")
442 : {
443 1 : index_t blocks = 77;
444 2 : std::vector<std::unique_ptr<DataDescriptor>> descriptors(0);
445 :
446 2 : IndexVector_t offsets(blocks);
447 1 : offsets[0] = 0;
448 78 : for (index_t i = 0; i < blocks; i++) {
449 154 : IndexVector_t coeffs(2);
450 77 : coeffs << 1 + std::rand() % 100, 1 + std::rand() % 100;
451 77 : descriptors.emplace_back(std::make_unique<VolumeDescriptor>(coeffs));
452 77 : if (i != blocks - 1)
453 76 : offsets[i + 1] = offsets[i] + coeffs.prod();
454 : }
455 :
456 2 : RandomBlocksDescriptor bd(descriptors);
457 2 : WHEN("cloning the descriptor")
458 : {
459 2 : auto bdClone = bd.clone();
460 :
461 2 : THEN("it's a real clone")
462 : {
463 1 : REQUIRE_NE(bdClone.get(), &bd);
464 1 : REQUIRE_UNARY(is<RandomBlocksDescriptor>(bdClone.get()));
465 1 : REQUIRE_EQ(*bdClone, bd);
466 : }
467 : }
468 : }
469 :
470 4 : GIVEN("a RandomBlocksDescriptor of descriptors with arbitrary dimensions")
471 : {
472 1 : index_t blocks = 13;
473 2 : std::vector<std::unique_ptr<DataDescriptor>> descriptors(0);
474 :
475 2 : IndexVector_t offsets(blocks);
476 1 : offsets[0] = 0;
477 14 : for (index_t i = 0; i < blocks; i++) {
478 26 : IndexVector_t coeffs(1 + std::rand() % 5);
479 13 : coeffs.setRandom();
480 51 : for (int j = 0; j < coeffs.size(); j++)
481 38 : coeffs[j] = 1 + std::abs(coeffs[j]) % 100;
482 :
483 13 : descriptors.emplace_back(std::make_unique<VolumeDescriptor>(coeffs));
484 :
485 13 : if (i != blocks - 1)
486 12 : offsets[i + 1] = offsets[i] + coeffs.prod();
487 : }
488 :
489 2 : RandomBlocksDescriptor bd(descriptors);
490 2 : WHEN("cloning the descriptor")
491 : {
492 2 : auto bdClone = bd.clone();
493 :
494 2 : THEN("it's a real clone")
495 : {
496 1 : REQUIRE_NE(bdClone.get(), &bd);
497 1 : REQUIRE_UNARY(is<RandomBlocksDescriptor>(bdClone.get()));
498 1 : REQUIRE_EQ(*bdClone, bd);
499 : }
500 : }
501 : }
502 3 : }
503 :
504 : TEST_SUITE_END();
|