Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
mitkConnectomicsStatisticsCalculator.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
19 
20 #include <numeric>
21 
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>
26 
27 #include "vnl/algo/vnl_symmetric_eigensystem.h"
28 
29 template<typename GraphType>
30 class all_pairs_shortest_recorder : public boost::default_bfs_visitor
31 {
32 public:
33  typedef typename boost::graph_traits<GraphType>::vertex_descriptor VertexType;
34  typedef typename boost::graph_traits<GraphType>::edge_descriptor EdgeType;
35 
36  all_pairs_shortest_recorder(int* dist, int &max, unsigned int &size)
37  {
38  d = dist;
39  ecc = &max;
40  component_size = &size;
41  }
42 
43  void tree_edge(EdgeType edge, const GraphType& graph) {
44  VertexType u = boost::source(edge, graph);
45  VertexType v = boost::target(edge, graph);
46  d[v] = d[u] + 1;
47  *ecc = d[v];
48  *component_size = *component_size + 1;
49  }
50 private:
51  int* d;
52  int* ecc;
53  unsigned int* component_size;
54 };
55 
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 )
64  , m_Components(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 )
87  , m_Diameter( 0 )
88  , m_Diameter90( 0 )
89  , m_Radius( 0 )
90  , m_Radius90( 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 )
114 {
115 }
116 
118 {
119 }
120 
122 {
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();
140 }
141 
143 {
144  m_NumberOfVertices = boost::num_vertices( *(m_Network->GetBoostGraph()) );
145 }
146 
148 {
149  m_NumberOfEdges = boost::num_edges( *(m_Network->GetBoostGraph()) );
150 }
151 
153 {
154  m_AverageDegree = ( ( (double) m_NumberOfEdges * 2.0 ) / (double) m_NumberOfVertices );
155 }
156 
158 {
159  double numberOfPossibleEdges = (double) m_NumberOfVertices * ( (double) m_NumberOfVertices - 1 ) / 2;
160 
161  m_ConnectionDensity = (double) m_NumberOfEdges / numberOfPossibleEdges;
162 }
163 
165 {
166  m_Components.resize( m_NumberOfVertices );
167  m_NumberOfConnectedComponents = boost::connected_components( *(m_Network->GetBoostGraph()), &m_Components[0] );
168 }
169 
171 {
172  m_AverageComponentSize = (double) m_NumberOfVertices / (double) m_NumberOfConnectedComponents ;
173 }
174 
176 {
177  m_LargestComponentSize = 0;
178  std::vector<unsigned int> bins( m_NumberOfConnectedComponents );
179 
180  for(unsigned int i=0; i < m_NumberOfVertices; i++)
181  {
182  bins[ m_Components[i] ]++;
183  }
184 
185  for(unsigned int i=0; i < m_NumberOfConnectedComponents; i++)
186  {
187  if (bins[i] > m_LargestComponentSize )
188  {
189  m_LargestComponentSize = bins[i];
190  }
191  }
192 }
193 
195 {
196  m_RatioOfNodesInLargestComponent = (double) m_LargestComponentSize / (double) m_NumberOfVertices ;
197 }
198 
200 {
201  std::vector<int> bins( m_NumberOfVertices );
202 
203  VertexIteratorType vi, vi_end;
204  unsigned int index( 0 );
205 
206  for( boost::tie( vi, vi_end ) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi != vi_end; ++vi)
207  {
208  std::vector<int> distances(m_NumberOfVertices, 0);
209  int max_distance = 0;
210  VertexDescriptorType src = *vi;
211  distances[src] = 0;
212  unsigned int size = 0;
213 
214  boost::breadth_first_search(*(m_Network->GetBoostGraph()), src,
215  visitor(all_pairs_shortest_recorder< NetworkType >
216  (&distances[0], max_distance, size)));
217 
218  for(index=0; index < distances.size(); index++)
219  {
220  if(distances[index] > 0)
221  {
222  bins[distances[index]]++;
223  }
224  }
225  }
226 
227  bins[0] = m_NumberOfVertices;
228  for(index=1; index < bins.size(); index++)
229  {
230  bins[index] = bins[index] + bins[index-1];
231  }
232 
233  int counter = 0;
234  double C=0, D=0, E=0, F=0;
235 
236  for (unsigned int i=1; i<bins.size()-1; i++)
237  {
238  counter ++;
239  if(fabs(log(double(bins[i+1])) - log(double(bins[i]))) < 0.0000001)
240  {
241  break;
242  }
243  }
244 
245  for (int i=1; i<=counter; i++)
246  {
247  double x = log(double(i));
248  double y = log(double(bins[i]));
249  C += x;
250  D += y;
251  E += x * y;
252  F += x * x;
253  }
254  double b = (D*F - C*E)/(F*counter - C*C);
255  m_HopPlotExponent = (E - b*C)/F;
256 
257  m_EffectiveHopDiameter =
258  std::pow( ( m_NumberOfVertices * m_NumberOfVertices )
259  / ( m_NumberOfVertices + 2 * m_NumberOfEdges ), 1.0 / m_HopPlotExponent );
260 }
261 
263 {
264  VertexIteratorType vi, vi_end;
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;
270 
271  for(boost::tie(vi,vi_end) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi!=vi_end; ++vi)
272  {
273  // Get the list of vertices which are in the neighborhood of vi.
274  std::pair<AdjacencyIteratorType, AdjacencyIteratorType> adjacent =
275  boost::adjacent_vertices(*vi, *(m_Network->GetBoostGraph()) );
276 
277  //Populate a set with the neighbors of vi
278  NeighborSetType neighbors;
279  for(; adjacent.first!=adjacent.second; ++adjacent.first)
280  {
281  neighbors.insert(*adjacent.first);
282  }
283 
284  // Now, count the edges between vertices in the neighborhood.
285  unsigned int neighborhood_edge_count = 0;
286  if(neighbors.size() > 0)
287  {
288  NeighborSetType::iterator iter;
289  for(iter = neighbors.begin(); iter != neighbors.end(); ++iter)
290  {
291  std::pair<OutEdgeIterType, OutEdgeIterType> oe = out_edges(*iter, *(m_Network->GetBoostGraph()) );
292  for(; oe.first != oe.second; ++oe.first)
293  {
294  if(neighbors.find(target(*oe.first, *(m_Network->GetBoostGraph()) )) != neighbors.end())
295  {
296  ++neighborhood_edge_count;
297  }
298  }
299  }
300  neighborhood_edge_count /= 2;
301  }
302  //Clustering Coefficienct C,E
303  if(neighbors.size() > 1)
304  {
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);
309  }
310  else
311  {
312  m_VectorOfClusteringCoefficientsC.push_back(0.0);
313  }
314 
315  //Clustering Coefficienct D
316  if(neighbors.size() > 0)
317  {
318  double num = neighbors.size() + neighborhood_edge_count;
319  double denum = ( (neighbors.size()+1) * neighbors.size()) / 2;
320  m_VectorOfClusteringCoefficientsD.push_back( num / denum);
321  }
322  else
323  {
324  m_VectorOfClusteringCoefficientsD.push_back(0.0);
325  }
326  }
327 
328  // Average Clustering coefficienies:
329  m_AverageClusteringCoefficientsC = std::accumulate(m_VectorOfClusteringCoefficientsC.begin(),
330  m_VectorOfClusteringCoefficientsC.end(),
331  0.0) / m_NumberOfVertices;
332 
333  m_AverageClusteringCoefficientsD = std::accumulate(m_VectorOfClusteringCoefficientsD.begin(),
334  m_VectorOfClusteringCoefficientsD.end(),
335  0.0) / m_NumberOfVertices;
336 
337  m_AverageClusteringCoefficientsE = std::accumulate(m_VectorOfClusteringCoefficientsE.begin(),
338  m_VectorOfClusteringCoefficientsE.end(),
339  0.0) / m_VectorOfClusteringCoefficientsE.size();
340 }
341 
343 {
344  // std::map used for convenient initialization
345  EdgeIndexStdMapType stdEdgeIndex;
346  // associative property map needed for iterator property map-wrapper
347  EdgeIndexMapType edgeIndex(stdEdgeIndex);
348 
349  EdgeIteratorType iterator, end;
350 
351  // sets iterator to start end end to end
352  boost::tie(iterator, end) = boost::edges( *(m_Network->GetBoostGraph()) );
353 
354  int i(0);
355  for ( ; iterator != end; ++iterator, ++i)
356  {
357  stdEdgeIndex.insert(std::pair< EdgeDescriptorType, int >( *iterator, i));
358  }
359 
360  // Define EdgeCentralityMap
361  m_VectorOfEdgeBetweennessCentralities.resize( m_NumberOfEdges, 0.0);
362  // Create the external property map
363  m_PropertyMapOfEdgeBetweennessCentralities = EdgeIteratorPropertyMapType(m_VectorOfEdgeBetweennessCentralities.begin(), edgeIndex);
364 
365  // Define VertexCentralityMap
366  VertexIndexMapType vertexIndex = get(boost::vertex_index, *(m_Network->GetBoostGraph()) );
367  m_VectorOfVertexBetweennessCentralities.resize( m_NumberOfVertices, 0.0);
368  // Create the external property map
369  m_PropertyMapOfVertexBetweennessCentralities = VertexIteratorPropertyMapType(m_VectorOfVertexBetweennessCentralities.begin(), vertexIndex);
370 
371  boost::brandes_betweenness_centrality( *(m_Network->GetBoostGraph()),
372  m_PropertyMapOfVertexBetweennessCentralities, m_PropertyMapOfEdgeBetweennessCentralities );
373 
374  m_AverageVertexBetweennessCentrality = std::accumulate(m_VectorOfVertexBetweennessCentralities.begin(),
375  m_VectorOfVertexBetweennessCentralities.end(),
376  0.0) / (double) m_NumberOfVertices;
377 
378  m_AverageEdgeBetweennessCentrality = std::accumulate(m_VectorOfEdgeBetweennessCentralities.begin(),
379  m_VectorOfEdgeBetweennessCentralities.end(),
380  0.0) / (double) m_NumberOfEdges;
381 }
382 
384 {
385  m_NumberOfIsolatedPoints = 0;
386  m_NumberOfEndPoints = 0;
387 
388  VertexIteratorType vi, vi_end;
389  for( boost::tie(vi,vi_end) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi!=vi_end; ++vi)
390  {
391  int degree = boost::out_degree(*vi, *(m_Network->GetBoostGraph()) );
392  if(degree == 0)
393  {
394  m_NumberOfIsolatedPoints++;
395  }
396  else if (degree == 1)
397  {
398  m_NumberOfEndPoints++;
399  }
400  }
401 
402  m_RatioOfEndPoints = (double) m_NumberOfEndPoints / (double) m_NumberOfVertices;
403  m_RatioOfIsolatedPoints = (double) m_NumberOfIsolatedPoints / (double) m_NumberOfVertices;
404 }
405 
406 
417 {
418  //for all vertices:
419  VertexIteratorType vi, vi_end;
420 
421  //store the eccentricities in a vector.
422  m_VectorOfEccentrities.resize( m_NumberOfVertices );
423  m_VectorOfEccentrities90.resize( m_NumberOfVertices );
424  m_VectorOfAveragePathLengths.resize( m_NumberOfVertices );
425 
426  //assign diameter and radius while iterating over the ecccencirities.
427  m_Diameter = 0;
428  m_Diameter90 = 0;
431  m_AverageEccentricity = 0.0;
432  m_AverageEccentricity90 = 0.0;
433  m_AveragePathLength = 0.0;
434 
435  //The size of the giant connected component so far.
436  unsigned int giant_component_size = 0;
437  VertexDescriptorType radius_src(0);
438 
439  //Loop over the vertices
440  for( boost::tie(vi, vi_end) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi!=vi_end; ++vi)
441  {
442  //We are going to start a BFS, initialize the neccessary
443  //structures for that. Store the distances of nodes from the
444  //source in distance vector. The maximum distance is stored in
445  //max. The BFS will start from the node that vi is pointing, that
446  //is the src is *vi. We also init the distance of the src node to
447  //itself to 0. size gives the number of nodes discovered during
448  //this BFS.
449  std::vector<int> distances( m_NumberOfVertices );
450  int max_distance = 0;
451  VertexDescriptorType src = *vi;
452  distances[src] = 0;
453  unsigned int size = 0;
454 
455  breadth_first_search(*(m_Network->GetBoostGraph()), src,
456  visitor(all_pairs_shortest_recorder<NetworkType>
457  (&distances[0], max_distance, size)));
458  // vertex vi has eccentricity equal to max_distance
459  m_VectorOfEccentrities[src] = max_distance;
460 
461  //check whether there is any change in the diameter or the radius.
462  //note that the diameter we are calculating here is also the
463  //diameter of the giant connected component!
464  if(m_VectorOfEccentrities[src] > m_Diameter)
465  {
466  m_Diameter = m_VectorOfEccentrities[src];
467  }
468 
469  //The radius should be calculated on the largest connected
470  //component, otherwise it is very likely that radius will be 1.
471  //We change the value of the radius only if this is the giant
472  //connected component so far. After all the eccentricities are
473  //found we should loop over this connected component and find the
474  //minimum eccentricity which is the radius. So we keep the src
475  //node, so that we can find the connected component later on.
476  if(size > giant_component_size)
477  {
478  giant_component_size = size;
479  radius_src = src;
480  }
481 
482  //Calculate in how many hops we can reach 90 percent of the
483  //nodes. We store the number of hops we can reach in h hops in the
484  //bucket vector. That is bucket[h] gives the number of nodes
485  //reachable in exactly h hops. sum of bucket[i<h] gives the number
486  //of nodes that are reachable in less than h hops. We also
487  //calculate sum of the distances from this node to every single
488  //other node in the graph.
489  int reachable90 = std::ceil((double)size * 0.9);
490  std::vector <int> bucket (max_distance+1);
491  int counter = 0;
492  for(unsigned int i=0; i<distances.size(); i++)
493  {
494  if(distances[i]>0)
495  {
496  bucket[distances[i]]++;
497  m_VectorOfAveragePathLengths[src] += distances[i];
498  counter ++;
499  }
500  }
501  if(counter > 0)
502  {
503  m_VectorOfAveragePathLengths[src] = m_VectorOfAveragePathLengths[src] / counter;
504  }
505 
506  int eccentricity90 = 0;
507  while(reachable90 > 0)
508  {
509  eccentricity90 ++;
510  reachable90 = reachable90 - bucket[eccentricity90];
511  }
512  // vertex vi has eccentricity90 equal to eccentricity90
513  m_VectorOfEccentrities90[src] = eccentricity90;
514  if(m_VectorOfEccentrities90[src] > m_Diameter90)
515  {
516  m_Diameter90 = m_VectorOfEccentrities90[src];
517  }
518  }
519 
520  //We are going to calculate the radius now. We stored the src node
521  //that when we start a BFS gives the giant connected component, and
522  //we have the eccentricities calculated. Iterate over the nodes of
523  //this giant component and find the minimum eccentricity.
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++)
527  {
528  //If we are in the same component and the radius is not the
529  //minimum so far store the eccentricity as the radius.
530  if( component[i] == component[radius_src])
531  {
532  if(m_Radius > m_VectorOfEccentrities[i])
533  {
534  m_Radius = m_VectorOfEccentrities[i];
535  }
536  if(m_Radius90 > m_VectorOfEccentrities90[i])
537  {
538  m_Radius90 = m_VectorOfEccentrities90[i];
539  }
540  }
541  }
542 
543  m_AverageEccentricity = std::accumulate(m_VectorOfEccentrities.begin(),
544  m_VectorOfEccentrities.end(), 0.0) / m_NumberOfVertices;
545 
546  m_AverageEccentricity90 = std::accumulate(m_VectorOfEccentrities90.begin(),
547  m_VectorOfEccentrities90.end(), 0.0) / m_NumberOfVertices;
548 
549  m_AveragePathLength = std::accumulate(m_VectorOfAveragePathLengths.begin(),
550  m_VectorOfAveragePathLengths.end(), 0.0) / m_NumberOfVertices;
551 
552  //calculate Number of Central Points, nodes having eccentricity = radius.
553  m_NumberOfCentralPoints = 0;
554  for (boost::tie(vi, vi_end) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi != vi_end; ++vi)
555  {
556  if(m_VectorOfEccentrities[*vi] == m_Radius)
557  {
558  m_NumberOfCentralPoints++;
559  }
560  }
561  m_RatioOfCentralPoints = (double)m_NumberOfCentralPoints / m_NumberOfVertices;
562 }
563 
565 {
567  converter->SetNetwork( m_Network );
568  vnl_matrix<double> adjacencyMatrix = converter->GetNetworkAsVNLAdjacencyMatrix();
569 
570  vnl_symmetric_eigensystem<double> eigenSystem(adjacencyMatrix);
571 
572  m_AdjacencyTrace = 0;
573  m_AdjacencyEnergy = 0;
574  m_VectorOfSortedEigenValues.clear();
575 
576  for(unsigned int i=0; i < m_NumberOfVertices; ++i)
577  {
578  double value = std::fabs(eigenSystem.get_eigenvalue(i));
579  m_VectorOfSortedEigenValues.push_back(value);
580  m_AdjacencyTrace += value;
581  m_AdjacencyEnergy += value * value;
582  }
583 
584  std::sort(m_VectorOfSortedEigenValues.begin(), m_VectorOfSortedEigenValues.end());
585 
586  m_SpectralRadius = m_VectorOfSortedEigenValues[ m_NumberOfVertices - 1];
587  m_SecondLargestEigenValue = m_VectorOfSortedEigenValues[ m_NumberOfVertices - 2];
588 }
589 
591 {
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();
597 
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)
605  {
606  double value = std::fabs( laplacianEigenSystem.get_eigenvalue(i) );
607  m_VectorOfSortedLaplacianEigenValues.push_back( value );
608  m_LaplacianTrace += value;
609  m_LaplacianEnergy += value * value;
610  if ( std::fabs( value ) < mitk::eps )
611  {
612  numberOfConnectedComponents++;
613  }
614  }
615 
616  std::sort(m_VectorOfSortedLaplacianEigenValues.begin(), m_VectorOfSortedLaplacianEigenValues.end());
617  for(unsigned int i(0); i < m_VectorOfSortedLaplacianEigenValues.size(); ++i)
618  {
619  if(m_VectorOfSortedLaplacianEigenValues[i] > mitk::eps )
620  {
621  m_LaplacianSpectralGap = m_VectorOfSortedLaplacianEigenValues[i];
622  break;
623  }
624  }
625 }
626 
628 {
629  vnl_matrix<double> normalizedLaplacianMatrix(m_NumberOfVertices, m_NumberOfVertices, 0);
630  EdgeIteratorType ei, ei_end;
631  VertexDescriptorType sourceVertex, destinationVertex;
632  int sourceIndex, destinationIndex;
633  VertexIndexMapType vertexIndexMap = boost::get(boost::vertex_index, *(m_Network->GetBoostGraph()) );
634  m_VectorOfSortedNormalizedLaplacianEigenValues.clear();
635 
636  // Normalized laplacian matrix
637  for( boost::tie(ei, ei_end) = boost::edges( *(m_Network->GetBoostGraph()) ); ei != ei_end; ++ei)
638  {
639  sourceVertex = boost::source(*ei, *(m_Network->GetBoostGraph()) );
640  sourceIndex = vertexIndexMap[sourceVertex];
641 
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()) );
646 
647  normalizedLaplacianMatrix.put(
648  sourceIndex, destinationIndex, -1 / (sqrt(double(sourceDegree * destinationDegree))));
649  normalizedLaplacianMatrix.put(
650  destinationIndex, sourceIndex, -1 / (sqrt(double(sourceDegree * destinationDegree))));
651  }
652 
653  VertexIteratorType vi, vi_end;
654  for(boost::tie(vi, vi_end)=boost::vertices( *(m_Network->GetBoostGraph()) ); vi!=vi_end; ++vi)
655  {
656  if(boost::out_degree(*vi, *(m_Network->GetBoostGraph()) ) > 0)
657  {
658  normalizedLaplacianMatrix.put(vertexIndexMap[*vi], vertexIndexMap[*vi], 1);
659  }
660  }
661  //End of normalized laplacian matrix definition
662 
663  vnl_symmetric_eigensystem <double>
664  normalizedLaplacianEigensystem(normalizedLaplacianMatrix);
665 
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;
673 
674  for(unsigned int i(0); i< m_NumberOfVertices; ++i)
675  {
676  double eigenValue = std::fabs(normalizedLaplacianEigensystem.get_eigenvalue(i));
677  m_VectorOfSortedNormalizedLaplacianEigenValues.push_back(eigenValue);
678  m_NormalizedLaplacianTrace += eigenValue;
679  m_NormalizedLaplacianEnergy += eigenValue * eigenValue;
680 
681  //0
682  if(eigenValue < mitk::eps)
683  {
684  m_NormalizedLaplacianNumberOf0s++;
685  }
686 
687  //Between 0 and 1.
688  else if(eigenValue > mitk::eps && eigenValue< 1 - mitk::eps)
689  {
690  C1 += i;
691  D1 += eigenValue;
692  E1 += i * eigenValue;
693  F1 += i * i;
694  N1 ++;
695  }
696 
697  //1
698  else if(std::fabs( std::fabs(eigenValue) - 1) < mitk::eps)
699  {
700  m_NormalizedLaplacianNumberOf1s++;
701  }
702 
703  //Between 1 and 2
704  else if(std::fabs(eigenValue) > 1+mitk::eps && std::fabs(eigenValue)< 2 - mitk::eps)
705  {
706  C2 += i;
707  D2 += eigenValue;
708  E2 += i * eigenValue;
709  F2 += i * i;
710  N2 ++;
711  }
712 
713  //2
714  else if(std::fabs( std::fabs(eigenValue) - 2) < mitk::eps)
715  {
716  m_NormalizedLaplacianNumberOf2s++;
717  }
718  }
719 
720  b1 = (D1*F1 - C1*E1)/(F1*N1 - C1*C1);
721  m_NormalizedLaplacianLowerSlope = (E1 - b1*C1)/F1;
722 
723  b2 = (D2*F2 - C2*E2)/(F2*N2 - C2*C2);
724  m_NormalizedLaplacianUpperSlope = (E2 - b2*C2)/F2;
725 }
726 
728 {
729  double k( this->GetAverageDegree() );
730  double N( this->GetNumberOfVertices() );
731  // The clustering coefficient of an Erdos-Reny network is equivalent to
732  // the likelihood two random nodes are connected
733  double gamma = this->GetAverageClusteringCoefficientsC() / ( k / N );
734  //The mean path length of an Erdos-Reny network is approximately
735  // ln( #vertices ) / ln( average degree )
736  double lambda = this->GetAveragePathLength() / ( std::log( N ) / std::log( k ) );
737 
738  m_SmallWorldness = gamma / lambda;
739 }
itk::SmartPointer< Self > Pointer
boost::graph_traits< NetworkType >::edge_iterator EdgeIteratorType
void CalculateClusteringCoefficients()
Calculate the different clustering coefficients.
std::map< EdgeDescriptorType, int > EdgeIndexStdMapType
mitk::ConnectomicsNetwork::VertexDescriptorType VertexDescriptorType
boost::graph_traits< NetworkType >::vertex_iterator VertexIteratorType
boost::associative_property_map< EdgeIndexStdMapType > EdgeIndexMapType
static T max(T x, T y)
Definition: svm.cpp:70
boost::iterator_property_map< std::vector< double >::iterator, VertexIndexMapType > VertexIteratorPropertyMapType
void CalculateSmallWorldness()
Calculate the small worldness of the network.
MITKCORE_EXPORT const ScalarType eps
boost::property_map< NetworkType, boost::vertex_index_t >::type VertexIndexMapType
boost::iterator_property_map< std::vector< double >::iterator, EdgeIndexMapType > EdgeIteratorPropertyMapType