Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
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