18 #ifndef itkSymmetricEigenAnalysis_h
19 #define itkSymmetricEigenAnalysis_h
22 #include "itk_eigen.h"
23 #include ITK_EIGEN(Eigenvalues)
27 #include "vnl/vnl_matrix.h"
28 #include "vnl/vnl_matrix_fixed.h"
36 template<
typename TValueType,
unsigned int NRows,
unsigned int NCols>
39 return inputMatrix.data_block();
41 template<
typename TValueType>
44 return inputMatrix.data_block();
47 template<
typename TValueType,
unsigned int NRows,
unsigned int NCols>
68 template<
typename TArray>
71 std::vector<int> indicesSortPermutations(numberOfElements, 0);
72 std::iota(std::begin(indicesSortPermutations), std::end(indicesSortPermutations), 0);
76 std::begin(indicesSortPermutations),
77 std::end(indicesSortPermutations),
78 [&eigenValues](
unsigned int a,
unsigned int b)
79 {
return std::abs(eigenValues[a]) < std::abs(eigenValues[b]); }
81 auto tmpCopy = eigenValues;
82 for (
unsigned int i = 0; i < numberOfElements; ++i)
84 eigenValues[i] = tmpCopy[indicesSortPermutations[i]];
86 return indicesSortPermutations;
97 template<
typename QMatrix>
99 const std::vector<int> & indicesSortPermutations)
101 using EigenLibPermutationMatrix =
102 Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic>;
103 auto numberOfElements = indicesSortPermutations.size();
106 EigenLibPermutationMatrix perm(numberOfElements);
108 std::copy(indicesSortPermutations.begin(), indicesSortPermutations.end(),
109 perm.indices().data());
111 eigenVectors = eigenVectors * perm;
151 template<
typename TMatrix,
typename TVector,
typename TEigenMatrix = TMatrix >
164 m_OrderEigenValues(OrderByValue) {}
167 m_UseEigenLibrary(false),
168 m_Dimension(dimension),
170 m_OrderEigenValues(OrderByValue) {}
191 unsigned int ComputeEigenValues(
193 TVector & EigenValues)
const;
215 unsigned int ComputeEigenValuesAndVectors(
217 TVector & EigenValues,
218 TEigenMatrix & EigenVectors)
const;
237 if ( b ) { m_OrderEigenValues = OrderByValue; }
238 else { m_OrderEigenValues = DoNotOrder; }
249 if ( b ) { m_OrderEigenValues = OrderByMagnitude; }
250 else { m_OrderEigenValues = DoNotOrder; }
263 m_Order = m_Dimension;
275 m_UseEigenLibrary = input;
279 m_UseEigenLibrary =
true;
283 m_UseEigenLibrary =
false;
287 bool m_UseEigenLibrary{
false};
288 unsigned int m_Dimension{0};
289 unsigned int m_Order{0};
312 void ReduceToTridiagonalMatrix(
double *inputMatrix,
double *d,
313 double *
e,
double *e2)
const;
336 void ReduceToTridiagonalMatrixAndGetTransformation(
337 double *inputMatrix,
double *diagonalElements,
338 double *subDiagonalElements,
double *transformMatrix)
const;
369 unsigned int ComputeEigenValuesUsingQL(
double *d,
double *
e)
const;
408 unsigned int ComputeEigenValuesAndVectorsUsingQL(
double *d,
double *
e,
double *z)
const;
413 unsigned int ComputeEigenValuesLegacy(
415 TVector & EigenValues)
const;
417 unsigned int ComputeEigenValuesAndVectorsLegacy(
419 TVector & EigenValues,
420 TEigenMatrix & EigenVectors)
const;
436 template<
typename QMatrix = TMatrix >
438 -> typename QMatrix::element_type
440 return QMatrix::element_type();
442 template<
typename QMatrix = TMatrix >
444 -> typename QMatrix::ValueType
446 return QMatrix::ValueType();
452 TVector & EigenValues,
453 TEigenMatrix & EigenVectors)
const
455 return ComputeEigenValuesAndVectorsWithEigenLibraryImpl(
456 A, EigenValues, EigenVectors,
true);
465 template<
typename QMatrix >
468 TVector & EigenValues,
469 TEigenMatrix & EigenVectors,
471 -> decltype(static_cast<
unsigned int>(1))
473 using ValueType = decltype(GetMatrixValueType(
true));
474 using EigenLibMatrixType =
475 Eigen::Matrix< ValueType, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
476 EigenLibMatrixType inputMatrix( m_Dimension, m_Dimension);
477 for (
unsigned int row = 0; row < m_Dimension; ++row)
479 for (
unsigned int col = 0; col < m_Dimension; ++col)
481 inputMatrix(row, col) = A(row, col);
484 using EigenSolverType = Eigen::SelfAdjointEigenSolver<EigenLibMatrixType>;
485 EigenSolverType solver(inputMatrix);
486 const auto &eigenValues = solver.eigenvalues();
490 const auto &eigenVectors = solver.eigenvectors();
492 if(m_OrderEigenValues == OrderByMagnitude)
494 auto copyEigenValues = eigenValues;
495 auto copyEigenVectors = eigenVectors;
499 for (
unsigned int row = 0; row < m_Dimension; ++row)
501 EigenValues[row] = copyEigenValues[row];
502 for (
unsigned int col = 0; col < m_Dimension; ++col)
504 EigenVectors[row][col] = copyEigenVectors(col, row);
510 for (
unsigned int row = 0; row < m_Dimension; ++row)
512 EigenValues[row] = eigenValues[row];
513 for (
unsigned int col = 0; col < m_Dimension; ++col)
515 EigenVectors[row][col] = eigenVectors(col, row);
533 template<
typename QMatrix >
536 TVector & EigenValues,
537 TEigenMatrix & EigenVectors,
542 using PointerType = decltype(pointerToData);
543 using ValueTypeCV =
typename std::remove_pointer<PointerType>::type;
544 using ValueType =
typename std::remove_cv<ValueTypeCV>::type;
545 using EigenLibMatrixType =
546 Eigen::Matrix< ValueType, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
547 using EigenConstMatrixMap = Eigen::Map<const EigenLibMatrixType>;
548 EigenConstMatrixMap inputMatrix(pointerToData, m_Dimension, m_Dimension);
549 using EigenSolverType = Eigen::SelfAdjointEigenSolver<EigenLibMatrixType>;
550 EigenSolverType solver(inputMatrix);
551 const auto & eigenValues = solver.eigenvalues();
555 const auto & eigenVectors = solver.eigenvectors();
556 if(m_OrderEigenValues == OrderByMagnitude)
558 auto copyEigenValues = eigenValues;
559 auto copyEigenVectors = eigenVectors;
562 for (
unsigned int row = 0; row < m_Dimension; ++row)
564 EigenValues[row] = copyEigenValues[row];
565 for (
unsigned int col = 0; col < m_Dimension; ++col)
567 EigenVectors[row][col] = copyEigenVectors(col, row);
573 for (
unsigned int row = 0; row < m_Dimension; ++row)
575 EigenValues[row] = eigenValues[row];
576 for (
unsigned int col = 0; col < m_Dimension; ++col)
578 EigenVectors[row][col] = eigenVectors(col, row);
589 TVector & EigenValues)
const
591 return ComputeEigenValuesWithEigenLibraryImpl(
592 A, EigenValues,
true);
601 template<
typename QMatrix >
604 TVector & EigenValues,
606 -> decltype(static_cast<
unsigned int>(1))
608 using ValueType = decltype(GetMatrixValueType(
true));
609 using EigenLibMatrixType =
610 Eigen::Matrix< ValueType, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
611 EigenLibMatrixType inputMatrix(m_Dimension, m_Dimension);
612 for (
unsigned int row = 0; row < m_Dimension; ++row)
614 for (
unsigned int col = 0; col < m_Dimension; ++col)
616 inputMatrix(row, col) = A(row, col);
619 using EigenSolverType = Eigen::SelfAdjointEigenSolver<EigenLibMatrixType>;
620 EigenSolverType solver(inputMatrix, Eigen::EigenvaluesOnly);
621 auto eigenValues = solver.eigenvalues();
622 if(m_OrderEigenValues == OrderByMagnitude)
626 for (
unsigned int i = 0; i < m_Dimension; ++i)
628 EigenValues[i] = eigenValues[i];
644 template<
typename QMatrix >
647 TVector & EigenValues,
652 using PointerType = decltype(pointerToData);
653 using ValueTypeCV =
typename std::remove_pointer<PointerType>::type;
654 using ValueType =
typename std::remove_cv<ValueTypeCV>::type;
655 using EigenLibMatrixType =
656 Eigen::Matrix< ValueType, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
657 using EigenConstMatrixMap = Eigen::Map<const EigenLibMatrixType>;
658 EigenConstMatrixMap inputMatrix(pointerToData, m_Dimension, m_Dimension);
659 using EigenSolverType = Eigen::SelfAdjointEigenSolver<EigenLibMatrixType>;
660 EigenSolverType solver(inputMatrix, Eigen::EigenvaluesOnly);
661 auto eigenValues = solver.eigenvalues();
662 if(m_OrderEigenValues == OrderByMagnitude)
666 for (
unsigned int i = 0; i < m_Dimension; ++i)
668 EigenValues[i] = eigenValues[i];
675 template<
typename TMatrix,
typename TVector,
typename TEigenMatrix >
679 os <<
"[ClassType: SymmetricEigenAnalysis]" << std::endl;
681 os <<
" Order : " << s.
GetOrder() << std::endl;
688 template<
unsigned int VDimension,
typename TMatrix,
typename TVector,
typename TEigenMatrix = TMatrix >
722 TVector & EigenValues)
const
724 return ComputeEigenValuesWithEigenLibraryImpl(
725 A, EigenValues,
true);
750 TVector & EigenValues,
751 TEigenMatrix & EigenVectors)
const
753 return ComputeEigenValuesAndVectorsWithEigenLibraryImpl(
754 A, EigenValues, EigenVectors,
true);
759 if ( b ) { m_OrderEigenValues = OrderByValue; }
760 else { m_OrderEigenValues = DoNotOrder; }
765 if ( b ) { m_OrderEigenValues = OrderByMagnitude; }
766 else { m_OrderEigenValues = DoNotOrder; }
769 constexpr
unsigned int GetOrder()
const {
return VDimension; }
784 template<
typename QMatrix = TMatrix >
786 -> typename QMatrix::element_type
788 return QMatrix::element_type();
790 template<
typename QMatrix = TMatrix >
792 -> typename QMatrix::ValueType
794 return QMatrix::ValueType();
806 template<
typename QMatrix >
809 TVector & EigenValues,
810 TEigenMatrix & EigenVectors,
815 using PointerType = decltype(pointerToData);
816 using ValueTypeCV =
typename std::remove_pointer<PointerType>::type;
817 using ValueType =
typename std::remove_cv<ValueTypeCV>::type;
818 using EigenLibMatrixType = Eigen::Matrix< ValueType, VDimension, VDimension, Eigen::RowMajor>;
819 using EigenConstMatrixMap = Eigen::Map<const EigenLibMatrixType>;
820 EigenConstMatrixMap inputMatrix(pointerToData);
821 using EigenSolverType = Eigen::SelfAdjointEigenSolver<EigenLibMatrixType>;
822 EigenSolverType solver(inputMatrix);
823 const auto & eigenValues = solver.eigenvalues();
827 const auto & eigenVectors = solver.eigenvectors();
828 if(m_OrderEigenValues == OrderByMagnitude)
830 auto copyEigenValues = eigenValues;
831 auto copyEigenVectors = eigenVectors;
834 for (
unsigned int row = 0; row < VDimension; ++row)
836 EigenValues[row] = copyEigenValues[row];
837 for (
unsigned int col = 0; col < VDimension; ++col)
839 EigenVectors[row][col] = copyEigenVectors(col, row);
845 for (
unsigned int row = 0; row < VDimension; ++row)
847 EigenValues[row] = eigenValues[row];
848 for (
unsigned int col = 0; col < VDimension; ++col)
850 EigenVectors[row][col] = eigenVectors(col, row);
864 template<
typename QMatrix >
867 TVector & EigenValues,
868 TEigenMatrix & EigenVectors,
870 -> decltype(static_cast<
unsigned int>(1))
872 using ValueType = decltype(GetMatrixValueType(
true));
873 using EigenLibMatrixType = Eigen::Matrix< ValueType, VDimension, VDimension, Eigen::RowMajor>;
874 EigenLibMatrixType inputMatrix;
875 for (
unsigned int row = 0; row < VDimension; ++row)
877 for (
unsigned int col = 0; col < VDimension; ++col)
879 inputMatrix(row, col) = A(row, col);
882 using EigenSolverType = Eigen::SelfAdjointEigenSolver<EigenLibMatrixType>;
883 EigenSolverType solver(inputMatrix);
884 const auto &eigenValues = solver.eigenvalues();
888 const auto &eigenVectors = solver.eigenvectors();
890 if(m_OrderEigenValues == OrderByMagnitude)
892 auto copyEigenValues = eigenValues;
893 auto copyEigenVectors = eigenVectors;
897 for (
unsigned int row = 0; row < VDimension; ++row)
899 EigenValues[row] = copyEigenValues[row];
900 for (
unsigned int col = 0; col < VDimension; ++col)
902 EigenVectors[row][col] = copyEigenVectors(col, row);
908 for (
unsigned int row = 0; row < VDimension; ++row)
910 EigenValues[row] = eigenValues[row];
911 for (
unsigned int col = 0; col < VDimension; ++col)
913 EigenVectors[row][col] = eigenVectors(col, row);
927 template<
typename QMatrix >
930 TVector & EigenValues,
932 -> decltype(static_cast<
unsigned int>(1))
934 using ValueType = decltype(GetMatrixValueType(
true));
935 using EigenLibMatrixType = Eigen::Matrix< ValueType, VDimension, VDimension, Eigen::RowMajor>;
936 EigenLibMatrixType inputMatrix;
937 for (
unsigned int row = 0; row < VDimension; ++row)
939 for (
unsigned int col = 0; col < VDimension; ++col)
941 inputMatrix(row, col) = A(row, col);
944 using EigenSolverType = Eigen::SelfAdjointEigenSolver<EigenLibMatrixType>;
945 EigenSolverType solver(inputMatrix, Eigen::EigenvaluesOnly);
946 auto eigenValues = solver.eigenvalues();
947 if(m_OrderEigenValues == OrderByMagnitude)
951 for (
unsigned int i = 0; i < VDimension; ++i)
953 EigenValues[i] = eigenValues[i];
969 template<
typename QMatrix >
972 TVector & EigenValues,
977 using PointerType = decltype(pointerToData);
978 using ValueTypeCV =
typename std::remove_pointer<PointerType>::type;
979 using ValueType =
typename std::remove_cv<ValueTypeCV>::type;
980 using EigenLibMatrixType = Eigen::Matrix< ValueType, VDimension, VDimension, Eigen::RowMajor>;
981 using EigenConstMatrixMap = Eigen::Map<const EigenLibMatrixType>;
982 EigenConstMatrixMap inputMatrix(pointerToData);
983 using EigenSolverType = Eigen::SelfAdjointEigenSolver<EigenLibMatrixType>;
984 EigenSolverType solver(inputMatrix, Eigen::EigenvaluesOnly);
985 auto eigenValues = solver.eigenvalues();
986 if(m_OrderEigenValues == OrderByMagnitude)
990 for (
unsigned int i = 0; i < VDimension; ++i)
992 EigenValues[i] = eigenValues[i];
999 template<
unsigned int VDimension,
typename TMatrix,
typename TVector,
typename TEigenMatrix >
1002 TMatrix, TVector, TEigenMatrix > & s)
1004 os <<
"[ClassType: SymmetricEigenAnalysisFixedDimension]" << std::endl;
1005 os <<
" Dimension : " << s.GetDimension() << std::endl;
1006 os <<
" Order : " << s.GetOrder() << std::endl;
1007 os <<
" OrderEigenValues: " << s.GetOrderEigenValues() << std::endl;
1008 os <<
" OrderEigenMagnitudes: " << s.GetOrderEigenMagnitudes() << std::endl;
1009 os <<
" UseEigenLibrary: " << s.GetUseEigenLibrary() << std::endl;
1014 #ifndef ITK_MANUAL_INSTANTIATION
1015 #include "itkSymmetricEigenAnalysis.hxx"
A templated class holding a M x N size Matrix.
auto ComputeEigenValuesAndVectorsWithEigenLibraryImpl(const QMatrix &A, TVector &EigenValues, TEigenMatrix &EigenVectors, bool) const -> decltype(GetPointerToMatrixData(A), static_cast< unsigned int >(1))
auto ComputeEigenValuesWithEigenLibraryImpl(const QMatrix &A, TVector &EigenValues, long) const -> decltype(static_cast< unsigned int >(1))
Find Eigen values of a real 2D symmetric matrix. It serves as a thread-safe alternative to the class:...
auto GetMatrixValueType(bool) const -> typename QMatrix::element_type
constexpr bool GetUseEigenLibrary() const
auto ComputeEigenValuesWithEigenLibraryImpl(const QMatrix &A, TVector &EigenValues, bool) const -> decltype(GetPointerToMatrixData(A), static_cast< unsigned int >(1))
TInputImage::PixelType MatrixType
bool GetOrderEigenValues() const
constexpr unsigned int GetDimension() const
EigenValueOrderType m_OrderEigenValues
SymmetricEigenAnalysisFixedDimension()
std::ostream & operator<<(std::ostream &os, const Array< TValue > &arr)
void SetOrder(const unsigned int n)
void SetUseEigenLibraryOff()
const TValueType * GetPointerToMatrixData(const vnl_matrix_fixed< TValueType, NRows, NCols > &inputMatrix)
unsigned int ComputeEigenValues(const TMatrix &A, TVector &EigenValues) const
bool GetUseEigenLibrary() const
void SetUseEigenLibrary(const bool input)
unsigned int ComputeEigenValuesAndVectors(const TMatrix &A, TVector &EigenValues, TEigenMatrix &EigenVectors) const
auto ComputeEigenValuesWithEigenLibraryImpl(const QMatrix &A, TVector &EigenValues, long) const -> decltype(static_cast< unsigned int >(1))
void SetOrderEigenMagnitudes(const bool b)
auto GetMatrixValueType(bool) const -> typename QMatrix::ValueType
void SetOrderEigenValues(const bool b)
constexpr unsigned int GetOrder() const
auto ComputeEigenValuesAndVectorsWithEigenLibraryImpl(const QMatrix &A, TVector &EigenValues, TEigenMatrix &EigenVectors, long) const -> decltype(static_cast< unsigned int >(1))
TInputImage::PixelType EigenMatrixType
auto GetMatrixValueType(...) const -> typename QMatrix::ValueType
void permuteColumnsWithSortIndices(QMatrix &eigenVectors, const std::vector< int > &indicesSortPermutations)
bool GetOrderEigenMagnitudes() const
unsigned int ComputeEigenValuesAndVectorsWithEigenLibrary(const TMatrix &A, TVector &EigenValues, TEigenMatrix &EigenVectors) const
void SetUseEigenLibraryOn()
std::vector< int > sortEigenValuesByMagnitude(TArray &eigenValues, const unsigned int numberOfElements)
unsigned int GetDimension() const
auto GetMatrixValueType(bool) const -> typename QMatrix::element_type
void SetDimension(const unsigned int n)
TOutputImage::PixelType VectorType
EigenValueOrderType m_OrderEigenValues
InternalMatrixType & GetVnlMatrix()
bool GetOrderEigenMagnitudes() const
static constexpr double e
The base of the natural logarithm or Euler's number
void SetOrderEigenMagnitudes(const bool b)
unsigned int GetOrder() const
unsigned int ComputeEigenValuesWithEigenLibrary(const TMatrix &A, TVector &EigenValues) const
auto ComputeEigenValuesAndVectorsWithEigenLibraryImpl(const QMatrix &A, TVector &EigenValues, TEigenMatrix &EigenVectors, long) const -> decltype(static_cast< unsigned int >(1))
auto ComputeEigenValuesWithEigenLibraryImpl(const QMatrix &A, TVector &EigenValues, bool) const -> decltype(GetPointerToMatrixData(A), static_cast< unsigned int >(1))
SymmetricEigenAnalysis(const unsigned int dimension)
bool GetOrderEigenValues() const
void SetOrderEigenValues(const bool b)
auto ComputeEigenValuesAndVectorsWithEigenLibraryImpl(const QMatrix &A, TVector &EigenValues, TEigenMatrix &EigenVectors, bool) const -> decltype(GetPointerToMatrixData(A), static_cast< unsigned int >(1))