OpenWalnut  1.4.0
WFiberCluster_test.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WFIBERCLUSTER_TEST_H
00026 #define WFIBERCLUSTER_TEST_H
00027 
00028 #include <list>
00029 
00030 #include <cxxtest/TestSuite.h>
00031 
00032 #include "../../../common/WLimits.h"
00033 #include "../../../common/WLogger.h"
00034 #include "../../test/WDataSetFiberVectorTraits.h"
00035 #include "../WFiberCluster.h"
00036 
00037 /**
00038  * Unit test the WFiberCluster class
00039  */
00040 class WFiberClusterTest : public CxxTest::TestSuite
00041 {
00042 public:
00043     /**
00044      * When merging two clusters the indices are merged and the second cluster
00045      * becomes empty.
00046      */
00047     void testMerge( void )
00048     {
00049         WFiberCluster a( 1 );
00050         WFiberCluster b;
00051         size_t mydata[] = { 16, 2, 77, 29 }; // NOLINT
00052         std::list< size_t > data( mydata, mydata + sizeof( mydata ) / sizeof( size_t ) );
00053         b.m_memberIndices = data;
00054         a.merge( b );
00055         TS_ASSERT( b.empty() );
00056         size_t mxdata[] = { 1, 16, 2, 77, 29 }; // NOLINT
00057         std::list< size_t > xdata( mxdata, mxdata + sizeof( mxdata ) / sizeof( size_t ) );
00058         WFiberCluster expected;
00059         expected.m_memberIndices = xdata;
00060         TS_ASSERT_EQUALS( expected, a );
00061     }
00062 
00063     /**
00064      * Generates a dataset for some unit tests.
00065      \verbatim
00066        Fiber B had initially 3 points: [0;2],[2;2],[4;2] after resampling there are 5 points:
00067                                        [0;2],[1;2],[2;2],[3;2],[4;2]
00068        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:
00069                                        [0;0],[1.5;1],[3;1],[4.5;1],[6;1]
00070 
00071            |
00072         2 -B----B-----B------B-----B
00073            |
00074            |
00075            |   ,.m------m---------m-------m (center line)
00076            |  /
00077            | /
00078         1 -m     aA----a--A--a---A-a----Aa-----A
00079            |    /
00080            |   /
00081            |  /
00082            | /
00083            |/
00084            A-----+-----+-----+-----+-----+-----+---
00085            0     1     2     3     4     5     6
00086 
00087      \endverbatim
00088      */
00089     void testCenterLine( void )
00090     {
00091         WFiber expected;
00092         expected.push_back( WPosition( 0,                                                                                               1, 0 ) );
00093         expected.push_back( WPosition( ( ( 9.0 - 3 * std::sqrt( 2.0 ) ) / 4.0 - 1.0 ) / 2.0 + 1,                                      1.5, 0 ) );
00094         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 ) );
00095         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 ) );
00096         expected.push_back( WPosition( 5,                                                                                             1.5, 0 ) );
00097         m_cluster->generateCenterLine();
00098         assert_equals_delta( *m_cluster->getCenterLine(), expected, wlimits::FLT_EPS );
00099         std::cout << *m_cluster->getDataSetReference() << std::endl;
00100     }
00101 
00102     /**
00103      * If there are two fibers which are nearly parallel changing ones direction
00104      * will have huge effect
00105      */
00106     void testUnifyDirectionOnTwoNearlyParallelFibers( void )
00107     {
00108         WDataSetFiberVector expected( *m_cluster->getDataSetReference() ); // make a copy
00109 
00110         boost::shared_ptr< WDataSetFiberVector > fibs( new WDataSetFiberVector( expected ) );
00111         fibs->at( 1 ).reverseOrder(); // simulate wrong direction of the second fiber
00112 
00113         m_cluster->unifyDirection( fibs );
00114         using string_utils::operator<<;
00115         TS_ASSERT_EQUALS( *fibs, expected );
00116     }
00117 
00118     /**
00119      * 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).
00120      \verbatim
00121        AS--------------------------->AE    BS------------------------->BE
00122      \endverbatim
00123      */
00124     void testUnifyDirectionOnTwoConsecutiveFibers( void )
00125     {
00126         WFiber a;
00127         a.push_back( WPosition(  0, 0, 0 ) );
00128         a.push_back( WPosition(  1, 0, 0 ) );
00129         a.push_back( WPosition(  2, 0, 0 ) );
00130         a.push_back( WPosition(  3, 0, 0 ) );
00131         a.push_back( WPosition(  4, 0, 0 ) );
00132         a.push_back( WPosition(  5, 0, 0 ) );
00133         a.push_back( WPosition(  6, 0, 0 ) );
00134         WFiber b;
00135         b.push_back( WPosition( 10, 0, 0 ) );
00136         b.push_back( WPosition( 11, 0, 0 ) );
00137         b.push_back( WPosition( 12, 0, 0 ) );
00138         b.push_back( WPosition( 13, 0, 0 ) );
00139         b.push_back( WPosition( 14, 0, 0 ) );
00140         b.push_back( WPosition( 15, 0, 0 ) );
00141         b.push_back( WPosition( 16, 0, 0 ) );
00142         WDataSetFiberVector expected;
00143         expected.push_back( a );
00144         expected.push_back( b );
00145 
00146         boost::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector( expected ) );
00147         ds->at( 1 ).reverseOrder();
00148         m_cluster->unifyDirection( ds );
00149         TS_ASSERT_EQUALS( *ds, expected ); // second tract should flip over
00150         m_cluster->unifyDirection( ds );
00151         TS_ASSERT_EQUALS( *ds, expected ); // no tract should flip over
00152     }
00153 
00154     /**
00155      * Check determination of the direction of a pair of fibers which are in the following shape.
00156      *
00157       \verbatim
00158        AS.                   _BS
00159           `.              ,-'
00160             `.           /
00161               \         /
00162                \       |
00163                `.     .'
00164                  |   |
00165                  |   |
00166                  |   |
00167                  |   |
00168                  |   |
00169                  |   |
00170                 AE   BE
00171       \endverbatim
00172      */
00173     void testUnifyDirectionOnTwoCSTShapedFibers( void )
00174     {
00175         WFiber a;
00176         a.push_back( WPosition(  0,  0, 0 ) );
00177         a.push_back( WPosition(  5,  1, 0 ) );
00178         a.push_back( WPosition(  8,  3, 0 ) );
00179         a.push_back( WPosition( 11,  7, 0 ) );
00180         a.push_back( WPosition( 11, 10, 0 ) );
00181         a.push_back( WPosition( 11, 12, 0 ) );
00182         WFiber b;
00183         b.push_back( WPosition( 23,  0, 0 ) );
00184         b.push_back( WPosition( 19,  2, 0 ) );
00185         b.push_back( WPosition( 17,  5, 0 ) );
00186         b.push_back( WPosition( 15,  7, 0 ) );
00187         b.push_back( WPosition( 16, 10, 0 ) );
00188         b.push_back( WPosition( 16, 12, 0 ) );
00189         WDataSetFiberVector expected;
00190         expected.push_back( a );
00191         expected.push_back( b );
00192 
00193         boost::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector( expected ) );
00194         ds->at( 1 ).reverseOrder();
00195         m_cluster->unifyDirection( ds );
00196         TS_ASSERT_EQUALS( *ds, expected ); // second tract should flip over
00197         m_cluster->unifyDirection( ds );
00198         TS_ASSERT_EQUALS( *ds, expected ); // no tract should flip over
00199     }
00200 
00201     /**
00202      * Check determination of the direction of a pair of fibers which are in the following shape.
00203      *
00204       \verbatim
00205              _.-----AS
00206            ,'
00207           /      ,-'BS
00208          |     ,'
00209          |    /               AE
00210         |    /           BE    |
00211         |   |             |    |
00212         |   |             |    |
00213          \   \           ,|    |
00214           \   `.       ,Y'  _,'
00215            `\_  `''''''  _.'
00216              '`--------''
00217       \endverbatim
00218      */
00219     void testUnifyDirectionOnTwoCircularShapedFibersInSameCircle( void )
00220     {
00221         WFiber a;
00222         a.push_back( WPosition( 14,  0, 0 ) );
00223         a.push_back( WPosition(  5,  1, 0 ) );
00224         a.push_back( WPosition(  2,  4, 0 ) );
00225         a.push_back( WPosition(  3,  9, 0 ) );
00226         a.push_back( WPosition( 11, 11, 0 ) );
00227         a.push_back( WPosition( 19, 10, 0 ) );
00228         a.push_back( WPosition( 24,  8, 0 ) );
00229         a.push_back( WPosition( 23,  4, 0 ) );
00230         WFiber b;
00231         b.push_back( WPosition( 13,  2, 0 ) );
00232         b.push_back( WPosition(  7,  4, 0 ) );
00233         b.push_back( WPosition(  6,  8, 0 ) );
00234         b.push_back( WPosition( 10, 10, 0 ) );
00235         b.push_back( WPosition( 17,  9, 0 ) );
00236         b.push_back( WPosition( 19,  7, 0 ) );
00237         b.push_back( WPosition( 19,  5, 0 ) );
00238         WDataSetFiberVector expected;
00239         expected.push_back( a );
00240         expected.push_back( b );
00241 
00242         boost::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector( expected ) );
00243         ds->at( 1 ).reverseOrder();
00244         m_cluster->unifyDirection( ds );
00245         TS_ASSERT_EQUALS( *ds, expected ); // second tract should flip over
00246         m_cluster->unifyDirection( ds );
00247         TS_ASSERT_EQUALS( *ds, expected ); // no tract should flip over
00248     }
00249 
00250     /**
00251      * Check determination of the direction of a pair of fibers which are in the following shape.
00252      *
00253       \verbatim
00254             ,,---._
00255           ,'       \
00256          /          \
00257          |           |
00258          \          ,'
00259           \        ,'
00260            `-AS  AE
00261             BS    BE
00262           ,'       `.
00263          /           \
00264         |             |
00265         |             |
00266         |             |
00267          \           /
00268           `-._   _,-'
00269               `''
00270       \endverbatim
00271      */
00272     void testUnifyDirectionOnTwoCircularShapedFibersInDifferentCircle( void )
00273     {
00274         WFiber a;
00275         a.push_back( WPosition(  6,  6, 0 ) );
00276         a.push_back( WPosition(  3,  5, 0 ) );
00277         a.push_back( WPosition(  2,  3, 0 ) );
00278         a.push_back( WPosition(  4,  1, 0 ) );
00279         a.push_back( WPosition(  7,  0, 0 ) );
00280         a.push_back( WPosition( 11,  0, 0 ) );
00281         a.push_back( WPosition( 14,  2, 0 ) );
00282         a.push_back( WPosition( 13,  4, 0 ) );
00283         a.push_back( WPosition( 11,  6, 0 ) );
00284         WFiber b;
00285         b.push_back( WPosition(  6,  7, 0 ) );
00286         b.push_back( WPosition(  3,  9, 0 ) );
00287         b.push_back( WPosition(  1, 11, 0 ) );
00288         b.push_back( WPosition(  3, 14, 0 ) );
00289         b.push_back( WPosition(  8, 15, 0 ) );
00290         b.push_back( WPosition( 13, 14, 0 ) );
00291         b.push_back( WPosition( 15, 12, 0 ) );
00292         b.push_back( WPosition( 14,  9, 0 ) );
00293         b.push_back( WPosition( 11,  7, 0 ) );
00294         WDataSetFiberVector expected;
00295         expected.push_back( a );
00296         expected.push_back( b );
00297 
00298         boost::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector( expected ) );
00299         ds->at( 1 ).reverseOrder();
00300         m_cluster->unifyDirection( ds );
00301         TS_ASSERT_EQUALS( *ds, expected ); // second tract should flip over
00302         m_cluster->unifyDirection( ds );
00303         TS_ASSERT_EQUALS( *ds, expected ); // no tract should flip over
00304     }
00305 
00306     /**
00307      * Check determination of the direction of a pair of fibers which are in the following shape.
00308      *
00309       \verbatim
00310               ,,-'-AE   BS''`-._
00311             ,'                   `.
00312            /                       \
00313           /                         `.
00314          /                           `.
00315          /                            |
00316         |                              |
00317         |                              |
00318         |                               |
00319        |                                |
00320        |                                |
00321        |                                |
00322        AS                               BE
00323       \endverbatim
00324      */
00325     void testUnifyDirectionOnTwoInverseCSTShapedFibers( void )
00326     {
00327         WFiber a;
00328         a.push_back( WPosition(  1, 12, 0 ) );
00329         a.push_back( WPosition(  1,  9, 0 ) );
00330         a.push_back( WPosition(  2,  5, 0 ) );
00331         a.push_back( WPosition(  5,  1, 0 ) );
00332         a.push_back( WPosition(  9,  0, 0 ) );
00333         a.push_back( WPosition( 14,  0, 0 ) );
00334         WFiber b;
00335         b.push_back( WPosition( 19,  0, 0 ) );
00336         b.push_back( WPosition( 24,  0, 0 ) );
00337         b.push_back( WPosition( 29,  2, 0 ) );
00338         b.push_back( WPosition( 32,  5, 0 ) );
00339         b.push_back( WPosition( 33,  8, 0 ) );
00340         b.push_back( WPosition( 33, 12, 0 ) );
00341         WDataSetFiberVector expected;
00342         expected.push_back( a );
00343         expected.push_back( b );
00344 
00345         boost::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector( expected ) );
00346         ds->at( 1 ).reverseOrder();
00347         m_cluster->unifyDirection( ds );
00348         TS_ASSERT_EQUALS( *ds, expected ); // second tract should flip over
00349         m_cluster->unifyDirection( ds );
00350         TS_ASSERT_EQUALS( *ds, expected ); // no tract should flip over
00351     }
00352 
00353 private:
00354     /**
00355      * Compares to point sequences (aka lines) with a given delta.
00356      *
00357      * \param first First line to compare with
00358      * \param second Second line to compare with
00359      * \param delta The delta within two points are considered as equally
00360      */
00361     void assert_equals_delta( const WLine& first, const WLine& second, double delta = wlimits::DBL_EPS ) const
00362     {
00363         int diffPos = 0;
00364         if( ( diffPos =  equalsDelta( first, second, delta ) ) != -1 )
00365         {
00366             using string_utils::operator<<;
00367             std::stringstream msg;
00368             msg << "Lines are different in at least point: " << diffPos;
00369             TS_FAIL( msg.str() );
00370             std::cout << "first  line at: " << diffPos << std::endl << first[diffPos] << std::endl;
00371             std::cout << "second line at: " << diffPos << std::endl << second[diffPos] << std::endl;
00372             std::cout << "first  line: " << std::endl << first << std::endl;
00373             std::cout << "second line: " << std::endl << second << std::endl;
00374         }
00375     }
00376 
00377     /**
00378      * Generates a dataset for some unit tests.
00379      \verbatim
00380        Fiber B has 3 points: [0;2],[2;2],[4;2]
00381        Fiber A has 7 points: [0;0],[1;1],[2;1],[3;1],[4;1],[5;1],[6;1]
00382 
00383            |
00384         2 -b----------b------------b
00385            |
00386            |
00387            |
00388            |
00389            |
00390         1 -|     a-----a-----a-----a-----a-----a
00391            |    /
00392            |   /
00393            |  /
00394            | /
00395            |/
00396            a-----+-----+-----+-----+-----+-----+---
00397            0     1     2     3     4     5     6
00398 
00399      \endverbatim
00400      */
00401     void setUp( void )
00402     {
00403         // generate fiber dataset to operate on
00404         WFiber fib_a;
00405         fib_a.push_back( WPosition( 0, 0, 0 ) );
00406         fib_a.push_back( WPosition( 1, 1, 0 ) );
00407         fib_a.push_back( WPosition( 2, 1, 0 ) );
00408         fib_a.push_back( WPosition( 3, 1, 0 ) );
00409         fib_a.push_back( WPosition( 4, 1, 0 ) );
00410         fib_a.push_back( WPosition( 5, 1, 0 ) );
00411         fib_a.push_back( WPosition( 6, 1, 0 ) );
00412         WFiber fib_b;
00413         fib_b.push_back( WPosition( 0, 2, 0 ) );
00414         fib_b.push_back( WPosition( 2, 2, 0 ) );
00415         fib_b.push_back( WPosition( 4, 2, 0 ) );
00416         boost::shared_ptr< WDataSetFiberVector > ds( new WDataSetFiberVector() );
00417         ds->push_back( fib_a );
00418         ds->push_back( fib_b );
00419         generateFiberCluster( ds );
00420     }
00421 
00422     /**
00423      * Generates out of the given dataset a WFiberCluster containing all fibers.
00424      *
00425      * \param ds The fiber dataset
00426      */
00427     void generateFiberCluster( const boost::shared_ptr< WDataSetFiberVector > ds )
00428     {
00429         m_cluster.reset();
00430         m_cluster = boost::shared_ptr< WFiberCluster >( new WFiberCluster() );
00431         m_cluster->setDataSetReference( ds );
00432         std::list< size_t > idx;
00433         for( size_t i = 0; i < ds->size(); ++i )
00434         {
00435             idx.push_back( i );
00436         }
00437         m_cluster->setIndices( idx );
00438     }
00439 
00440     /**
00441      * Tidyups the dataset used in some unit tests
00442      */
00443     void tearDown( void )
00444     {
00445         m_cluster.reset();
00446     }
00447 
00448     boost::shared_ptr< WFiberCluster > m_cluster; //!< pre generated cluster for some unit tests
00449 };
00450 
00451 #endif  // WFIBERCLUSTER_TEST_H