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