void  mitk::ConnectomicsStatisticsCalculator::CalculateNormalizedLaplacianMetrics()
{
  vnl_matrix<double> normalizedLaplacianMatrix(m_NumberOfVertices, m_NumberOfVertices, 0);
  EdgeIteratorType ei, ei_end;
  VertexDescriptorType sourceVertex, destinationVertex;
  int sourceIndex, destinationIndex;
  VertexIndexMapType vertexIndexMap = boost::get(boost::vertex_index, *(m_Network->GetBoostGraph()) );
  m_VectorOfSortedNormalizedLaplacianEigenValues.clear();

  // Normalized laplacian matrix
  for( boost::tie(ei, ei_end) = boost::edges( *(m_Network->GetBoostGraph()) ); ei != ei_end; ++ei)
  {
    sourceVertex = boost::source(*ei, *(m_Network->GetBoostGraph()) );
    sourceIndex = vertexIndexMap[sourceVertex];

    destinationVertex = boost::target(*ei, *(m_Network->GetBoostGraph()) );
    destinationIndex = vertexIndexMap[destinationVertex];
    int sourceDegree = boost::out_degree(sourceVertex, *(m_Network->GetBoostGraph()) );
    int destinationDegree = boost::out_degree(destinationVertex, *(m_Network->GetBoostGraph()) );

    normalizedLaplacianMatrix.put(
      sourceIndex, destinationIndex, -1 / (sqrt(double(sourceDegree * destinationDegree))));
    normalizedLaplacianMatrix.put(
      destinationIndex, sourceIndex, -1 / (sqrt(double(sourceDegree * destinationDegree))));
  }

  VertexIteratorType vi, vi_end;
  for(boost::tie(vi, vi_end)=boost::vertices( *(m_Network->GetBoostGraph()) ); vi!=vi_end; ++vi)
  {
    if(boost::out_degree(*vi, *(m_Network->GetBoostGraph()) ) > 0)
    {
      normalizedLaplacianMatrix.put(vertexIndexMap[*vi], vertexIndexMap[*vi], 1);
    }
  }
  //End of normalized laplacian matrix definition

  vnl_symmetric_eigensystem <double>
    normalizedLaplacianEigensystem(normalizedLaplacianMatrix);

  double N1=0, C1=0, D1=0, E1=0, F1=0, b1=0;
  double N2=0, C2=0, D2=0, E2=0, F2=0, b2=0;
  m_NormalizedLaplacianNumberOf2s = 0;
  m_NormalizedLaplacianNumberOf1s = 0;
  m_NormalizedLaplacianNumberOf0s = 0;
  m_NormalizedLaplacianTrace = 0;
  m_NormalizedLaplacianEnergy = 0;

  for(int i(0); i< m_NumberOfVertices; ++i)
  {
    double eigenValue = std::fabs(normalizedLaplacianEigensystem.get_eigenvalue(i));
    m_VectorOfSortedNormalizedLaplacianEigenValues.push_back(eigenValue);
    m_NormalizedLaplacianTrace  += eigenValue;
    m_NormalizedLaplacianEnergy += eigenValue * eigenValue;

    //0
    if(eigenValue < mitk::eps)
    {
      m_NormalizedLaplacianNumberOf0s++;
    }

    //Between 0 and 1.
    else if(eigenValue > mitk::eps && eigenValue< 1 - mitk::eps)
    {
      C1 += i;
      D1 += eigenValue;
      E1 += i * eigenValue;
      F1 += i * i;
      N1 ++;
    }

    //1
    else if(std::fabs( std::fabs(eigenValue) - 1) < mitk::eps)
    {
      m_NormalizedLaplacianNumberOf1s++;
    }

    //Between 1 and 2
    else if(std::fabs(eigenValue) > 1+mitk::eps && std::fabs(eigenValue)< 2 - mitk::eps)
    {
      C2 += i;
      D2 += eigenValue;
      E2 += i * eigenValue;
      F2 += i * i;
      N2 ++;
    }

    //2
    else if(std::fabs( std::fabs(eigenValue) - 2) < mitk::eps)
    {
      m_NormalizedLaplacianNumberOf2s++;
    }
  }

  b1 = (D1*F1 - C1*E1)/(F1*N1 - C1*C1);
  m_NormalizedLaplacianLowerSlope = (E1 - b1*C1)/F1;

  b2 = (D2*F2 - C2*E2)/(F2*N2 - C2*C2);
  m_NormalizedLaplacianUpperSlope = (E2 - b2*C2)/F2;
}
TEST(NormalizedLaplacianMatrixGTest, testSmallNormalizedLaplacianMatrix) {
	NetworKit::Graph graph(7);
	graph.addEdge(0, 1);
	graph.addEdge(0, 4);
	graph.addEdge(1, 4);
	graph.addEdge(1, 2);
	graph.addEdge(2, 3);
	graph.addEdge(3, 4);
	graph.addEdge(3, 5);

	NormalizedLaplacianMatrix normalizedLaplacianMatrix(graph);
	ASSERT_EQ(graph.numberOfNodes(), normalizedLaplacianMatrix.numberOfRows());
	ASSERT_EQ(graph.numberOfNodes(), normalizedLaplacianMatrix.numberOfColumns());

	EXPECT_EQ(1, normalizedLaplacianMatrix(0,0));
	EXPECT_EQ(-1.0 / sqrt(2.0 * 3.0), normalizedLaplacianMatrix(0,1));
	EXPECT_EQ(0, normalizedLaplacianMatrix(0,2));
	EXPECT_EQ(0, normalizedLaplacianMatrix(0,3));
	EXPECT_EQ(-1.0 / sqrt(2.0 * 3.0), normalizedLaplacianMatrix(0,4));
	EXPECT_EQ(0, normalizedLaplacianMatrix(0,5));
	EXPECT_EQ(0, normalizedLaplacianMatrix(0,6));
	EXPECT_EQ(1, normalizedLaplacianMatrix(1,1));
	EXPECT_EQ(-1.0 / sqrt(2.0 * 3.0), normalizedLaplacianMatrix(1,2));
	EXPECT_EQ(0, normalizedLaplacianMatrix(1,3));
	EXPECT_EQ(-1.0 / 3.0, normalizedLaplacianMatrix(1,4));
	EXPECT_EQ(0, normalizedLaplacianMatrix(1,5));
	EXPECT_EQ(0, normalizedLaplacianMatrix(1,6));
	EXPECT_EQ(1, normalizedLaplacianMatrix(2,2));
	EXPECT_EQ(-1.0 / sqrt(2.0 * 3.0), normalizedLaplacianMatrix(2,3));
	EXPECT_EQ(0, normalizedLaplacianMatrix(2,4));
	EXPECT_EQ(0, normalizedLaplacianMatrix(2,5));
	EXPECT_EQ(0, normalizedLaplacianMatrix(2,6));
	EXPECT_EQ(1, normalizedLaplacianMatrix(3,3));
	EXPECT_EQ(-1.0 / 3.0, normalizedLaplacianMatrix(3,4));
	EXPECT_EQ(-1.0 / sqrt(3.0), normalizedLaplacianMatrix(3,5));
	EXPECT_EQ(0, normalizedLaplacianMatrix(3,6));
	EXPECT_EQ(1, normalizedLaplacianMatrix(4,4));
	EXPECT_EQ(0, normalizedLaplacianMatrix(4,5));
	EXPECT_EQ(0, normalizedLaplacianMatrix(4,6));
	EXPECT_EQ(1, normalizedLaplacianMatrix(5,5));
	EXPECT_EQ(0, normalizedLaplacianMatrix(5,6));
	EXPECT_EQ(0, normalizedLaplacianMatrix(6,6));
}