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 : TEST_CASE("RandomBlocksDescriptors: Testing constructions")
22 27 : {
23 27 : GIVEN("0 an empty descriptor list")
24 27 : {
25 1 : THEN("construction of a RandomBlocksDescriptor fails")
26 1 : {
27 1 : REQUIRE_THROWS(RandomBlocksDescriptor(std::vector<std::unique_ptr<DataDescriptor>>(0)));
28 1 : }
29 1 : }
30 27 : GIVEN("five 1D descriptors")
31 27 : {
32 8 : index_t blocks = 5;
33 8 : std::vector<std::unique_ptr<DataDescriptor>> descriptors(0);
34 :
35 8 : index_t size = 0;
36 8 : 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 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 40 : }
46 :
47 8 : WHEN("creating a RandomBlocksDescriptor containing these descriptors")
48 8 : {
49 5 : RandomBlocksDescriptor bd(descriptors);
50 :
51 5 : THEN("there are 5 blocks of the correct size")
52 5 : {
53 1 : REQUIRE_EQ(bd.getNumberOfBlocks(), blocks);
54 :
55 6 : for (index_t i = 0; i < blocks; ++i)
56 1 : REQUIRE_EQ(bd.getDescriptorOfBlock(i),
57 1 : *descriptors[static_cast<std::size_t>(i)]);
58 :
59 1 : REQUIRE_THROWS(bd.getDescriptorOfBlock(blocks));
60 1 : }
61 :
62 5 : THEN("the new RandomBlocksDescriptor has the correct sizes")
63 5 : {
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 1 : }
73 :
74 5 : THEN("the block offsets are correct")
75 5 : {
76 6 : for (index_t i = 0; i < blocks; ++i)
77 1 : REQUIRE_EQ(bd.getOffsetOfBlock(i), offsets[i]);
78 :
79 1 : REQUIRE_THROWS(bd.getOffsetOfBlock(blocks));
80 1 : }
81 :
82 5 : THEN("the block descriptor is different from a monolithic descriptor with the same "
83 5 : "dimensions")
84 5 : {
85 1 : IndexVector_t size = IndexVector_t::Constant(1, bd.getNumberOfCoefficients());
86 1 : VolumeDescriptor dd(size);
87 1 : REQUIRE_NE(bd, dd);
88 1 : REQUIRE_NE(dd, bd);
89 1 : }
90 :
91 5 : THEN("the block descriptor is different from a RandomBlocksDescriptor with the same "
92 5 : "size but a different number of blocks")
93 5 : {
94 1 : IndexVector_t size = IndexVector_t::Constant(1, bd.getNumberOfCoefficients());
95 1 : VolumeDescriptor dd(size);
96 1 : std::vector<std::unique_ptr<DataDescriptor>> vec;
97 1 : vec.push_back(dd.clone());
98 1 : RandomBlocksDescriptor bd2(vec);
99 1 : REQUIRE_NE(bd, bd2);
100 1 : REQUIRE_NE(bd2, bd);
101 1 : }
102 5 : }
103 :
104 8 : WHEN("creating a RandomBlocksDescriptor containing these descriptors by moving")
105 8 : {
106 3 : std::vector<std::unique_ptr<DataDescriptor>> tmp(0);
107 3 : for (const auto& desc : descriptors)
108 15 : tmp.push_back(desc->clone());
109 :
110 3 : RandomBlocksDescriptor bd(std::move(tmp));
111 :
112 3 : THEN("there are 5 blocks of the correct size")
113 3 : {
114 1 : REQUIRE_EQ(bd.getNumberOfBlocks(), blocks);
115 :
116 6 : for (index_t i = 0; i < blocks; ++i)
117 1 : REQUIRE_EQ(bd.getDescriptorOfBlock(i),
118 1 : *descriptors[static_cast<std::size_t>(i)]);
119 :
120 1 : REQUIRE_THROWS(bd.getDescriptorOfBlock(blocks));
121 1 : }
122 :
123 3 : THEN("the new RandomBlocksDescriptor has the correct sizes")
124 3 : {
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 1 : }
134 :
135 3 : THEN("the block offsets are correct")
136 3 : {
137 6 : for (index_t i = 0; i < blocks; ++i)
138 1 : REQUIRE_EQ(bd.getOffsetOfBlock(i), offsets[i]);
139 :
140 1 : REQUIRE_THROWS(bd.getOffsetOfBlock(blocks));
141 1 : }
142 3 : }
143 8 : }
144 :
145 27 : GIVEN("ten 2D descriptors")
146 27 : {
147 9 : index_t blocks = 10;
148 9 : std::vector<std::unique_ptr<DataDescriptor>> descriptors(0);
149 :
150 9 : index_t size = 0;
151 9 : IndexVector_t offsets(blocks);
152 9 : offsets[0] = 0;
153 99 : for (index_t i = 0; i < blocks; i++) {
154 90 : 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 90 : }
161 :
162 9 : WHEN("creating a RandomBlocksDescriptor containing these descriptors")
163 9 : {
164 6 : RandomBlocksDescriptor bd(descriptors);
165 :
166 6 : THEN("there are 10 blocks of the correct size")
167 6 : {
168 1 : REQUIRE_EQ(bd.getNumberOfBlocks(), blocks);
169 :
170 11 : for (index_t i = 0; i < blocks; ++i)
171 1 : REQUIRE_EQ(bd.getDescriptorOfBlock(i),
172 1 : *descriptors[static_cast<std::size_t>(i)]);
173 :
174 1 : REQUIRE_THROWS(bd.getDescriptorOfBlock(blocks));
175 1 : }
176 :
177 6 : THEN("the new RandomBlocksDescriptor has the correct sizes")
178 6 : {
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 1 : }
188 :
189 6 : THEN("the block offsets are correct")
190 6 : {
191 11 : for (index_t i = 0; i < blocks; ++i)
192 1 : REQUIRE_EQ(bd.getOffsetOfBlock(i), offsets[i]);
193 :
194 1 : REQUIRE_THROWS(bd.getOffsetOfBlock(blocks));
195 1 : }
196 :
197 6 : THEN("the block descriptor is different from a monolithic descriptor with the same "
198 6 : "dimensions")
199 6 : {
200 1 : IndexVector_t size = IndexVector_t::Constant(1, bd.getNumberOfCoefficients());
201 1 : VolumeDescriptor dd(size);
202 1 : REQUIRE_NE(bd, dd);
203 1 : REQUIRE_NE(dd, bd);
204 1 : }
205 :
206 6 : THEN("the block descriptor is different from a RandomBlocksDescriptor with the same "
207 6 : "size but a different number of blocks")
208 6 : {
209 1 : IndexVector_t size = IndexVector_t::Constant(1, bd.getNumberOfCoefficients());
210 1 : VolumeDescriptor dd(size);
211 1 : std::vector<std::unique_ptr<DataDescriptor>> vec;
212 1 : vec.push_back(dd.clone());
213 1 : RandomBlocksDescriptor bd2(vec);
214 1 : REQUIRE_NE(bd, bd2);
215 1 : REQUIRE_NE(bd2, bd);
216 1 : }
217 :
218 6 : THEN("the block descriptor is different from a RandomBlocksDescriptor with the same "
219 6 : "size and number of blocks but different individual block descriptors")
220 6 : {
221 1 : std::vector<std::unique_ptr<DataDescriptor>> descriptors2;
222 10 : for (const auto& desc : descriptors) {
223 10 : auto linearized = std::make_unique<VolumeDescriptor>(
224 10 : IndexVector_t::Constant(1, desc->getNumberOfCoefficients()));
225 10 : descriptors2.push_back(std::move(linearized));
226 10 : }
227 :
228 1 : RandomBlocksDescriptor bd2(descriptors2);
229 1 : REQUIRE_NE(bd, bd2);
230 1 : REQUIRE_NE(bd2, bd);
231 1 : }
232 6 : }
233 :
234 9 : WHEN("creating a RandomBlocksDescriptor containing these descriptors by moving")
235 9 : {
236 3 : std::vector<std::unique_ptr<DataDescriptor>> tmp(0);
237 3 : for (const auto& desc : descriptors)
238 30 : tmp.push_back(desc->clone());
239 :
240 3 : RandomBlocksDescriptor bd(std::move(tmp));
241 :
242 3 : THEN("there are 10 blocks of the correct size")
243 3 : {
244 1 : REQUIRE_EQ(bd.getNumberOfBlocks(), blocks);
245 :
246 11 : for (index_t i = 0; i < blocks; ++i)
247 1 : REQUIRE_EQ(bd.getDescriptorOfBlock(i),
248 1 : *descriptors[static_cast<std::size_t>(i)]);
249 :
250 1 : REQUIRE_THROWS(bd.getDescriptorOfBlock(blocks));
251 1 : }
252 :
253 3 : THEN("the new RandomBlocksDescriptor has the correct sizes")
254 3 : {
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 1 : }
264 :
265 3 : THEN("the block offsets are correct")
266 3 : {
267 11 : for (index_t i = 0; i < blocks; ++i)
268 1 : REQUIRE_EQ(bd.getOffsetOfBlock(i), offsets[i]);
269 :
270 1 : REQUIRE_THROWS(bd.getOffsetOfBlock(blocks));
271 1 : }
272 3 : }
273 9 : }
274 :
275 27 : GIVEN("25 descriptors with arbitrary dimensions")
276 27 : {
277 9 : index_t blocks = 25;
278 9 : std::vector<std::unique_ptr<DataDescriptor>> descriptors(0);
279 :
280 9 : index_t size = 0;
281 9 : IndexVector_t offsets(blocks);
282 9 : offsets[0] = 0;
283 234 : for (index_t i = 0; i < blocks; i++) {
284 225 : 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 225 : }
295 :
296 9 : WHEN("creating a RandomBlocksDescriptor containing these descriptors")
297 9 : {
298 6 : RandomBlocksDescriptor bd(descriptors);
299 :
300 6 : THEN("there are 10 blocks of the correct size")
301 6 : {
302 1 : REQUIRE_EQ(bd.getNumberOfBlocks(), blocks);
303 :
304 26 : for (index_t i = 0; i < blocks; ++i)
305 1 : REQUIRE_EQ(bd.getDescriptorOfBlock(i),
306 1 : *descriptors[static_cast<std::size_t>(i)]);
307 :
308 1 : REQUIRE_THROWS(bd.getDescriptorOfBlock(blocks));
309 1 : }
310 :
311 6 : THEN("the new RandomBlocksDescriptor has the correct sizes")
312 6 : {
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 1 : }
322 :
323 6 : THEN("the block offsets are correct")
324 6 : {
325 26 : for (index_t i = 0; i < blocks; ++i)
326 1 : REQUIRE_EQ(bd.getOffsetOfBlock(i), offsets[i]);
327 :
328 1 : REQUIRE_THROWS(bd.getDescriptorOfBlock(blocks));
329 1 : }
330 :
331 6 : THEN("the block descriptor is different from a monolithic descriptor with the same "
332 6 : "dimensions")
333 6 : {
334 1 : IndexVector_t size = IndexVector_t::Constant(1, bd.getNumberOfCoefficients());
335 1 : VolumeDescriptor dd(size);
336 1 : REQUIRE_NE(bd, dd);
337 1 : REQUIRE_NE(dd, bd);
338 1 : }
339 :
340 6 : THEN("the block descriptor is different from a RandomBlocksDescriptor with the same "
341 6 : "size but a different number of blocks")
342 6 : {
343 1 : IndexVector_t size = IndexVector_t::Constant(1, bd.getNumberOfCoefficients());
344 1 : VolumeDescriptor dd(size);
345 1 : std::vector<std::unique_ptr<DataDescriptor>> vec;
346 1 : vec.push_back(dd.clone());
347 1 : RandomBlocksDescriptor bd2(vec);
348 1 : REQUIRE_NE(bd, bd2);
349 1 : REQUIRE_NE(bd2, bd);
350 1 : }
351 :
352 6 : THEN("the block descriptor is different from a RandomBlocksDescriptor with the same "
353 6 : "size and number of blocks but different individual block descriptors")
354 6 : {
355 1 : std::vector<std::unique_ptr<DataDescriptor>> descriptors2;
356 25 : for (const auto& desc : descriptors) {
357 25 : auto linearized = std::make_unique<VolumeDescriptor>(
358 25 : IndexVector_t::Constant(1, desc->getNumberOfCoefficients()));
359 25 : descriptors2.push_back(std::move(linearized));
360 25 : }
361 :
362 1 : RandomBlocksDescriptor bd2(descriptors2);
363 1 : REQUIRE_NE(bd, bd2);
364 1 : REQUIRE_NE(bd2, bd);
365 1 : }
366 6 : }
367 :
368 9 : WHEN("creating a RandomBlocksDescriptor containing these descriptors by moving")
369 9 : {
370 3 : std::vector<std::unique_ptr<DataDescriptor>> tmp(0);
371 3 : for (const auto& desc : descriptors)
372 75 : tmp.push_back(desc->clone());
373 :
374 3 : RandomBlocksDescriptor bd(std::move(tmp));
375 :
376 3 : THEN("there are 10 blocks of the correct size")
377 3 : {
378 1 : REQUIRE_EQ(bd.getNumberOfBlocks(), blocks);
379 :
380 26 : for (index_t i = 0; i < blocks; ++i)
381 1 : REQUIRE_EQ(bd.getDescriptorOfBlock(i),
382 1 : *descriptors[static_cast<std::size_t>(i)]);
383 :
384 1 : REQUIRE_THROWS(bd.getDescriptorOfBlock(blocks));
385 1 : }
386 :
387 3 : THEN("the new RandomBlocksDescriptor has the correct sizes")
388 3 : {
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 1 : }
398 :
399 3 : THEN("the block offsets are correct")
400 3 : {
401 26 : for (index_t i = 0; i < blocks; ++i)
402 1 : REQUIRE_EQ(bd.getOffsetOfBlock(i), offsets[i]);
403 :
404 1 : REQUIRE_THROWS(bd.getDescriptorOfBlock(blocks));
405 1 : }
406 3 : }
407 9 : }
408 27 : }
409 :
410 : TEST_CASE("RandomBlocksDescriptor: Testing clone()")
411 3 : {
412 3 : GIVEN("a RandomBlocksDescriptor of 1D descriptors")
413 3 : {
414 1 : index_t blocks = 21;
415 1 : std::vector<std::unique_ptr<DataDescriptor>> descriptors(0);
416 :
417 1 : 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 21 : 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 21 : }
426 :
427 1 : RandomBlocksDescriptor bd(descriptors);
428 1 : WHEN("cloning the descriptor")
429 1 : {
430 1 : auto bdClone = bd.clone();
431 :
432 1 : THEN("it's a real clone")
433 1 : {
434 1 : REQUIRE_NE(bdClone.get(), &bd);
435 1 : REQUIRE_UNARY(is<RandomBlocksDescriptor>(bdClone.get()));
436 1 : REQUIRE_EQ(*bdClone, bd);
437 1 : }
438 1 : }
439 1 : }
440 :
441 3 : GIVEN("a RandomBlocksDescriptor of 2D descriptors")
442 3 : {
443 1 : index_t blocks = 77;
444 1 : std::vector<std::unique_ptr<DataDescriptor>> descriptors(0);
445 :
446 1 : IndexVector_t offsets(blocks);
447 1 : offsets[0] = 0;
448 78 : for (index_t i = 0; i < blocks; i++) {
449 77 : 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 77 : }
455 :
456 1 : RandomBlocksDescriptor bd(descriptors);
457 1 : WHEN("cloning the descriptor")
458 1 : {
459 1 : auto bdClone = bd.clone();
460 :
461 1 : THEN("it's a real clone")
462 1 : {
463 1 : REQUIRE_NE(bdClone.get(), &bd);
464 1 : REQUIRE_UNARY(is<RandomBlocksDescriptor>(bdClone.get()));
465 1 : REQUIRE_EQ(*bdClone, bd);
466 1 : }
467 1 : }
468 1 : }
469 :
470 3 : GIVEN("a RandomBlocksDescriptor of descriptors with arbitrary dimensions")
471 3 : {
472 1 : index_t blocks = 13;
473 1 : std::vector<std::unique_ptr<DataDescriptor>> descriptors(0);
474 :
475 1 : IndexVector_t offsets(blocks);
476 1 : offsets[0] = 0;
477 14 : for (index_t i = 0; i < blocks; i++) {
478 13 : 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 13 : }
488 :
489 1 : RandomBlocksDescriptor bd(descriptors);
490 1 : WHEN("cloning the descriptor")
491 1 : {
492 1 : auto bdClone = bd.clone();
493 :
494 1 : THEN("it's a real clone")
495 1 : {
496 1 : REQUIRE_NE(bdClone.get(), &bd);
497 1 : REQUIRE_UNARY(is<RandomBlocksDescriptor>(bdClone.get()));
498 1 : REQUIRE_EQ(*bdClone, bd);
499 1 : }
500 1 : }
501 1 : }
502 3 : }
503 :
504 : TEST_SUITE_END();
|