OpenWalnut  1.5.0dev
WFiberCluster_test.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WFIBERCLUSTER_TEST_H
26 #define WFIBERCLUSTER_TEST_H
27 
28 #include <list>
29 #include <memory>
30 
31 #include <cxxtest/TestSuite.h>
32 
33 #include "../../../common/WLimits.h"
34 #include "../../../common/WLogger.h"
35 #include "../../test/WDataSetFiberVectorTraits.h"
36 #include "../WFiberCluster.h"
37 
38 /**
39  * Unit test the WFiberCluster class
40  */
41 class WFiberClusterTest : public CxxTest::TestSuite
42 {
43 public:
44  /**
45  * When merging two clusters the indices are merged and the second cluster
46  * becomes empty.
47  */
48  void testMerge( void )
49  {
50  WFiberCluster a( 1 );
51  WFiberCluster b;
52  size_t mydata[] = { 16, 2, 77, 29 }; // NOLINT
53  std::list< size_t > data( mydata, mydata + sizeof( mydata ) / sizeof( size_t ) );
54  b.m_memberIndices = data;
55  a.merge( b );
56  TS_ASSERT( b.empty() );
57  size_t mxdata[] = { 1, 16, 2, 77, 29 }; // NOLINT
58  std::list< size_t > xdata( mxdata, mxdata + sizeof( mxdata ) / sizeof( size_t ) );
59  WFiberCluster expected;
60  expected.m_memberIndices = xdata;
61  TS_ASSERT_EQUALS( expected, a );
62  }
63 
64  /**
65  * Generates a dataset for some unit tests.
66  \verbatim
67  Fiber B had initially 3 points: [0;2],[2;2],[4;2] after resampling there are 5 points:
68  [0;2],[1;2],[2;2],[3;2],[4;2]
69  Fiber A had initially 7 points: [0;0],[1;1],[2;1],[3;1],[4;1],[5;1],[6;1] after resampling there are 5 points:
70  [0;0],[1.5;1],[3;1],[4.5;1],[6;1]
71 
72  |
73  2 -B----B-----B------B-----B
74  |
75  |
76  | ,.m------m---------m-------m (center line)
77  | /
78  | /
79  1 -m aA----a--A--a---A-a----Aa-----A
80  | /
81  | /
82  | /
83  | /
84  |/
85  A-----+-----+-----+-----+-----+-----+---
86  0 1 2 3 4 5 6
87 
88  \endverbatim
89  */
90  void testCenterLine( void )
91  {
92  WFiber expected;
93  expected.push_back( WPosition( 0, 1, 0 ) );
94  expected.push_back( WPosition( ( ( 9.0 - 3 * std::sqrt( 2.0 ) ) / 4.0 - 1.0 ) / 2.0 + 1, 1.5, 0 ) );
95  expected.push_back( WPosition( ( ( 9.0 - 3 * std::sqrt( 2.0 ) ) / 4.0 + ( 5 + std::sqrt( 2.0 ) ) / 4.0 - 2.0 ) / 2.0 + 2, 1.5, 0 ) );
96  expected.push_back( WPosition( ( ( 9.0 - 3 * std::sqrt( 2.0 ) ) / 4.0 + 2 * ( 5 + std::sqrt( 2.0 ) ) / 4.0 - 3.0 ) / 2.0 + 3, 1.5, 0 ) );
97  expected.push_back( WPosition( 5, 1.5, 0 ) );
98  m_cluster->generateCenterLine();
99  assert_equals_delta( *m_cluster->getCenterLine(), expected, wlimits::FLT_EPS );
100  std::cout << *m_cluster->getDataSetReference() << std::endl;
101  }
102 
103  /**
104  * If there are two fibers which are nearly parallel changing ones direction
105  * will have huge effect
106  */
108  {
109  WDataSetFiberVector expected( *m_cluster->getDataSetReference() ); // make a copy
110 
111  std::shared_ptr< WDataSetFiberVector > fibs( new WDataSetFiberVector( expected ) );
112  fibs->at( 1 ).reverseOrder(); // simulate wrong direction of the second fiber
113 
114  m_cluster->unifyDirection( fibs );
115  using string_utils::operator<<;
116  TS_ASSERT_EQUALS( *fibs, expected );
117  }
118 
119  /**
120  * Check determination of the direction of a pair of fibers which are in the following shape (all points having the same Y and Z coordinate).
121  \verbatim
122  AS--------------------------->AE BS------------------------->BE
123  \endverbatim
124  */
126  {
127  WFiber a;
128  a.push_back( WPosition( 0, 0, 0 ) );
129  a.push_back( WPosition( 1, 0, 0 ) );
130  a.push_back( WPosition( 2, 0, 0 ) );
131  a.push_back( WPosition( 3, 0, 0 ) );
132  a.push_back( WPosition( 4, 0, 0 ) );
133  a.push_back( WPosition( 5, 0, 0 ) );
134  a.push_back( WPosition( 6, 0, 0 ) );
135  WFiber b;
136  b.push_back( WPosition( 10, 0, 0 ) );
137  b.push_back( WPosition( 11, 0, 0 ) );
138  b.push_back( WPosition( 12, 0, 0 ) );
139  b.push_back( WPosition( 13, 0, 0 ) );
140  b.push_back( WPosition( 14, 0, 0 ) );
141  b.push_back( WPosition( 15, 0, 0 ) );
142  b.push_back( WPosition( 16, 0, 0 ) );
143  WDataSetFiberVector expected;
144  expected.push_back( a );
145  expected.push_back( b );
146 
147  std::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector( expected ) );
148  ds->at( 1 ).reverseOrder();
149  m_cluster->unifyDirection( ds );
150  TS_ASSERT_EQUALS( *ds, expected ); // second tract should flip over
151  m_cluster->unifyDirection( ds );
152  TS_ASSERT_EQUALS( *ds, expected ); // no tract should flip over
153  }
154 
155  /**
156  * Check determination of the direction of a pair of fibers which are in the following shape.
157  *
158  \verbatim
159  AS. _BS
160  `. ,-'
161  `. /
162  \ /
163  \ |
164  `. .'
165  | |
166  | |
167  | |
168  | |
169  | |
170  | |
171  AE BE
172  \endverbatim
173  */
175  {
176  WFiber a;
177  a.push_back( WPosition( 0, 0, 0 ) );
178  a.push_back( WPosition( 5, 1, 0 ) );
179  a.push_back( WPosition( 8, 3, 0 ) );
180  a.push_back( WPosition( 11, 7, 0 ) );
181  a.push_back( WPosition( 11, 10, 0 ) );
182  a.push_back( WPosition( 11, 12, 0 ) );
183  WFiber b;
184  b.push_back( WPosition( 23, 0, 0 ) );
185  b.push_back( WPosition( 19, 2, 0 ) );
186  b.push_back( WPosition( 17, 5, 0 ) );
187  b.push_back( WPosition( 15, 7, 0 ) );
188  b.push_back( WPosition( 16, 10, 0 ) );
189  b.push_back( WPosition( 16, 12, 0 ) );
190  WDataSetFiberVector expected;
191  expected.push_back( a );
192  expected.push_back( b );
193 
194  std::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector( expected ) );
195  ds->at( 1 ).reverseOrder();
196  m_cluster->unifyDirection( ds );
197  TS_ASSERT_EQUALS( *ds, expected ); // second tract should flip over
198  m_cluster->unifyDirection( ds );
199  TS_ASSERT_EQUALS( *ds, expected ); // no tract should flip over
200  }
201 
202  /**
203  * Check determination of the direction of a pair of fibers which are in the following shape.
204  *
205  \verbatim
206  _.-----AS
207  ,'
208  / ,-'BS
209  | ,'
210  | / AE
211  | / BE |
212  | | | |
213  | | | |
214  \ \ ,| |
215  \ `. ,Y' _,'
216  `\_ `'''''' _.'
217  '`--------''
218  \endverbatim
219  */
221  {
222  WFiber a;
223  a.push_back( WPosition( 14, 0, 0 ) );
224  a.push_back( WPosition( 5, 1, 0 ) );
225  a.push_back( WPosition( 2, 4, 0 ) );
226  a.push_back( WPosition( 3, 9, 0 ) );
227  a.push_back( WPosition( 11, 11, 0 ) );
228  a.push_back( WPosition( 19, 10, 0 ) );
229  a.push_back( WPosition( 24, 8, 0 ) );
230  a.push_back( WPosition( 23, 4, 0 ) );
231  WFiber b;
232  b.push_back( WPosition( 13, 2, 0 ) );
233  b.push_back( WPosition( 7, 4, 0 ) );
234  b.push_back( WPosition( 6, 8, 0 ) );
235  b.push_back( WPosition( 10, 10, 0 ) );
236  b.push_back( WPosition( 17, 9, 0 ) );
237  b.push_back( WPosition( 19, 7, 0 ) );
238  b.push_back( WPosition( 19, 5, 0 ) );
239  WDataSetFiberVector expected;
240  expected.push_back( a );
241  expected.push_back( b );
242 
243  std::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector( expected ) );
244  ds->at( 1 ).reverseOrder();
245  m_cluster->unifyDirection( ds );
246  TS_ASSERT_EQUALS( *ds, expected ); // second tract should flip over
247  m_cluster->unifyDirection( ds );
248  TS_ASSERT_EQUALS( *ds, expected ); // no tract should flip over
249  }
250 
251  /**
252  * Check determination of the direction of a pair of fibers which are in the following shape.
253  *
254  \verbatim
255  ,,---._
256  ,' \
257  / \
258  | |
259  \ ,'
260  \ ,'
261  `-AS AE
262  BS BE
263  ,' `.
264  / \
265  | |
266  | |
267  | |
268  \ /
269  `-._ _,-'
270  `''
271  \endverbatim
272  */
274  {
275  WFiber a;
276  a.push_back( WPosition( 6, 6, 0 ) );
277  a.push_back( WPosition( 3, 5, 0 ) );
278  a.push_back( WPosition( 2, 3, 0 ) );
279  a.push_back( WPosition( 4, 1, 0 ) );
280  a.push_back( WPosition( 7, 0, 0 ) );
281  a.push_back( WPosition( 11, 0, 0 ) );
282  a.push_back( WPosition( 14, 2, 0 ) );
283  a.push_back( WPosition( 13, 4, 0 ) );
284  a.push_back( WPosition( 11, 6, 0 ) );
285  WFiber b;
286  b.push_back( WPosition( 6, 7, 0 ) );
287  b.push_back( WPosition( 3, 9, 0 ) );
288  b.push_back( WPosition( 1, 11, 0 ) );
289  b.push_back( WPosition( 3, 14, 0 ) );
290  b.push_back( WPosition( 8, 15, 0 ) );
291  b.push_back( WPosition( 13, 14, 0 ) );
292  b.push_back( WPosition( 15, 12, 0 ) );
293  b.push_back( WPosition( 14, 9, 0 ) );
294  b.push_back( WPosition( 11, 7, 0 ) );
295  WDataSetFiberVector expected;
296  expected.push_back( a );
297  expected.push_back( b );
298 
299  std::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector( expected ) );
300  ds->at( 1 ).reverseOrder();
301  m_cluster->unifyDirection( ds );
302  TS_ASSERT_EQUALS( *ds, expected ); // second tract should flip over
303  m_cluster->unifyDirection( ds );
304  TS_ASSERT_EQUALS( *ds, expected ); // no tract should flip over
305  }
306 
307  /**
308  * Check determination of the direction of a pair of fibers which are in the following shape.
309  *
310  \verbatim
311  ,,-'-AE BS''`-._
312  ,' `.
313  / \
314  / `.
315  / `.
316  / |
317  | |
318  | |
319  | |
320  | |
321  | |
322  | |
323  AS BE
324  \endverbatim
325  */
327  {
328  WFiber a;
329  a.push_back( WPosition( 1, 12, 0 ) );
330  a.push_back( WPosition( 1, 9, 0 ) );
331  a.push_back( WPosition( 2, 5, 0 ) );
332  a.push_back( WPosition( 5, 1, 0 ) );
333  a.push_back( WPosition( 9, 0, 0 ) );
334  a.push_back( WPosition( 14, 0, 0 ) );
335  WFiber b;
336  b.push_back( WPosition( 19, 0, 0 ) );
337  b.push_back( WPosition( 24, 0, 0 ) );
338  b.push_back( WPosition( 29, 2, 0 ) );
339  b.push_back( WPosition( 32, 5, 0 ) );
340  b.push_back( WPosition( 33, 8, 0 ) );
341  b.push_back( WPosition( 33, 12, 0 ) );
342  WDataSetFiberVector expected;
343  expected.push_back( a );
344  expected.push_back( b );
345 
346  std::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector( expected ) );
347  ds->at( 1 ).reverseOrder();
348  m_cluster->unifyDirection( ds );
349  TS_ASSERT_EQUALS( *ds, expected ); // second tract should flip over
350  m_cluster->unifyDirection( ds );
351  TS_ASSERT_EQUALS( *ds, expected ); // no tract should flip over
352  }
353 
354 private:
355  /**
356  * Compares to point sequences (aka lines) with a given delta.
357  *
358  * \param first First line to compare with
359  * \param second Second line to compare with
360  * \param delta The delta within two points are considered as equally
361  */
362  void assert_equals_delta( const WLine& first, const WLine& second, double delta = wlimits::DBL_EPS ) const
363  {
364  int diffPos = 0;
365  if( ( diffPos = equalsDelta( first, second, delta ) ) != -1 )
366  {
367  using string_utils::operator<<;
368  std::stringstream msg;
369  msg << "Lines are different in at least point: " << diffPos;
370  TS_FAIL( msg.str() );
371  std::cout << "first line at: " << diffPos << std::endl << first[diffPos] << std::endl;
372  std::cout << "second line at: " << diffPos << std::endl << second[diffPos] << std::endl;
373  std::cout << "first line: " << std::endl << first << std::endl;
374  std::cout << "second line: " << std::endl << second << std::endl;
375  }
376  }
377 
378  /**
379  * Generates a dataset for some unit tests.
380  \verbatim
381  Fiber B has 3 points: [0;2],[2;2],[4;2]
382  Fiber A has 7 points: [0;0],[1;1],[2;1],[3;1],[4;1],[5;1],[6;1]
383 
384  |
385  2 -b----------b------------b
386  |
387  |
388  |
389  |
390  |
391  1 -| a-----a-----a-----a-----a-----a
392  | /
393  | /
394  | /
395  | /
396  |/
397  a-----+-----+-----+-----+-----+-----+---
398  0 1 2 3 4 5 6
399 
400  \endverbatim
401  */
402  void setUp( void )
403  {
404  // generate fiber dataset to operate on
405  WFiber fib_a;
406  fib_a.push_back( WPosition( 0, 0, 0 ) );
407  fib_a.push_back( WPosition( 1, 1, 0 ) );
408  fib_a.push_back( WPosition( 2, 1, 0 ) );
409  fib_a.push_back( WPosition( 3, 1, 0 ) );
410  fib_a.push_back( WPosition( 4, 1, 0 ) );
411  fib_a.push_back( WPosition( 5, 1, 0 ) );
412  fib_a.push_back( WPosition( 6, 1, 0 ) );
413  WFiber fib_b;
414  fib_b.push_back( WPosition( 0, 2, 0 ) );
415  fib_b.push_back( WPosition( 2, 2, 0 ) );
416  fib_b.push_back( WPosition( 4, 2, 0 ) );
417  std::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector() );
418  ds->push_back( fib_a );
419  ds->push_back( fib_b );
420  generateFiberCluster( ds );
421  }
422 
423  /**
424  * Generates out of the given dataset a WFiberCluster containing all fibers.
425  *
426  * \param ds The fiber dataset
427  */
428  void generateFiberCluster( const std::shared_ptr< WDataSetFiberVector > ds )
429  {
430  m_cluster.reset();
431  m_cluster = std::shared_ptr< WFiberCluster >( new WFiberCluster() );
432  m_cluster->setDataSetReference( ds );
433  std::list< size_t > idx;
434  for( size_t i = 0; i < ds->size(); ++i )
435  {
436  idx.push_back( i );
437  }
438  m_cluster->setIndices( idx );
439  }
440 
441  /**
442  * Tidyups the dataset used in some unit tests
443  */
444  void tearDown( void )
445  {
446  m_cluster.reset();
447  }
448 
449  std::shared_ptr< WFiberCluster > m_cluster; //!< pre generated cluster for some unit tests
450 };
451 
452 #endif // WFIBERCLUSTER_TEST_H
Represents a simple set of WFibers.
Unit test the WFiberCluster class.
void generateFiberCluster(const std::shared_ptr< WDataSetFiberVector > ds)
Generates out of the given dataset a WFiberCluster containing all fibers.
void testUnifyDirectionOnTwoNearlyParallelFibers(void)
If there are two fibers which are nearly parallel changing ones direction will have huge effect.
std::shared_ptr< WFiberCluster > m_cluster
pre generated cluster for some unit tests
void testMerge(void)
When merging two clusters the indices are merged and the second cluster becomes empty.
void assert_equals_delta(const WLine &first, const WLine &second, double delta=wlimits::DBL_EPS) const
Compares to point sequences (aka lines) with a given delta.
void testUnifyDirectionOnTwoConsecutiveFibers(void)
Check determination of the direction of a pair of fibers which are in the following shape (all points...
void testUnifyDirectionOnTwoCSTShapedFibers(void)
Check determination of the direction of a pair of fibers which are in the following shape.
void tearDown(void)
Tidyups the dataset used in some unit tests.
void testCenterLine(void)
Generates a dataset for some unit tests.
void setUp(void)
Generates a dataset for some unit tests.
void testUnifyDirectionOnTwoCircularShapedFibersInDifferentCircle(void)
Check determination of the direction of a pair of fibers which are in the following shape.
void testUnifyDirectionOnTwoInverseCSTShapedFibers(void)
Check determination of the direction of a pair of fibers which are in the following shape.
void testUnifyDirectionOnTwoCircularShapedFibersInSameCircle(void)
Check determination of the direction of a pair of fibers which are in the following shape.
Represents a cluster of indices of a WDataSetFiberVector.
Definition: WFiberCluster.h:45
IndexList m_memberIndices
All indices in this set are members of this cluster.
bool empty() const
Returns true if there are no fibers in that cluster, false otherwise.
void merge(WFiberCluster &other)
Merge the fibers of the other cluster with the fibers of this cluster.
Represents a neural pathway.
Definition: WFiber.h:40
A line is an ordered sequence of WPositions.
Definition: WLine.h:42
void push_back(const value_type &value)
Wrapper around std::vector member function.
Definition: WMixinVector.h:457
This only is a 3d double vector.
const float FLT_EPS
Smallest float such: 1.0 + FLT_EPS == 1.0 is still true.
Definition: WLimits.cpp:47
const double DBL_EPS
Smallest double such: 1.0 + DBL_EPS == 1.0 is still true.
Definition: WLimits.cpp:46