diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsBetweennessHistogram.cpp b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsBetweennessHistogram.cpp new file mode 100644 index 0000000000..3e42652d6f --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsBetweennessHistogram.cpp @@ -0,0 +1,132 @@ + +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Module: $RCSfile$ +Language: C++ +Date: $Date$ +Version: $Revision: 11989 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include + +#include + +#include + +mitk::ConnectomicsBetweennessHistogram::ConnectomicsBetweennessHistogram() +: m_Mode( UnweightedUndirectedMode ) +, m_CentralityMap() +{ + m_Subject = "Node Betweenness"; +} + +mitk::ConnectomicsBetweennessHistogram::~ConnectomicsBetweennessHistogram() +{ +} + +void mitk::ConnectomicsBetweennessHistogram::SetBetweennessCalculationMode( + const mitk::ConnectomicsBetweennessHistogram::BetweennessCalculationMode & mode ) +{ + m_Mode = mode; +} + +mitk::ConnectomicsBetweennessHistogram::BetweennessCalculationMode mitk::ConnectomicsBetweennessHistogram::GetBetweennessCalculationMode() +{ + return m_Mode; +} + +void mitk::ConnectomicsBetweennessHistogram::ComputeFromConnectomicsNetwork( ConnectomicsNetwork* source ) +{ + NetworkType* boostGraph = source->GetBoostGraph(); + IteratorType vertex_iterator_begin, vertex_iterator_end; + + m_CentralityMap.clear(); + m_CentralityMap.resize( source->GetNumberOfVertices() ); + + switch( m_Mode ) + { + case UnweightedUndirectedMode: + { + CalculateUnweightedUndirectedBetweennessCentrality( boostGraph, vertex_iterator_begin, vertex_iterator_end ); + break; + } + case WeightedUndirectedMode: + { + CalculateWeightedUndirectedBetweennessCentrality( boostGraph, vertex_iterator_begin, vertex_iterator_end ); + break; + } + } + + ConvertCentralityMapToHistogram(); +} + +void mitk::ConnectomicsBetweennessHistogram::CalculateUnweightedUndirectedBetweennessCentrality( + NetworkType* boostGraph, IteratorType vertex_iterator_begin, IteratorType vertex_iterator_end ) +{ + boost::brandes_betweenness_centrality( + *boostGraph, + boost::centrality_map( + boost::make_iterator_property_map( m_CentralityMap.begin(), boost::get( &mitk::ConnectomicsNetwork::NetworkNode::id, *boostGraph ), double() ) + ).vertex_index_map( boost::get( &mitk::ConnectomicsNetwork::NetworkNode::id, *boostGraph ) ) + ); + +} + +void mitk::ConnectomicsBetweennessHistogram::CalculateWeightedUndirectedBetweennessCentrality( + NetworkType* boostGraph, IteratorType vertex_iterator_begin, IteratorType vertex_iterator_end ) +{ + MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_UNIMPLEMENTED_FEATURE; +} + +void mitk::ConnectomicsBetweennessHistogram::ConvertCentralityMapToHistogram() +{ + double maximumFloat( 0.0 ); + + for ( int index( 0 ); index < m_CentralityMap.size(); index++ ) + { + if( m_CentralityMap[ index ] > maximumFloat ) + { + maximumFloat = m_CentralityMap[ index ]; + } + } + + // use the boost double to int converter + // it defaults to trunc + typedef boost::numeric::converter Double2Int ; + + // for rounding, reduces the number of nodes classed as zero + maximumFloat += 0.5; + + int maximumInt( 0 ); + try + { + maximumInt = Double2Int::convert( maximumFloat ); + } + catch ( boost::numeric::positive_overflow const& ) + { + MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_OUTSIDE_INTEGER_RANGE; + } + + m_HistogramVector.resize( maximumInt + 1 ); + + for ( int index( 0 ); index < m_CentralityMap.size(); index++ ) + { + int value( 0 ); + value = Double2Int::convert( ( m_CentralityMap[index ] + 0.5 ) ); + m_HistogramVector[ value ]++; + } + + UpdateYMax(); + + m_Valid = true; +} \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsBetweennessHistogram.h b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsBetweennessHistogram.h new file mode 100644 index 0000000000..33c683ecf9 --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsBetweennessHistogram.h @@ -0,0 +1,82 @@ + +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Module: $RCSfile$ +Language: C++ +Date: $Date$ +Version: $Revision: 11989 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#ifndef _MITK_ConnectomicsBetweennessHistogram_H +#define _MITK_ConnectomicsBetweennessHistogram_H + +#include + +#include + +namespace mitk { + + /** + * \brief A class to calculate and store the betweenness of each node */ + class ConnectomicsBetweennessHistogram : public mitk::ConnectomicsHistogramBase + { + + public: + + /** Enum for different ways to calculate betweenness centrality */ + + enum BetweennessCalculationMode + { + UnweightedUndirectedMode, + WeightedUndirectedMode + }; + + ConnectomicsBetweennessHistogram(); + virtual ~ConnectomicsBetweennessHistogram(); + + /** Set the calucaltion mode */ + void SetBetweennessCalculationMode( const BetweennessCalculationMode & ); + + /** Get the calculation mode */ + BetweennessCalculationMode GetBetweennessCalculationMode(); + + protected: + + /* Typedefs */ + typedef mitk::ConnectomicsNetwork::NetworkType NetworkType; + typedef boost::graph_traits< NetworkType >::vertex_iterator IteratorType; + typedef std::vector< double > BCMapType; + + /** @brief Creates a new histogram from the network source. */ + virtual void ComputeFromConnectomicsNetwork( ConnectomicsNetwork* source ); + + /** Calculate betweenness centrality ignoring the weight of the edges */ + void CalculateUnweightedUndirectedBetweennessCentrality( NetworkType*, IteratorType, IteratorType ); + + /** Calculate betweenness centrality taking into consideration the weight of the edges */ + void CalculateWeightedUndirectedBetweennessCentrality( NetworkType*, IteratorType, IteratorType ); + + /** Converts the centrality map to a histogram by binning */ + void ConvertCentralityMapToHistogram(); + + /** Stores which mode has been selected for betweenness centrality calculation */ + BetweennessCalculationMode m_Mode; + + /** Stores the betweenness centralities for each node */ + BCMapType m_CentralityMap; + }; + +} + +#endif /* _MITK_ConnectomicsBetweennessHistogram_H */ \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsDegreeHistogram.cpp b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsDegreeHistogram.cpp new file mode 100644 index 0000000000..061f335322 --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsDegreeHistogram.cpp @@ -0,0 +1,60 @@ + +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Module: $RCSfile$ +Language: C++ +Date: $Date$ +Version: $Revision: 11989 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include + +mitk::ConnectomicsDegreeHistogram::ConnectomicsDegreeHistogram() +{ + m_Subject = "Node degree"; +} + +mitk::ConnectomicsDegreeHistogram::~ConnectomicsDegreeHistogram() +{ +} + +void mitk::ConnectomicsDegreeHistogram::ComputeFromConnectomicsNetwork( ConnectomicsNetwork* source ) +{ + std::vector< int > degreeOfNodesVector = source->GetDegreeOfNodes(); + + int maximumDegree( 0 ); + + for( int index( 0 ); index < degreeOfNodesVector.size(); index++ ) + { + if( maximumDegree < degreeOfNodesVector[ index ] ) + { + maximumDegree = degreeOfNodesVector[ index ]; + } + } + + this->m_HistogramVector.resize( maximumDegree + 1 ); + + for( int index( 0 ); index < m_HistogramVector.size(); index++ ) + { + this->m_HistogramVector[ index ] = 0; + } + this->m_TopValue = maximumDegree; + + for( int index( 0 ); index < degreeOfNodesVector.size(); index++ ) + { + this->m_HistogramVector[ degreeOfNodesVector[ index ] ]++; + + } + // successfully created a valid histogram + this->m_Valid = true; +} \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsDegreeHistogram.h b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsDegreeHistogram.h new file mode 100644 index 0000000000..325451273e --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsDegreeHistogram.h @@ -0,0 +1,49 @@ + +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Module: $RCSfile$ +Language: C++ +Date: $Date$ +Version: $Revision: 11989 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#ifndef _MITK_ConnectomicsDegreeHistogram_H +#define _MITK_ConnectomicsDegreeHistogram_H + +#include + +namespace mitk { + + /** + * \brief A class to calculate and store the degree of each node */ + class ConnectomicsDegreeHistogram : public mitk::ConnectomicsHistogramBase + { + + public: + + ConnectomicsDegreeHistogram(); + virtual ~ConnectomicsDegreeHistogram(); + + + + protected: + + /** @brief Creates a new histogram from the network source. */ + virtual void ComputeFromConnectomicsNetwork( ConnectomicsNetwork* source ); + + }; + +} + +#endif /* _MITK_ConnectomicsDegreeHistogram_H */ \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsHistogramBase.cpp b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsHistogramBase.cpp new file mode 100644 index 0000000000..6235fc30d9 --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsHistogramBase.cpp @@ -0,0 +1,228 @@ + + +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Module: $RCSfile$ +Language: C++ +Date: $Date$ +Version: $Revision: 11989 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include +#include + +#include + +mitk::ConnectomicsHistogramBase::ConnectomicsHistogramBase() +: m_Valid( false ) +, m_BaselineValue( 0 ) +, m_TopValue( 1 ) +, m_StartValue( 0 ) +, m_Subject( "" ) +{ +} + +mitk::ConnectomicsHistogramBase::~ConnectomicsHistogramBase() +{ +} + + +double mitk::ConnectomicsHistogramBase::GetYMin() const +{ + return m_BaselineValue; +} + +double mitk::ConnectomicsHistogramBase::GetYMax() const +{ + return m_TopValue; +} + +double mitk::ConnectomicsHistogramBase::GetMin() const +{ + return this->GetXMin(); +} + +double mitk::ConnectomicsHistogramBase::GetMax() const +{ + return this->GetXMax(); +} + +double mitk::ConnectomicsHistogramBase::GetXMin() const +{ + return m_StartValue; +} + +double mitk::ConnectomicsHistogramBase::GetXMax() const +{ + return ( m_StartValue + this->GetRange() ); +} + +int mitk::ConnectomicsHistogramBase::GetRange() const +{ + return m_HistogramVector.size(); +} + +bool mitk::ConnectomicsHistogramBase::IsValid() const +{ + return m_Valid; +} + +void mitk::ConnectomicsHistogramBase::PrintToConsole() const +{ + MITK_INFO << "Histogram - Maximum " << this->GetYMax() << " Minimum " << this->GetYMin() << " Range " << this->GetRange(); + + for( int index( 0 ); index < m_HistogramVector.size(); index++ ) + { + MITK_INFO << " Bin: " << index << " Value: " << m_HistogramVector[ index ]; + } +} + +std::string mitk::ConnectomicsHistogramBase::GetSubject() const +{ + return m_Subject; +} + +void mitk::ConnectomicsHistogramBase::SetSubject( std::string subject ) +{ + m_Subject = subject; +} + +void mitk::ConnectomicsHistogramBase::ComputeFromBaseData( BaseData* source ) +{ + m_Valid = false; + m_HistogramVector.clear(); + + //check if input is valid + if (source==NULL) + { // empty base data + return; + } + + mitk::ConnectomicsNetwork* networkSource = dynamic_cast(source); + + if (networkSource==NULL) + { // base data but no network + return; + } + + ComputeFromConnectomicsNetwork( networkSource ); +} + +float mitk::ConnectomicsHistogramBase::GetRelativeBin( double start, double end ) const +{ + // use the boost double to int converter + // it defaults to trunc + typedef boost::numeric::converter Double2Int ; + + float result( 0.0 ); + + if( !m_Valid ) + { + MITK_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_TRIED_TO_ACCESS_INVALID_HISTOGRAM; + return result; + } + + if( ( start < 0.0 ) || + ( end < 0.0 ) ) + { + MITK_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_PASSED_NEGATIVE_INDEX_TO_HISTOGRAM; + return result; + } + + // calculate result + if( std::abs( end - start ) <= 1.0 ) + { // if the bin size is one or less, we can do not need to interpolate + + int index( 0 ); + try + { + // show the value for n between n - .5 and n + .5 + double temp = ( start + end ) / 2.0; + index = Double2Int::convert( temp ); // By default throws positive_overflow() + } + catch ( boost::numeric::positive_overflow const& ) + { + MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_OUTSIDE_INTEGER_RANGE; + } + + if( index < m_HistogramVector.size() ) + { + result = m_HistogramVector[ index ]; + } + else + { + MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_BEYOND_SCOPE << + index << " on vector sized: " << m_HistogramVector.size(); + } + } + else + { // if the bin size is more than one we need to interpolate + + int indexStart( 0 ), indexEnd( 0 ); + + try + { + indexStart = Double2Int::convert( start ); + indexEnd = Double2Int::convert( end ); + } + catch ( boost::numeric::positive_overflow const& ) + { + MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_OUTSIDE_INTEGER_RANGE; + } + + if( ( indexStart < m_HistogramVector.size() ) && + ( indexEnd < m_HistogramVector.size() ) ) + { + // add up weighted values and divide by range + + // add partial start and end bin + + double startPercentage = 1.0 - start + indexStart; + double endPercentage = end - indexEnd; + + result += startPercentage * m_HistogramVector[ indexStart ]; + result += endPercentage * m_HistogramVector[ indexEnd ]; + + // add whole inbetween bins + for( int tempIndex = indexStart + 1; tempIndex < indexEnd; tempIndex++ ) + { + result += m_HistogramVector[ tempIndex ]; + } + } + else + { + MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_BEYOND_SCOPE << indexStart << " to " << + indexEnd << " on vector sized: " << m_HistogramVector.size(); + } + } + + // normalizeresult by dividing through maximum degree + result = result / GetYMax(); + return result; +} + +void mitk::ConnectomicsHistogramBase::UpdateYMax() +{ + for ( int index( 0 ); index < m_HistogramVector.size(); index++ ) + { + if( m_HistogramVector[ index ] > m_TopValue ) + { + m_TopValue = m_HistogramVector[ index ]; + } + } +} + +std::vector< double > mitk::ConnectomicsHistogramBase::GetHistogramVector() +{ + return m_HistogramVector; +} \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsHistogramBase.h b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsHistogramBase.h new file mode 100644 index 0000000000..ee5981640f --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsHistogramBase.h @@ -0,0 +1,103 @@ + +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Module: $RCSfile$ +Language: C++ +Date: $Date$ +Version: $Revision: 11989 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef _MITK_ConnectomicsHistogramBase_H +#define _MITK_ConnectomicsHistogramBase_H + +#include "mitkSimpleHistogram.h" +#include "mitkCommon.h" + +#include "mitkConnectomicsNetwork.h" + +namespace mitk { + + //##Documentation + //## @brief Superclass for histograms working with connectomic networks + + class ConnectomicsHistogramBase : public mitk::SimpleHistogram + { + + public: + + ConnectomicsHistogramBase(); + virtual ~ConnectomicsHistogramBase(); + + /** @brief Returns the minimal y=f(x) value of the histogram. */ + virtual double GetYMin() const; + /** @brief Returns the maximum y=f(x) value of the histogram. */ + virtual double GetYMax() const; + /** @brief Returns the minimal x value of the histogram. */ + virtual double GetXMin() const; + /** @brief Returns the maximum x value of the histogram. */ + virtual double GetXMax() const; + /** @brief Returns the range of the histogram. */ + virtual int GetRange() const; + /** @brief Update the Y maximum to the maximal value in the histogram */ + virtual void UpdateYMax(); + /** @brief Creates a new histogram from the source. */ + virtual void ComputeFromBaseData( BaseData* source ); + /** @brief Print values to console. */ + virtual void PrintToConsole( ) const; + /** @brief Returns whether the histogram can be considered valid. */ + virtual bool IsValid() const; + /** @brief Returns the subject of the histogram as a string. */ + virtual std::string GetSubject() const; + /** @brief Set the subject of the histogram as a string. */ + virtual void SetSubject( std::string ); + + /** @brief Get bin height for the bin between start and end*/ + virtual float GetRelativeBin( double start, double end ) const; + + /** @brief Get the double vector*/ + virtual std::vector< double > GetHistogramVector(); + + protected: + + // Functions + + /** @brief Creates a new histogram from the network source. */ + virtual void ComputeFromConnectomicsNetwork( ConnectomicsNetwork* source ) = 0; + /** @brief Legacy method, do no use */ + virtual double GetMin() const; + /** @brief Legacy method, do no use */ + virtual double GetMax() const; + + // Variables + + /** @brief Is this a valid histogram*/ + bool m_Valid; + /** @brief Which is the baseline value for the histogram + /* + /* This value should be zero for all network histograms */ + int m_BaselineValue; + /** @brief Which is the top value for the histogram */ + int m_TopValue; + /** @brief Which is the starting x value for the histogram */ + int m_StartValue; + + /** @brief We expect not continuous but discrete histograms */ + std::vector< double > m_HistogramVector; + + /** @brief Subject of the histogram as a string. */ + std::string m_Subject; + }; + +} + +#endif /* _MITK_ConnectomicsHistogramBase_H */ \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsHistogramCache.cpp b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsHistogramCache.cpp new file mode 100644 index 0000000000..183b3b5358 --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsHistogramCache.cpp @@ -0,0 +1,84 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkConnectomicsHistogramCache.h" + +mitk::ConnectomicsHistogramCache::ConnectomicsHistogramCache() +{ +} + +mitk::ConnectomicsHistogramCache::~ConnectomicsHistogramCache() +{ +} + +mitk::ConnectomicsHistogramsContainer * mitk::ConnectomicsHistogramCache::operator[]( mitk::ConnectomicsNetwork::Pointer sp_NetworkData ) +{ + BaseData *p_BaseData = dynamic_cast< BaseData* >( sp_NetworkData.GetPointer() ); + + if(!p_BaseData) + { + MITK_WARN << "ConnectomicsHistogramCache::operator[] with null connectomics network data called"; + return 0; + } + + ConnectomicsHistogramsCacheElement *elementToUpdate = 0; + + bool first = true; + + for(CacheContainer::iterator iter = cache.begin(); iter != cache.end(); iter++) + { + ConnectomicsHistogramsCacheElement *e = dynamic_cast(*iter); + BaseData *p_tmp = e->baseData.GetPointer(); + + if(p_tmp == p_BaseData) + { + if(!first) + { + cache.erase(iter); + cache.push_front(e); + } + if( p_BaseData->GetMTime() > e->m_LastUpdateTime.GetMTime()) + goto recomputeElement; + + + return dynamic_cast( e->GetHistograms() ); + } + + first = false; + } + + if (dynamic_cast(p_BaseData)) + { + elementToUpdate = new ConnectomicsHistogramsCacheElement(); + } + else + { + MITK_WARN << "not supported: " << p_BaseData->GetNameOfClass(); + return NULL; + } + + elementToUpdate->baseData = p_BaseData; + cache.push_front(elementToUpdate); + TrimCache(); + + recomputeElement: + + elementToUpdate->ComputeFromBaseData(p_BaseData); + elementToUpdate->m_LastUpdateTime.Modified(); + return dynamic_cast( elementToUpdate->GetHistograms() ); +} + diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsHistogramCache.h b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsHistogramCache.h new file mode 100644 index 0000000000..78985554f0 --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsHistogramCache.h @@ -0,0 +1,113 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#ifndef MITKCONNECTOMICSHISTOGRAMCACHE_H +#define MITKCONNECTOMICSHISTOGRAMCACHE_H + +#include "mitkSimpleHistogram.h" +#include "mitkConnectomicsNetwork.h" + +#include +#include +#include + +#include "MitkDiffusionImagingExports.h" + +namespace mitk { + + //##Documentation + //## @brief Provides a method to cache network histograms + + class ConnectomicsHistogramsContainer + { + public: + + void ComputeFromBaseData(BaseData* baseData) + { + m_BetweennessHistogram.ComputeFromBaseData(baseData); + m_DegreeHistogram.ComputeFromBaseData(baseData); + m_ShortestPathHistogram.ComputeFromBaseData(baseData); + } + + ConnectomicsBetweennessHistogram* GetBetweennessHistogram( ) + { + return &m_BetweennessHistogram; + } + + ConnectomicsDegreeHistogram* GetDegreeHistogram( ) + { + return &m_DegreeHistogram; + } + + ConnectomicsShortestPathHistogram* GetShortestPathHistogram( ) + { + return &m_ShortestPathHistogram; + } + + ConnectomicsBetweennessHistogram m_BetweennessHistogram; + ConnectomicsDegreeHistogram m_DegreeHistogram; + ConnectomicsShortestPathHistogram m_ShortestPathHistogram; + }; + + class MitkDiffusionImaging_EXPORT ConnectomicsHistogramCache : public SimpleHistogramCache + { + public: + + ConnectomicsHistogramCache(); + ~ConnectomicsHistogramCache(); + + ConnectomicsHistogramsContainer *operator[]( ConnectomicsNetwork::Pointer sp_NetworkData); + + + protected: + + // purposely not implemented + SimpleHistogram *operator[](BaseData::Pointer sp_BaseData); + + }; + + + + class ConnectomicsHistogramsCacheElement : public ConnectomicsHistogramCache::Element + { + public: + + void ComputeFromBaseData(BaseData* baseData) + { + m_Container.ComputeFromBaseData(baseData); + } + + ConnectomicsHistogramsContainer* GetHistograms() + { + return &m_Container; + } + + ConnectomicsHistogramsContainer m_Container; + + private: + ConnectomicsHistogramBase* GetHistogram() + { + return NULL; + } + }; + + + +} + +#endif // MITKCONNECTOMICSHISTOGRAMCACHE_H diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsNetworkCreator.cpp b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsNetworkCreator.cpp new file mode 100644 index 0000000000..12317bfb1a --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsNetworkCreator.cpp @@ -0,0 +1,758 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkConnectomicsNetworkCreator.h" + +#include +#include + +#include "mitkConnectomicsConstantsManager.h" + +// VTK +#include +#include +#include + +mitk::ConnectomicsNetworkCreator::ConnectomicsNetworkCreator() +: m_FiberBundle() +, m_Segmentation() +, m_ConNetwork( mitk::ConnectomicsNetwork::New() ) +, idCounter(0) +, m_LabelToVertexMap() +, m_LabelToNodePropertyMap() +, allowLoops( false ) +{ +} + +mitk::ConnectomicsNetworkCreator::ConnectomicsNetworkCreator( mitk::Image::Pointer segmentation, mitk::FiberBundleX::Pointer fiberBundle ) +: m_FiberBundle(fiberBundle) +, m_Segmentation(segmentation) +, m_ConNetwork( mitk::ConnectomicsNetwork::New() ) +, idCounter(0) +, m_LabelToVertexMap() +, m_LabelToNodePropertyMap() +, allowLoops( false ) +{ +} + +mitk::ConnectomicsNetworkCreator::~ConnectomicsNetworkCreator() +{ +} + +void mitk::ConnectomicsNetworkCreator::SetFiberBundle(mitk::FiberBundleX::Pointer fiberBundle) +{ + m_FiberBundle = fiberBundle; +} + +void mitk::ConnectomicsNetworkCreator::SetSegmentation(mitk::Image::Pointer segmentation) +{ + m_Segmentation = segmentation; +} + +itk::Point mitk::ConnectomicsNetworkCreator::GetItkPoint(double point[3]) +{ + itk::Point itkPoint; + itkPoint[0] = point[0]; + itkPoint[1] = point[1]; + itkPoint[2] = point[2]; + return itkPoint; +} + +void mitk::ConnectomicsNetworkCreator::CreateNetworkFromFibersAndSegmentation() +{ + + //empty graph + m_ConNetwork->clear(); + m_LabelToVertexMap.clear(); + m_LabelToNodePropertyMap.clear(); + + vtkSmartPointer fiberPolyData = m_FiberBundle->GetFiberPolyData(); + vtkSmartPointer vLines = fiberPolyData->GetLines(); + vLines->InitTraversal(); + + //int numFibers = m_FiberBundle->GetNumFibers(); + int numFibers= 10; + for( int fiberID( 0 ); fiberID < numFibers; fiberID++ ) + { + vtkIdType numPointsInCell(0); + vtkIdType* pointsInCell(NULL); + vLines->GetNextCell ( numPointsInCell, pointsInCell ); + + TractType::Pointer singleTract = TractType::New(); + for( int pointInCellID( 0 ); pointInCellID < numPointsInCell ; pointInCellID++) + { + // push back point + PointType point = GetItkPoint( fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] ) ); + singleTract->InsertElement( singleTract->Size(), point ); + } + + //MappingStrategy strategy = EndElementPosition; + //MappingStrategy strategy = JustEndPointVerticesNoLabel; + MappingStrategy strategy = EndElementPositionAvoidingWhiteMatter; + if ( singleTract && ( singleTract->Size() > 0 ) ) + { + AddConnectionToNetwork( + ReturnAssociatedVertexPairForLabelPair( + ReturnLabelForFiberTract( singleTract, strategy ) + ) + ); + } + } + + // provide network with geometry + m_ConNetwork->SetGeometry( m_Segmentation->GetGeometry() ); + m_ConNetwork->SetIsModified( true ); + + MBI_INFO << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_INFO_NETWORK_CREATED; +} + +void mitk::ConnectomicsNetworkCreator::AddConnectionToNetwork(ConnectionType newConnection) +{ + VertexType vertexA = newConnection.first; + VertexType vertexB = newConnection.second; + + // if vertices A and B exist + if( vertexA && vertexB) + { + // check for loops (if they are not allowed + if( allowLoops || !( vertexA == vertexB ) ) + { + // If the connection already exists, increment weight, else create connection + if ( m_ConNetwork->EdgeExists( vertexA, vertexB ) ) + { + m_ConNetwork->IncreaseEdgeWeight( vertexA, vertexB ); + } + else + { + m_ConNetwork->AddEdge( vertexA, vertexB ); + } + } + } +} + + +mitk::ConnectomicsNetworkCreator::VertexType mitk::ConnectomicsNetworkCreator::ReturnAssociatedVertexForLabel( ImageLabelType label ) +{ + // if label is not known, create entry + if( ! ( m_LabelToVertexMap.count( label ) > 0 ) ) + { + VertexType newVertex = m_ConNetwork->AddVertex( idCounter ); + idCounter++; + SupplyVertexWithInformation(label, newVertex); + m_LabelToVertexMap.insert( std::pair< ImageLabelType, VertexType >( label, newVertex ) ); + } + + //return associated vertex + return m_LabelToVertexMap.find( label )->second; +} + +mitk::ConnectomicsNetworkCreator::ConnectionType mitk::ConnectomicsNetworkCreator::ReturnAssociatedVertexPairForLabelPair( ImageLabelPairType labelpair ) +{ + //hand both labels through to the single label function + ConnectionType connection( ReturnAssociatedVertexForLabel(labelpair.first), ReturnAssociatedVertexForLabel(labelpair.second) ); + + return connection; +} + +mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::ReturnLabelForFiberTract( TractType::Pointer singleTract, mitk::ConnectomicsNetworkCreator::MappingStrategy strategy) +{ + switch( strategy ) + { + case EndElementPosition: + { + return EndElementPositionLabel( singleTract ); + } + case PrecomputeAndDistance: + { + return PrecomputeVertexLocationsBySegmentation( singleTract ); + } + case JustEndPointVerticesNoLabel: + { + return JustEndPointVerticesNoLabelTest( singleTract ); + } + case EndElementPositionAvoidingWhiteMatter: + { + return EndElementPositionLabelAvoidingWhiteMatter( singleTract ); + } + } + + // To remove warnings, this code should never be reached + MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_MAPPING; + ImageLabelPairType nullPair( NULL, NULL ); + return nullPair; +} + +mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::EndElementPositionLabel( TractType::Pointer singleTract ) +{ + ImageLabelPairType labelpair; + + {// Note: .fib image tracts are safed using index coordinates + mitk::Point3D firstElementFiberCoord, lastElementFiberCoord; + mitk::Point3D firstElementSegCoord, lastElementSegCoord; + mitk::Index3D firstElementSegIndex, lastElementSegIndex; + + if( singleTract->front().Size() != 3 ) + { + MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3; + } + for( int index = 0; index < singleTract->front().Size(); index++ ) + { + firstElementFiberCoord.SetElement( index, singleTract->front().GetElement( index ) ); + lastElementFiberCoord.SetElement( index, singleTract->back().GetElement( index ) ); + } + + // convert from fiber index coordinates to segmentation index coordinates + FiberToSegmentationCoords( firstElementFiberCoord, firstElementSegCoord ); + FiberToSegmentationCoords( lastElementFiberCoord, lastElementSegCoord ); + + for( int index = 0; index < 3; index++ ) + { + firstElementSegIndex.SetElement( index, firstElementSegCoord.GetElement( index ) ); + lastElementSegIndex.SetElement( index, lastElementSegCoord.GetElement( index ) ); + } + + int firstLabel = m_Segmentation->GetPixelValueByIndex( firstElementSegIndex ); + int lastLabel = m_Segmentation->GetPixelValueByIndex( lastElementSegIndex ); + + labelpair.first = firstLabel; + labelpair.second = lastLabel; + + // Add property to property map + if( ! ( m_LabelToNodePropertyMap.count( firstLabel ) > 0 ) ) + { + NetworkNode firstNode; + + firstNode.coordinates.resize( 3 ); + for( unsigned int index = 0; index < firstNode.coordinates.size() ; index++ ) + { + firstNode.coordinates[ index ] = firstElementSegIndex[ index ] ; + } + + firstNode.label = LabelToString( firstLabel ); + + m_LabelToNodePropertyMap.insert( std::pair< ImageLabelType, NetworkNode >( firstLabel, firstNode ) ); + } + + if( ! ( m_LabelToNodePropertyMap.count( lastLabel ) > 0 ) ) + { + NetworkNode lastNode; + + lastNode.coordinates.resize( 3 ); + for( unsigned int index = 0; index < lastNode.coordinates.size() ; index++ ) + { + lastNode.coordinates[ index ] = lastElementSegIndex[ index ] ; + } + + lastNode.label = LabelToString( lastLabel ); + + m_LabelToNodePropertyMap.insert( std::pair< ImageLabelType, NetworkNode >( lastLabel, lastNode ) ); + } + } + + return labelpair; +} + +mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::PrecomputeVertexLocationsBySegmentation( TractType::Pointer singleTract ) +{ + ImageLabelPairType labelpair; + + return labelpair; +} + +mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::EndElementPositionLabelAvoidingWhiteMatter( TractType::Pointer singleTract ) +{ + ImageLabelPairType labelpair; + + {// Note: .fib image tracts are safed using index coordinates + mitk::Point3D firstElementFiberCoord, lastElementFiberCoord; + mitk::Point3D firstElementSegCoord, lastElementSegCoord; + mitk::Index3D firstElementSegIndex, lastElementSegIndex; + + if( singleTract->front().Size() != 3 ) + { + MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3; + } + for( int index = 0; index < singleTract->front().Size(); index++ ) + { + firstElementFiberCoord.SetElement( index, singleTract->front().GetElement( index ) ); + lastElementFiberCoord.SetElement( index, singleTract->back().GetElement( index ) ); + } + + // convert from fiber index coordinates to segmentation index coordinates + FiberToSegmentationCoords( firstElementFiberCoord, firstElementSegCoord ); + FiberToSegmentationCoords( lastElementFiberCoord, lastElementSegCoord ); + + for( int index = 0; index < 3; index++ ) + { + firstElementSegIndex.SetElement( index, firstElementSegCoord.GetElement( index ) ); + lastElementSegIndex.SetElement( index, lastElementSegCoord.GetElement( index ) ); + } + + int firstLabel = m_Segmentation->GetPixelValueByIndex( firstElementSegIndex ); + int lastLabel = m_Segmentation->GetPixelValueByIndex( lastElementSegIndex ); + + // Check whether the labels belong to the white matter (which means, that the fibers ended early) + bool extendFront(false), extendEnd(false), retractFront(false), retractEnd(false); + extendFront = !IsNonWhiteMatterLabel( firstLabel ); + extendEnd = !IsNonWhiteMatterLabel( lastLabel ); + retractFront = IsBackgroundLabel( firstLabel ); + retractEnd = IsBackgroundLabel( lastLabel ); + + //if( extendFront || extendEnd ) + //{ + //MBI_INFO << "Before Start: " << firstLabel << " at " << firstElementSegIndex[ 0 ] << " " << firstElementSegIndex[ 1 ] << " " << firstElementSegIndex[ 2 ] << " End: " << lastLabel << " at " << lastElementSegIndex[ 0 ] << " " << lastElementSegIndex[ 1 ] << " " << lastElementSegIndex[ 2 ]; + //} + if ( extendFront ) + { + std::vector< int > indexVectorOfPointsToUse; + + //Use first two points for direction + indexVectorOfPointsToUse.push_back( 1 ); + indexVectorOfPointsToUse.push_back( 0 ); + + // label and coordinate temp storage + int tempLabel( firstLabel ); + mitk::Index3D tempIndex = firstElementSegIndex; + + LinearExtensionUntilGreyMatter( indexVectorOfPointsToUse, singleTract, tempLabel, tempIndex ); + + firstLabel = tempLabel; + firstElementSegIndex = tempIndex; + + } + + if ( extendEnd ) + { + std::vector< int > indexVectorOfPointsToUse; + + //Use last two points for direction + indexVectorOfPointsToUse.push_back( singleTract->Size() - 2 ); + indexVectorOfPointsToUse.push_back( singleTract->Size() - 1 ); + + // label and coordinate temp storage + int tempLabel( lastLabel ); + mitk::Index3D tempIndex = lastElementSegIndex; + + LinearExtensionUntilGreyMatter( indexVectorOfPointsToUse, singleTract, tempLabel, tempIndex ); + + lastLabel = tempLabel; + lastElementSegIndex = tempIndex; + } + if ( retractFront ) + { + // label and coordinate temp storage + int tempLabel( firstLabel ); + mitk::Index3D tempIndex = firstElementSegIndex; + + RetractionUntilBrainMatter( true, singleTract, tempLabel, tempIndex ); + + firstLabel = tempLabel; + firstElementSegIndex = tempIndex; + + } + + if ( retractEnd ) + { + // label and coordinate temp storage + int tempLabel( lastLabel ); + mitk::Index3D tempIndex = lastElementSegIndex; + + RetractionUntilBrainMatter( false, singleTract, tempLabel, tempIndex ); + + lastLabel = tempLabel; + lastElementSegIndex = tempIndex; + } + //if( extendFront || extendEnd ) + //{ + // MBI_INFO << "After Start: " << firstLabel << " at " << firstElementSegIndex[ 0 ] << " " << firstElementSegIndex[ 1 ] << " " << firstElementSegIndex[ 2 ] << " End: " << lastLabel << " at " << lastElementSegIndex[ 0 ] << " " << lastElementSegIndex[ 1 ] << " " << lastElementSegIndex[ 2 ]; + //} + + labelpair.first = firstLabel; + labelpair.second = lastLabel; + + // Add property to property map + if( ! ( m_LabelToNodePropertyMap.count( firstLabel ) > 0 ) ) + { + NetworkNode firstNode; + + firstNode.coordinates.resize( 3 ); + for( unsigned int index = 0; index < firstNode.coordinates.size() ; index++ ) + { + firstNode.coordinates[ index ] = firstElementSegIndex[ index ] ; + } + + firstNode.label = LabelToString( firstLabel ); + + m_LabelToNodePropertyMap.insert( std::pair< ImageLabelType, NetworkNode >( firstLabel, firstNode ) ); + } + + if( ! ( m_LabelToNodePropertyMap.count( lastLabel ) > 0 ) ) + { + NetworkNode lastNode; + + lastNode.coordinates.resize( 3 ); + for( unsigned int index = 0; index < lastNode.coordinates.size() ; index++ ) + { + lastNode.coordinates[ index ] = lastElementSegIndex[ index ] ; + } + + lastNode.label = LabelToString( lastLabel ); + + m_LabelToNodePropertyMap.insert( std::pair< ImageLabelType, NetworkNode >( lastLabel, lastNode ) ); + } + } + + return labelpair; +} + +mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::JustEndPointVerticesNoLabelTest( TractType::Pointer singleTract ) +{ + ImageLabelPairType labelpair; + + {// Note: .fib image tracts are safed using index coordinates + mitk::Point3D firstElementFiberCoord, lastElementFiberCoord; + mitk::Point3D firstElementSegCoord, lastElementSegCoord; + mitk::Index3D firstElementSegIndex, lastElementSegIndex; + + if( singleTract->front().Size() != 3 ) + { + MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3; + } + for( int index = 0; index < singleTract->front().Size(); index++ ) + { + firstElementFiberCoord.SetElement( index, singleTract->front().GetElement( index ) ); + lastElementFiberCoord.SetElement( index, singleTract->back().GetElement( index ) ); + } + + // convert from fiber index coordinates to segmentation index coordinates + FiberToSegmentationCoords( firstElementFiberCoord, firstElementSegCoord ); + FiberToSegmentationCoords( lastElementFiberCoord, lastElementSegCoord ); + + for( int index = 0; index < 3; index++ ) + { + firstElementSegIndex.SetElement( index, firstElementSegCoord.GetElement( index ) ); + lastElementSegIndex.SetElement( index, lastElementSegCoord.GetElement( index ) ); + } + + int firstLabel = 1 * firstElementSegIndex[ 0 ] + 1000 * firstElementSegIndex[ 1 ] + 1000000 * firstElementSegIndex[ 2 ]; + int lastLabel = 1 * firstElementSegIndex[ 0 ] + 1000 * firstElementSegIndex[ 1 ] + 1000000 * firstElementSegIndex[ 2 ]; + + labelpair.first = firstLabel; + labelpair.second = lastLabel; + + // Add property to property map + if( ! ( m_LabelToNodePropertyMap.count( firstLabel ) > 0 ) ) + { + NetworkNode firstNode; + + firstNode.coordinates.resize( 3 ); + for( unsigned int index = 0; index < firstNode.coordinates.size() ; index++ ) + { + firstNode.coordinates[ index ] = firstElementSegIndex[ index ] ; + } + + firstNode.label = LabelToString( firstLabel ); + + m_LabelToNodePropertyMap.insert( std::pair< ImageLabelType, NetworkNode >( firstLabel, firstNode ) ); + } + + if( ! ( m_LabelToNodePropertyMap.count( lastLabel ) > 0 ) ) + { + NetworkNode lastNode; + + lastNode.coordinates.resize( 3 ); + for( unsigned int index = 0; index < lastNode.coordinates.size() ; index++ ) + { + lastNode.coordinates[ index ] = lastElementSegIndex[ index ] ; + } + + lastNode.label = LabelToString( lastLabel ); + + m_LabelToNodePropertyMap.insert( std::pair< ImageLabelType, NetworkNode >( lastLabel, lastNode ) ); + } + } + + return labelpair; +} + +void mitk::ConnectomicsNetworkCreator::SupplyVertexWithInformation( ImageLabelType& label, VertexType& vertex ) +{ // supply a vertex with the additional information belonging to the label + + // TODO: Implement additional information acquisition + + m_ConNetwork->SetLabel( vertex, m_LabelToNodePropertyMap.find( label )->second.label ); + m_ConNetwork->SetCoordinates( vertex, m_LabelToNodePropertyMap.find( label )->second.coordinates ); + +} + +std::string mitk::ConnectomicsNetworkCreator::LabelToString( ImageLabelType& label ) +{ + int tempInt = (int) label; + std::stringstream ss;//create a stringstream + std::string tempString; + ss << tempInt;//add number to the stream + tempString = ss.str(); + return tempString;//return a string with the contents of the stream +} + +mitk::ConnectomicsNetwork::Pointer mitk::ConnectomicsNetworkCreator::GetNetwork() +{ + return m_ConNetwork; +} + +void mitk::ConnectomicsNetworkCreator::FiberToSegmentationCoords( mitk::Point3D& fiberCoord, mitk::Point3D& segCoord ) +{ + mitk::Point3D tempPoint; + + // convert from fiber index coordinates to segmentation index coordinates + m_FiberBundle->GetGeometry()->IndexToWorld( fiberCoord, tempPoint ); + m_Segmentation->GetGeometry()->WorldToIndex( tempPoint, segCoord ); +} + +void mitk::ConnectomicsNetworkCreator::SegmentationToFiberCoords( mitk::Point3D& segCoord, mitk::Point3D& fiberCoord ) +{ + mitk::Point3D tempPoint; + + // convert from fiber index coordinates to segmentation index coordinates + m_Segmentation->GetGeometry()->IndexToWorld( segCoord, tempPoint ); + m_FiberBundle->GetGeometry()->WorldToIndex( tempPoint, fiberCoord ); +} + +bool mitk::ConnectomicsNetworkCreator::IsNonWhiteMatterLabel( int labelInQuestion ) +{ + bool isWhite( false ); + + isWhite = ( + ( labelInQuestion == freesurfer_Left_Cerebral_White_Matter ) || + ( labelInQuestion == freesurfer_Left_Cerebellum_White_Matter ) || + ( labelInQuestion == freesurfer_Right_Cerebral_White_Matter ) || + ( labelInQuestion == freesurfer_Right_Cerebellum_White_Matter ) + ); + + return !isWhite; +} + +bool mitk::ConnectomicsNetworkCreator::IsBackgroundLabel( int labelInQuestion ) +{ + bool isBackground( false ); + + isBackground = ( labelInQuestion == 0 ); + + return isBackground; +} + +void mitk::ConnectomicsNetworkCreator::LinearExtensionUntilGreyMatter( + std::vector & indexVectorOfPointsToUse, + TractType::Pointer singleTract, + int & label, + mitk::Index3D & mitkIndex ) +{ + if( indexVectorOfPointsToUse.size() > singleTract->Size() ) + { + MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_MORE_POINTS_THAN_PRESENT; + return; + } + + if( indexVectorOfPointsToUse.size() < 2 ) + { + MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_LESS_THAN_2; + return; + } + + for( int index( 0 ); index < indexVectorOfPointsToUse.size(); index++ ) + { + if( indexVectorOfPointsToUse[ index ] > singleTract->Size() ) + { + MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_BEYOND_END; + return; + } + if( indexVectorOfPointsToUse[ index ] < 0 ) + { + MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_BEYOND_START; + return; + } + } + + mitk::Point3D startPoint, endPoint; + std::vector< double > differenceVector; + differenceVector.resize( singleTract->front().Size() ); + + { + // which points to use, currently only last two //TODO correct using all points + int endPointIndex = indexVectorOfPointsToUse.size() - 1; + int startPointIndex = indexVectorOfPointsToUse.size() - 2; + + // convert to segmentation coords + mitk::Point3D startFiber, endFiber; + for( int index = 0; index < singleTract->front().Size(); index++ ) + { + endFiber.SetElement( index, singleTract->GetElement( indexVectorOfPointsToUse[ endPointIndex ] ).GetElement( index ) ); + startFiber.SetElement( index, singleTract->GetElement( indexVectorOfPointsToUse[ startPointIndex ] ).GetElement( index ) ); + } + + FiberToSegmentationCoords( endFiber, endPoint ); + FiberToSegmentationCoords( startFiber, startPoint ); + + // calculate straight line + + for( int index = 0; index < singleTract->front().Size(); index++ ) + { + differenceVector[ index ] = endPoint.GetElement( index ) - startPoint.GetElement( index ); + } + + // normalizing direction vector + + double length( 0.0 ); + double sum( 0.0 ); + + for( int index = 0; index < differenceVector.size() ; index++ ) + { + sum = sum + differenceVector[ index ] * differenceVector[ index ]; + } + + length = std::sqrt( sum ); + + for( int index = 0; index < differenceVector.size() ; index++ ) + { + differenceVector[ index ] = differenceVector[ index ] / length; + } + + // follow line until first non white matter label + mitk::Index3D tempIndex; + int tempLabel( label ); + + bool keepOn( true ); + + for( int parameter( 0 ) ; keepOn ; parameter++ ) + { + if( parameter > 1000 ) + { + MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_DID_NOT_FIND_WHITE; + break; + } + + for( int index( 0 ); index < 3; index++ ) + { + tempIndex.SetElement( index, endPoint.GetElement( index ) + parameter * differenceVector[ index ] ); + } + + tempLabel = m_Segmentation->GetPixelValueByIndex( tempIndex ); + + if( IsNonWhiteMatterLabel( tempLabel ) ) + { + if( tempLabel < 1 ) + { + keepOn = false; + MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_NOT_EXTEND_TO_WHITE; + } + else + { + label = tempLabel; + mitkIndex = tempIndex; + keepOn = false; + } + } + } + + } + +} + +void mitk::ConnectomicsNetworkCreator::RetractionUntilBrainMatter( bool retractFront, TractType::Pointer singleTract, + int & label, mitk::Index3D & mitkIndex ) +{ + int retractionStartIndex( singleTract->Size() - 1 ); + int retractionStepIndexSize( -1 ); + int retractionTerminationIndex( 0 ); + + if( retractFront ) + { + retractionStartIndex = 0; + retractionStepIndexSize = 1; + retractionTerminationIndex = singleTract->Size() - 1; + } + + int currentRetractionIndex = retractionStartIndex; + + bool keepRetracting( true ); + + mitk::Point3D currentPoint, nextPoint; + std::vector< double > differenceVector; + differenceVector.resize( singleTract->front().Size() ); + + while( keepRetracting && ( currentRetractionIndex != retractionTerminationIndex ) ) + { + // convert to segmentation coords + mitk::Point3D currentPointFiberCoord, nextPointFiberCoord; + for( int index = 0; index < singleTract->front().Size(); index++ ) + { + currentPointFiberCoord.SetElement( index, singleTract->GetElement( currentRetractionIndex ).GetElement( index ) ); + nextPointFiberCoord.SetElement( index, singleTract->GetElement( currentRetractionIndex + retractionStepIndexSize ).GetElement( index ) ); + } + + FiberToSegmentationCoords( currentPointFiberCoord, currentPoint ); + FiberToSegmentationCoords( nextPointFiberCoord, nextPoint ); + + // calculate straight line + + for( int index = 0; index < singleTract->front().Size(); index++ ) + { + differenceVector[ index ] = nextPoint.GetElement( index ) - currentPoint.GetElement( index ); + } + + // calculate length of direction vector + + double length( 0.0 ); + double sum( 0.0 ); + + for( int index = 0; index < differenceVector.size() ; index++ ) + { + sum = sum + differenceVector[ index ] * differenceVector[ index ]; + } + + length = std::sqrt( sum ); + + // retract + mitk::Index3D tempIndex; + int tempLabel( label ); + + for( int parameter( 0 ) ; parameter < length ; parameter++ ) + { + + for( int index( 0 ); index < 3; index++ ) + { + tempIndex.SetElement( index, + currentPoint.GetElement( index ) + ( 1.0 + parameter ) / ( 1.0 + length ) * differenceVector[ index ] ); + } + + tempLabel = m_Segmentation->GetPixelValueByIndex( tempIndex ); + + if( !IsBackgroundLabel( tempLabel ) ) + { + label = tempLabel; + mitkIndex = tempIndex; + return; + } + // hit next point without finding brain matter + currentRetractionIndex = currentRetractionIndex + retractionStepIndexSize; + if( ( currentRetractionIndex < 1 ) || ( currentRetractionIndex > ( singleTract->Size() - 2 ) ) ) + { + keepRetracting = false; + } + } + } +} diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsNetworkCreator.h b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsNetworkCreator.h new file mode 100644 index 0000000000..e3112ae719 --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsNetworkCreator.h @@ -0,0 +1,192 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef mitkConnectomicsNetworkCreator_h +#define mitkConnectomicsNetworkCreator_h + +#include +#include +#include + +#include "mitkCommon.h" +#include "mitkImage.h" + +#include "mitkFiberBundleX.h" +#include "mitkConnectomicsNetwork.h" + +#include "MitkDiffusionImagingExports.h" + +namespace mitk +{ + + class MitkDiffusionImaging_EXPORT ConnectomicsNetworkCreator : public itk::Object + { + public: + + /** Enum for different ways to create the mapping from fibers to network */ + + enum MappingStrategy + { + EndElementPosition, + PrecomputeAndDistance, + JustEndPointVerticesNoLabel, + EndElementPositionAvoidingWhiteMatter + }; + + /** Standard class typedefs. */ + /** Method for creation through the object factory. */ + + mitkClassMacro(ConnectomicsNetworkCreator, itk::Object); + itkNewMacro(Self); + + /** Types for the standardized Tract **/ + typedef itk::Point PointType; + typedef itk::VectorContainer TractType; + typedef itk::VectorContainer< unsigned int, TractType::Pointer > TractContainerType; //init via smartpointer + + + /** Types for Network **/ + typedef mitk::ConnectomicsNetwork::VertexDescriptorType VertexType; + typedef mitk::ConnectomicsNetwork::EdgeDescriptorType EdgeType; + typedef mitk::ConnectomicsNetwork::NetworkNode NetworkNode; + typedef std::pair< VertexType, VertexType > ConnectionType; + + /** Types for labels **/ + typedef int ImageLabelType; + typedef std::pair< ImageLabelType, ImageLabelType > ImageLabelPairType; + + + + + void CreateNetworkFromFibersAndSegmentation(); + void SetFiberBundle(mitk::FiberBundleX::Pointer fiberBundle); + void SetSegmentation(mitk::Image::Pointer segmentation); + + mitk::ConnectomicsNetwork::Pointer GetNetwork(); + + protected: + + //////////////////// Functions /////////////////////// + ConnectomicsNetworkCreator(); + ConnectomicsNetworkCreator( mitk::Image::Pointer segmentation, mitk::FiberBundleX::Pointer fiberBundle ); + ~ConnectomicsNetworkCreator(); + + /** Add a connection to the network */ + void AddConnectionToNetwork(ConnectionType newConnection); + + /** Determine if a label is already identified with a vertex, otherwise create a new one */ + VertexType ReturnAssociatedVertexForLabel( ImageLabelType label ); + + /** Return the vertexes associated with a pair of labels */ + ConnectionType ReturnAssociatedVertexPairForLabelPair( ImageLabelPairType labelpair ); + + /** Return the pair of labels which identify the areas connected by a single fiber */ + ImageLabelPairType ReturnLabelForFiberTract( TractType::Pointer singleTract, MappingStrategy strategy ); + + /** Assign the additional information which should be part of the vertex */ + void SupplyVertexWithInformation( ImageLabelType& label, VertexType& vertex ); + + /** Create a string from the label */ + std::string LabelToString( ImageLabelType& label ); + + /** Check whether the label in question belongs to white matter according to the freesurfer table */ + bool IsNonWhiteMatterLabel( int labelInQuestion ); + + /** Check whether the label in question belongs to background according to the freesurfer table */ + bool IsBackgroundLabel( int labelInQuestion ); + + /** Extend a straight line through the given points and look for the first non white matter label + + It will try extend in the direction of the points in the vector so a vector {B,C} will result in + extending from C in the direction C-B */ + void LinearExtensionUntilGreyMatter( std::vector & indexVectorOfPointsToUse, TractType::Pointer singleTract, + int & label, mitk::Index3D & mitkIndex ); + + /** Retract fiber until the first brain matter label is hit + + The bool parameter controls whether the front or the end is retracted */ + void RetractionUntilBrainMatter( bool retractFront, TractType::Pointer singleTract, + int & label, mitk::Index3D & mitkIndex ); + + /** Convert point to itk point */ + itk::Point GetItkPoint(double point[3]); + + ///////// Mapping strategies ////////// + + /** Use the position of the end and starting element only to map to labels + + Map a fiber to a vertex by taking the value of the parcellation image at the same world coordinates as the last + and first element of the tract.*/ + ImageLabelPairType EndElementPositionLabel( TractType::Pointer singleTract ); + + /** Map by distance between elements and vertices depending on their volume + + First go through the parcellation and compute the coordinates of the future vertices. Assign a radius according on their volume. + Then map an edge to a label by considering the nearest vertices and comparing the distance to them to their radii. */ + ImageLabelPairType PrecomputeVertexLocationsBySegmentation( TractType::Pointer singleTract ); + + /** Use the position of the end and starting element only to map to labels + + Just take first and last position, no labelling, nothing */ + ImageLabelPairType JustEndPointVerticesNoLabelTest( TractType::Pointer singleTract ); + + /** Use the position of the end and starting element unless it is in white matter, then search for nearby parcellation to map to labels + + Map a fiber to a vertex by taking the value of the parcellation image at the same world coordinates as the last + and first element of the tract. If this happens to be white matter, then try to extend the fiber in a line and + take the first non-white matter parcel, that is intersected. */ + ImageLabelPairType EndElementPositionLabelAvoidingWhiteMatter( TractType::Pointer singleTract ); + + ///////// Conversions ////////// + /** Convert fiber index to segmentation index coordinates */ + void FiberToSegmentationCoords( mitk::Point3D& fiberCoord, mitk::Point3D& segCoord ); + /** Convert segmentation index to fiber index coordinates */ + void SegmentationToFiberCoords( mitk::Point3D& segCoord, mitk::Point3D& fiberCoord ); + + /////////////////////// Variables //////////////////////// + mitk::FiberBundleX::Pointer m_FiberBundle; + mitk::Image::Pointer m_Segmentation; + + // the graph itself + mitk::ConnectomicsNetwork::Pointer m_ConNetwork; + + // the id counter + int idCounter; + + // the map mapping labels to vertices + std::map< ImageLabelType, VertexType > m_LabelToVertexMap; + + // mapping labels to additional information + std::map< ImageLabelType, NetworkNode > m_LabelToNodePropertyMap; + + // toggles whether edges between a node and itself can exist + bool allowLoops; + + //////////////////////// IDs //////////////////////////// + + // These IDs are the freesurfer ids used in parcellation + + static const int freesurfer_Left_Cerebral_White_Matter = 2; + static const int freesurfer_Left_Cerebellum_White_Matter = 7; + static const int freesurfer_Right_Cerebral_White_Matter = 41; + static const int freesurfer_Right_Cerebellum_White_Matter = 46; + + }; + +}// end namespace mitk + +#endif // _mitkConnectomicsNetworkCreator_H_INCLUDED \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsShortestPathHistogram.cpp b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsShortestPathHistogram.cpp new file mode 100644 index 0000000000..3c34278bef --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsShortestPathHistogram.cpp @@ -0,0 +1,186 @@ + +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Module: $RCSfile$ +Language: C++ +Date: $Date$ +Version: $Revision: 11989 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include + +#include + +#include "mitkConnectomicsConstantsManager.h" + +mitk::ConnectomicsShortestPathHistogram::ConnectomicsShortestPathHistogram() +: m_Mode( UnweightedUndirectedMode ) +, m_EverythingConnected( true ) +{ + m_Subject = "Shortest path"; +} + +mitk::ConnectomicsShortestPathHistogram::~ConnectomicsShortestPathHistogram() +{ +} + +void mitk::ConnectomicsShortestPathHistogram::SetShortestPathCalculationMode( const mitk::ConnectomicsShortestPathHistogram::ShortestPathCalculationMode & mode) +{ + m_Mode = mode; +} + +mitk::ConnectomicsShortestPathHistogram::ShortestPathCalculationMode mitk::ConnectomicsShortestPathHistogram::GetShortestPathCalculationMode() +{ + return m_Mode; +} + +void mitk::ConnectomicsShortestPathHistogram::ComputeFromConnectomicsNetwork( ConnectomicsNetwork* source ) +{ + + NetworkType* boostGraph = source->GetBoostGraph(); + + switch( m_Mode ) + { + case UnweightedUndirectedMode: + { + CalculateUnweightedUndirectedShortestPaths( boostGraph ); + break; + } + case WeightedUndirectedMode: + { + CalculateWeightedUndirectedShortestPaths( boostGraph ); + break; + } + } + + ConvertDistanceMapToHistogram(); +} + +void mitk::ConnectomicsShortestPathHistogram::CalculateUnweightedUndirectedShortestPaths( NetworkType* boostGraph ) +{ + std::vector< DescriptorType > predecessorMap( boost::num_vertices( *boostGraph ) ); + int numberOfNodes( boost::num_vertices( *boostGraph ) ); + + m_DistanceMatrix.resize( numberOfNodes ); + for( int index(0); index < m_DistanceMatrix.size(); index++ ) + { + m_DistanceMatrix[ index ].resize( numberOfNodes ); + } + + IteratorType iterator, end; + boost::tie(iterator, end) = boost::vertices( *boostGraph ); + + for ( int index(0) ; iterator != end; ++iterator, index++) + { + boost::dijkstra_shortest_paths(*boostGraph, *iterator, boost::predecessor_map(&predecessorMap[ 0 ]).distance_map(&m_DistanceMatrix[ index ][ 0 ]).weight_map( boost::get( &mitk::ConnectomicsNetwork::NetworkEdge::edge_weight ,*boostGraph ) ) ) ; + } +} + +void mitk::ConnectomicsShortestPathHistogram::CalculateWeightedUndirectedShortestPaths( NetworkType* boostGraph ) +{ + MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_UNIMPLEMENTED_FEATURE; +} + +void mitk::ConnectomicsShortestPathHistogram::ConvertDistanceMapToHistogram() +{ + // get the longest path between any two nodes in the network + // we assume that no nodes are farther apart than there are nodes, + // this is to filter unconnected nodes + int longestPath( 0 ); + int numberOfNodes( m_DistanceMatrix.size() ); + m_EverythingConnected = true; + + for( int index(0); index < m_DistanceMatrix.size(); index++ ) + { + for( int innerIndex(0); innerIndex < m_DistanceMatrix[ index ].size(); innerIndex++ ) + { + if( m_DistanceMatrix[ index ][ innerIndex ] > longestPath ) + { + if( m_DistanceMatrix[ index ][ innerIndex ] < numberOfNodes ) + { + longestPath = m_DistanceMatrix[ index ][ innerIndex ]; + } + else + { + // these nodes are not connected + m_EverythingConnected = false; + } + } + } + } + + m_HistogramVector.resize( longestPath + 1 ); + + for( int index(0); index < m_DistanceMatrix.size(); index++ ) + { + for( int innerIndex(0); innerIndex < m_DistanceMatrix[ index ].size(); innerIndex++ ) + { + if( m_DistanceMatrix[ index ][ innerIndex ] < numberOfNodes ) + { + m_HistogramVector[ m_DistanceMatrix[ index ][ innerIndex ] ]++; + } + } + } + + // correct for every path being counted twice + + for( int index(1); index < m_HistogramVector.size(); index++ ) + { + m_HistogramVector[ index ] = m_HistogramVector[ index ] / 2; + } + + // correct for every node being distance zero to itself + if( m_HistogramVector[ 0 ] >= numberOfNodes ) + { + m_HistogramVector[ 0 ] = m_HistogramVector[ 0 ] - numberOfNodes; + } + else + { + MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ZERO_DISTANCE_NODES; + } + + UpdateYMax(); + + this->m_Valid = true; +} + +double mitk::ConnectomicsShortestPathHistogram::GetEfficiency() +{ + if( !this->m_Valid ) + { + MBI_INFO << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_CAN_NOT_COMPUTE_EFFICIENCY << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_NETWORK_NOT_VALID; + return 0.0; + } + + if( !m_EverythingConnected ) + { // efficiency of disconnected graphs is 0 + MBI_INFO << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_NETWORK_DISCONNECTED; + return 0.0; + } + + double efficiency( 0.0 ); + + double overallDistance( 0.0 ); + double numberOfPairs( 0.0 ); + // add up all distances + for( int index(0); index < m_HistogramVector.size(); index++ ) + { + overallDistance = overallDistance + m_HistogramVector[ index ] * index; + numberOfPairs = numberOfPairs + m_HistogramVector[ index ]; + } + + // efficiency = 1 / averageDistance = 1 / ( overallDistance / numberofPairs ) + efficiency = numberOfPairs / overallDistance; + + return efficiency; +} diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsShortestPathHistogram.h b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsShortestPathHistogram.h new file mode 100644 index 0000000000..90059a5ea3 --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsShortestPathHistogram.h @@ -0,0 +1,88 @@ + +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Module: $RCSfile$ +Language: C++ +Date: $Date$ +Version: $Revision: 11989 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#ifndef _MITK_ConnectomicsShortestPathHistogram_H +#define _MITK_ConnectomicsShortestPathHistogram_H + +#include + +#include "MitkDiffusionImagingExports.h" + +namespace mitk { + + /** + * \brief A class to calculate and store the shortest path between each pair of nodes */ + class MitkDiffusionImaging_EXPORT ConnectomicsShortestPathHistogram : public mitk::ConnectomicsHistogramBase + { + + public: + + /** Enum for different ways to calculate shortest paths */ + enum ShortestPathCalculationMode + { + UnweightedUndirectedMode, + WeightedUndirectedMode + }; + + ConnectomicsShortestPathHistogram(); + virtual ~ConnectomicsShortestPathHistogram(); + + /** Set the calucaltion mode */ + void SetShortestPathCalculationMode( const ShortestPathCalculationMode & ); + + /** Get the calculation mode */ + ShortestPathCalculationMode GetShortestPathCalculationMode(); + + /** Get efficiency */ + double GetEfficiency(); + + + protected: + + /* Typedefs */ + typedef mitk::ConnectomicsNetwork::NetworkType NetworkType; + typedef boost::graph_traits< NetworkType >::vertex_descriptor DescriptorType; + typedef boost::graph_traits< NetworkType >::vertex_iterator IteratorType; + + /** @brief Creates a new histogram from the network source. */ + virtual void ComputeFromConnectomicsNetwork( ConnectomicsNetwork* source ); + + /** Calculate shortest paths ignoring the weight of the edges */ + void CalculateUnweightedUndirectedShortestPaths( NetworkType* boostGraph ); + + /** Calculate shortest paths taking into consideration the weight of the edges */ + void CalculateWeightedUndirectedShortestPaths( NetworkType* boostGraph ); + + /** Converts the distance map to a histogram */ + void ConvertDistanceMapToHistogram(); + + /** Stores which mode has been selected for shortest path calculation */ + ShortestPathCalculationMode m_Mode; + + /** Stores the shortest paths between the nodes */ + std::vector< std::vector< int > > m_DistanceMatrix; + + /** Stores, whether the graph has disconnected components */ + bool m_EverythingConnected; + }; + +} + +#endif /* _MITK_ConnectomicsShortestPathHistogram_H */ \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionBase.cpp b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionBase.cpp new file mode 100644 index 0000000000..251007d975 --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionBase.cpp @@ -0,0 +1,26 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkConnectomicsSimulatedAnnealingCostFunctionBase.h" + +mitk::ConnectomicsSimulatedAnnealingCostFunctionBase::ConnectomicsSimulatedAnnealingCostFunctionBase() +{ +} + +mitk::ConnectomicsSimulatedAnnealingCostFunctionBase::~ConnectomicsSimulatedAnnealingCostFunctionBase() +{ +} diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionBase.h b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionBase.h new file mode 100644 index 0000000000..f44c49e0de --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionBase.h @@ -0,0 +1,55 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef mitkConnectomicsSimulatedAnnealingCostFunctionBase_h +#define mitkConnectomicsSimulatedAnnealingCostFunctionBase_h + +#include +#include +#include + +#include "mitkCommon.h" + +#include "MitkDiffusionImagingExports.h" + +namespace mitk +{ + /** + * \brief A generic base class for cost functions for use in simulated annealing */ + class MitkDiffusionImaging_EXPORT ConnectomicsSimulatedAnnealingCostFunctionBase : public itk::Object + { + public: + + /** Standard class typedefs. */ + /** Method for creation through the object factory. */ + + mitkClassMacro(ConnectomicsSimulatedAnnealingCostFunctionBase, itk::Object); + itkNewMacro(Self); + + + + protected: + + //////////////////// Functions /////////////////////// + ConnectomicsSimulatedAnnealingCostFunctionBase(); + ~ConnectomicsSimulatedAnnealingCostFunctionBase(); + + }; + +}// end namespace mitk + +#endif // mitkConnectomicsSimulatedAnnealingCostFunctionBase_h \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.cpp b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.cpp new file mode 100644 index 0000000000..cd480df657 --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.cpp @@ -0,0 +1,126 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h" + +mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::ConnectomicsSimulatedAnnealingCostFunctionModularity() +{ +} + +mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::~ConnectomicsSimulatedAnnealingCostFunctionModularity() +{ +} + +double mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::Evaluate( mitk::ConnectomicsNetwork::Pointer network, ToModuleMapType* vertexToModuleMap ) const +{ + double cost( 0.0 ); + cost = 100.0 * ( 1.0 - CalculateModularity( network, vertexToModuleMap ) ); + return cost; +} + +double mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::CalculateModularity( mitk::ConnectomicsNetwork::Pointer network, ToModuleMapType* vertexToModuleMap ) const +{ + double modularity( 0.0 ); + int numberOfModules = getNumberOfModules( vertexToModuleMap ); + + if( network->GetNumberOfVertices() != vertexToModuleMap->size() ) + { + MBI_ERROR << "Number of vertices and vertex to module map size do not match!"; + return modularity; + } + + int numberOfLinksInNetwork( 0 ); + std::vector< int > numberOfLinksInModule, sumOfDegreesInModule; + numberOfLinksInModule.resize( numberOfModules, 0 ); + sumOfDegreesInModule.resize( numberOfModules, 0 ); + // get vector of all vertex descriptors in the network + + const std::vector< VertexDescriptorType > allNodesVector + = network->GetVectorOfAllVertexDescriptors(); + + for( int nodeNumber( 0 ); nodeNumber < allNodesVector.size() ; nodeNumber++) + { + int correspondingModule = vertexToModuleMap->find( allNodesVector[ nodeNumber ] )->second; + const std::vector< VertexDescriptorType > adjacentNodexVector + = network->GetVectorOfAdjacentNodes( allNodesVector[ nodeNumber ] ); + numberOfLinksInNetwork += adjacentNodexVector.size(); + sumOfDegreesInModule[ correspondingModule ] += adjacentNodexVector.size(); + + for( int adjacentNodeNumber( 0 ); adjacentNodeNumber < adjacentNodexVector.size() ; adjacentNodeNumber++) + { + if( correspondingModule == vertexToModuleMap->find( adjacentNodexVector[ adjacentNodeNumber ] )->second ) + { + numberOfLinksInModule[ correspondingModule ]++; + } + } + } + + // the numbers for links have to be halved, as each edge was counted twice + numberOfLinksInNetwork = numberOfLinksInNetwork / 2; + + // if the network contains no links return 0 + if( numberOfLinksInNetwork < 1) + { + return 0; + } + + for( int index( 0 ); index < numberOfModules ; index++) + { + numberOfLinksInModule[ index ] = numberOfLinksInModule[ index ] / 2; + } + + //Calculate modularity M: + //M = sum_{s=1}^{N_{M}} [ (l_{s} / L) - (d_{s} / ( 2L ))^2 ] + //where N_{M} is the number of modules + //L is the number of links in the network + //l_{s} is the number of links between nodes in the module + //s is the module + //d_{s} is the sum of degrees of the nodes in the module + //( taken from Guimera, R. AND Amaral, L. A. N. + // Cartography of complex networks: modules and universal roles + // Journal of Statistical Mechanics: Theory and Experiment, 2005, 2005, P02001 ) + + for( int moduleID( 0 ); moduleID < numberOfModules; moduleID++ ) + { + modularity += (((double) numberOfLinksInModule[ moduleID ]) / ((double) numberOfLinksInNetwork)) - + ( + (((double) sumOfDegreesInModule[ moduleID ]) / ((double) 2 * numberOfLinksInNetwork) ) * + (((double) sumOfDegreesInModule[ moduleID ]) / ((double) 2 * numberOfLinksInNetwork) ) + ); + } + + return modularity; +} + +int mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::getNumberOfModules( + ToModuleMapType *vertexToModuleMap ) const +{ + int maxModule( 0 ); + ToModuleMapType::iterator iter = vertexToModuleMap->begin(); + ToModuleMapType::iterator end = vertexToModuleMap->end(); + while( iter != end ) + { + if( iter->second > maxModule ) + { + maxModule = iter->second; + } + + iter++; + } + + return maxModule + 1; +} \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h new file mode 100644 index 0000000000..b4bb01631a --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h @@ -0,0 +1,63 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef mitkConnectomicsSimulatedAnnealingCostFunctionModularity_h +#define mitkConnectomicsSimulatedAnnealingCostFunctionModularity_h + +#include "mitkConnectomicsSimulatedAnnealingCostFunctionBase.h" + +#include "mitkConnectomicsNetwork.h" + +namespace mitk +{ + /** + * \brief A cost function using the modularity of the network */ + class MitkDiffusionImaging_EXPORT ConnectomicsSimulatedAnnealingCostFunctionModularity : public mitk::ConnectomicsSimulatedAnnealingCostFunctionBase + { + public: + + typedef mitk::ConnectomicsNetwork::VertexDescriptorType VertexDescriptorType; + typedef std::map< VertexDescriptorType, int > ToModuleMapType; + typedef std::map< VertexDescriptorType, VertexDescriptorType > VertexToVertexMapType; + + /** Standard class typedefs. */ + /** Method for creation through the object factory. */ + + mitkClassMacro(ConnectomicsSimulatedAnnealingCostFunctionModularity, itk::Object); + itkNewMacro(Self); + + // Evaluate the network according to the set cost function + double Evaluate( mitk::ConnectomicsNetwork::Pointer network, ToModuleMapType *vertexToModuleMap ) const; + + // Will calculate and return the modularity of the network + double CalculateModularity( mitk::ConnectomicsNetwork::Pointer network, ToModuleMapType *vertexToModuleMap ) const; + + + protected: + + // returns the number of modules + int getNumberOfModules( ToModuleMapType *vertexToModuleMap ) const; + + //////////////////// Functions /////////////////////// + ConnectomicsSimulatedAnnealingCostFunctionModularity(); + ~ConnectomicsSimulatedAnnealingCostFunctionModularity(); + + }; + +}// end namespace mitk + +#endif // mitkConnectomicsSimulatedAnnealingCostFunctionModularity_h \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingManager.cpp b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingManager.cpp new file mode 100644 index 0000000000..79aa823024 --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingManager.cpp @@ -0,0 +1,181 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkConnectomicsSimulatedAnnealingManager.h" + +//for random number generation +#include "vxl/core/vnl/vnl_random.h" +#include "vxl/core/vnl/vnl_math.h" + +mitk::ConnectomicsSimulatedAnnealingManager::ConnectomicsSimulatedAnnealingManager() +: m_Permutation( 0 ) +{ +} + +mitk::ConnectomicsSimulatedAnnealingManager::~ConnectomicsSimulatedAnnealingManager() +{ +} + + +bool mitk::ConnectomicsSimulatedAnnealingManager::AcceptChange( double costBefore, double costAfter, double temperature ) +{ + if( costAfter <= costBefore ) + {// if cost is lower after + return true; + } + + //the random number generators + vnl_random rng( (unsigned int) rand() ); + + //randomly generate threshold + const double threshold = rng.drand64( 0.0 , 1.0); + + //the likelihood of acceptance + double likelihood = std::exp( - ( costAfter - costBefore ) / temperature ); + + if( threshold < likelihood ) + { + return true; + } + + return false; +} + +void mitk::ConnectomicsSimulatedAnnealingManager::SetPermutation( mitk::ConnectomicsSimulatedAnnealingPermutationBase::Pointer permutation ) +{ + m_Permutation = permutation; +} + +void mitk::ConnectomicsSimulatedAnnealingManager::RunSimulatedAnnealing( + double temperature, + double stepSize + ) +{ + if( m_Permutation.IsNull() ) + { + MBI_ERROR << "Trying to run simulated annealing on empty permutation."; + return; + } + + if( !m_Permutation->HasCostFunction() ) + { + MBI_ERROR << "Trying to run simulated annealing on empty cost function."; + return; + } + + // Initialize the associated permutation + m_Permutation->Initialize(); + + + for( double currentTemperature( temperature ); + currentTemperature > 0.00001; + currentTemperature = currentTemperature / stepSize ) + { + // Run Permutations at the current temperature + m_Permutation->Permutate( currentTemperature ); + + } + + // Clean up result + m_Permutation->CleanUp(); + +} + + +//void mitk::ConnectomicsSimulatedAnnealingManager::Testing( mitk::ConnectomicsNetwork::Pointer network ) +//{ +// // precursor to an actual test, this will assign a to module map which is only valid for a +// // specific network and whose modularity is known +// ToModuleMapType threeModuleSolution; +// std::vector< VertexDescriptorType > vertexVector = network->GetVectorOfAllVertexDescriptors(); +// +// threeModuleSolution.insert( std::pair( vertexVector[ 0 ], 0 ) ); +// threeModuleSolution.insert( std::pair( vertexVector[ 1 ], 0 ) ); +// threeModuleSolution.insert( std::pair( vertexVector[ 2 ], 0 ) ); +// threeModuleSolution.insert( std::pair( vertexVector[ 3 ], 0 ) ); +// threeModuleSolution.insert( std::pair( vertexVector[ 4 ], 0 ) ); +// threeModuleSolution.insert( std::pair( vertexVector[ 5 ], 1 ) ); +// threeModuleSolution.insert( std::pair( vertexVector[ 6 ], 1 ) ); +// threeModuleSolution.insert( std::pair( vertexVector[ 7 ], 1 ) ); +// threeModuleSolution.insert( std::pair( vertexVector[ 8 ], 1 ) ); +// threeModuleSolution.insert( std::pair( vertexVector[ 9 ], 2 ) ); +// threeModuleSolution.insert( std::pair( vertexVector[ 10 ], 2 ) ); +// threeModuleSolution.insert( std::pair( vertexVector[ 11 ], 2 ) ); +// +// std::cout << "Modularity is " << CalculateModularity( network, &threeModuleSolution ) << " and should be " << 0.4753 << std::endl; +// +// std::cout << " Module 0 contains " << getNumberOfVerticesInModule( &threeModuleSolution, 0 ) << " nodes, should be 5.\n"; +// std::cout << " Module 1 contains " << getNumberOfVerticesInModule( &threeModuleSolution, 1 ) << " nodes, should be 4.\n"; +// std::cout << " Module 2 contains " << getNumberOfVerticesInModule( &threeModuleSolution, 2 ) << " nodes, should be 3.\n"; +// +// ToModuleMapType oneModuleSolution; +// oneModuleSolution.insert( std::pair( vertexVector[ 0 ], 0 ) ); +// oneModuleSolution.insert( std::pair( vertexVector[ 1 ], 0 ) ); +// oneModuleSolution.insert( std::pair( vertexVector[ 2 ], 0 ) ); +// oneModuleSolution.insert( std::pair( vertexVector[ 3 ], 0 ) ); +// oneModuleSolution.insert( std::pair( vertexVector[ 4 ], 0 ) ); +// oneModuleSolution.insert( std::pair( vertexVector[ 5 ], 0 ) ); +// oneModuleSolution.insert( std::pair( vertexVector[ 6 ], 0 ) ); +// oneModuleSolution.insert( std::pair( vertexVector[ 7 ], 0 ) ); +// oneModuleSolution.insert( std::pair( vertexVector[ 8 ], 0 ) ); +// oneModuleSolution.insert( std::pair( vertexVector[ 9 ], 0 ) ); +// oneModuleSolution.insert( std::pair( vertexVector[ 10 ], 0 ) ); +// oneModuleSolution.insert( std::pair( vertexVector[ 11 ], 0 ) ); +// +// std::cout << "Modularity is " << CalculateModularity( network, &oneModuleSolution ) << " and should be " << 0.0 << std::endl; +// +// std::cout << " Module 0 contains " << getNumberOfVerticesInModule( &oneModuleSolution, 0 ) << " nodes, should be 12.\n"; +// +// ToModuleMapType badTwoModuleSolution; +// badTwoModuleSolution.insert( std::pair( vertexVector[ 0 ], 0 ) ); +// badTwoModuleSolution.insert( std::pair( vertexVector[ 1 ], 0 ) ); +// badTwoModuleSolution.insert( std::pair( vertexVector[ 2 ], 0 ) ); +// badTwoModuleSolution.insert( std::pair( vertexVector[ 3 ], 0 ) ); +// badTwoModuleSolution.insert( std::pair( vertexVector[ 4 ], 0 ) ); +// badTwoModuleSolution.insert( std::pair( vertexVector[ 5 ], 1 ) ); +// badTwoModuleSolution.insert( std::pair( vertexVector[ 6 ], 1 ) ); +// badTwoModuleSolution.insert( std::pair( vertexVector[ 7 ], 1 ) ); +// badTwoModuleSolution.insert( std::pair( vertexVector[ 8 ], 0 ) ); +// badTwoModuleSolution.insert( std::pair( vertexVector[ 9 ], 1 ) ); +// badTwoModuleSolution.insert( std::pair( vertexVector[ 10 ], 1 ) ); +// badTwoModuleSolution.insert( std::pair( vertexVector[ 11 ], 0 ) ); +// +// std::cout << "Modularity is " << CalculateModularity( network, &badTwoModuleSolution ) << " and should be " << 0.10 << std::endl; +// std::cout << " Module 0 contains " << getNumberOfVerticesInModule( &badTwoModuleSolution, 0 ) << " nodes, should be 7.\n"; +// std::cout << " Module 1 contains " << getNumberOfVerticesInModule( &badTwoModuleSolution, 1 ) << " nodes, should be 5.\n"; +// +// ToModuleMapType noInternalLinksThreeModuleSolution; +// noInternalLinksThreeModuleSolution.insert( std::pair( vertexVector[ 0 ], 0 ) ); +// noInternalLinksThreeModuleSolution.insert( std::pair( vertexVector[ 1 ], 2 ) ); +// noInternalLinksThreeModuleSolution.insert( std::pair( vertexVector[ 2 ], 1 ) ); +// noInternalLinksThreeModuleSolution.insert( std::pair( vertexVector[ 3 ], 0 ) ); +// noInternalLinksThreeModuleSolution.insert( std::pair( vertexVector[ 4 ], 1 ) ); +// noInternalLinksThreeModuleSolution.insert( std::pair( vertexVector[ 5 ], 2 ) ); +// noInternalLinksThreeModuleSolution.insert( std::pair( vertexVector[ 6 ], 0 ) ); +// noInternalLinksThreeModuleSolution.insert( std::pair( vertexVector[ 7 ], 0 ) ); +// noInternalLinksThreeModuleSolution.insert( std::pair( vertexVector[ 8 ], 1 ) ); +// noInternalLinksThreeModuleSolution.insert( std::pair( vertexVector[ 9 ], 2 ) ); +// noInternalLinksThreeModuleSolution.insert( std::pair( vertexVector[ 10 ], 1 ) ); +// noInternalLinksThreeModuleSolution.insert( std::pair( vertexVector[ 11 ], 0 ) ); +// +// std::cout << "Modularity is " << CalculateModularity( network, &noInternalLinksThreeModuleSolution ) << " and should be " << -0.34 << std::endl; +// +// std::cout << " Module 0 contains " << getNumberOfVerticesInModule( &noInternalLinksThreeModuleSolution, 0 ) << " nodes, should be 5.\n"; +// std::cout << " Module 1 contains " << getNumberOfVerticesInModule( &noInternalLinksThreeModuleSolution, 1 ) << " nodes, should be 4.\n"; +// std::cout << " Module 2 contains " << getNumberOfVerticesInModule( &noInternalLinksThreeModuleSolution, 2 ) << " nodes, should be 3.\n"; +// +//} \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingManager.h b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingManager.h new file mode 100644 index 0000000000..a3964d0f4e --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingManager.h @@ -0,0 +1,70 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef mitkConnectomicsSimulatedAnnealingManager_h +#define mitkConnectomicsSimulatedAnnealingManager_h + +#include +#include +#include + +#include "mitkCommon.h" + +#include "MitkDiffusionImagingExports.h" + +#include "mitkConnectomicsSimulatedAnnealingPermutationBase.h" + +namespace mitk +{ + /** + * \brief A class allow generic simulated annealing by using classes derived from ConnectomicsSimulatedAnnealingPermutationBase */ + class MitkDiffusionImaging_EXPORT ConnectomicsSimulatedAnnealingManager : public itk::Object + { + public: + + /** Standard class typedefs. */ + /** Method for creation through the object factory. */ + + mitkClassMacro(ConnectomicsSimulatedAnnealingManager, itk::Object); + itkNewMacro(Self); + + // Decide whether to accept the change or not + bool AcceptChange( double costBefore, double costAfter, double temperature ); + + // Run the permutations at different temperatures, where t_n = t_n-1 / stepSize + void RunSimulatedAnnealing( double temperature, double stepSize ); + + // Set the permutation to be used + void SetPermutation( mitk::ConnectomicsSimulatedAnnealingPermutationBase::Pointer permutation ); + + //void Testing( mitk::ConnectomicsNetwork::Pointer network ); + + protected: + + //////////////////// Functions /////////////////////// + ConnectomicsSimulatedAnnealingManager(); + ~ConnectomicsSimulatedAnnealingManager(); + + /////////////////////// Variables //////////////////////// + // The permutation assigned to the simulated annealing manager + mitk::ConnectomicsSimulatedAnnealingPermutationBase::Pointer m_Permutation; + + }; + +}// end namespace mitk + +#endif // mitkConnectomicsSimulatedAnnealingManager_h \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationBase.cpp b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationBase.cpp new file mode 100644 index 0000000000..895c434309 --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationBase.cpp @@ -0,0 +1,45 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkConnectomicsSimulatedAnnealingPermutationBase.h" + +mitk::ConnectomicsSimulatedAnnealingPermutationBase::ConnectomicsSimulatedAnnealingPermutationBase() +: m_CostFunction( 0 ) +{ +} + +mitk::ConnectomicsSimulatedAnnealingPermutationBase::~ConnectomicsSimulatedAnnealingPermutationBase() +{ +} + +void mitk::ConnectomicsSimulatedAnnealingPermutationBase::SetCostFunction( + mitk::ConnectomicsSimulatedAnnealingCostFunctionBase::Pointer costFunction ) +{ + m_CostFunction = costFunction; +} + +bool mitk::ConnectomicsSimulatedAnnealingPermutationBase::HasCostFunction( ) +{ + bool hasCostFunction( false ); + + if( m_CostFunction.IsNotNull() ) + { + hasCostFunction = true; + } + + return hasCostFunction; +} diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationBase.h b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationBase.h new file mode 100644 index 0000000000..9b0906c12c --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationBase.h @@ -0,0 +1,75 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef mitkConnectomicsSimulatedAnnealingPermutationBase_h +#define mitkConnectomicsSimulatedAnnealingPermutationBase_h + +#include +#include +#include + +#include "mitkCommon.h" + +#include "MitkDiffusionImagingExports.h" + +#include "mitkConnectomicsSimulatedAnnealingCostFunctionBase.h" + +namespace mitk +{ + + /** + * \brief Base class of a permutation to be used in simulated annealing */ + class MitkDiffusionImaging_EXPORT ConnectomicsSimulatedAnnealingPermutationBase : public itk::Object + { + public: + + /** Standard class typedefs. */ + /** Method for creation through the object factory. */ + + mitkClassMacro(ConnectomicsSimulatedAnnealingPermutationBase, itk::Object); + itkNewMacro(Self); + + // Set the cost function + void SetCostFunction( mitk::ConnectomicsSimulatedAnnealingCostFunctionBase::Pointer costFunction ); + + // Returns true if a cost function is assigned + bool HasCostFunction( ); + + // Initialize the permutation + virtual void Initialize(){}; + + // Do a permutation for a specific temperature + virtual void Permutate( double temperature ){}; + + // Do clean up necessary after a permutation + virtual void CleanUp(){}; + + protected: + + //////////////////// Functions /////////////////////// + ConnectomicsSimulatedAnnealingPermutationBase(); + ~ConnectomicsSimulatedAnnealingPermutationBase(); + + /////////////////////// Variables //////////////////////// + // The cost function assigned to the permutation + mitk::ConnectomicsSimulatedAnnealingCostFunctionBase::Pointer m_CostFunction; + + }; + +}// end namespace mitk + +#endif // mitkConnectomicsSimulatedAnnealingPermutationBase_h \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationModularity.cpp b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationModularity.cpp new file mode 100644 index 0000000000..fcbdfe1797 --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationModularity.cpp @@ -0,0 +1,545 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkConnectomicsSimulatedAnnealingPermutationModularity.h" +#include "mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h" +#include "mitkConnectomicsSimulatedAnnealingManager.h" + +//for random number generation +#include "vxl/core/vnl/vnl_random.h" +#include "vxl/core/vnl/vnl_math.h" + +mitk::ConnectomicsSimulatedAnnealingPermutationModularity::ConnectomicsSimulatedAnnealingPermutationModularity() +{ +} + +mitk::ConnectomicsSimulatedAnnealingPermutationModularity::~ConnectomicsSimulatedAnnealingPermutationModularity() +{ +} + +void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::SetNetwork( + mitk::ConnectomicsNetwork::Pointer theNetwork ) +{ + m_Network = theNetwork; +} + +void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::Initialize() +{ + // create entry for every vertex + std::vector< VertexDescriptorType > vertexVector = m_Network->GetVectorOfAllVertexDescriptors(); + const int vectorSize = vertexVector.size(); + + for( int index( 0 ); index < vectorSize; index++) + { + m_BestSolution.insert( std::pair( vertexVector[ index ], 0 ) ); + } + + // initialize with random distribution of n modules + int n( 5 ); + randomlyAssignNodesToModules( &m_BestSolution, n ); + +} + +void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::Permutate( double temperature ) +{ + + ToModuleMapType currentSolution = m_BestSolution; + ToModuleMapType currentBestSolution = m_BestSolution; + + int factor = 1; + int numberOfVertices = m_BestSolution.size(); + int singleNodeMaxNumber = factor * numberOfVertices * numberOfVertices; + int moduleMaxNumber = factor * numberOfVertices; + double currentBestCost = Evaluate( ¤tBestSolution ); + + // do singleNodeMaxNumber node permutations and evaluate + for(int loop( 0 ); loop < singleNodeMaxNumber; loop++) + { + permutateMappingSingleNodeShift( ¤tSolution, m_Network ); + if( AcceptChange( currentBestCost, Evaluate( ¤tSolution ), temperature ) ) + { + currentBestSolution = currentSolution; + currentBestCost = Evaluate( ¤tBestSolution ); + } + } + + // do moduleMaxNumber module permutations + for(int loop( 0 ); loop < moduleMaxNumber; loop++) + { + permutateMappingModuleChange( ¤tSolution, temperature, m_Network ); + if( AcceptChange( currentBestCost, Evaluate( ¤tSolution ), temperature ) ) + { + currentBestSolution = currentSolution; + currentBestCost = Evaluate( ¤tBestSolution ); + } + } + + // store the best solution after the run + m_BestSolution = currentBestSolution; +} + +void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::CleanUp() +{ + // delete empty modules, if any + for( int loop( 0 ); loop < getNumberOfModules( &m_BestSolution ) ; loop++ ) + { + if( getNumberOfVerticesInModule( &m_BestSolution, loop ) < 1 ) + { + removeModule( &m_BestSolution, loop ); + } + } +} + +void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::permutateMappingSingleNodeShift( + ToModuleMapType *vertexToModuleMap, mitk::ConnectomicsNetwork::Pointer network ) +{ + + const int nodeCount = vertexToModuleMap->size(); + const int moduleCount = getNumberOfModules( vertexToModuleMap ); + + // the random number generators + vnl_random rng( (unsigned int) rand() ); + unsigned long randomNode = rng.lrand32( nodeCount - 1 ); + // move the node either to any existing module, or to its own + //unsigned long randomModule = rng.lrand32( moduleCount ); + unsigned long randomModule = rng.lrand32( moduleCount - 1 ); + + // do some sanity checks + + if ( nodeCount < 2 ) + { + // no sense in doing anything + return; + } + + const std::vector< VertexDescriptorType > allNodesVector + = network->GetVectorOfAllVertexDescriptors(); + + ToModuleMapType::iterator iter = vertexToModuleMap->find( allNodesVector[ randomNode ] ); + const int previousModuleNumber = iter->second; + + // if we move the node to its own module, do nothing + if( previousModuleNumber == randomModule ) + { + return; + } + + iter->second = randomModule; + + if( getNumberOfVerticesInModule( vertexToModuleMap, previousModuleNumber ) < 1 ) + { + removeModule( vertexToModuleMap, previousModuleNumber ); + } +} + +void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::permutateMappingModuleChange( + ToModuleMapType *vertexToModuleMap, double currentTemperature, mitk::ConnectomicsNetwork::Pointer network ) +{ + //the random number generators + vnl_random rng( (unsigned int) rand() ); + + //randomly generate threshold + const double threshold = rng.drand64( 0.0 , 1.0); + + //for deciding whether to join two modules or split one + double splitThreshold = 0.5; + + //stores whether to join or two split + bool joinModules( false ); + + //select random module + int numberOfModules = getNumberOfModules( vertexToModuleMap ); + unsigned long randomModuleA = rng.lrand32( numberOfModules - 1 ); + + //select the second module to join, if joining + unsigned long randomModuleB = rng.lrand32( numberOfModules - 1 ); + + if( ( threshold < splitThreshold ) && ( randomModuleA != randomModuleB ) ) + { + joinModules = true; + } + + if( joinModules ) + { + // this being an kommutative operation, we will always join B to A + joinTwoModules( vertexToModuleMap, randomModuleA, randomModuleB ); + //eliminate the empty module + removeModule( vertexToModuleMap, randomModuleB ); + + } + else + { + //split module + splitModule( vertexToModuleMap, currentTemperature, network, randomModuleA ); + } + + +} + +void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::joinTwoModules( + ToModuleMapType *vertexToModuleMap, int moduleA, int moduleB ) +{ + + ToModuleMapType::iterator iter = vertexToModuleMap->begin(); + ToModuleMapType::iterator end = vertexToModuleMap->end(); + + while( iter != end ) + { + // if vertex belongs to module B move it to A + if( iter->second == moduleB ) + { + iter->second = moduleA; + } + + iter++; + }// end while( iter != end ) +} + +void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::splitModule( + ToModuleMapType *vertexToModuleMap, double currentTemperature, mitk::ConnectomicsNetwork::Pointer network, int moduleToSplit ) +{ + + if( m_Depth == 0 ) + { + // do nothing + return; + } + + // if the module contains only one node, no more division is sensible + if( getNumberOfVerticesInModule( vertexToModuleMap, moduleToSplit ) < 2 ) + { + // do nothing + return; + } + + // create subgraph of the module, that is to be splitted + + mitk::ConnectomicsNetwork::Pointer subNetwork = mitk::ConnectomicsNetwork::New(); + VertexToVertexMapType graphToSubgraphVertexMap; + VertexToVertexMapType subgraphToGraphVertexMap; + + + extractModuleSubgraph( vertexToModuleMap, network, moduleToSplit, subNetwork, &graphToSubgraphVertexMap, &subgraphToGraphVertexMap ); + + + // The submap + ToModuleMapType vertexToModuleSubMap; + + // copy vertices + VertexToVertexMapType::iterator iter = graphToSubgraphVertexMap.begin(); + VertexToVertexMapType::iterator end = graphToSubgraphVertexMap.end(); + + // run simulated annealing on the subgraph to determine how the module should be split + if( m_Depth > 0 && m_StepSize > 0 ) + { + mitk::ConnectomicsSimulatedAnnealingManager::Pointer manager = mitk::ConnectomicsSimulatedAnnealingManager::New(); + mitk::ConnectomicsSimulatedAnnealingPermutationModularity::Pointer permutation = mitk::ConnectomicsSimulatedAnnealingPermutationModularity::New(); + mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::Pointer costFunction = mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::New(); + + permutation->SetCostFunction( costFunction.GetPointer() ); + permutation->SetNetwork( subNetwork ); + permutation->SetDepth( m_Depth - 1 ); + permutation->SetStepSize( m_StepSize * 2 ); + + manager->SetPermutation( permutation.GetPointer() ); + + manager->RunSimulatedAnnealing( currentTemperature, m_StepSize * 2 ); + + vertexToModuleSubMap = permutation->GetMapping(); + } + + // now carry the information over to the original map + std::vector< int > moduleTranslationVector; + moduleTranslationVector.resize( getNumberOfModules( &vertexToModuleSubMap ), 0 ); + int originalNumber = getNumberOfModules( vertexToModuleMap ); + + // the new parts are added at the end + for(int index( 0 ); index < moduleTranslationVector.size() ; index++) + { + moduleTranslationVector[ index ] = originalNumber + index; + } + + ToModuleMapType::iterator iter2 = vertexToModuleSubMap.begin(); + ToModuleMapType::iterator end2 = vertexToModuleSubMap.end(); + + while( iter2 != end2 ) + { + // translate vertex descriptor from subgraph to graph + VertexDescriptorType key = subgraphToGraphVertexMap.find( iter2->first )->second; + // translate module number from subgraph to graph + int value = moduleTranslationVector[ iter2->second ]; + // change the corresponding entry + vertexToModuleMap->find( key )->second = value; + + iter2++; + } + + // remove the now empty module, that was splitted + removeModule( vertexToModuleMap, moduleToSplit ); + +} + +void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::extractModuleSubgraph( + ToModuleMapType *vertexToModuleMap, + mitk::ConnectomicsNetwork::Pointer network, + int moduleToSplit, + mitk::ConnectomicsNetwork::Pointer subNetwork, + VertexToVertexMapType* graphToSubgraphVertexMap, + VertexToVertexMapType* subgraphToGraphVertexMap ) +{ + const std::vector< VertexDescriptorType > allNodesVector = network->GetVectorOfAllVertexDescriptors(); + + // add vertices to subgraph + for( int nodeNumber( 0 ); nodeNumber < allNodesVector.size() ; nodeNumber++) + { + int correspondingModule = vertexToModuleMap->find( allNodesVector[ nodeNumber ] )->second; + + if( moduleToSplit == vertexToModuleMap->find( allNodesVector[ nodeNumber ] )->second ) + { + int id = network->GetNode( allNodesVector[ nodeNumber ] ).id; + VertexDescriptorType newVertex = subNetwork->AddVertex( id ); + + graphToSubgraphVertexMap->insert( + std::pair( + allNodesVector[ nodeNumber ], newVertex + ) + ); + subgraphToGraphVertexMap->insert( + std::pair( + newVertex, allNodesVector[ nodeNumber ] + ) + ); + } + } + + // add edges to subgraph + VertexToVertexMapType::iterator iter = graphToSubgraphVertexMap->begin(); + VertexToVertexMapType::iterator end = graphToSubgraphVertexMap->end(); + + while( iter != end ) + { + const std::vector< VertexDescriptorType > adjacentNodexVector + = network->GetVectorOfAdjacentNodes( iter->first ); + + for( int adjacentNodeNumber( 0 ); adjacentNodeNumber < adjacentNodexVector.size() ; adjacentNodeNumber++) + { + // if the adjacent vertex is part of the subgraph, + // add edge, if it does not exist yet, else do nothing + + VertexDescriptorType adjacentVertex = adjacentNodexVector[ adjacentNodeNumber ]; + if( graphToSubgraphVertexMap->count( adjacentVertex ) > 0 ) + { + if( !subNetwork->EdgeExists( iter->second, graphToSubgraphVertexMap->find( adjacentVertex )->second ) ) + { //edge exists in parent network, but not yet in sub network + const VertexDescriptorType vertexA = iter->second; + const VertexDescriptorType vertexB = graphToSubgraphVertexMap->find( adjacentVertex )->second; + const int sourceID = network->GetNode( vertexA ).id; + const int targetID = network->GetNode( vertexB ).id; + const int weight = network->GetEdge( iter->first, graphToSubgraphVertexMap->find( adjacentVertex )->first ).weight; + subNetwork->AddEdge( vertexA , vertexB, sourceID, targetID, weight ); + } + } + } + iter++; + }// end while( iter != end ) +} + +int mitk::ConnectomicsSimulatedAnnealingPermutationModularity::getNumberOfModules( + ToModuleMapType *vertexToModuleMap ) const +{ + int maxModule( 0 ); + ToModuleMapType::iterator iter = vertexToModuleMap->begin(); + ToModuleMapType::iterator end = vertexToModuleMap->end(); + while( iter != end ) + { + if( iter->second > maxModule ) + { + maxModule = iter->second; + } + + iter++; + } + + return maxModule + 1; +} + +int mitk::ConnectomicsSimulatedAnnealingPermutationModularity::getNumberOfVerticesInModule( + ToModuleMapType *vertexToModuleMap, int module ) const +{ + int number( 0 ); + ToModuleMapType::iterator iter = vertexToModuleMap->begin(); + ToModuleMapType::iterator end = vertexToModuleMap->end(); + while( iter != end ) + { + if( iter->second == module ) + { + number++; + } + + iter++; + } + + return number; +} + +void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::removeModule( + ToModuleMapType *vertexToModuleMap, int module ) +{ + int lastModuleNumber = getNumberOfModules( vertexToModuleMap ) - 1; + if( module == lastModuleNumber ) + { + // no need to do anything, the last module is deleted "automatically" + return; + } + + if( getNumberOfVerticesInModule( vertexToModuleMap, module ) > 0 ) + { + MBI_WARN << "Trying to remove non-empty module"; + return; + } + + ToModuleMapType::iterator iter = vertexToModuleMap->begin(); + ToModuleMapType::iterator end = vertexToModuleMap->end(); + while( iter != end ) + { + if( iter->second == lastModuleNumber ) + { + // renumber last module to to-be-deleted module + iter->second = module; + } + + iter++; + } +} + +void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::randomlyAssignNodesToModules( + ToModuleMapType *vertexToModuleMap, int numberOfIntendedModules ) +{ + // we make sure that each intended module contains *at least* one node + // thus if more modules are asked for than node exists we will only generate + // as many modules as there are nodes + if( numberOfIntendedModules > vertexToModuleMap->size() ) + { + MBI_ERROR << "Tried to generate more modules than vertices were provided"; + numberOfIntendedModules = vertexToModuleMap->size(); + } + + //the random number generators + vnl_random rng( (unsigned int) rand() ); + + std::vector< int > histogram; + std::vector< int > nodeList; + + histogram.resize( numberOfIntendedModules, 0 ); + nodeList.resize( vertexToModuleMap->size(), 0 ); + + int numberOfVertices = vertexToModuleMap->size(); + + //randomly distribute nodes to modules + for( int nodeIndex( 0 ); nodeIndex < nodeList.size(); nodeIndex++ ) + { + //select random module + nodeList[ nodeIndex ] = rng.lrand32( numberOfIntendedModules - 1 ); + + histogram[ nodeList[ nodeIndex ] ]++; + + } + + // make sure no module contains no node, if one does assign it one of a random module + // that does contain at least two + for( int moduleIndex( 0 ); moduleIndex < histogram.size(); moduleIndex++ ) + { + while( histogram[ moduleIndex ] == 0 ) + { + int randomNodeIndex = rng.lrand32( numberOfVertices - 1 ); + if( histogram[ nodeList[ randomNodeIndex ] ] > 1 ) + { + histogram[ moduleIndex ]++; + histogram[ nodeList[ randomNodeIndex ] ]--; + nodeList[ randomNodeIndex ] = moduleIndex; + } + } + } + + ToModuleMapType::iterator iter = vertexToModuleMap->begin(); + ToModuleMapType::iterator end = vertexToModuleMap->end(); + + for( int index( 0 ); ( iter != end ) && ( index < nodeList.size() ); index++, iter++ ) + { + iter->second = nodeList[ index ] ; + } +} + +void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::SetMapping( ToModuleMapType mapping ) +{ + m_BestSolution = mapping; +} + +mitk::ConnectomicsSimulatedAnnealingPermutationModularity::ToModuleMapType +mitk::ConnectomicsSimulatedAnnealingPermutationModularity::GetMapping() +{ + return m_BestSolution; +} + +double mitk::ConnectomicsSimulatedAnnealingPermutationModularity::Evaluate( ToModuleMapType* mapping ) const +{ + mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity* costMapping = + dynamic_cast( m_CostFunction.GetPointer() ); + if( costMapping ) + { + return costMapping->Evaluate( m_Network, mapping ); + } + else + { + return 0; + } +} + +bool mitk::ConnectomicsSimulatedAnnealingPermutationModularity::AcceptChange( double costBefore, double costAfter, double temperature ) const +{ + if( costAfter <= costBefore ) + {// if cost is lower after + return true; + } + + //the random number generators + vnl_random rng( (unsigned int) rand() ); + + //randomly generate threshold + const double threshold = rng.drand64( 0.0 , 1.0); + + //the likelihood of acceptance + double likelihood = std::exp( - ( costAfter - costBefore ) / temperature ); + + if( threshold < likelihood ) + { + return true; + } + + return false; +} + + +void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::SetDepth( int depth ) +{ + m_Depth = depth; +} + +void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::SetStepSize( double size ) +{ + m_StepSize = size; +} \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationModularity.h b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationModularity.h new file mode 100644 index 0000000000..9f56b2d7e1 --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationModularity.h @@ -0,0 +1,140 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef mitkConnectomicsSimulatedAnnealingPermutationModularity_h +#define mitkConnectomicsSimulatedAnnealingPermutationModularity_h + +#include "mitkConnectomicsSimulatedAnnealingPermutationBase.h" + +#include "mitkConnectomicsNetwork.h" + +namespace mitk +{ + /** + * \brief A class providing permutations for the calculation of modularity using simulated annealing */ + class MitkDiffusionImaging_EXPORT ConnectomicsSimulatedAnnealingPermutationModularity : public mitk::ConnectomicsSimulatedAnnealingPermutationBase + { + public: + + typedef mitk::ConnectomicsNetwork::VertexDescriptorType VertexDescriptorType; + typedef std::map< VertexDescriptorType, int > ToModuleMapType; + typedef std::map< VertexDescriptorType, VertexDescriptorType > VertexToVertexMapType; + + /** Standard class typedefs. */ + /** Method for creation through the object factory. */ + + mitkClassMacro(ConnectomicsSimulatedAnnealingPermutationModularity, itk::Object); + itkNewMacro(Self); + + // Initialize the permutation + virtual void Initialize(); + + // Do a permutation for a specific temperature + virtual void Permutate( double temperature ); + + // Do clean up necessary after a permutation + virtual void CleanUp(); + + // set the network permutation is to be run upon + void SetNetwork( mitk::ConnectomicsNetwork::Pointer theNetwork ); + + // Get the number of modules the graph has ( highest number - 1 ) + int getNumberOfModules( ToModuleMapType *vertexToModuleMap ) const; + + // Get the number of vertices belonging to a given module + int getNumberOfVerticesInModule( ToModuleMapType *vertexToModuleMap, int module ) const; + + // Set the mapping + void SetMapping( ToModuleMapType mapping ); + + // Get the mapping + ToModuleMapType GetMapping(); + + // Set depth + void SetDepth( int depth ); + + // Set stepSize + void SetStepSize( double size ); + + protected: + + //////////////////// Functions /////////////////////// + ConnectomicsSimulatedAnnealingPermutationModularity(); + ~ConnectomicsSimulatedAnnealingPermutationModularity(); + + // This function moves one single node from a module to another + void permutateMappingSingleNodeShift( + ToModuleMapType *vertexToModuleMap, + mitk::ConnectomicsNetwork::Pointer network ); + + // This function splits and joins modules + void permutateMappingModuleChange( + ToModuleMapType *vertexToModuleMap, + double currentTemperature, + mitk::ConnectomicsNetwork::Pointer network ); + + // join the two given modules to a single one + void joinTwoModules( ToModuleMapType *vertexToModuleMap, int moduleA, int moduleB ); + + // split the given module recursively up to a certain level + // first randomly assigns nodes and then starts another simulated annealing + // on the sub network, as long as depthOfModuleChange > 0 + void splitModule( + ToModuleMapType *vertexToModuleMap, + double currentTemperature, + mitk::ConnectomicsNetwork::Pointer network, + int moduleToSplit ); + + // Extract the subgraph of a network containing all nodes + // of a given module and the egdes between them + void extractModuleSubgraph( + ToModuleMapType *vertexToModuleMap, + mitk::ConnectomicsNetwork::Pointer network, + int moduleToSplit, + mitk::ConnectomicsNetwork::Pointer subNetwork, + VertexToVertexMapType* graphToSubgraphVertexMap, + VertexToVertexMapType* subgraphToGraphVertexMap ); + + // Remove empty modules by moving all nodes of the highest module to the given module + void removeModule( ToModuleMapType *vertexToModuleMap, int module ); + + // Randomly assign nodes to modules, this makes sure each module contains at least one node + // as long as numberOfIntendedModules < number of nodes + void randomlyAssignNodesToModules(ToModuleMapType *vertexToModuleMap, int numberOfIntendedModules ); + + // Evaluate mapping using a modularity cost function + double Evaluate( ToModuleMapType* mapping ) const; + + // Whether to accept the permutation + bool AcceptChange( double costBefore, double costAfter, double temperature ) const; + + // the current best solution + ToModuleMapType m_BestSolution; + + // the network + mitk::ConnectomicsNetwork::Pointer m_Network; + + // How many levels of recursive calls can be gone down + int m_Depth; + + // The step size for recursive configuring of simulated annealing manager + double m_StepSize; + }; + +}// end namespace mitk + +#endif // mitkConnectomicsSimulatedAnnealingPermutationModularity_h \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.cpp b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.cpp new file mode 100644 index 0000000000..927ae173c6 --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.cpp @@ -0,0 +1,350 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkConnectomicsSyntheticNetworkGenerator.h" + +#include +#include + +#include "mitkConnectomicsConstantsManager.h" + +#include + +//for random number generation +#include "vxl/core/vnl/vnl_random.h" +#include "vxl/core/vnl/vnl_math.h" + +mitk::ConnectomicsSyntheticNetworkGenerator::ConnectomicsSyntheticNetworkGenerator() +{ +} + +mitk::ConnectomicsSyntheticNetworkGenerator::~ConnectomicsSyntheticNetworkGenerator() +{ +} + +mitk::ConnectomicsNetwork::Pointer mitk::ConnectomicsSyntheticNetworkGenerator::CreateSyntheticNetwork(int networkTypeId, int paramterOne, double parameterTwo) +{ + mitk::ConnectomicsNetwork::Pointer network = mitk::ConnectomicsNetwork::New(); + + // give the network an artificial geometry + network->SetGeometry( this->GenerateDefaultGeometry() ); + + switch (networkTypeId) { + case 0: + GenerateSyntheticCubeNetwork( network, paramterOne, parameterTwo ); + break; + case 1: + GenerateSyntheticCenterToSurfaceNetwork( network, paramterOne, parameterTwo ); + break; + case 2: + GenerateSyntheticRandomNetwork( network, paramterOne, parameterTwo ); + break; + case 3: + //GenerateSyntheticScaleFreeNetwork( network, 1000 ); + break; + case 4: + //GenerateSyntheticSmallWorldNetwork( network, 1000 ); + break; + default: + MBI_ERROR << "Unrecognized Network ID"; + } + + return network; + +} + +mitk::Geometry3D::Pointer mitk::ConnectomicsSyntheticNetworkGenerator::GenerateDefaultGeometry() +{ + mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); + + double zero( 0.0 ); + double one( 1.0 ); + // origin = {0,0,0} + mitk::Point3D origin; + + origin[0] = zero; + origin[1] = zero; + origin[2] = zero; + geometry->SetOrigin(origin); + + // spacing = {1,1,1} + float spacing[3]; + spacing[0] = one; + spacing[1] = one; + spacing[2] = one; + geometry->SetSpacing(spacing); + + // transform + vtkMatrix4x4* transformMatrix = vtkMatrix4x4::New(); + transformMatrix->SetElement(0,0,one); + transformMatrix->SetElement(1,0,zero); + transformMatrix->SetElement(2,0,zero); + transformMatrix->SetElement(0,1,zero); + transformMatrix->SetElement(1,1,one); + transformMatrix->SetElement(2,1,zero); + transformMatrix->SetElement(0,2,zero); + transformMatrix->SetElement(1,2,zero); + transformMatrix->SetElement(2,2,one); + + transformMatrix->SetElement(0,3,origin[0]); + transformMatrix->SetElement(1,3,origin[1]); + transformMatrix->SetElement(2,3,origin[2]); + transformMatrix->SetElement(3,3,1); + geometry->SetIndexToWorldTransformByVtkMatrix( transformMatrix ); + + geometry->SetImageGeometry(true); + + return geometry; +} + +void mitk::ConnectomicsSyntheticNetworkGenerator::GenerateSyntheticCubeNetwork( + mitk::ConnectomicsNetwork::Pointer network, int cubeExtent, double distance ) +{ + // map for storing the conversion from indices to vertex descriptor + std::map< int, mitk::ConnectomicsNetwork::VertexDescriptorType > idToVertexMap; + + int vertexID(0); + for( int loopX( 0 ); loopX < cubeExtent; loopX++ ) + { + for( int loopY( 0 ); loopY < cubeExtent; loopY++ ) + { + for( int loopZ( 0 ); loopZ < cubeExtent; loopZ++ ) + { + std::vector< float > position; + std::string label; + std::stringstream labelStream; + labelStream << vertexID; + label = labelStream.str(); + + position.push_back( loopX * distance ); + position.push_back( loopY * distance ); + position.push_back( loopZ * distance ); + + mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = network->AddVertex( vertexID ); + network->SetLabel( newVertex, label ); + network->SetCoordinates( newVertex, position ); + + if ( idToVertexMap.count( vertexID ) > 0 ) + { + MITK_ERROR << "Aborting network creation, duplicate vertex ID generated."; + return; + } + idToVertexMap.insert( std::pair< int, mitk::ConnectomicsNetwork::VertexDescriptorType >( vertexID, newVertex) ); + + vertexID++; + } + } + } + + int edgeID(0), edgeSourceID(0), edgeTargetID(0); + // uniform weight of one + int edgeWeight(1); + + mitk::ConnectomicsNetwork::VertexDescriptorType source; + mitk::ConnectomicsNetwork::VertexDescriptorType target; + + for( int loopX( 0 ); loopX < cubeExtent; loopX++ ) + { + for( int loopY( 0 ); loopY < cubeExtent; loopY++ ) + { + for( int loopZ( 0 ); loopZ < cubeExtent; loopZ++ ) + { + // to avoid creating an edge twice (this being an undirected graph) we only generate + // edges in three directions, the others will be supplied by the corresponding nodes + if( loopX != 0 ) + { + edgeTargetID = edgeSourceID - cubeExtent * cubeExtent; + + source = idToVertexMap.find( edgeSourceID )->second; + target = idToVertexMap.find( edgeTargetID )->second; + network->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight); + + edgeID++; + } + if( loopY != 0 ) + { + edgeTargetID = edgeSourceID - cubeExtent; + + source = idToVertexMap.find( edgeSourceID )->second; + target = idToVertexMap.find( edgeTargetID )->second; + network->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight); + + edgeID++; + } + if( loopZ != 0 ) + { + edgeTargetID = edgeSourceID - 1; + + source = idToVertexMap.find( edgeSourceID )->second; + target = idToVertexMap.find( edgeTargetID )->second; + network->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight); + + edgeID++; + } + + edgeSourceID++; + } // end for( int loopZ( 0 ); loopZ < cubeExtent; loopZ++ ) + } // end for( int loopY( 0 ); loopY < cubeExtent; loopY++ ) + } // end for( int loopX( 0 ); loopX < cubeExtent; loopX++ ) +} + +void mitk::ConnectomicsSyntheticNetworkGenerator::GenerateSyntheticCenterToSurfaceNetwork( + mitk::ConnectomicsNetwork::Pointer network, int numberOfPoints, double radius ) +{ + //the random number generators + unsigned int randomOne = (unsigned int) rand(); + unsigned int randomTwo = (unsigned int) rand(); + + vnl_random rng( (unsigned int) rand() ); + vnl_random rng2( (unsigned int) rand() ); + + mitk::ConnectomicsNetwork::VertexDescriptorType centerVertex; + int vertexID(0); + { //add center vertex + std::vector< float > position; + std::string label; + std::stringstream labelStream; + labelStream << vertexID; + label = labelStream.str(); + + position.push_back( 0 ); + position.push_back( 0 ); + position.push_back( 0 ); + + centerVertex = network->AddVertex( vertexID ); + network->SetLabel( centerVertex, label ); + network->SetCoordinates( centerVertex, position ); + }//end add center vertex + + // uniform weight of one + int edgeWeight(1); + + mitk::ConnectomicsNetwork::VertexDescriptorType source; + mitk::ConnectomicsNetwork::VertexDescriptorType target; + + //add vertices on sphere surface + for( int loopID( 1 ); loopID < numberOfPoints; loopID++ ) + { + + std::vector< float > position; + std::string label; + std::stringstream labelStream; + labelStream << loopID; + label = labelStream.str(); + + //generate random, uniformly distributed points on a sphere surface + const double uVariable = rng.drand64( 0.0 , 1.0); + const double vVariable = rng.drand64( 0.0 , 1.0); + const double phi = 2 * vnl_math::pi * uVariable; + const double theta = std::acos( 2 * vVariable - 1 ); + + double xpos = radius * std::cos( phi ) * std::sin( theta ); + double ypos = radius * std::sin( phi ) * std::sin( theta ); + double zpos = radius * std::cos( theta ); + + position.push_back( xpos ); + position.push_back( ypos ); + position.push_back( zpos ); + + mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = network->AddVertex( loopID ); + network->SetLabel( newVertex, label ); + network->SetCoordinates( newVertex, position ); + + network->AddEdge( newVertex, centerVertex, loopID, 0, edgeWeight); + } +} + +void mitk::ConnectomicsSyntheticNetworkGenerator::GenerateSyntheticRandomNetwork( + mitk::ConnectomicsNetwork::Pointer network, int numberOfPoints, double threshold ) +{ + // as the surface is proportional to the square of the radius the density stays the same + double radius = 5 * std::sqrt( (float) numberOfPoints ); + + //the random number generators + unsigned int randomOne = (unsigned int) rand(); + unsigned int randomTwo = (unsigned int) rand(); + + vnl_random rng( (unsigned int) rand() ); + vnl_random rng2( (unsigned int) rand() ); + + // map for storing the conversion from indices to vertex descriptor + std::map< int, mitk::ConnectomicsNetwork::VertexDescriptorType > idToVertexMap; + + //add vertices on sphere surface + for( int loopID( 0 ); loopID < numberOfPoints; loopID++ ) + { + + std::vector< float > position; + std::string label; + std::stringstream labelStream; + labelStream << loopID; + label = labelStream.str(); + + //generate random, uniformly distributed points on a sphere surface + const double uVariable = rng.drand64( 0.0 , 1.0); + const double vVariable = rng.drand64( 0.0 , 1.0); + const double phi = 2 * vnl_math::pi * uVariable; + const double theta = std::acos( 2 * vVariable - 1 ); + + double xpos = radius * std::cos( phi ) * std::sin( theta ); + double ypos = radius * std::sin( phi ) * std::sin( theta ); + double zpos = radius * std::cos( theta ); + + position.push_back( xpos ); + position.push_back( ypos ); + position.push_back( zpos ); + + mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = network->AddVertex( loopID ); + network->SetLabel( newVertex, label ); + network->SetCoordinates( newVertex, position ); + + if ( idToVertexMap.count( loopID ) > 0 ) + { + MITK_ERROR << "Aborting network creation, duplicate vertex ID generated."; + return; + } + idToVertexMap.insert( std::pair< int, mitk::ConnectomicsNetwork::VertexDescriptorType >( loopID, newVertex) ); + } + + int edgeID(0); + // uniform weight of one + int edgeWeight(1); + + mitk::ConnectomicsNetwork::VertexDescriptorType source; + mitk::ConnectomicsNetwork::VertexDescriptorType target; + + for( int loopID( 0 ); loopID < numberOfPoints; loopID++ ) + { + // to avoid creating an edge twice (this being an undirected graph) we only + // potentially generate edges with all nodes with a bigger ID + for( int innerLoopID( loopID ); innerLoopID < numberOfPoints; innerLoopID++ ) + { + if( rng.drand64( 0.0 , 1.0) > threshold) + { + // do nothing + } + else + { + source = idToVertexMap.find( loopID )->second; + target = idToVertexMap.find( innerLoopID )->second; + network->AddEdge( source, target, loopID, innerLoopID, edgeWeight); + + edgeID++; + } + } // end for( int innerLoopID( loopID ); innerLoopID < numberOfPoints; innerLoopID++ ) + } // end for( int loopID( 0 ); loopID < numberOfPoints; loopID++ ) +} \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.h b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.h new file mode 100644 index 0000000000..dca9005c48 --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.h @@ -0,0 +1,83 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef mitkConnectomicsSyntheticNetworkGenerator_h +#define mitkConnectomicsSyntheticNetworkGenerator_h + +#include +#include +#include + +#include "mitkCommon.h" +#include "mitkImage.h" + +#include "mitkConnectomicsNetwork.h" + +#include "MitkDiffusionImagingExports.h" + +namespace mitk +{ + + /** + * \brief A class to generate synthetic networks */ + class MitkDiffusionImaging_EXPORT ConnectomicsSyntheticNetworkGenerator : public itk::Object + { + public: + + /** Standard class typedefs. */ + /** Method for creation through the object factory. */ + + mitkClassMacro(ConnectomicsSyntheticNetworkGenerator, itk::Object); + itkNewMacro(Self); + + /** Create Synthetic Networks */ + mitk::ConnectomicsNetwork::Pointer CreateSyntheticNetwork(int networkTypeId, int paramterOne, double parameterTwo); + + protected: + + //////////////////// Functions /////////////////////// + ConnectomicsSyntheticNetworkGenerator(); + ~ConnectomicsSyntheticNetworkGenerator(); + + /** Generate a default geometry for synthetic images */ + mitk::Geometry3D::Pointer GenerateDefaultGeometry(); + + /** Generate a synthetic cube (regular lattice) network */ + void GenerateSyntheticCubeNetwork( mitk::ConnectomicsNetwork::Pointer network, int cubeExtent, double distance ); + + /** Generate a highly heterogenic network + * + * This is achieved by generating a center vertex and vertices on + * a sphere surface, which are all only connected to the center + * vertex. */ + void GenerateSyntheticCenterToSurfaceNetwork( + mitk::ConnectomicsNetwork::Pointer network, int numberOfPoints, double radius ); + + /** Generate a random network without specific characteristics + * + * This is achieved by generating vertices and then deciding whether to + * specific vertices are connected by comparing a random number to the threshold */ + void GenerateSyntheticRandomNetwork( + mitk::ConnectomicsNetwork::Pointer network, int numberOfPoints, double threshold ); + + /////////////////////// Variables //////////////////////// + + }; + +}// end namespace mitk + +#endif // _mitkConnectomicsSyntheticNetworkGenerator_H_INCLUDED \ No newline at end of file diff --git a/Modules/DiffusionImaging/CMakeLists.txt b/Modules/DiffusionImaging/CMakeLists.txt index d072bc8493..0baae5d9ef 100644 --- a/Modules/DiffusionImaging/CMakeLists.txt +++ b/Modules/DiffusionImaging/CMakeLists.txt @@ -1,28 +1,28 @@ find_package(ITK) if(ITK_GDCM_DIR) include(${ITK_GDCM_DIR}/GDCMConfig.cmake) if(GDCM_MAJOR_VERSION EQUAL 2) add_definitions(-DGDCM2) set(ITK_USES_GDCM2 1) endif(GDCM_MAJOR_VERSION EQUAL 2) endif(ITK_GDCM_DIR) MITK_CREATE_MODULE( MitkDiffusionImaging SUBPROJECTS MITK-DTI - INCLUDE_DIRS IODataStructures Reconstruction Tractography Rendering Algorithms DicomImport Interactions IODataStructures/DiffusionWeightedImages IODataStructures/QBallImages IODataStructures/TensorImages IODataStructures/FiberBundle IODataStructures/FiberBundleX IODataStructures/PlanarFigureComposite IODataStructures/TbssImages ${CMAKE_CURRENT_BINARY_DIR} + INCLUDE_DIRS IODataStructures Reconstruction Tractography Rendering Algorithms DicomImport Interactions IODataStructures/DiffusionWeightedImages IODataStructures/QBallImages IODataStructures/TensorImages IODataStructures/FiberBundle IODataStructures/FiberBundleX IODataStructures/PlanarFigureComposite IODataStructures/TbssImages Algorithms/Connectomics IODataStructures/ConnectomicsNetwork ${CMAKE_CURRENT_BINARY_DIR} DEPENDS MitkExt SceneSerializationBase QmitkExt MitkGraphAlgorithms PACKAGE_DEPENDS Boost ) MITK_USE_MODULE(MitkDiffusionImaging) if(MitkDiffusionImaging_IS_ENABLED) file(DOWNLOAD http://mitk.org/download/data/FibertrackingLUT.tar.gz ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FibertrackingLUT.tar.gz TIMEOUT 10) execute_process(COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} tar xzf FibertrackingLUT.tar.gz) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Rendering/mitkShaderFiberClipping.xml ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mitkShaderFiberClipping.xml) MITK_INSTALL(FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mitkShaderFiberClipping.xml ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FiberTrackingLUTBaryCoords.bin ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FiberTrackingLUTIndices.bin) endif() add_subdirectory(Testing) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mitkDiffusionImagingConfigure.h.in ${CMAKE_CURRENT_BINARY_DIR}/mitkDiffusionImagingConfigure.h) diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsConstantsManager.cpp b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsConstantsManager.cpp new file mode 100644 index 0000000000..884f2ec928 --- /dev/null +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsConstantsManager.cpp @@ -0,0 +1,61 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Module: $RCSfile$ +Language: C++ +Date: $Date$ +Version: $Revision: 11989 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +//#ifndef _MITK_ConnectomicsConstantsManager_CPP +//#define _MITK_ConnectomicsConstantsManager_CPP + +#include "mitkConnectomicsConstantsManager.h" + +//============== String and other constants =================== + +//==== Error messages ==== +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_TRIED_TO_ACCESS_INVALID_HISTOGRAM = "Tried to access invalid histogram."; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_PASSED_NEGATIVE_INDEX_TO_HISTOGRAM = "Passed negative index to histogram."; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_OUTSIDE_INTEGER_RANGE = "Tried to access histogram vector outside integer range."; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_BEYOND_SCOPE = "Tried to access histogram vector for value beyond scope: "; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_MAPPING = "Invalid mapping strategy selected."; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3 = "Invalid dimension, need dimension 3."; + +//==== Warnings ==== +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ZERO_DISTANCE_NODES = "There are nodes which are not distance 0 to themselves."; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_UNIMPLEMENTED_FEATURE = "You are trying to use an as of yet unimplemented feature."; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_MORE_POINTS_THAN_PRESENT = "Trying to estimate using more points than are present."; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_LESS_THAN_2 = "Trying to estimate using less than two points."; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_BEYOND_END = "Trying to estimate using points beyond track end."; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_BEYOND_START = "Trying to estimate using points beyond track start."; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_DID_NOT_FIND_WHITE = "Did not find a non white matter label."; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_NOT_EXTEND_TO_WHITE = "Could not extend to non white matter."; + +//==== Information ==== +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_INFO_NETWORK_CREATED = "Network has been created."; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_NETWORK_NOT_VALID = "Network not valid."; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_NETWORK_DISCONNECTED = "Network is disconnected."; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_CAN_NOT_COMPUTE_EFFICIENCY = "Can not compute efficiency. "; + +//==== GUI ==== +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH = "-"; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS_CREATION = "Connectomics Creation"; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_SELECTION_WARNING = "Please load and select exactly one parcellation image and one fiber image before starting network creation."; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_PERFORMING_IMAGE_PROCESSING_FOR_IMAGE = "Performing image processing for image "; + +//==== Properties ==== +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_DEFAULT_RGBA_NAME = "rgbaImage"; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_NAME = "name"; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_VOLUMERENDERING = "volumerendering"; +const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_DEFAULT_CNF_NAME = "Connectomics network"; + +//#endif /* _MITK_ConnectomicsConstantsManager_CPP */ \ No newline at end of file diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsConstantsManager.h b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsConstantsManager.h new file mode 100644 index 0000000000..12cbdf5b45 --- /dev/null +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsConstantsManager.h @@ -0,0 +1,86 @@ + +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Module: $RCSfile$ +Language: C++ +Date: $Date$ +Version: $Revision: 11989 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef _MITK_ConnectomicsConstantsManager_H +#define _MITK_ConnectomicsConstantsManager_H + +#include "MitkDiffusionImagingExports.h" + +namespace mitk +{ + + /** \brief The XML consts for reading and writing + */ + + class MitkDiffusionImaging_EXPORT ConnectomicsConstantsManager + { + public: + + //============== String and other constants =================== + + //==== Error messages ==== + static const char* CONNECTOMICS_ERROR_TRIED_TO_ACCESS_INVALID_HISTOGRAM; + static const char* CONNECTOMICS_ERROR_PASSED_NEGATIVE_INDEX_TO_HISTOGRAM; + static const char* CONNECTOMICS_ERROR_OUTSIDE_INTEGER_RANGE; + static const char* CONNECTOMICS_ERROR_BEYOND_SCOPE; + static const char* CONNECTOMICS_ERROR_INVALID_MAPPING; + static const char* CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3; + + //==== Warnings ==== + static const char* CONNECTOMICS_WARNING_ZERO_DISTANCE_NODES; + static const char* CONNECTOMICS_WARNING_UNIMPLEMENTED_FEATURE; + static const char* CONNECTOMICS_WARNING_MORE_POINTS_THAN_PRESENT; + static const char* CONNECTOMICS_WARNING_ESTIMATING_LESS_THAN_2; + static const char* CONNECTOMICS_WARNING_ESTIMATING_BEYOND_END; + static const char* CONNECTOMICS_WARNING_ESTIMATING_BEYOND_START; + static const char* CONNECTOMICS_WARNING_DID_NOT_FIND_WHITE; + static const char* CONNECTOMICS_WARNING_NOT_EXTEND_TO_WHITE; + + //==== Information ==== + static const char* CONNECTOMICS_WARNING_INFO_NETWORK_CREATED; + static const char* CONNECTOMICS_WARNING_NETWORK_NOT_VALID; + static const char* CONNECTOMICS_WARNING_NETWORK_DISCONNECTED; + static const char* CONNECTOMICS_WARNING_CAN_NOT_COMPUTE_EFFICIENCY; + + //==== GUI ==== + static const char* CONNECTOMICS_GUI_DASH; + static const char* CONNECTOMICS_GUI_CONNECTOMICS_CREATION; + static const char* CONNECTOMICS_GUI_SELECTION_WARNING; + static const char* CONNECTOMICS_GUI_PERFORMING_IMAGE_PROCESSING_FOR_IMAGE; + + //==== Properties ==== + static const char* CONNECTOMICS_PROPERTY_DEFAULT_RGBA_NAME; + static const char* CONNECTOMICS_PROPERTY_NAME; + static const char* CONNECTOMICS_PROPERTY_VOLUMERENDERING; + static const char* CONNECTOMICS_PROPERTY_DEFAULT_CNF_NAME; + + + private: + ConnectomicsConstantsManager(); + ~ConnectomicsConstantsManager(); + + }; + +} //namespace MITK + +// include cpp + +//#include + +#endif /* _MITK_ConnectomicsConstantsManager_H */ \ No newline at end of file diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.cpp b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.cpp new file mode 100644 index 0000000000..144e4227c5 --- /dev/null +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.cpp @@ -0,0 +1,454 @@ + +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Module: $RCSfile$ +Language: C++ +Date: $Date$ +Version: $Revision: 11989 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkConnectomicsNetwork.h" +#include + +/* Constructor and Destructor */ +mitk::ConnectomicsNetwork::ConnectomicsNetwork() +: m_IsModified( false ) +{ +} + +mitk::ConnectomicsNetwork::~ConnectomicsNetwork() +{ +} + +/* Wrapper methods */ + +bool mitk::ConnectomicsNetwork::EdgeExists( + mitk::ConnectomicsNetwork::VertexDescriptorType vertexA, mitk::ConnectomicsNetwork::VertexDescriptorType vertexB ) const +{ + return boost::edge(vertexA, vertexB, m_Network ).second; +} + +void mitk::ConnectomicsNetwork::IncreaseEdgeWeight( + mitk::ConnectomicsNetwork::VertexDescriptorType vertexA, mitk::ConnectomicsNetwork::VertexDescriptorType vertexB ) +{ + m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].weight++; + + SetIsModified( true ); +} + +void mitk::ConnectomicsNetwork::AddEdge( + mitk::ConnectomicsNetwork::VertexDescriptorType vertexA, + mitk::ConnectomicsNetwork::VertexDescriptorType vertexB + ) +{ + AddEdge(vertexA, vertexB, m_Network[ vertexA ].id, m_Network[ vertexB ].id ); +} + +void mitk::ConnectomicsNetwork::AddEdge( + mitk::ConnectomicsNetwork::VertexDescriptorType vertexA, + mitk::ConnectomicsNetwork::VertexDescriptorType vertexB, + int sourceID, int targetID, int weight ) +{ + boost::add_edge( vertexA, vertexB, m_Network ); + m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].sourceId = sourceID; + m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].targetId = targetID; + m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].weight = weight; + m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].edge_weight = 1.0; + + SetIsModified( true ); +} + +mitk::ConnectomicsNetwork::VertexDescriptorType mitk::ConnectomicsNetwork::AddVertex( int id ) +{ + VertexDescriptorType vertex = boost::add_vertex( m_Network ); + m_Network[vertex].id = id; + + SetIsModified( true ); + + return vertex; +} + +void mitk::ConnectomicsNetwork::SetLabel( + mitk::ConnectomicsNetwork::VertexDescriptorType vertex, std::string inLabel ) +{ + m_Network[vertex].label = inLabel; + + SetIsModified( true ); +} + +void mitk::ConnectomicsNetwork::SetCoordinates( + mitk::ConnectomicsNetwork::VertexDescriptorType vertex, std::vector< float > inCoordinates ) +{ + m_Network[vertex].coordinates = inCoordinates; + + SetIsModified( true ); +} + +void mitk::ConnectomicsNetwork::clear() +{ + m_Network.clear(); + + SetIsModified( true ); +} + +/* Superclass methods, that need to be implemented */ +void mitk::ConnectomicsNetwork::UpdateOutputInformation() +{ + +} +void mitk::ConnectomicsNetwork::SetRequestedRegionToLargestPossibleRegion() +{ + +} +bool mitk::ConnectomicsNetwork::RequestedRegionIsOutsideOfTheBufferedRegion() +{ + return false; +} +bool mitk::ConnectomicsNetwork::VerifyRequestedRegion() +{ + return true; +} +void mitk::ConnectomicsNetwork::SetRequestedRegion( itk::DataObject *data ) +{ + +} + + + +std::vector< mitk::ConnectomicsNetwork::NetworkNode > +mitk::ConnectomicsNetwork::GetVectorOfAllNodes() const +{ + boost::graph_traits::vertex_iterator iterator, end; + + // sets iterator to start end end to end + boost::tie(iterator, end) = boost::vertices( m_Network ); + + std::vector< NetworkNode > vectorOfNodes; + + for ( ; iterator != end; ++iterator) + { + NetworkNode tempNode; + + // the value of an iterator is a descriptor + tempNode = m_Network[ *iterator ]; + + vectorOfNodes.push_back( tempNode ); + } + + return vectorOfNodes; +} + +std::vector< mitk::ConnectomicsNetwork::VertexDescriptorType > +mitk::ConnectomicsNetwork::GetVectorOfAllVertexDescriptors() const +{ + boost::graph_traits::vertex_iterator iterator, end; + + // sets iterator to start end end to end + boost::tie(iterator, end) = boost::vertices( m_Network ); + + std::vector< VertexDescriptorType > vectorOfDescriptors; + + for ( ; iterator != end; ++iterator) + { + vectorOfDescriptors.push_back( *iterator ); + } + + return vectorOfDescriptors; +} + +std::vector< std::pair< +std::pair< mitk::ConnectomicsNetwork::NetworkNode, mitk::ConnectomicsNetwork::NetworkNode > +, mitk::ConnectomicsNetwork::NetworkEdge > > +mitk::ConnectomicsNetwork::GetVectorOfAllEdges() const +{ + boost::graph_traits::edge_iterator iterator, end; + + // sets iterator to start end end to end + boost::tie(iterator, end) = boost::edges( m_Network ); + + std::vector< + std::pair< + std::pair< NetworkNode, NetworkNode > + , NetworkEdge + > + > vectorOfEdges; + + for ( ; iterator != end; ++iterator) + { + NetworkNode sourceNode, targetNode; + NetworkEdge tempEdge; + + // the value of an iterator is a descriptor + tempEdge = m_Network[ *iterator ]; + sourceNode = m_Network[ boost::source( *iterator, m_Network ) ]; + targetNode = m_Network[ boost::target( *iterator, m_Network ) ]; + + std::pair< NetworkNode, NetworkNode > nodePair( sourceNode, targetNode ); + std::pair< std::pair< NetworkNode, NetworkNode > , NetworkEdge > edgePair( nodePair, tempEdge); + vectorOfEdges.push_back( edgePair ); + } + + return vectorOfEdges; +} + +int mitk::ConnectomicsNetwork::GetNumberOfVertices() const +{ + return boost::num_vertices( m_Network ); +} + +int mitk::ConnectomicsNetwork::GetNumberOfEdges() +{ + return boost::num_edges( m_Network ); +} + +int mitk::ConnectomicsNetwork::GetMaximumWeight() const +{ + int maxWeight( 0 ); + + boost::graph_traits::edge_iterator iterator, end; + + // sets iterator to start end end to end + boost::tie(iterator, end) = boost::edges( m_Network ); + + for ( ; iterator != end; ++iterator) + { + int tempWeight; + + // the value of an iterator is a descriptor + tempWeight = m_Network[ *iterator ].weight; + + if( tempWeight > maxWeight ) + { + maxWeight = tempWeight; + } + } + + return maxWeight; +} + +int mitk::ConnectomicsNetwork::GetNumberOfSelfLoops() +{ + int noOfSelfLoops( 0 ); + + std::vector< std::pair< std::pair< NetworkNode, NetworkNode > , NetworkEdge > > + edgeVector = GetVectorOfAllEdges(); + + for( int index = 0; index < edgeVector.size() ; index++ ) + { + double sourceX, sourceY, sourceZ, targetX, targetY, targetZ; + + sourceX = edgeVector[ index ].first.first.coordinates[0] ; + sourceY = edgeVector[ index ].first.first.coordinates[1] ; + sourceZ = edgeVector[ index ].first.first.coordinates[2] ; + targetX = edgeVector[ index ].first.second.coordinates[0] ; + targetY = edgeVector[ index ].first.second.coordinates[1] ; + targetZ = edgeVector[ index ].first.second.coordinates[2] ; + + // if the coordinates are the same + if( + sourceX > ( targetX - 0.01 ) && + sourceX < ( targetX + 0.01 ) && + sourceY > ( targetY - 0.01 ) && + sourceY < ( targetY + 0.01 ) && + sourceZ > ( targetZ - 0.01 ) && + sourceZ < ( targetZ + 0.01 ) + ) + { + noOfSelfLoops++; + } + } + + return noOfSelfLoops; +} + +double mitk::ConnectomicsNetwork::GetAverageDegree() +{ + double vertices = (double) GetNumberOfVertices(); + double edges = (double) GetNumberOfEdges(); + + return ( ( edges * 2.0 ) / vertices ); +} + +double mitk::ConnectomicsNetwork::GetConnectionDensity() +{ + double vertices = (double) GetNumberOfVertices(); + double edges = (double) GetNumberOfEdges(); + double numberOfPossibleEdges = vertices * ( vertices - 1 ) / 2 ; + + return ( edges / numberOfPossibleEdges ); +} + +std::vector< int > mitk::ConnectomicsNetwork::GetDegreeOfNodes( ) const +{ + std::vector< int > vectorOfDegree; + + boost::graph_traits::vertex_iterator iterator, end; + + // sets iterator to start end end to end + boost::tie( iterator, end ) = boost::vertices( m_Network ); + + vectorOfDegree.resize( this->GetNumberOfVertices() ); + + for ( ; iterator != end; ++iterator) + { + // the value of an iterator is a descriptor + vectorOfDegree[ m_Network[ *iterator ].id ] = GetVectorOfAdjacentNodes( *iterator ).size(); + } + return vectorOfDegree; +} + +std::vector< mitk::ConnectomicsNetwork::VertexDescriptorType > +mitk::ConnectomicsNetwork::GetVectorOfAdjacentNodes( mitk::ConnectomicsNetwork::VertexDescriptorType vertex ) const +{ + std::vector< mitk::ConnectomicsNetwork::VertexDescriptorType > vectorOfAdjacentNodes; + + boost::graph_traits::adjacency_iterator adjIter, adjEnd; + + boost::tie( adjIter, adjEnd ) = boost::adjacent_vertices( vertex, m_Network); + + for ( ; adjIter != adjEnd; ++adjIter) + { + vectorOfAdjacentNodes.push_back( *adjIter ); + } + + return vectorOfAdjacentNodes; +} + +int mitk::ConnectomicsNetwork::GetMaximumDegree() const +{ + int maximumDegree( 0 ); + + std::vector< int > vectorOfDegree = GetDegreeOfNodes(); + + for( int index( 0 ); index < vectorOfDegree.size(); ++index ) + { + if( maximumDegree < vectorOfDegree[ index ] ) + { + maximumDegree = vectorOfDegree[ index ]; + } + } + + return maximumDegree; +} + +std::vector< double > mitk::ConnectomicsNetwork::GetLocalClusteringCoefficients( ) +{ + std::vector< double > vectorOfClusteringCoefficients; + + typedef boost::graph_traits::vertex_iterator vertexIter; + + vectorOfClusteringCoefficients.resize( this->GetNumberOfVertices() ); + + std::pair vertexPair; + + //for every vertex calculate the clustering coefficient + for (vertexPair = vertices(m_Network); vertexPair.first != vertexPair.second; ++vertexPair.first) + { + vectorOfClusteringCoefficients[ m_Network[ *vertexPair.first ].id ] = + boost::clustering_coefficient(m_Network,*vertexPair.first) ; + } + + return vectorOfClusteringCoefficients; +} + +std::vector< double > mitk::ConnectomicsNetwork::GetClusteringCoefficientsByDegree( ) +{ + std::vector< double > vectorOfClusteringCoefficients = GetLocalClusteringCoefficients(); + std::vector< int > vectorOfDegree = GetDegreeOfNodes(); + + std::vector< double > vectorOfClusteringCoefficientsByDegree; + vectorOfClusteringCoefficientsByDegree.resize( GetMaximumDegree() + 1, 0 ); + + // c_{mean}(k) = frac{1}_{N_{k}} sum_{i in Y(k)} c_{i} + // where N_{k} is the number of vertices of degree k + // Y(k) is the set of vertices of degree k + // c_{i} is the local clustering coefficient of vertex i + for( int degree( 0 ); degree < vectorOfClusteringCoefficientsByDegree.size(); ++degree ) + { + vectorOfClusteringCoefficientsByDegree[ degree ] = 0; + int n_k( 0 ); + for( int index( 0 ); index < vectorOfDegree.size(); ++index ) + { + if( degree == vectorOfDegree[ index ] ) + {// if in Y( degree ) + vectorOfClusteringCoefficientsByDegree[ degree ] += vectorOfClusteringCoefficients[ index ]; + n_k++; + } + } + if( n_k != 0 ) + { + vectorOfClusteringCoefficientsByDegree[ degree ] = + vectorOfClusteringCoefficientsByDegree[ degree ] / n_k; + } + } + + return vectorOfClusteringCoefficientsByDegree; +} + +double mitk::ConnectomicsNetwork::GetGlobalClusteringCoefficient( ) +{ + double globalClusteringCoefficient( 0.0 ); + + std::vector< double > vectorOfClusteringCoefficientsByDegree = GetClusteringCoefficientsByDegree(); + std::vector< int > vectorOfDegree = GetDegreeOfNodes(); + std::vector< int > degreeDistribution; + degreeDistribution.resize( vectorOfClusteringCoefficientsByDegree.size(), 0 ); + + int normalizationParameter( 0 ); + + for( int index( 0 ); index < vectorOfDegree.size(); ++index ) + { + degreeDistribution[ vectorOfDegree[ index ] ]++; + normalizationParameter++; + } + // c_{mean} = sum_{k} P_{k} c_{mean}(k) + // where P_{k} is the degree distribution + // k is the degree + for( int degree( 0 ); degree < degreeDistribution.size(); ++degree ) + { + globalClusteringCoefficient += + degreeDistribution[ degree ] / ( (double) normalizationParameter) + * vectorOfClusteringCoefficientsByDegree[ degree ]; + } + + return globalClusteringCoefficient; +} + +mitk::ConnectomicsNetwork::NetworkType* mitk::ConnectomicsNetwork::GetBoostGraph() +{ + return &m_Network; +} + + +bool mitk::ConnectomicsNetwork::GetIsModified() const +{ + return m_IsModified; +} + + +void mitk::ConnectomicsNetwork::SetIsModified( bool value) +{ + m_IsModified = value; +} + + +mitk::ConnectomicsNetwork::NetworkNode mitk::ConnectomicsNetwork::GetNode( VertexDescriptorType vertex ) const +{ + return m_Network[ vertex ]; +} + + +mitk::ConnectomicsNetwork::NetworkEdge mitk::ConnectomicsNetwork::GetEdge( VertexDescriptorType vertexA, VertexDescriptorType vertexB ) const +{ + return m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ]; +} \ No newline at end of file diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.h b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.h new file mode 100644 index 0000000000..0f60898443 --- /dev/null +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.h @@ -0,0 +1,177 @@ + +/*========================================================================= + + Program: Medical Imaging & Interaction Toolkit + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision: 11989 $ + + Copyright (c) German Cancer Research Center, Division of Medical and + Biological Informatics. All rights reserved. + See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + + =========================================================================*/ + + +#ifndef _MITK_ConnectomicsNetwork_H +#define _MITK_ConnectomicsNetwork_H + +#include "MitkDiffusionImagingExports.h" + +#include "mitkBaseData.h" + +#include + +namespace mitk { + + /** + * \brief Base Class for Connectomics Networks */ + class MitkDiffusionImaging_EXPORT ConnectomicsNetwork : public BaseData + { + public: + /** Structs for the graph */ + + /** The Node */ + struct NetworkNode + { + int id; + std::string label; + std::vector< float > coordinates; + }; + + /** The Edge */ + struct NetworkEdge + { + int sourceId; + int targetId; + int weight; // For now the number of times it was present + double edge_weight; // For boost, currently set to 1 by default for unweighted calculations + }; + + /** Typedefs **/ + //typedef boost::adjacency_list< boost::listS, boost::listS, boost::undirectedS, NetworkNode, NetworkEdge > NetworkType; + typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::undirectedS, NetworkNode, NetworkEdge > NetworkType; + typedef boost::graph_traits::vertex_descriptor VertexDescriptorType; + typedef boost::graph_traits::edge_descriptor EdgeDescriptorType; + + // virtual methods that need to be implemented + virtual void UpdateOutputInformation(); + virtual void SetRequestedRegionToLargestPossibleRegion(); + virtual bool RequestedRegionIsOutsideOfTheBufferedRegion(); + virtual bool VerifyRequestedRegion(); + virtual void SetRequestedRegion( itk::DataObject *data ); + + + // Macros + mitkClassMacro( ConnectomicsNetwork, BaseData ); + itkNewMacro( Self ); + + ////////////////// Interface /////////////////// + /** return whether an edge exists between the two given vertices */ + bool EdgeExists( VertexDescriptorType vertexA, VertexDescriptorType vertexB ) const; + + /** increase the weight of an edge between the two given vertices */ + void IncreaseEdgeWeight( VertexDescriptorType vertexA, VertexDescriptorType vertexB ); + + /** add an edge between two given vertices */ + void AddEdge( VertexDescriptorType vertexA, VertexDescriptorType vertexB); + + /** add an edge between two given vertices ( with a specific weight ) */ + void AddEdge( VertexDescriptorType vertexA, VertexDescriptorType vertexB, int sourceID, int targetID, int weight = 1 ); + + /** add a vertex with a specified id */ + VertexDescriptorType AddVertex( int id); + + /** set the label of a vertex */ + void SetLabel( VertexDescriptorType vertex, std::string inLabel ); + + /** set the coordinates of a vertex */ + void SetCoordinates( VertexDescriptorType vertex, std::vector< float > inCoordinates ); + + /** clear the graph */ + void clear(); + + /** return the node struct for a given node descriptor */ + NetworkNode GetNode( VertexDescriptorType vertex ) const; + + /** return the edge struct for two given node descriptors */ + NetworkEdge GetEdge( VertexDescriptorType vertexA, VertexDescriptorType vertexB ) const; + + /** get vector containing all the nodes of the network */ + std::vector< NetworkNode > GetVectorOfAllNodes() const; + + /** get vector containing all the vertex descriptors of the network */ + std::vector< VertexDescriptorType > GetVectorOfAllVertexDescriptors() const; + + /** get vector containing the descriptors of nodes adjacent to the vertex denoted by the given descriptor */ + std::vector< VertexDescriptorType > GetVectorOfAdjacentNodes( VertexDescriptorType vertex ) const; + + /** get vector containing all the edges of the network and the connected nodes */ + std::vector< std::pair< std::pair< NetworkNode, NetworkNode > , NetworkEdge > > GetVectorOfAllEdges() const; + + /** get overall number of vertices in the network */ + int GetNumberOfVertices() const; + + /** get overall number of edges in the network */ + int GetNumberOfEdges(); + + /** get number of vertices, that are connected to themselves */ + int GetNumberOfSelfLoops(); + + /** get number of vertices, that are connected to themselves */ + double GetAverageDegree(); + + /** get number of edges divided by number of possible edges */ + double GetConnectionDensity(); + + /** Get the maximum weight of all edges */ + int GetMaximumWeight() const; + + /** Get a vector in the format vector[ vertexID ] = degree */ + std::vector< int > GetDegreeOfNodes( ) const; + + /** Get the maximum degree of all nodes */ + int GetMaximumDegree() const; + + /** Get a vector in the format vector[ vertexID ] = clustering coefficient */ + std::vector< double > GetLocalClusteringCoefficients( ); + + /** Get a vector in the format vector[ degree ] = average clustering coefficient */ + std::vector< double > GetClusteringCoefficientsByDegree( ); + + /** Get the global clustering coefficient */ + double GetGlobalClusteringCoefficient( ); + + /** Access boost graph directly */ + NetworkType* GetBoostGraph(); + + /** Get the modified flag */ + bool GetIsModified() const; + + /** Set the modified flag */ + void SetIsModified( bool ); + + protected: + ConnectomicsNetwork(); + virtual ~ConnectomicsNetwork(); + + NetworkType m_Network; + + /// Flag which indicates whether the network has been modified since the last check + /// + /// mainly for rendering purposes + + bool m_IsModified; + + private: + + }; + +} // namespace mitk + +#endif /* _MITK_ConnectomicsNetwork_H */ diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkDefinitions.cpp b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkDefinitions.cpp new file mode 100644 index 0000000000..b9c87455eb --- /dev/null +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkDefinitions.cpp @@ -0,0 +1,65 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2009-07-14 19:11:20 +0200 (Tue, 14 Jul 2009) $ +Version: $Revision: 18127 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkConnectomicsNetworkDefinitions.h" + +//============== XML const chars =================== + +//==== Header information ==== +const char* mitk::ConnectomicsNetworkDefinitions::XML_CONNECTOMICS_FILE = "connectomics_network_file" ; +const char* mitk::ConnectomicsNetworkDefinitions::XML_FILE_VERSION = "file_version" ; +const char* mitk::ConnectomicsNetworkDefinitions::VERSION_STRING = "0.1" ; +const char* mitk::ConnectomicsNetworkDefinitions::ASCII_FILE = "ascii_file" ; +const char* mitk::ConnectomicsNetworkDefinitions::FILE_NAME = "file_name" ; + +//==== Geometry details ==== +const char* mitk::ConnectomicsNetworkDefinitions::XML_GEOMETRY = "geometry"; + +const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XX = "xx"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XY = "xy"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XZ = "xz"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YX = "yx"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YY = "yy"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YZ = "yz"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZX = "zx"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZY = "zy"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZZ = "zz"; + +const char* mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_X = "origin_x"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Y = "origin_y"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Z = "origin_z"; + +const char* mitk::ConnectomicsNetworkDefinitions::XML_SPACING_X = "spacing_x"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Y = "spacing_y"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Z = "spacing_z"; + +//==== Connectomics structures ==== +const char* mitk::ConnectomicsNetworkDefinitions::XML_VERTICES = "vertices"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_EDGES = "edges"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_VERTEX = "vertex"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_EDGE = "edge"; + +//==== Connectomics properties ==== +const char* mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_ID = "v_id"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_LABEL = "v_label"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_X = "v_x"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Y = "v_y"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Z = "v_z"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_EDGE_ID = "e_id"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_EDGE_SOURCE_ID = "e_s_id"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_EDGE_TARGET_ID = "e_t_id"; +const char* mitk::ConnectomicsNetworkDefinitions::XML_EDGE_WEIGHT_ID = "e_weight"; diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkDefinitions.h b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkDefinitions.h new file mode 100644 index 0000000000..11173ee956 --- /dev/null +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkDefinitions.h @@ -0,0 +1,86 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2009-07-14 19:11:20 +0200 (Tue, 14 Jul 2009) $ +Version: $Revision: 18127 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef __mitkConnectomicsNetworkDefinitions_h +#define __mitkConnectomicsNetworkDefinitions_h + +namespace mitk +{ + + /** \brief The XML consts for reading and writing + */ + + class ConnectomicsNetworkDefinitions + { + public: + + //============== XML const chars =================== + + //==== Header information ==== + static const char* XML_CONNECTOMICS_FILE; + static const char* XML_FILE_VERSION; + static const char* VERSION_STRING; + static const char* ASCII_FILE; + static const char* FILE_NAME; + + //==== Geometry details ==== + static const char* XML_GEOMETRY; + + static const char* XML_MATRIX_XX; + static const char* XML_MATRIX_XY; + static const char* XML_MATRIX_XZ; + static const char* XML_MATRIX_YX; + static const char* XML_MATRIX_YY; + static const char* XML_MATRIX_YZ; + static const char* XML_MATRIX_ZX; + static const char* XML_MATRIX_ZY; + static const char* XML_MATRIX_ZZ; + + static const char* XML_ORIGIN_X; + static const char* XML_ORIGIN_Y; + static const char* XML_ORIGIN_Z; + + static const char* XML_SPACING_X; + static const char* XML_SPACING_Y; + static const char* XML_SPACING_Z; + + //==== Connectomics structures ==== + static const char* XML_VERTICES; + static const char* XML_EDGES; + static const char* XML_VERTEX; + static const char* XML_EDGE; + + //==== Connectomics properties ==== + static const char* XML_VERTEX_ID; + static const char* XML_VERTEX_LABEL; + static const char* XML_VERTEX_X; + static const char* XML_VERTEX_Y; + static const char* XML_VERTEX_Z; + static const char* XML_EDGE_ID; + static const char* XML_EDGE_SOURCE_ID; + static const char* XML_EDGE_TARGET_ID; + static const char* XML_EDGE_WEIGHT_ID; + + private: + ConnectomicsNetworkDefinitions(); + ~ConnectomicsNetworkDefinitions(); + + }; + +} //namespace MITK + +#endif // __mitkConnectomicsNetworkDefinitions_h diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkIOFactory.cpp b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkIOFactory.cpp new file mode 100644 index 0000000000..d7aece611b --- /dev/null +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkIOFactory.cpp @@ -0,0 +1,52 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2007-12-11 14:46:19 +0100 (Di, 11 Dez 2007) $ +Version: $Revision: 6607 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkConnectomicsNetworkIOFactory.h" +#include "mitkIOAdapter.h" +#include "mitkConnectomicsNetworkReader.h" + +#include "itkVersion.h" + + +namespace mitk +{ + +ConnectomicsNetworkIOFactory::ConnectomicsNetworkIOFactory() +{ + typedef ConnectomicsNetworkReader ConnectomicsNetworkReaderType; + this->RegisterOverride("mitkIOAdapter", //beibehalten + "mitkConnectomicsNetworkReader", //umbenennen + "Connectomics Network IO", //angezeigter name + 1, + itk::CreateObjectFunction >::New()); +} + +ConnectomicsNetworkIOFactory::~ConnectomicsNetworkIOFactory() +{ +} + +const char* ConnectomicsNetworkIOFactory::GetITKSourceVersion() const +{ + return ITK_SOURCE_VERSION; +} + +const char* ConnectomicsNetworkIOFactory::GetDescription() const +{ + return "ConnectomicsNetworkIOFactory, allows the loading of Connectomics Networks"; +} + +} // end namespace mitk diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkIOFactory.h b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkIOFactory.h new file mode 100644 index 0000000000..7132cfe89e --- /dev/null +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkIOFactory.h @@ -0,0 +1,73 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2009-05-13 18:06:46 +0200 (Mi, 13 Mai 2009) $ +Version: $Revision: 6590 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __MITK_CONNECTOMICS_NETWORK_IO_FACTORY_H_HEADER__ +#define __MITK_CONNECTOMICS_NETWORK_IO_FACTORY_H_HEADER__ + +#ifdef _MSC_VER +#pragma warning ( disable : 4786 ) +#endif + +#include "itkObjectFactoryBase.h" +#include "mitkBaseData.h" +#include "MitkDiffusionImagingExports.h" + +namespace mitk +{ +//##Documentation +//## @brief Create instances of ConnectomicsNetwork objects using an object factory. +//## +//## @ingroup IO +class MitkDiffusionImaging_EXPORT ConnectomicsNetworkIOFactory : public itk::ObjectFactoryBase +{ +public: + /** Standard class typedefs. */ + typedef ConnectomicsNetworkIOFactory Self; + typedef itk::ObjectFactoryBase Superclass; + typedef itk::SmartPointer Pointer; + typedef itk::SmartPointer ConstPointer; + + /** Class methods used to interface with the registered factories. */ + virtual const char* GetITKSourceVersion(void) const; + virtual const char* GetDescription(void) const; + + /** Method for class instantiation. */ + itkFactorylessNewMacro(Self); + static ConnectomicsNetworkIOFactory* FactoryNew() { return new ConnectomicsNetworkIOFactory;} + /** Run-time type information (and related methods). */ + itkTypeMacro(ConnectomicsNetworkIOFactory, ObjectFactoryBase); + + /** Register one factory of this type */ + static void RegisterOneFactory(void) + { + ConnectomicsNetworkIOFactory::Pointer ConnectomicsNetworkIOFactory = ConnectomicsNetworkIOFactory::New(); + ObjectFactoryBase::RegisterFactory(ConnectomicsNetworkIOFactory); + } + +protected: + ConnectomicsNetworkIOFactory(); + ~ConnectomicsNetworkIOFactory(); + +private: + ConnectomicsNetworkIOFactory(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + +}; + + +} // end namespace mitk + +#endif // __MITK_CONNECTOMICS_NETWORK_IO_FACTORY_H_HEADER__ diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.cpp b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.cpp new file mode 100644 index 0000000000..a1d3fcd1e2 --- /dev/null +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.cpp @@ -0,0 +1,252 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2009-07-14 19:11:20 +0200 (Tue, 14 Jul 2009) $ +Version: $Revision: 18127 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkConnectomicsNetworkReader.h" +#include "mitkConnectomicsNetworkDefinitions.h" +#include +#include "itksys/SystemTools.hxx" +#include + +void mitk::ConnectomicsNetworkReader::GenerateData() +{ + MITK_INFO << "Reading connectomics network"; + if ( ( ! m_OutputCache ) ) + { + Superclass::SetNumberOfRequiredOutputs(0); + this->GenerateOutputInformation(); + } + + if (!m_OutputCache) + { + itkWarningMacro("Tree cache is empty!"); + } + + + Superclass::SetNumberOfRequiredOutputs(1); + Superclass::SetNthOutput(0, m_OutputCache.GetPointer()); +} + +void mitk::ConnectomicsNetworkReader::GenerateOutputInformation() +{ + m_OutputCache = OutputType::New(); + + std::string ext = itksys::SystemTools::GetFilenameLastExtension(m_FileName); + ext = itksys::SystemTools::LowerCase(ext); + + if ( m_FileName == "") + { + MITK_ERROR << "No file name specified."; + } + else if (ext == ".cnf") + { + try + { + TiXmlDocument doc( m_FileName ); + doc.LoadFile(); + + TiXmlHandle hDoc(&doc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement().Element(); + + // save this for later + hRoot = TiXmlHandle(pElem); + + pElem = hRoot.FirstChildElement(mitk::ConnectomicsNetworkDefinitions::XML_GEOMETRY).Element(); + + // read geometry + mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); + + // read origin + mitk::Point3D origin; + double temp = 0; + pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_X, &temp); + origin[0] = temp; + pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Y, &temp); + origin[1] = temp; + pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Z, &temp); + origin[2] = temp; + geometry->SetOrigin(origin); + + // read spacing + float spacing[3]; + pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_X, &temp); + spacing[0] = temp; + pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Y, &temp); + spacing[1] = temp; + pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Z, &temp); + spacing[2] = temp; + geometry->SetSpacing(spacing); + + // read transform + vtkMatrix4x4* m = vtkMatrix4x4::New(); + pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XX, &temp); + m->SetElement(0,0,temp); + pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XY, &temp); + m->SetElement(1,0,temp); + pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XZ, &temp); + m->SetElement(2,0,temp); + pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YX, &temp); + m->SetElement(0,1,temp); + pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YY, &temp); + m->SetElement(1,1,temp); + pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YZ, &temp); + m->SetElement(2,1,temp); + pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZX, &temp); + m->SetElement(0,2,temp); + pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZY, &temp); + m->SetElement(1,2,temp); + pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZZ, &temp); + m->SetElement(2,2,temp); + + m->SetElement(0,3,origin[0]); + m->SetElement(1,3,origin[1]); + m->SetElement(2,3,origin[2]); + m->SetElement(3,3,1); + geometry->SetIndexToWorldTransformByVtkMatrix(m); + + geometry->SetImageGeometry(true); + m_OutputCache->SetGeometry(geometry); + + // read network + std::map< int, mitk::ConnectomicsNetwork::VertexDescriptorType > idToVertexMap; + // read vertices + pElem = hRoot.FirstChildElement(mitk::ConnectomicsNetworkDefinitions::XML_VERTICES).Element(); + { + // walk through the vertices + TiXmlElement* vertexElement = pElem->FirstChildElement(); + + for( vertexElement; vertexElement; vertexElement=vertexElement->NextSiblingElement()) + { + std::vector< float > pos; + std::string label; + int vertexID(0); + + vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_X, &temp); + pos.push_back(temp); + vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Y, &temp); + pos.push_back(temp); + vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Z, &temp); + pos.push_back(temp); + vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_ID, &vertexID); + vertexElement->QueryStringAttribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_LABEL, &label); + + mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = m_OutputCache->AddVertex( vertexID ); + m_OutputCache->SetLabel( newVertex, label ); + m_OutputCache->SetCoordinates( newVertex, pos ); + + if ( idToVertexMap.count( vertexID ) > 0 ) + { + MITK_ERROR << "Aborting network creation, duplicate vertex ID in file."; + return; + } + idToVertexMap.insert( std::pair< int, mitk::ConnectomicsNetwork::VertexDescriptorType >( vertexID, newVertex) ); + } + } + + // read edges + pElem = hRoot.FirstChildElement(mitk::ConnectomicsNetworkDefinitions::XML_EDGES).Element(); + { + // walk through the edges + TiXmlElement* edgeElement = pElem->FirstChildElement(); + + for( edgeElement; edgeElement; edgeElement=edgeElement->NextSiblingElement()) + { + int edgeID(0), edgeSourceID(0), edgeTargetID(0), edgeWeight(0); + + edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_ID, &edgeID); + edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_SOURCE_ID, &edgeSourceID); + edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_TARGET_ID, &edgeTargetID); + edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_WEIGHT_ID, &edgeWeight); + + mitk::ConnectomicsNetwork::VertexDescriptorType source = idToVertexMap.find( edgeSourceID )->second; + mitk::ConnectomicsNetwork::VertexDescriptorType target = idToVertexMap.find( edgeTargetID )->second; + m_OutputCache->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight); + } + } + + MITK_INFO << "Network read"; + } + catch(...) + { + MITK_INFO << "Could not read file "; + } + } +} + +void mitk::ConnectomicsNetworkReader::Update() +{ + this->GenerateData(); +} + +const char* mitk::ConnectomicsNetworkReader::GetFileName() const +{ + return m_FileName.c_str(); +} + + +void mitk::ConnectomicsNetworkReader::SetFileName(const char* aFileName) +{ + m_FileName = aFileName; +} + + +const char* mitk::ConnectomicsNetworkReader::GetFilePrefix() const +{ + return m_FilePrefix.c_str(); +} + + +void mitk::ConnectomicsNetworkReader::SetFilePrefix(const char* aFilePrefix) +{ + m_FilePrefix = aFilePrefix; +} + + +const char* mitk::ConnectomicsNetworkReader::GetFilePattern() const +{ + return m_FilePattern.c_str(); +} + + +void mitk::ConnectomicsNetworkReader::SetFilePattern(const char* aFilePattern) +{ + m_FilePattern = aFilePattern; +} + + +bool mitk::ConnectomicsNetworkReader::CanReadFile( + const std::string filename, const std::string /*filePrefix*/, + const std::string /*filePattern*/) +{ + // First check the extension + if( filename == "" ) + { + return false; + } + std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename); + ext = itksys::SystemTools::LowerCase(ext); + + if (ext == ".cnf") + { + return true; + } + + return false; +} + diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.h b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.h new file mode 100644 index 0000000000..af6666984d --- /dev/null +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.h @@ -0,0 +1,72 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2009-07-14 19:11:20 +0200 (Tue, 14 Jul 2009) $ +Version: $Revision: 18127 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef __mitkConnectomicsNetworkReader_h +#define __mitkConnectomicsNetworkReader_h + +#include "mitkCommon.h" +#include "mitkFileReader.h" +#include "mitkConnectomicsNetwork.h" + +namespace mitk +{ + + /** \brief The reader for connectomics network files (.cnf) + */ + + class ConnectomicsNetworkReader : public FileReader, public BaseProcess + { + public: + + + typedef mitk::ConnectomicsNetwork OutputType; + + mitkClassMacro( ConnectomicsNetworkReader, BaseProcess ); + itkNewMacro(Self); + + const char* GetFileName() const; + void SetFileName(const char* aFileName); + const char* GetFilePrefix() const; + void SetFilePrefix(const char* aFilePrefix); + const char* GetFilePattern() const; + void SetFilePattern(const char* aFilePattern); + + static bool CanReadFile(const std::string filename, const std::string filePrefix, const std::string filePattern); + + virtual void Update(); + + + + protected: + + /** Does the real work. */ + virtual void GenerateData(); + virtual void GenerateOutputInformation(); + + OutputType::Pointer m_OutputCache; + + std::string m_FileName; + std::string m_FilePrefix; + std::string m_FilePattern; + + private: + void operator=(const Self&); //purposely not implemented + }; + +} //namespace MITK + +#endif // __mitkConnectomicsNetworkReader_h diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkSerializer.cpp b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkSerializer.cpp new file mode 100644 index 0000000000..95bf4b0277 --- /dev/null +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkSerializer.cpp @@ -0,0 +1,75 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision: 1.12 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkConnectomicsNetworkSerializer.h" +#include "mitkConnectomicsNetwork.h" +#include "mitkConnectomicsNetworkWriter.h" + +#include + + +MITK_REGISTER_SERIALIZER(ConnectomicsNetworkSerializer) + + +mitk::ConnectomicsNetworkSerializer::ConnectomicsNetworkSerializer() +{ +} + + +mitk::ConnectomicsNetworkSerializer::~ConnectomicsNetworkSerializer() +{ +} + + +std::string mitk::ConnectomicsNetworkSerializer::Serialize() +{ + const ConnectomicsNetwork* conNet = dynamic_cast( m_Data.GetPointer() ); + if (conNet == NULL) + { + MITK_ERROR << " Object at " << (const void*) this->m_Data + << " is not an mitk::ConnectomicsNetwork. Cannot serialize as ConnectomicsNetwork."; + return ""; + } + + std::string filename( this->GetUniqueFilenameInWorkingDirectory() ); + filename += "_"; + filename += m_FilenameHint; + filename += ".cnf"; + + std::string fullname(m_WorkingDirectory); + fullname += "/"; + fullname += itksys::SystemTools::ConvertToOutputPath(filename.c_str()); + + try + { + ConnectomicsNetworkWriter::Pointer writer = ConnectomicsNetworkWriter::New(); + writer->SetFileName(fullname); + writer->SetInputConnectomicsNetwork(const_cast(conNet)); + writer->Write(); + } + catch (std::exception& e) + { + MITK_ERROR << " Error serializing object at " << (const void*) this->m_Data + << " to " + << fullname + << ": " + << e.what(); + return ""; + } + return filename; +} + diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkSerializer.h b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkSerializer.h new file mode 100644 index 0000000000..9c18cefe6f --- /dev/null +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkSerializer.h @@ -0,0 +1,40 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision: 1.12 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef mitkConnectomicsNetworkSerializer_h_included +#define mitkConnectomicsNetworkSerializer_h_included + +#include "MitkDiffusionImagingExports.h" +#include "mitkBaseDataSerializer.h" + +namespace mitk +{ +/** + \brief Serializes mitk::Surface for mitk::SceneIO +*/ +class MitkDiffusionImaging_EXPORT ConnectomicsNetworkSerializer : public BaseDataSerializer +{ + public: + mitkClassMacro( ConnectomicsNetworkSerializer, BaseDataSerializer ); + itkNewMacro(Self); + virtual std::string Serialize(); + protected: + ConnectomicsNetworkSerializer(); + virtual ~ConnectomicsNetworkSerializer(); +}; +} // namespace +#endif diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriter.cpp b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriter.cpp new file mode 100644 index 0000000000..c183a3d596 --- /dev/null +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriter.cpp @@ -0,0 +1,158 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2008-12-10 18:05:13 +0100 (Mi, 10 Dez 2008) $ +Version: $Revision: 15922 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkConnectomicsNetworkWriter.h" +#include "mitkConnectomicsNetworkDefinitions.h" +#include +#include "itksys/SystemTools.hxx" + +mitk::ConnectomicsNetworkWriter::ConnectomicsNetworkWriter() +: m_FileName(""), m_FilePrefix(""), m_FilePattern(""), m_Success(false) +{ + this->SetNumberOfRequiredInputs( 1 ); +} + + +mitk::ConnectomicsNetworkWriter::~ConnectomicsNetworkWriter() +{} + + +void mitk::ConnectomicsNetworkWriter::GenerateData() +{ + MITK_INFO << "Writing connectomics network"; + m_Success = false; + InputType* input = this->GetInput(); + if (input == NULL) + { + itkWarningMacro(<<"Sorry, input to ConnectomicsNetworkWriter is NULL!"); + return; + } + if ( m_FileName == "" ) + { + itkWarningMacro( << "Sorry, filename has not been set!" ); + return ; + } + + std::string ext = itksys::SystemTools::GetFilenameLastExtension(m_FileName); + ext = itksys::SystemTools::LowerCase(ext); + + if (ext == ".cnf") + { + // Get geometry of the network + mitk::Geometry3D* geometry = input->GetGeometry(); + + // Create XML document + TiXmlDocument documentXML; + { // begin document + TiXmlDeclaration* declXML = new TiXmlDeclaration( "1.0", "", "" ); // TODO what to write here? encoding? etc.... + documentXML.LinkEndChild( declXML ); + + TiXmlElement* mainXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_CONNECTOMICS_FILE); + mainXML->SetAttribute(mitk::ConnectomicsNetworkDefinitions::XML_FILE_VERSION, mitk::ConnectomicsNetworkDefinitions::VERSION_STRING); + documentXML.LinkEndChild(mainXML); + + TiXmlElement* geometryXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_GEOMETRY); + { // begin geometry + geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XX, geometry->GetMatrixColumn(0)[0]); + geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XY, geometry->GetMatrixColumn(0)[1]); + geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XZ, geometry->GetMatrixColumn(0)[2]); + geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YX, geometry->GetMatrixColumn(1)[0]); + geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YY, geometry->GetMatrixColumn(1)[1]); + geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YZ, geometry->GetMatrixColumn(1)[2]); + geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZX, geometry->GetMatrixColumn(2)[0]); + geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZY, geometry->GetMatrixColumn(2)[1]); + geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZZ, geometry->GetMatrixColumn(2)[2]); + + geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_X, geometry->GetOrigin()[0]); + geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Y, geometry->GetOrigin()[1]); + geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Z, geometry->GetOrigin()[2]); + + geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_X, geometry->GetSpacing()[0]); + geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Y, geometry->GetSpacing()[1]); + geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Z, geometry->GetSpacing()[2]); + + } // end geometry + mainXML->LinkEndChild(geometryXML); + + TiXmlElement* verticesXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_VERTICES); + { // begin vertices section + VertexVectorType vertexVector = this->GetInput()->GetVectorOfAllNodes(); + for( int index = 0; index < vertexVector.size(); index++ ) + { + // not localized as of yet TODO + TiXmlElement* vertexXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX ); + vertexXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_ID , vertexVector[ index ].id ); + vertexXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_LABEL , vertexVector[ index ].label ); + vertexXML->SetDoubleAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_X , vertexVector[ index ].coordinates[0] ); + vertexXML->SetDoubleAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Y , vertexVector[ index ].coordinates[1] ); + vertexXML->SetDoubleAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Z , vertexVector[ index ].coordinates[2] ); + verticesXML->LinkEndChild(vertexXML); + } + } // end vertices section + mainXML->LinkEndChild(verticesXML); + + TiXmlElement* edgesXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_EDGES); + { // begin edges section + EdgeVectorType edgeVector = this->GetInput()->GetVectorOfAllEdges(); + for( int index = 0; index < edgeVector.size(); index++ ) + { + TiXmlElement* edgeXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_EDGE ); + edgeXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_ID , index ); + edgeXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_SOURCE_ID , edgeVector[ index ].second.sourceId ); + edgeXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_TARGET_ID , edgeVector[ index ].second.targetId ); + edgeXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_WEIGHT_ID , edgeVector[ index ].second.weight ); + edgesXML->LinkEndChild(edgeXML); + } + } // end edges section + mainXML->LinkEndChild(edgesXML); + + } // end document + documentXML.SaveFile( m_FileName ); + + m_Success = true; + + MITK_INFO << "Connectomics network written"; + + } +} + + +void mitk::ConnectomicsNetworkWriter::SetInputConnectomicsNetwork( InputType* conNetwork ) +{ + this->ProcessObject::SetNthInput( 0, conNetwork ); +} + + +mitk::ConnectomicsNetwork* mitk::ConnectomicsNetworkWriter::GetInput() +{ + if ( this->GetNumberOfInputs() < 1 ) + { + return NULL; + } + else + { + return dynamic_cast ( this->ProcessObject::GetInput( 0 ) ); + } +} + + +std::vector mitk::ConnectomicsNetworkWriter::GetPossibleFileExtensions() +{ + std::vector possibleFileExtensions; + possibleFileExtensions.push_back(".cnf"); + return possibleFileExtensions; +} diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriter.h b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriter.h new file mode 100644 index 0000000000..dba351d031 --- /dev/null +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriter.h @@ -0,0 +1,157 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2008-08-27 17:18:46 +0200 (Mi, 27 Aug 2008) $ +Version: $Revision: 15096 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef __mitkConnectomicsNetworkWriter_h +#define __mitkConnectomicsNetworkWriter_h + +#include +#include +#include "mitkConnectomicsNetwork.h" +#include + + +namespace mitk +{ + + /** + * Writes connectomics networks to a file + * @ingroup Process + */ + class ConnectomicsNetworkWriter : public mitk::FileWriterWithInformation + { + public: + + mitkClassMacro( ConnectomicsNetworkWriter, mitk::FileWriterWithInformation ); + + //mitkWriterMacro; + + virtual void Write() + { + if ( this->GetInput() == NULL ) + { + itkExceptionMacro(<<"Write:Please specify an input!"); + return; + } + /* Fill in image information.*/ + this->UpdateOutputInformation(); + (*(this->GetInputs().begin()))->SetRequestedRegionToLargestPossibleRegion(); + this->PropagateRequestedRegion(NULL); + this->UpdateOutputData(NULL); + } + + virtual void Update() + { + Write(); + } + + itkNewMacro( Self ); + + typedef mitk::ConnectomicsNetwork InputType; + typedef std::vector< std::pair< std::pair< + mitk::ConnectomicsNetwork::NetworkNode, mitk::ConnectomicsNetwork::NetworkNode > + , mitk::ConnectomicsNetwork::NetworkEdge > > EdgeVectorType; + typedef std::vector< mitk::ConnectomicsNetwork::NetworkNode > VertexVectorType; + + /** + * Sets the filename of the file to write. + * @param FileName the name of the file to write. + */ + itkSetStringMacro( FileName ); + + /** + * @returns the name of the file to be written to disk. + */ + itkGetStringMacro( FileName ); + + /** + * @warning multiple write not (yet) supported + */ + itkSetStringMacro( FilePrefix ); + + /** + * @warning multiple write not (yet) supported + */ + itkGetStringMacro( FilePrefix ); + + /** + * @warning multiple write not (yet) supported + */ + itkSetStringMacro( FilePattern ); + + /** + * @warning multiple write not (yet) supported + */ + itkGetStringMacro( FilePattern ); + + /** + * Sets the input object for the filter. + * @param input the diffusion volumes to write to file. + */ + void SetInputConnectomicsNetwork( InputType* input ); + + /** + * @returns the 0'th input object of the filter. + */ + InputType* GetInput(); + + /** + * Returns false if an error happened during writing + */ + itkGetMacro( Success, bool ); + + /** + * @return possible file extensions for the data type associated with the writer + */ + virtual std::vector GetPossibleFileExtensions(); + + // FileWriterWithInformation methods + virtual const char * GetDefaultFilename() { return "ConnectomicsNetwork.cnf"; } + virtual const char * GetFileDialogPattern() { return "ConnectomicsNetwork (*.cnf)"; } + virtual const char * GetDefaultExtension() { return ".cnf"; } + virtual bool CanWriteBaseDataType(BaseData::Pointer data) { + return (dynamic_cast(data.GetPointer()) != NULL); } + + virtual void DoWrite(BaseData::Pointer data) { + if (CanWriteBaseDataType(data)) { + this->SetInputConnectomicsNetwork(dynamic_cast(data.GetPointer())); + this->Update(); + } + } + + + protected: + + ConnectomicsNetworkWriter(); + + virtual ~ConnectomicsNetworkWriter(); + + virtual void GenerateData(); + + std::string m_FileName; + + std::string m_FilePrefix; + + std::string m_FilePattern; + + bool m_Success; + + }; + + +} // end of namespace mitk + +#endif //__mitkConnectomicsNetworkWriter_h diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriterFactory.cpp b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriterFactory.cpp new file mode 100644 index 0000000000..182fe975eb --- /dev/null +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriterFactory.cpp @@ -0,0 +1,76 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2007-12-11 14:46:19 +0100 (Di, 11 Dez 2007) $ +Version: $Revision: 11215 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkConnectomicsNetworkWriterFactory.h" + +#include "itkCreateObjectFunction.h" +#include "itkVersion.h" + +#include "mitkConnectomicsNetworkWriter.h" + +namespace mitk +{ + +template +class CreateConnectomicsNetworkWriter : public itk::CreateObjectFunctionBase +{ +public: + + /** Standard class typedefs. */ + typedef CreateConnectomicsNetworkWriter Self; + typedef itk::SmartPointer Pointer; + + /** Methods from itk:LightObject. */ + itkFactorylessNewMacro(Self); + LightObject::Pointer CreateObject() { typename T::Pointer p = T::New(); + p->Register(); + return p.GetPointer(); + } + +protected: + CreateConnectomicsNetworkWriter() {} + ~CreateConnectomicsNetworkWriter() {} + +private: + CreateConnectomicsNetworkWriter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented +}; + +ConnectomicsNetworkWriterFactory::ConnectomicsNetworkWriterFactory() +{ + this->RegisterOverride("IOWriter", + "ConnectomicsNetworkWriter", + "ConnectomicsNetwork Writer", + 1, + mitk::CreateConnectomicsNetworkWriter< mitk::ConnectomicsNetworkWriter >::New()); +} + +ConnectomicsNetworkWriterFactory::~ConnectomicsNetworkWriterFactory() +{ +} + +const char* ConnectomicsNetworkWriterFactory::GetITKSourceVersion() const +{ + return ITK_SOURCE_VERSION; +} + +const char* ConnectomicsNetworkWriterFactory::GetDescription() const +{ + return "ConnectomicsNetworkWriterFactory"; +} + +} // end namespace mitk diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriterFactory.h b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriterFactory.h new file mode 100644 index 0000000000..a1e6fc19fc --- /dev/null +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriterFactory.h @@ -0,0 +1,68 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2009-05-13 18:06:46 +0200 (Mi, 13 Mai 2009) $ +Version: $Revision: 11215 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef ConnectomicsNetwork_WRITERFACTORY_H_HEADER_INCLUDED +#define ConnectomicsNetwork_WRITERFACTORY_H_HEADER_INCLUDED + +#include "itkObjectFactoryBase.h" +#include "mitkBaseData.h" +#include "MitkDiffusionImagingExports.h" + +namespace mitk +{ + +class MitkDiffusionImaging_EXPORT ConnectomicsNetworkWriterFactory : public itk::ObjectFactoryBase +{ +public: + + mitkClassMacro( mitk::ConnectomicsNetworkWriterFactory, itk::ObjectFactoryBase ) + + /** Class methods used to interface with the registered factories. */ + virtual const char* GetITKSourceVersion(void) const; + virtual const char* GetDescription(void) const; + + /** Method for class instantiation. */ + itkFactorylessNewMacro(Self); + + /** Register one factory of this type */ + static void RegisterOneFactory(void) + { + static bool IsRegistered = false; + if ( !IsRegistered ) + { + ConnectomicsNetworkWriterFactory::Pointer cnfWriterFactory = ConnectomicsNetworkWriterFactory::New(); + ObjectFactoryBase::RegisterFactory( cnfWriterFactory ); + IsRegistered = true; + } + } + +protected: + ConnectomicsNetworkWriterFactory(); + ~ConnectomicsNetworkWriterFactory(); + +private: + ConnectomicsNetworkWriterFactory(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + +}; + +} // end namespace mitk + +#endif // ConnectomicsNetwork_WRITERFACTORY_H_HEADER_INCLUDED + + + diff --git a/Modules/DiffusionImaging/IODataStructures/mitkDiffusionImagingObjectFactory.cpp b/Modules/DiffusionImaging/IODataStructures/mitkDiffusionImagingObjectFactory.cpp index 4fd83614f6..23bd820e97 100644 --- a/Modules/DiffusionImaging/IODataStructures/mitkDiffusionImagingObjectFactory.cpp +++ b/Modules/DiffusionImaging/IODataStructures/mitkDiffusionImagingObjectFactory.cpp @@ -1,374 +1,396 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-06-18 15:59:04 +0200 (Do, 18 Jun 2009) $ Version: $Revision: 16916 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkDiffusionImagingObjectFactory.h" #include "mitkProperties.h" #include "mitkBaseRenderer.h" #include "mitkDataNode.h" #include "mitkNrrdDiffusionImageIOFactory.h" #include "mitkNrrdDiffusionImageWriterFactory.h" #include "mitkNrrdDiffusionImageWriter.h" #include "mitkDiffusionImage.h" #include "mitkNrrdQBallImageIOFactory.h" #include "mitkNrrdQBallImageWriterFactory.h" #include "mitkNrrdQBallImageWriter.h" #include "mitkNrrdTensorImageIOFactory.h" #include "mitkNrrdTensorImageWriterFactory.h" #include "mitkNrrdTensorImageWriter.h" #include "mitkCompositeMapper.h" #include "mitkDiffusionImageMapper.h" #include "mitkGPUVolumeMapper3D.h" #include "mitkVolumeDataVtkMapper3D.h" #include "mitkTbssImageMapper.h" //modernized fiberbundle datastrucutre #include "mitkFiberBundleX.h" #include "mitkFiberBundleXIOFactory.h" #include "mitkFiberBundleXWriterFactory.h" #include "mitkFiberBundleXWriter.h" #include "mitkFiberBundleXMapper3D.h" #include "mitkFiberBundleXMapper2D.h" #include "mitkFiberBundleXThreadMonitorMapper3D.h" #include "mitkFiberBundleXThreadMonitor.h" #include "mitkNrrdTbssImageIOFactory.h" #include "mitkNrrdTbssImageWriterFactory.h" #include "mitkNrrdTbssImageWriter.h" #include "mitkNrrdTbssRoiImageIOFactory.h" #include "mitkNrrdTbssRoiImageWriterFactory.h" #include "mitkNrrdTbssRoiImageWriter.h" #include "mitkPlanarCircleMapper3D.h" #include "mitkPlanarPolygonMapper3D.h" - +#include "mitkConnectomicsNetwork.h" +#include "mitkConnectomicsNetworkIOFactory.h" +#include "mitkConnectomicsNetworkWriter.h" +#include "mitkConnectomicsNetworkWriterFactory.h" +#include "mitkConnectomicsNetworkMapper3D.h" typedef short DiffusionPixelType; typedef char TbssRoiPixelType; typedef float TbssPixelType; typedef int TbssGradientPixelType; typedef mitk::DiffusionImage DiffusionImageShort; typedef std::multimap MultimapType; mitk::DiffusionImagingObjectFactory::DiffusionImagingObjectFactory(bool /*registerSelf*/) :CoreObjectFactoryBase() { static bool alreadyDone = false; if (!alreadyDone) { MITK_DEBUG << "DiffusionImagingObjectFactory c'tor" << std::endl; RegisterIOFactories(); mitk::NrrdDiffusionImageIOFactory::RegisterOneFactory(); mitk::NrrdQBallImageIOFactory::RegisterOneFactory(); mitk::NrrdTensorImageIOFactory::RegisterOneFactory(); mitk::NrrdTbssImageIOFactory::RegisterOneFactory(); mitk::NrrdTbssRoiImageIOFactory::RegisterOneFactory(); mitk::FiberBundleXIOFactory::RegisterOneFactory(); //modernized + mitk::ConnectomicsNetworkIOFactory::RegisterOneFactory(); mitk::NrrdDiffusionImageWriterFactory::RegisterOneFactory(); mitk::NrrdQBallImageWriterFactory::RegisterOneFactory(); mitk::NrrdTensorImageWriterFactory::RegisterOneFactory(); mitk::NrrdTbssImageWriterFactory::RegisterOneFactory(); mitk::NrrdTbssRoiImageWriterFactory::RegisterOneFactory(); mitk::FiberBundleXWriterFactory::RegisterOneFactory();//modernized + mitk::ConnectomicsNetworkWriterFactory::RegisterOneFactory(); m_FileWriters.push_back( NrrdDiffusionImageWriter::New().GetPointer() ); m_FileWriters.push_back( NrrdQBallImageWriter::New().GetPointer() ); m_FileWriters.push_back( NrrdTensorImageWriter::New().GetPointer() ); m_FileWriters.push_back( NrrdTbssImageWriter::New().GetPointer() ); m_FileWriters.push_back( NrrdTbssRoiImageWriter::New().GetPointer() ); m_FileWriters.push_back( mitk::FiberBundleXWriter::New().GetPointer() );//modernized + m_FileWriters.push_back( mitk::ConnectomicsNetworkWriter::New().GetPointer() ); mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory(this); CreateFileExtensionsMap(); alreadyDone = true; } } mitk::Mapper::Pointer mitk::DiffusionImagingObjectFactory::CreateMapper(mitk::DataNode* node, MapperSlotId id) { mitk::Mapper::Pointer newMapper=NULL; if ( id == mitk::BaseRenderer::Standard2D ) { std::string classname("QBallImage"); if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::CompositeMapper::New(); newMapper->SetDataNode(node); node->SetMapper(3, ((CompositeMapper*)newMapper.GetPointer())->GetImageMapper()); } classname = "TensorImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::CompositeMapper::New(); newMapper->SetDataNode(node); node->SetMapper(3, ((CompositeMapper*)newMapper.GetPointer())->GetImageMapper()); } classname = "DiffusionImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::DiffusionImageMapper::New(); newMapper->SetDataNode(node); } classname = "TbssRoiImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::ImageVtkMapper2D::New(); newMapper->SetDataNode(node); } classname = "FiberBundleX"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::FiberBundleXMapper2D::New(); newMapper->SetDataNode(node); } classname = "TbssImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::TbssImageMapper::New(); newMapper->SetDataNode(node); } } else if ( id == mitk::BaseRenderer::Standard3D ) { std::string classname("QBallImage"); if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::GPUVolumeMapper3D::New(); newMapper->SetDataNode(node); } classname = "TensorImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::GPUVolumeMapper3D::New(); newMapper->SetDataNode(node); } classname = "DiffusionImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::GPUVolumeMapper3D::New(); newMapper->SetDataNode(node); } classname = "FiberBundleX"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::FiberBundleXMapper3D::New(); newMapper->SetDataNode(node); } classname = "FiberBundleXThreadMonitor"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::FiberBundleXThreadMonitorMapper3D::New(); newMapper->SetDataNode(node); } classname = "TbssRoiImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::VolumeDataVtkMapper3D::New(); newMapper->SetDataNode(node); } classname = "TbssImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::TbssImageMapper::New(); newMapper->SetDataNode(node); } classname = "PlanarCircle"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::PlanarCircleMapper3D::New(); newMapper->SetDataNode(node); } classname = "PlanarPolygon"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::PlanarPolygonMapper3D::New(); newMapper->SetDataNode(node); } + + classname = "ConnectomicsNetwork"; + if (node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) + { + newMapper = mitk::ConnectomicsNetworkMapper3D::New(); + newMapper->SetDataNode(node); + } } return newMapper; } void mitk::DiffusionImagingObjectFactory::SetDefaultProperties(mitk::DataNode* node) { std::string classname = "QBallImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::CompositeMapper::SetDefaultProperties(node); mitk::GPUVolumeMapper3D::SetDefaultProperties(node); } classname = "TensorImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::CompositeMapper::SetDefaultProperties(node); mitk::GPUVolumeMapper3D::SetDefaultProperties(node); } classname = "DiffusionImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::DiffusionImageMapper::SetDefaultProperties(node); mitk::GPUVolumeMapper3D::SetDefaultProperties(node); } classname = "FiberBundleX"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::FiberBundleXMapper3D::SetDefaultProperties(node); mitk::FiberBundleXMapper2D::SetDefaultProperties(node); } classname = "FiberBundleXThreadMonitor"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::FiberBundleXThreadMonitorMapper3D::SetDefaultProperties(node); } classname = "TbssRoiImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::ImageVtkMapper2D::SetDefaultProperties(node); mitk::VolumeDataVtkMapper3D::SetDefaultProperties(node); } classname = "TbssImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::TbssImageMapper::SetDefaultProperties(node); mitk::GPUVolumeMapper3D::SetDefaultProperties(node); } classname = "PlanarCircle"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::PlanarCircleMapper3D::SetDefaultProperties(node); } classname = "PlanarPolygon"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::PlanarPolygonMapper3D::SetDefaultProperties(node); } + + classname = "ConnectomicsNetwork"; + if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) + { + mitk::ConnectomicsNetworkMapper3D::SetDefaultProperties(node); + } } const char* mitk::DiffusionImagingObjectFactory::GetFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_FileExtensionsMap, fileExtension); return fileExtension.c_str(); }; mitk::CoreObjectFactoryBase::MultimapType mitk::DiffusionImagingObjectFactory::GetFileExtensionsMap() { return m_FileExtensionsMap; } const char* mitk::DiffusionImagingObjectFactory::GetSaveFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_SaveFileExtensionsMap, fileExtension); return fileExtension.c_str(); }; mitk::CoreObjectFactoryBase::MultimapType mitk::DiffusionImagingObjectFactory::GetSaveFileExtensionsMap() { return m_SaveFileExtensionsMap; } void mitk::DiffusionImagingObjectFactory::CreateFileExtensionsMap() { m_FileExtensionsMap.insert(std::pair("*.dwi", "Diffusion Weighted Images")); m_FileExtensionsMap.insert(std::pair("*.hdwi", "Diffusion Weighted Images")); m_FileExtensionsMap.insert(std::pair("*.nii", "Diffusion Weighted Images for FSL")); m_FileExtensionsMap.insert(std::pair("*.fsl", "Diffusion Weighted Images for FSL")); m_FileExtensionsMap.insert(std::pair("*.fslgz", "Diffusion Weighted Images for FSL")); m_FileExtensionsMap.insert(std::pair("*.qbi", "Q-Ball Images")); m_FileExtensionsMap.insert(std::pair("*.hqbi", "Q-Ball Images")); m_FileExtensionsMap.insert(std::pair("*.dti", "Tensor Images")); m_FileExtensionsMap.insert(std::pair("*.hdti", "Tensor Images")); m_FileExtensionsMap.insert(std::pair("*.fib", "Fiber Bundle")); m_FileExtensionsMap.insert(std::pair("*.vtk", "Fiber Bundle")); m_FileExtensionsMap.insert(std::pair("*.tbss", "TBSS data")); m_FileExtensionsMap.insert(std::pair("*.pf", "Planar Figure File")); m_FileExtensionsMap.insert(std::pair("*.roi", "TBSS ROI data")); + m_FileExtensionsMap.insert(std::pair("*.cnf", "Connectomics Network File")); m_SaveFileExtensionsMap.insert(std::pair("*.dwi", "Diffusion Weighted Images")); m_SaveFileExtensionsMap.insert(std::pair("*.hdwi", "Diffusion Weighted Images")); m_SaveFileExtensionsMap.insert(std::pair("*.nii", "Diffusion Weighted Images for FSL")); m_SaveFileExtensionsMap.insert(std::pair("*.fsl", "Diffusion Weighted Images for FSL")); m_SaveFileExtensionsMap.insert(std::pair("*.fslgz", "Diffusion Weighted Images for FSL")); m_SaveFileExtensionsMap.insert(std::pair("*.qbi", "Q-Ball Images")); m_SaveFileExtensionsMap.insert(std::pair("*.hqbi", "Q-Ball Images")); m_SaveFileExtensionsMap.insert(std::pair("*.dti", "Tensor Images")); m_SaveFileExtensionsMap.insert(std::pair("*.hdti", "Tensor Images")); m_SaveFileExtensionsMap.insert(std::pair("*.fib", "Fiber Bundle")); m_SaveFileExtensionsMap.insert(std::pair("*.vtk", "Fiber Bundle")); m_SaveFileExtensionsMap.insert(std::pair("*.tbss", "TBSS data")); m_SaveFileExtensionsMap.insert(std::pair("*.pf", "Planar Figure File")); m_SaveFileExtensionsMap.insert(std::pair("*.roi", "TBSS ROI data")); + m_SaveFileExtensionsMap.insert(std::pair("*.cnf", "Connectomics Network File")); } void mitk::DiffusionImagingObjectFactory::RegisterIOFactories() { } void RegisterDiffusionImagingObjectFactory() { static bool oneDiffusionImagingObjectFactoryRegistered = false; if ( ! oneDiffusionImagingObjectFactoryRegistered ) { MITK_DEBUG << "Registering DiffusionImagingObjectFactory..." << std::endl; mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory(mitk::DiffusionImagingObjectFactory::New()); oneDiffusionImagingObjectFactoryRegistered = true; } } diff --git a/Modules/DiffusionImaging/Rendering/mitkConnectomicsNetworkMapper3D.cpp b/Modules/DiffusionImaging/Rendering/mitkConnectomicsNetworkMapper3D.cpp new file mode 100644 index 0000000000..45ee4656e3 --- /dev/null +++ b/Modules/DiffusionImaging/Rendering/mitkConnectomicsNetworkMapper3D.cpp @@ -0,0 +1,181 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2009-05-12 19:56:03 +0200 (Di, 12 Mai 2009) $ +Version: $Revision: 17179 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkConnectomicsNetworkMapper3D.h" + +mitk::ConnectomicsNetworkMapper3D::ConnectomicsNetworkMapper3D() +{ + //TODO: implement + m_NetworkAssembly = vtkPropAssembly::New(); + +} + +mitk::ConnectomicsNetworkMapper3D:: ~ConnectomicsNetworkMapper3D() +{ + //TODO: implement + m_NetworkAssembly->Delete(); + +} + +void mitk::ConnectomicsNetworkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer* renderer) +{ + //TODO: implement + + if( this->GetInput() == NULL ) + { + return; + } + if( this->GetInput()->GetIsModified( ) ) + { + GenerateData(); + } +} + +void mitk::ConnectomicsNetworkMapper3D::GenerateData() +{ + //TODO: implement + + // Here is the part where a graph is given and converted to points and connections between points... + std::vector< mitk::ConnectomicsNetwork::NetworkNode > vectorOfNodes = this->GetInput()->GetVectorOfAllNodes(); + std::vector< std::pair< + std::pair< mitk::ConnectomicsNetwork::NetworkNode, mitk::ConnectomicsNetwork::NetworkNode > + , mitk::ConnectomicsNetwork::NetworkEdge > > vectorOfEdges = this->GetInput()->GetVectorOfAllEdges(); + + mitk::Point3D tempWorldPoint, tempCNFGeometryPoint; + + //////////////////////Create Spheres///////////////////////// + for(unsigned int i = 0; i < vectorOfNodes.size(); i++) + { + vtkSmartPointer sphereSource = + vtkSmartPointer::New(); + + for(unsigned int dimension = 0; dimension < 3; dimension++) + { + tempCNFGeometryPoint.SetElement( dimension , vectorOfNodes[i].coordinates[dimension] ); + } + + this->GetData()->GetGeometry()->IndexToWorld( tempCNFGeometryPoint, tempWorldPoint ); + + sphereSource->SetCenter( tempWorldPoint[0] , tempWorldPoint[1], tempWorldPoint[2] ); + sphereSource->SetRadius(1.0); + + vtkSmartPointer mapper = + vtkSmartPointer::New(); + mapper->SetInput(sphereSource->GetOutput()); + + vtkSmartPointer actor = + vtkSmartPointer::New(); + actor->SetMapper(mapper); + + m_NetworkAssembly->AddPart(actor); + } + + //////////////////////Create Tubes///////////////////////// + + for(unsigned int i = 0; i < vectorOfEdges.size(); i++) + { + + vtkSmartPointer lineSource = + vtkSmartPointer::New(); + + for(unsigned int dimension = 0; dimension < 3; dimension++) + { + tempCNFGeometryPoint[ dimension ] = vectorOfEdges[i].first.first.coordinates[dimension]; + } + + this->GetData()->GetGeometry()->IndexToWorld( tempCNFGeometryPoint, tempWorldPoint ); + + lineSource->SetPoint1(tempWorldPoint[0], tempWorldPoint[1],tempWorldPoint[2] ); + + for(unsigned int dimension = 0; dimension < 3; dimension++) + { + tempCNFGeometryPoint[ dimension ] = vectorOfEdges[i].first.second.coordinates[dimension]; + } + + this->GetData()->GetGeometry()->IndexToWorld( tempCNFGeometryPoint, tempWorldPoint ); + + lineSource->SetPoint2(tempWorldPoint[0], tempWorldPoint[1], tempWorldPoint[2] ); + + vtkSmartPointer tubes = vtkSmartPointer::New(); + tubes->SetInput( lineSource->GetOutput() ); + tubes->SetNumberOfSides( 12 ); + double radiusFactor = 1.0 + ((double) vectorOfEdges[i].second.weight) / 10.0 ; + tubes->SetRadius( std::log10( radiusFactor ) ); + + vtkSmartPointer mapper2 = + vtkSmartPointer::New(); + mapper2->SetInput( tubes->GetOutput() ); + + vtkSmartPointer actor = + vtkSmartPointer::New(); + actor->SetMapper(mapper2); + + double maxWeight = (double) this->GetInput()->GetMaximumWeight(); + double colourFactor = vectorOfEdges[i].second.weight / maxWeight; + actor->GetProperty()->SetColor( colourFactor, colourFactor, colourFactor); + + + m_NetworkAssembly->AddPart(actor); + + } + + (static_cast ( GetData() ) )->SetIsModified( false ); + + //this->UpdateVtkObjects(); + + +} + +const mitk::ConnectomicsNetwork* mitk::ConnectomicsNetworkMapper3D::GetInput() +{ + + return static_cast ( GetData() ); +} + + +void mitk::ConnectomicsNetworkMapper3D::SetDefaultProperties(DataNode* node, BaseRenderer* renderer , bool overwrite) +{ + //TODO: implement + + + // hand it to the superclass for base default properties + Superclass::SetDefaultProperties(node, renderer, overwrite); +} + +void mitk::ConnectomicsNetworkMapper3D::ApplyProperties(mitk::BaseRenderer* renderer) +{ + //TODO: implement + +} + +void mitk::ConnectomicsNetworkMapper3D::SetVtkMapperImmediateModeRendering(vtkMapper *mapper) +{ + //TODO: implement + +} + +void mitk::ConnectomicsNetworkMapper3D::UpdateVtkObjects() +{ + //TODO: implement +} + +vtkProp* mitk::ConnectomicsNetworkMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) +{ + + return m_NetworkAssembly; + +} \ No newline at end of file diff --git a/Modules/DiffusionImaging/Rendering/mitkConnectomicsNetworkMapper3D.h b/Modules/DiffusionImaging/Rendering/mitkConnectomicsNetworkMapper3D.h new file mode 100644 index 0000000000..ff68ca0f30 --- /dev/null +++ b/Modules/DiffusionImaging/Rendering/mitkConnectomicsNetworkMapper3D.h @@ -0,0 +1,107 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2009-05-12 19:56:03 +0200 (Di, 12 Mai 2009) $ +Version: $Revision: 17179 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#ifndef ConnectomicsNetworkMapper3D_H_HEADER_INCLUDED +#define ConnectomicsNetworkMapper3D_H_HEADER_INCLUDED + +// VTK includes + +#include +#include "vtkPropAssembly.h" + +// MITK includes +// base class +#include "mitkVtkMapper3D.h" + +// data type + +#include "mitkConnectomicsNetwork.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include "MitkDiffusionImagingExports.h" + +namespace mitk { + + //##Documentation + //## @brief Mapper for Networks + //## @ingroup Mapper +// template + class MitkDiffusionImaging_EXPORT ConnectomicsNetworkMapper3D : public VtkMapper3D + { + public: + + mitkClassMacro(ConnectomicsNetworkMapper3D, VtkMapper3D); + itkNewMacro(Self); + + virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer); //looks like deprecated.. should be replaced bz GetViewProp() + static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false ); + + virtual void ApplyProperties(mitk::BaseRenderer* renderer); + static void SetVtkMapperImmediateModeRendering(vtkMapper *mapper); + + virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); + virtual void GenerateData(); + + virtual const mitk::ConnectomicsNetwork* GetInput(); + + + protected: + + ConnectomicsNetworkMapper3D(); + virtual ~ConnectomicsNetworkMapper3D(); + + void UpdateVtkObjects(); + + vtkPropAssembly *m_NetworkAssembly; + + + + + + }; + +} // namespace mitk + + + + +#endif /* ConnectomicsNetworkMapper3D_H_HEADER_INCLUDED */ + diff --git a/Modules/DiffusionImaging/files.cmake b/Modules/DiffusionImaging/files.cmake index d3a7484ab7..a637ddc986 100644 --- a/Modules/DiffusionImaging/files.cmake +++ b/Modules/DiffusionImaging/files.cmake @@ -1,165 +1,215 @@ set(CPP_FILES # DicomImport DicomImport/mitkDicomDiffusionImageReader.cpp DicomImport/mitkGroupDiffusionHeadersFilter.cpp DicomImport/mitkDicomDiffusionImageHeaderReader.cpp DicomImport/mitkGEDicomDiffusionImageHeaderReader.cpp DicomImport/mitkPhilipsDicomDiffusionImageHeaderReader.cpp DicomImport/mitkSiemensDicomDiffusionImageHeaderReader.cpp DicomImport/mitkSiemensMosaicDicomDiffusionImageHeaderReader.cpp # DataStructures IODataStructures/mitkDiffusionImagingObjectFactory.cpp # DataStructures -> DWI IODataStructures/DiffusionWeightedImages/mitkDiffusionImageHeaderInformation.cpp IODataStructures/DiffusionWeightedImages/mitkDiffusionImageSource.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageReader.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageWriter.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageIOFactory.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageWriterFactory.cpp IODataStructures/DiffusionWeightedImages/mitkDiffusionImageSerializer.cpp # DataStructures -> QBall IODataStructures/QBallImages/mitkQBallImageSource.cpp IODataStructures/QBallImages/mitkNrrdQBallImageReader.cpp IODataStructures/QBallImages/mitkNrrdQBallImageWriter.cpp IODataStructures/QBallImages/mitkNrrdQBallImageIOFactory.cpp IODataStructures/QBallImages/mitkNrrdQBallImageWriterFactory.cpp IODataStructures/QBallImages/mitkQBallImage.cpp IODataStructures/QBallImages/mitkQBallImageSerializer.cpp # DataStructures -> Tensor IODataStructures/TensorImages/mitkTensorImageSource.cpp IODataStructures/TensorImages/mitkNrrdTensorImageReader.cpp IODataStructures/TensorImages/mitkNrrdTensorImageWriter.cpp IODataStructures/TensorImages/mitkNrrdTensorImageIOFactory.cpp IODataStructures/TensorImages/mitkNrrdTensorImageWriterFactory.cpp IODataStructures/TensorImages/mitkTensorImage.cpp IODataStructures/TensorImages/mitkTensorImageSerializer.cpp # DataStructures -> FiberBundleX IODataStructures/FiberBundleX/mitkFiberBundleX.cpp IODataStructures/FiberBundleX/mitkFiberBundleXWriter.cpp IODataStructures/FiberBundleX/mitkFiberBundleXReader.cpp IODataStructures/FiberBundleX/mitkFiberBundleXIOFactory.cpp IODataStructures/FiberBundleX/mitkFiberBundleXWriterFactory.cpp IODataStructures/FiberBundleX/mitkFiberBundleXSerializer.cpp IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.cpp # DataStructures -> PlanarFigureComposite IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp # DataStructures -> Tbss IODataStructures/TbssImages/mitkTbssImageSource.cpp IODataStructures/TbssImages/mitkTbssRoiImageSource.cpp IODataStructures/TbssImages/mitkNrrdTbssImageReader.cpp IODataStructures/TbssImages/mitkNrrdTbssImageIOFactory.cpp IODataStructures/TbssImages/mitkNrrdTbssRoiImageReader.cpp IODataStructures/TbssImages/mitkNrrdTbssRoiImageIOFactory.cpp IODataStructures/TbssImages/mitkTbssImage.cpp IODataStructures/TbssImages/mitkTbssRoiImage.cpp IODataStructures/TbssImages/mitkNrrdTbssImageWriter.cpp IODataStructures/TbssImages/mitkNrrdTbssImageWriterFactory.cpp IODataStructures/TbssImages/mitkNrrdTbssRoiImageWriter.cpp IODataStructures/TbssImages/mitkNrrdTbssRoiImageWriterFactory.cpp IODataStructures/TbssImages/mitkTbssImporter.cpp + + # DataStructures Connectomics + IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.cpp + IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.cpp + IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkIOFactory.cpp + IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkSerializer.cpp + IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriter.cpp + IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriterFactory.cpp + IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkDefinitions.cpp + IODataStructures/ConnectomicsNetwork/mitkConnectomicsConstantsManager.cpp # Rendering Rendering/vtkMaskedProgrammableGlyphFilter.cpp Rendering/mitkCompositeMapper.cpp Rendering/mitkVectorImageVtkGlyphMapper3D.cpp Rendering/vtkOdfSource.cxx Rendering/vtkThickPlane.cxx Rendering/mitkOdfNormalizationMethodProperty.cpp Rendering/mitkOdfScaleByProperty.cpp Rendering/mitkFiberBundleXMapper2D.cpp Rendering/mitkFiberBundleXMapper3D.cpp Rendering/mitkFiberBundleXThreadMonitorMapper3D.cpp Rendering/mitkTbssImageMapper.cpp Rendering/mitkPlanarCircleMapper3D.cpp Rendering/mitkPlanarPolygonMapper3D.cpp + Rendering/mitkConnectomicsNetworkMapper3D.cpp # Interactions Interactions/mitkFiberBundleInteractor.cpp # Algorithms Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.cpp Algorithms/mitkTractAnalyzer.cpp + + # Algorithms Connectomics + Algorithms/Connectomics/mitkConnectomicsNetworkCreator.cpp + Algorithms/Connectomics/mitkConnectomicsHistogramBase.cpp + Algorithms/Connectomics/mitkConnectomicsDegreeHistogram.cpp + Algorithms/Connectomics/mitkConnectomicsShortestPathHistogram.cpp + Algorithms/Connectomics/mitkConnectomicsBetweennessHistogram.cpp + Algorithms/Connectomics/mitkConnectomicsHistogramCache.cpp + Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.cpp + Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationBase.cpp + Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationModularity.cpp + Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingManager.cpp + Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionBase.cpp + Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.cpp # Tractography Tractography/itkStochasticTractographyFilter.h ) set(H_FILES # Rendering Rendering/mitkDiffusionImageMapper.h Rendering/mitkTbssImageMapper.h Rendering/mitkOdfVtkMapper2D.h Rendering/mitkFiberBundleXMapper3D.h Rendering/mitkFiberBundleXMapper2D.h Rendering/mitkFiberBundleXThreadMonitorMapper3D.h Rendering/mitkPlanarCircleMapper3D.h Rendering/mitkPlanarPolygonMapper3D.h + Rendering/mitkConnectomicsNetworkMapper3D.h # Reconstruction Reconstruction/itkDiffusionQballReconstructionImageFilter.h Reconstruction/mitkTeemDiffusionTensor3DReconstructionImageFilter.h Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.h Reconstruction/itkPointShell.h Reconstruction/itkOrientationDistributionFunction.h Reconstruction/itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h Reconstruction/itkRegularizedIVIMLocalVariationImageFilter.h Reconstruction/itkRegularizedIVIMReconstructionFilter.h Reconstruction/itkRegularizedIVIMReconstructionSingleIteration.h # IO Datastructures IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.h IODataStructures/TbssImages/mitkTbssImporter.h # DataStructures -> FiberBundleX IODataStructures/FiberBundleX/mitkFiberBundleX.h IODataStructures/FiberBundleX/mitkFiberBundleXWriter.h IODataStructures/FiberBundleX/mitkFiberBundleXReader.h IODataStructures/FiberBundleX/mitkFiberBundleXIOFactory.h IODataStructures/FiberBundleX/mitkFiberBundleXWriterFactory.h IODataStructures/FiberBundleX/mitkFiberBundleXSerializer.h IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.h + + # Datastructures Connectomics + IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.h + IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.h + IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkIOFactory.h + IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkSerializer.h + IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriter.h + IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriterFactory.h + IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkDefinitions.h + IODataStructures/ConnectomicsNetwork/mitkConnectomicsConstantsManager.h # Tractography Tractography/itkGibbsTrackingFilter.h Tractography/itkStochasticTractographyFilter.h # Algorithms Algorithms/itkDiffusionQballGeneralizedFaImageFilter.h Algorithms/itkDiffusionQballPrepareVisualizationImageFilter.h Algorithms/itkTensorDerivedMeasurementsFilter.h Algorithms/itkBrainMaskExtractionImageFilter.h Algorithms/itkB0ImageExtractionImageFilter.h Algorithms/itkTensorImageToDiffusionImageFilter.h Algorithms/itkTensorToL2NormImageFilter.h Algorithms/itkTractDensityImageFilter.h Algorithms/itkTractsToFiberEndingsImageFilter.h Algorithms/itkTractsToRgbaImageFilter.h Algorithms/itkGaussianInterpolateImageFunction.h Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.h Algorithms/itkDiffusionTensorPrincipleDirectionImageFilter.h Algorithms/itkCartesianToPolarVectorImageFilter.h Algorithms/itkPolarToCartesianVectorImageFilter.h Algorithms/itkDistanceMapFilter.h Algorithms/itkProjectionFilter.h Algorithms/itkSkeletonizationFilter.h Algorithms/itkReduceDirectionGradientsFilter.h Algorithms/itkResidualImageFilter.h + + # Algorithms Connectomics + Algorithms/Connectomics/mitkConnectomicsNetworkCreator.h + Algorithms/Connectomics/mitkConnectomicsHistogramBase.h + Algorithms/Connectomics/mitkConnectomicsDegreeHistogram.h + Algorithms/Connectomics/mitkConnectomicsShortestPathHistogram.h + Algorithms/Connectomics/mitkConnectomicsBetweennessHistogram.h + Algorithms/Connectomics/mitkConnectomicsHistogramCache.h + Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.h + Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationBase.h + Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationModularity.h + Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingManager.h + Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionBase.h + Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h ) set( TOOL_FILES ) if(WIN32) endif(WIN32) #MITK_MULTIPLEX_PICTYPE( Algorithms/mitkImageRegistrationMethod-TYPE.cpp ) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkBrainNetworkAnalysis.dox b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkBrainNetworkAnalysis.dox new file mode 100644 index 0000000000..62a5bceb4c --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkBrainNetworkAnalysis.dox @@ -0,0 +1,61 @@ +/** +\bundlemainpage{org_brainnetworkanalysis} The Brain Network Analysis Module + +\image html QmitkBrainNetworkAnalysisViewIcon_64.png "Icon of the Module" + +\section QmitkBrainNetworkAnalysisUserManualSummary Summary + +This module can be used to create a network from a parcellation and a fiber image as well as to calculate and display network statistics. + +This document will tell you how to use this module, but it is assumed that you already know how to use MITK in general. + +Please see \ref QmitkBrainNetworkAnalysisUserManualDetails for more detailed information on usage and supported filters. +If you encounter problems using the module, please have a look at the \ref QmitkBrainNetworkAnalysisUserManualTrouble page. + +\section QmitkBrainNetworkAnalysisUserManualDetails Details + +Manual sections: + +- \ref QmitkBrainNetworkAnalysisUserManualOverview +- \ref QmitkBrainNetworkAnalysisUserManualUsage +- \ref QmitkBrainNetworkAnalysisUserManualTrouble + +\section QmitkBrainNetworkAnalysisUserManualOverview Overview + +This module is currently under heavy development and as such the interface as well as the capabilities are likely to change significantly between different versions. + +This documentation describes the features of this current version. + +\image html QmitkBrainNetworkAnalysisInterface.png "The interface" + +\section QmitkBrainNetworkAnalysisUserManualUsage Usage + +To create a network select first a parcellation of the brain (e.g. as provided by freesurfer ) by CTRL+Leftclick and secondly a fiber image ( as created using tractography module). Then click on the "Create Network" button. + +To calculate network statistics select a network in the datamanager. At this time the following statistics are calculated for the entire network: + +
    +
  • The number of vertices in the network +
  • The number of edges in the network +
  • The number of edges which have the same vertex as beginning and end point +
  • The average degree of the nodes in the network +
  • The connection density the network (the number of edges divided by the number of possible edges) +
  • The unweighted efficiency of the network ( 1 divided by average path length, this is zero for disconnected graphs) +
+ +Furthermore some statistics are calculated on a per node basis and displayed as histograms: + +
    +
  • The degree of each node +
  • The (unweighted) betweenness centrality of each node +
  • The spread of shortest paths between each pair of nodes (For disconnected graphs the shortest paths with infinite length are omitted for readability) +
+ +\section QmitkBrainNetworkAnalysisUserManualTrouble Troubleshooting + +No known problems. + +All other problems.
+Please report to the MITK mailing list. +See http://www.mitk.org/wiki/Mailinglist on how to do this. +*/ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkBrainNetworkAnalysisInterface.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkBrainNetworkAnalysisInterface.png new file mode 100644 index 0000000000..f6ef05bdb9 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkBrainNetworkAnalysisInterface.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkBrainNetworkAnalysisViewIcon_64.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkBrainNetworkAnalysisViewIcon_64.png new file mode 100644 index 0000000000..edcbab0254 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkBrainNetworkAnalysisViewIcon_64.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/files.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging/files.cmake index 22679483fb..6d734cf9ed 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/files.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/files.cmake @@ -1,114 +1,120 @@ set(SRC_CPP_FILES QmitkODFDetailsWidget.cpp QmitkODFRenderWidget.cpp QmitkPartialVolumeAnalysisWidget.cpp QmitkIVIMWidget.cpp QmitkTbssRoiAnalysisWidget.cpp QmitkResidualAnalysisWidget.cpp QmitkResidualViewWidget.cpp ) set(INTERNAL_CPP_FILES mitkPluginActivator.cpp QmitkQBallReconstructionView.cpp QmitkPreprocessingView.cpp QmitkDiffusionDicomImportView.cpp QmitkDiffusionQuantificationView.cpp QmitkTensorReconstructionView.cpp QmitkDiffusionImagingPublicPerspective.cpp QmitkControlVisualizationPropertiesView.cpp QmitkODFDetailsView.cpp QmitkGibbsTrackingView.cpp QmitkStochasticFiberTrackingView.cpp QmitkFiberProcessingView.cpp QmitkFiberBundleDeveloperView.cpp QmitkPartialVolumeAnalysisView.cpp QmitkIVIMView.cpp QmitkTractbasedSpatialStatisticsView.cpp QmitkTbssTableModel.cpp QmitkTbssMetaTableModel.cpp QmitkTbssSkeletonizationView.cpp + Connectomics/QmitkBrainNetworkAnalysisView.cpp + Connectomics/QmitkNetworkHistogramCanvas.cpp ) set(UI_FILES src/internal/QmitkQBallReconstructionViewControls.ui src/internal/QmitkPreprocessingViewControls.ui src/internal/QmitkDiffusionDicomImportViewControls.ui src/internal/QmitkDiffusionQuantificationViewControls.ui src/internal/QmitkTensorReconstructionViewControls.ui src/internal/QmitkControlVisualizationPropertiesViewControls.ui src/internal/QmitkODFDetailsViewControls.ui src/internal/QmitkGibbsTrackingViewControls.ui src/internal/QmitkStochasticFiberTrackingViewControls.ui src/internal/QmitkFiberProcessingViewControls.ui src/internal/QmitkFiberBundleDeveloperViewControls.ui src/internal/QmitkPartialVolumeAnalysisViewControls.ui src/internal/QmitkIVIMViewControls.ui src/internal/QmitkTractbasedSpatialStatisticsViewControls.ui src/internal/QmitkTbssSkeletonizationViewControls.ui + src/internal/Connectomics/QmitkBrainNetworkAnalysisViewControls.ui ) set(MOC_H_FILES src/internal/mitkPluginActivator.h src/internal/QmitkQBallReconstructionView.h src/internal/QmitkPreprocessingView.h src/internal/QmitkDiffusionDicomImportView.h src/internal/QmitkDiffusionImagingPublicPerspective.h src/internal/QmitkDiffusionQuantificationView.h src/internal/QmitkTensorReconstructionView.h src/internal/QmitkControlVisualizationPropertiesView.h src/internal/QmitkODFDetailsView.h src/QmitkODFRenderWidget.h src/QmitkODFDetailsWidget.h src/internal/QmitkGibbsTrackingView.h src/internal/QmitkStochasticFiberTrackingView.h src/internal/QmitkFiberProcessingView.h src/internal/QmitkFiberBundleDeveloperView.h src/internal/QmitkPartialVolumeAnalysisView.h src/QmitkPartialVolumeAnalysisWidget.h src/internal/QmitkIVIMView.h src/internal/QmitkTractbasedSpatialStatisticsView.h src/internal/QmitkTbssSkeletonizationView.h src/QmitkTbssRoiAnalysisWidget.h src/QmitkResidualAnalysisWidget.h src/QmitkResidualViewWidget.h + src/internal/Connectomics/QmitkBrainNetworkAnalysisView.h + src/internal/Connectomics/QmitkNetworkHistogramCanvas.h ) set(CACHED_RESOURCE_FILES # list of resource files which can be used by the plug-in # system without loading the plug-ins shared library, # for example the icon used in the menu and tabs for the # plug-in views in the workbench plugin.xml resources/preprocessing.png resources/dwiimport.png resources/quantification.png resources/reconodf.png resources/recontensor.png resources/vizControls.png resources/OdfDetails.png resources/GibbsTracking.png resources/FiberBundleOperations.png resources/PartialVolumeAnalysis_24.png resources/IVIM_48.png resources/stochFB.png resources/tbss.png + resources/QmitkBrainNetworkAnalysisViewIcon_48.png ) set(QRC_FILES # uncomment the following line if you want to use Qt resources resources/QmitkDiffusionImaging.qrc #resources/QmitkTractbasedSpatialStatisticsView.qrc ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/plugin.xml b/Plugins/org.mitk.gui.qt.diffusionimaging/plugin.xml index 53f7c26b88..e8b9846c4b 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/plugin.xml +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/plugin.xml @@ -1,119 +1,125 @@ + + + diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkBrainNetworkAnalysisViewIcon_48.png b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkBrainNetworkAnalysisViewIcon_48.png new file mode 100644 index 0000000000..7f458d358d Binary files /dev/null and b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkBrainNetworkAnalysisViewIcon_48.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkBrainNetworkAnalysisViewIcon_64.png b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkBrainNetworkAnalysisViewIcon_64.png new file mode 100644 index 0000000000..edcbab0254 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkBrainNetworkAnalysisViewIcon_64.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkBrainNetworkAnalysisView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkBrainNetworkAnalysisView.cpp new file mode 100644 index 0000000000..10a3a57089 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkBrainNetworkAnalysisView.cpp @@ -0,0 +1,537 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +// ####### Blueberry includes ####### +#include +#include + +// ####### Qmitk includes ####### +#include "QmitkBrainNetworkAnalysisView.h" +#include "QmitkStdMultiWidget.h" + +// ####### Qt includes ####### +#include + +// ####### ITK includes ####### +#include + +// ####### MITK includes ####### + +#include +#include "mitkConnectomicsSyntheticNetworkGenerator.h" +#include "mitkConnectomicsSimulatedAnnealingManager.h" +#include "mitkConnectomicsSimulatedAnnealingPermutationModularity.h" +#include "mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h" + +// Includes for image casting between ITK and MITK +#include "mitkImageCast.h" +#include "mitkITKImageImport.h" +#include "mitkImageAccessByItk.h" + +const std::string QmitkBrainNetworkAnalysisView::VIEW_ID = "org.mitk.views.brainnetworkanalysis"; + +QmitkBrainNetworkAnalysisView::QmitkBrainNetworkAnalysisView() +: QmitkFunctionality() +, m_Controls( 0 ) +, m_MultiWidget( NULL ) +, m_ConnectomicsNetworkCreator( mitk::ConnectomicsNetworkCreator::New() ) +, m_demomode( false ) +, m_currentIndex( 0 ) +{ +} + +QmitkBrainNetworkAnalysisView::~QmitkBrainNetworkAnalysisView() +{ +} + + +void QmitkBrainNetworkAnalysisView::CreateQtPartControl( QWidget *parent ) +{ + // build up qt view, unless already done + if ( !m_Controls ) + { + // create GUI widgets from the Qt Designer's .ui file + m_Controls = new Ui::QmitkBrainNetworkAnalysisViewControls; + m_Controls->setupUi( parent ); + + QObject::connect( m_Controls->convertToRGBAImagePushButton, SIGNAL(clicked()), this, SLOT(OnConvertToRGBAImagePushButtonClicked()) ); + QObject::connect( m_Controls->networkifyPushButton, SIGNAL(clicked()), this, SLOT(OnNetworkifyPushButtonClicked()) ); + QObject::connect( m_Controls->syntheticNetworkCreationPushButton, SIGNAL(clicked()), this, SLOT(OnSyntheticNetworkCreationPushButtonClicked()) ); + QObject::connect( (QObject*)( m_Controls->syntheticNetworkComboBox ), SIGNAL(currentIndexChanged (int)), this, SLOT(OnSyntheticNetworkComboBoxCurrentIndexChanged(int)) ); + QObject::connect( (QObject*)( m_Controls->modularizePushButton ), SIGNAL(clicked()), this, SLOT(OnModularizePushButtonClicked()) ); + } + + // GUI is different for developer and demo mode + m_demomode = false; + if( m_demomode ) + { + this->m_Controls->convertToRGBAImagePushButton->hide(); + this->m_Controls->networkifyPushButton->show(); + this->m_Controls->networkifyPushButton->setText( "Create Network" ); + this->m_Controls->modularizePushButton->show(); + + this->m_Controls->syntheticNetworkOptionsGroupBox->hide(); + } + else + { + this->m_Controls->convertToRGBAImagePushButton->show(); + this->m_Controls->networkifyPushButton->show(); + this->m_Controls->networkifyPushButton->setText( "Networkify" ); + this->m_Controls->modularizePushButton->show(); + + this->m_Controls->syntheticNetworkOptionsGroupBox->show(); + //--------------------------- fill comboBox--------------------------- + this->m_Controls->syntheticNetworkComboBox->insertItem(0,"Regular lattice"); + this->m_Controls->syntheticNetworkComboBox->insertItem(1,"Heterogenic sphere"); + this->m_Controls->syntheticNetworkComboBox->insertItem(2,"Random network"); + this->m_Controls->syntheticNetworkComboBox->insertItem(3,"Scale free network"); + this->m_Controls->syntheticNetworkComboBox->insertItem(4,"Small world network"); + } +} + + +void QmitkBrainNetworkAnalysisView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) +{ + m_MultiWidget = &stdMultiWidget; +} + + +void QmitkBrainNetworkAnalysisView::StdMultiWidgetNotAvailable() +{ + m_MultiWidget = NULL; +} + +void QmitkBrainNetworkAnalysisView::WipeDisplay() +{ + m_Controls->numberOfVerticesLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH ); + m_Controls->numberOfEdgesLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH ); + m_Controls->numberOfSelfLoopsLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH ); + m_Controls->averageDegreeLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH ); + m_Controls->connectionDensityLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH ); + m_Controls->efficiencyLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH ); + m_Controls->globalClusteringLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH ); + m_Controls->betweennessNetworkHistogramCanvas->SetHistogram( NULL ); + m_Controls->degreeNetworkHistogramCanvas->SetHistogram( NULL ); + m_Controls->shortestPathNetworkHistogramCanvas->SetHistogram( NULL ); + m_Controls->betweennessNetworkHistogramCanvas->update(); + m_Controls->degreeNetworkHistogramCanvas->update(); + m_Controls->shortestPathNetworkHistogramCanvas->update(); +} + +void QmitkBrainNetworkAnalysisView::OnSelectionChanged( std::vector nodes ) +{ + this->WipeDisplay(); + + // iterate all selected objects, adjust warning visibility + for( std::vector::iterator it = nodes.begin(); + it != nodes.end(); + ++it ) + { + mitk::DataNode::Pointer node = *it; + + if( node.IsNotNull() && dynamic_cast(node->GetData()) ) + { + m_Controls->lblWarning->setVisible( false ); + return; + } + + { + mitk::ConnectomicsNetwork* network = dynamic_cast( node->GetData() ); + if( node.IsNotNull() && network ) + { + m_Controls->lblWarning->setVisible( false ); + + int noVertices = network->GetNumberOfVertices(); + int noEdges = network->GetNumberOfEdges(); + int noSelfLoops = network->GetNumberOfSelfLoops(); + double averageDegree = network->GetAverageDegree(); + double connectionDensity = network->GetConnectionDensity(); + double globalClustering = network->GetGlobalClusteringCoefficient(); + + m_Controls->numberOfVerticesLabel->setText( QString::number( noVertices ) ); + m_Controls->numberOfEdgesLabel->setText( QString::number( noEdges ) ); + m_Controls->numberOfSelfLoopsLabel->setText( QString::number( noSelfLoops ) ); + m_Controls->averageDegreeLabel->setText( QString::number( averageDegree ) ); + m_Controls->connectionDensityLabel->setText( QString::number( connectionDensity ) ); + m_Controls->globalClusteringLabel->setText( QString::number( globalClustering ) ); + + mitk::ConnectomicsNetwork::Pointer connectomicsNetwork( network ); + mitk::ConnectomicsHistogramsContainer *histogramContainer = histogramCache[ connectomicsNetwork ]; + m_Controls->betweennessNetworkHistogramCanvas->SetHistogram( histogramContainer->GetBetweennessHistogram() ); + m_Controls->degreeNetworkHistogramCanvas->SetHistogram( histogramContainer->GetDegreeHistogram() ); + m_Controls->shortestPathNetworkHistogramCanvas->SetHistogram( histogramContainer->GetShortestPathHistogram() ); + m_Controls->betweennessNetworkHistogramCanvas->DrawProfiles(); + m_Controls->degreeNetworkHistogramCanvas->DrawProfiles(); + m_Controls->shortestPathNetworkHistogramCanvas->DrawProfiles(); + + double efficiency = histogramContainer->GetShortestPathHistogram()->GetEfficiency(); + + m_Controls->efficiencyLabel->setText( QString::number( efficiency ) ); + + return; + } + } + } + + m_Controls->lblWarning->setVisible( true ); +} + +void QmitkBrainNetworkAnalysisView::OnSyntheticNetworkComboBoxCurrentIndexChanged(int currentIndex) +{ + m_currentIndex = currentIndex; + + switch (m_currentIndex) { + case 0: + this->m_Controls->parameterOneLabel->setText( "Nodes per side" ); + this->m_Controls->parameterTwoLabel->setText( "Internode distance" ); + this->m_Controls->parameterOneSpinBox->setEnabled( true ); + this->m_Controls->parameterOneSpinBox->setValue( 5 ); + this->m_Controls->parameterTwoDoubleSpinBox->setEnabled( true ); + this->m_Controls->parameterTwoDoubleSpinBox->setMaximum( 999.999 ); + this->m_Controls->parameterTwoDoubleSpinBox->setValue( 10.0 ); + break; + case 1: + this->m_Controls->parameterOneLabel->setText( "Number of nodes" ); + this->m_Controls->parameterTwoLabel->setText( "Radius" ); + this->m_Controls->parameterOneSpinBox->setEnabled( true ); + this->m_Controls->parameterOneSpinBox->setValue( 1000 ); + this->m_Controls->parameterTwoDoubleSpinBox->setEnabled( true ); + this->m_Controls->parameterTwoDoubleSpinBox->setMaximum( 999.999 ); + this->m_Controls->parameterTwoDoubleSpinBox->setValue( 50.0 ); + break; + case 2: + this->m_Controls->parameterOneLabel->setText( "Number of nodes" ); + this->m_Controls->parameterTwoLabel->setText( "Edge percentage" ); + this->m_Controls->parameterOneSpinBox->setEnabled( true ); + this->m_Controls->parameterOneSpinBox->setValue( 100 ); + this->m_Controls->parameterTwoDoubleSpinBox->setEnabled( true ); + this->m_Controls->parameterTwoDoubleSpinBox->setMaximum( 1.0 ); + this->m_Controls->parameterTwoDoubleSpinBox->setValue( 0.5 ); + break; + case 3: + //GenerateSyntheticScaleFreeNetwork( network, 1000 ); + break; + case 4: + //GenerateSyntheticSmallWorldNetwork( network, 1000 ); + break; + default: + this->m_Controls->parameterOneLabel->setText( "Parameter 1" ); + this->m_Controls->parameterTwoLabel->setText( "Paramater 2" ); + this->m_Controls->parameterOneSpinBox->setEnabled( false ); + this->m_Controls->parameterOneSpinBox->setValue( 0 ); + this->m_Controls->parameterTwoDoubleSpinBox->setEnabled( false ); + this->m_Controls->parameterTwoDoubleSpinBox->setValue( 0.0 ); + } +} + +void QmitkBrainNetworkAnalysisView::OnSyntheticNetworkCreationPushButtonClicked() +{ + mitk::ConnectomicsSyntheticNetworkGenerator::Pointer generator = mitk::ConnectomicsSyntheticNetworkGenerator::New(); + + mitk::DataNode::Pointer networkNode = mitk::DataNode::New(); + int parameterOne = this->m_Controls->parameterOneSpinBox->value(); + double parameterTwo = this->m_Controls->parameterTwoDoubleSpinBox->value(); + ////add network to datastorage + networkNode->SetData( generator->CreateSyntheticNetwork( m_currentIndex, parameterOne, parameterTwo ) ); + networkNode->SetName( mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_DEFAULT_CNF_NAME ); + this->GetDefaultDataStorage()->Add( networkNode ); + + return; +} + +void QmitkBrainNetworkAnalysisView::OnConvertToRGBAImagePushButtonClicked() +{ + std::vector nodes = this->GetDataManagerSelection(); + if (nodes.empty()) return; + + mitk::DataNode* node = nodes.front(); + + if (!node) + { + // Nothing selected. Inform the user and return + QMessageBox::information( NULL, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS_CREATION, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_SELECTION_WARNING); + return; + } + + // here we have a valid mitk::DataNode + + // a node itself is not very useful, we need its data item (the image) + mitk::BaseData* data = node->GetData(); + if (data) + { + // test if this data item is an image or not (could also be a surface or something totally different) + mitk::Image* image = dynamic_cast( data ); + if (image) + { + std::stringstream message; + std::string name; + message << mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_PERFORMING_IMAGE_PROCESSING_FOR_IMAGE; + if (node->GetName(name)) + { + // a property called "name" was found for this DataNode + message << "'" << name << "'"; + } + message << "."; + MITK_INFO << message.str(); + + // Convert to RGBA + AccessByItk( image, TurnIntoRGBA ); + this->GetDefaultDataStorage()->GetNamedNode( mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_DEFAULT_RGBA_NAME )->GetData()->SetGeometry( node->GetData()->GetGeometry() ); + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } + } +} + +template < typename TPixel, unsigned int VImageDimension > +void QmitkBrainNetworkAnalysisView::TurnIntoRGBA( itk::Image* inputImage) +{ + typedef itk::RGBAPixel< unsigned char > RGBAPixelType; + typedef itk::Image< TPixel, VImageDimension > TemplateImageType; + typedef itk::Image< RGBAPixelType, VImageDimension > RGBAImageType; + + itk::ImageRegionIterator it_inputImage(inputImage, inputImage->GetLargestPossibleRegion()); + + TPixel minimumValue, maximumValue; + + it_inputImage.GoToBegin(); + maximumValue = minimumValue = it_inputImage.Value(); + + for(it_inputImage.GoToBegin(); !it_inputImage.IsAtEnd(); ++it_inputImage) + { + if ( it_inputImage.Value() < minimumValue ) + { + minimumValue = it_inputImage.Value(); + } + else + { + if ( it_inputImage.Value() > maximumValue ) + { + maximumValue = it_inputImage.Value(); + } + } + } + + int range = int ( maximumValue - minimumValue ); //needs to be castable to int + int offset = int ( minimumValue ); + + if ( range < 0 ) //error + { + return; + } + + std::vector< unsigned int > histogram; + histogram.resize( range + 1, 0 ); + + for(it_inputImage.GoToBegin(); !it_inputImage.IsAtEnd(); ++it_inputImage) + { + histogram[ int ( it_inputImage.Value() ) - offset ] += 1; + } + + int gapCounter = 0; //this variable will be used to count the empty labels + + //stores how much has to be subtracted from the image to remove gaps + std::vector< TPixel > subtractionStorage; + subtractionStorage.resize( range + 1, 0 ); + + for( int index = 0; index <= range; index++ ) + { + if( histogram[ index ] == 0 ) + { + gapCounter++; //if the label is empty, increase gapCounter + } + else + { + subtractionStorage[ index ] = TPixel ( gapCounter ); + } + } + + //remove gaps from label image + for(it_inputImage.GoToBegin(); !it_inputImage.IsAtEnd(); ++it_inputImage) + { + it_inputImage.Value() = it_inputImage.Value() - subtractionStorage[ int ( it_inputImage.Value() ) ]; + } + + // create colour vector + std::vector< RGBAPixelType > lookupTable; + + { + RGBAPixelType backgroundColour; + for( int elementIndex = 0; elementIndex < 4; ++elementIndex ) + { + backgroundColour.SetElement( elementIndex, 0 ); + } + + lookupTable.push_back( backgroundColour ); + + for(int colourNumber = 0; colourNumber < range ; ++colourNumber) + { + RGBAPixelType colour; + for( int elementIndex = 0; elementIndex < 3; ++elementIndex ) + { + colour.SetElement( elementIndex, rand() % 256 ); + } + colour.SetAlpha( 255 ); + lookupTable.push_back( colour ); + } + } + + // create RGBA image + typename RGBAImageType::Pointer rgbaImage = RGBAImageType::New(); + + rgbaImage->SetRegions(inputImage->GetLargestPossibleRegion().GetSize()); + rgbaImage->SetSpacing(inputImage->GetSpacing()); + rgbaImage->SetOrigin(inputImage->GetOrigin()); + rgbaImage->Allocate(); + + //fill with appropriate colours + itk::ImageRegionIterator it_rgbaImage(rgbaImage, rgbaImage->GetLargestPossibleRegion()); + + for(it_inputImage.GoToBegin(), it_rgbaImage.GoToBegin(); !it_inputImage.IsAtEnd(); ++it_inputImage, ++it_rgbaImage) + { + it_rgbaImage.Value() = lookupTable[ int ( it_inputImage.Value() ) ]; + } + + mitk::Image::Pointer mitkRGBAImage = mitk::ImportItkImage( rgbaImage ); + + mitk::DataNode::Pointer rgbaImageNode = mitk::DataNode::New(); + rgbaImageNode->SetData(mitkRGBAImage); + rgbaImageNode->SetProperty(mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_NAME, mitk::StringProperty::New(mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_DEFAULT_RGBA_NAME)); + rgbaImageNode->SetBoolProperty( mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_VOLUMERENDERING, true); + this->GetDefaultDataStorage()->Add( rgbaImageNode ); +} + +void QmitkBrainNetworkAnalysisView::OnNetworkifyPushButtonClicked() +{ + std::vector nodes = this->GetDataManagerSelection(); + if ( nodes.empty() ) + { + QMessageBox::information( NULL, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS_CREATION, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_SELECTION_WARNING); + return; + } + + if (! ( nodes.size() == 2 ) ) + { + QMessageBox::information( NULL, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS_CREATION, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_SELECTION_WARNING); + return; + } + mitk::DataNode* node = nodes.front(); + mitk::DataNode* fiberNode = nodes.at(1); + + if (!node) + { + // Nothing selected. Inform the user and return + QMessageBox::information( NULL, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS_CREATION, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_SELECTION_WARNING); + return; + } + + // here we have a valid mitk::DataNode + + // a node itself is not very useful, we need its data item (the image) + mitk::BaseData* data = node->GetData(); + mitk::BaseData* fiberData = fiberNode->GetData(); + if (data && fiberData) + { + // test if this data item is an image or not (could also be a surface or something totally different) + mitk::Image* image = dynamic_cast( data ); + mitk::FiberBundleX* fiberBundle = dynamic_cast( fiberData ); + if (image && fiberBundle) + { + m_ConnectomicsNetworkCreator->SetSegmentation( image ); + m_ConnectomicsNetworkCreator->SetFiberBundle( fiberBundle ); + m_ConnectomicsNetworkCreator->CreateNetworkFromFibersAndSegmentation(); + mitk::DataNode::Pointer networkNode = mitk::DataNode::New(); + + ////add network to datastorage + networkNode->SetData( m_ConnectomicsNetworkCreator->GetNetwork() ); + networkNode->SetName( mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_DEFAULT_CNF_NAME ); + this->GetDefaultDataStorage()->Add( networkNode ); + } + } + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +void QmitkBrainNetworkAnalysisView::OnModularizePushButtonClicked() +{ + std::vector nodes = this->GetDataManagerSelection(); + if ( nodes.empty() ) + { + QMessageBox::information( NULL, "Modularization calculation", "Please select exactly one network."); + return; + } + + for( std::vector::iterator it = nodes.begin(); + it != nodes.end(); + ++it ) + { + mitk::DataNode::Pointer node = *it; + + if( node.IsNotNull() && dynamic_cast(node->GetData()) ) + { + return; + } + + { + mitk::ConnectomicsNetwork* network = dynamic_cast( node->GetData() ); + if( node.IsNotNull() && network ) + { + + typedef mitk::ConnectomicsSimulatedAnnealingPermutationModularity::ToModuleMapType MappingType; + + int depthOfModuleRecursive( 2 ); + double startTemperature( 2.0 ); + double stepSize( 4.0 ); + + mitk::ConnectomicsNetwork::Pointer connectomicsNetwork( network ); + mitk::ConnectomicsSimulatedAnnealingManager::Pointer manager = mitk::ConnectomicsSimulatedAnnealingManager::New(); + mitk::ConnectomicsSimulatedAnnealingPermutationModularity::Pointer permutation = mitk::ConnectomicsSimulatedAnnealingPermutationModularity::New(); + mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::Pointer costFunction = mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::New(); + + permutation->SetCostFunction( costFunction.GetPointer() ); + permutation->SetNetwork( connectomicsNetwork ); + permutation->SetDepth( depthOfModuleRecursive ); + permutation->SetStepSize( stepSize ); + + manager->SetPermutation( permutation.GetPointer() ); + + manager->RunSimulatedAnnealing( startTemperature, stepSize ); + + MappingType mapping = permutation->GetMapping(); + + MappingType::iterator iter = mapping.begin(); + MappingType::iterator end = mapping.end(); + + int loop( 0 ); + while( iter != end ) + { + MBI_DEBUG << "Vertex " << iter->first << " belongs to module " << iter->second ; + MBI_INFO << "Vertex " << iter->first << " belongs to module " << iter->second ; + iter++; + } + + MBI_DEBUG << "Overall number of modules is " << permutation->getNumberOfModules( &mapping ) ; + MBI_DEBUG << "Cost is " << costFunction->Evaluate( network, &mapping ) ; + MBI_INFO << "Overall number of modules is " << permutation->getNumberOfModules( &mapping ) ; + MBI_INFO << "Cost is " << costFunction->Evaluate( network, &mapping ) ; + + return; + } + } + } + +} diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkBrainNetworkAnalysisView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkBrainNetworkAnalysisView.h new file mode 100644 index 0000000000..36592fa804 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkBrainNetworkAnalysisView.h @@ -0,0 +1,116 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef QmitkBrainNetworkAnalysisView_h +#define QmitkBrainNetworkAnalysisView_h + +#include + +#include + +#include "ui_QmitkBrainNetworkAnalysisViewControls.h" + +#include "mitkConnectomicsNetworkCreator.h" +#include "mitkConnectomicsNetworkMapper3D.h" + +#include "mitkConnectomicsHistogramCache.h" + +// ####### ITK includes ####### +#include + +/*! +\brief QmitkBrainNetworkAnalysisView + +This bundle provides GUI for the brain network analysis algorithms. + +\sa QmitkFunctionality +\ingroup Functionalities +*/ +class QmitkBrainNetworkAnalysisView : public QmitkFunctionality +{ + // this is needed for all Qt objects that should have a Qt meta-object + // (everything that derives from QObject and wants to have signal/slots) + Q_OBJECT + +public: + + static const std::string VIEW_ID; + + QmitkBrainNetworkAnalysisView(); + virtual ~QmitkBrainNetworkAnalysisView(); + + virtual void CreateQtPartControl(QWidget *parent); + + virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); + virtual void StdMultiWidgetNotAvailable(); + + protected slots: + + /// \brief Called when the user clicks the GUI button + void OnConvertToRGBAImagePushButtonClicked(); + + /// \brief Align two images by copying the geometry + void OnNetworkifyPushButtonClicked(); + + /// \brief Create synthetic networks + void OnSyntheticNetworkCreationPushButtonClicked(); + + /// \brief Adjust parameters depending on synthetic network type + void OnSyntheticNetworkComboBoxCurrentIndexChanged(int currentIndex); + + /// \brief Create modularization of network + void OnModularizePushButtonClicked(); + +protected: + + // ####### Functions ####### + /// \brief called by QmitkFunctionality when DataManager's selection has changed + virtual void OnSelectionChanged( std::vector nodes ); + + /// \brief Converts an image into a RGBA image + template < typename TPixel, unsigned int VImageDimension > + void TurnIntoRGBA( itk::Image* inputImage); + + /// \brief Wipe display and empty statistics + void WipeDisplay(); + + + // ####### Variables ####### + + + Ui::QmitkBrainNetworkAnalysisViewControls* m_Controls; + + QmitkStdMultiWidget* m_MultiWidget; + + mitk::ConnectomicsNetworkCreator::Pointer m_ConnectomicsNetworkCreator; + + mitk::ConnectomicsNetworkMapper3D::Pointer m_NetworkMapper; + + /// Cache for histograms + mitk::ConnectomicsHistogramCache histogramCache; + + // Demo/Developer mode toggle + bool m_demomode; + + // The selected synthetic network type + int m_currentIndex; +}; + + + +#endif // _QMITKBRAINNETWORKANALYSISVIEW_H_INCLUDED + diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkBrainNetworkAnalysisViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkBrainNetworkAnalysisViewControls.ui new file mode 100644 index 0000000000..d92a3700de --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkBrainNetworkAnalysisViewControls.ui @@ -0,0 +1,318 @@ + + + QmitkBrainNetworkAnalysisViewControls + + + + 0 + 0 + 227 + 941 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + QLabel { color: rgb(255, 0, 0) } + + + Please select data! + + + + + + + Convert the selected image to RGBA format + + + Convert to RGBA + + + + + + + Create a network from a parcellation and a fiber image + + + Networkify + + + + + + + Create Synthetic Networks + + + + + + + Divide in Modules + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + true + + + Synthetic Network Options + + + + + + + + + + + Parameter 1 + + + + + + + false + + + 9999 + + + + + + + + + + + Parameter 2 + + + + + + + false + + + 3 + + + 999.899999999999977 + + + + + + + + + + + + Network Statistics + + + + + + # of vertices: + + + + + + + # of edges: + + + + + + + - + + + + + + + - + + + + + + + # of self loops: + + + + + + + - + + + + + + + average degree + + + + + + + - + + + + + + + connection density + + + + + + + - + + + + + + + efficiency + + + + + + + - + + + + + + + global clustering + + + + + + + - + + + + + + + + + + Histograms + + + + + + + 0 + 0 + + + + + 50 + 150 + + + + + + + + + 50 + 150 + + + + + + + + + 50 + 150 + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + QmitkNetworkHistogramCanvas + QWidget +
internal/Connectomics/QmitkNetworkHistogramCanvas.h
+ 1 +
+
+ + +
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkNetworkHistogramCanvas.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkNetworkHistogramCanvas.cpp new file mode 100644 index 0000000000..5aaab3a638 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkNetworkHistogramCanvas.cpp @@ -0,0 +1,99 @@ +/*========================================================================= + + Program: Medical Imaging & Interaction Toolkit + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) German Cancer Research Center, Division of Medical and + Biological Informatics. All rights reserved. + See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + + =========================================================================*/ + +#include "QmitkNetworkHistogramCanvas.h" + +#include + +#include +#include +#include +#include +#include +#include + +QmitkNetworkHistogramCanvas::QmitkNetworkHistogramCanvas(QWidget * parent, + Qt::WindowFlags f) + : QmitkPlotWidget(parent) +{ + setEnabled(false); + setFocusPolicy(Qt::ClickFocus); + +} + +QmitkNetworkHistogramCanvas::~QmitkNetworkHistogramCanvas() +{ +} + +void QmitkNetworkHistogramCanvas::DrawProfiles( ) +{ + this->Clear(); + + if( !(m_Histogram) || !( m_Histogram->IsValid() )) + { + return; + } + + std::vector histogramVector = m_Histogram->GetHistogramVector(); + + // create a data vector which contains the points to be drawn + // to create nice bars, the curve takes four points for each bar + std::vector< std::pair< double, double > > dataPointsVector; + + std::pair< double, double > leftBottom, leftTop, rightTop, rightBottom; + + // how wide the bar is, the gap to the next one will be 1 - barWidth + double barWidth( 0.95 ); + const int range = histogramVector.size(); + + for(int i=0; i < range ; ++i) + { + leftBottom.first = ((double) i) ; + leftBottom.second = 0.0; + leftTop.first = ((double) i) ; + leftTop.second = histogramVector.at( i ); + rightTop.first = ((double) i) + barWidth ; + rightTop.second = histogramVector.at( i ); + rightBottom.first = ((double) i) + barWidth ; + rightBottom.second = 0.0; + + dataPointsVector.push_back( leftBottom ); + dataPointsVector.push_back( leftTop ); + dataPointsVector.push_back( rightTop ); + dataPointsVector.push_back( rightBottom ); + } + + this->SetPlotTitle( (m_Histogram->GetSubject()).c_str() ); + + QPen pen( Qt::NoPen ); + QBrush brush( Qt::SolidPattern ); + + brush.setColor( Qt::blue ); + + int curveId = this->InsertCurve( (m_Histogram->GetSubject()).c_str() ); + this->SetCurveData( curveId, dataPointsVector ); + + this->SetCurvePen( curveId, pen ); + this->SetCurveBrush( curveId, brush ); + + // Axis 0 is the y axis, axis to the x axis + this->m_Plot->setAxisTitle(0, "n"); + //this->m_Plot->setAxisTitle(2, ""); + + this->Replot(); + +} \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkNetworkHistogramCanvas.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkNetworkHistogramCanvas.h new file mode 100644 index 0000000000..37a84e83ff --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkNetworkHistogramCanvas.h @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Medical Imaging & Interaction Toolkit + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) German Cancer Research Center, Division of Medical and + Biological Informatics. All rights reserved. + See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + + =========================================================================*/ + +#ifndef QmitkNetworkHistogramCanvas_H_INCLUDED +#define QmitkNetworkHistogramCanvas_H_INCLUDED + + +#include +#include + +#include "QmitkPlotWidget.h" + +#include +#include +#include +#include +#include + + //##Documentation + //## @brief A widget for displaying the data in a ConnectomicsHistogramBase + +class QmitkNetworkHistogramCanvas : public QmitkPlotWidget +{ + + Q_OBJECT + +public: + + QmitkNetworkHistogramCanvas( QWidget * parent=0, Qt::WindowFlags f = 0 ); + ~QmitkNetworkHistogramCanvas(); + + /** @brief Returns the histogram the canvas is using */ + mitk::ConnectomicsHistogramBase* GetHistogram() + { + return m_Histogram; + } + + /** @brief Set the histogram the canvas is to use */ + void SetHistogram(mitk::ConnectomicsHistogramBase *histogram) + { + m_Histogram = histogram; + } + + /** @brief Draw the histogram */ + void DrawProfiles(); + + /** @brief Return the plot */ + QwtPlot* GetPlot() + { + return m_Plot; + } + + +protected: + + /** @brief The histogram to be plotted */ + mitk::ConnectomicsHistogramBase *m_Histogram; + +}; +#endif + diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp index c9fc3aba29..4df517ea27 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp @@ -1,54 +1,56 @@ #include "mitkPluginActivator.h" #include #include "src/internal/QmitkDiffusionImagingPublicPerspective.h" #include "src/internal/QmitkQBallReconstructionView.h" #include "src/internal/QmitkPreprocessingView.h" #include "src/internal/QmitkDiffusionDicomImportView.h" #include "src/internal/QmitkDiffusionQuantificationView.h" #include "src/internal/QmitkTensorReconstructionView.h" #include "src/internal/QmitkControlVisualizationPropertiesView.h" #include "src/internal/QmitkODFDetailsView.h" #include "src/internal/QmitkGibbsTrackingView.h" #include "src/internal/QmitkStochasticFiberTrackingView.h" #include "src/internal/QmitkFiberProcessingView.h" #include "src/internal/QmitkFiberBundleDeveloperView.h" #include "src/internal/QmitkPartialVolumeAnalysisView.h" #include "src/internal/QmitkIVIMView.h" #include "src/internal/QmitkTractbasedSpatialStatisticsView.h" #include "src/internal/QmitkTbssSkeletonizationView.h" +#include "src/internal/Connectomics/QmitkBrainNetworkAnalysisView.h" namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionImagingPublicPerspective, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkQBallReconstructionView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkPreprocessingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionDicomImport, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionQuantificationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkTensorReconstructionView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkControlVisualizationPropertiesView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkODFDetailsView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkGibbsTrackingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkStochasticFiberTrackingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberProcessingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberBundleDeveloperView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkPartialVolumeAnalysisView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkIVIMView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkTractbasedSpatialStatisticsView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkTbssSkeletonizationView, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkBrainNetworkAnalysisView, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_diffusionimaging, mitk::PluginActivator)