From 2a5c654ff8212da4faffe8d688e2702c7bf2ea85 Mon Sep 17 00:00:00 2001 From: Jon Haitz Legarreta Date: Tue, 11 Apr 2017 19:44:54 +0200 Subject: [PATCH 01/21] ENH: Honor the ITK conventions to name modules, flags and folders. Add the 'Module_' prefix to the module's flags so that they can be grouped together with the module itself by the CMake GUI. Change the 'Examples' and 'Documentation' folder names to 'examples' and 'doc' respectively. Make the module's example and documentation build flags dependent on ITK's BUILD_EXAMPLES and BUILD_DOCUMENTATION flags: if the latter are set to OFF, the module's options will remain hidden and defaulted to OFF. --- CMakeLists.txt | 19 +++++++++--------- {Documents => doc}/CMakeLists.txt | 0 {Documents => doc}/Report001/CMakeLists.txt | 0 ...udateFirstPrincipalComponentOnMomentum.jpg | Bin .../Report001/InsightArticle.cls | 0 .../Report001/InsightJournal.bib | 0 .../Report001/InsightJournal.ist | 0 .../Report001/InsightJournal.sty | 0 .../Report001/PrincipalComponentsAnalysis.tex | 0 {Documents => doc}/Report001/algorithm.sty | 0 {Documents => doc}/Report001/algorithmic.sty | 0 {Documents => doc}/Report001/amssymb.sty | 0 {Documents => doc}/Report001/fancyhdr.sty | 0 {Documents => doc}/Report001/floatflt.sty | 0 {Documents => doc}/Report001/fncychap.sty | 0 {Documents => doc}/Report001/picins.sty | 0 {Documents => doc}/Report001/times.sty | 0 {Examples => examples}/CMakeLists.txt | 0 {Examples => examples}/VectorKernelPCA.cxx | 0 19 files changed, 10 insertions(+), 9 deletions(-) rename {Documents => doc}/CMakeLists.txt (100%) rename {Documents => doc}/Report001/CMakeLists.txt (100%) rename {Documents => doc}/Report001/CaudateFirstPrincipalComponentOnMomentum.jpg (100%) rename {Documents => doc}/Report001/InsightArticle.cls (100%) rename {Documents => doc}/Report001/InsightJournal.bib (100%) rename {Documents => doc}/Report001/InsightJournal.ist (100%) rename {Documents => doc}/Report001/InsightJournal.sty (100%) rename {Documents => doc}/Report001/PrincipalComponentsAnalysis.tex (100%) rename {Documents => doc}/Report001/algorithm.sty (100%) rename {Documents => doc}/Report001/algorithmic.sty (100%) rename {Documents => doc}/Report001/amssymb.sty (100%) rename {Documents => doc}/Report001/fancyhdr.sty (100%) rename {Documents => doc}/Report001/floatflt.sty (100%) rename {Documents => doc}/Report001/fncychap.sty (100%) rename {Documents => doc}/Report001/picins.sty (100%) rename {Documents => doc}/Report001/times.sty (100%) rename {Examples => examples}/CMakeLists.txt (100%) rename {Examples => examples}/VectorKernelPCA.cxx (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2231f55..9d93f3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,10 +3,10 @@ IF(COMMAND CMAKE_POLICY) CMAKE_POLICY(SET CMP0003 NEW) ENDIF(COMMAND CMAKE_POLICY) -SET(kit PrincipalComponentsAnalysis) -PROJECT(${kit}) +SET(PCA PrincipalComponentsAnalysis) +PROJECT(${PCA}) -IF (NOT ITK_SOURCE_DIR) +IF(NOT ITK_SOURCE_DIR) FIND_PACKAGE(ITK REQUIRED) LIST(APPEND CMAKE_MODULE_PATH ${ITK_CMAKE_DIR}) INCLUDE(ITKModuleExternal) @@ -14,13 +14,14 @@ ELSE() itk_module_impl() ENDIF() -OPTION(${kit}_BUILD_EXAMPLES "Build the examples" OFF) -IF(${kit}_BUILD_EXAMPLES) - ADD_SUBDIRECTORY( Examples ) +CMAKE_DEPENDENT_OPTION(Module_${PCA}_BUILD_EXAMPLES "Build the examples" OFF "BUILD_EXAMPLES" OFF) +if(Module_${PCA}_BUILD_EXAMPLES) + ADD_SUBDIRECTORY( examples ) ENDIF() -OPTION(${kit}_GENERATE_REPORT "Generate the PDF report from latex files, source code examples and result screenshots" OFF) -IF(${kit}_GENERATE_REPORT) - ADD_SUBDIRECTORY( Documents ) +CMAKE_DEPENDENT_OPTION(Module_${PCA}_BUILD_DOCUMENTATION "Generate documentation from LaTeX files, source code examples and result screenshots" OFF + "BUILD_DOCUMENTATION" OFF) +IF(Module_${PCA}_BUILD_DOCUMENTATION) + ADD_SUBDIRECTORY( doc ) ENDIF() diff --git a/Documents/CMakeLists.txt b/doc/CMakeLists.txt similarity index 100% rename from Documents/CMakeLists.txt rename to doc/CMakeLists.txt diff --git a/Documents/Report001/CMakeLists.txt b/doc/Report001/CMakeLists.txt similarity index 100% rename from Documents/Report001/CMakeLists.txt rename to doc/Report001/CMakeLists.txt diff --git a/Documents/Report001/CaudateFirstPrincipalComponentOnMomentum.jpg b/doc/Report001/CaudateFirstPrincipalComponentOnMomentum.jpg similarity index 100% rename from Documents/Report001/CaudateFirstPrincipalComponentOnMomentum.jpg rename to doc/Report001/CaudateFirstPrincipalComponentOnMomentum.jpg diff --git a/Documents/Report001/InsightArticle.cls b/doc/Report001/InsightArticle.cls similarity index 100% rename from Documents/Report001/InsightArticle.cls rename to doc/Report001/InsightArticle.cls diff --git a/Documents/Report001/InsightJournal.bib b/doc/Report001/InsightJournal.bib similarity index 100% rename from Documents/Report001/InsightJournal.bib rename to doc/Report001/InsightJournal.bib diff --git a/Documents/Report001/InsightJournal.ist b/doc/Report001/InsightJournal.ist similarity index 100% rename from Documents/Report001/InsightJournal.ist rename to doc/Report001/InsightJournal.ist diff --git a/Documents/Report001/InsightJournal.sty b/doc/Report001/InsightJournal.sty similarity index 100% rename from Documents/Report001/InsightJournal.sty rename to doc/Report001/InsightJournal.sty diff --git a/Documents/Report001/PrincipalComponentsAnalysis.tex b/doc/Report001/PrincipalComponentsAnalysis.tex similarity index 100% rename from Documents/Report001/PrincipalComponentsAnalysis.tex rename to doc/Report001/PrincipalComponentsAnalysis.tex diff --git a/Documents/Report001/algorithm.sty b/doc/Report001/algorithm.sty similarity index 100% rename from Documents/Report001/algorithm.sty rename to doc/Report001/algorithm.sty diff --git a/Documents/Report001/algorithmic.sty b/doc/Report001/algorithmic.sty similarity index 100% rename from Documents/Report001/algorithmic.sty rename to doc/Report001/algorithmic.sty diff --git a/Documents/Report001/amssymb.sty b/doc/Report001/amssymb.sty similarity index 100% rename from Documents/Report001/amssymb.sty rename to doc/Report001/amssymb.sty diff --git a/Documents/Report001/fancyhdr.sty b/doc/Report001/fancyhdr.sty similarity index 100% rename from Documents/Report001/fancyhdr.sty rename to doc/Report001/fancyhdr.sty diff --git a/Documents/Report001/floatflt.sty b/doc/Report001/floatflt.sty similarity index 100% rename from Documents/Report001/floatflt.sty rename to doc/Report001/floatflt.sty diff --git a/Documents/Report001/fncychap.sty b/doc/Report001/fncychap.sty similarity index 100% rename from Documents/Report001/fncychap.sty rename to doc/Report001/fncychap.sty diff --git a/Documents/Report001/picins.sty b/doc/Report001/picins.sty similarity index 100% rename from Documents/Report001/picins.sty rename to doc/Report001/picins.sty diff --git a/Documents/Report001/times.sty b/doc/Report001/times.sty similarity index 100% rename from Documents/Report001/times.sty rename to doc/Report001/times.sty diff --git a/Examples/CMakeLists.txt b/examples/CMakeLists.txt similarity index 100% rename from Examples/CMakeLists.txt rename to examples/CMakeLists.txt diff --git a/Examples/VectorKernelPCA.cxx b/examples/VectorKernelPCA.cxx similarity index 100% rename from Examples/VectorKernelPCA.cxx rename to examples/VectorKernelPCA.cxx From 9fb4e23861d9d9f2dbf61aec24f748d1c3116f4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sat, 22 Apr 2017 18:31:08 +0200 Subject: [PATCH 02/21] STYLE: Improve the itkVectorFieldPCA class style. Use the ITK_DISALLOW_COPY_AND_ASSIGN macro to save typing the copy and assignment method disallow statements. Use initialization lists: initialize the missing m_VertexCount ivar to zero; SmartPointer initialize themselves to the null pointer. Print all member variables. Use the itkPrintSelfObjectMacro macro to print SmartPointers. Remove unnecessary/ducplicate/empty Doxygen-style, out-of-method-body documentation from the implementation file/use it to improve the method documentation in the header file. Use the 'this' keyword when calling self functions. Make flow control variables have a more local scope. Start comments with capital letters. --- include/itkVectorFieldPCA.h | 13 +-- include/itkVectorFieldPCA.hxx | 189 +++++++++++++++------------------- test/CMakeLists.txt | 10 +- 3 files changed, 96 insertions(+), 116 deletions(-) diff --git a/include/itkVectorFieldPCA.h b/include/itkVectorFieldPCA.h index 8b32218..74312ac 100644 --- a/include/itkVectorFieldPCA.h +++ b/include/itkVectorFieldPCA.h @@ -197,13 +197,14 @@ class ITK_EXPORT VectorFieldPCA : public Object virtual ~VectorFieldPCA() {}; void PrintSelf(std::ostream& os, Indent indent) const; - void KernelPCA(void); - void computeMomentumSCP(void); + /** Kernel PCA. */ + void KernelPCA(); -private: + /** Compute Momentum SCP. */ + void ComputeMomentumSCP(); - VectorFieldPCA(const Self&); //purposely not implemented - void operator=(const Self&); //purposely not implemented +private: + ITK_DISALLOW_COPY_AND_ASSIGN(VectorFieldPCA); VectorType m_PCAEigenValues; @@ -212,7 +213,7 @@ class ITK_EXPORT VectorFieldPCA : public Object InputPointSetPointer m_PointSet; KernelFunctionPointer m_KernelFunction; - // problem dimensions + // Problem dimensions unsigned int m_ComponentCount; unsigned int m_SetSize; unsigned int m_VectorDimCount; diff --git a/include/itkVectorFieldPCA.hxx b/include/itkVectorFieldPCA.hxx index 95510e9..20dc124 100644 --- a/include/itkVectorFieldPCA.hxx +++ b/include/itkVectorFieldPCA.hxx @@ -27,9 +27,6 @@ namespace itk { -/** - * Constructor - */ template< typename TVectorFieldElementType, typename TPCType, @@ -39,22 +36,17 @@ template< class TPointSetType > VectorFieldPCA -::VectorFieldPCA() +::VectorFieldPCA() : + m_BasisVectors( BasisSetType::New() ), + m_ComponentCount( 0 ), + m_SetSize( 0 ), + m_VectorDimCount( 0 ), + m_VertexCount( 0 ), + m_PointDim( 0 ), + m_PCACalculated( false ) { - m_PCACalculated = false; - m_SetSize = 0; - m_VectorDimCount = 0; - m_PointDim = 0; - m_ComponentCount = 0; - m_KernelFunction = NULL; - m_BasisVectors = BasisSetType::New(); - m_VectorFieldSet = NULL; - m_PointSet = NULL; } -/** - * - */ template< typename TVectorFieldElementType, typename TPCType, @@ -65,71 +57,9 @@ template< > void VectorFieldPCA -::PrintSelf(std::ostream& os, Indent indent) const +::Compute() { - Superclass::PrintSelf(os,indent); - - if (this->m_VectorFieldSet.IsNull()) - { - os << indent << "Vector Field Set Empty" << std::endl; - } - else - { - os << indent << "Vector Field Set Count: " << this->m_VectorFieldSet->Size() << std::endl; - } - - os << indent << "Component Count: " << this->m_ComponentCount << std::endl; - os << indent << "Eigenvalues: " << this->m_PCAEigenValues << std::endl; - if (this->m_BasisVectors.IsNull()) - { - os << indent << "Basis Vector Empty" << std::endl; - } - else - { - os << indent << "Basis Vector Count: " << this->m_BasisVectors->Size() << std::endl; - if (this->m_BasisVectors->Size()) - { - MatrixType& thisBasis = this->m_BasisVectors->ElementAt(0); - os << indent << "Basis Vector Dimensions: " << thisBasis.rows() << "x" << thisBasis.cols() << std::endl; - } - } - - if (this->m_PointSet.IsNull()) - { - os << indent << "PointSet Empty" << std::endl; - } - else - { - os << indent << "PointSet is " << m_PointSet->GetNumberOfPoints() << - "x" << this->m_PointSet->PointDimension << std::endl; - } - - if (this->m_KernelFunction.IsNull()) - { - os << indent << "Kernel Function not set" << std::endl; - } - else - { - os << indent << "KernelFunction is set." << std::endl; - } -} - -/** - * Compute the principal components - */ -template< - typename TVectorFieldElementType, - typename TPCType, - typename TPointSetPixelType, - typename TPointSetCoordRepType, - typename KernelFunctionType, - class TPointSetType - > -void -VectorFieldPCA -::Compute(void) -{ - // check parameters + // Check parameters if (!m_VectorFieldSet || !m_VectorFieldSet->Size()) { itkExceptionMacro("Vector Field Set not specified."); @@ -144,13 +74,13 @@ VectorFieldPCAElementAt(0); m_VectorDimCount = firstField.rows(); m_PointDim = firstField.cols(); - // check all vector dimensions in the set + // Check all vector dimensions in the set for (unsigned int i = 1; i < m_VectorFieldSet->Size(); i++) { VectorFieldType& thisField = m_VectorFieldSet->ElementAt(i); @@ -190,13 +120,13 @@ VectorFieldPCAComputeMomentumSCP(); + this->KernelPCA(); - // save only the desired eigenvalues + // Save only the desired eigenvalues m_PCAEigenValues = m_PCAEigenValues.extract(m_ComponentCount); - // save only the desired eigenvectors + // Save only the desired eigenvectors m_V0 = m_V0.extract(m_V0.rows(), m_ComponentCount); m_BasisVectors->Reserve(m_ComponentCount); @@ -225,10 +155,6 @@ VectorFieldPCA void VectorFieldPCA -::computeMomentumSCP(void) +::ComputeMomentumSCP() { - VectorFieldType accum; accum.set_size(m_VectorDimCount, m_PointDim); accum = 0.0; - // determine the average of the vector field over the set + // Determine the average of the vector field over the set for (unsigned k = 0; k < m_SetSize; k++) { accum += m_VectorFieldSet->ElementAt(k); @@ -261,7 +186,7 @@ VectorFieldPCA void VectorFieldPCA -::KernelPCA(void) +::KernelPCA() { VectorType rowMeans(m_SetSize); - unsigned int k, l; - for (k = 0; k < m_SetSize; k++) + for (unsigned int k = 0; k < m_SetSize; k++) { rowMeans(k) = m_K.get_row(k).mean(); } TPCType meanOfMeans = rowMeans.mean(); MatrixType K0(m_K - meanOfMeans); - for (k = 0; k < m_SetSize; k++) + for (unsigned int k = 0; k < m_SetSize; k++) { - for (l = 0; l < m_SetSize; l++) + for (unsigned int l = 0; l < m_SetSize; l++) { K0(k, l) -= rowMeans(k) + rowMeans(l); } @@ -354,20 +275,78 @@ VectorFieldPCA eigs(K0); m_PCAEigenValues = eigs.D.diagonal(); - // eigs come out in ascending order, reorder them + + // Eigenvalues come out in ascending order, reorder them m_PCAEigenValues.flip(); - // reorder eigenvectors + // Reorder eigenvectors m_V0 = eigs.V; m_V0.fliplr(); const double eigenvalue_epsilon = 1.0e-10; - for (k = 0; k < m_SetSize; k++) + for (unsigned int k = 0; k < m_SetSize; k++) { m_V0.scale_column(k, 1.0 / vcl_sqrt(m_PCAEigenValues(k) + eigenvalue_epsilon)); } } +template< + typename TVectorFieldElementType, + typename TPCType, + typename TPointSetPixelType, + typename TPointSetCoordRepType, + typename KernelFunctionType, + class TPointSetType + > +void +VectorFieldPCA +::PrintSelf(std::ostream& os, Indent indent) const +{ + Superclass::PrintSelf( os, indent ); + + os << indent << "PCAEigenvalues: " << this->m_PCAEigenValues << std::endl; + + if( this->m_BasisVectors.IsNotNull() ) + { + os << indent << "Basis Vector count: " << this->m_BasisVectors->Size() + << std::endl; + if( this->m_BasisVectors->Size() ) + { + MatrixType& thisBasis = this->m_BasisVectors->ElementAt(0); + os << indent << "Basis Vector dimensions: " << thisBasis.rows() << "x" + << thisBasis.cols() << std::endl; + } + } + itkPrintSelfObjectMacro( BasisVectors ); + + if( this->m_VectorFieldSet.IsNotNull() ) + { + os << indent << "Vector Field Set count: " << this->m_VectorFieldSet->Size() + << std::endl; + } + itkPrintSelfObjectMacro( VectorFieldSet ); + + if( this->m_PointSet.IsNotNull() ) + { + os << indent << "PointSet dimensions: " << m_PointSet->GetNumberOfPoints() + << "x" << this->m_PointSet->PointDimension << std::endl; + } + itkPrintSelfObjectMacro( PointSet ); + + itkPrintSelfObjectMacro( KernelFunction ); + + os << indent << "ComponentCount: " << this->m_ComponentCount << std::endl; + os << indent << "SetSize: " << this->m_SetSize << std::endl; + os << indent << "VectorDimCount: " << this->m_VectorDimCount << std::endl; + os << indent << "VertexCount: " << this->m_VertexCount << std::endl; + os << indent << "PointDim: " << this->m_PointDim << std::endl; + + os << indent << "V0 : " << this->m_V0 << std::endl; + os << indent << "AveVectorField: " << this->m_AveVectorField << std::endl; + os << indent << "K: " << this->m_K << std::endl; + + os << indent << "PCACalculated: " << this->m_PCACalculated << std::endl; +} } // end namespace itk #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8e8ff2d..b446f4f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,16 +1,16 @@ itk_module_test() -SET(kit PrincipalComponentsAnalysis) -SET(${kit}Tests +SET(PCA PrincipalComponentsAnalysis) +SET(${PCA}Tests itkVectorKernelPCATest.cxx ) -SET(TEST_DATA_ROOT ${${kit}_SOURCE_DIR}/Data) +SET(TEST_DATA_ROOT ${${PCA}_SOURCE_DIR}/Data) -CreateTestDriver(${kit} "${${kit}-Test_LIBRARIES}" "${${kit}Tests}") +CreateTestDriver(${PCA} "${${PCA}-Test_LIBRARIES}" "${${PCA}Tests}") itk_add_test(NAME itkVectorKernelPCATest - COMMAND ${kit}TestDriver itkVectorKernelPCATest + COMMAND ${PCA}TestDriver itkVectorKernelPCATest DATA{${TEST_DATA_ROOT}/PCATestSurface.vtk} DATA{${TEST_DATA_ROOT}/PCATestSurface_alpha0_01.vtk} DATA{${TEST_DATA_ROOT}/PCATestSurface_alpha0_02.vtk} From a4bbbab090e3a22b280970f4a82863abeaec95e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sat, 22 Apr 2017 17:57:55 +0200 Subject: [PATCH 03/21] ENH: Improve code coverage for itk::VectorFieldPCA. Exercise basic object methods. Hence, remove the unncessary calls to the GetNameOfClass or Print methods of the class instance. Exercise all Set/Get methods using the TEST_SET_GET_VALUE macro. Remove unnecessary print of input mesh vertex and cell count. Refactor the test in order to improve the readability: create a helper function to parse the input vector fields. Other style changes for the sake of consistency across ITK: return codes, white spaces, comment styles, etc. --- test/itkVectorKernelPCATest.cxx | 390 ++++++++++++++++---------------- 1 file changed, 191 insertions(+), 199 deletions(-) diff --git a/test/itkVectorKernelPCATest.cxx b/test/itkVectorKernelPCATest.cxx index 62d608d..48160ac 100644 --- a/test/itkVectorKernelPCATest.cxx +++ b/test/itkVectorKernelPCATest.cxx @@ -19,274 +19,266 @@ #include "itkMesh.h" #include "itkMeshFileReader.h" #include "itkVectorFieldPCA.h" +#include "itkTestingMacros.h" #include "vnl/vnl_vector.h" #include "vnl/vnl_vector.h" -int showUsage(const char* programName) -{ - std::cerr << "USAGE: " << programName << std::endl; - std::cerr << " ... " << std::endl; - std::cerr << "\t\tN must be greater than 3" << std::endl; - return EXIT_FAILURE; -} -int itkVectorKernelPCATest(int argc, char *argv[]) +template< typename TPixel, typename TMesh, typename TVectorContainer > +int ParseVectorFields( std::vector< std::string > vectorFieldFilenames, typename TVectorContainer::Pointer vectorFieldSet ) { -#define MIN_ARG_COUNT 6 -#define FIRST_VECTOR_FIELD_ARG 2 - if(argc < MIN_ARG_COUNT) - return (showUsage(argv[0])); - - unsigned int pcaCount = 3; - double kernelSigma = 6.25; - - typedef double PointDataType; - typedef itk::Array PointDataVectorType; - typedef PointDataVectorType PixelType; - typedef double CoordRep; - const unsigned int Dimension = 3; - -// typedef float PCAResultsType; - typedef double PCAResultsType; - - // Declare the type of the input mesh - typedef itk::Mesh InMeshType; - - // Declare the type of the kernel function class - // typedef itk::GaussianDistanceKernel KernelType; - typedef itk::GaussianDistanceKernel KernelType; - - // Declare the type of the PCA calculator - typedef itk::VectorFieldPCA< PointDataType, PCAResultsType, - PixelType, CoordRep, KernelType, InMeshType > - PCACalculatorType; - - // Here we recover the file names from the command line arguments - const char* inMeshFile = argv[1]; + int testStatus = EXIT_SUCCESS; - // We can now instantiate the types of the reader/writer. - typedef itk::MeshFileReader< InMeshType > ReaderType; - - // create readers/writers + typedef itk::MeshFileReader< TMesh > ReaderType; ReaderType::Pointer meshReader = ReaderType::New(); - // The name of the file to be read or written is passed with the - // SetFileName() method. - meshReader->SetFileName( inMeshFile ); + unsigned int fieldSetCount = vectorFieldFilenames.size(); + vectorFieldSet->Reserve( fieldSetCount ); - try - { - meshReader->Update(); - } - catch( itk::ExceptionObject & excp ) - { - std::cerr << "Error reading mesh file " << inMeshFile << std::endl; - std::cerr << excp << std::endl; - } - - // get the objects - InMeshType::Pointer mesh = meshReader->GetOutput(); - std::cout << "Vertex Count: " << - mesh->GetNumberOfPoints() << std::endl; - std::cout << "Cell Count: " << - mesh->GetNumberOfCells() << std::endl; + typename TVectorContainer::Element vectorField; - const char* vectorFieldName; - PCACalculatorType::VectorFieldType vectorField; - - // should know vector field dimensions now unsigned int vectorFieldDim = 0; unsigned int vectorFieldCount = 0; - // how many vector field sets? - unsigned int fieldSetCount = argc - FIRST_VECTOR_FIELD_ARG; - - PCACalculatorType::VectorFieldSetTypePointer vectorFieldSet = - PCACalculatorType::VectorFieldSetType::New(); - - vectorFieldSet->Reserve(fieldSetCount); - unsigned int setIx = 0; - for (int i = FIRST_VECTOR_FIELD_ARG; i < argc; i++) + for( unsigned int i = 0; i < fieldSetCount; i++ ) { - vectorFieldName = argv[i]; - // The name of the file to be read or written is passed with the - // SetFileName() method. - meshReader->SetFileName( vectorFieldName ); + std::string vectorFieldName = vectorFieldFilenames[i]; - try - { - meshReader->Update(); - } - catch( itk::ExceptionObject & excp ) - { - std::cerr << "Error reading mesh field file " << vectorFieldName << std::endl; - std::cerr << excp << std::endl; - } + meshReader->SetFileName( vectorFieldName ); - // get the objects - InMeshType::Pointer meshWithField = meshReader->GetOutput(); + TRY_EXPECT_NO_EXCEPTION( meshReader->Update() ); - InMeshType::PointDataContainerPointer pointData = meshWithField->GetPointData(); - if (setIx == 0) + // Get the objects + TMesh::Pointer meshWithField = meshReader->GetOutput(); + + TMesh::PointDataContainerPointer pointData = meshWithField->GetPointData(); + if( setIx == 0 ) { vectorFieldCount = pointData->Size(); - if (vectorFieldCount) + if( vectorFieldCount ) { - PixelType oneDataSetVal = pointData->GetElement(0); + TPixel oneDataSetVal = pointData->GetElement( 0 ); vectorFieldDim = oneDataSetVal.size(); } - if (vectorFieldCount != meshWithField->GetNumberOfPoints()) + if( vectorFieldCount != meshWithField->GetNumberOfPoints() ) { + std::cerr << "Test failed!" << std::endl; std::cerr << "Vector field count (" << vectorFieldCount << - ") doesn't match mesh vertext count (" << - meshWithField->GetNumberOfPoints() << ")." << std::endl; - exit (EXIT_FAILURE); + ") doesn't match mesh vertext count (" << + meshWithField->GetNumberOfPoints() << ")." << std::endl; + testStatus = EXIT_FAILURE; } - vectorField.set_size(vectorFieldCount, vectorFieldDim); + vectorField.set_size( vectorFieldCount, vectorFieldDim ); } else { - if (vectorFieldDim != vectorField.cols() || - vectorFieldCount != meshWithField->GetNumberOfPoints()) + if( vectorFieldDim != vectorField.cols() || + vectorFieldCount != meshWithField->GetNumberOfPoints() ) { - std::cerr << "Unexpected dimensions in vector field file " << vectorFieldName << std::endl; - std::cerr << "\tExpected " << vectorFieldCount << " x " << vectorFieldDim; - std::cerr << "\t, got " << meshWithField->GetNumberOfPoints() << " x " << vectorField.cols() << std::endl; - exit(1); + std::cerr << "Test failed!" << std::endl; + std::cerr << "Unexpected dimensions in vector field file " + << vectorFieldName << std::endl; + std::cerr << "Expected: " << vectorFieldCount << " x " << vectorFieldDim + << ", but got " << meshWithField->GetNumberOfPoints() << " x " + << vectorField.cols() << std::endl; + testStatus = EXIT_FAILURE; } } - for (unsigned int k = 0; k < pointData->Size(); k++) + for( unsigned int k = 0; k < pointData->Size(); k++ ) { - PixelType oneDataSetVal = pointData->GetElement(k); - vectorField.set_row(k, oneDataSetVal); + TPixel oneDataSetVal = pointData->GetElement(k); + vectorField.set_row( k, oneDataSetVal ); } - vectorFieldSet->SetElement(setIx++, vectorField); + vectorFieldSet->SetElement( setIx++, vectorField ); } - PCACalculatorType::Pointer pcaCalc = PCACalculatorType::New(); - - std::cout << "Name of Class = " << pcaCalc->GetNameOfClass() << std::endl; + return testStatus; +} - std::cout << "Test Print() = " << std::endl; - pcaCalc->Print( std::cout ); - // try to Compute before setting much of anything - expect failure - try +int itkVectorKernelPCATest( int argc, char *argv[] ) +{ + if( argc < 6 ) { - pcaCalc->Compute(); - std::cerr << "Failed to throw expected exception" << std::endl; + std::cerr << "Missing parameters." << std::endl; + std::cerr << "Usage: " << argv[0] + << " ... " << std::endl; + std::cerr << "where N must be greater than 3" << std::endl; return EXIT_FAILURE; } - catch( itk::ExceptionObject & excp ) - { - std::cout << "SUCCESSFULLY caught expected exception" << std::endl; - std::cout << excp << std::endl; - } - // set user variables + + int testStatus = EXIT_SUCCESS; + + const unsigned int Dimension = 3; + + typedef double PointDataType; + typedef itk::Array< PointDataType > PointDataVectorType; + typedef PointDataVectorType PixelType; + typedef double CoordRep; + + typedef double PCAResultsType; + + // Declare the type of the input mesh + typedef itk::Mesh< PixelType, Dimension > MeshType; + + // Declare the type of the kernel function class + typedef itk::GaussianDistanceKernel< CoordRep > KernelType; + + // Declare the type of the PCA calculator + typedef itk::VectorFieldPCA< PointDataType, PCAResultsType, PixelType, + CoordRep, KernelType, MeshType > PCACalculatorType; + + // Instantiate the reader + typedef itk::MeshFileReader< MeshType > ReaderType; + ReaderType::Pointer meshReader = ReaderType::New(); + + meshReader->SetFileName( argv[1] ); + + TRY_EXPECT_NO_EXCEPTION( meshReader->Update() ); + + + // Get the input mesh + MeshType::Pointer mesh = meshReader->GetOutput(); + + + PCACalculatorType::Pointer pcaCalc = PCACalculatorType::New(); + + EXERCISE_BASIC_OBJECT_METHODS( pcaCalc, VectorFieldPCA, Object ); + + + // Test exception when trying to compute before setting much of anything + TRY_EXPECT_EXCEPTION( pcaCalc->Compute() ); + + + // Set user variables + unsigned int pcaCount = 3; pcaCalc->SetComponentCount( pcaCount ); - // - // Now connect the input. - // + // Connect the input pcaCalc->SetPointSet( mesh ); - // set vector fields - pcaCalc->SetVectorFieldSet( vectorFieldSet ); - // - // Now verify that it runs fine. - // - try - { - pcaCalc->Compute(); - std::cout << "SUCCESSFULLY ran non-Kernel version" << std::endl; - } - catch( itk::ExceptionObject & excp ) + TEST_SET_GET_VALUE( mesh, pcaCalc->GetPointSet() ); + + // Set vector fields + + PCACalculatorType::VectorFieldType vectorField; + + // Should know vector field dimensions now + unsigned int vectorFieldDim = 0; + unsigned int vectorFieldCount = 0; + + // how many vector field sets? + std::vector< std::string > vectorFieldFilenames; + unsigned int firstVectorFieldIdx = 2; + unsigned int fieldSetCount = argc - firstVectorFieldIdx; + for( unsigned int i = firstVectorFieldIdx; i < firstVectorFieldIdx + fieldSetCount; i++ ) { - std::cout << "Failed to run non-Kernel version" << std::endl; - std::cerr << excp << std::endl; - return EXIT_FAILURE; + vectorFieldFilenames.push_back( argv[i] ); } + PCACalculatorType::VectorFieldSetTypePointer vectorFieldSet = + PCACalculatorType::VectorFieldSetType::New(); + + testStatus = ParseVectorFields< PixelType, MeshType, PCACalculatorType::VectorFieldSetType >( + vectorFieldFilenames, vectorFieldSet ); + + pcaCalc->SetVectorFieldSet( vectorFieldSet ); + TEST_SET_GET_VALUE( vectorFieldSet, pcaCalc->GetVectorFieldSet() ); + + + // Execute the PCA calculator + TRY_EXPECT_NO_EXCEPTION( pcaCalc->Compute() ); + + + double kernelSigma = 6.25; KernelType::Pointer distKernel = KernelType::New(); distKernel->SetKernelSigma( kernelSigma ); pcaCalc->SetKernelFunction( distKernel ); - std::cout << "PCA Calculator All Set Up: Print() = " << std::endl; - pcaCalc->Print( std::cout ); std::ofstream debugOut; - debugOut.precision(15); + debugOut.precision( 15 ); - // get the output and perform basic checks - for (unsigned int j = 0; j < pcaCalc->GetComponentCount(); j++) + // Get the output and perform basic checks + unsigned int computedNumberOfAverageVectorFieldCols = + pcaCalc->GetAveVectorField().cols(); + + unsigned int computedNumberOfAverageVectorFieldRows = + pcaCalc->GetAveVectorField().rows(); + + for( unsigned int j = 0; j < pcaCalc->GetComponentCount(); j++ ) { - if ((pcaCalc->GetBasisVectors()->GetElement(j)).cols() != vectorFieldDim) + unsigned int expectedBasisVectorCols = + pcaCalc->GetVectorFieldSet()->GetElement(j).cols(); + unsigned int computedBasisVectorCols = + pcaCalc->GetBasisVectors()->GetElement(j).cols(); + if( computedBasisVectorCols != expectedBasisVectorCols ) { - std::cout << "Basis Vector Results Failed Dimension check:" << std::endl; - std::cout << "Expected: " << vectorFieldDim << std::endl - << " columns. Got: " - << (pcaCalc->GetBasisVectors()->GetElement(j)).cols() - << std::endl; - return EXIT_FAILURE; + std::cout << "Test failed!" << std::endl; + std::cout << "Error in GetBasisVectors() dimension check at index [" << j << "]" + << std::endl; + std::cout << "Expected: " << expectedBasisVectorCols << " columns, but got: " + << computedBasisVectorCols << std::endl; + testStatus = EXIT_FAILURE; } - if ((pcaCalc->GetBasisVectors()->GetElement(j)).rows() != vectorFieldCount) + + unsigned int expectedBasisVectorRows = + pcaCalc->GetVectorFieldSet()->GetElement(j).rows(); + unsigned int computedBasisVectorRows = + pcaCalc->GetBasisVectors()->GetElement(j).rows(); + if( computedBasisVectorRows != expectedBasisVectorRows ) { - std::cout << "Basis Vector Results Failed Dimension check:" << std::endl; - std::cout << "Expected: " << vectorFieldDim << std::endl - << " rows. Got: " - << pcaCalc->GetBasisVectors()->GetElement(j).rows() - << std::endl; - return EXIT_FAILURE; + std::cout << "Test failed!" << std::endl; + std::cout << "Error in GetBasisVectors() dimension check at index [" << j << "]" + << std::endl; + std::cout << "Expected: " << expectedBasisVectorRows << " row, but got: " + << computedBasisVectorRows << std::endl; + testStatus = EXIT_FAILURE; } - } - if (pcaCalc->GetPCAEigenValues().size() != pcaCount) - { - std::cout << "Eigenvalue Vector Results Failed Dimension check:" << std::endl; - std::cout << "Expected: " << pcaCount << std::endl - << ". Got: " - << pcaCalc->GetPCAEigenValues().size() - << std::endl; - return EXIT_FAILURE; - } + if( computedNumberOfAverageVectorFieldCols != expectedBasisVectorCols ) + { + std::cout << "Test failed!" << std::endl; + std::cout << "Error in GetAveVectorField() dimension check at index [" << j << "]" + << std::endl; + std::cout << "Expected: " << vectorFieldDim << " columns, but got: " + << computedNumberOfAverageVectorFieldCols << std::endl; + testStatus = EXIT_FAILURE; + } - if (pcaCalc->GetAveVectorField().cols() != vectorFieldDim) - { - std::cout << "Average Vector Field Results Failed Dimension check:" << std::endl; - std::cout << "Expected: " << vectorFieldDim << std::endl - << " columns. Got: " - << pcaCalc->GetAveVectorField().cols() - << std::endl; - return EXIT_FAILURE; + if( computedNumberOfAverageVectorFieldRows != expectedBasisVectorRows ) + { + std::cout << "Test failed!" << std::endl; + std::cout << "Error in GetAveVectorField() dimension check at index [" << j << "]" + << std::endl; + std::cout << "Expected: " << vectorFieldDim << " rows, but got: " + << computedNumberOfAverageVectorFieldRows << std::endl; + testStatus = EXIT_FAILURE; + } } - if (pcaCalc->GetAveVectorField().rows() != vectorFieldCount) + + unsigned int computedNumberOfEigenValueVectors = + pcaCalc->GetPCAEigenValues().size(); + if( computedNumberOfEigenValueVectors != pcaCount ) { - std::cout << "Average Vector Field Failed Dimension check:" << std::endl; - std::cout << "Expected: " << vectorFieldDim << std::endl - << " rows. Got: " - << pcaCalc->GetAveVectorField().rows() - << std::endl; - return EXIT_FAILURE; + std::cout << "Test failed!" << std::endl; + std::cout << "Error in GetPCAEigenValues() dimension check." << std::endl; + std::cout << "Expected: " << pcaCount << ", but got: " + << computedNumberOfEigenValueVectors << std::endl; + testStatus = EXIT_FAILURE; } - // set the requested input count greater than the number of vector field sets + // Test exception when trying to compute with a requested input count greater + // than the number of vector field sets pcaCalc->SetComponentCount( fieldSetCount + 1 ); - // try to Compute - expect failure - try - { - pcaCalc->Compute(); - std::cerr << "Failed to throw expected exception" << std::endl; - return EXIT_FAILURE; - } - catch( itk::ExceptionObject & excp ) - { - std::cout << "SUCCESSFULLY caught expected exception" << std::endl; - std::cout << excp << std::endl; - } - return EXIT_SUCCESS; + TRY_EXPECT_EXCEPTION( pcaCalc->Compute() ); + + + std::cout << "Test finished." << std::endl; + return testStatus; } From 0c7002ae10b8bd7c0fab82dcc92b97f47ccd8fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Wed, 26 Apr 2017 08:18:08 +0200 Subject: [PATCH 04/21] ENH: Include the ITK_MANUAL_INSTANTIATION macro. Add the #ifndef ITK_MANUAL_INSTANTIATION statement for explicit object instantiation. --- include/itkVectorFieldPCA.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/itkVectorFieldPCA.h b/include/itkVectorFieldPCA.h index 74312ac..9eb9e3d 100644 --- a/include/itkVectorFieldPCA.h +++ b/include/itkVectorFieldPCA.h @@ -230,6 +230,8 @@ class ITK_EXPORT VectorFieldPCA : public Object } // end namespace itk +#ifndef ITK_MANUAL_INSTANTIATION #include "itkVectorFieldPCA.hxx" +#endif #endif From 90772541b726e69e7d919f7f89896983082b6055 Mon Sep 17 00:00:00 2001 From: Jon Haitz Legarreta Date: Wed, 17 Jan 2018 18:21:47 +0100 Subject: [PATCH 05/21] ENH: Require cmake minimum version to be 3.9.5. Require CMake minimum version to be 3.9.5 following ITKv5 requiring C++11: https://discourse.itk.org/t/minimum-cmake-version-update/585 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d93f3b..f2d0e83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.9) +CMAKE_MINIMUM_REQUIRED(VERSION 3.9.5) IF(COMMAND CMAKE_POLICY) CMAKE_POLICY(SET CMP0003 NEW) ENDIF(COMMAND CMAKE_POLICY) From d88bcf6a1b4865306b4b9aa56ffa60f194c2e9b1 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Sat, 16 Dec 2017 16:30:40 -0600 Subject: [PATCH 06/21] COMP: Remove deprecated code usages ITKv5 removed deprecated interfaces. --- include/itkVectorFieldPCA.h | 2 +- test/itkVectorKernelPCATest.cxx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/itkVectorFieldPCA.h b/include/itkVectorFieldPCA.h index 9eb9e3d..8940d2d 100644 --- a/include/itkVectorFieldPCA.h +++ b/include/itkVectorFieldPCA.h @@ -78,7 +78,7 @@ class ITK_EXPORT GaussianDistanceKernel : public KernelFunctionBase vectorFieldFilenames, typename int testStatus = EXIT_SUCCESS; typedef itk::MeshFileReader< TMesh > ReaderType; - ReaderType::Pointer meshReader = ReaderType::New(); + typename ReaderType::Pointer meshReader = ReaderType::New(); unsigned int fieldSetCount = vectorFieldFilenames.size(); vectorFieldSet->Reserve( fieldSetCount ); @@ -51,9 +51,9 @@ int ParseVectorFields( std::vector< std::string > vectorFieldFilenames, typename TRY_EXPECT_NO_EXCEPTION( meshReader->Update() ); // Get the objects - TMesh::Pointer meshWithField = meshReader->GetOutput(); + typename TMesh::Pointer meshWithField = meshReader->GetOutput(); - TMesh::PointDataContainerPointer pointData = meshWithField->GetPointData(); + typename TMesh::PointDataContainerPointer pointData = meshWithField->GetPointData(); if( setIx == 0 ) { vectorFieldCount = pointData->Size(); From 1a2bac9a765747b1f17d01f17b5667f692804012 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Sat, 16 Dec 2017 19:17:11 -0600 Subject: [PATCH 07/21] ENH: ITKv5 override consistency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provide remove virtual and override Use clang-tidy to add ITK_OVERRIDE, and to remove redundant virtual on functions. cd ../ITK; clang-tidy -p ITK-clangtidy $find Modules/[A-J]* -name *.cxx |fgrep -v ThirdParty) -checks=-*,modernize-use-override -header-filter=.* -fix clang-tidy -p ITK-clangtidy $(find Modules/[K-Z]* -name *.cxx |fgrep -v ThirdParty) -checks=-*,modernize-use-override -header-filter=.* -fix https://stackoverflow.com/questions/39932391/virtual-override-or-both-c When you override a function you don't technically need to write either virtual or override. The original base class declaration needs the keyword virtual to mark it as virtual. In the derived class the function is virtual by way of having the ¹same type as the base class function. However, an override can help avoid bugs by producing a compilation error when the intended override isn't technically an override. E.g. that the function type isn't exactly like the base class function. Or that a maintenance of the base class changes that function's type, e.g. adding a defaulted argument. In the same way, a virtual keyword in the derived class can make such a bug more subtle, by ensuring that the function is still is virtual in further derived classes. So the general advice is, virtual for the base class function declaration. This is technically necessary. Use override (only) for a derived class' override. This helps with maintenance. --- include/itkVectorFieldPCA.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/itkVectorFieldPCA.h b/include/itkVectorFieldPCA.h index 8940d2d..455df5f 100644 --- a/include/itkVectorFieldPCA.h +++ b/include/itkVectorFieldPCA.h @@ -83,8 +83,8 @@ class ITK_EXPORT GaussianDistanceKernel : public KernelFunctionBase Date: Sat, 16 Dec 2017 19:36:26 -0600 Subject: [PATCH 08/21] COMP: Use C++11 override directly git grep -l "ITK_OVERRIDE" | fgrep -v itk_compiler_detection.h | fgrep -v CMakeLists.txt |fgrep -v .cmake | xargs sed -i '' -e "s/ITK_OVERRIDE/override/g" --- include/itkVectorFieldPCA.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/itkVectorFieldPCA.h b/include/itkVectorFieldPCA.h index 455df5f..c4afa05 100644 --- a/include/itkVectorFieldPCA.h +++ b/include/itkVectorFieldPCA.h @@ -78,13 +78,13 @@ class ITK_EXPORT GaussianDistanceKernel : public KernelFunctionBase Date: Fri, 22 Dec 2017 08:08:51 -0600 Subject: [PATCH 09/21] ENH: Remove unused variables. --- examples/VectorKernelPCA.cxx | 2 -- test/itkVectorKernelPCATest.cxx | 1 - 2 files changed, 3 deletions(-) diff --git a/examples/VectorKernelPCA.cxx b/examples/VectorKernelPCA.cxx index 991c16e..cc38ab2 100644 --- a/examples/VectorKernelPCA.cxx +++ b/examples/VectorKernelPCA.cxx @@ -49,9 +49,7 @@ int main( int argc, char *argv[] ) typedef itk::Vector OutPointDataVectorType; typedef OutPointDataVectorType OutPixelType; - typedef double DDataType; typedef double CoordRep; - typedef double InterpRep; const unsigned int Dimension = 3; // typedef float PCAResultsType; diff --git a/test/itkVectorKernelPCATest.cxx b/test/itkVectorKernelPCATest.cxx index a3b095e..b5d1a71 100644 --- a/test/itkVectorKernelPCATest.cxx +++ b/test/itkVectorKernelPCATest.cxx @@ -169,7 +169,6 @@ int itkVectorKernelPCATest( int argc, char *argv[] ) // Should know vector field dimensions now unsigned int vectorFieldDim = 0; - unsigned int vectorFieldCount = 0; // how many vector field sets? std::vector< std::string > vectorFieldFilenames; From 4384ecc9bc07fedf3e98e875768078e778e0276b Mon Sep 17 00:00:00 2001 From: Jon Haitz Legarreta Date: Sat, 14 Apr 2018 19:24:28 +0200 Subject: [PATCH 10/21] COMP: Move ITK_DISALLOW_COPY_AND_ASSIGN calls to public section. Move `ITK_DISALLOW_COPY_AND_ASSIGN` calls to public section following the discussion in https://discourse.itk.org/t/noncopyable If legacy (pre-macro) copy and assing methods existed, subsitute them for the `ITK_DISALLOW_COPY_AND_ASSIGN` macro. --- include/itkVectorFieldPCA.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/itkVectorFieldPCA.h b/include/itkVectorFieldPCA.h index c4afa05..10dee8e 100644 --- a/include/itkVectorFieldPCA.h +++ b/include/itkVectorFieldPCA.h @@ -104,6 +104,8 @@ template < class ITK_EXPORT VectorFieldPCA : public Object { public: + ITK_DISALLOW_COPY_AND_ASSIGN(VectorFieldPCA); + /** Standard class typedefs. */ typedef VectorFieldPCA Self; typedef Object Superclass; @@ -204,8 +206,6 @@ class ITK_EXPORT VectorFieldPCA : public Object void ComputeMomentumSCP(); private: - ITK_DISALLOW_COPY_AND_ASSIGN(VectorFieldPCA); - VectorType m_PCAEigenValues; BasisSetTypePointer m_BasisVectors; From 6152917fef87c47fb9737cf455205c8d4d666b77 Mon Sep 17 00:00:00 2001 From: Jon Haitz Legarreta Date: Sat, 5 May 2018 12:32:05 +0200 Subject: [PATCH 11/21] COMP: Set the minimum required CMake version to 3.10.2. As agreed in: https://discourse.itk.org/t/cmake-update/870/ Set the `cmake_minimum_required` to version **3.10.2**. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f2d0e83..0edc2e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.9.5) +CMAKE_MINIMUM_REQUIRED(VERSION 3.10.2) IF(COMMAND CMAKE_POLICY) CMAKE_POLICY(SET CMP0003 NEW) ENDIF(COMMAND CMAKE_POLICY) From ef5b8987d2fc076a8b108c4cbe0578c6a91a475d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Thu, 7 Jun 2018 19:23:52 +0200 Subject: [PATCH 12/21] ENH: Add CI configuration files. Add CircleCI configuration files and badges. --- .circleci/config.yml | 63 ++++++++++++++++++++++++++++++++++++++++++++ .travis.yml | 15 +++++++++++ README.rst | 17 ++++++++++-- appveyor.yml | 21 +++++++++++++++ setup.py | 54 +++++++++++++++++++++++++++++++++++++ 5 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 .circleci/config.yml create mode 100644 .travis.yml create mode 100644 appveyor.yml create mode 100644 setup.py diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..c078b1b --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,63 @@ +version: 2 +jobs: + build-and-test: + working_directory: /ITKPrincipalComponentsAnalysis-build + docker: + - image: insighttoolkit/module-ci:latest + steps: + - checkout: + path: /ITKPrincipalComponentsAnalysis + - run: + name: Fetch CTest driver script + command: | + curl -L https://raw.githubusercontent.com/InsightSoftwareConsortium/ITK/dashboard/itk_common.cmake -O + - run: + name: Configure CTest script + command: | + SHASNIP=$(echo $CIRCLE_SHA1 | cut -c1-7) + cat > dashboard.cmake << EOF + set(CTEST_SITE "CircleCI") + set(CTEST_BUILD_NAME "External-ITKPrincipalComponentsAnalysis-${CIRCLE_BRANCH}-${CIRCLE_BUILD_NUM}-${SHASNIP}") + set(CTEST_BUILD_CONFIGURATION "MinSizeRel") + set(CTEST_CMAKE_GENERATOR "Unix Makefiles") + set(CTEST_BUILD_FLAGS: "-j5") + set(CTEST_SOURCE_DIRECTORY /ITKPrincipalComponentsAnalysis) + set(CTEST_BINARY_DIRECTORY /ITKPrincipalComponentsAnalysis-build) + set(dashboard_model Experimental) + set(dashboard_no_clean 1) + set(dashboard_cache " + ITK_DIR:PATH=/ITK-build + BUILD_TESTING:BOOL=ON + ") + include(\${CTEST_SCRIPT_DIRECTORY}/itk_common.cmake) + EOF + - run: + name: Build and Test + no_output_timeout: 1.0h + command: | + ctest -j 2 -VV -S dashboard.cmake + package: + working_directory: ~/ITKPrincipalComponentsAnalysis + machine: true + steps: + - checkout + - run: + name: Fetch build script + command: | + curl -L https://rawgit.com/InsightSoftwareConsortium/ITKPythonPackage/master/scripts/dockcross-manylinux-download-cache-and-build-module-wheels.sh -O + chmod u+x dockcross-manylinux-download-cache-and-build-module-wheels.sh + - run: + name: Build Python packages + no_output_timeout: 1.0h + command: | + ./dockcross-manylinux-download-cache-and-build-module-wheels.sh + - store_artifacts: + path: dist + destination: dist + +workflows: + version: 2 + build-test-package: + jobs: + - build-and-test + - package diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..fefe98c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,15 @@ +sudo: true +language: cpp +os: +- osx +compiler: +- gcc +cache: + directories: + - "$HOME/Library/Caches/Homebrew" +script: +- curl -L https://rawgit.com/InsightSoftwareConsortium/ITKPythonPackage/master/scripts/macpython-download-cache-and-build-module-wheels.sh -O +- chmod u+x macpython-download-cache-and-build-module-wheels.sh +- ./macpython-download-cache-and-build-module-wheels.sh +- tar -zcvf dist.tar.gz dist/ +- curl -F file="@dist.tar.gz" https://file.io diff --git a/README.rst b/README.rst index 9f8e0ca..2671ab5 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,20 @@ PrincipalComponentsAnalysis -============================ +=========================== -.. ADD circle ci badge once this module is merge to ITK's repository +.. |CircleCI| image:: https://circleci.com/gh/InsightSoftwareConsortium/ITKPrincipalComponentsAnalysis.svg?style=shield + :target: https://circleci.com/gh/InsightSoftwareConsortium/ITKPrincipalComponentsAnalysis + +.. |TravisCI| image:: https://travis-ci.org/InsightSoftwareConsortium/ITKPrincipalComponentsAnalysis.svg?branch=master + :target: https://travis-ci.org/InsightSoftwareConsortium/ITKPrincipalComponentsAnalysis + +.. |AppVeyor| image:: https://img.shields.io/appveyor/ci/itkrobot/itkprincipalcomponentsanalysis.svg + :target: https://ci.appveyor.com/project/itkrobot/itkprincipalcomponentsanalysis + +=========== =========== =========== + Linux macOS Windows +=========== =========== =========== +|CircleCI| |TravisCI| |AppVeyor| +=========== =========== =========== An `ITK `_-based implementation of principal components analysis. A more detailed description can be found in the Insight Journal article:: diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..f93db11 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,21 @@ +branches: + only: + - master + +version: "0.0.1.{build}" + +install: + + - curl -L https://rawgit.com/InsightSoftwareConsortium/ITKPythonPackage/master/scripts/windows-download-cache-and-build-module-wheels.ps1 -O + - ps: .\windows-download-cache-and-build-module-wheels.ps1 + +build: off + +test: off + +artifacts: + + # pushing entire folder as a zip archive + - path: dist\* + +deploy: off \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..3e9df8e --- /dev/null +++ b/setup.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +from __future__ import print_function +from os import sys + +try: + from skbuild import setup +except ImportError: + print('scikit-build is required to build from source.', file=sys.stderr) + print('Please run:', file=sys.stderr) + print('', file=sys.stderr) + print(' python -m pip install scikit-build') + sys.exit(1) + +setup( + name='itk-principalcomponentsanalysis', + version='1.0.0', + author='Michael Bowers and Laurent Younes', + author_email='mbowers@cis.jhu.edu', + packages=['itk'], + package_dir={'itk': 'itk'}, + download_url=r'https://github.com/InsightSoftwareConsortium/ITKPrincipalComponentsAnalysis', + description=r'ITK classes for the analysis of the principal components of data sets, optionally point data associated with the vertices of a mesh.', + long_description='ITKPrincipalComponentsAnalysis provides an' + 'implementation of standard principal components analysis' + 'algorithms for use on scalar or vector data sets.\n' + 'Please refer to:\n' + 'M. Bowers and L. Younes, “Principal Components Analysis of Scalar, Vector, and Mesh Vertex Data.”,' + 'Insight Journal, January-December 2012, http://hdl.handle.net/10380/3386', + classifiers=[ + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python", + "Programming Language :: C++", + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Intended Audience :: Education", + "Intended Audience :: Healthcare Industry", + "Intended Audience :: Science/Research", + "Topic :: Scientific/Engineering", + "Topic :: Scientific/Engineering :: Medical Science Apps.", + "Topic :: Scientific/Engineering :: Information Analysis", + "Topic :: Software Development :: Libraries", + "Operating System :: Android", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX", + "Operating System :: Unix", + "Operating System :: MacOS" + ], + license='Apache', + keywords='ITK PCA Mesh', + url=r'https://github.com/InsightSoftwareConsortium/ITKPrincipalComponentsAnalysis', + install_requires=[ + r'itk' + ] + ) \ No newline at end of file From d96a00be7ada93135ee19c13bdd2caf88996c07f Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Sun, 15 Jul 2018 22:27:33 -0400 Subject: [PATCH 13/21] BUG: Add missing CTestConfig.cmake --- CTestConfig.cmake | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 CTestConfig.cmake diff --git a/CTestConfig.cmake b/CTestConfig.cmake new file mode 100644 index 0000000..62f68ac --- /dev/null +++ b/CTestConfig.cmake @@ -0,0 +1,7 @@ +set(CTEST_PROJECT_NAME "ITK") +set(CTEST_NIGHTLY_START_TIME "1:00:00 UTC") + +set(CTEST_DROP_METHOD "http") +set(CTEST_DROP_SITE "open.cdash.org") +set(CTEST_DROP_LOCATION "/submit.php?project=Insight") +set(CTEST_DROP_SITE_CDASH TRUE) From 98c919465c01de439bdbbac87036a7c4ee29fe40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sat, 22 Sep 2018 18:18:50 -0400 Subject: [PATCH 14/21] ENH: Use transfer.sh for macOS package upload. Prefer `transfer.sh` over `file.io` for macOS package upload. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fefe98c..fcd5383 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,4 +12,4 @@ script: - chmod u+x macpython-download-cache-and-build-module-wheels.sh - ./macpython-download-cache-and-build-module-wheels.sh - tar -zcvf dist.tar.gz dist/ -- curl -F file="@dist.tar.gz" https://file.io +- curl --upload-file dist.tar.gz https://transfer.sh/dist.tar.gz From 9b12ac218bb5305ac22e3742e285815a70cd05b9 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Mon, 1 Oct 2018 11:12:33 -0400 Subject: [PATCH 15/21] DOC: Add missing LICENSE file --- LICENSE | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From 56b4b1e6db6e09d0b86c88a11fa9526cb8f68486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Mon, 1 Oct 2018 19:48:14 -0400 Subject: [PATCH 16/21] STYLE: Improve README file. Improve `README` file: - Split the document in section. - Improve the documentation layout referencing the IJ article. - Cross reference the `LICENSE` file. --- README.rst | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index 2671ab5..b7b48a7 100644 --- a/README.rst +++ b/README.rst @@ -16,17 +16,31 @@ PrincipalComponentsAnalysis |CircleCI| |TravisCI| |AppVeyor| =========== =========== =========== +Overview +-------- + An `ITK `_-based implementation of principal components analysis. -A more detailed description can be found in the Insight Journal article:: - Bowers M., Younes L. "Principal Components Analysis of Scalar, Vector, and Mesh Vertex Data." - http://hdl.handle.net/10380/3386 - http://www.insight-journal.org/browse/publication/878 - August, 2013. +For more information, see the `Insight Journal article `_:: + + Bowers M., Younes L. + Principal Components Analysis of Scalar, Vector, and Mesh Vertex Data + The Insight Journal. August. 2013. + http://hdl.handle.net/10380/3386 + http://www.insight-journal.org/browse/publication/878 + +Installation +------------ Since ITK 4.10.0, this module is available in the ITK source tree as a Remote -module. To enable it, set:: +module. To enable it, set:: Module_PrincipalComponentsAnalysis:BOOL=ON in ITK's CMake build configuration. + +License +------- + +This software is distributed under the Apache 2.0 license. Please see +the *LICENSE* file for details. From 67d0e4af8383ebc4de62136692e491ddcb0f8128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Thu, 11 Oct 2018 23:34:45 -0400 Subject: [PATCH 17/21] COMP: Do not use rawgit.com. Do not use `rawgit.com` as part of the curl command argument when generating the Python package. It is no longer supported. Use `raw.githubusercontent` instead. --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fcd5383..c0a5d09 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ cache: directories: - "$HOME/Library/Caches/Homebrew" script: -- curl -L https://rawgit.com/InsightSoftwareConsortium/ITKPythonPackage/master/scripts/macpython-download-cache-and-build-module-wheels.sh -O +- curl -L https://raw.githubusercontent.com/InsightSoftwareConsortium/ITKPythonPackage/master/scripts/macpython-download-cache-and-build-module-wheels.sh -O - chmod u+x macpython-download-cache-and-build-module-wheels.sh - ./macpython-download-cache-and-build-module-wheels.sh - tar -zcvf dist.tar.gz dist/ diff --git a/appveyor.yml b/appveyor.yml index f93db11..e18ea36 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,7 +6,7 @@ version: "0.0.1.{build}" install: - - curl -L https://rawgit.com/InsightSoftwareConsortium/ITKPythonPackage/master/scripts/windows-download-cache-and-build-module-wheels.ps1 -O + - curl -L https://raw.githubusercontent.com/InsightSoftwareConsortium/ITKPythonPackage/master/scripts/windows-download-cache-and-build-module-wheels.ps1 -O - ps: .\windows-download-cache-and-build-module-wheels.ps1 build: off From 836f6e89324c23a52747e864c88e74aa1c81389b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sat, 20 Oct 2018 17:30:10 -0400 Subject: [PATCH 18/21] STYLE: Prefer C++11 type alias over typedef. Prefer C++11 type alias over typedef for the reasons stated here: http://review.source.kitware.com/#/c/23103/ --- examples/VectorKernelPCA.cxx | 34 ++++++++++----------- include/itkVectorFieldPCA.h | 52 ++++++++++++++++----------------- test/itkVectorKernelPCATest.cxx | 22 +++++++------- 3 files changed, 54 insertions(+), 54 deletions(-) diff --git a/examples/VectorKernelPCA.cxx b/examples/VectorKernelPCA.cxx index cc38ab2..86e8e7c 100644 --- a/examples/VectorKernelPCA.cxx +++ b/examples/VectorKernelPCA.cxx @@ -43,36 +43,36 @@ int main( int argc, char *argv[] ) int pcaCount = atoi(argv[1]); double kernelSigma = atof(argv[2]); - typedef double PointDataType; - typedef itk::Array PointDataVectorType; - typedef PointDataVectorType PixelType; - typedef itk::Vector OutPointDataVectorType; - typedef OutPointDataVectorType OutPixelType; + using PointDataType = double; + using PointDataVectorType = itk::Array; + using PixelType = PointDataVectorType; + using OutPointDataVectorType = itk::Vector; + using OutPixelType = OutPointDataVectorType; - typedef double CoordRep; + using CoordRep = double; const unsigned int Dimension = 3; -// typedef float PCAResultsType; - typedef double PCAResultsType; +// using PCAResultsType = float; + using PCAResultsType = double; // Declare the type of the input mesh - typedef itk::Mesh InMeshType; - typedef itk::Mesh OutMeshType; + using InMeshType = itk::Mesh; + using OutMeshType = itk::Mesh; // Declare the type of the kernel function class - typedef itk::GaussianDistanceKernel KernelType; + using KernelType = itk::GaussianDistanceKernel; // Declare the type of the PCA calculator - typedef itk::VectorFieldPCA< PointDataType, PCAResultsType, - PixelType, CoordRep, KernelType, InMeshType > PCACalculatorType; + using PCACalculatorType = itk::VectorFieldPCA< PointDataType, PCAResultsType, + PixelType, CoordRep, KernelType, InMeshType >; // Here we recover the file names from the command line arguments const char* inMeshFile = argv[3]; const char* outFileNameBase = argv[4]; // We can now instantiate the types of the reader/writer. - typedef itk::MeshFileReader< InMeshType > ReaderType; - typedef itk::MeshFileWriter< OutMeshType > WriterType; + using ReaderType = itk::MeshFileReader< InMeshType >; + using WriterType = itk::MeshFileWriter< OutMeshType >; // create readers/writers ReaderType::Pointer meshReader = ReaderType::New(); @@ -220,8 +220,8 @@ int main( int argc, char *argv[] ) InMeshType::CellsContainerConstIterator itCellsEnd = cells->End(); outMesh->GetCells()->Reserve( cells->Size() ); - typedef OutMeshType::CellType::CellAutoPointer CellAutoPointer; - typedef itk::TriangleCell< OutMeshType::CellType > TriangleType; + using CellAutoPointer = OutMeshType::CellType::CellAutoPointer; + using TriangleType = itk::TriangleCell< OutMeshType::CellType >; while ( itCells != itCellsEnd ) { diff --git a/include/itkVectorFieldPCA.h b/include/itkVectorFieldPCA.h index 10dee8e..1bbdadd 100644 --- a/include/itkVectorFieldPCA.h +++ b/include/itkVectorFieldPCA.h @@ -55,11 +55,11 @@ template< typename TRealValueType = double > class ITK_EXPORT GaussianDistanceKernel : public KernelFunctionBase { public: - /** Standard class typedefs. */ - typedef GaussianDistanceKernel Self; - typedef KernelFunctionBase Superclass; - typedef SmartPointer Pointer; - typedef SmartPointer ConstPointer; + /** Standard class type alias. */ + using Self = GaussianDistanceKernel; + using Superclass = KernelFunctionBase; + using Pointer = SmartPointer; + using ConstPointer = SmartPointer; /** Run-time type information (and related methods). */ itkTypeMacro(GaussianDistanceKernel, KernelFunction); @@ -106,11 +106,11 @@ class ITK_EXPORT VectorFieldPCA : public Object public: ITK_DISALLOW_COPY_AND_ASSIGN(VectorFieldPCA); - /** Standard class typedefs. */ - typedef VectorFieldPCA Self; - typedef Object Superclass; - typedef SmartPointer Pointer; - typedef SmartPointer ConstPointer; + /** Standard class type alias. */ + using Self = VectorFieldPCA; + using Superclass = Object; + using Pointer = SmartPointer; + using ConstPointer = SmartPointer; /** Method for creation through the object factory. */ itkNewMacro(Self); @@ -119,20 +119,20 @@ class ITK_EXPORT VectorFieldPCA : public Object itkTypeMacro(VectorFieldPCA, Object); /** Type definitions for the PointSet. */ - typedef TPointSetType InputPointSetType; + using InputPointSetType = TPointSetType; /** Definitions for points of the PointSet. */ - typedef typename InputPointSetType::PointType InputPointType; + using InputPointType = typename InputPointSetType::PointType; /** Definitions for the PointsContainer. */ - typedef typename InputPointSetType::PointsContainer PointsContainer; - typedef typename PointsContainer::Iterator PointsContainerIterator; + using PointsContainer = typename InputPointSetType::PointsContainer; + using PointsContainerIterator = typename PointsContainer::Iterator; /** Pointer types for the PointSet. */ - typedef typename InputPointSetType::Pointer InputPointSetPointer; + using InputPointSetPointer = typename InputPointSetType::Pointer; /** Const Pointer type for the PointSet. */ - typedef typename InputPointSetType::ConstPointer InputPointSetConstPointer; + using InputPointSetConstPointer = typename InputPointSetType::ConstPointer; /** * \brief Input PointSet dimension @@ -141,21 +141,21 @@ class ITK_EXPORT VectorFieldPCA : public Object TPointSetType::PointDimension); /** type for the vector fields. */ - typedef vnl_matrix< TVectorFieldElementType > VectorFieldType; - typedef VectorContainer< unsigned int, VectorFieldType > VectorFieldSetType; + using VectorFieldType = vnl_matrix< TVectorFieldElementType >; + using VectorFieldSetType = VectorContainer< unsigned int, VectorFieldType >; - typedef typename VectorFieldSetType::Pointer VectorFieldSetTypePointer; - typedef typename VectorFieldSetType::ConstPointer VectorFieldSetTypeConstPointer; + using VectorFieldSetTypePointer = typename VectorFieldSetType::Pointer; + using VectorFieldSetTypeConstPointer = typename VectorFieldSetType::ConstPointer; /** types for the output. */ - typedef vnl_matrix< TPCType > MatrixType; - typedef vnl_vector< TPCType > VectorType; + using MatrixType = vnl_matrix< TPCType >; + using VectorType = vnl_vector< TPCType >; - typedef VectorContainer< unsigned int, MatrixType > BasisSetType; - typedef VectorContainer< unsigned int, VectorType > ResSetType; + using BasisSetType = VectorContainer< unsigned int, MatrixType >; + using ResSetType = VectorContainer< unsigned int, VectorType >; - typedef typename BasisSetType::Pointer BasisSetTypePointer; - typedef typename KernelFunctionType::Pointer KernelFunctionPointer; + using BasisSetTypePointer = typename BasisSetType::Pointer; + using KernelFunctionPointer = typename KernelFunctionType::Pointer; /** * \brief Set and get the input point set. diff --git a/test/itkVectorKernelPCATest.cxx b/test/itkVectorKernelPCATest.cxx index b5d1a71..9763ffd 100644 --- a/test/itkVectorKernelPCATest.cxx +++ b/test/itkVectorKernelPCATest.cxx @@ -29,7 +29,7 @@ int ParseVectorFields( std::vector< std::string > vectorFieldFilenames, typename { int testStatus = EXIT_SUCCESS; - typedef itk::MeshFileReader< TMesh > ReaderType; + using ReaderType = itk::MeshFileReader< TMesh >; typename ReaderType::Pointer meshReader = ReaderType::New(); unsigned int fieldSetCount = vectorFieldFilenames.size(); @@ -116,25 +116,25 @@ int itkVectorKernelPCATest( int argc, char *argv[] ) const unsigned int Dimension = 3; - typedef double PointDataType; - typedef itk::Array< PointDataType > PointDataVectorType; - typedef PointDataVectorType PixelType; - typedef double CoordRep; + using PointDataType = double; + using PointDataVectorType = itk::Array< PointDataType >; + using PixelType = PointDataVectorType; + using CoordRep = double; - typedef double PCAResultsType; + using PCAResultsType = double; // Declare the type of the input mesh - typedef itk::Mesh< PixelType, Dimension > MeshType; + using MeshType = itk::Mesh< PixelType, Dimension >; // Declare the type of the kernel function class - typedef itk::GaussianDistanceKernel< CoordRep > KernelType; + using KernelType = itk::GaussianDistanceKernel< CoordRep >; // Declare the type of the PCA calculator - typedef itk::VectorFieldPCA< PointDataType, PCAResultsType, PixelType, - CoordRep, KernelType, MeshType > PCACalculatorType; + using PCACalculatorType = itk::VectorFieldPCA< PointDataType, PCAResultsType, PixelType, + CoordRep, KernelType, MeshType >; // Instantiate the reader - typedef itk::MeshFileReader< MeshType > ReaderType; + using ReaderType = itk::MeshFileReader< MeshType >; ReaderType::Pointer meshReader = ReaderType::New(); meshReader->SetFileName( argv[1] ); From 804b555d69ddd8ffaf90e9cd7d093cc6af4290fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Thu, 1 Nov 2018 21:35:53 -0400 Subject: [PATCH 19/21] STYLE: Prefer error checked std::sto[id] over ato[if]. The `ato[if]` functions do not provide mechanisms for distinguishing between `0` and the error condion where the input can not be converted. `std::sto[id]` provides exception handling and detects when an invalid string attempts to be converted to an [integer|double]. `ato[if]()` - **Con**: No error handling. - **Con**: Handle neither hexadecimal nor octal. The use of `ato[if]` in code can cause it to be subtly broken. `ato[if]` makes two very big assumptions indeed: - The string represents an integer/floating point value. - The integer can fit into an int. As stated in http://review.source.kitware.com/#/c/23738/ --- examples/VectorKernelPCA.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/VectorKernelPCA.cxx b/examples/VectorKernelPCA.cxx index cc38ab2..71a5b78 100644 --- a/examples/VectorKernelPCA.cxx +++ b/examples/VectorKernelPCA.cxx @@ -40,8 +40,8 @@ int main( int argc, char *argv[] ) if(argc < MIN_ARG_COUNT) return (showUsage(argv[0])); - int pcaCount = atoi(argv[1]); - double kernelSigma = atof(argv[2]); + int pcaCount = std::stoi(argv[1]); + double kernelSigma = std::stod(argv[2]); typedef double PointDataType; typedef itk::Array PointDataVectorType; From 0e52ead26fec6c1241818b5d2219b7912463684a Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Sat, 3 Nov 2018 10:48:07 -0500 Subject: [PATCH 20/21] COMP: Future proof vnl_math_XXX function usage. Prefer C++ over aliased names vnl_math_[min|max] -> std::[min|max] Prefer vnl_math::abs over deprecated alias vnl_math_abs In all compilers currently supported by VXL, vnl_math_[min|max] could be replaced with std::[min|max] without loss of functionality. This also circumvents part of the backwards compatibility requirements as vnl_math_ has been recently replaced with a namespace of vnl_math::. Since Wed Nov 14 07:42:48 2012: The vnl_math_* functions use #define aliases to their vnl_math::* counterparts in the "real" vnl_math:: namespace. The new syntax should be backwards compatible to VXL versions as old as 2012. Prefer to use itk::Math:: over vnl_math:: namespace --- include/itkVectorFieldPCA.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/itkVectorFieldPCA.hxx b/include/itkVectorFieldPCA.hxx index 20dc124..3189c19 100644 --- a/include/itkVectorFieldPCA.hxx +++ b/include/itkVectorFieldPCA.hxx @@ -22,7 +22,7 @@ #include "itkVectorFieldPCA.h" #include "vnl/algo/vnl_symmetric_eigensystem.h" #include "vnl/vnl_c_vector.h" -#include "vnl/vnl_math.h" +#include "itkMath.h" namespace itk { From b27d85c11f668bc8c5a6a7323d18db9c352785b4 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Sat, 3 Nov 2018 13:07:59 -0500 Subject: [PATCH 21/21] STYLE: Remove unnecessary vcl_XXX.h headers Now that all supported compilers simply result in vcl_* being an alias to exactly one function signature (i.e. namely the one provided in the std:: namespace) there is no need to use the vcl_ aliases. The vcl_XXX.h headers used in these files are simple files that only include the c++11 standard headers that were already included, thereby making these lines of code completely redundant. Dependance on VCL_CHAR_IS_UNSIGNED variable was removed in favor of std::numeric_limits::is_signed Replaced VCL_LIMIT with NUM_LIMIT to reflect the change made from vcl to std::numeric_limits vxl/scripts/VCL_ModernizeNaming.py --- examples/VectorKernelPCA.cxx | 52 +++++++++++++++++------------------ include/itkVectorFieldPCA.h | 2 +- include/itkVectorFieldPCA.hxx | 2 +- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/examples/VectorKernelPCA.cxx b/examples/VectorKernelPCA.cxx index 8772b52..cfb6ab8 100644 --- a/examples/VectorKernelPCA.cxx +++ b/examples/VectorKernelPCA.cxx @@ -25,10 +25,10 @@ int showUsage(const char* programName) { - vcl_cerr << "USAGE: " << programName << " " << vcl_endl; - vcl_cerr << " " << vcl_endl; - vcl_cerr << "\t\tpcaCount : number of principal components to calculate" << vcl_endl; - vcl_cerr << "\t\tkernelSigma : KernelSigma" << vcl_endl; + std::cerr << "USAGE: " << programName << " " << std::endl; + std::cerr << " " << std::endl; + std::cerr << "\t\tpcaCount : number of principal components to calculate" << std::endl; + std::cerr << "\t\tkernelSigma : KernelSigma" << std::endl; return EXIT_FAILURE; } @@ -88,17 +88,17 @@ int main( int argc, char *argv[] ) } catch( itk::ExceptionObject & excp ) { - vcl_cerr << "Error reading mesh file " << inMeshFile << vcl_endl; - vcl_cerr << excp << vcl_endl; + std::cerr << "Error reading mesh file " << inMeshFile << std::endl; + std::cerr << excp << std::endl; } // get the objects InMeshType::Pointer mesh = meshReader->GetOutput(); - vcl_cout << "Vertex Count: " << - mesh->GetNumberOfPoints() << vcl_endl; - vcl_cout << "Cell Count: " << - mesh->GetNumberOfCells() << vcl_endl; + std::cout << "Vertex Count: " << + mesh->GetNumberOfPoints() << std::endl; + std::cout << "Cell Count: " << + mesh->GetNumberOfCells() << std::endl; const char* vectorFieldName; PCACalculatorType::VectorFieldType vectorField; @@ -127,8 +127,8 @@ int main( int argc, char *argv[] ) } catch( itk::ExceptionObject & excp ) { - vcl_cerr << "Error reading mesh field file " << vectorFieldName << vcl_endl; - vcl_cerr << excp << vcl_endl; + std::cerr << "Error reading mesh field file " << vectorFieldName << std::endl; + std::cerr << excp << std::endl; } // get the objects @@ -146,9 +146,9 @@ int main( int argc, char *argv[] ) } if (vectorFieldCount != meshWithField->GetNumberOfPoints()) { - vcl_cerr << "Vector field count (" << vectorFieldCount << + std::cerr << "Vector field count (" << vectorFieldCount << ") doesn't match mesh vertext count (" << - meshWithField->GetNumberOfPoints() << ")." << vcl_endl; + meshWithField->GetNumberOfPoints() << ")." << std::endl; exit (EXIT_FAILURE); } vectorField.set_size(vectorFieldCount, vectorFieldDimension); @@ -158,9 +158,9 @@ int main( int argc, char *argv[] ) if (vectorFieldDimension != vectorField.cols() || vectorFieldCount != vectorField.rows()) { - vcl_cerr << "Unexpected dimensions in vector field file " << vectorFieldName << vcl_endl; - vcl_cerr << "\tExpected " << vectorFieldCount << " x " << vectorFieldDimension; - vcl_cerr << "\t, got " << vectorField.rows() << " x " << vectorField.cols() << vcl_endl; + std::cerr << "Unexpected dimensions in vector field file " << vectorFieldName << std::endl; + std::cerr << "\tExpected " << vectorFieldCount << " x " << vectorFieldDimension; + std::cerr << "\t, got " << vectorField.rows() << " x " << vectorField.cols() << std::endl; exit(1); } } @@ -196,7 +196,7 @@ int main( int argc, char *argv[] ) } catch( itk::ExceptionObject & excp ) { - vcl_cerr << excp << vcl_endl; + std::cerr << excp << std::endl; return EXIT_FAILURE; } @@ -266,8 +266,8 @@ int main( int argc, char *argv[] ) // The name of the file to be read or written is passed with the // SetFileName() method. char outFileName[2048]; - vcl_strcpy(outFileName, outFileNameBase); - vcl_strcat(outFileName, "Ave.vtk"); + std::strcpy(outFileName, outFileNameBase); + std::strcat(outFileName, "Ave.vtk"); meshWriter->SetFileName(outFileName); meshWriter->SetInput(outMesh); @@ -278,7 +278,7 @@ int main( int argc, char *argv[] ) } catch( itk::ExceptionObject & excp ) { - vcl_cerr << excp << vcl_endl; + std::cerr << excp << std::endl; return EXIT_FAILURE; } @@ -298,12 +298,12 @@ int main( int argc, char *argv[] ) } // The name of the file to be read or written is passed with the // SetFileName() method. - vcl_strcpy(outFileName, outFileNameBase); - vcl_strcat(outFileName, "Basis"); + std::strcpy(outFileName, outFileNameBase); + std::strcat(outFileName, "Basis"); char fileCount[8]; sprintf(fileCount, "%d", j + 1); - vcl_strcat(outFileName, fileCount); - vcl_strcat(outFileName, ".vtk"); + std::strcat(outFileName, fileCount); + std::strcat(outFileName, ".vtk"); meshWriter->SetFileName(outFileName); meshWriter->SetInput(outMesh); @@ -314,7 +314,7 @@ int main( int argc, char *argv[] ) } catch( itk::ExceptionObject & excp ) { - vcl_cerr << excp << vcl_endl; + std::cerr << excp << std::endl; return EXIT_FAILURE; } } diff --git a/include/itkVectorFieldPCA.h b/include/itkVectorFieldPCA.h index 1bbdadd..75f5af4 100644 --- a/include/itkVectorFieldPCA.h +++ b/include/itkVectorFieldPCA.h @@ -79,7 +79,7 @@ class ITK_EXPORT GaussianDistanceKernel : public KernelFunctionBase