22 #include <boost/graph/connected_components.hpp>
23 #include <boost/graph/clustering_coefficient.hpp>
24 #include <boost/graph/betweenness_centrality.hpp>
25 #include <boost/graph/visitors.hpp>
27 #include "vnl/algo/vnl_symmetric_eigensystem.h"
29 template<
typename GraphType>
30 class all_pairs_shortest_recorder :
public boost::default_bfs_visitor
33 typedef typename boost::graph_traits<GraphType>::vertex_descriptor VertexType;
34 typedef typename boost::graph_traits<GraphType>::edge_descriptor EdgeType;
36 all_pairs_shortest_recorder(
int* dist,
int &
max,
unsigned int &size)
40 component_size = &size;
43 void tree_edge(EdgeType edge,
const GraphType& graph) {
44 VertexType u = boost::source(edge, graph);
45 VertexType v = boost::target(edge, graph);
48 *component_size = *component_size + 1;
53 unsigned int* component_size;
57 : m_Network( nullptr )
58 , m_NumberOfVertices( 0 )
59 , m_NumberOfEdges( 0 )
60 , m_AverageDegree( 0.0 )
61 , m_ConnectionDensity( 0.0 )
62 , m_NumberOfConnectedComponents( 0 )
63 , m_AverageComponentSize( 0.0 )
65 , m_LargestComponentSize( 0 )
66 , m_HopPlotExponent( 0.0 )
67 , m_EffectiveHopDiameter( 0.0 )
68 , m_VectorOfClusteringCoefficientsC( 0 )
69 , m_VectorOfClusteringCoefficientsD( 0 )
70 , m_VectorOfClusteringCoefficientsE( 0 )
71 , m_AverageClusteringCoefficientsC( 0.0 )
72 , m_AverageClusteringCoefficientsD( 0.0 )
73 , m_AverageClusteringCoefficientsE( 0.0 )
74 , m_VectorOfVertexBetweennessCentralities( 0 )
75 , m_PropertyMapOfVertexBetweennessCentralities( )
76 , m_AverageVertexBetweennessCentrality( 0.0 )
77 , m_VectorOfEdgeBetweennessCentralities( 0 )
78 , m_PropertyMapOfEdgeBetweennessCentralities( )
79 , m_AverageEdgeBetweennessCentrality( 0.0 )
80 , m_NumberOfIsolatedPoints( 0 )
81 , m_RatioOfIsolatedPoints( 0.0 )
82 , m_NumberOfEndPoints( 0 )
83 , m_RatioOfEndPoints( 0.0 )
84 , m_VectorOfEccentrities( 0 )
85 , m_VectorOfEccentrities90( 0 )
86 , m_VectorOfAveragePathLengths( 0.0 )
91 , m_AverageEccentricity( 0.0 )
92 , m_AverageEccentricity90( 0.0 )
93 , m_AveragePathLength( 0.0 )
94 , m_NumberOfCentralPoints( 0 )
95 , m_RatioOfCentralPoints( 0.0 )
96 , m_VectorOfSortedEigenValues( 0 )
97 , m_SpectralRadius( 0.0 )
98 , m_SecondLargestEigenValue( 0.0 )
99 , m_AdjacencyTrace( 0.0 )
100 , m_AdjacencyEnergy( 0.0 )
101 , m_VectorOfSortedLaplacianEigenValues( 0 )
102 , m_LaplacianTrace( 0.0 )
103 , m_LaplacianEnergy( 0.0 )
104 , m_LaplacianSpectralGap( 0.0 )
105 , m_VectorOfSortedNormalizedLaplacianEigenValues( 0 )
106 , m_NormalizedLaplacianTrace( 0.0 )
107 , m_NormalizedLaplacianEnergy( 0.0 )
108 , m_NormalizedLaplacianNumberOf2s( 0 )
109 , m_NormalizedLaplacianNumberOf1s( 0 )
110 , m_NormalizedLaplacianNumberOf0s( 0 )
111 , m_NormalizedLaplacianLowerSlope( 0.0 )
112 , m_NormalizedLaplacianUpperSlope( 0.0 )
113 , m_SmallWorldness( 0.0 )
123 CalculateNumberOfVertices();
124 CalculateNumberOfEdges();
125 CalculateAverageDegree();
126 CalculateConnectionDensity();
127 CalculateNumberOfConnectedComponents();
128 CalculateAverageComponentSize();
129 CalculateLargestComponentSize();
130 CalculateRatioOfNodesInLargestComponent();
131 CalculateHopPlotValues();
132 CalculateClusteringCoefficients();
133 CalculateBetweennessCentrality();
134 CalculateIsolatedAndEndPoints();
135 CalculateShortestPathMetrics();
136 CalculateSpectralMetrics();
137 CalculateLaplacianMetrics();
138 CalculateNormalizedLaplacianMetrics();
139 CalculateSmallWorldness();
144 m_NumberOfVertices = boost::num_vertices( *(m_Network->GetBoostGraph()) );
149 m_NumberOfEdges = boost::num_edges( *(m_Network->GetBoostGraph()) );
154 m_AverageDegree = ( ( (double) m_NumberOfEdges * 2.0 ) / (double) m_NumberOfVertices );
159 double numberOfPossibleEdges = (double) m_NumberOfVertices * ( (
double) m_NumberOfVertices - 1 ) / 2;
161 m_ConnectionDensity = (double) m_NumberOfEdges / numberOfPossibleEdges;
166 m_Components.resize( m_NumberOfVertices );
167 m_NumberOfConnectedComponents = boost::connected_components( *(m_Network->GetBoostGraph()), &m_Components[0] );
172 m_AverageComponentSize = (double) m_NumberOfVertices / (
double) m_NumberOfConnectedComponents ;
177 m_LargestComponentSize = 0;
178 std::vector<unsigned int> bins( m_NumberOfConnectedComponents );
180 for(
unsigned int i=0; i < m_NumberOfVertices; i++)
182 bins[ m_Components[i] ]++;
185 for(
unsigned int i=0; i < m_NumberOfConnectedComponents; i++)
187 if (bins[i] > m_LargestComponentSize )
189 m_LargestComponentSize = bins[i];
196 m_RatioOfNodesInLargestComponent = (double) m_LargestComponentSize / (
double) m_NumberOfVertices ;
201 std::vector<int> bins( m_NumberOfVertices );
204 unsigned int index( 0 );
206 for( boost::tie( vi, vi_end ) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi != vi_end; ++vi)
208 std::vector<int> distances(m_NumberOfVertices, 0);
209 int max_distance = 0;
212 unsigned int size = 0;
214 boost::breadth_first_search(*(m_Network->GetBoostGraph()), src,
215 visitor(all_pairs_shortest_recorder< NetworkType >
216 (&distances[0], max_distance, size)));
218 for(index=0; index < distances.size(); index++)
220 if(distances[index] > 0)
222 bins[distances[index]]++;
227 bins[0] = m_NumberOfVertices;
228 for(index=1; index < bins.size(); index++)
230 bins[index] = bins[index] + bins[index-1];
234 double C=0, D=0, E=0, F=0;
236 for (
unsigned int i=1; i<bins.size()-1; i++)
239 if(fabs(log(
double(bins[i+1])) - log(
double(bins[i]))) < 0.0000001)
245 for (
int i=1; i<=counter; i++)
247 double x = log(
double(i));
248 double y = log(
double(bins[i]));
254 double b = (D*F - C*E)/(F*counter - C*C);
255 m_HopPlotExponent = (E - b*C)/F;
257 m_EffectiveHopDiameter =
258 std::pow( ( m_NumberOfVertices * m_NumberOfVertices )
259 / ( m_NumberOfVertices + 2 * m_NumberOfEdges ), 1.0 / m_HopPlotExponent );
265 std::vector<double> m_VectorOfClusteringCoefficientsC;
266 std::vector<double> m_VectorOfClusteringCoefficientsD;
267 std::vector<double> m_VectorOfClusteringCoefficientsE;
268 typedef std::set<VertexDescriptorType> NeighborSetType;
269 typedef NetworkType::out_edge_iterator OutEdgeIterType;
271 for(boost::tie(vi,vi_end) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi!=vi_end; ++vi)
274 std::pair<AdjacencyIteratorType, AdjacencyIteratorType> adjacent =
275 boost::adjacent_vertices(*vi, *(m_Network->GetBoostGraph()) );
278 NeighborSetType neighbors;
279 for(; adjacent.first!=adjacent.second; ++adjacent.first)
281 neighbors.insert(*adjacent.first);
285 unsigned int neighborhood_edge_count = 0;
286 if(neighbors.size() > 0)
288 NeighborSetType::iterator iter;
289 for(iter = neighbors.begin(); iter != neighbors.end(); ++iter)
291 std::pair<OutEdgeIterType, OutEdgeIterType> oe = out_edges(*iter, *(m_Network->GetBoostGraph()) );
292 for(; oe.first != oe.second; ++oe.first)
294 if(neighbors.find(target(*oe.first, *(m_Network->GetBoostGraph()) )) != neighbors.end())
296 ++neighborhood_edge_count;
300 neighborhood_edge_count /= 2;
303 if(neighbors.size() > 1)
305 double num = neighborhood_edge_count;
306 double denum = neighbors.size() * (neighbors.size()-1)/2;
307 m_VectorOfClusteringCoefficientsC.push_back( num / denum);
308 m_VectorOfClusteringCoefficientsE.push_back( num / denum);
312 m_VectorOfClusteringCoefficientsC.push_back(0.0);
316 if(neighbors.size() > 0)
318 double num = neighbors.size() + neighborhood_edge_count;
319 double denum = ( (neighbors.size()+1) * neighbors.size()) / 2;
320 m_VectorOfClusteringCoefficientsD.push_back( num / denum);
324 m_VectorOfClusteringCoefficientsD.push_back(0.0);
329 m_AverageClusteringCoefficientsC = std::accumulate(m_VectorOfClusteringCoefficientsC.begin(),
330 m_VectorOfClusteringCoefficientsC.end(),
331 0.0) / m_NumberOfVertices;
333 m_AverageClusteringCoefficientsD = std::accumulate(m_VectorOfClusteringCoefficientsD.begin(),
334 m_VectorOfClusteringCoefficientsD.end(),
335 0.0) / m_NumberOfVertices;
337 m_AverageClusteringCoefficientsE = std::accumulate(m_VectorOfClusteringCoefficientsE.begin(),
338 m_VectorOfClusteringCoefficientsE.end(),
339 0.0) / m_VectorOfClusteringCoefficientsE.size();
352 boost::tie(iterator, end) = boost::edges( *(m_Network->GetBoostGraph()) );
355 for ( ; iterator != end; ++iterator, ++i)
357 stdEdgeIndex.insert(std::pair< EdgeDescriptorType, int >( *iterator, i));
361 m_VectorOfEdgeBetweennessCentralities.resize( m_NumberOfEdges, 0.0);
363 m_PropertyMapOfEdgeBetweennessCentralities =
EdgeIteratorPropertyMapType(m_VectorOfEdgeBetweennessCentralities.begin(), edgeIndex);
366 VertexIndexMapType vertexIndex =
get(boost::vertex_index, *(m_Network->GetBoostGraph()) );
367 m_VectorOfVertexBetweennessCentralities.resize( m_NumberOfVertices, 0.0);
371 boost::brandes_betweenness_centrality( *(m_Network->GetBoostGraph()),
372 m_PropertyMapOfVertexBetweennessCentralities, m_PropertyMapOfEdgeBetweennessCentralities );
374 m_AverageVertexBetweennessCentrality = std::accumulate(m_VectorOfVertexBetweennessCentralities.begin(),
375 m_VectorOfVertexBetweennessCentralities.end(),
376 0.0) / (double) m_NumberOfVertices;
378 m_AverageEdgeBetweennessCentrality = std::accumulate(m_VectorOfEdgeBetweennessCentralities.begin(),
379 m_VectorOfEdgeBetweennessCentralities.end(),
380 0.0) / (double) m_NumberOfEdges;
385 m_NumberOfIsolatedPoints = 0;
386 m_NumberOfEndPoints = 0;
389 for( boost::tie(vi,vi_end) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi!=vi_end; ++vi)
391 int degree = boost::out_degree(*vi, *(m_Network->GetBoostGraph()) );
394 m_NumberOfIsolatedPoints++;
396 else if (degree == 1)
398 m_NumberOfEndPoints++;
402 m_RatioOfEndPoints = (double) m_NumberOfEndPoints / (
double) m_NumberOfVertices;
403 m_RatioOfIsolatedPoints = (double) m_NumberOfIsolatedPoints / (
double) m_NumberOfVertices;
422 m_VectorOfEccentrities.resize( m_NumberOfVertices );
423 m_VectorOfEccentrities90.resize( m_NumberOfVertices );
424 m_VectorOfAveragePathLengths.resize( m_NumberOfVertices );
431 m_AverageEccentricity = 0.0;
432 m_AverageEccentricity90 = 0.0;
433 m_AveragePathLength = 0.0;
436 unsigned int giant_component_size = 0;
440 for( boost::tie(vi, vi_end) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi!=vi_end; ++vi)
449 std::vector<int> distances( m_NumberOfVertices );
450 int max_distance = 0;
453 unsigned int size = 0;
455 breadth_first_search(*(m_Network->GetBoostGraph()), src,
456 visitor(all_pairs_shortest_recorder<NetworkType>
457 (&distances[0], max_distance, size)));
459 m_VectorOfEccentrities[src] = max_distance;
464 if(m_VectorOfEccentrities[src] > m_Diameter)
466 m_Diameter = m_VectorOfEccentrities[src];
476 if(size > giant_component_size)
478 giant_component_size = size;
489 int reachable90 = std::ceil((
double)size * 0.9);
490 std::vector <int> bucket (max_distance+1);
492 for(
unsigned int i=0; i<distances.size(); i++)
496 bucket[distances[i]]++;
497 m_VectorOfAveragePathLengths[src] += distances[i];
503 m_VectorOfAveragePathLengths[src] = m_VectorOfAveragePathLengths[src] / counter;
506 int eccentricity90 = 0;
507 while(reachable90 > 0)
510 reachable90 = reachable90 - bucket[eccentricity90];
513 m_VectorOfEccentrities90[src] = eccentricity90;
514 if(m_VectorOfEccentrities90[src] > m_Diameter90)
516 m_Diameter90 = m_VectorOfEccentrities90[src];
524 std::vector<int> component( m_NumberOfVertices );
525 boost::connected_components( *(m_Network->GetBoostGraph()), &component[0]);
526 for (
unsigned int i=0; i<component.size(); i++)
530 if( component[i] == component[radius_src])
532 if(m_Radius > m_VectorOfEccentrities[i])
534 m_Radius = m_VectorOfEccentrities[i];
536 if(m_Radius90 > m_VectorOfEccentrities90[i])
538 m_Radius90 = m_VectorOfEccentrities90[i];
543 m_AverageEccentricity = std::accumulate(m_VectorOfEccentrities.begin(),
544 m_VectorOfEccentrities.end(), 0.0) / m_NumberOfVertices;
546 m_AverageEccentricity90 = std::accumulate(m_VectorOfEccentrities90.begin(),
547 m_VectorOfEccentrities90.end(), 0.0) / m_NumberOfVertices;
549 m_AveragePathLength = std::accumulate(m_VectorOfAveragePathLengths.begin(),
550 m_VectorOfAveragePathLengths.end(), 0.0) / m_NumberOfVertices;
553 m_NumberOfCentralPoints = 0;
554 for (boost::tie(vi, vi_end) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi != vi_end; ++vi)
556 if(m_VectorOfEccentrities[*vi] == m_Radius)
558 m_NumberOfCentralPoints++;
561 m_RatioOfCentralPoints = (double)m_NumberOfCentralPoints / m_NumberOfVertices;
567 converter->SetNetwork( m_Network );
568 vnl_matrix<double> adjacencyMatrix = converter->GetNetworkAsVNLAdjacencyMatrix();
570 vnl_symmetric_eigensystem<double> eigenSystem(adjacencyMatrix);
572 m_AdjacencyTrace = 0;
573 m_AdjacencyEnergy = 0;
574 m_VectorOfSortedEigenValues.clear();
576 for(
unsigned int i=0; i < m_NumberOfVertices; ++i)
578 double value = std::fabs(eigenSystem.get_eigenvalue(i));
579 m_VectorOfSortedEigenValues.push_back(value);
580 m_AdjacencyTrace += value;
581 m_AdjacencyEnergy += value * value;
584 std::sort(m_VectorOfSortedEigenValues.begin(), m_VectorOfSortedEigenValues.end());
586 m_SpectralRadius = m_VectorOfSortedEigenValues[ m_NumberOfVertices - 1];
587 m_SecondLargestEigenValue = m_VectorOfSortedEigenValues[ m_NumberOfVertices - 2];
593 converter->SetNetwork( m_Network );
594 vnl_matrix<double> adjacencyMatrix = converter->GetNetworkAsVNLAdjacencyMatrix();
595 vnl_matrix<double> laplacianMatrix ( m_NumberOfVertices, m_NumberOfVertices, 0);
596 vnl_matrix<double> degreeMatrix = converter->GetNetworkAsVNLDegreeMatrix();
598 m_VectorOfSortedLaplacianEigenValues.clear();
599 laplacianMatrix = degreeMatrix - adjacencyMatrix;
600 int numberOfConnectedComponents = 0;
601 vnl_symmetric_eigensystem <double> laplacianEigenSystem( laplacianMatrix );
602 m_LaplacianEnergy = 0;
603 m_LaplacianTrace = 0;
604 for(
unsigned int i(0); i < m_NumberOfVertices; ++i)
606 double value = std::fabs( laplacianEigenSystem.get_eigenvalue(i) );
607 m_VectorOfSortedLaplacianEigenValues.push_back( value );
608 m_LaplacianTrace += value;
609 m_LaplacianEnergy += value * value;
612 numberOfConnectedComponents++;
616 std::sort(m_VectorOfSortedLaplacianEigenValues.begin(), m_VectorOfSortedLaplacianEigenValues.end());
617 for(
unsigned int i(0); i < m_VectorOfSortedLaplacianEigenValues.size(); ++i)
619 if(m_VectorOfSortedLaplacianEigenValues[i] >
mitk::eps )
621 m_LaplacianSpectralGap = m_VectorOfSortedLaplacianEigenValues[i];
629 vnl_matrix<double> normalizedLaplacianMatrix(m_NumberOfVertices, m_NumberOfVertices, 0);
632 int sourceIndex, destinationIndex;
633 VertexIndexMapType vertexIndexMap = boost::get(boost::vertex_index, *(m_Network->GetBoostGraph()) );
634 m_VectorOfSortedNormalizedLaplacianEigenValues.clear();
637 for( boost::tie(ei, ei_end) = boost::edges( *(m_Network->GetBoostGraph()) ); ei != ei_end; ++ei)
639 sourceVertex = boost::source(*ei, *(m_Network->GetBoostGraph()) );
640 sourceIndex = vertexIndexMap[sourceVertex];
642 destinationVertex = boost::target(*ei, *(m_Network->GetBoostGraph()) );
643 destinationIndex = vertexIndexMap[destinationVertex];
644 int sourceDegree = boost::out_degree(sourceVertex, *(m_Network->GetBoostGraph()) );
645 int destinationDegree = boost::out_degree(destinationVertex, *(m_Network->GetBoostGraph()) );
647 normalizedLaplacianMatrix.put(
648 sourceIndex, destinationIndex, -1 / (sqrt(
double(sourceDegree * destinationDegree))));
649 normalizedLaplacianMatrix.put(
650 destinationIndex, sourceIndex, -1 / (sqrt(
double(sourceDegree * destinationDegree))));
654 for(boost::tie(vi, vi_end)=boost::vertices( *(m_Network->GetBoostGraph()) ); vi!=vi_end; ++vi)
656 if(boost::out_degree(*vi, *(m_Network->GetBoostGraph()) ) > 0)
658 normalizedLaplacianMatrix.put(vertexIndexMap[*vi], vertexIndexMap[*vi], 1);
663 vnl_symmetric_eigensystem <double>
664 normalizedLaplacianEigensystem(normalizedLaplacianMatrix);
666 double N1=0, C1=0, D1=0, E1=0, F1=0, b1=0;
667 double N2=0, C2=0, D2=0, E2=0, F2=0, b2=0;
668 m_NormalizedLaplacianNumberOf2s = 0;
669 m_NormalizedLaplacianNumberOf1s = 0;
670 m_NormalizedLaplacianNumberOf0s = 0;
671 m_NormalizedLaplacianTrace = 0;
672 m_NormalizedLaplacianEnergy = 0;
674 for(
unsigned int i(0); i< m_NumberOfVertices; ++i)
676 double eigenValue = std::fabs(normalizedLaplacianEigensystem.get_eigenvalue(i));
677 m_VectorOfSortedNormalizedLaplacianEigenValues.push_back(eigenValue);
678 m_NormalizedLaplacianTrace += eigenValue;
679 m_NormalizedLaplacianEnergy += eigenValue * eigenValue;
684 m_NormalizedLaplacianNumberOf0s++;
692 E1 += i * eigenValue;
698 else if(std::fabs( std::fabs(eigenValue) - 1) <
mitk::eps)
700 m_NormalizedLaplacianNumberOf1s++;
708 E2 += i * eigenValue;
714 else if(std::fabs( std::fabs(eigenValue) - 2) <
mitk::eps)
716 m_NormalizedLaplacianNumberOf2s++;
720 b1 = (D1*F1 - C1*E1)/(F1*N1 - C1*C1);
721 m_NormalizedLaplacianLowerSlope = (E1 - b1*C1)/F1;
723 b2 = (D2*F2 - C2*E2)/(F2*N2 - C2*C2);
724 m_NormalizedLaplacianUpperSlope = (E2 - b2*C2)/F2;
729 double k( this->GetAverageDegree() );
730 double N( this->GetNumberOfVertices() );
733 double gamma = this->GetAverageClusteringCoefficientsC() / ( k / N );
736 double lambda = this->GetAveragePathLength() / ( std::log( N ) / std::log( k ) );
738 m_SmallWorldness = gamma / lambda;
itk::SmartPointer< Self > Pointer
boost::graph_traits< NetworkType >::edge_iterator EdgeIteratorType
ConnectomicsStatisticsCalculator()
void CalculateNumberOfEdges()
void CalculateIsolatedAndEndPoints()
void CalculateLargestComponentSize()
void CalculateClusteringCoefficients()
Calculate the different clustering coefficients.
std::map< EdgeDescriptorType, int > EdgeIndexStdMapType
void CalculateNumberOfConnectedComponents()
~ConnectomicsStatisticsCalculator()
mitk::ConnectomicsNetwork::VertexDescriptorType VertexDescriptorType
void CalculateHopPlotValues()
void CalculateNumberOfVertices()
boost::graph_traits< NetworkType >::vertex_iterator VertexIteratorType
void CalculateAverageDegree()
boost::associative_property_map< EdgeIndexStdMapType > EdgeIndexMapType
void CalculateSpectralMetrics()
boost::iterator_property_map< std::vector< double >::iterator, VertexIndexMapType > VertexIteratorPropertyMapType
void CalculateSmallWorldness()
Calculate the small worldness of the network.
MITKCORE_EXPORT const ScalarType eps
void CalculateConnectionDensity()
void CalculateShortestPathMetrics()
void CalculateNormalizedLaplacianMetrics()
void CalculateLaplacianMetrics()
void CalculateAverageComponentSize()
boost::property_map< NetworkType, boost::vertex_index_t >::type VertexIndexMapType
void CalculateBetweennessCentrality()
void CalculateRatioOfNodesInLargestComponent()
boost::iterator_property_map< std::vector< double >::iterator, EdgeIndexMapType > EdgeIteratorPropertyMapType