From 3bcd064e000912302f2f0d3556d518ff46c146aa Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leonardo=20Fl=C3=B3rez-Valencia?= Date: Thu, 5 Oct 2017 16:22:00 -0500 Subject: [PATCH] ... --- CMakeLists.txt | 24 +-- appli/CTArteries/CMakeLists.txt | 12 +- appli/CTArteries/CTArteries.cxx | 113 +++++++---- appli/CTArteries/CTArteries.h | 4 +- appli/CTArteries/Parameters.ui | 4 +- .../algorithms/DijkstraWithMeanAndVariance.h | 4 +- .../algorithms/RandomWalkLabelling.hxx | 27 +-- .../algorithms/RandomWalkSegmentation.h | 5 +- .../algorithms/RandomWalkSegmentation.hxx | 106 +++++----- cmake/Definitions.cmake | 53 ----- cmake/Functions.cmake | 160 --------------- cmake/InstallCommands.cmake | 40 ---- cmake_uninstall.cmake.in | 27 +++ data/axial_CT_slice.mhd | 13 ++ data/axial_CT_slice.raw | Bin 0 -> 65536 bytes data/axial_CT_slice_labels_00.mhd | 13 ++ data/axial_CT_slice_labels_00.raw | Bin 0 -> 65536 bytes examples/image/Dijkstra/CMakeLists.txt | 3 +- examples/image/RandomWalker/CMakeLists.txt | 3 +- examples/image/RegionGrow/CMakeLists.txt | 3 +- lib/fpa/CMakeLists.txt | 12 +- lib/fpa/Common/IncrementalMeanAndVariance.cxx | 74 ------- lib/fpa/Common/IncrementalMeanAndVariance.h | 44 ----- lib/fpa/Common/PeakDetector.cxx | 187 ------------------ lib/fpa/Common/PeakDetector.h | 75 ------- lib/fpa/Filters/Mori.h | 5 +- 26 files changed, 255 insertions(+), 756 deletions(-) delete mode 100644 cmake/Definitions.cmake delete mode 100644 cmake/Functions.cmake delete mode 100644 cmake/InstallCommands.cmake create mode 100644 cmake_uninstall.cmake.in create mode 100644 data/axial_CT_slice.mhd create mode 100644 data/axial_CT_slice.raw create mode 100644 data/axial_CT_slice_labels_00.mhd create mode 100644 data/axial_CT_slice_labels_00.raw delete mode 100644 lib/fpa/Common/IncrementalMeanAndVariance.cxx delete mode 100644 lib/fpa/Common/IncrementalMeanAndVariance.h delete mode 100644 lib/fpa/Common/PeakDetector.cxx delete mode 100644 lib/fpa/Common/PeakDetector.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 184f556..6031b51 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,17 +21,8 @@ foreach(_p ${_policies}) endif(POLICY ${_p}) endforeach(_p) -## == Some general configuration -include(cmake/Definitions.cmake) -include(cmake/Functions.cmake) - ## == Find cpPlugins -find_package(cpPlugins CONFIG) -if(NOT cpPlugins_FOUND) - ## == Find individual ITK (for a minimal build) - find_package(ITK CONFIG REQUIRED) - include(${ITK_USE_FILE}) -endif(NOT cpPlugins_FOUND) +find_package(cpPlugins CONFIG REQUIRED) ## == Find eigen3 (http://eigen.tuxfamily.org) find_package(Eigen3 CONFIG) @@ -40,10 +31,21 @@ if(Eigen3_FOUND) endif(Eigen3_FOUND) ## == Build packages +set(fpa_BUILD 1) subdirs(lib examples appli) ## == Installation commands -include(cmake/InstallCommands.cmake) +include(${cpPlugins_INSTALL_FILE}) + +## == Uninstall target +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY + ) +add_custom_target( + uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) ## eof - $RCSfile$ diff --git a/appli/CTArteries/CMakeLists.txt b/appli/CTArteries/CMakeLists.txt index 25a4109..f968ebc 100644 --- a/appli/CTArteries/CMakeLists.txt +++ b/appli/CTArteries/CMakeLists.txt @@ -2,9 +2,15 @@ ## @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) ## ========================================================================= -if(cpPlugins_FOUND) +if(cpPlugins_USE_VTK AND cpPlugins_USE_Qt5) find_package(Qt5 CONFIG REQUIRED COMPONENTS PrintSupport) - BuildApplication(CTArteries fpa cpPlugins::ivq Qt5::PrintSupport) -endif(cpPlugins_FOUND) + BuildApplication( + CTArteries + SOURCE . + INSTALL + RECURRENT + LINKS fpa Qt5::PrintSupport + ) +endif(cpPlugins_USE_VTK AND cpPlugins_USE_Qt5) ## eof - $RCSfile$ diff --git a/appli/CTArteries/CTArteries.cxx b/appli/CTArteries/CTArteries.cxx index 345b94e..8b8a333 100644 --- a/appli/CTArteries/CTArteries.cxx +++ b/appli/CTArteries/CTArteries.cxx @@ -122,6 +122,16 @@ CTArteries( int argc, char* argv[], QWidget* parent ) QT_ACTION_CONN( Open ); QT_ACTION_CONN( Config ); QT_ACTION_CONN( Process ); + + // Load log + if( argc == 3 ) + { + std::string cmd( argv[ 1 ] ); + std::string fname( argv[ 2 ] ); + if( cmd == "-log" ) + this->_ExecuteLog( fname ); + + } // fi } // ------------------------------------------------------------------------- @@ -138,6 +148,13 @@ template< class _TStrings > void CTArteries:: _openImage( const _TStrings& fnames ) { + // Save log + std::ofstream str_log( "CTArteries.log" ); + str_log << fnames.size( ) << std::endl; + for( const std::string& s: fnames ) + str_log << s << std::endl; + str_log.close( ); + // Create appropriate reader itk::ImageSource< TImage >::Pointer reader; if( fnames.size( ) == 1 ) @@ -221,36 +238,17 @@ _showInputImage( ) // ------------------------------------------------------------------------- void CTArteries:: -_process( ) +_process( const std::vector< TImage::PointType >& seeds ) { - // Get seeds - typedef ivq::VTK::SeedWidgetOverImageActor::TSeeds _TSeeds; - if( this->m_Image.IsNull( ) || this->m_Seeds.GetPointer( ) == NULL ) - { - QMessageBox::critical( this, "Error processing", "No valid input image." ); - return; - - } // fi - std::vector< TImage::PointType > seeds; - for( _TSeeds::value_type sValue: this->m_Seeds->GetSeeds( ) ) - { - for( unsigned int i = 0; i < sValue.second.size( ); i += 3 ) - { - TImage::PointType pnt; - pnt[ 0 ] = sValue.second[ i + 0 ]; - pnt[ 1 ] = sValue.second[ i + 1 ]; - pnt[ 2 ] = sValue.second[ i + 2 ]; - seeds.push_back( pnt ); - - } // rof - - } // rof - if( seeds.size( ) < 2 ) - { - QMessageBox::critical( this, "Error processing", "Not enough seeds." ); - return; - - } // fi + // Save log + std::ofstream str_log( "CTArteries.log", std::ios_base::app ); + str_log << this->m_UIParameters->Beta->value( ) << std::endl; + str_log << this->m_UIParameters->Sigma->value( ) << std::endl; + str_log << this->m_UIParameters->Radius->value( ) << std::endl; + str_log << seeds.size( ) << std::endl; + for( TImage::PointType seed: seeds ) + str_log << seed << std::endl; + str_log.close( ); // Create algorithm typedef RandomWalkSegmentation< TImage, TScalarImage > _TSegmentation; @@ -265,7 +263,9 @@ _process( ) seg->AddSeed( seed ); try { + seg->DebugOn( ); seg->Update( ); + seg->DebugOff( ); } catch( std::exception& err ) { @@ -370,12 +370,17 @@ _prepareQuantification( ) while( lines->GetNextCell( npts, ids ) != 0 ) mesh->AddEdge( ids[ 0 ], ids[ 1 ] ); delete ids; - mesh->AddFace( mesh->GetEdge( ) ); _TQEMesh::QEPrimal* edge = mesh->GetEdge( ); - for( auto eIt = edge->BeginGeomLnext( ); eIt != edge->EndGeomLnext( ); ++eIt ) - points.push_back( mesh->GetPoint( *eIt ) ); + if( edge != NULL ) + { + mesh->AddFace( edge ); + edge = mesh->GetEdge( ); + for( auto eIt = edge->BeginGeomLnext( ); eIt != edge->EndGeomLnext( ); ++eIt ) + points.push_back( mesh->GetPoint( *eIt ) ); + + } // fi - TFourier f( points.begin( ), points.end( ), 3 ); + TFourier f( points.begin( ), points.end( ), 6 ); f.SetOrderingToCounterClockWise( ); this->m_Fourier.push_back( f ); @@ -531,6 +536,18 @@ _showProcessResults( ) this->_prepareQuantification( ); } +// ------------------------------------------------------------------------- +void CTArteries:: +_ExecuteLog( const std::string& fname ) +{ + std::ifstream str_log( fname.c_str( ) ); + if( str_log ) + { + str_log.close( ); + + } // fi +} + // ------------------------------------------------------------------------- void CTArteries:: _sOpen( ) @@ -579,7 +596,35 @@ _sConfig( ) void CTArteries:: _sProcess( ) { - this->_process( ); + // Get seeds + typedef ivq::VTK::SeedWidgetOverImageActor::TSeeds _TSeeds; + if( this->m_Image.IsNull( ) || this->m_Seeds.GetPointer( ) == NULL ) + { + QMessageBox::critical( this, "Error processing", "No valid input image." ); + return; + + } // fi + std::vector< TImage::PointType > seeds; + for( _TSeeds::value_type sValue: this->m_Seeds->GetSeeds( ) ) + { + for( unsigned int i = 0; i < sValue.second.size( ); i += 3 ) + { + TImage::PointType pnt; + pnt[ 0 ] = sValue.second[ i + 0 ]; + pnt[ 1 ] = sValue.second[ i + 1 ]; + pnt[ 2 ] = sValue.second[ i + 2 ]; + seeds.push_back( pnt ); + + } // rof + + } // rof + if( seeds.size( ) < 2 ) + { + QMessageBox::critical( this, "Error processing", "Not enough seeds." ); + return; + + } // fi + this->_process( seeds ); this->_showProcessResults( ); } diff --git a/appli/CTArteries/CTArteries.h b/appli/CTArteries/CTArteries.h index 4875917..b3e97c5 100644 --- a/appli/CTArteries/CTArteries.h +++ b/appli/CTArteries/CTArteries.h @@ -72,10 +72,12 @@ protected: void _openDicom( const std::string& dirname ); void _showInputImage( ); - void _process( ); + void _process( const std::vector< TImage::PointType >& seeds ); void _prepareQuantification( ); void _showProcessResults( ); + void _ExecuteLog( const std::string& fname ); + protected slots: void _sOpen( ); void _sConfig( ); diff --git a/appli/CTArteries/Parameters.ui b/appli/CTArteries/Parameters.ui index 2a40238..566bf01 100644 --- a/appli/CTArteries/Parameters.ui +++ b/appli/CTArteries/Parameters.ui @@ -71,7 +71,7 @@ 100000.000000000000000 - 20.000000000000000 + 90.000000000000000 @@ -131,7 +131,7 @@ 100000.000000000000000 - 5.000000000000000 + 7.000000000000000 diff --git a/appli/CTArteries/algorithms/DijkstraWithMeanAndVariance.h b/appli/CTArteries/algorithms/DijkstraWithMeanAndVariance.h index a82c8aa..e5c3274 100644 --- a/appli/CTArteries/algorithms/DijkstraWithMeanAndVariance.h +++ b/appli/CTArteries/algorithms/DijkstraWithMeanAndVariance.h @@ -4,9 +4,9 @@ #ifndef __DijkstraWithMeanAndVariance__h__ #define __DijkstraWithMeanAndVariance__h__ -#include #include #include +#include /** */ @@ -22,7 +22,7 @@ public: typedef typename Superclass::TTraits TTraits; fpaTraitsMacro( typename TTraits ); - typedef fpa::Common::IncrementalMeanAndVariance TMeanAndVar; + typedef ivq::ITK::IncrementalMeanAndVariance TMeanAndVar; public: itkNewMacro( Self ); diff --git a/appli/CTArteries/algorithms/RandomWalkLabelling.hxx b/appli/CTArteries/algorithms/RandomWalkLabelling.hxx index 3cd2c6a..de662f1 100644 --- a/appli/CTArteries/algorithms/RandomWalkLabelling.hxx +++ b/appli/CTArteries/algorithms/RandomWalkLabelling.hxx @@ -47,6 +47,7 @@ void RandomWalkLabelling< _TRawImage, _TCostsImage, _TLabelsImage >:: SetOutsideLabel( const TLabel& v ) { this->SetInitValue( v ); + this->SetFillValue( v ); } // ------------------------------------------------------------------------- @@ -111,9 +112,9 @@ _PostComputeOutputValue( TNode& n ) if( costs->GetPixel( n.Vertex ) == this->m_MaxCost ) { double v = double( raw->GetPixel( n.Vertex ) ); - if( v <= this->m_LowerThreshold ) + if( v < this->m_LowerThreshold ) n.Value = this->GetLowerLabel( ); - else if( v >= this->m_UpperThreshold ) + else if( this->m_UpperThreshold < v ) n.Value = this->GetUpperLabel( ); else n.Value = TLabel( 0 ); @@ -135,17 +136,21 @@ void RandomWalkLabelling< _TRawImage, _TCostsImage, _TLabelsImage >:: _Reinitialize( ) { const TPath* path = this->GetInputPath( ); - while( - this->_GetMark( path->GetVertex( this->m_CurrIdx ) ) > 0 && - this->m_CurrIdx < path->GetSize( ) - ) - this->m_CurrIdx += 1; if( this->m_CurrIdx < path->GetSize( ) ) { - TNode node; - node.Vertex = node.Parent = path->GetVertex( this->m_CurrIdx ); - node.FrontId = 1; - this->_QueuePush( node ); + while( + this->_GetMark( path->GetVertex( this->m_CurrIdx ) ) > 0 && + this->m_CurrIdx < path->GetSize( ) + ) + this->m_CurrIdx += 1; + if( this->m_CurrIdx < path->GetSize( ) ) + { + TNode node; + node.Vertex = node.Parent = path->GetVertex( this->m_CurrIdx ); + node.FrontId = 1; + this->_QueuePush( node ); + + } // fi } // fi } diff --git a/appli/CTArteries/algorithms/RandomWalkSegmentation.h b/appli/CTArteries/algorithms/RandomWalkSegmentation.h index 6644dba..b7199de 100644 --- a/appli/CTArteries/algorithms/RandomWalkSegmentation.h +++ b/appli/CTArteries/algorithms/RandomWalkSegmentation.h @@ -75,7 +75,7 @@ private: void _SynchSeed( const _TIn* in, _TSeed& seed ); template< class _TIn, class _TOutPtr > - void _Smooth( const _TIn* in, _TOutPtr& out ); + void _Smooth( const _TIn* in, _TOutPtr& out, double s ); template< class _TIn, class _TOutPtr, class _TAxisPtr, class _TSeeds > typename _TIn::RegionType _RawSegmentation( @@ -121,6 +121,9 @@ private: _TOutPtr& out_dist, _TAxisPtr& out_axis ); + template< class _TInPtr > + void _Save( const _TInPtr& in, const std::string& fname ); + private: // Purposely not implemented RandomWalkSegmentation( const Self& other ); diff --git a/appli/CTArteries/algorithms/RandomWalkSegmentation.hxx b/appli/CTArteries/algorithms/RandomWalkSegmentation.hxx index 15fb9af..30738e9 100644 --- a/appli/CTArteries/algorithms/RandomWalkSegmentation.hxx +++ b/appli/CTArteries/algorithms/RandomWalkSegmentation.hxx @@ -12,15 +12,7 @@ #include "DijkstraWithMeanAndVariance.h" #include "RandomWalkLabelling.h" -/* TODO - #include - #include - - - #include - - #include -*/ +#include // ------------------------------------------------------------------------- template< class _TInputImage, class _TOutputImage > @@ -140,9 +132,12 @@ GenerateData( ) // Smooth input typename TOutputImage::Pointer smooth_in; - this->_Smooth( this->GetInput( ), smooth_in ); + std::cout << "smooth" << std::endl; + this->_Smooth( this->GetInput( ), smooth_in, 2 ); + this->_Save( smooth_in, "smooth.mhd" ); // Initial segmentation + std::cout << "raw" << std::endl; typename TOutputImage::Pointer init_seg; typename TPath::Pointer init_axis; _TScalar init_mean, init_std; @@ -153,9 +148,12 @@ GenerateData( ) this->m_Beta, init_seg, init_axis, init_mean, init_std ); + std::cout << "Stat: " << init_mean << " +/- " << init_std << std::endl; init_std *= _TScalar( this->m_Sigma ); + this->_Save( init_seg, "raw.mhd" ); // Extract input ROIs + std::cout << "ROI" << std::endl; typename TOutputImage::Pointer smooth_in_roi, init_seg_roi; roi = this->_ROI( smooth_in.GetPointer( ), roi, 10, smooth_in_roi ); this->_ROI( init_seg.GetPointer( ), roi, 0, init_seg_roi ); @@ -164,6 +162,7 @@ GenerateData( ) this->_AxisROI( init_axis.GetPointer( ), roi, init_axis_roi ); // Labelling + std::cout << "labelling" << std::endl; typename _TLabels::Pointer init_labels; _TScalar radius = _TScalar( this->m_Radius ); this->_Label( @@ -173,17 +172,20 @@ GenerateData( ) init_mean, init_std, radius, init_labels ); + this->_Save( init_labels, "init_labels.mhd" ); // Random walker + std::cout << "random walker " << init_std << " " << this->m_Beta << std::endl; typename _TLabels::Pointer rw_seg; this->_RandomWalker( smooth_in_roi.GetPointer( ), init_labels.GetPointer( ), - init_std / _TScalar( 2 ), + this->m_Beta, // init_std / _TScalar( 2 ), rw_seg ); // ROI outputs + std::cout << "axis" << std::endl; typename TOutputImage::Pointer out_dist; typename TPath::Pointer out_axis; this->_DistanceAndAxis( @@ -193,37 +195,34 @@ GenerateData( ) ); // Put everything back to requested region - /* TODO - std::cout << "6" << std::endl; - { // begin - TOutputImage* output = this->GetOutput( ); - output->SetBufferedRegion( output->GetRequestedRegion( ) ); - output->Allocate( ); - output->FillBuffer( -std::numeric_limits< _TScalar >::max( ) ); - - itk::ImageRegionConstIterator< TOutputImage > rIt( - output_roi, output_roi->GetRequestedRegion( ) - ); - itk::ImageRegionIterator< TOutputImage > oIt( output, roi ); - rIt.GoToBegin( ); - oIt.GoToBegin( ); - for( ; !rIt.IsAtEnd( ); ++rIt, ++oIt ) - oIt.Set( rIt.Get( ) ); - - TPath* output_axis = this->GetOutputAxis( ); - output_axis->SetReferenceImage( output ); - for( unsigned long i = 0; i < output_axis_roi->GetSize( ); ++i ) - { - TIndex v = output_axis_roi->GetVertex( i ); - for( unsigned int d = 0; d < TInputImage::ImageDimension; ++d ) - v[ d ] += roi.GetIndex( )[ d ]; - output_axis->AddVertex( v ); - - } // rof - - } // end - std::cout << "7" << std::endl; - */ + std::cout << "output" << std::endl; + { // begin + TOutputImage* output = this->GetOutput( ); + output->SetBufferedRegion( output->GetRequestedRegion( ) ); + output->Allocate( ); + output->FillBuffer( -std::numeric_limits< _TScalar >::max( ) ); + + itk::ImageRegionConstIterator< TOutputImage > rIt( + out_dist, out_dist->GetRequestedRegion( ) + ); + itk::ImageRegionIterator< TOutputImage > oIt( output, roi ); + rIt.GoToBegin( ); + oIt.GoToBegin( ); + for( ; !rIt.IsAtEnd( ); ++rIt, ++oIt ) + oIt.Set( rIt.Get( ) ); + + TPath* output_axis = this->GetOutputAxis( ); + output_axis->SetReferenceImage( output ); + for( unsigned long i = 0; i < out_axis->GetSize( ); ++i ) + { + TIndex v = out_axis->GetVertex( i ); + for( unsigned int d = 0; d < TInputImage::ImageDimension; ++d ) + v[ d ] += roi.GetIndex( )[ d ]; + output_axis->AddVertex( v ); + + } // rof + + } // end } // ------------------------------------------------------------------------- @@ -243,7 +242,7 @@ _SynchSeed( const _TIn* in, _TSeed& seed ) template< class _TInputImage, class _TOutputImage > template< class _TIn, class _TOutPtr > void RandomWalkSegmentation< _TInputImage, _TOutputImage >:: -_Smooth( const _TIn* in, _TOutPtr& out ) +_Smooth( const _TIn* in, _TOutPtr& out, double s ) { typedef typename _TOutPtr::ObjectType _TOut; typedef itk::SmoothingRecursiveGaussianImageFilter< _TIn, _TOut > _TSmooth; @@ -251,7 +250,7 @@ _Smooth( const _TIn* in, _TOutPtr& out ) typename _TSmooth::Pointer smooth = _TSmooth::New( ); smooth->SetInput( in ); smooth->SetNormalizeAcrossScale( true ); - smooth->SetSigmaArray( in->GetSpacing( ) * double( 2 ) ); + smooth->SetSigmaArray( in->GetSpacing( ) * s ); smooth->Update( ); out = smooth->GetOutput( ); out->DisconnectPipeline( ); @@ -380,6 +379,10 @@ _Label( label->Update( ); out = label->GetOutputLabels( ); out->DisconnectPipeline( ); + + std::cout << label->GetLowerThreshold( ) << std::endl; + std::cout << label->GetUpperThreshold( ) << std::endl; + } // ------------------------------------------------------------------------- @@ -447,7 +450,20 @@ _DistanceAndAxis( extract->Update( ); out_axis = TPath::New( ); out_axis->Graft( extract->GetOutput( ) ); - this->_Smooth( extract->GetCenterness( )->GetOutput( ), out_dist ); + this->_Smooth( extract->GetCenterness( )->GetOutput( ), out_dist, 1 ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +template< class _TInPtr > +void RandomWalkSegmentation< _TInputImage, _TOutputImage >:: +_Save( const _TInPtr& in, const std::string& fname ) +{ + typedef itk::ImageFileWriter< typename _TInPtr::ObjectType > _TWriter; + typename _TWriter::Pointer w = _TWriter::New( ); + w->SetInput( in ); + w->SetFileName( fname ); + w->Update( ); } #endif // __RandomWalkSegmentation__hxx__ diff --git a/cmake/Definitions.cmake b/cmake/Definitions.cmake deleted file mode 100644 index 46fb5cf..0000000 --- a/cmake/Definitions.cmake +++ /dev/null @@ -1,53 +0,0 @@ -## ========================================================================= -## @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) -## ========================================================================= - -## == If working on a MacOSX, activate the use of RPATH's -## == Furthermore: prepare the type of executables -set(EXECUTABLE_TYPE "" CACHE STRING "Executable linking." FORCE) -if(APPLE) - set(EXECUTABLE_TYPE "MACOSX_BUNDLE" CACHE STRING "Executable linking." FORCE) - set(CMAKE_MACOSX_RPATH true CACHE BOOL "Use RPATH's on MacOSX." FORCE) - mark_as_advanced(CMAKE_MACOSX_RPATH) -elseif(WIN32) - set(EXECUTABLE_TYPE "WIN32" CACHE STRING "Executable linking." FORCE) -endif(APPLE) -mark_as_advanced(EXECUTABLE_TYPE) - -## == Force c++11 -if(NOT MSVC) - include(CheckCXXCompilerFlag) - check_cxx_compiler_flag("-std=c++11" COMPILER_SUPPORTS_CXX11) - if(COMPILER_SUPPORTS_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - else(COMPILER_SUPPORTS_CXX11) - check_cxx_compiler_flag("-std=c++0x" COMPILER_SUPPORTS_CXX0X) - if(COMPILER_SUPPORTS_CXX0X) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") - else(COMPILER_SUPPORTS_CXX0X) - message( - FATAL_ERROR - "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support." - ) - endif(COMPILER_SUPPORTS_CXX0X) - endif(COMPILER_SUPPORTS_CXX11) -endif(NOT MSVC) - -## == Prepare header generator to build shared libs -include(GenerateExportHeader) - -## == Do not allow to build inside the source tree -if(PROJECT_BINARY_DIR STREQUAL ${PROJECT_SOURCE_DIR}) - message(FATAL_ERROR "Building in the source tree is not allowed.") -endif(PROJECT_BINARY_DIR STREQUAL ${PROJECT_SOURCE_DIR}) - -## == Where to put targets (executables and libs) -set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}) -set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}) -mark_as_advanced( - CMAKE_BACKWARDS_COMPATIBILITY - EXECUTABLE_OUTPUT_PATH - LIBRARY_OUTPUT_PATH - ) - -## eof - $RCSfile$ diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake deleted file mode 100644 index 1649a0b..0000000 --- a/cmake/Functions.cmake +++ /dev/null @@ -1,160 +0,0 @@ -## ========================================================================= -## @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) -## ========================================================================= - -## ------------------------------------------------------------------------- -function(BuildLibrary lib typ src maj min rel) - -## -- Get sources -set(_files) -foreach(_s ${src}) - - ## -- Canonicalize path - get_filename_component(_p "${_s}" ABSOLUTE) - - ## -- Check type of input - if(IS_DIRECTORY ${_p}) - file(GLOB _f "${_p}/*") - foreach(_x ${_f}) - if(NOT IS_DIRECTORY ${_x}) - list(APPEND _files ${_x}) - endif(NOT IS_DIRECTORY ${_x}) - endforeach(_x) - else(IS_DIRECTORY ${_p}) - list(APPEND _files ${_p}) - endif(IS_DIRECTORY ${_p}) - -endforeach(_s) - -## -- Process sources -set(_cpp) -set(_hpp) -set(_qui) -foreach(_f ${_files}) - - ## -- Separate filename from extension - string(REGEX REPLACE "\\.[^.]*$" "" _name ${_f}) - string(REPLACE ${_name} "" _ext ${_f}) - set(_out_name ${_name}) - set(_out_ext ${_ext}) - - ## -- Process .in files - string(COMPARE EQUAL "${_ext}" ".in" _in_cmp) - if(_in_cmp) - string(REPLACE ${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR} _out ${_name}) - configure_file(${_f} ${_out} @ONLY) - string(REGEX REPLACE "\\.[^.]*$" "" _out_name ${_out}) - string(REPLACE ${_out_name} "" _out_ext ${_out}) - endif(_in_cmp) - - ## -- Now, get real extension - string(SUBSTRING ${_out_ext} 0 2 _ext_cmp) - - ## -- Process .c?? files - string(COMPARE EQUAL "${_ext_cmp}" ".c" _c_cmp) - if(_c_cmp) - list(APPEND _cpp ${_out_name}${_out_ext}) - endif(_c_cmp) - - ## -- Process .h?? files - string(COMPARE EQUAL "${_ext_cmp}" ".h" _h_cmp) - if(_h_cmp) - list(APPEND _hpp ${_out_name}${_out_ext}) - endif(_h_cmp) - - ## -- Process .ui files - string(COMPARE EQUAL "${_out_ext}" ".ui" _u_cmp) - if(_u_cmp) - list(APPEND _qui ${_out_name}${_out_ext}) - endif(_u_cmp) - -endforeach(_f) - -## -- Process Qt ui files -list(LENGTH _qui _qui_len) -if(${_qui_len} GREATER 0) - qt5_wrap_ui(_qui_hpp ${_qui}) -endif(${_qui_len} GREATER 0) - -## -- Real build -add_library(${lib} ${typ} ${_cpp} ${_hpp} ${_qui_hpp}) - -## -- Header creation -generate_export_header(${lib}) -set_property(TARGET ${lib} PROPERTY VERSION "${maj}.${min}.${rel}") -set_property(TARGET ${lib} PROPERTY SOVERSION ${maj}) -set_property(TARGET ${lib} PROPERTY INTERFACE_${lib}_MAJOR_VERSION ${maj}) -set_property(TARGET ${lib} APPEND PROPERTY COMPATIBLE_INTERFACE_STRING ${maj}) - -## -- Link library -target_link_libraries(${lib} PUBLIC ${ARGN}) - -## -- Installation rules -option(${lib}_INSTALL_DEVEL "Install development files for ${lib}" OFF) -string(COMPARE EQUAL "${type}" "SHARED" _cmp) -if(_cmp OR ${lib}_INSTALL_DEVEL) - install( - TARGETS ${lib} - EXPORT "${targets_export_name}" - LIBRARY DESTINATION "lib" - ARCHIVE DESTINATION "lib" - RUNTIME DESTINATION "bin" - INCLUDES DESTINATION "${include_install_dir}" - ) -endif(_cmp OR ${lib}_INSTALL_DEVEL) -if(${lib}_INSTALL_DEVEL) - string(TOLOWER ${lib} _lower_lib) - set( - _install_hdr - ${_hpp} - ${CMAKE_CURRENT_BINARY_DIR}/${_lower_lib}_export.h - ) - set(_install_dirs) - foreach(_h ${_install_hdr}) - string(REPLACE ${CMAKE_CURRENT_SOURCE_DIR} "" _h_name ${_h}) - string(COMPARE EQUAL "${_h_name}" "${_h}" _h_cmp) - if(_h_cmp) - string(REPLACE ${CMAKE_CURRENT_BINARY_DIR} "" _h_name ${_h}) - endif(_h_cmp) - set(_h_out ${include_install_dir}/${lib}${_h_name}) - get_filename_component(_h_dir ${_h_out} DIRECTORY) - install( - FILES "${_h}" - DESTINATION "${_h_dir}" - ) - endforeach(_h) -endif(${lib}_INSTALL_DEVEL) - -endfunction() - -## ------------------------------------------------------------------------- -function(BuildLibraryRecursive lib typ dir maj min rel) - -## -- Globbing directory -file(GLOB_RECURSE _files "${dir}/*") - -## -- Build library -BuildLibrary(${lib} ${typ} "${_files}" ${maj} ${min} ${rel} ${ARGN}) - -endfunction() - -## ------------------------------------------------------------------------- -function(BuildApplication app) -option(BUILD_${app} "Build ${app}" OFF) -if(BUILD_${app}) - ## -- Use a static library - BuildLibraryRecursive( - _${app}_ STATIC ${CMAKE_CURRENT_SOURCE_DIR} 0 0 0 ${ARGN} - ) - - ## -- Create an empty application - set(_m ${CMAKE_CURRENT_BINARY_DIR}/__main__${app}.cxx) - file(WRITE ${_m} "// Automatically generated dummy file") - add_executable(${app} ${EXECUTABLE_TYPE} ${_m}) - - ## -- Link it against static library - target_link_libraries(${app} PUBLIC _${app}_) -endif(BUILD_${app}) -endfunction() - -## eof - $RCSfile$ diff --git a/cmake/InstallCommands.cmake b/cmake/InstallCommands.cmake deleted file mode 100644 index 97500ae..0000000 --- a/cmake/InstallCommands.cmake +++ /dev/null @@ -1,40 +0,0 @@ -## ========================================================================= -## @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) -## ========================================================================= - -## ========================= -## == Installation values == -## ========================= - -set(config_install_dir "lib/cmake/${PROJECT_NAME}") -set(include_install_dir "include") -set(generated_dir "${PROJECT_BINARY_DIR}/generated") -set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake") -set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake") -set(targets_export_name "${PROJECT_NAME}Targets") -set(namespace "${PROJECT_NAME}::") - -## =============================== -## == Global installation rules == -## =============================== - -include(CMakePackageConfigHelpers) -write_basic_package_version_file( - "${version_config}" COMPATIBILITY SameMajorVersion - ) -configure_package_config_file( - "cmake/${PROJECT_NAME}Config.cmake.in" - "${project_config}" - INSTALL_DESTINATION "${config_install_dir}" - ) -install( - EXPORT "${targets_export_name}" - NAMESPACE "${namespace}" - DESTINATION "${config_install_dir}" - ) -install( - FILES "${project_config}" - DESTINATION "${config_install_dir}" - ) - -## eof - $RCSfile$ diff --git a/cmake_uninstall.cmake.in b/cmake_uninstall.cmake.in new file mode 100644 index 0000000..34c9330 --- /dev/null +++ b/cmake_uninstall.cmake.in @@ -0,0 +1,27 @@ +## ========================================================================= +## @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +## ========================================================================= + +if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") +endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + +file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") +foreach(file ${files}) + message(STATUS "Uninstalling $ENV{DESTDIR}${file}") + if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + exec_program( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + if(NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") + endif(NOT "${rm_retval}" STREQUAL 0) + else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + message(STATUS "File $ENV{DESTDIR}${file} does not exist.") + endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") +endforeach(file) + +## eof - $RCSfile$ diff --git a/data/axial_CT_slice.mhd b/data/axial_CT_slice.mhd new file mode 100644 index 0000000..ee256bf --- /dev/null +++ b/data/axial_CT_slice.mhd @@ -0,0 +1,13 @@ +ObjectType = Image +NDims = 2 +BinaryData = True +BinaryDataByteOrderMSB = False +CompressedData = False +TransformMatrix = 1 0 0 1 +Offset = 0 0 +CenterOfRotation = 0 0 +ElementSpacing = 1 1 +DimSize = 256 256 +AnatomicalOrientation = ?? +ElementType = MET_UCHAR +ElementDataFile = axial_CT_slice.raw diff --git a/data/axial_CT_slice.raw b/data/axial_CT_slice.raw new file mode 100644 index 0000000000000000000000000000000000000000..ffce46323a72974459506cc1411f06ad54ab905a GIT binary patch literal 65536 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 literal 0 HcmV?d00001 diff --git a/data/axial_CT_slice_labels_00.mhd b/data/axial_CT_slice_labels_00.mhd new file mode 100644 index 0000000..47eca6b --- /dev/null +++ b/data/axial_CT_slice_labels_00.mhd @@ -0,0 +1,13 @@ +ObjectType = Image +NDims = 2 +BinaryData = True +BinaryDataByteOrderMSB = False +CompressedData = False +TransformMatrix = 1 0 0 1 +Offset = 0 0 +CenterOfRotation = 0 0 +ElementSpacing = 1 1 +DimSize = 256 256 +AnatomicalOrientation = ?? +ElementType = MET_UCHAR +ElementDataFile = axial_CT_slice_labels_00.raw diff --git a/data/axial_CT_slice_labels_00.raw b/data/axial_CT_slice_labels_00.raw new file mode 100644 index 0000000000000000000000000000000000000000..a1ce172836b2f35c9fc2f2a47a801289beb0cfa0 GIT binary patch literal 65536 zcmeIu!3h8W2m>*7|Dhd1gg(*%j*==PK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+z>`2fb!7< -#include - -// ------------------------------------------------------------------------- -fpa::Common::IncrementalMeanAndVariance:: -IncrementalMeanAndVariance( ) -{ - this->Clear( ); -} - -// ------------------------------------------------------------------------- -fpa::Common::IncrementalMeanAndVariance:: -~IncrementalMeanAndVariance( ) -{ -} - -// ------------------------------------------------------------------------- -double fpa::Common::IncrementalMeanAndVariance:: -GetMean( ) const -{ - return( this->m_M ); -} - -// ------------------------------------------------------------------------- -double fpa::Common::IncrementalMeanAndVariance:: -GetVariance( ) const -{ - return( this->m_V ); -} - -// ------------------------------------------------------------------------- -double fpa::Common::IncrementalMeanAndVariance:: -GetDeviation( ) const -{ - return( std::sqrt( this->m_V ) ); -} - -// ------------------------------------------------------------------------- -unsigned long fpa::Common::IncrementalMeanAndVariance:: -GetNumberOfSamples( ) const -{ - return( ( unsigned long )( this->m_N ) ); -} - -// ------------------------------------------------------------------------- -void fpa::Common::IncrementalMeanAndVariance:: -Clear( ) -{ - this->m_M = double( 0 ); - this->m_V = double( 0 ); - this->m_N = double( 0 ); -} - -// ------------------------------------------------------------------------- -void fpa::Common::IncrementalMeanAndVariance:: -AddValue( double v ) -{ - this->m_N += double( 1 ); - double d = v - this->m_M; - if( this->m_N > double( 1 ) ) - { - double o = ( this->m_N - double( 2 ) ) / ( this->m_N - double( 1 ) ); - this->m_V = ( o * this->m_V ) + ( ( d * d ) / this->m_N ); - } - else - this->m_V = double( 0 ); - this->m_M += d / this->m_N; -} - -// eof - $RCSfile$ diff --git a/lib/fpa/Common/IncrementalMeanAndVariance.h b/lib/fpa/Common/IncrementalMeanAndVariance.h deleted file mode 100644 index 83383c3..0000000 --- a/lib/fpa/Common/IncrementalMeanAndVariance.h +++ /dev/null @@ -1,44 +0,0 @@ -// ========================================================================= -// @author Leonardo Florez Valencia -// @email florez-l@javeriana.edu.co -// ========================================================================= -#ifndef __fpa__Common__IncrementalMeanAndVariance__h__ -#define __fpa__Common__IncrementalMeanAndVariance__h__ - -#include - -namespace fpa -{ - namespace Common - { - /** - */ - class FPA_EXPORT IncrementalMeanAndVariance - { - public: - typedef IncrementalMeanAndVariance Self; - - public: - IncrementalMeanAndVariance( ); - virtual ~IncrementalMeanAndVariance( ); - - double GetMean( ) const; - double GetVariance( ) const; - double GetDeviation( ) const; - unsigned long GetNumberOfSamples( ) const; - - void Clear( ); - void AddValue( double v ); - - protected: - double m_M; - double m_V; - double m_N; - }; - - } // ecapseman - -} // ecapseman - -#endif // __fpa__Common__IncrementalMeanAndVariance__h__ -// eof - $RCSfile$ diff --git a/lib/fpa/Common/PeakDetector.cxx b/lib/fpa/Common/PeakDetector.cxx deleted file mode 100644 index 0a53e1e..0000000 --- a/lib/fpa/Common/PeakDetector.cxx +++ /dev/null @@ -1,187 +0,0 @@ -// ========================================================================= -// @author Leonardo Florez Valencia -// @email florez-l@javeriana.edu.co -// ========================================================================= -#include -#include - -// ------------------------------------------------------------------------- -fpa::Common::PeakDetector:: -PeakDetector( ) - : m_K( 3 ), - m_T( 3.5 ), - m_I( 0.5 ) -{ -} - -// ------------------------------------------------------------------------- -fpa::Common::PeakDetector:: -~PeakDetector( ) -{ -} - -// ------------------------------------------------------------------------- -unsigned long fpa::Common::PeakDetector:: -GetKernelSize( ) const -{ - return( this->m_K ); -} - -// ------------------------------------------------------------------------- -double fpa::Common::PeakDetector:: -GetThreshold( ) const -{ - return( this->m_T ); -} - -// ------------------------------------------------------------------------- -double fpa::Common::PeakDetector:: -GetInfluence( ) const -{ - return( this->m_I ); -} - -// ------------------------------------------------------------------------- -void fpa::Common::PeakDetector:: -SetKernelSize( unsigned long k ) -{ - this->m_K = k; - this->Clear( ); -} - -// ------------------------------------------------------------------------- -void fpa::Common::PeakDetector:: -SetThreshold( double t ) -{ - this->m_T = t; - this->Clear( ); -} - -// ------------------------------------------------------------------------- -void fpa::Common::PeakDetector:: -SetInfluence( double i ) -{ - this->m_I = i; - this->Clear( ); -} - -// ------------------------------------------------------------------------- -void fpa::Common::PeakDetector:: -Clear( ) -{ - this->m_X.clear( ); - this->m_Y.clear( ); - this->m_YF.clear( ); - this->m_Avg.clear( ); - this->m_STD.clear( ); - this->m_Peaks.clear( ); - this->m_MeanAndVar.Clear( ); -} - -// ------------------------------------------------------------------------- -const std::vector< double >& fpa::Common::PeakDetector:: -GetXValues( ) const -{ - return( this->m_X ); -} - -// ------------------------------------------------------------------------- -const std::vector< double >& fpa::Common::PeakDetector:: -GetYValues( ) const -{ - return( this->m_Y ); -} - -// ------------------------------------------------------------------------- -const std::vector< double >& fpa::Common::PeakDetector:: -GetFilteredYValues( ) const -{ - return( this->m_YF ); -} - -// ------------------------------------------------------------------------- -const std::vector< double >& fpa::Common::PeakDetector:: -GetAverages( ) const -{ - return( this->m_Avg ); -} - -// ------------------------------------------------------------------------- -const std::vector< double >& fpa::Common::PeakDetector:: -GetDeviations( ) const -{ - return( this->m_STD ); -} - -// ------------------------------------------------------------------------- -const std::vector< fpa::Common::PeakDetector::TPeak >& fpa::Common:: -PeakDetector::GetPeaks( ) const -{ - return( this->m_Peaks ); -} - -// ------------------------------------------------------------------------- -unsigned long fpa::Common::PeakDetector:: -GetNumberOfSamples( ) const -{ - return( this->m_X.size( ) ); -} - -// ------------------------------------------------------------------------- -fpa::Common::PeakDetector:: -TPeak fpa::Common::PeakDetector:: -AddValue( double x, double y ) -{ - this->m_X.push_back( x ); - this->m_Y.push_back( y ); - - if( this->m_YF.size( ) < this->m_K ) - { - this->m_YF.push_back( y ); - this->m_Avg.push_back( double( 0 ) ); - this->m_STD.push_back( double( 0 ) ); - this->m_Peaks.push_back( Self::NoPeak ); - - this->m_MeanAndVar.AddValue( y ); - if( this->m_YF.size( ) == this->m_K ) - { - this->m_Avg.push_back( this->m_MeanAndVar.GetMean( ) ); - this->m_STD.push_back( this->m_MeanAndVar.GetDeviation( ) ); - - } // fi - } - else - { - unsigned long i = this->m_X.size( ) - 1; - if( - ( std::fabs( y - this->m_Avg[ i - 1 ] ) ) > - ( this->m_T * this->m_STD[ i - 1 ] ) - ) - { - this->m_Peaks.push_back( - ( y > this->m_Avg[ i - 1 ] )? Self::PosPeak: Self::NegPeak - ); - this->m_YF.push_back( - ( this->m_I * y ) + - ( ( double( 1 ) - this->m_I ) * this->m_YF[ i - 1 ] ) - ); - } - else - { - this->m_Peaks.push_back( Self::NoPeak ); - this->m_YF.push_back( y ); - - } // fi - - this->m_MeanAndVar.Clear( ); - unsigned long k = 0; - for( unsigned long j = i - this->m_K; j <= i; ++j, ++k ) - this->m_MeanAndVar.AddValue( this->m_YF[ j ] ); - this->m_Avg.push_back( this->m_MeanAndVar.GetMean( ) ); - this->m_STD.push_back( this->m_MeanAndVar.GetDeviation( ) ); - - } // fi - return( this->m_Peaks.back( ) ); -} - -// eof - $RCSfile$ diff --git a/lib/fpa/Common/PeakDetector.h b/lib/fpa/Common/PeakDetector.h deleted file mode 100644 index 8796cc3..0000000 --- a/lib/fpa/Common/PeakDetector.h +++ /dev/null @@ -1,75 +0,0 @@ -// ========================================================================= -// @author Leonardo Florez Valencia -// @email florez-l@javeriana.edu.co -// ========================================================================= -#ifndef __fpa__Common__PeakDetector__h__ -#define __fpa__Common__PeakDetector__h__ - -#include -#include -#include - -namespace fpa -{ - namespace Common - { - /** - */ - /** - * https://stackoverflow.com/questions/22583391/peak-signal-detection-in-realtime-timeseries-data - */ - class FPA_EXPORT PeakDetector - { - public: - typedef PeakDetector Self; - - enum TPeak - { - NoPeak = 0, - PosPeak, - NegPeak - }; - - public: - PeakDetector( ); - virtual ~PeakDetector( ); - - unsigned long GetKernelSize( ) const; - double GetThreshold( ) const; - double GetInfluence( ) const; - - void SetKernelSize( unsigned long k ); - void SetThreshold( double t ); - void SetInfluence( double i ); - - const std::vector< double >& GetXValues( ) const; - const std::vector< double >& GetYValues( ) const; - const std::vector< double >& GetFilteredYValues( ) const; - const std::vector< double >& GetAverages( ) const; - const std::vector< double >& GetDeviations( ) const; - const std::vector< TPeak >& GetPeaks( ) const; - - void Clear( ); - unsigned long GetNumberOfSamples( ) const; - TPeak AddValue( double x, double y ); - - protected: - unsigned long m_K; - double m_T; - double m_I; - - std::vector< double > m_X; - std::vector< double > m_Y; - std::vector< double > m_YF; - std::vector< double > m_Avg; - std::vector< double > m_STD; - std::vector< TPeak > m_Peaks; - fpa::Common::IncrementalMeanAndVariance m_MeanAndVar; - }; - - } // ecapseman - -} // ecapseman - -#endif // __fpa__Common__PeakDetector__h__ -// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Mori.h b/lib/fpa/Filters/Mori.h index 14e8c53..df99fb7 100644 --- a/lib/fpa/Filters/Mori.h +++ b/lib/fpa/Filters/Mori.h @@ -6,10 +6,11 @@ #define __fpa__Filters__Mori__h__ #include -#include #include #include +#include + namespace fpa { namespace Filters @@ -31,7 +32,7 @@ namespace fpa fpaTraitsMacro( typename TTraits ); typedef std::set< TInputValue > TThresholds; - typedef fpa::Common::PeakDetector TPeakDetector; + typedef ivq::ITK::PeakDetector TPeakDetector; typedef TPeakDetector::TPeak TPeak; typedef fpa::Functors::RegionGrow::BinaryThreshold< TInputValue > TPredicate; -- 2.45.1