diff --git a/CMakeLists.txt b/CMakeLists.txt index e1f5817..b54fd75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,304 +1,304 @@ #----------------------------------------------------------------------------- # This is the root RTToolbox CMakeList file. #----------------------------------------------------------------------------- PROJECT(RTToolbox) CMAKE_MINIMUM_REQUIRED(VERSION 3.1) # RTToolbox version number. SET(RTToolbox_VERSION_MAJOR "5") SET(RTToolbox_VERSION_MINOR "0") SET(RTToolbox_VERSION_PATCH "0") # Version string should not include patch level. The major.minor is # enough to distinguish available features of the toolbox. SET(RTToolbox_VERSION_STRING "${RTToolbox_VERSION_MAJOR}.${RTToolbox_VERSION_MINOR}") SET(RTToolbox_FULL_VERSION_STRING "${RTToolbox_VERSION_MAJOR}.${RTToolbox_VERSION_MINOR}.${RTToolbox_VERSION_PATCH}") # default build type SET(CMAKE_BUILD_TYPE Release) MARK_AS_ADVANCED(BUILD_SHARED_LIBS) IF (WIN32) IF (MSVC_VERSION LESS 1600) MESSAGE(FATAL_ERROR "RTToolbox requires at least Visual Studio 2010.") ENDIF(MSVC_VERSION LESS 1600) add_definitions(-D_SCL_SECURE_NO_WARNINGS) ELSE (WIN32) IF (CMAKE_COMPILER_IS_GNUCC) IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 5.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.0) MESSAGE(AUTHOR_WARNING "RTToolbox was only tested with GCC 4.6 and GCC 4.9. You are using GCC " ${CMAKE_CXX_COMPILER_VERSION} ". This compiler version might not work.") ENDIF() ENDIF() ENDIF(WIN32) IF(COMMAND CMAKE_POLICY) # Enable old CMake behaviour when dealing with export_library_dependencies(). # This is necessary to avoid warnings in CMake versions # greater than 3.0 # See http://www.cmake.org/cmake/help/v3.0/policy/CMP0033.html CMAKE_POLICY(SET CMP0033 OLD) - IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 3.2) + IF (${CMAKE_VERSION} VERSION_GREATER 3.2) # See https://cmake.org/cmake/help/v3.3/policy/CMP0062.html CMAKE_POLICY(SET CMP0062 OLD) ENDIF() ENDIF(COMMAND CMAKE_POLICY) #----------------------------------------------------------------------------- # CMake Function(s) and Macro(s) #----------------------------------------------------------------------------- include(cmake/MacroParseArguments.cmake) include(cmake/rttbMacroCreateModuleConf.cmake) include(cmake/rttbMacroCreateModule.cmake) include(cmake/rttbMacroCreateApplication.cmake) include(cmake/rttbMacroCheckModule.cmake) include(cmake/rttbMacroUseModule.cmake) include(cmake/rttbMacroCreateTestModule.cmake) include(cmake/rttbFunctionOrganizeSources.cmake) include(cmake/rttbMacroCreateApplicationTests.cmake) #----------------------------------------------------------------------------- # Basis config RTTB module infrastructure #----------------------------------------------------------------------------- set(RTTB_MODULES_CONF_DIR ${RTToolbox_BINARY_DIR}/modulesConf CACHE INTERNAL "Modules Conf") set(RTTB_MODULES_PACKAGE_DEPENDS_DIR ${RTToolbox_SOURCE_DIR}/cmake/PackageDepends) set(MODULES_PACKAGE_DEPENDS_DIRS ${RTTB_MODULES_PACKAGE_DEPENDS_DIR}) #----------------------------------------------------------------------------- # Testing setup # Configure Dart testing support. This should be done before any # MESSAGE(FATAL_ERROR ...) commands are invoked. #----------------------------------------------------------------------------- SET(CTEST_NEW_FORMAT 1) INCLUDE(CTest) ENABLE_TESTING() IF(BUILD_TESTING) CONFIGURE_FILE(${RTToolbox_SOURCE_DIR}/cmake/RemoveTemporaryFiles.cmake.in ${RTToolbox_BINARY_DIR}/cmake/RemoveTemporaryFiles.cmake @ONLY IMMEDIATE) CONFIGURE_FILE(${RTToolbox_SOURCE_DIR}/cmake/rttbSampleBuildTest.cmake.in ${RTToolbox_BINARY_DIR}/cmake/rttbSampleBuildTest.cmake @ONLY) CONFIGURE_FILE(${RTToolbox_SOURCE_DIR}/cmake/CTestCustom.ctest.in ${RTToolbox_BINARY_DIR}/cmake/CTestCustom.ctest @ONLY) FILE(WRITE ${RTToolbox_BINARY_DIR}/CTestCustom.cmake "INCLUDE(\"${RTToolbox_BINARY_DIR}/cmake/CTestCustom.ctest\")\n") SET(BUILDNAME "${BUILDNAME}" CACHE STRING "Name of build on the dashboard") MARK_AS_ADVANCED(BUILDNAME) ENDIF(BUILD_TESTING) #----------------------------------------------------------------------------- # Output directories. #----------------------------------------------------------------------------- IF(NOT LIBRARY_OUTPUT_PATH) SET (LIBRARY_OUTPUT_PATH ${RTToolbox_BINARY_DIR}/bin CACHE PATH "Single output directory for building all libraries.") ENDIF(NOT LIBRARY_OUTPUT_PATH) IF(NOT EXECUTABLE_OUTPUT_PATH) SET (EXECUTABLE_OUTPUT_PATH ${RTToolbox_BINARY_DIR}/bin CACHE PATH "Single output directory for building all executables.") ENDIF(NOT EXECUTABLE_OUTPUT_PATH) MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH) MARK_AS_ADVANCED(LIBRARY_OUTPUT_PATH EXECUTABLE_OUTPUT_PATH) SET(RTToolbox_LIBRARY_PATH "${LIBRARY_OUTPUT_PATH}") SET(RTToolbox_EXECUTABLE_PATH "${EXECUTABLE_OUTPUT_PATH}") #----------------------------------------------------------------------------- # Find Doxygen. #----------------------------------------------------------------------------- FIND_PROGRAM(DOXYGEN_EXECUTABLE "doxygen") #----------------------------------------------------------------------------- # Installation vars. # RTToolbox_INSTALL_BIN_DIR - binary dir (executables) # RTToolbox_INSTALL_LIB_DIR - library dir (libs) # RTToolbox_INSTALL_INCLUDE_DIR - include dir (headers) # RTToolbox_INSTALL_NO_DEVELOPMENT - do not install development files # RTToolbox_INSTALL_NO_RUNTIME - do not install runtime files # RTToolbox_INSTALL_NO_DOCUMENTATION - do not install documentation files # Remark: needs directory are stored with no leading slash (CMake 2.4 and newer) #----------------------------------------------------------------------------- IF(NOT RTTOOLBOX_INSTALL_BIN_DIR) SET(RTTOOLBOX_INSTALL_BIN_DIR "bin") ENDIF(NOT RTTOOLBOX_INSTALL_BIN_DIR) IF(NOT RTTOOLBOX_INSTALL_LIB_DIR) SET(RTTOOLBOX_INSTALL_LIB_DIR "lib") ENDIF(NOT RTTOOLBOX_INSTALL_LIB_DIR) IF(NOT RTTOOLBOX_INSTALL_PACKAGE_DIR) SET(RTTOOLBOX_INSTALL_PACKAGE_DIR "lib") ENDIF(NOT RTTOOLBOX_INSTALL_PACKAGE_DIR) IF(NOT RTTOOLBOX_INSTALL_INCLUDE_DIR) SET(RTTOOLBOX_INSTALL_INCLUDE_DIR "include") ENDIF(NOT RTTOOLBOX_INSTALL_INCLUDE_DIR) IF(NOT RTTOOLBOX_INSTALL_NO_DEVELOPMENT) SET(RTTOOLBOX_INSTALL_NO_DEVELOPMENT 0) ENDIF(NOT RTTOOLBOX_INSTALL_NO_DEVELOPMENT) IF(NOT RTTOOLBOX_INSTALL_NO_RUNTIME) SET(RTTOOLBOX_INSTALL_NO_RUNTIME 0) ENDIF(NOT RTTOOLBOX_INSTALL_NO_RUNTIME) IF(NOT RTTOOLBOX_INSTALL_NO_DOCUMENTATION) SET(RTTOOLBOX_INSTALL_NO_DOCUMENTATION 0) ENDIF(NOT RTTOOLBOX_INSTALL_NO_DOCUMENTATION) SET(RTTOOLBOX_INSTALL_NO_LIBRARIES) IF(RTTOOLBOX_BUILD_SHARED_LIBS) IF(RTTOOLBOX_INSTALL_NO_RUNTIME AND RTTOOLBOX_INSTALL_NO_DEVELOPMENT) SET(RTTOOLBOX_INSTALL_NO_LIBRARIES 1) ENDIF(RTTOOLBOX_INSTALL_NO_RUNTIME AND RTTOOLBOX_INSTALL_NO_DEVELOPMENT) ELSE(RTTOOLBOX_BUILD_SHARED_LIBS) IF(RTTOOLBOX_INSTALL_NO_DEVELOPMENT) SET(RTTOOLBOX_INSTALL_NO_LIBRARIES 1) ENDIF(RTTOOLBOX_INSTALL_NO_DEVELOPMENT) ENDIF(RTTOOLBOX_BUILD_SHARED_LIBS) # set RTToolbox_DIR so it can be used by subprojects SET(RTToolbox_DIR "${CMAKE_BINARY_DIR}" CACHE INTERNAL "RTToolbox dir to be used by subprojects") #----------------------------------------------------------------------------- # DCMTK MT-Flag treat #----------------------------------------------------------------------------- option(RTTB_DCMTK_COMPLIANCE_ENFORCE_MT "This enforces the whole RTToolbox to be compiled with /MT,/MTd to be compliant with DCMTK" OFF) string(FIND ${CMAKE_GENERATOR} "Visual Studio" RTTB_VS_USED) if(RTTB_DCMTK_COMPLIANCE_ENFORCE_MT AND RTTB_VS_USED EQUAL 0) message(STATUS "Enforce DCMTK compliance: /MT and /MTd flags are used") string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG}) message(STATUS "CMAKE_C_FLAGS_DEBUG set to: ${CMAKE_C_FLAGS_DEBUG}") string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE}) message(STATUS "CMAKE_C_FLAGS_RELEASE set to: ${CMAKE_C_FLAGS_RELEASE}") string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_MINSIZEREL ${CMAKE_C_FLAGS_MINSIZEREL}) message(STATUS "CMAKE_C_FLAGS_MINSIZEREL set to: ${CMAKE_C_FLAGS_MINSIZEREL}") string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELWITHDEBINFO}) message(STATUS "CMAKE_C_FLAGS_RELWITHDEBINFO set to: ${CMAKE_C_FLAGS_RELWITHDEBINFO}") string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) message(STATUS "CMAKE_CXX_FLAGS_DEBUG set to: ${CMAKE_CXX_FLAGS_DEBUG}") string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE}) message(STATUS "CMAKE_CXX_FLAGS_RELEASE set to: ${CMAKE_CXX_FLAGS_RELEASE}") string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS_MINSIZEREL}) message(STATUS "CMAKE_CXX_FLAGS_MINSIZEREL set to: ${CMAKE_CXX_FLAGS_MINSIZEREL}") string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}) message(STATUS "CMAKE_CXX_FLAGS_RELWITHDEBINFO set to: ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") endif() #----------------------------------------------------------------------------- # Advanced RTToolbox configuration #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # RTToolbox build configuration options. IF (WIN32) OPTION(BUILD_SHARED_LIBS "Build RTToolbox with shared libraries." OFF) ELSE (WIN32) OPTION(BUILD_SHARED_LIBS "Build RTToolbox with shared libraries." ON) ENDIF (WIN32) OPTION (RTTB_VIRTUOS_SUPPORT "Build RTToolbox with Virtuos support." OFF) IF (RTTB_VIRTUOS_SUPPORT) SET(RTToolbox_VIRTUOS_SUPPORT "1") ELSE() SET(RTToolbox_VIRTUOS_SUPPORT "0") ENDIF() IF(NOT BUILD_SHARED_LIBS) IF(UNIX) MESSAGE(FATAL_ERROR "RTToolbox currently does not support a static build on unix like systems. We are working on that...") ENDIF(UNIX) ENDIF(NOT BUILD_SHARED_LIBS) SET(RTTB_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS}) IF(NOT RTToolbox_NO_LIBRARY_VERSION) # This setting of SOVERSION assumes that any API change # will increment either the minor or major version number of RTToolbox. SET(RTToolbox_LIBRARY_PROPERTIES VERSION "${RTToolbox_VERSION_MAJOR}.${RTToolbox_VERSION_MINOR}.${RTToolbox_VERSION_PATCH}" SOVERSION "${RTToolbox_VERSION_MAJOR}.${RTToolbox_VERSION_MINOR}" ) ENDIF(NOT RTToolbox_NO_LIBRARY_VERSION) #----------------------------------------------------------------------------- # Configure files with settings for use by the build. # #----------------------------------------------------------------------------- CONFIGURE_FILE(${RTToolbox_SOURCE_DIR}/RTToolboxConfigure.h.in ${RTToolbox_BINARY_DIR}/RTToolboxConfigure.h) IF(NOT RTTOOLBOX_INSTALL_NO_DEVELOPMENT) INSTALL(FILES ${RTToolbox_BINARY_DIR}/RTToolboxConfigure.h DESTINATION ${RTTOOLBOX_INSTALL_INCLUDE_DIR} COMPONENT Development) ENDIF(NOT RTTOOLBOX_INSTALL_NO_DEVELOPMENT) #----------------------------------------------------------------------------- # The entire RTToolbox tree should use the same include path #----------------------------------------------------------------------------- #Default include dir. Others dirs will be defined by activated subprojects INCLUDE_DIRECTORIES(${RTToolbox_BINARY_DIR}) LINK_DIRECTORIES(${LIBARY_OUTPUT_PATH}) #Prepare the correct target information export by the subprojects SET(RTToolbox_TARGETS_FILE "${RTToolbox_BINARY_DIR}/RTToolboxTargets.cmake") FILE(WRITE ${RTToolbox_TARGETS_FILE} "# Generated by CMake, do not edit!") #----------------------------------------------------------------------------- # Dispatch the build into the proper subdirectories. #----------------------------------------------------------------------------- OPTION(BUILD_Apps "Determine if the CLI applications will be generated." ON) MESSAGE (STATUS "generating Project RTToolbox") ADD_SUBDIRECTORY (code) IF (BUILD_Apps) ADD_SUBDIRECTORY (apps) ENDIF() IF (BUILD_TESTING) ADD_SUBDIRECTORY (testing) ENDIF (BUILD_TESTING) ADD_SUBDIRECTORY (documentation) #----------------------------------------------------------------------------- # Help other projects use RTToolbox. #----------------------------------------------------------------------------- EXPORT(PACKAGE RTToolbox) # Copy the UseRTToolbox.cmake file to the binary tree for backward compatability. CONFIGURE_FILE(${RTToolbox_SOURCE_DIR}/UseRTToolbox.cmake.in ${RTToolbox_BINARY_DIR}/UseRTToolbox.cmake COPYONLY IMMEDIATE) # Save library dependencies. EXPORT_LIBRARY_DEPENDENCIES(${RTToolbox_BINARY_DIR}/RTToolboxLibraryDepends.cmake) # Create the RTToolboxConfig.cmake file containing the RTToolbox configuration. INCLUDE (${RTToolbox_SOURCE_DIR}/rttbGenerateRTToolboxConfig.cmake) IF(NOT RTToolbox_INSTALL_NO_DEVELOPMENT) INSTALL(FILES ${RTToolbox_BINARY_DIR}/RTToolboxConfig.cmake ${RTToolbox_BINARY_DIR}/RTToolboxTargets.cmake ${RTToolbox_BINARY_DIR}/RTToolboxLibraryDepends.cmake ${RTToolbox_BINARY_DIR}/UseRTToolbox.cmake DESTINATION ${RTTOOLBOX_INSTALL_PACKAGE_DIR} COMPONENT Development ) ENDIF(NOT RTToolbox_INSTALL_NO_DEVELOPMENT) diff --git a/apps/BioModelCalc/CMakeLists.txt b/apps/BioModelCalc/CMakeLists.txt index a89985a..eccb779 100644 --- a/apps/BioModelCalc/CMakeLists.txt +++ b/apps/BioModelCalc/CMakeLists.txt @@ -1,8 +1,8 @@ MESSAGE (STATUS "generating demo app: BioModelCalc - calculating the radiobiological effect based on dose") SET(RTTB_Boost_ADDITIONAL_COMPONENT program_options) RTTB_CREATE_APPLICATION(BioModelCalc DEPENDS RTTBCore RTTBITKIO RTTBDicomIO RTTBHelaxIO RTTBModels PACKAGE_DEPENDS ArgumentParsingLib BoostBinaries) IF (NOT WIN32) - #CMake 3.1 provides target_compile_features(RTTB_Interpolation cxx_auto_type cxx_nullptr cxx_override) to automatically add required compiler flags - set(CMAKE_CXX_FLAGS "-std=c++11 -fpermissive") + target_compile_features(BioModelCalc PRIVATE cxx_auto_type cxx_nullptr cxx_override) + set(CMAKE_CXX_FLAGS "-fpermissive") ENDIF() diff --git a/apps/BioModelCalc4V/CMakeLists.txt b/apps/BioModelCalc4V/CMakeLists.txt index e90acb1..f9d2660 100644 --- a/apps/BioModelCalc4V/CMakeLists.txt +++ b/apps/BioModelCalc4V/CMakeLists.txt @@ -1,7 +1,7 @@ MESSAGE (STATUS "generating demo app: BioModelCalc4V - calculating the radiobiological effect based on dose") SET(RTTB_Boost_ADDITIONAL_COMPONENT program_options) RTTB_CREATE_APPLICATION(BioModelCalc4V DEPENDS RTTBCore RTTBITKIO RTTBVirtuosIO RTTBDicomIO RTTBHelaxIO RTTBModels PACKAGE_DEPENDS ArgumentParsingLib BoostBinaries) IF (NOT WIN32) - #CMake 3.1 provides target_compile_features(RTTB_Interpolation cxx_auto_type cxx_nullptr cxx_override) to automatically add required compiler flags - set(CMAKE_CXX_FLAGS "-std=c++11 -fpermissive") + target_compile_features(BioModelCalc4V PRIVATE cxx_auto_type cxx_nullptr cxx_override) + set(CMAKE_CXX_FLAGS "-fpermissive") ENDIF() diff --git a/apps/DoseAcc/CMakeLists.txt b/apps/DoseAcc/CMakeLists.txt index 52b17ad..da7191d 100644 --- a/apps/DoseAcc/CMakeLists.txt +++ b/apps/DoseAcc/CMakeLists.txt @@ -1,3 +1,8 @@ MESSAGE (STATUS "generating demo app: DoseAcc - simple dose accumulation tool example") +SET(RTTB_Boost_ADDITIONAL_COMPONENT program_options) +RTTB_CREATE_APPLICATION(DoseAcc DEPENDS RTTBCore RTTBAlgorithms RTTBInterpolation RTTBInterpolationMatchPointTransformation RTTBITKIO RTTBDicomIO RTTBHelaxIO PACKAGE_DEPENDS ArgumentParsingLib MatchPoint ITK BoostBinaries) -RTTB_CREATE_APPLICATION(DoseAcc DEPENDS RTTBCore RTTBAlgorithms RTTBInterpolation RTTBInterpolationMatchPointTransformation RTTBITKIO RTTBDicomIO RTTBHelaxIO PACKAGE_DEPENDS ArgumentParsingLib MatchPoint ITK) \ No newline at end of file +IF (NOT WIN32) + target_compile_features(DoseAcc PRIVATE cxx_auto_type cxx_nullptr cxx_override) + set(CMAKE_CXX_FLAGS "-fpermissive") +ENDIF() diff --git a/apps/DoseAcc4V/CMakeLists.txt b/apps/DoseAcc4V/CMakeLists.txt index c1074fb..dead576 100644 --- a/apps/DoseAcc4V/CMakeLists.txt +++ b/apps/DoseAcc4V/CMakeLists.txt @@ -1,7 +1,7 @@ MESSAGE (STATUS "generating app: DoseAcc4V - simple dose accumulation tool with Virtuos") SET(RTTB_Boost_ADDITIONAL_COMPONENT program_options) RTTB_CREATE_APPLICATION(DoseAcc4V DEPENDS RTTBCore RTTBAlgorithms RTTBInterpolation RTTBInterpolationMatchPointTransformation RTTBITKIO RTTBVirtuosIO RTTBDicomIO RTTBHelaxIO PACKAGE_DEPENDS ArgumentParsingLib MatchPoint ITK) IF (NOT WIN32) - #CMake 3.1 provides target_compile_features(RTTB_Interpolation cxx_auto_type cxx_nullptr cxx_override) to automatically add required compiler flags - set(CMAKE_CXX_FLAGS "-std=c++11 -fpermissive") + target_compile_features(BioModelCalc4V PRIVATE cxx_auto_type cxx_nullptr cxx_override) + set(CMAKE_CXX_FLAGS "-fpermissive") ENDIF() diff --git a/apps/DoseMap/CMakeLists.txt b/apps/DoseMap/CMakeLists.txt index d330313..dd13079 100644 --- a/apps/DoseMap/CMakeLists.txt +++ b/apps/DoseMap/CMakeLists.txt @@ -1,3 +1,8 @@ MESSAGE (STATUS "generating demo app: DoseMap - simple dose mapping tool example") +SET(RTTB_Boost_ADDITIONAL_COMPONENT program_options) +RTTB_CREATE_APPLICATION(DoseMap DEPENDS RTTBCore RTTBAlgorithms RTTBInterpolation RTTBInterpolationMatchPointTransformation RTTBITKIO RTTBVirtuosIO RTTBDicomIO RTTBHelaxIO PACKAGE_DEPENDS MatchPoint ITK ArgumentParsingLib BoostBinaries) -RTTB_CREATE_APPLICATION(DoseMap DEPENDS RTTBCore RTTBAlgorithms RTTBInterpolation RTTBInterpolationMatchPointTransformation RTTBITKIO RTTBVirtuosIO RTTBDicomIO RTTBHelaxIO PACKAGE_DEPENDS MatchPoint ITK ArgumentParsingLib BoostBinaries) \ No newline at end of file +IF (NOT WIN32) + target_compile_features(DoseMap PRIVATE cxx_auto_type cxx_nullptr cxx_override) + set(CMAKE_CXX_FLAGS "-fpermissive") +ENDIF() diff --git a/apps/DoseTool/CMakeLists.txt b/apps/DoseTool/CMakeLists.txt index da4b4d0..9e706f0 100644 --- a/apps/DoseTool/CMakeLists.txt +++ b/apps/DoseTool/CMakeLists.txt @@ -1,8 +1,8 @@ MESSAGE (STATUS "generating demo app: DoseTool - calculating dose statistics of a structure") SET(RTTB_Boost_ADDITIONAL_COMPONENT program_options) RTTB_CREATE_APPLICATION(DoseTool DEPENDS RTTBCore RTTBITKIO RTTBDicomIO RTTBHelaxIO RTTBMasks RTTBMasks RTTBBoostMask RTTBOtherIO RTTBAlgorithms PACKAGE_DEPENDS ArgumentParsingLib BoostBinaries) IF (NOT WIN32) - #CMake 3.1 provides target_compile_features(RTTB_Interpolation cxx_auto_type cxx_nullptr cxx_override) to automatically add required compiler flags - set(CMAKE_CXX_FLAGS "-std=c++11 -fpermissive") + target_compile_features(DoseTool PRIVATE cxx_auto_type cxx_nullptr cxx_override) + set(CMAKE_CXX_FLAGS "-fpermissive") ENDIF() diff --git a/apps/DoseTool4V/CMakeLists.txt b/apps/DoseTool4V/CMakeLists.txt index 3daddfd..02a8aae 100644 --- a/apps/DoseTool4V/CMakeLists.txt +++ b/apps/DoseTool4V/CMakeLists.txt @@ -1,7 +1,7 @@ MESSAGE (STATUS "generating demo app: DoseTool4V - calculating dose statistics of a structure") SET(RTTB_Boost_ADDITIONAL_COMPONENT program_options) RTTB_CREATE_APPLICATION(DoseTool4V DEPENDS RTTBCore RTTBITKIO RTTBVirtuosIO RTTBDicomIO RTTBHelaxIO RTTBMasks RTTBMasks RTTBBoostMask RTTBOtherIO RTTBAlgorithms PACKAGE_DEPENDS ArgumentParsingLib BoostBinaries) IF (NOT WIN32) - #CMake 3.1 provides target_compile_features(RTTB_Interpolation cxx_auto_type cxx_nullptr cxx_override) to automatically add required compiler flags - set(CMAKE_CXX_FLAGS "-std=c++11 -fpermissive") + target_compile_features(DoseTool4V PRIVATE cxx_auto_type cxx_nullptr cxx_override) + set(CMAKE_CXX_FLAGS "-fpermissive") ENDIF() diff --git a/apps/VoxelizerTool/CMakeLists.txt b/apps/VoxelizerTool/CMakeLists.txt index 844787b..9cc9934 100644 --- a/apps/VoxelizerTool/CMakeLists.txt +++ b/apps/VoxelizerTool/CMakeLists.txt @@ -1,7 +1,7 @@ MESSAGE (STATUS "generating app: VoxelizerTool - writing files of voxelized structures") - +SET(RTTB_Boost_ADDITIONAL_COMPONENT program_options) RTTB_CREATE_APPLICATION(VoxelizerTool DEPENDS RTTBITKIO RTTBBoostMask RTTBDicomIO RTTBMasks RTTBCore PACKAGE_DEPENDS ArgumentParsingLib ITK BoostBinaries) IF (NOT WIN32) - #CMake 3.1 provides target_compile_features(RTTB_Interpolation cxx_auto_type cxx_nullptr cxx_override) to automatically add required compiler flags - set(CMAKE_CXX_FLAGS "-std=c++11 -fpermissive") + target_compile_features(VoxelizerTool PRIVATE cxx_auto_type cxx_nullptr cxx_override) + set(CMAKE_CXX_FLAGS "-fpermissive") ENDIF() diff --git a/cmake/PackageDepends/RTTB_BoostBinaries_Config.cmake b/cmake/PackageDepends/RTTB_BoostBinaries_Config.cmake index 239183e..3d97238 100644 --- a/cmake/PackageDepends/RTTB_BoostBinaries_Config.cmake +++ b/cmake/PackageDepends/RTTB_BoostBinaries_Config.cmake @@ -1,34 +1,34 @@ IF(NOT BoostBinaries_FOUND) IF(DEFINED Boost_INCLUDE_DIR) IF(NOT IS_ABSOLUTE ${Boost_INCLUDE_DIR}) SET(Boost_INCLUDE_DIR "${RTToolbox_BINARY_DIR}/${Boost_INCLUDE_DIR}") ENDIF(NOT IS_ABSOLUTE ${Boost_INCLUDE_DIR}) ENDIF(DEFINED Boost_INCLUDE_DIR) IF(NOT DEFINED RTTB_USE_MITK_BOOST) OPTION(RTTB_USE_MITK_BOOST "RTTB should use a boost which is available in the MITK superbuild external projects structure." OFF) MARK_AS_ADVANCED(RTTB_USE_MITK_BOOST) ENDIF(NOT DEFINED RTTB_USE_MITK_BOOST) IF(BUILD_SHARED_LIBS OR RTTB_USE_MITK_BOOST) SET(Boost_USE_STATIC_LIBS OFF) ADD_DEFINITIONS(-DBOOST_ALL_DYN_LINK) ELSE(BUILD_SHARED_LIBS OR RTTB_USE_MITK_BOOST) SET(Boost_USE_STATIC_LIBS ON) ENDIF(BUILD_SHARED_LIBS OR RTTB_USE_MITK_BOOST) SET(BOOST_MIN_VERSION "1.56.0") - FIND_PACKAGE(Boost ${BOOST_MIN_VERSION} REQUIRED COMPONENTS filesystem regex system ${RTTB_Boost_ADDITIONAL_COMPONENT}) + FIND_PACKAGE(Boost ${BOOST_MIN_VERSION} REQUIRED COMPONENTS filesystem regex system thread ${RTTB_Boost_ADDITIONAL_COMPONENT}) LIST(APPEND ALL_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIRS}) LIST(APPEND ALL_LIBRARIES ${Boost_LIBRARIES}) link_directories(${Boost_LIBRARY_DIRS}) MARK_AS_ADVANCED(CLEAR Boost_INCLUDE_DIR) SET(BoostBinaries_FOUND TRUE) ENDIF(NOT BoostBinaries_FOUND) diff --git a/code/algorithms/rttbDoseStatisticsCalculator.cpp b/code/algorithms/rttbDoseStatisticsCalculator.cpp index 2e70a5b..d78273f 100644 --- a/code/algorithms/rttbDoseStatisticsCalculator.cpp +++ b/code/algorithms/rttbDoseStatisticsCalculator.cpp @@ -1,675 +1,685 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include "rttbDoseStatisticsCalculator.h" #include #include #include +#include #include "rttbNullPointerException.h" #include "rttbInvalidDoseException.h" #include "rttbInvalidParameterException.h" #include namespace rttb { namespace algorithms { DoseStatisticsCalculator::DoseStatisticsCalculator(DoseIteratorPointer aDoseIterator) { if (aDoseIterator == NULL) { throw core::NullPointerException("DoseIterator must not be NULL"); } else { _doseIterator = aDoseIterator; } _simpleDoseStatisticsCalculated = false; _multiThreading = false; + _mutex = ::boost::make_shared<::boost::shared_mutex>(); } DoseStatisticsCalculator::~DoseStatisticsCalculator() { } DoseStatisticsCalculator::DoseIteratorPointer DoseStatisticsCalculator::getDoseIterator() const { return _doseIterator; } DoseStatisticsCalculator::DoseStatisticsPointer DoseStatisticsCalculator::calculateDoseStatistics( bool computeComplexMeasures, unsigned int maxNumberMinimaPositions, unsigned int maxNumberMaximaPositions) { if (!_doseIterator) { throw core::NullPointerException("_doseIterator must not be NULL!"); } //"simple" dose statistics are mandatory calculateSimpleDoseStatistics(maxNumberMinimaPositions, maxNumberMaximaPositions); if (computeComplexMeasures) { //more complex dose statistics are optional with default maximum dose and default relative x values calculateComplexDoseStatistics(_statistics->getMaximum(), std::vector(), std::vector()); } return _statistics; } DoseStatisticsCalculator::DoseStatisticsPointer DoseStatisticsCalculator::calculateDoseStatistics( DoseTypeGy referenceDose, unsigned int maxNumberMinimaPositions, unsigned int maxNumberMaximaPositions) { if (!_doseIterator) { throw core::NullPointerException("_doseIterator must not be NULL!"); } if (referenceDose <= 0) { throw rttb::core::InvalidParameterException("Reference dose must be > 0 !"); } //simple dose statistics calculateSimpleDoseStatistics(maxNumberMinimaPositions, maxNumberMaximaPositions); //more complex dose statistics with given reference dose and default x values calculateComplexDoseStatistics(referenceDose, std::vector(), std::vector()); return _statistics; } DoseStatisticsCalculator::DoseStatisticsPointer DoseStatisticsCalculator::calculateDoseStatistics( const std::vector& precomputeDoseValues, const std::vector& precomputeVolumeValues, DoseTypeGy referenceDose, unsigned int maxNumberMinimaPositions, unsigned int maxNumberMaximaPositions) { if (!_doseIterator) { throw core::NullPointerException("_doseIterator must not be NULL!"); } //"simple" dose statistics calculateSimpleDoseStatistics(maxNumberMinimaPositions, maxNumberMaximaPositions); if (referenceDose <= 0) { //more complex dose statistics with default maximum dose and relative x values calculateComplexDoseStatistics(_statistics->getMaximum(), precomputeDoseValues, precomputeVolumeValues); } else { //more complex dose statistics with given reference dose and relative x values calculateComplexDoseStatistics(referenceDose, precomputeDoseValues, precomputeVolumeValues); } return _statistics; } void DoseStatisticsCalculator::calculateSimpleDoseStatistics(unsigned int maxNumberMinimaPositions, unsigned int maxNumberMaximaPositions) { _doseVector.clear(); _voxelProportionVector.clear(); std::multimap doseValueVSIndexMap; std::vector voxelProportionVectorTemp; DoseStatisticType maximumDose = 0; DoseStatisticType minimumDose = std::numeric_limits::max(); DoseStatisticType meanDose; DoseStatisticType stdDeviationDose; DoseTypeGy sum = 0; VolumeType numVoxels = 0.0; DoseTypeGy squareSum = 0; VolumeType volume = 0; _doseIterator->reset(); int i = 0; DoseTypeGy doseValue = 0; while (_doseIterator->isPositionValid()) { doseValue = _doseIterator->getCurrentDoseValue(); if (i == 0) { minimumDose = doseValue; volume = _doseIterator->getCurrentVoxelVolume(); } rttb::FractionType voxelProportion = _doseIterator->getCurrentRelevantVolumeFraction(); sum += doseValue * voxelProportion; numVoxels += voxelProportion; squareSum += doseValue * doseValue * voxelProportion; if (doseValue > maximumDose) { maximumDose = doseValue; } else if (doseValue < minimumDose) { minimumDose = doseValue; } voxelProportionVectorTemp.push_back(voxelProportion); doseValueVSIndexMap.insert(std::pair(doseValue, i)); i++; _doseIterator->next(); } if (numVoxels != 0) { meanDose = sum / numVoxels; //standard deviation is defined only for n>=2 if (numVoxels >= 2) { //uncorrected variance is calculated DoseStatisticType varianceDose = (squareSum / numVoxels - meanDose * meanDose); if (varianceDose < errorConstant) { stdDeviationDose = 0; } else { stdDeviationDose = pow(varianceDose, 0.5); } } else { stdDeviationDose = 0; } } //sort dose values and corresponding volume fractions in member variables for (auto it = doseValueVSIndexMap.begin(); it != doseValueVSIndexMap.end(); ++it) { _doseVector.push_back((float)(*it).first); _voxelProportionVector.push_back(voxelProportionVectorTemp.at((*it).second)); } volume *= numVoxels; _statistics = boost::make_shared(minimumDose, maximumDose, meanDose, stdDeviationDose, numVoxels, volume); _simpleDoseStatisticsCalculated = true; ResultListPointer minimumVoxelPositions = computeMinimumPositions(maxNumberMinimaPositions); ResultListPointer maximumVoxelPositions = computeMaximumPositions(maxNumberMaximaPositions); _statistics->setMinimumVoxelPositions(minimumVoxelPositions); _statistics->setMaximumVoxelPositions(maximumVoxelPositions); } void DoseStatisticsCalculator::calculateComplexDoseStatistics(DoseTypeGy referenceDose, const std::vector& precomputeDoseValues, const std::vector& precomputeVolumeValues) { if (!_simpleDoseStatisticsCalculated) { throw core::InvalidDoseException("simple DoseStatistics have to be computed in order to call calculateComplexDoseStatistics()"); } std::vector precomputeDoseValuesNonConst = precomputeDoseValues; std::vector precomputeVolumeValuesNonConst = precomputeVolumeValues; //set default values if (precomputeDoseValues.empty()) { std::vector defaultPrecomputeDoseValues = boost::assign::list_of(0.02)(0.05)(0.1)(0.9)( 0.95)(0.98); precomputeDoseValuesNonConst = defaultPrecomputeDoseValues; } if (precomputeVolumeValues.empty()) { std::vector defaultPrecomputeVolumeValues = boost::assign::list_of(0.02)(0.05)(0.1)(0.9)( 0.95)(0.98); precomputeVolumeValuesNonConst = defaultPrecomputeVolumeValues; } DoseToVolumeFunctionType Vx = computeDoseToVolumeFunctionMulti(referenceDose, precomputeDoseValuesNonConst, DoseStatistics::Vx); VolumeToDoseFunctionType Dx = computeVolumeToDoseFunctionMulti(precomputeVolumeValuesNonConst, DoseStatistics::Dx); VolumeToDoseFunctionType MOHx = computeVolumeToDoseFunctionMulti(precomputeVolumeValuesNonConst, DoseStatistics::MOHx); VolumeToDoseFunctionType MOCx = computeVolumeToDoseFunctionMulti(precomputeVolumeValuesNonConst, DoseStatistics::MOCx); VolumeToDoseFunctionType MaxOHx = computeVolumeToDoseFunctionMulti(precomputeVolumeValuesNonConst, DoseStatistics::MaxOHx); VolumeToDoseFunctionType MinOCx = computeVolumeToDoseFunctionMulti(precomputeVolumeValuesNonConst, DoseStatistics::MinOCx); _statistics->setVx(Vx); _statistics->setDx(Dx); _statistics->setMOHx(MOHx); _statistics->setMOCx(MOCx); _statistics->setMaxOHx(MaxOHx); _statistics->setMinOCx(MinOCx); _statistics->setReferenceDose(referenceDose); } DoseStatisticsCalculator::ResultListPointer DoseStatisticsCalculator::computeMaximumPositions( unsigned int maxNumberMaxima) const { if (!_simpleDoseStatisticsCalculated) { throw core::InvalidDoseException("simple DoseStatistics have to be computed in order to call computeMaximumPositions()"); } ResultListPointer maxVoxelVector = boost::make_shared > >(); unsigned int count = 0; this->_doseIterator->reset(); DoseTypeGy doseValue = 0; while (_doseIterator->isPositionValid() && count < maxNumberMaxima) { doseValue = _doseIterator->getCurrentDoseValue(); if (doseValue == _statistics->getMaximum()) { VoxelGridID currentID = _doseIterator->getCurrentVoxelGridID(); std::pair voxel(doseValue, currentID); maxVoxelVector->push_back(voxel); count++; } _doseIterator->next(); } return maxVoxelVector; } DoseStatisticsCalculator::ResultListPointer DoseStatisticsCalculator::computeMinimumPositions( unsigned int maxNumberMinima) const { if (!_simpleDoseStatisticsCalculated) { throw core::InvalidDoseException("simple DoseStatistics have to be computed in order to call computeMinimumPositions()"); } ResultListPointer minVoxelVector = boost::make_shared > >(); /*! @todo: Architecture Annotation: Finding the positions for the minimum only once reduces computation time, but will require sensible use by the programmers. To be save the output vector minVoxelVector will be always cleared here to garantee that no false values are presented. This change may be revoced to increase computation speed later on (only compute if(minVoxelVector->size()==0)). */ unsigned int count = 0; this->_doseIterator->reset(); DoseTypeGy doseValue = 0; while (_doseIterator->isPositionValid() && count < maxNumberMinima) { doseValue = _doseIterator->getCurrentDoseValue(); if (doseValue == _statistics->getMinimum()) { VoxelGridID currentID = _doseIterator->getCurrentVoxelGridID(); std::pair voxel(doseValue, currentID); minVoxelVector->push_back(voxel); count++; } _doseIterator->next(); } return minVoxelVector; } VolumeType DoseStatisticsCalculator::computeVx(DoseTypeGy xDoseAbsolute) const { rttb::FractionType count = 0; _doseIterator->reset(); DoseTypeGy currentDose = 0; while (_doseIterator->isPositionValid()) { currentDose = _doseIterator->getCurrentDoseValue(); if (currentDose >= xDoseAbsolute) { count += _doseIterator->getCurrentRelevantVolumeFraction(); } _doseIterator->next(); } return count * this->_doseIterator->getCurrentVoxelVolume(); } DoseTypeGy DoseStatisticsCalculator::computeDx(VolumeType xVolumeAbsolute) const { double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); DoseTypeGy resultDose = 0; double countVoxels = 0; int i = _doseVector.size() - 1; for (; i >= 0; i--) { countVoxels += _voxelProportionVector.at(i); if (countVoxels >= noOfVoxel) { break; } } if (i >= 0) { resultDose = _doseVector.at(i); } else { resultDose = _statistics->getMinimum(); } return resultDose; } DoseTypeGy DoseStatisticsCalculator::computeMOHx(VolumeType xVolumeAbsolute) const { double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); if (noOfVoxel == 0) { return 0; } else { double countVoxels = 0; double sum = 0; for (size_t i = _doseVector.size() - 1; i >= 0; i--) { double voxelProportion = _voxelProportionVector.at(i); countVoxels += voxelProportion; sum += _doseVector.at(i) * voxelProportion; if (countVoxels >= noOfVoxel) { break; } } return (DoseTypeGy)(sum / noOfVoxel); } } DoseTypeGy DoseStatisticsCalculator::computeMOCx(DoseTypeGy xVolumeAbsolute) const { double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); if (noOfVoxel == 0) { return 0; } else { double countVoxels = 0; double sum = 0; std::vector::const_iterator it = _doseVector.begin(); std::vector::const_iterator itD = _voxelProportionVector.begin(); for (; it != _doseVector.end(); ++it, ++itD) { double voxelProportion = *itD; countVoxels += voxelProportion; sum += (*it) * voxelProportion; if (countVoxels >= noOfVoxel) { break; } } return (DoseTypeGy)(sum / noOfVoxel); } } DoseTypeGy DoseStatisticsCalculator::computeMaxOHx(DoseTypeGy xVolumeAbsolute) const { double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); DoseTypeGy resultDose = 0; double countVoxels = 0; int i = _doseVector.size() - 1; for (; i >= 0; i--) { countVoxels += _voxelProportionVector.at(i); if (countVoxels >= noOfVoxel) { break; } } if (i - 1 >= 0) { resultDose = _doseVector.at(i - 1); } return resultDose; } DoseTypeGy DoseStatisticsCalculator::computeMinOCx(DoseTypeGy xVolumeAbsolute) const { double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); DoseTypeGy resultDose = 0; double countVoxels = 0; std::vector::const_iterator it = _doseVector.begin(); std::vector::const_iterator itD = _voxelProportionVector.begin(); for (; itD != _voxelProportionVector.end(); ++itD, ++it) { countVoxels += *itD; if (countVoxels >= noOfVoxel) { break; } } if (it != _doseVector.end()) { ++it; if (it != _doseVector.end()) { resultDose = *it; } else { resultDose = (DoseTypeGy)_statistics->getMaximum(); } } else { resultDose = (DoseTypeGy)_statistics->getMinimum(); } return resultDose; } DoseStatisticsCalculator::DoseToVolumeFunctionType DoseStatisticsCalculator::computeDoseToVolumeFunctionMulti(DoseTypeGy referenceDose, const std::vector& precomputeDoseValues, DoseStatistics::complexStatistics name) const { std::vector threads; DoseToVolumeFunctionType VxMulti; for (size_t i = 0; i < precomputeDoseValues.size(); ++i) { if (_multiThreading) { threads.push_back(std::thread(&DoseStatisticsCalculator::computeDoseToVolumeSingle, this, referenceDose, precomputeDoseValues.at(i), name, std::ref(VxMulti))); } else { DoseStatisticsCalculator::computeDoseToVolumeSingle(referenceDose, precomputeDoseValues.at(i), name, std::ref(VxMulti)); } } for (auto& t : threads) { t.join(); } return VxMulti; } void DoseStatisticsCalculator::computeDoseToVolumeSingle(DoseTypeGy referenceDose, double precomputeDoseValue, DoseStatistics::complexStatistics name, DoseToVolumeFunctionType& VxMulti) const { if (name == DoseStatistics::Vx) { double xAbsolue = precomputeDoseValue * referenceDose; - VxMulti.insert(std::pair(xAbsolue, - computeVx(xAbsolue))); + if (_multiThreading){ + ::boost::unique_lock<::boost::shared_mutex> lock(*_mutex); + VxMulti.insert(std::pair(xAbsolue, + computeVx(xAbsolue))); + } + else { + VxMulti.insert(std::pair(xAbsolue, + computeVx(xAbsolue))); + } } else { throw core::InvalidParameterException("unknown DoseStatistics name!"); } } DoseStatisticsCalculator::VolumeToDoseFunctionType DoseStatisticsCalculator::computeVolumeToDoseFunctionMulti( const std::vector& precomputeVolumeValues, DoseStatistics::complexStatistics name) const { std::vector threads; VolumeToDoseFunctionType multiValues; VolumeType volume = _statistics->getVolume(); for (size_t i = 0; i < precomputeVolumeValues.size(); ++i) { if (_multiThreading) { threads.push_back(std::thread(&DoseStatisticsCalculator::computeVolumeToDoseSingle, this, precomputeVolumeValues.at(i), name, std::ref(multiValues), volume)); } else { DoseStatisticsCalculator::computeVolumeToDoseSingle(precomputeVolumeValues.at(i), name, std::ref(multiValues), volume); } } for (auto& t : threads) { t.join(); } return multiValues; } void DoseStatisticsCalculator::computeVolumeToDoseSingle(const double& precomputeVolumeValue, DoseStatistics::complexStatistics name, VolumeToDoseFunctionType& multiValues, VolumeType volume) const { double xAbsolute = precomputeVolumeValue * volume; + ::boost::unique_lock<::boost::shared_mutex> lock(*_mutex); switch (name) { case DoseStatistics::Dx: multiValues.insert(std::pair(xAbsolute, computeDx(xAbsolute))); break; case DoseStatistics::MOHx: multiValues.insert(std::pair(xAbsolute, computeMOHx(xAbsolute))); break; case DoseStatistics::MOCx: multiValues.insert(std::pair(xAbsolute, computeMOCx(xAbsolute))); break; case DoseStatistics::MaxOHx: multiValues.insert(std::pair(xAbsolute, computeMaxOHx(xAbsolute))); break; case DoseStatistics::MinOCx: multiValues.insert(std::pair(xAbsolute, computeMinOCx(xAbsolute))); break; default: throw core::InvalidParameterException("unknown DoseStatistics name!"); } } void DoseStatisticsCalculator::setMultiThreading(const bool choice) { _multiThreading = choice; } }//end namespace algorithms }//end namespace rttb diff --git a/code/algorithms/rttbDoseStatisticsCalculator.h b/code/algorithms/rttbDoseStatisticsCalculator.h index 09abb10..5bcdd6d 100644 --- a/code/algorithms/rttbDoseStatisticsCalculator.h +++ b/code/algorithms/rttbDoseStatisticsCalculator.h @@ -1,192 +1,197 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #ifndef __DOSE_STATISTICS_CALCULATOR_H #define __DOSE_STATISTICS_CALCULATOR_H #include +#include +#include + #include "rttbBaseType.h" #include "rttbDoseIteratorInterface.h" #include "rttbDoseStatistics.h" #include "RTTBAlgorithmsExports.h" namespace rttb { namespace algorithms { /*! @class DoseStatisticsCalculator @brief Class for calculating different statistical values from a RT dose distribution @details These values range from standard statistical values such as minimum, maximum and mean to more complex dose specific measures such as Vx (volume irradiated with a dose >=x), Dx (minimal dose delivered to x% of the VOI) or MOHx (mean in the hottest volume). For a complete list, see calculateDoseStatistics(). @note the complex dose statistics are precomputed and cannot be computed "on the fly" lateron! The doses/volumes that should be used for precomputation have to be set in calculateDoseStatistics() */ class RTTBAlgorithms_EXPORT DoseStatisticsCalculator { public: typedef core::DoseIteratorInterface::DoseIteratorPointer DoseIteratorPointer; typedef DoseStatistics::ResultListPointer ResultListPointer; typedef DoseStatistics::DoseStatisticsPointer DoseStatisticsPointer; typedef DoseStatistics::DoseToVolumeFunctionType DoseToVolumeFunctionType; typedef DoseStatistics::VolumeToDoseFunctionType VolumeToDoseFunctionType; private: DoseIteratorPointer _doseIterator; /*! @brief Contains relevant dose values sorted in descending order. */ std::vector _doseVector; /*! @brief Contains the corresponding voxel proportions to the values in doseVector. */ std::vector _voxelProportionVector; /*! @brief The doseStatistics are stored here. */ DoseStatisticsPointer _statistics; bool _simpleDoseStatisticsCalculated; bool _multiThreading; + ::boost::shared_ptr _mutex; + /*! @brief Calculates the positions where the dose has its maximum @param maxNumberMaximaPositions the maximal amount of computed positions @pre maximumDose must be defined in _statistics with the correct value */ ResultListPointer computeMaximumPositions(unsigned int maxNumberMaximaPositions) const; /*! @brief Calculates the positions where the dose has its minimum @param maxNumberMinimaPositions the maximal amount of computed positions (they are read sequentially using the iterator until maxNumberMinimaPositions have been read, other positions are not considered) @pre minimumDose must be defined in _statistics with the correct value */ ResultListPointer computeMinimumPositions(unsigned int maxNumberMinimaPositions) const; VolumeType computeVx(DoseTypeGy xDoseAbsolute) const; DoseTypeGy computeDx(VolumeType xVolumeAbsolute) const; DoseTypeGy computeMOHx(VolumeType xVolumeAbsolute) const; DoseTypeGy computeMOCx(DoseTypeGy xVolumeAbsolute) const; DoseTypeGy computeMaxOHx(DoseTypeGy xVolumeAbsolute) const; DoseTypeGy computeMinOCx(DoseTypeGy xVolumeAbsolute) const; DoseToVolumeFunctionType computeDoseToVolumeFunctionMulti(DoseTypeGy referenceDose, const std::vector& precomputeDoseValues, DoseStatistics::complexStatistics name) const; VolumeToDoseFunctionType computeVolumeToDoseFunctionMulti(const std::vector& precomputeVolumeValues, DoseStatistics::complexStatistics name) const; void computeDoseToVolumeSingle(DoseTypeGy referenceDose, double precomputeDoseValue, DoseStatistics::complexStatistics name, DoseToVolumeFunctionType& VxMulti) const; void computeVolumeToDoseSingle(const double& precomputeVolumeValue, DoseStatistics::complexStatistics name, VolumeToDoseFunctionType& multiValues, VolumeType volume) const; /*! @brief Calculates simple dose statistics (min, mean, max, stdDev, minDosePositions, maxDosePositions) @param maxNumberMinimaPositions the maximal amount of computed positions where the dose has its minimum that is computed @param maxNumberMaximaPositions the maximal amount of computed positions where the dose has its maximum that is computed */ void calculateSimpleDoseStatistics(unsigned int maxNumberMinimaPositions, unsigned int maxNumberMaximaPositions); /*! @brief Calculates complex dose statistics (Dx, Vx, MOHx, MOCx, MaxOHx, MinOCx) @warning computations can take quite long (>1 min) for large structures as many statistics are precomputed */ void calculateComplexDoseStatistics(DoseTypeGy referenceDose, const std::vector& precomputeDoseValues, const std::vector& precomputeVolumeValues); public: ~DoseStatisticsCalculator(); /*! @brief Constructor @param aDoseIterator the dose to be analyzed */ DoseStatisticsCalculator(DoseIteratorPointer aDoseIterator); DoseIteratorPointer getDoseIterator() const; /*! @brief Compute simple or complex dose statistics with default relative x values and the maximum dose as default reference dose (for Vx computation) @details The following statistics are calculated always (i.e. also if computeComplexMeasures=false):
  • minimum dose
  • mean dose
  • maximum dose
  • standard deviation dose
  • voxel positions of minimum dose
  • voxel positions of maximum dose
Additionally, these statistics are computed if computeComplexMeasures=true:
  • Dx (the minimal dose delivered to a volume >= x)
  • Vx (the volume irradiated with a dose >= x)
  • MOHx (mean dose of the hottest x volume)
  • MOCx (mean dose of the coldest x volume)
  • MaxOHx (Maximum outside of the hottest x volume)
  • MinOCx (Minimum outside of the coldest x volume)
Default x values for Vx are 0.02, 0.05, 0.1, 0.9, 0.95 and 0.98, with respect to maxDose. Default x values for Dx, MOHx, MOCx, MaxOHx and MinOCx are 0.02, 0.05, 0.1, 0.9, 0.95 and 0.98, with respect to volume. @param computeComplexMeasures should complex statistics be calculated? If it is true, the complex dose statistics will be calculated with default relative x values and the maximum dose as reference dose @param maxNumberMinimaPositions the maximal amount of computed positions where the dose has its minimum that is computed @param maxNumberMaximaPositions the maximal amount of computed positions where the dose has its maximum that is computed @warning If computeComplexMeasures==true, computations can take quite long (>1 min) for large structures as many statistics are precomputed @note The complex dose statistics are precomputed and cannot be computed "on the fly" lateron! Only the default x values can be requested in DoseStatistics! */ DoseStatisticsPointer calculateDoseStatistics(bool computeComplexMeasures = false, unsigned int maxNumberMinimaPositions = 10, unsigned int maxNumberMaximaPositions = 10); /*! @brief Compute complex dose statistics with given reference dose and default relative x values @param referenceDose the reference dose to compute Vx, normally it should be the prescribed dose @param maxNumberMinimaPositions the maximal amount of computed positions where the dose has its minimum that is computed @param maxNumberMaximaPositions the maximal amount of computed positions where the dose has its maximum that is computed @exception InvalidParameterException thrown if referenceDose <= 0 @warning Computations can take quite long (>1 min) for large structures as many statistics are precomputed @note The complex dose statistics are precomputed and cannot be computed "on the fly" lateron! Only the default x values can be requested in DoseStatistics! */ DoseStatisticsPointer calculateDoseStatistics(DoseTypeGy referenceDose, unsigned int maxNumberMinimaPositions = 10, unsigned int maxNumberMaximaPositions = 10); /*! @brief Compute complex dose statistics with given relative x values and reference dose @param precomputeDoseValues the relative dose values for Vx precomputation, e.g. 0.02, 0.05, 0.95... @param precomputeVolumeValues the relative volume values for Dx, MOHx, MOCx, MaxOHx and MinOCx precomputation, e.g. 0.02, 0.05, 0.95... @param referenceDose the reference dose to compute Vx, normally it should be the prescribed dose. Default value is the maximum dose. @param maxNumberMinimaPositions the maximal amount of computed positions where the dose has its minimum that is computed @param maxNumberMaximaPositions the maximal amount of computed positions where the dose has its maximum that is computed @warning Computations can take quite long (>1 min) for large structures as many statistics are precomputed @note The complex dose statistics are precomputed and cannot be computed "on the fly" lateron! The doses/volumes that should be used for precomputation have to be set by in precomputeDoseValues and precomputeVolumeValues. Only these values can be requested in DoseStatistics! */ DoseStatisticsPointer calculateDoseStatistics(const std::vector& precomputeDoseValues, const std::vector& precomputeVolumeValues, DoseTypeGy referenceDose = -1, unsigned int maxNumberMinimaPositions = 10, unsigned int maxNumberMaximaPositions = 10); void setMultiThreading(bool choice); }; } } #endif diff --git a/code/core/CMakeLists.txt b/code/core/CMakeLists.txt index eb85b02..fefd69b 100644 --- a/code/core/CMakeLists.txt +++ b/code/core/CMakeLists.txt @@ -1,2 +1,5 @@ RTTB_CREATE_MODULE(RTTBCore PACKAGE_DEPENDS BoostBinaries) +IF (NOT WIN32) + target_compile_features(RTTBCore PRIVATE cxx_auto_type cxx_nullptr cxx_override) +ENDIF() diff --git a/code/interpolation/MatchPointTransformation/CMakeLists.txt b/code/interpolation/MatchPointTransformation/CMakeLists.txt index 68feb4f..66f617f 100644 --- a/code/interpolation/MatchPointTransformation/CMakeLists.txt +++ b/code/interpolation/MatchPointTransformation/CMakeLists.txt @@ -1 +1,6 @@ RTTB_CREATE_MODULE(RTTBInterpolationMatchPointTransformation DEPENDS RTTBCore RTTBInterpolation PACKAGE_DEPENDS Boost MatchPoint ITK) + +IF (NOT WIN32) + target_compile_features(RTTBInterpolationMatchPointTransformation PRIVATE cxx_auto_type cxx_nullptr cxx_override) + set(CMAKE_CXX_FLAGS "-fpermissive") +ENDIF() diff --git a/code/io/dicom/CMakeLists.txt b/code/io/dicom/CMakeLists.txt index 849ac4d..1b34ffe 100644 --- a/code/io/dicom/CMakeLists.txt +++ b/code/io/dicom/CMakeLists.txt @@ -1,5 +1,4 @@ RTTB_CREATE_MODULE(RTTBDicomIO DEPENDS RTTBCore RTTBAlgorithms PACKAGE_DEPENDS BoostBinaries DCMTK) IF (NOT WIN32) - #CMake 3.1 provides target_compile_features(RTTB_Interpolation cxx_auto_type cxx_nullptr cxx_override) to automatically add required compiler flags - set(CMAKE_CXX_FLAGS "-std=c++11") + target_compile_features(RTTBDicomIO PRIVATE cxx_auto_type cxx_nullptr cxx_override) ENDIF() diff --git a/code/io/dicom/rttbDicomDoseAccessor.h b/code/io/dicom/rttbDicomDoseAccessor.h index 9f4df69..6f61603 100644 --- a/code/io/dicom/rttbDicomDoseAccessor.h +++ b/code/io/dicom/rttbDicomDoseAccessor.h @@ -1,101 +1,101 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #ifndef __DICOM_DOSE_ACCESSOR_H #define __DICOM_DOSE_ACCESSOR_H +#include "osconfig.h" /* make sure OS specific configuration is included first */ +#include "drtdose.h" + #include #include #include #include -#include "osconfig.h" /* make sure OS specific configuration is included first */ -#include "drtdose.h" - #include "rttbAccessorWithGeoInfoBase.h" #include "rttbBaseType.h" namespace rttb { namespace io { namespace dicom { /*! @class DicomDoseAccessor @brief This class gives access to dose information from DRTDoseIOD and DcmItem */ class DicomDoseAccessor: public core::AccessorWithGeoInfoBase { public: typedef boost::shared_ptr DRTDoseIODPtr; typedef boost::shared_ptr DcmItemPtr; private: DRTDoseIODPtr _dose; DcmItemPtr _dataSet; /*! vector of dose data(absolute Gy dose/doseGridScaling)*/ std::vector doseData; double _doseGridScaling; IDType _doseUID; DicomDoseAccessor(); protected: /*! @brief Initialize dose data @exception InvalidDoseException Thrown if _dose is invalid: one of column/row/numberOfFrames/doseGridScaling/pixelSpacing=0 @exception DcmrtException Throw if dcmrt error @exception boost/bad_lexical_cast Thrown if the imported header tags are not numerical. */ bool begin(); /*! @brief get all required data from dicom information contained in _dose @exception boost/bad_lexical_cast Thrown if the imported header tags are not numerical. */ bool assembleGeometricInfo(); public: ~DicomDoseAccessor(); /*! @brief Constructor. Initialisation with a boost::shared_ptr of DRTDoseIOD and of DcmItem to get the pixel data @exception DcmrtException Throw if dcmrt error */ DicomDoseAccessor(DRTDoseIODPtr aDRTDoseIODP, DcmItemPtr aDcmDataset); GenericValueType getValueAt(const VoxelGridID aID) const; GenericValueType getValueAt(const VoxelGridIndex3D& aIndex) const; const IDType getUID() const { return _doseUID; }; }; } } } #endif diff --git a/code/io/itk/CMakeLists.txt b/code/io/itk/CMakeLists.txt index f5308ab..00910b2 100644 --- a/code/io/itk/CMakeLists.txt +++ b/code/io/itk/CMakeLists.txt @@ -1,5 +1,5 @@ RTTB_CREATE_MODULE(RTTBITKIO DEPENDS RTTBCore PACKAGE_DEPENDS Boost ITK) IF (NOT WIN32) - #CMake 3.1 provides target_compile_features(RTTB_Interpolation cxx_auto_type cxx_nullptr cxx_override) to automatically add required compiler flags + target_compile_features(RTTBITKIO PRIVATE cxx_auto_type cxx_nullptr cxx_override) set(CMAKE_CXX_FLAGS "-fpermissive") ENDIF() diff --git a/code/io/other/rttbDoseStatisticsXMLReader.cpp b/code/io/other/rttbDoseStatisticsXMLReader.cpp index bed370d..c68563b 100644 --- a/code/io/other/rttbDoseStatisticsXMLReader.cpp +++ b/code/io/other/rttbDoseStatisticsXMLReader.cpp @@ -1,178 +1,187 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1328 $ (last changed revision) // @date $Date: 2016-04-22 09:50:01 +0200 (Fr, 22 Apr 2016) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include #include #include "rttbDoseStatisticsXMLReader.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace io { namespace other { typedef boost::shared_ptr DoseStatisticsPtr; DoseStatisticsXMLReader::DoseStatisticsXMLReader(const std::string& filename) : _filename(filename), _newFile(true){ } DoseStatisticsXMLReader::~DoseStatisticsXMLReader(){ } void DoseStatisticsXMLReader::setFilename(const std::string& filename){ _filename = filename; _newFile = true; } DoseStatisticsPtr DoseStatisticsXMLReader::generateDoseStatistic(){ if (_newFile){ this->createDoseStatistic(); } return _doseStatistic; } void DoseStatisticsXMLReader::createDoseStatistic(){ boost::property_tree::ptree pt; // Load the XML file into the property tree. If reading fails // (cannot open file, parse error), an exception is thrown. try { read_xml(_filename, pt); } catch (boost::property_tree::xml_parser_error& /*e*/) { throw rttb::core::InvalidParameterException("DoseStatistics file name invalid: could not open the xml file!"); } // data to fill the parameter for the DoseStatistics std::string name; std::string datum; unsigned int x; std::pair voxelid; std::vector < std::pair> vec; //parameter for the DoseSTatistics double minimum; double maximum; double numVoxels; double volume; double referenceDose = -1; double mean; double stdDeviation; boost::shared_ptr > > minimumVoxelPositions = nullptr; boost::shared_ptr > > maximumVoxelPositions = nullptr; std::map Dx; std::map Vx; std::map MOHx; std::map MOCx; std::map MaxOHx; std::map MinOCx; BOOST_FOREACH(boost::property_tree::ptree::value_type & data, pt.get_child("statistics.results")){ datum = data.second.data(); +std::cout << "datum: " << datum << std::endl; BOOST_FOREACH(boost::property_tree::ptree::value_type & middel, data.second){ BOOST_FOREACH(boost::property_tree::ptree::value_type & innernode, middel.second){ std::string mia = innernode.first; +std::cout << "mia: " << mia << std::endl; if (innernode.first == "name"){ name = innernode.second.data(); } else if (innernode.first == "voxelGridID"){ +std::cout << 1.1 << std::endl; datum.erase(std::remove(datum.begin(), datum.end(), '\t'), datum.end()); datum.erase(std::remove(datum.begin(), datum.end(), '\n'), datum.end()); voxelid.first = boost::lexical_cast(datum); voxelid.second = boost::lexical_cast(innernode.second.data()); vec.push_back(voxelid); +std::cout << 1.2 << std::endl; } else if (innernode.first == "x"){ x = boost::lexical_cast(innernode.second.data()); } + else { + std::cout << "damn" << std::endl; + } } } +std::cout << name << std::endl; // fill with the extracted data if (name == "numberOfVoxels"){ numVoxels = boost::lexical_cast(datum); } else if (name == "volume"){ volume = boost::lexical_cast(datum); } else if (name == "referenceDose"){ referenceDose = boost::lexical_cast(datum); } else if (name == "mean"){ mean = boost::lexical_cast(datum); } else if (name == "standardDeviation"){ stdDeviation = boost::lexical_cast(datum); } else if (name == "minimum"){ minimum = boost::lexical_cast(datum); if (!vec.empty()){ minimumVoxelPositions = boost::make_shared>>(vec); vec.clear(); } } else if (name == "maximum"){ maximum = boost::lexical_cast(datum); if (!vec.empty()){ maximumVoxelPositions = boost::make_shared>>(vec); vec.clear(); } } else if (name == "Dx"){ Dx[boost::lexical_cast(x)*volume / 100] = boost::lexical_cast(datum); } else if (name == "Vx"){ Vx[boost::lexical_cast(x)*referenceDose / 100] = boost::lexical_cast(datum); } else if (name == "MOHx"){ MOHx[boost::lexical_cast(x)*volume / 100] = boost::lexical_cast(datum); } else if (name == "MOCx"){ MOCx[boost::lexical_cast(x)*volume / 100] = boost::lexical_cast(datum); } else if (name == "MaxOHx"){ MaxOHx[boost::lexical_cast(x)*volume / 100] = boost::lexical_cast(datum); } else if (name == "MinOCx"){ MinOCx[boost::lexical_cast(x)*volume / 100] = boost::lexical_cast(datum); } +std::cout << "end" << std::endl; } // make DoseStatistcs _doseStatistic = boost::make_shared( minimum, maximum, mean, stdDeviation, numVoxels, volume, minimumVoxelPositions, maximumVoxelPositions ,Dx, Vx, MOHx, MOCx, MaxOHx, MinOCx, referenceDose); } }//end namespace other }//end namespace io }//end namespace rttb diff --git a/code/masks/boost/CMakeLists.txt b/code/masks/boost/CMakeLists.txt index 66d33bf..0b4c169 100644 --- a/code/masks/boost/CMakeLists.txt +++ b/code/masks/boost/CMakeLists.txt @@ -1 +1,6 @@ -RTTB_CREATE_MODULE(RTTBBoostMask DEPENDS RTTBCore RTTBMasks PACKAGE_DEPENDS Boost) \ No newline at end of file +SET(RTTB_Boost_ADDITIONAL_COMPONENT thread) +RTTB_CREATE_MODULE(RTTBBoostMask DEPENDS RTTBCore RTTBMasks PACKAGE_DEPENDS BoostBinaries) + +IF (NOT WIN32) + target_compile_features(RTTBBoostMask PRIVATE cxx_auto_type cxx_nullptr cxx_override) +ENDIF() diff --git a/code/masks/boost/rttbBoostMaskGenerateMaskVoxelListThread.cpp b/code/masks/boost/rttbBoostMaskGenerateMaskVoxelListThread.cpp index 9ecccdc..fa25303 100644 --- a/code/masks/boost/rttbBoostMaskGenerateMaskVoxelListThread.cpp +++ b/code/masks/boost/rttbBoostMaskGenerateMaskVoxelListThread.cpp @@ -1,155 +1,155 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1127 $ (last changed revision) // @date $Date: 2015-10-01 13:33:33 +0200 (Do, 01 Okt 2015) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "rttbBoostMaskGenerateMaskVoxelListThread.h" #include "rttbInvalidParameterException.h" #include namespace rttb { namespace masks { namespace boost { BoostMaskGenerateMaskVoxelListThread::BoostMaskGenerateMaskVoxelListThread( const VoxelIndexVector& aGlobalBoundingBox, GeometricInfoPointer aGeometricInfo, BoostArrayMapPointer aVoxelizationMap, double aVoxelizationThickness, unsigned int aBeginSlice, unsigned int aEndSlice, MaskVoxelListPointer aMaskVoxelList, ::boost::shared_ptr<::boost::shared_mutex> aMutex) : _globalBoundingBox(aGlobalBoundingBox), _geometricInfo(aGeometricInfo), _voxelizationMap(aVoxelizationMap), _voxelizationThickness(aVoxelizationThickness), _beginSlice(aBeginSlice), _endSlice(aEndSlice), _resultMaskVoxelList(aMaskVoxelList), _mutex(aMutex) {} void BoostMaskGenerateMaskVoxelListThread::operator()() { rttb::VoxelGridIndex3D minIndex = _globalBoundingBox.at(0); rttb::VoxelGridIndex3D maxIndex = _globalBoundingBox.at(1); unsigned int globalBoundingBoxSize0 = maxIndex[0] - minIndex[0] + 1; unsigned int globalBoundingBoxSize1 = maxIndex[1] - minIndex[1] + 1; std::vector maskVoxelsInThread; for (unsigned int indexZ = _beginSlice; indexZ < _endSlice; ++indexZ) { //calculate weight vector std::map weightVectorForZ; calcWeightVector(indexZ, weightVectorForZ); //For each x,y, calc sum of all voxelization plane, use weight vector for (unsigned int x = 0; x < globalBoundingBoxSize0; ++x) { for (unsigned int y = 0; y < globalBoundingBoxSize1; ++y) { rttb::VoxelGridIndex3D currentIndex; currentIndex[0] = x + minIndex[0]; currentIndex[1] = y + minIndex[1]; currentIndex[2] = indexZ; rttb::VoxelGridID gridID; _geometricInfo->convert(currentIndex, gridID); double volumeFraction = 0; auto it = weightVectorForZ.cbegin(); auto itMap = _voxelizationMap->cbegin(); for (; it != weightVectorForZ.cend() && itMap != _voxelizationMap->cend(); ++it, ++itMap) { double weight = it->second; if (weight > 0){ BoostArray2DPointer voxelizationArray = itMap->second; //calc sum of all voxelization plane, use weight volumeFraction += (*voxelizationArray)[x][y] * weight; } } if (volumeFraction > 1 && (volumeFraction - 1) <= errorConstant) { volumeFraction = 1; } else if (volumeFraction < 0 || (volumeFraction - 1) > errorConstant) { throw rttb::core::InvalidParameterException("Mask calculation failed! The volume fraction should >= 0 and <= 1!"); } //insert mask voxel if volumeFraction > 0 if (volumeFraction > 0) { core::MaskVoxel maskVoxelPtr = core::MaskVoxel(gridID, volumeFraction); maskVoxelsInThread.push_back(maskVoxelPtr); } } } } ::boost::unique_lock<::boost::shared_mutex> lock(*_mutex); _resultMaskVoxelList->insert(_resultMaskVoxelList->end(), maskVoxelsInThread.begin(), maskVoxelsInThread.end()); } void BoostMaskGenerateMaskVoxelListThread::calcWeightVector(const rttb::VoxelGridID& aIndexZ, std::map& weightVector) const { double indexZMin = aIndexZ - 0.5; double indexZMax = aIndexZ + 0.5; for (auto it = _voxelizationMap->begin(); it != _voxelizationMap->end(); ++it) { double voxelizationPlaneIndexMin = (*it).first - 0.5 * _voxelizationThickness; double voxelizationPlaneIndexMax = (*it).first + 0.5 * _voxelizationThickness; double weight = 0; if ((voxelizationPlaneIndexMin < indexZMin) && (voxelizationPlaneIndexMax > indexZMin)) { if (voxelizationPlaneIndexMax < indexZMax) { weight = voxelizationPlaneIndexMax - indexZMin; } else { weight = 1; } } else if ((voxelizationPlaneIndexMin >= indexZMin) && (voxelizationPlaneIndexMin < indexZMax)) { if (voxelizationPlaneIndexMax < indexZMax) { weight = _voxelizationThickness; } else { weight = indexZMax - voxelizationPlaneIndexMin; } } weightVector.insert(std::pair(it->first, weight)); } } } } -} \ No newline at end of file +} diff --git a/code/models/CMakeLists.txt b/code/models/CMakeLists.txt index 0611aa1..1bf3814 100644 --- a/code/models/CMakeLists.txt +++ b/code/models/CMakeLists.txt @@ -1 +1,5 @@ RTTB_CREATE_MODULE(RTTBModels DEPENDS RTTBCore PACKAGE_DEPENDS Boost) + +IF (NOT WIN32) + target_compile_features(RTTBModels PRIVATE cxx_auto_type cxx_nullptr cxx_override) +ENDIF() diff --git a/testing/algorithms/DoseStatisticsCalculatorTest.cpp b/testing/algorithms/DoseStatisticsCalculatorTest.cpp index 009aaff..d09f4f9 100644 --- a/testing/algorithms/DoseStatisticsCalculatorTest.cpp +++ b/testing/algorithms/DoseStatisticsCalculatorTest.cpp @@ -1,325 +1,326 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include #include #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbGenericDoseIterator.h" #include "rttbDoseIteratorInterface.h" #include "rttbNullPointerException.h" #include "rttbDoseStatisticsCalculator.h" #include "rttbInvalidDoseException.h" #include "rttbInvalidParameterException.h" #include "rttbDataNotAvailableException.h" #include "../core/DummyDoseAccessor.h" namespace rttb { namespace testing { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef core::DoseIteratorInterface::DoseIteratorPointer DoseIteratorPointer; typedef rttb::algorithms::DoseStatistics::ResultListPointer ResultListPointer; typedef rttb::algorithms::DoseStatistics::DoseStatisticsPointer DoseStatisticsPointer; /*! @brief DoseStatisticsCalculatorTest - test the API of DoseStatisticsCalculator 1) test constructors 2) test setDoseIterator 3) test calculateDoseSatistics 4) get statistical values */ int DoseStatisticsCalculatorTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DoseAccessorPointer spDoseAccessor(spTestDoseAccessor); const std::vector* doseVals = spTestDoseAccessor->getDoseVector(); boost::shared_ptr spTestDoseIterator = boost::make_shared(spDoseAccessor); DoseIteratorPointer spDoseIterator(spTestDoseIterator); DoseIteratorPointer spDoseIteratorNull; //1) test constructors // the values cannot be accessed from outside, therefore correct default values are not tested CHECK_THROW_EXPLICIT(rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator( spDoseIteratorNull), core::NullPointerException); CHECK_NO_THROW(rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator(spDoseIterator)); rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator(spDoseIterator); //2) test setDoseIterator //3) test calculateDoseStatistics DoseStatisticsPointer theStatistics; //simple dose statistics CHECK_NO_THROW(theStatistics = myDoseStatsCalculator.calculateDoseStatistics()); CHECK_EQUAL(theStatistics->getMinimumVoxelPositions()->empty(), false); CHECK_EQUAL(theStatistics->getMaximumVoxelPositions()->empty(), false); CHECK_EQUAL(theStatistics->getAllVx().empty(), true); CHECK_EQUAL(theStatistics->getAllDx().empty(), true); CHECK_EQUAL(theStatistics->getAllVx().empty(), true); CHECK_EQUAL(theStatistics->getAllMaxOHx().empty(), true); CHECK_EQUAL(theStatistics->getAllMOHx().empty(), true); CHECK_EQUAL(theStatistics->getAllMOCx().empty(), true); CHECK_EQUAL(theStatistics->getAllMinOCx().empty(), true); //check default values for computeComplexMeasures=true DoseStatisticsPointer theStatisticsDefault; myDoseStatsCalculator.setMultiThreading(true); CHECK_NO_THROW(theStatisticsDefault = myDoseStatsCalculator.calculateDoseStatistics(true)); CHECK_NO_THROW(theStatisticsDefault->getVx(0.02 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getVx(0.05 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getVx(0.1 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getVx(0.9 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getVx(0.95 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getVx(0.98 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getDx(0.02 * theStatisticsDefault->getVolume())); CHECK_NO_THROW(theStatisticsDefault->getDx(0.05 * theStatisticsDefault->getVolume())); CHECK_NO_THROW(theStatisticsDefault->getDx(0.1 * theStatisticsDefault->getVolume())); CHECK_NO_THROW(theStatisticsDefault->getDx(0.9 * theStatisticsDefault->getVolume())); CHECK_NO_THROW(theStatisticsDefault->getDx(0.95 * theStatisticsDefault->getVolume())); CHECK_NO_THROW(theStatisticsDefault->getDx(0.98 * theStatisticsDefault->getVolume())); //check manually set reference dose and the default x values CHECK_NO_THROW(theStatistics = myDoseStatsCalculator.calculateDoseStatistics(100.0)); CHECK_THROW_EXPLICIT(theStatistics->getVx(0.1 * theStatistics->getMaximum()), core::DataNotAvailableException); CHECK_NO_THROW(theStatistics->getVx(0.1 * 100.0)); CHECK_NO_THROW(theStatistics->getDx(0.1 * theStatistics->getVolume())); CHECK_NO_THROW(theStatistics->getDx(0.9 * theStatistics->getVolume())); CHECK_NO_THROW(theStatistics->getMOHx(0.95 * theStatistics->getVolume())); CHECK_NO_THROW(theStatistics->getMOCx(0.98 * theStatistics->getVolume())); CHECK_EQUAL(theStatistics->getReferenceDose(), 100.0); //check manually set x values std::vector precomputeDoseValues, precomputeVolumeValues; precomputeDoseValues.push_back(0.01); precomputeDoseValues.push_back(0.02); precomputeDoseValues.push_back(0.05); precomputeVolumeValues.push_back(0.9); precomputeVolumeValues.push_back(0.95); precomputeVolumeValues.push_back(0.99); CHECK_NO_THROW(theStatistics = myDoseStatsCalculator.calculateDoseStatistics(precomputeDoseValues, precomputeVolumeValues)); CHECK_NO_THROW(theStatistics->getVx(0.01 * theStatistics->getMaximum())); CHECK_NO_THROW(theStatistics->getVx(0.02 * theStatistics->getMaximum())); CHECK_NO_THROW(theStatistics->getVx(0.05 * theStatistics->getMaximum())); CHECK_THROW_EXPLICIT(theStatistics->getVx(0.03 * theStatistics->getMaximum()), core::DataNotAvailableException); CHECK_NO_THROW(theStatistics->getDx(0.9 * theStatistics->getVolume())); CHECK_NO_THROW(theStatistics->getDx(0.95 * theStatistics->getVolume())); CHECK_NO_THROW(theStatistics->getDx(0.99 * theStatistics->getVolume())); CHECK_THROW_EXPLICIT(theStatistics->getDx(0.03 * theStatistics->getVolume()), core::DataNotAvailableException); + std::cout << "maximum: " << theStatistics->getMaximum() << std::endl; CHECK_EQUAL(theStatistics->getVx(0.02 * theStatistics->getMaximum()), theStatisticsDefault->getVx(0.02 * theStatistics->getMaximum())); CHECK_EQUAL(theStatistics->getVx(0.05 * theStatistics->getMaximum()), theStatisticsDefault->getVx(0.05 * theStatistics->getMaximum())); CHECK_EQUAL(theStatistics->getDx(0.9 * theStatistics->getVolume()), theStatisticsDefault->getDx(0.9 * theStatistics->getVolume())); CHECK_EQUAL(theStatistics->getDx(0.95 * theStatistics->getVolume()), theStatisticsDefault->getDx(0.95 * theStatistics->getVolume())); //check manually set reference dose and x values CHECK_NO_THROW(theStatistics = myDoseStatsCalculator.calculateDoseStatistics(precomputeDoseValues, precomputeVolumeValues, 100.0)); CHECK_THROW_EXPLICIT(theStatistics->getVx(0.01 * theStatistics->getMaximum()), core::DataNotAvailableException); CHECK_NO_THROW(theStatistics->getVx(0.01 * 100.0)); CHECK_NO_THROW(theStatistics->getDx(0.9 * theStatistics->getVolume())); CHECK_EQUAL(theStatistics->getReferenceDose(), 100.0); //MOHx, MOCx, MaxOHx and MinOCx are computed analogous to Dx, they will not be checked. //4) get statistical values CHECK_EQUAL(theStatistics->getNumberOfVoxels(), doseVals->size()); //compute simple statistical values (min, mean, max, stddev) for comparison DoseStatisticType maximum = 0; DoseStatisticType minimum = 1000000; DoseStatisticType mean = 0; DoseStatisticType variance = 0; std::vector::const_iterator doseIt = doseVals->begin(); while (doseIt != doseVals->end()) { if (maximum < *doseIt) { maximum = *doseIt; } if (minimum > *doseIt) { minimum = *doseIt; } mean += *doseIt; ++doseIt; } mean /= doseVals->size(); DoseTypeGy compMean = (int(mean * 100)) / 100; doseIt = doseVals->begin(); while (doseIt != doseVals->end()) { variance += pow(*doseIt - mean, 2); ++doseIt; } variance /= doseVals->size(); DoseStatisticType stdDev = pow(variance, 0.5); //we have some precision problems here... double errorConstantLarger = 1e-2; CHECK_EQUAL(theStatistics->getMaximum(), maximum); CHECK_EQUAL(theStatistics->getMinimum(), minimum); CHECK_CLOSE(theStatistics->getMean(), mean, errorConstantLarger); CHECK_CLOSE(theStatistics->getStdDeviation(), stdDev, errorConstantLarger); CHECK_CLOSE(theStatistics->getVariance(), variance, errorConstantLarger); //check for complex doseStatistics (maximumPositions, minimumPositions, Vx, Dx, MOHx, MOCx, MAXOHx, MinOCx) unsigned int nMax = 0, nMin = 0; doseIt = doseVals->begin(); while (doseIt != doseVals->end()) { if (*doseIt == theStatistics->getMaximum()) { nMax++; } if (*doseIt == theStatistics->getMinimum()) { nMin++; } ++doseIt; } //only 100 positions are stored if (nMax > 100) { nMax = 100; } if (nMin > 100) { nMin = 100; } auto maximaPositions = theStatistics->getMaximumVoxelPositions(); auto minimaPositions = theStatistics->getMinimumVoxelPositions(); CHECK_EQUAL(maximaPositions->size(), nMax); CHECK_EQUAL(minimaPositions->size(), nMin); for (auto maximaPositionsIterator = std::begin(*maximaPositions); maximaPositionsIterator != std::end(*maximaPositions); ++maximaPositionsIterator) { CHECK_EQUAL(maximaPositionsIterator->first, theStatistics->getMaximum()); } for (auto minimaPositionsIterator = std::begin(*minimaPositions); minimaPositionsIterator != std::end(*minimaPositions); ++minimaPositionsIterator) { CHECK_EQUAL(minimaPositionsIterator->first, theStatistics->getMinimum()); } //generate specific example dose maximum = 9.5; minimum = 2.5; mean = 6; int sizeTemplate = 500; std::vector aDoseVector; for (int i = 0; i < sizeTemplate; i++) { aDoseVector.push_back(maximum); aDoseVector.push_back(minimum); } core::GeometricInfo geoInfo = spTestDoseAccessor->getGeometricInfo(); geoInfo.setNumRows(20); geoInfo.setNumColumns(10); geoInfo.setNumSlices(5); boost::shared_ptr spTestDoseAccessor2 = boost::make_shared(aDoseVector, geoInfo); DoseAccessorPointer spDoseAccessor2(spTestDoseAccessor2); boost::shared_ptr spTestDoseIterator2 = boost::make_shared(spDoseAccessor2); DoseIteratorPointer spDoseIterator2(spTestDoseIterator2); rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator2(spDoseIterator2); DoseStatisticsPointer theStatistics3 = myDoseStatsCalculator2.calculateDoseStatistics(); CHECK_EQUAL(theStatistics3->getMaximum(), maximum); CHECK_EQUAL(theStatistics3->getMinimum(), minimum); CHECK_EQUAL(theStatistics3->getMean(), mean); maximaPositions = theStatistics3->getMaximumVoxelPositions(); minimaPositions = theStatistics3->getMinimumVoxelPositions(); CHECK_EQUAL(maximaPositions->empty(), false); CHECK_EQUAL(minimaPositions->empty(), false); for (auto maximaPositionsIterator = std::begin(*maximaPositions); maximaPositionsIterator != std::end(*maximaPositions); ++maximaPositionsIterator) { CHECK_EQUAL(maximaPositionsIterator->first, theStatistics3->getMaximum()); } for (auto minimaPositionsIterator = std::begin(*minimaPositions); minimaPositionsIterator != std::end(*minimaPositions); ++minimaPositionsIterator) { CHECK_EQUAL(minimaPositionsIterator->first, theStatistics3->getMinimum()); } RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/apps/DoseTool/CMakeLists.txt b/testing/apps/DoseTool/CMakeLists.txt index b9107d7..0c71be3 100644 --- a/testing/apps/DoseTool/CMakeLists.txt +++ b/testing/apps/DoseTool/CMakeLists.txt @@ -1,35 +1,39 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(DOSETOOL_TEST ${EXECUTABLE_OUTPUT_PATH}/rttbDoseToolTests) SET(TEST_DATA_ROOT ${RTTBTesting_SOURCE_DIR}/data) SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) #----------------------------------------------------------------------------- IF(MSVC) ADD_DEFINITIONS(/bigobj) ENDIF() IF (WIN32) SET(DOSETOOLEXE "DoseTool.exe") ELSE (WIN32) SET(DOSETOOLEXE "./DoseTool") ENDIF (WIN32) ADD_TEST(DoseToolInvalidParametersTest ${DOSETOOL_TEST} DoseToolInvalidParametersTest ${DOSETOOLEXE}) ADD_TEST(DoseToolDicomDoseDicomStructTest ${DOSETOOL_TEST} DoseToolDicomDoseTest ${DOSETOOLEXE} "${TEST_DATA_ROOT}/Dose/DICOM/dicompylerTestDose.dcm" "${TEST_DATA_ROOT}/StructureSet/DICOM/rtss.dcm" "Nodes" "${TEST_DATA_ROOT}/DoseStatistics/XML/dicom.xml" "${TEST_DATA_ROOT}/DVH/XML/dicompylerDVH.xml" "${TEST_DATA_ROOT}/DoseStatistics/XML/dicomComplex.xml") ADD_TEST(DoseToolITKDoseDicomStructTest ${DOSETOOL_TEST} DoseToolITKDoseTest ${DOSETOOLEXE} "${TEST_DATA_ROOT}/Dose/ITK/dicompylerTestDose.mhd" "${TEST_DATA_ROOT}/StructureSet/DICOM/rtss.dcm" "Nodes" "${TEST_DATA_ROOT}/DoseStatistics/XML/itkDicomStruct.xml" "${TEST_DATA_ROOT}/DoseStatistics/XML/itkDicomStructComplex.xml") ADD_TEST(DoseToolDicomDoseDicomStructRegexTest ${DOSETOOL_TEST} DoseToolRegexTest ${DOSETOOLEXE} "${TEST_DATA_ROOT}/Dose/DICOM/dicompylerTestDose.dcm" "dicom" "${TEST_DATA_ROOT}/StructureSet/DICOM/rtss.dcm" "dicom" "Nodes|Heart" "${TEST_DATA_ROOT}/DoseStatistics/XML/dicom.xml" "${TEST_DATA_ROOT}/DoseStatistics/XML/dicom_heart.xml") ADD_TEST(DoseToolDVHTest ${DOSETOOL_TEST} DoseToolDVHTest ${DOSETOOLEXE} "${TEST_DATA_ROOT}/Dose/DICOM/dicompylerTestDose.dcm" "${TEST_DATA_ROOT}/StructureSet/DICOM/rtss.dcm" "Nodes" "${TEST_DATA_ROOT}/DVH/XML/dicompylerDVH.xml") RTTB_CREATE_APPLICATION_TESTS(DoseTool DEPENDS RTTBOtherIO PACKAGE_DEPENDS Litmus BoostBinaries) + +IF (NOT WIN32) + target_compile_features(rttbDoseToolTests PRIVATE cxx_auto_type cxx_nullptr cxx_override) +ENDIF() diff --git a/testing/apps/DoseTool/DoseToolDicomDoseTest.cpp b/testing/apps/DoseTool/DoseToolDicomDoseTest.cpp index 53ec134..5cd923f 100644 --- a/testing/apps/DoseTool/DoseToolDicomDoseTest.cpp +++ b/testing/apps/DoseTool/DoseToolDicomDoseTest.cpp @@ -1,136 +1,137 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1221 $ (last changed revision) // @date $Date: 2015-12-01 13:43:31 +0100 (Di, 01 Dez 2015) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "rttbDoseStatisticsXMLReader.h" #include "rttbDVHXMLFileReader.h" #include "../../io/other/CompareDoseStatistic.h" #include "../../io/other/CompareDVH.h" #include "litCheckMacros.h" #include "boost/filesystem.hpp" namespace rttb { namespace testing { //path to the current running directory. DoseTool is in the same directory (Debug/Release) extern const char* _callingAppPath; int DoseToolDicomDoseTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string doseToolExecutable; std::string doseFilename; std::string structFilename; std::string structName; std::string referenceXMLFilename; std::string referenceDVHXMLFilename; std::string referenceXMLComplexFilename; boost::filesystem::path callingPath(_callingAppPath); if (argc > 7) { doseToolExecutable = argv[1]; doseFilename = argv[2]; structFilename = argv[3]; structName = argv[4]; referenceXMLFilename = argv[5]; referenceDVHXMLFilename = argv[6]; referenceXMLComplexFilename = argv[7]; } std::string doseToolExeWithPath = callingPath.parent_path().string() + "/" + doseToolExecutable; std::string defaultOutputFilename = "dicomOutput.xml"; std::string defaultDVHOutputFilename = "dicomDVHOutput.xml"; std::string complexOutputFilename = "dicomOutputComplex.xml"; std::string baseCommand = doseToolExeWithPath; baseCommand += " -d " + doseFilename; baseCommand += " -s " + structFilename; if (structName != "") { baseCommand += " -n " + structName; } else { baseCommand += " -u itk "; } std::string defaultDoseStatisticsCommand = baseCommand + " -y " + defaultOutputFilename; std::cout << "Command line call: " + defaultDoseStatisticsCommand << std::endl; CHECK_EQUAL(system(defaultDoseStatisticsCommand.c_str()), 0); std::string defaultDoseStatisticsAndDVHCommand = defaultDoseStatisticsCommand + " -z " + defaultDVHOutputFilename; std::cout << "Command line call: " + defaultDoseStatisticsAndDVHCommand << std::endl; CHECK_EQUAL(system(defaultDoseStatisticsAndDVHCommand.c_str()), 0); std::string complexDoseStatisticsCommand = baseCommand + " -y " + complexOutputFilename; //prescribed dose is 14 Gy complexDoseStatisticsCommand += " -f -p 14"; std::cout << "Command line call: " + complexDoseStatisticsCommand << std::endl; CHECK_EQUAL(system(complexDoseStatisticsCommand.c_str()), 0); //check if file exists CHECK_EQUAL(boost::filesystem::exists(defaultOutputFilename), true); CHECK_EQUAL(boost::filesystem::exists(complexOutputFilename), true); CHECK_EQUAL(boost::filesystem::exists(defaultDVHOutputFilename), true); //check if file has dose statistics that are same than these in than reference file - io::other::DoseStatisticsXMLReader readerDefaultExpected(referenceXMLFilename); - auto doseStatisticsDefaultExpected = readerDefaultExpected.generateDoseStatistic(); - io::other::DoseStatisticsXMLReader readerDefaultActual(defaultOutputFilename); - auto doseStatisticsDefaultActual = readerDefaultActual.generateDoseStatistic(); - CHECK(checkEqualDoseStatistic(doseStatisticsDefaultExpected, doseStatisticsDefaultActual)); + io::other::DoseStatisticsXMLReader readerDefaultExpected(referenceXMLFilename); + auto doseStatisticsDefaultExpected = readerDefaultExpected.generateDoseStatistic(); + io::other::DoseStatisticsXMLReader readerDefaultActual(defaultOutputFilename); + auto doseStatisticsDefaultActual = readerDefaultActual.generateDoseStatistic(); - io::other::DoseStatisticsXMLReader readerComplexExpected(complexOutputFilename); - auto doseStatisticsComplexExpected = readerComplexExpected.generateDoseStatistic(); - io::other::DoseStatisticsXMLReader readerComplexActual(referenceXMLComplexFilename); - auto doseStatisticsComplexActual = readerComplexActual.generateDoseStatistic(); + CHECK(checkEqualDoseStatistic(doseStatisticsDefaultExpected, doseStatisticsDefaultActual)); - CHECK(checkEqualDoseStatistic(doseStatisticsComplexExpected, doseStatisticsComplexActual)); + io::other::DoseStatisticsXMLReader readerComplexExpected(complexOutputFilename); + auto doseStatisticsComplexExpected = readerComplexExpected.generateDoseStatistic(); + io::other::DoseStatisticsXMLReader readerComplexActual(referenceXMLComplexFilename); + auto doseStatisticsComplexActual = readerComplexActual.generateDoseStatistic(); - //check DVH files - io::other::DVHXMLFileReader xmlDVHDefaultReaderActual(defaultDVHOutputFilename); - DVHPointer defaultDVHActual = xmlDVHDefaultReaderActual.generateDVH(); + CHECK(checkEqualDoseStatistic(doseStatisticsComplexExpected, doseStatisticsComplexActual)); - io::other::DVHXMLFileReader xmlDVHDefaultReaderExpected(referenceDVHXMLFilename); - DVHPointer defaultDVHExpected = xmlDVHDefaultReaderExpected.generateDVH(); - CHECK(checkEqualDVH(defaultDVHActual, defaultDVHExpected)); + //check DVH files + io::other::DVHXMLFileReader xmlDVHDefaultReaderActual(defaultDVHOutputFilename); + DVHPointer defaultDVHActual = xmlDVHDefaultReaderActual.generateDVH(); + + io::other::DVHXMLFileReader xmlDVHDefaultReaderExpected(referenceDVHXMLFilename); + DVHPointer defaultDVHExpected = xmlDVHDefaultReaderExpected.generateDVH(); + CHECK(checkEqualDVH(defaultDVHActual, defaultDVHExpected)); //delete file again CHECK_EQUAL(std::remove(defaultOutputFilename.c_str()), 0); CHECK_EQUAL(std::remove(defaultDVHOutputFilename.c_str()), 0); CHECK_EQUAL(std::remove(complexOutputFilename.c_str()), 0); RETURN_AND_REPORT_TEST_SUCCESS; } } //namespace testing } //namespace rttb diff --git a/testing/apps/VoxelizerTool/CMakeLists.txt b/testing/apps/VoxelizerTool/CMakeLists.txt index e966337..15047d2 100644 --- a/testing/apps/VoxelizerTool/CMakeLists.txt +++ b/testing/apps/VoxelizerTool/CMakeLists.txt @@ -1,30 +1,30 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(VoxelizerTool_TESTS ${EXECUTABLE_OUTPUT_PATH}/rttbVoxelizerToolTests) SET(TEST_DATA_ROOT ${RTTBTesting_SOURCE_DIR}/data) SET(TEST_DATA ${RTToolbox_BINARY_DIR}/Testing/apps/VoxelizerTool) IF (WIN32) SET(VOXELIZERTOOL_EXE "VoxelizerTool") ELSE (WIN32) SET(VOXELIZERTOOL_EXE "./VoxelizerTool") ENDIF (WIN32) SET(STRUCT_FILE "${TEST_DATA_ROOT}/StructureSet/DICOM/RS1.3.6.1.4.1.2452.6.841242143.1311652612.1170940299.4217870819.dcm") SET(REFERENCE_FILE "${TEST_DATA_ROOT}/Dose/DICOM/ConstantTwo.dcm") #----------------------------------------------------------------------------- -ADD_TEST(rttbVoxelizerToolIncorrectCommandsTest ${VoxelizerTool_TESTS} VoxelizerToolIncorrectCommandsTest +ADD_TEST(VoxelizerToolIncorrectCommandsTest ${VoxelizerTool_TESTS} VoxelizerToolIncorrectCommandsTest "${VOXELIZERTOOL_EXE}" ${STRUCT_FILE} "${TEST_DATA_ROOT}/StructureSet/DICOM/Wrong_Data_Struct_file.dicom" ${REFERENCE_FILE} "${TEST_DATA_ROOT}/Dose/DICOM/Wrong_Reference_file.dicom" "Rueckenmark" "blabla") -ADD_TEST(rttbVoxelizerToolVoxelizerAllStructsTest ${VoxelizerTool_TESTS} VoxelizerToolVoxelizerAllStructsTest +ADD_TEST(VoxelizerToolVoxelizerAllStructsTest ${VoxelizerTool_TESTS} VoxelizerToolVoxelizerAllStructsTest "${VOXELIZERTOOL_EXE}" ${TEST_DATA} ${STRUCT_FILE} ${REFERENCE_FILE} ) -ADD_TEST(rttbVoxelizerToolDifferentCommandsTest ${VoxelizerTool_TESTS} VoxelizerToolDifferentCommandsTest +ADD_TEST(VoxelizerToolDifferentCommandsTest ${VoxelizerTool_TESTS} VoxelizerToolDifferentCommandsTest "${VOXELIZERTOOL_EXE}" ${TEST_DATA} ${STRUCT_FILE} ${REFERENCE_FILE}) -ADD_TEST(rttbVoxelizerToolVoxelValueTest ${VoxelizerTool_TESTS} VoxelizerToolVoxelValue +ADD_TEST(VoxelizerToolVoxelValueTest ${VoxelizerTool_TESTS} VoxelizerToolVoxelValue "${VOXELIZERTOOL_EXE}" ${TEST_DATA} ${STRUCT_FILE} ${REFERENCE_FILE} "Leber") -RTTB_CREATE_TEST_MODULE(RTTBVoxelizerTool PACKAGE_DEPENDS Litmus ITK BoostBinaries) +RTTB_CREATE_APPLICATION_TESTS(VoxelizerTool PACKAGE_DEPENDS Litmus ITK BoostBinaries) diff --git a/testing/core/CMakeLists.txt b/testing/core/CMakeLists.txt index 2e617db..c65b1be 100644 --- a/testing/core/CMakeLists.txt +++ b/testing/core/CMakeLists.txt @@ -1,28 +1,29 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(CORE_TESTS ${EXECUTABLE_OUTPUT_PATH}/rttbCoreTests) SET(CORE_HEADER_TEST ${EXECUTABLE_OUTPUT_PATH}/rttbCoreHeaderTest) SET(TEST_DATA_ROOT ${RTTBTesting_SOURCE_DIR}/data) SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) #----------------------------------------------------------------------------- ADD_TEST(GeometricInfoTest ${CORE_TESTS} GeometricInfoTest) ADD_TEST(MaskVoxelTest ${CORE_TESTS} MaskVoxelTest) ADD_TEST(GenericDoseIteratorTest ${CORE_TESTS} GenericDoseIteratorTest) ADD_TEST(GenericMaskedDoseIteratorTest ${CORE_TESTS} GenericMaskedDoseIteratorTest) ADD_TEST(DVHCalculatorTest ${CORE_TESTS} DVHCalculatorTest) ADD_TEST(DVHTest ${CORE_TESTS} DVHTest) ADD_TEST(DVHSetTest ${CORE_TESTS} DVHSetTest) ADD_TEST(StructureTest ${CORE_TESTS} StructureTest) ADD_TEST(StrVectorStructureSetGeneratorTest ${CORE_TESTS} StrVectorStructureSetGeneratorTest) - RTTB_CREATE_TEST_MODULE(rttbCore DEPENDS RTTBCore PACKAGE_DEPENDS Boost Litmus) + + diff --git a/testing/core/DummyDoseAccessor.h b/testing/core/DummyDoseAccessor.h index f73fea2..6c47856 100644 --- a/testing/core/DummyDoseAccessor.h +++ b/testing/core/DummyDoseAccessor.h @@ -1,80 +1,82 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #ifndef __DUMMY_DOSE_ACCESSOR_H #define __DUMMY_DOSE_ACCESSOR_H #include +#include + #include "rttbAccessorWithGeoInfoBase.h" #include "rttbGeometricInfo.h" #include "rttbBaseType.h" namespace rttb { namespace testing { /*! @class DummyDoseAccessor @brief A dummy DoseAccessor for testing filled with random dose values between 0 and 100. The default grid size is [11,10,5] */ class DummyDoseAccessor: public core::AccessorWithGeoInfoBase { private: /*! vector of dose data(absolute Gy dose/doseGridScaling)*/ std::vector doseData; IDType _doseUID; public: ~DummyDoseAccessor(); /*! @brief A dummy DoseAccessor for testing filled with random dose values between 0 and 100. The default grid size is [11,10,5] */ DummyDoseAccessor(); /*! @brief Constructor. Initialisation of dose with a given vector. */ DummyDoseAccessor(const std::vector& aDoseVector, const core::GeometricInfo& geoInfo); const std::vector* getDoseVector() const { return &doseData; }; GenericValueType getValueAt(const VoxelGridID aID) const; GenericValueType getValueAt(const VoxelGridIndex3D& aIndex) const; const IDType getUID() const { return _doseUID; }; }; } } #endif diff --git a/testing/examples/CMakeLists.txt b/testing/examples/CMakeLists.txt index b12fbef..69c19ed 100644 --- a/testing/examples/CMakeLists.txt +++ b/testing/examples/CMakeLists.txt @@ -1,29 +1,33 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(CORE_TEST_EXAMPLES ${EXECUTABLE_OUTPUT_PATH}/rttbExamplesTests) SET(TEST_DATA_ROOT ${RTTBTesting_SOURCE_DIR}/data) SET(TEMP ${RTTBTesting_BINARY_DIR}/Temporary) #----------------------------------------------------------------------------- ADD_TEST(RTBioModelExampleTest ${CORE_TEST_EXAMPLES} RTBioModelExampleTest "${TEST_DATA_ROOT}/DVH/Text/dvh_PTV_HIT.txt" "${TEST_DATA_ROOT}/DVH/Text/dvh_test_HT1.txt" "${TEST_DATA_ROOT}/DVH/Text/dvh_test_HT2.txt" "${TEST_DATA_ROOT}/DVH/Text/dvh_test_HT3.txt" "${TEST_DATA_ROOT}/DVH/Text/dvh_test_TV.txt" "${TEST_DATA_ROOT}/DVH/Text/dvh_virtuos_diff_trunk6.txt" "${TEST_DATA_ROOT}/DVH/Text/dvh_virtuos_diff_trunk8.txt") ADD_TEST(RTDoseIndexTest ${CORE_TEST_EXAMPLES} RTDoseIndexTest "${TEST_DATA_ROOT}/DVH/Text/dvh_test_TV.txt" "${TEST_DATA_ROOT}/DVH/Text/dvh_test_HT1.txt" "${TEST_DATA_ROOT}/DVH/Text/dvh_test_HT2.txt" "${TEST_DATA_ROOT}/DVH/Text/dvh_test_HT3.txt") ADD_TEST(RTDoseStatisticsDicomTest ${CORE_TEST_EXAMPLES} RTDoseStatisticsDicomTest "${TEST_DATA_ROOT}/Dose/DICOM/ConstantTwo_withDoseGridScaling.dcm") ADD_TEST(RTDVHTest ${CORE_TEST_EXAMPLES} RTDVHTest "${TEST_DATA_ROOT}/DVH/Text/dvh_test.txt") ADD_TEST(RTBioModelScatterPlotExampleTest ${CORE_TEST_EXAMPLES} RTBioModelScatterPlotExampleTest "${TEST_DATA_ROOT}/DVH/Text/dvh_PTV_HIT.txt" "${TEST_DATA_ROOT}/DVH/Text/dvh_test_HT1.txt" "${TEST_DATA_ROOT}/DVH/Text/dvh_test_TV.txt") -RTTB_CREATE_TEST_MODULE(rttbExamples DEPENDS RTTBCore RTTBAlgorithms RTTBMasks RTTBBoostMask RTTBIndices RTTBDicomIO RTTBITKIO RTTBOtherIO RTTBModels PACKAGE_DEPENDS Litmus) \ No newline at end of file +RTTB_CREATE_TEST_MODULE(rttbExamples DEPENDS RTTBCore RTTBAlgorithms RTTBMasks RTTBBoostMask RTTBIndices RTTBDicomIO RTTBITKIO RTTBOtherIO RTTBModels PACKAGE_DEPENDS Litmus) + +IF (NOT WIN32) + target_compile_features(rttbExamplesTests PRIVATE cxx_auto_type cxx_nullptr cxx_override) +ENDIF() diff --git a/testing/interpolation/InterpolationMatchPointTransformation/CMakeLists.txt b/testing/interpolation/InterpolationMatchPointTransformation/CMakeLists.txt index f2be70a..3794d3e 100644 --- a/testing/interpolation/InterpolationMatchPointTransformation/CMakeLists.txt +++ b/testing/interpolation/InterpolationMatchPointTransformation/CMakeLists.txt @@ -1,17 +1,22 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(INTERPOLATION_MP_TRANSFORMATION_TESTS ${EXECUTABLE_OUTPUT_PATH}/rttbInterpolationMPTransformationTests) SET(TEST_DATA_ROOT ${RTTBTesting_SOURCE_DIR}/data) SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) #----------------------------------------------------------------------------- ADD_TEST(SimpleMappableDoseAccessorWithMatchPointTest ${INTERPOLATION_MP_TRANSFORMATION_TESTS} SimpleMappableDoseAccessorWithMatchPointTest "${TEST_DATA_ROOT}/Dose/DICOM/ConstantTwo.dcm" "${TEST_DATA_ROOT}/Dose/DICOM/LinearIncreaseX.dcm") RTTB_CREATE_TEST_MODULE(rttbInterpolationMPTransformation DEPENDS RTTBInterpolation RTTBInterpolationMatchPointTransformation RTTBDicomIO PACKAGE_DEPENDS Litmus MatchPoint) + +IF (NOT WIN32) + target_compile_features(rttbInterpolationMPTransformationTests PRIVATE cxx_auto_type cxx_nullptr cxx_override) + set(CMAKE_CXX_FLAGS "-fpermissive") +ENDIF() diff --git a/testing/io/models/ModelsIOTest.cpp b/testing/io/models/ModelsIOTest.cpp index d0cc7c7..415437f 100644 --- a/testing/io/models/ModelsIOTest.cpp +++ b/testing/io/models/ModelsIOTest.cpp @@ -1,139 +1,136 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // (c) Copyright 2007, DKFZ, Heidelberg, Germany // ALL RIGHTS RESERVED // // THIS FILE CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION OF DKFZ. // ANY DUPLICATION, MODIFICATION, DISTRIBUTION, OR // DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY PROHIBITED // WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF DKFZ. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1221 $ (last changed revision) // @date $Date: 2015-12-01 13:43:31 +0100 (Di, 01 Dez 2015) $ (last change date) // @author zhangl (last changed by) // @author *none* (Reviewer) // @author zhangl (Programmer) // // Subversion HeadURL: $HeadURL: http://sidt-hpc1/dkfz_repository/NotMeVisLab/SIDT/RTToolbox/trunk/testing/core/DVHCalculatorTest.cpp $ */ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests - - - +#include #include "litCheckMacros.h" #include "rttbBioModel.h" #include "rttbTCPLQModel.h" #include "rttbNTCPLKBModel.h" #include #include #include "boost/filesystem.hpp" #include "rttbModelXMLWriter.h" namespace rttb { namespace testing { static std::string readFile(const std::string& filename); int ModelsIOTest(int argc, char* argv[]) { std::string expectedxmlfilenametcpleq; std::string expectedxmlfilenamentcplk; if (argc > 2){ expectedxmlfilenametcpleq = argv[1]; expectedxmlfilenamentcplk = argv[2]; } typedef core::DVH::DataDifferentialType DataDifferentialType; PREPARE_DEFAULT_TEST_REPORTING; //generate artificial DVH and corresponding statistical values DoseTypeGy binSize = DoseTypeGy(0.1); DoseVoxelVolumeType voxelVolume = 8; DataDifferentialType aDataDifferential; DoseCalcType value = 0; DVHVoxelNumber numberOfVoxels = 0; // creat default values for (int i = 0; i < 98; i++) { value = 0; numberOfVoxels += value; aDataDifferential.push_back(value); } aDataDifferential.push_back(10); aDataDifferential.push_back(20); const IDType structureID = "myStructure"; const IDType doseID = "myDose"; const IDType voxelizationID = "myVoxelization"; core::DVH::DVHPointer dvhPtr = boost::make_shared(aDataDifferential, binSize, voxelVolume, structureID, doseID, voxelizationID); //test TCP LQ Model models::BioModelParamType alpha = 0.35; models::BioModelParamType beta = 0.023333333333333; models::BioModelParamType roh = 10000000; int numFractions = 8; boost::shared_ptr tcplq = boost::make_shared(dvhPtr, roh, numFractions, alpha / beta, alpha, 0.08); std::string filename = "BioModeltcpleqIOTest.xml"; rttb::io::models::ModelXMLWriter writer = rttb::io::models::ModelXMLWriter(filename, tcplq, false); CHECK_NO_THROW(writer.writeModel()); CHECK_EQUAL(boost::filesystem::exists(filename), true); std::string defaultAsIs = readFile(filename); std::string defaultExpected = readFile(expectedxmlfilenametcpleq); CHECK_EQUAL(defaultAsIs, defaultExpected); CHECK_EQUAL(std::remove(filename.c_str()), 0); - //test NTCPLKBModel models::BioModelParamType aVal = 10; models::BioModelParamType mVal = 0.16; models::BioModelParamType d50Val = 35; boost::shared_ptr ntcplk= boost::make_shared(dvhPtr, d50Val, mVal, aVal); filename = "BioModelntcplkIOTest.xml"; rttb::io::models::ModelXMLWriter writer2 = rttb::io::models::ModelXMLWriter(filename, ntcplk); CHECK_NO_THROW(writer2.writeModel()); CHECK_EQUAL(boost::filesystem::exists(filename), true); defaultAsIs = readFile(filename); defaultExpected = readFile(expectedxmlfilenamentcplk); CHECK_EQUAL(defaultAsIs, defaultExpected); CHECK_EQUAL(std::remove(filename.c_str()), 0); std::string dvhFilename = "dvhfor" + ntcplk->getModelType()+".xml"; CHECK_EQUAL(std::remove(dvhFilename.c_str()), 0); RETURN_AND_REPORT_TEST_SUCCESS; } std::string readFile(const std::string& filename) { std::ifstream fileStream(filename.c_str()); std::string content((std::istreambuf_iterator(fileStream)), (std::istreambuf_iterator())); return content; } } -} \ No newline at end of file +} diff --git a/testing/masks/boost/BoostMaskTest.cpp b/testing/masks/boost/BoostMaskTest.cpp index 5231a26..22362a3 100644 --- a/testing/masks/boost/BoostMaskTest.cpp +++ b/testing/masks/boost/BoostMaskTest.cpp @@ -1,243 +1,242 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1127 $ (last changed revision) // @date $Date: 2015-10-01 13:33:33 +0200 (Do, 01 Okt 2015) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include #include #include "litCheckMacros.h" #include "rttbBaseType.h" #include "../../core/DummyStructure.h" #include "../../core/DummyDoseAccessor.h" #include "rttbDicomDoseAccessor.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomFileStructureSetGenerator.h" #include "rttbDicomFileStructureSetGenerator.h" #include "rttbGenericDoseIterator.h" #include "rttbDVHCalculator.h" #include "rttbGenericMaskedDoseIterator.h" #include "rttbBoostMask.h" #include "rttbBoostMaskAccessor.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace testing { /*! @brief BoostMaskRedesignTest. 1) test constructors 2) test getRelevantVoxelVector 3) test getMaskAt */ int BoostMaskTest(int argc, char* argv[]) { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef core::DVHCalculator::DoseIteratorPointer DoseIteratorPointer; typedef core::StructureSetGeneratorInterface::StructureSetPointer StructureSetPointer; typedef core::GenericMaskedDoseIterator::MaskAccessorPointer MaskAccessorPointer; typedef core::Structure::StructTypePointer StructTypePointer; PREPARE_DEFAULT_TEST_REPORTING; // generate test dose. geometric info: patient position (-25, -2, 35), center of the 1st.voxel boost::shared_ptr spTestDoseAccessor = boost::make_shared(); boost::shared_ptr geometricPtr = boost::make_shared (spTestDoseAccessor->getGeometricInfo()); DummyStructure myStructGenerator(spTestDoseAccessor->getGeometricInfo()); //generate test structure. contours are (-20,0.5,38.75); (-12.5,0.5,38.75); (-12.5,10.5,38.75); (-20,10.5,38.75); //(-20, 0.5, 41.25); (-12.5, 0.5, 41.25); (-12.5, 10.5, 41.25); (-20, 10.5, 41.25); core::Structure myTestStruct = myStructGenerator.CreateRectangularStructureCentered(2,3); StructTypePointer spMyStruct = boost::make_shared(myTestStruct); //generate test structure 2. contours are (-20,0.5,38.75); (-12.5,0.5,38.75); (-12.5,10.5,38.75); (-20,10.5,38.75); //(-20, 0.5, 40); (-12.5, 0.5, 40); (-12.5, 10.5, 40); (-20, 10.5, 40); core::Structure myTestStruct2 = myStructGenerator.CreateRectangularStructureCenteredContourPlaneThicknessNotEqualDosePlaneThickness(2); StructTypePointer spMyStruct2 = boost::make_shared(myTestStruct2); - //1) test BoostMask & BoostMaskAccessor constructor CHECK_NO_THROW(rttb::masks::boost::BoostMask(geometricPtr, spMyStruct)); rttb::masks::boost::BoostMask boostMask = rttb::masks::boost::BoostMask( geometricPtr, spMyStruct); CHECK_NO_THROW(rttb::masks::boost::BoostMaskAccessor(spMyStruct, spTestDoseAccessor->getGeometricInfo(), true)); rttb::masks::boost::BoostMaskAccessor boostMaskAccessor(spMyStruct, spTestDoseAccessor->getGeometricInfo(), true); //2) test getRelevantVoxelVector CHECK_NO_THROW(boostMask.getRelevantVoxelVector()); CHECK_NO_THROW(boostMaskAccessor.getRelevantVoxelVector()); //3) test getMaskAt const VoxelGridIndex3D inMask1(2, 1, 2); //corner between two contours slice -> volumeFraction = 0.25 const VoxelGridIndex3D inMask2(3, 4, 2); //inside between two contours slice ->volumeFraction = 1 const VoxelGridIndex3D inMask3(4, 5, 2); //side between two contours slice -> volumeFraction = 0.5 const VoxelGridIndex3D inMask4(2, 1, 1); //corner on the first contour slice -> volumeFraction = 0.25/2 = 0.125 const VoxelGridIndex3D inMask5(2, 1, 3); //corner on the last contour slice -> volumeFraction = 0.25/2 = 0.125 const VoxelGridIndex3D inMask6(3, 4, 1); //inside on the first contour slice ->volumeFraction = 1 /2 = 0.5 const VoxelGridIndex3D outMask1(7, 5, 4); const VoxelGridIndex3D outMask2(2, 1, 0); const VoxelGridIndex3D outMask3(2, 1, 4); VoxelGridID testId; double errorConstant = 1e-7; core::MaskVoxel tmpMV1(0), tmpMV2(0); CHECK(boostMaskAccessor.getMaskAt(inMask1, tmpMV1)); geometricPtr->convert(inMask1, testId); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_CLOSE(0.25, tmpMV1.getRelevantVolumeFraction(), errorConstant); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor.getMaskAt(inMask2, tmpMV1)); CHECK(geometricPtr->convert(inMask2, testId)); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(1, tmpMV1.getRelevantVolumeFraction()); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor.getMaskAt(inMask3, tmpMV1)); CHECK(geometricPtr->convert(inMask3, testId)); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_CLOSE(0.5, tmpMV1.getRelevantVolumeFraction(), errorConstant); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor.getMaskAt(inMask4, tmpMV1)); CHECK(geometricPtr->convert(inMask4, testId)); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_CLOSE(0.125, tmpMV1.getRelevantVolumeFraction(), errorConstant); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor.getMaskAt(inMask5, tmpMV1)); CHECK(geometricPtr->convert(inMask5, testId)); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_CLOSE(0.125, tmpMV1.getRelevantVolumeFraction(), errorConstant); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor.getMaskAt(inMask6, tmpMV1)); CHECK(geometricPtr->convert(inMask6, testId)); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_CLOSE(0.5, tmpMV1.getRelevantVolumeFraction(), errorConstant); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(!boostMaskAccessor.getMaskAt(outMask1, tmpMV1)); CHECK(geometricPtr->convert(outMask1, testId)); CHECK(!boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); CHECK(!boostMaskAccessor.getMaskAt(outMask2, tmpMV1)); CHECK(geometricPtr->convert(outMask2, testId)); CHECK(!boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); CHECK(!boostMaskAccessor.getMaskAt(outMask3, tmpMV1)); CHECK(geometricPtr->convert(outMask3, testId)); CHECK(!boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); rttb::masks::boost::BoostMask boostMask2 = rttb::masks::boost::BoostMask( geometricPtr, spMyStruct2); CHECK_NO_THROW(boostMask2.getRelevantVoxelVector()); rttb::masks::boost::BoostMaskAccessor boostMaskAccessor2(spMyStruct2, spTestDoseAccessor->getGeometricInfo(), true); CHECK_NO_THROW(boostMaskAccessor2.getRelevantVoxelVector()); CHECK(boostMaskAccessor2.getMaskAt(inMask1, tmpMV1)); geometricPtr->convert(inMask1, testId); CHECK(boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); //corner, the first contour weight 0.25, the second contour weights 0.5 -> volumeFraction = 0.25*0.25 + 1.25*0.5 = 0.1875 CHECK_CLOSE(0.1875, tmpMV1.getRelevantVolumeFraction(), errorConstant); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor2.getMaskAt(inMask2, tmpMV1)); CHECK(geometricPtr->convert(inMask2, testId)); CHECK(boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); //inside, the first contour weight 0.25, the second contour weights 0.5 -> ->volumeFraction = 1*0.25 + 1*0.5 = 0.75 CHECK_EQUAL(0.75, tmpMV1.getRelevantVolumeFraction()); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor2.getMaskAt(inMask3, tmpMV1)); CHECK(geometricPtr->convert(inMask3, testId)); CHECK(boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); //side the first contour weight 0.25, the second contour weights 0.5 -> ->volumeFraction = 0.5*0.25 + 0.5*0.5 = 0.75 CHECK_CLOSE(0.375, tmpMV1.getRelevantVolumeFraction(), errorConstant); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor2.getMaskAt(inMask4, tmpMV1)); CHECK(geometricPtr->convert(inMask4, testId)); CHECK(boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); //corner on the first contour slice, weight 0.25 -> volumeFraction = 0.25*0.25 = 0.0625 CHECK_CLOSE(0.0625, tmpMV1.getRelevantVolumeFraction(), errorConstant); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor2.getMaskAt(inMask6, tmpMV1)); CHECK(geometricPtr->convert(inMask6, testId)); CHECK(boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); //inside on the first contour slice, weight 0.25 ->volumeFraction = 1 * 0.25 = 0.25 CHECK_CLOSE(0.25, tmpMV1.getRelevantVolumeFraction(), errorConstant); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(!boostMaskAccessor2.getMaskAt(outMask1, tmpMV1)); CHECK(geometricPtr->convert(outMask1, testId)); CHECK(!boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); //CHECK_EQUAL(testId,tmpMV1.getVoxelGridID()); -> return value will not be valid outside the mask CHECK(!boostMaskAccessor2.getMaskAt(outMask2, tmpMV1)); CHECK(geometricPtr->convert(outMask2, testId)); CHECK(!boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); //CHECK_EQUAL(testId,tmpMV1.getVoxelGridID()); -> return value will not be valid outside the mask CHECK(!boostMaskAccessor2.getMaskAt(outMask3, tmpMV1)); CHECK(geometricPtr->convert(outMask3, testId)); CHECK(!boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); //CHECK_EQUAL(testId,tmpMV1.getVoxelGridID()); -> return value will not be valid outside the mask RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/masks/boost/CMakeLists.txt b/testing/masks/boost/CMakeLists.txt index 051b1e3..c7d0eea 100644 --- a/testing/masks/boost/CMakeLists.txt +++ b/testing/masks/boost/CMakeLists.txt @@ -1,20 +1,22 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(Boost_Mask_TESTS ${EXECUTABLE_OUTPUT_PATH}/rttbBoostMaskTests) SET(TEST_DATA_ROOT ${RTTBTesting_SOURCE_DIR}/data) SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) #----------------------------------------------------------------------------- ADD_TEST(BoostMaskTest ${Boost_Mask_TESTS} BoostMaskTest ) -RTTB_CREATE_TEST_MODULE(rttbBoostMask DEPENDS RTTBDicomIO RTTBMasks RTTBBoostMask PACKAGE_DEPENDS Boost BoostBinaries Litmus DCMTK) - +RTTB_CREATE_TEST_MODULE(rttbBoostMask DEPENDS RTTBDicomIO RTTBMasks RTTBBoostMask PACKAGE_DEPENDS BoostBinaries Litmus DCMTK) +IF (NOT WIN32) + set(CMAKE_CXX_FLAGS "-std=c++11") +ENDIF() diff --git a/testing/masks/legacy/CMakeLists.txt b/testing/masks/legacy/CMakeLists.txt index 1ef9f98..629be2b 100644 --- a/testing/masks/legacy/CMakeLists.txt +++ b/testing/masks/legacy/CMakeLists.txt @@ -1,23 +1,23 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(OTB_MASK_TESTS ${EXECUTABLE_OUTPUT_PATH}/rttbOTBMaskTests) SET(TEST_DATA_ROOT ${RTTBTesting_SOURCE_DIR}/data) SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) #----------------------------------------------------------------------------- ADD_TEST(OTBMaskAccessorTest ${OTB_MASK_TESTS} OTBMaskAccessorTest ) ADD_TEST(BoostMaskLegacyTest ${OTB_MASK_TESTS} BoostMaskLegacyTest ) -RTTB_CREATE_TEST_MODULE(rttbOTBMask DEPENDS RTTBMasks RTTBOTBMask PACKAGE_DEPENDS Litmus DCMTK boost) +RTTB_CREATE_TEST_MODULE(rttbOTBMask DEPENDS RTTBMasks RTTBOTBMask PACKAGE_DEPENDS Litmus DCMTK Boost) diff --git a/testing/models/CMakeLists.txt b/testing/models/CMakeLists.txt index 24860b0..0b18fe0 100644 --- a/testing/models/CMakeLists.txt +++ b/testing/models/CMakeLists.txt @@ -1,22 +1,25 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(MODELS_TESTS ${EXECUTABLE_OUTPUT_PATH}/rttbModelTests) SET(MODELS_HEADER_TEST ${EXECUTABLE_OUTPUT_PATH}/rttbModelsHeaderTest) SET(TEST_DATA_ROOT ${RTTBTesting_SOURCE_DIR}/data) SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) #----------------------------------------------------------------------------- ADD_TEST(BioModelTest ${MODELS_TESTS} BioModelTest) ADD_TEST(BioModelScatterPlotTest ${MODELS_TESTS} BioModelScatterPlotTest) ADD_TEST(DvhBasedModelsTest ${MODELS_TESTS} DvhBasedModelsTest) ADD_TEST(LQModelAccessorTest ${MODELS_TESTS} LQModelAccessorTest "${TEST_DATA_ROOT}/Dose/DICOM/ConstantTwo.dcm" "${TEST_DATA_ROOT}/Dose/DICOM/LinearIncreaseX.dcm") RTTB_CREATE_TEST_MODULE(rttbModel DEPENDS RTTBModels RTTBDicomIO PACKAGE_DEPENDS Boost Litmus DCMTK) +IF (NOT WIN32) + target_compile_features(rttbModelTests PRIVATE cxx_auto_type cxx_nullptr cxx_override) +ENDIF() diff --git a/testing/validation/CMakeLists.txt b/testing/validation/CMakeLists.txt index ff2c50f..1a19bcc 100644 --- a/testing/validation/CMakeLists.txt +++ b/testing/validation/CMakeLists.txt @@ -1,27 +1,31 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(CORE_TEST_VALIDATION ${EXECUTABLE_OUTPUT_PATH}/rttbValidationTests) SET(TEST_DATA_ROOT ${RTTBTesting_SOURCE_DIR}/data) SET(TEMP ${RTTBTesting_BINARY_DIR}/Temporary) #----------------------------------------------------------------------------- ADD_TEST(VoxelizationDVHComparisonTest ${CORE_TEST_VALIDATION} VoxelizationDVHComparisonTest "${TEST_DATA_ROOT}/StructureSet/DICOM/RS1.3.6.1.4.1.2452.6.841242143.1311652612.1170940299.4217870819.dcm" "${TEST_DATA_ROOT}/Dose/DICOM/LinearIncrease3D.dcm" "${TEST_DATA_ROOT}/DVH/XML/1.3.6.1.4.1.2452.6.2037938358.1234393433.864109958.30410275/OTBMask/" "${TEST_DATA_ROOT}/DVH/XML/1.3.6.1.4.1.2452.6.2037938358.1234393433.864109958.30410275/BoostMask_LEGACY/" "${RTTBTesting_BINARY_DIR}/validation/1.3.6.1.4.1.2452.6.2037938358.1234393433.864109958.30410275/BoostMask/") ADD_TEST(VoxelizationValidationTest ${CORE_TEST_VALIDATION} VoxelizationValidationTest "${TEST_DATA_ROOT}/StructureSet/DICOM/RS1.3.6.1.4.1.2452.6.841242143.1311652612.1170940299.4217870819.dcm" "${TEST_DATA_ROOT}/Dose/DICOM/LinearIncrease3D.dcm" "${TEST_DATA_ROOT}/Mask/1.3.6.1.4.1.2452.6.2037938358.1234393433.864109958.30410275/BoostMask/" "${TEST_DATA_ROOT}/Mask/1.3.6.1.4.1.2452.6.2037938358.1234393433.864109958.30410275/OTBMask/") RTTB_CREATE_TEST_MODULE(rttbValidation DEPENDS RTTBCore RTTBBoostMask RTTBDicomIO RTTBITKIO RTTBOtherIO PACKAGE_DEPENDS Litmus ITK) +IF (NOT WIN32) + target_compile_features(rttbValidationTests PRIVATE cxx_auto_type cxx_nullptr cxx_override) + set(CMAKE_CXX_FLAGS "-fpermissive") +ENDIF() diff --git a/utilities/ArgumentParsingLib/ArgumentParsingLib.tar.gz b/utilities/ArgumentParsingLib/ArgumentParsingLib.tar.gz index 01dffb5..3b6e1ff 100644 Binary files a/utilities/ArgumentParsingLib/ArgumentParsingLib.tar.gz and b/utilities/ArgumentParsingLib/ArgumentParsingLib.tar.gz differ diff --git a/utilities/ArgumentParsingLib/main/CmdLineParserBase.h b/utilities/ArgumentParsingLib/main/CmdLineParserBase.h index d660c77..928358e 100644 --- a/utilities/ArgumentParsingLib/main/CmdLineParserBase.h +++ b/utilities/ArgumentParsingLib/main/CmdLineParserBase.h @@ -1,294 +1,294 @@ //------------------------------------------------------------------------ // Copyright(c) German Cancer Research Center(DKFZ), // Software Development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // // Authors: Sascha Diatschuk, Simon Strubel, Clemens Hentschke, Fabrizio Ciccarese //------------------------------------------------------------------------ #ifndef __CmdLineParserBase_h #define __CmdLineParserBase_h #include #include #include #include #include #include #include "XMLGenerator.h" #include #include #include #include namespace cmdlineparsing { /*! @brief Thrown if accessing parsed parameters fails. */ class AccessException : public std::runtime_error { public: AccessException(const std::string& what) : std::runtime_error(what.c_str()) {} }; /*! @brief Should be thrown if CmdLineParserBase::validateInput() fails. */ class InvalidConstraintException : public std::runtime_error { public: InvalidConstraintException(const std::string& what) : std::runtime_error(what.c_str()) {} }; /*! @brief Base class for command line parsing including parsing from XML or INI-style config files. @details Derive from this class, define your own arguments with CmdLineParserBase::addOption(), CmdLineParserBase::addOptionWithDefaultValue() and CmdLineParserBase::addPositionalOption() and call CmdLineParserBase::parse() after that to validate them. If the parsing completes without exceptions, you can access the parsed arguments with CmdLineParserBase::isSet() and CmdLineParserBase::get(). @note You can override CmdLineParserBase::validateInput() to further add custom validation (e.g. one int parameter mustn't be greater than the other one). @note You can override CmdLineParserBase::printHelp() to control how the help is displayed. @note The default parameters defined in this base class are "--help" (or "-h") and "--config-file " (or "-c "). If the given config file name ends in ".xml" it is parsed using cmdlineparsing::parseXML(), otherwise boost::parse_config_file() is used which expects INI-style parameter definitions. @note There is a sample file for each format (.xml and .cfg) in the test data folder. */ class CmdLineParserBase { public: /*! @brief Adds the four default parameters "--help" (or "-h"), "--config-file " (or "-c "), "--version" (or "-v"), "--xml" (or "-x") under the group "Generic Arguments". */ CmdLineParserBase(const std::string& programName, const std::string& version = "1.0", const std::string& programDescription="", const std::string& programContributor="DKFZ", const std::string& programCategory="Generic"); virtual ~CmdLineParserBase() {} /*! @brief Adds a new option to the option group with the given name. Adds a new option group if it doesn't exist yet. @param description The description for this parameter that's shown in the help text. @param shorthand The shorthand character for this option (e.g. 'h' for "--help"). Make sure you don't set the same character twice. @param required Whether this parameter is mandatory or optional. @param multitoken Whether this parameter supports an unlimited number of values (e.g. "-n 1 2 3"). @param composing Whether this parameter can be composed of the values given in the command line and those given in the config file (usually the command line overwrites config file parameter values). */ template void addOption(const std::string& name, const std::string& optionGroupName, const std::string& description, char shorthand = 0, bool required = false, bool multitoken = false, bool composing = false); // Despite the similar signature this function needs its own name (instead of // addOption). Otherwise the default value might be implicitly cast to boolean and // match one of the other addOption signatures. /*! @brief Add option with default value @param defaultValueRepresentation a string representation of the default value for the output in help (e.g. std::vector is not streamable, thus defaultValue can't be used in some cases) @see CmdLineParserBase::addOption() */ template void addOptionWithDefaultValue(const std::string& name, const std::string& optionGroupName, const std::string& description, const T& defaultValue, const std::string& defaultValueRepresentation = "", char shorthand = 0, bool required = false, bool multitoken = false, bool composing = false); void addInformationForXML(const std::string& name, XMLGenerator::paramType aType, double min = 0.0, double max = 100.0, double step = 1.0); void addInformationForXML(const std::string& name, XMLGenerator::paramType aType, const std::vector& vectorData); /*! @brief Non-generic version for arguments without values (e.g. "help"). @see CmdLineParserBase::addOption() */ void addOption(const std::string& name, const std::string& optionGroupName, const std::string& description, char shorthand = 0); /*! @brief Adds a positional option with the number of expected values. @note In order for a positional option to work you need to also add a regular option of the same name (using CmdLineParserBase::addOption() or CmdLineParserBase::addOptionWithDefaultValue()). This isn't done for you so you can decide which group it belongs to. @note The "usage" line in the "help" text is generated from the positional arguments. @param numArgs -1 means an unlimited number of values and only the very last positional option can have it. */ void addPositionalOption(const std::string& name, int numValues); /*! @brief Starts parsing the given command line arguments. @details Beforehand all custom options must have been defined. Afterwards, the parsed parameters can be accessed with CmdLineParserBase::isSet() and CmdLineParserBase::get(). Also calls CmdLineParserBase::validateInput(). */ void parse(int argc, const char* argv[]); /*! @brief Prints the default help to the standard output. The help text is generated from the option groups, regular options and positional options. @note Override this function to print your own help text. */ virtual void printHelp() const; /*! @brief Prints the default version information to the standard output. @note Override this function to print your own version information. */ virtual void printVersion() const; /*! @brief Prints the default xml information of parameters to the standard output. @note Override this function to print your own xml information. */ virtual void printXML() const; /*! @brief Gets called at the end of CmdLineParserBase::parse(). @note Override this function to implement your own input validation. E.g. if one integer parameter mustn't be greater than the other. */ virtual void validateInput() const = 0; std::unordered_map > getOptionsAsStringMap() const; /*! @brief Access the parsed parameters by name. @note CmdLineParserBase::parse() must complete successfully before calling this. @throws cmdlineparsing::AccessException If used before parsing has completed. E.g. because CmdLineParserBase::parse() threw an exception or because the help parameter was set or because CmdLineParserBase::parse() wasn't called at all. @throws cmdlineparsing::AccessException If parameter doesn't exist in parameter map. */ template T get(const std::string& name) const; /*! @brief Check if the parsed parameter with the given name was given. @note CmdLineParserBase::parse() must complete sucessfully before calling this. */ bool isSet(const std::string& name) const; const std::string OPTION_GROUP_GENERIC = "Generic Arguments"; const std::string OPTION_HELP = "help"; const std::string OPTION_VERSION = "version"; const std::string OPTION_XML = "xml"; const std::string OPTION_CONFIG_FILE = "config-file"; protected: // These option groups are protected so you can access them when overriding // printHelp() boost::program_options::options_description m_cmdLineOptions, m_configFileOptions; boost::program_options::positional_options_description m_positionalOptions; //Stores basic options for each argument (key is longFlag) (shortFlag, description, optionGroup, default value) std::unordered_map > m_baseOptionsMap; //Stores additional options for each argument (key is longFlag) (parameter type, minimum constraint, maximum constraint, step constraint, vector for string vector data) std::unordered_map > > m_additionalOptionsMap; std::string m_programCategory; std::string m_programName; std::string m_programDescription; std::string m_programVersion; std::string m_programContributor; private: CmdLineParserBase(const CmdLineParserBase&) = delete; void operator=(const CmdLineParserBase&) = delete; // Add option with typed value. Helper function to reduce duplicate code. template void addOption(const std::string& name, const std::string& optionGroupName, const std::string& description, char shorthand, const boost::program_options::typed_value* value); // Returns the option group with the given name or creates a new one and returns it // if it already exists. boost::program_options::options_description& getOrCreateOptionGroup( const std::string& optionGroupName); // Generate typed value. Helper function to reduce duplicate code. template boost::program_options::typed_value* generateTypedValue(bool required = false, bool multitoken = false, bool composing = false) const; - void CmdLineParserBase::findDuplicate(const std::unordered_map >& optionsMap, + void findDuplicate(const std::unordered_map >& optionsMap, const std::string& name, char shorthand) const; std::unordered_map > getOptions(const std::string& name) const; boost::program_options::variables_map m_varMap; // Stores whether the parsing was successful and arguments can be read via get(). bool m_success; // Multi-index container for the option groups. // This offers two different indices to the same collection: // - nameTag: sorted by name (necessary for finding existing option groups) // - orderTag: sorted by the order they were inserted in (necessary for displaying // them in the help in the order they were defined) // Boost's options_description already has a container for option groups, however, // it doesn't offer enough access to add options to existing groups. struct nameTag {}; struct orderTag {}; typedef std::pair OptionGroup; boost::multi_index_container < OptionGroup, boost::multi_index::indexed_by < boost::multi_index::random_access >, boost::multi_index::ordered_unique < boost::multi_index::tag, BOOST_MULTI_INDEX_MEMBER(OptionGroup, std::string, first) > > > m_optionGroupMap; }; } #ifndef CMDLINEPARSING_MANUAL_INSTANTIATION #include "CmdLineParserBase.tpp" #endif -#endif \ No newline at end of file +#endif