diff --git a/CMakeLists.txt b/CMakeLists.txt index b12d92b..97d30d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,292 +1,302 @@ #----------------------------------------------------------------------------- # This is the root RTToolbox CMakeList file. #----------------------------------------------------------------------------- PROJECT(RTToolbox) CMAKE_MINIMUM_REQUIRED(VERSION 3.1) # RTToolbox version number. SET(RTToolbox_VERSION_MAJOR "4") SET(RTToolbox_VERSION_MINOR "1") -SET(RTToolbox_VERSION_PATCH "1") +SET(RTToolbox_VERSION_PATCH "2") # 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) + # See https://cmake.org/cmake/help/v3.3/policy/CMP0062.html + CMAKE_POLICY(SET CMP0062 OLD) 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/RTToolboxConfig.cmake.in b/RTToolboxConfig.cmake.in index 7d83139..3d7aa84 100644 --- a/RTToolboxConfig.cmake.in +++ b/RTToolboxConfig.cmake.in @@ -1,38 +1,39 @@ #----------------------------------------------------------------------------- # # RTToolboxConfig.cmake - RTToolbox CMake configuration file for external projects. # # This file is configured by RTToolbox and used by the UseRTToolbox.cmake module # to load RTToolbox's settings for an external project. SET(RTToolbox_FOUND 1) # The RTToolbox source tree. SET(RTToolbox_SOURCE_DIR "@RTToolbox_SOURCE_DIR@") # The RTToolbox binary tree. SET(RTToolbox_BINARY_DIR "@RTToolbox_BINARY_DIR@") # The RTToolbox include file directories. SET(RTToolbox_INCLUDE_DIRS "@RTToolbox_INCLUDE_DIRS_CONFIG@") # The RTToolbox library directories. SET(RTToolbox_LIBRARY_DIRS "@RTToolbox_LIBRARY_DIRS_CONFIG@") # The RTToolbox version number SET(RTToolbox_VERSION_MAJOR "@RTToolbox_VERSION_MAJOR@") SET(RTToolbox_VERSION_MINOR "@RTToolbox_VERSION_MINOR@") SET(RTToolbox_VERSION_PATCH "@RTToolbox_VERSION_PATCH@") + # The location of the UseRTToolbox.cmake file. SET(RTToolbox_USE_FILE "@RTToolbox_USE_FILE@") # The location of the MatchPointTargets.cmake file. SET(RTToolbox_TARGETS_FILE "@RTToolbox_TARGETS_FILE@") # The RTToolbox library dependencies. IF(NOT RTToolbox_NO_LIBRARY_DEPENDS AND EXISTS "@RTToolbox_LIBRARY_DEPENDS_FILE@") INCLUDE("@RTToolbox_LIBRARY_DEPENDS_FILE@") ENDIF(NOT RTToolbox_NO_LIBRARY_DEPENDS AND EXISTS "@RTToolbox_LIBRARY_DEPENDS_FILE@") \ No newline at end of file diff --git a/RTToolboxConfigure.h.in b/RTToolboxConfigure.h.in index 34f0556..d8cf1c0 100644 --- a/RTToolboxConfigure.h.in +++ b/RTToolboxConfigure.h.in @@ -1,102 +1,104 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ SIDT RT Interface // // 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) // // Subversion HeadURL: $HeadURL: http://sidt-hpc1/dkfz_repository/NotMeVisLab/SIDT/RTToolbox/branch/restructure/RTToolboxConfigure.h.in $ */ //---------------------------------------------------------- // !!!EXPERIMENTAL CODE!!! // // This code may not be used for release. // Add #define SIDT_ENFORCE_MATURE_CODE to any release module // to ensure this policy. //---------------------------------------------------------- #ifdef SIDT_ENFORCE_MATURE_CODE #error “This code is marked as experimental code. It must not be used because this build enforces mature code.” #endif #ifndef SIDT_CONTAINS_EXPERIMENTAL_CODE #define SIDT_CONTAINS_EXPERIMENTAL_CODE 1 #endif /*! @def RTTB_BUILD_SHARED_LIBS * This define indicates if RTTB will be build as static library (define RTTB_STATIC) or as DLL (define RTTB_DLL). * By default RTTB_BUILD_SHARED_LIBS is not defined. */ #cmakedefine RTTB_BUILD_SHARED_LIBS #ifdef RTTB_BUILD_SHARED_LIBS #define RTTB_DLL #else #define RTTB_STATIC #endif #ifndef __RTTB_CONFIGURE_H #define __RTTB_CONFIGURE_H /*! @def RTTB_BUILD_SHARED_LIBS * This define indicates if RTTB will be build as static library (define RTTB_STATIC) or as DLL (define RTTB_DLL). * By default RTTB_BUILD_SHARED_LIBS is not defined. */ #cmakedefine RTTB_BUILD_SHARED_LIBS #ifdef RTTB_BUILD_SHARED_LIBS #define RTTB_DLL #else #define RTTB_STATIC #endif /*! @def RTTB_ENFORCE_MATURE_CODE * This define controls if RTToolbox should force the whole build to be mature code. * Mature code convention is part of the SIDT coding styles. * Projects that use RTToolbox are able to ensure with SIDT_ENFORCE_MATURE_CODE * that used code is guaranteed to be tested and reviewed regarding the strict * SIDT coding styles.\n * RTTB_ENFORCE_MATURE_CODE can be used to ensure that strictness when prebuilding * static or dynamic libraries. * @remark This definition should by configured via the advance options in CMake. */ #cmakedefine RTTB_ENFORCE_MATURE_CODE #ifdef RTTB_ENFORCE_MATURE_CODE #define SIDT_ENFORCE_MATURE_CODE #endif /*! @def RTTB_DISABLE_ITK_IO_FACTORY_AUTO_REGISTER * This define controls if RTToolbox should disable the auto * register functionality of the itk io factory, when RTToolbox * io reader and writer classes are used. * This is needed in cases where RTToolbox is build "dynamic" and * used in an application that also uses the ITK shared objects * under Windows systems (e.g. MITK). Loading and unloading RTToolbox * shared objects in such an application would lead to an corrupted * itk factory stack, because its implementation is not fail safe * in this scenario. * @remark This definition should by configured via the advance options in CMake. */ #cmakedefine RTTB_DISABLE_ITK_IO_FACTORY_AUTO_REGISTER #define RTTB_VERSION_MAJOR @RTToolbox_VERSION_MAJOR@ #define RTTB_VERSION_MINOR @RTToolbox_VERSION_MINOR@ #define RTTB_VERSION_PATCH @RTToolbox_VERSION_PATCH@ #define RTTB_VERSION_STRING "@RTToolbox_VERSION_STRING@" #define RTTB_FULL_VERSION_STRING "@RTToolbox_FULL_VERSION_STRING@" +#define RTTB_VIRTUOS_SUPPORT @RTToolbox_VIRTUOS_SUPPORT@ + #endif diff --git a/apps/BioModelCalc/BioModelCalcHelper.cpp b/apps/BioModelCalc/BioModelCalcHelper.cpp index b833eaf..69e7f30 100644 --- a/apps/BioModelCalc/BioModelCalcHelper.cpp +++ b/apps/BioModelCalc/BioModelCalcHelper.cpp @@ -1,152 +1,131 @@ // ----------------------------------------------------------------------- // 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) +// @version $Revision: 1374 $ (last changed revision) +// @date $Date: 2016-05-30 14:15:42 +0200 (Mo, 30 Mai 2016) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "BioModelCalcHelper.h" #include "boost/make_shared.hpp" #include "boost/shared_ptr.hpp" #include "rttbExceptionMacros.h" -#include "rttbVirtuosPlanFileDoseAccessorGenerator.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomHelaxFileDoseAccessorGenerator.h" #include "rttbITKImageFileAccessorGenerator.h" #include "rttbITKImageAccessorConverter.h" #include "rttbImageWriter.h" #include "rttbLQModelAccessor.h" rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::bioModelCalc::loadDose(const std::string& fileName, const rttb::apps::bioModelCalc::ApplicationData::LoadingStyleArgType& args) { rttb::core::DoseAccessorInterface::DoseAccessorPointer result; std::cout << std::endl << "read dose file... "; if (args.empty() || args[0] == "dicom") { std::cout << "use RTTB dicom IO... "; result = loadDicomDose(fileName); } else if (args[0] == "helax") { std::cout << "use RTTB Helax IO... "; result = loadHelaxDose(fileName); } else if (args[0] == "itk") { std::cout << "use RTTB itk IO... "; result = loadITKDose(fileName); } - else if (args[0] == "virtuos") - { - if (args.size() < 2) - { - rttbDefaultExceptionStaticMacro( << - "Cannot load virtuos dose. Plan file is missing. Specify plan file as 2nd io stlye argument."); - } - - std::cout << "use RTTB virtuos IO... " << std::endl; - std::cout << " virtuos plan file: " << args[1] << " ... "; - result = loadVirtuosDose(fileName, args[1]); - } else { rttbDefaultExceptionStaticMacro( << "Unknown io style selected. Cannot load data. Selected style: " << args[0]); } std::cout << "done." << std::endl; return result; }; rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::bioModelCalc::loadDicomDose(const std::string& fileName) { rttb::io::dicom::DicomFileDoseAccessorGenerator generator(fileName); return generator.generateDoseAccessor(); }; rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::bioModelCalc::loadHelaxDose(const std::string& path) { rttb::io::helax::DicomHelaxFileDoseAccessorGenerator generator(path); return generator.generateDoseAccessor(); }; rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::bioModelCalc::loadITKDose(const std::string& fileName) { rttb::io::itk::ITKImageFileAccessorGenerator generator(fileName); return generator.generateDoseAccessor(); }; -rttb::core::DoseAccessorInterface::DoseAccessorPointer -rttb::apps::bioModelCalc::loadVirtuosDose(const std::string& fileName, - const std::string& planFileName) -{ - rttb::io::virtuos::VirtuosPlanFileDoseAccessorGenerator generator(fileName, planFileName); - return generator.generateDoseAccessor(); -}; - void rttb::apps::bioModelCalc::processData(rttb::apps::bioModelCalc::ApplicationData& appData) { rttb::core::DoseAccessorInterface::DoseAccessorPointer outputAccessor; std::cout << std::endl << "generate biomodel... "; auto bioModelAccessor = generateBioModel(appData._dose, appData._model, appData._modelParameters, appData._doseScaling); std::cout << "done." << std::endl; std::cout << std::endl << "generate output image... "; io::itk::ITKImageAccessorConverter converter(bioModelAccessor); converter.setFailOnInvalidIDs(true); converter.process(); io::itk::ITKImageAccessorConverter::ITKImageType::Pointer itkImage = converter.getITKImage(); std::cout << "done." << std::endl; std::cout << std::endl << "write output image... "; io::itk::ImageWriter writer(appData._outputFileName, itkImage); writer.writeFile(); std::cout << "done." << std::endl; }; rttb::core::AccessorInterface::AccessorPointer rttb::apps::bioModelCalc::generateBioModel( rttb::core::DoseAccessorInterface::DoseAccessorPointer dose, const std::string& model, const std::vector& modelParameters, double doseScaling) { if (model == "LQ") { return boost::make_shared(dose, modelParameters.at(0), modelParameters.at(1), doseScaling); } else { rttbDefaultExceptionStaticMacro( << "Unknown model selected. Cannot load data. Selected model: " << model); } } diff --git a/apps/BioModelCalc/BioModelCmdLineParser.cpp b/apps/BioModelCalc/BioModelCmdLineParser.cpp index 7287869..dd51640 100644 --- a/apps/BioModelCalc/BioModelCmdLineParser.cpp +++ b/apps/BioModelCalc/BioModelCmdLineParser.cpp @@ -1,100 +1,111 @@ #include "BioModelCmdLineParser.h" namespace rttb { namespace apps { namespace bioModelCalc { BioModelCmdLineParser::BioModelCmdLineParser(int argc, const char** argv, const std::string& name, - const std::string& version) : - CmdLineParserBase(name, version) + const std::string& version, bool virtuosSupport) : + CmdLineParserBase(name, version), _virtuosSupport(virtuosSupport) { addOption(OPTION_DOSE_FILE, OPTION_GROUP_REQUIRED, "The name of the dose file. Can be omitted if used as " "positional argument (see above).", 'd', true); addOption(OPTION_OUTPUT_FILE, OPTION_GROUP_REQUIRED, "The name of the output file. Can be omitted if used as " "positional argument (see above).", 'o', true); addPositionalOption(OPTION_DOSE_FILE, 1); addPositionalOption(OPTION_OUTPUT_FILE, 1); addOptionWithDefaultValue(OPTION_MODEL, OPTION_GROUP_REQUIRED, "The used radiobiological model the dose should be analyzed with. Available models are:\n \"LQ\"", "LQ", "LQ", 'm'); addOption >(OPTION_MODEL_PARAMETERS, OPTION_GROUP_REQUIRED, "The parameters for the radiobiological model.", 'p', true, true); addOptionWithDefaultValue(OPTION_DOSE_SCALING, OPTION_GROUP_REQUIRED, - "Dose scaling that should be applied.", 1.0, "1.0", 'c'); + "Dose scaling that should be applied.", 1.0, "1.0", 'e'); std::vector defaultLoadingStyle; defaultLoadingStyle.push_back("itk"); - addOptionWithDefaultValue >(OPTION_LOAD_STYLE, OPTION_GROUP_REQUIRED, - "The loading style for the dose. Available styles are:\n" - "\"dicom\": normal dicom dose\n" - "\"virtuos\": load of a virtuos dose (This style is a multi argument. The second argument specifies the virtuos plan file, e.g. : \"--loadStyle virtuos myFavorite.pln\")\n" - "\"itk\": use itk image loading\n\"helax\": load a helax dose (choosing this style, the dose path should only be a directory).", + + std::string doseLoadStyleDescription = "The loading style for the dose. Available styles are:\n" + "\"dicom\": normal dicom dose\n" + "\"itk\": use itk image loading\n" + "\"helax\": load a helax dose (choosing this style, the dose path should only be a directory)."; + + + if (_virtuosSupport) + { + doseLoadStyleDescription += "\n" + "\"virtuos\": load of a virtuos dose (This style is a multi argument. The second argument specifies the virtuos plan file, e.g. : \"--" + + OPTION_LOAD_STYLE + " virtuos myFavorite.pln\")"; + } + + + addOptionWithDefaultValue >(OPTION_LOAD_STYLE, OPTION_GROUP_REQUIRED, doseLoadStyleDescription, defaultLoadingStyle, defaultLoadingStyle.at(0), - 's', true, true); + 't', true, true); parse(argc, argv); } void BioModelCmdLineParser::validateInput() const { std::string model = get(OPTION_MODEL); if (model != "LQ") { throw cmdlineparsing::InvalidConstraintException("Unknown model: " + model + ".\nPlease refer to the help for valid models."); } else { if (get >(OPTION_MODEL_PARAMETERS).size() != 2) { throw cmdlineparsing::InvalidConstraintException("The LQ Model requires two parameters!"); } } std::vector loadStyle = get >(OPTION_LOAD_STYLE); std::string loadStyleAbbreviation = loadStyle.at(0); - if (loadStyleAbbreviation != "dicom" && loadStyleAbbreviation != "virtuos" + if (loadStyleAbbreviation != "dicom" && (!_virtuosSupport || loadStyleAbbreviation != "virtuos") && loadStyleAbbreviation != "itk" && loadStyleAbbreviation != "helax") { throw cmdlineparsing::InvalidConstraintException("Unknown load style:" + loadStyleAbbreviation + ".\nPlease refer to the help for valid loading style settings."); } - else if (loadStyleAbbreviation == "virtuos") + else if (_virtuosSupport && loadStyleAbbreviation == "virtuos") { if (loadStyle.size() < 2) { throw cmdlineparsing::InvalidConstraintException("Cannot load virtuos dose. Plan file is missing. Specify plan file as 2nd io style argument."); } } double doseScaling = get(OPTION_DOSE_SCALING); if (doseScaling <= 0) { throw cmdlineparsing::InvalidConstraintException("Negative dose scaling is invalid. Dose scaling has to be >0."); } } void BioModelCmdLineParser::printHelp() const { cmdlineparsing::CmdLineParserBase::printHelp(); std::cout << "Example:" << std::endl << std::endl; std::cout << m_programName << - " dose.mhd result.mhd -s itk -m LQ -p 0.2 0.02" << + " dose.mhd result.mhd -m LQ -p 0.2 0.02" << std::endl << std::endl; std::cout << "This will calculate the Linear quadratic (LQ) BioModel from \"dose.mhd\" and will write the result to \"result.mhd\". " "The alpha and beta parameters for the LQ model are 0.2 and 0.02, respectively." << std::endl; } } } } diff --git a/apps/BioModelCalc/BioModelCmdLineParser.h b/apps/BioModelCalc/BioModelCmdLineParser.h index ad27d84..a0618a2 100644 --- a/apps/BioModelCalc/BioModelCmdLineParser.h +++ b/apps/BioModelCalc/BioModelCmdLineParser.h @@ -1,40 +1,42 @@ #ifndef __BIO_MODEL_CMD_LINE_PARSER #define __BIO_MODEL_CMD_LINE_PARSER #include "CmdLineParserBase.h" namespace rttb { namespace apps { namespace bioModelCalc { /*! @class BioModelCmdLineParser @brief Argument parsing is parametrized here based on ArgParserLib @see cmdlineparsing::CmdLineParserBase */ class BioModelCmdLineParser : public cmdlineparsing::CmdLineParserBase { public: BioModelCmdLineParser(int argc, const char** argv, const std::string& name, - const std::string& version); + const std::string& version, bool virtuosSupport = false); void validateInput() const; void printHelp() const; // Option groups const std::string OPTION_GROUP_REQUIRED = "Required Arguments"; const std::string OPTION_GROUP_OPTIONAL = "Optional Arguments"; // Parameters const std::string OPTION_DOSE_FILE = "dose"; const std::string OPTION_OUTPUT_FILE = "outputFile"; const std::string OPTION_MODEL = "model"; const std::string OPTION_MODEL_PARAMETERS = "modelParameters"; const std::string OPTION_LOAD_STYLE = "loadStyle"; const std::string OPTION_DOSE_SCALING = "doseScaling"; + + bool _virtuosSupport; }; } } } #endif \ No newline at end of file diff --git a/apps/BioModelCalc/CMakeLists.txt b/apps/BioModelCalc/CMakeLists.txt index 9e24a9c..a89985a 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 RTTBVirtuosIO RTTBDicomIO RTTBHelaxIO RTTBModels PACKAGE_DEPENDS ArgumentParsingLib BoostBinaries) +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") ENDIF() diff --git a/apps/BioModelCalc4V/BioModelCalc4V.cpp b/apps/BioModelCalc4V/BioModelCalc4V.cpp new file mode 100644 index 0000000..218cf7b --- /dev/null +++ b/apps/BioModelCalc4V/BioModelCalc4V.cpp @@ -0,0 +1,134 @@ +// ----------------------------------------------------------------------- +// 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: 1334 $ (last changed revision) +// @date $Date: 2016-04-22 11:13:22 +0200 (Fr, 22 Apr 2016) $ (last change date) +// @author $Author: hentsch $ (last changed by) +*/ + +#include "../BioModelCalc/BioModelCalcApplicationData.h" +#include "../BioModelCalc/BioModelCalcHelper.h" +#include "../BioModelCalc/BioModelCmdLineParser.h" +#include "../DoseTool4V/DoseTool4VHelper.h" + +#include "boost/shared_ptr.hpp" +#include "boost/make_shared.hpp" + +#include "RTToolboxConfigure.h" + +#include "rttbException.h" + +rttb::apps::bioModelCalc::ApplicationData appData; + +int main(int argc, const char** argv) +{ + int result = 0; + + boost::shared_ptr argParser; + + try + { + std::string appName = "BioModelCalc4V"; + std::string appVersion = RTTB_FULL_VERSION_STRING; + + argParser = boost::make_shared(argc, argv, appName, + appVersion, true); + } + catch (const std::exception& e) + { + std::cerr << e.what() << std::endl; + return -1; + } + + // This is vital. The application needs to exit if the "help" or "version" parameter is set + // because this means the other parameters won't be parsed. + + if (argParser->isSet(argParser->OPTION_HELP) || argParser->isSet(argParser->OPTION_VERSION)) + { + return 0; + } + + rttb::apps::bioModelCalc::populateAppData(argParser, appData); + + std::cout << std::endl << "*******************************************" << std::endl; + std::cout << "Dose file: " << appData._doseFileName << std::endl; + std::cout << "Bio model output file: " << appData._outputFileName << std::endl; + std::cout << "Model: " << appData._model << std::endl; + std::cout << "Model parameters: "; + + + for (size_t i = 0; i < appData._modelParameters.size(); i++) + { + if (i != 0) + { + std::cout << ", "; + } + + std::cout << appData._modelParameters.at(i); + } + + std::cout << std::endl; + std::cout << "Dose scaling: " << appData._doseScaling << std::endl; + + std::cout << std::endl; + + try + { + appData._dose = rttb::apps::doseTool4V::loadDose(appData._doseFileName, appData._doseLoadStyle); + } + catch (rttb::core::Exception& e) + { + std::cerr << "RTTB Error!!!" << std::endl; + std::cerr << e.what() << std::endl; + return 1; + } + catch (const std::exception& e) + { + std::cerr << "Error!!!" << std::endl; + std::cerr << e.what() << std::endl; + return 1; + } + catch (...) + { + std::cerr << "Error!!! Unknown error while reading input image." << std::endl; + return 1; + } + + try + { + rttb::apps::bioModelCalc::processData(appData); + } + catch (rttb::core::Exception& e) + { + std::cerr << "RTTB Error!!!" << std::endl; + std::cerr << e.what() << std::endl; + return 2; + } + catch (std::exception& e) + { + std::cerr << "Error!!!" << std::endl; + std::cerr << e.what() << std::endl; + return 2; + } + catch (...) + { + std::cerr << "Error!!! Unknown error while calculating the bioModel or writing the image." << + std::endl; + return 2; + } + + return result; +} diff --git a/apps/BioModelCalc4V/CMakeLists.txt b/apps/BioModelCalc4V/CMakeLists.txt new file mode 100644 index 0000000..e90acb1 --- /dev/null +++ b/apps/BioModelCalc4V/CMakeLists.txt @@ -0,0 +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") +ENDIF() diff --git a/apps/BioModelCalc4V/files.cmake b/apps/BioModelCalc4V/files.cmake new file mode 100644 index 0000000..6e39b80 --- /dev/null +++ b/apps/BioModelCalc4V/files.cmake @@ -0,0 +1,13 @@ +SET(CPP_FILES +BioModelCalc4V.cpp +../DoseTool4V/DoseTool4VHelper.cpp +../BioModelCalc/BioModelCalcHelper.cpp +../BioModelCalc/BioModelCalcApplicationData.cpp +../BioModelCalc/BioModelCmdLineParser.cpp +) + +SET(H_FILES +../DoseTool4V/DoseTool4VHelper.h +../BioModelCalc/BioModelCalcApplicationData.h +../BioModelCalc/BioModelCmdLineParser.h +) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 85f474d..8dc52d2 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -1,55 +1,61 @@ MESSAGE(STATUS "processing RTToolbox apps") IF (BUILD_App_DoseTool OR BUILD_App_VoxelizerTool OR BUILD_App_BioModelCalc) IF (WIN32) IF (MSVC_VERSION LESS 1800) MESSAGE(FATAL_ERROR "Some features of RTToolbox requires C++11 features that require Visual Studio 2013 or higher.") ENDIF(MSVC_VERSION LESS 1800) ENDIF(WIN32) #extract and build ArgumentParsingLib include(ExternalProject) message(STATUS "ArgumentParsingLib will be automatically downloaded and built.") set(ArgumentParsingLib_SOURCE_DIR "${CMAKE_BINARY_DIR}/external/ArgumentParsingLib-src") set(ArgumentParsingLib_BUILD_DIR "${CMAKE_BINARY_DIR}/external/ArgumentParsingLib-build") set(ArgumentParsingLib_CMAKE_DIR "${CMAKE_BINARY_DIR}/external/ArgumentParsingLib-cmake") ExternalProject_Add( ArgumentParsingLib URL ${RTToolbox_SOURCE_DIR}/utilities/ArgumentParsingLib/ArgumentParsingLib.tar.gz SOURCE_DIR ${ArgumentParsingLib_SOURCE_DIR} BINARY_DIR ${ArgumentParsingLib_BUILD_DIR} PREFIX ${ArgumentParsingLib_CMAKE_DIR} INSTALL_COMMAND "" UPDATE_COMMAND "" CMAKE_ARGS -DBUILD_TESTS:BOOL=OFF -DBoost_INCLUDE_DIR:STRING=${Boost_INCLUDE_DIR} -DBoost_DIR:STRING=${Boost_DIR} ) ENDIF() OPTION(BUILD_App_DoseAcc "Determine if the application DoseAcc will be generated." OFF) -IF(BUILD_App_DoseAcc) +IF(BUILD_App_DoseAcc AND BUILD_IO_Virtuos) ADD_SUBDIRECTORY(DoseAcc) -ENDIF(BUILD_App_DoseAcc) +ENDIF() OPTION(BUILD_App_DoseMap "Determine if the application DoseMap will be generated." OFF) -IF(BUILD_App_DoseMap) +IF(BUILD_App_DoseMap AND BUILD_IO_Virtuos) ADD_SUBDIRECTORY(DoseMap) -ENDIF(BUILD_App_DoseMap) +ENDIF() -OPTION(BUILD_App_DoseTool "Determine if the application DoseTool will be generated." OFF) +OPTION(BUILD_App_DoseTool "Determine if the demo application DoseTool will be generated." OFF) IF(BUILD_App_DoseTool) ADD_SUBDIRECTORY(DoseTool) + IF(RTTB_VIRTUOS_SUPPORT AND BUILD_IO_Virtuos) + ADD_SUBDIRECTORY(DoseTool4V) + ENDIF() ENDIF(BUILD_App_DoseTool) OPTION(BUILD_App_VoxelizerTool "Determine if the application VoxelizerTool will be generated." OFF) IF(BUILD_App_VoxelizerTool) ADD_SUBDIRECTORY(VoxelizerTool) ENDIF(BUILD_App_VoxelizerTool) -OPTION(BUILD_App_BioModelCalc "Determine if the application BioModelCalc will be generated." OFF) +OPTION(BUILD_App_BioModelCalc "Determine if the demo application BioModelCalc will be generated." OFF) IF(BUILD_App_BioModelCalc) ADD_SUBDIRECTORY(BioModelCalc) + IF(RTTB_VIRTUOS_SUPPORT AND BUILD_IO_Virtuos) + ADD_SUBDIRECTORY(BioModelCalc4V) + ENDIF() ENDIF(BUILD_App_BioModelCalc) \ No newline at end of file diff --git a/apps/DoseTool/CMakeLists.txt b/apps/DoseTool/CMakeLists.txt index dc338ef..88ba7dc 100644 --- a/apps/DoseTool/CMakeLists.txt +++ b/apps/DoseTool/CMakeLists.txt @@ -1,7 +1,7 @@ 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 RTTBVirtuosIO RTTBDicomIO RTTBHelaxIO RTTBMasks RTTBMasks RTTBBoostMask RTTBOtherIO RTTBAlgorithms PACKAGE_DEPENDS ArgumentParsingLib BoostBinaries) +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") ENDIF() diff --git a/apps/DoseTool/DoseToolApplicationData.h b/apps/DoseTool/DoseToolApplicationData.h index bc79970..5e1f4e8 100644 --- a/apps/DoseTool/DoseToolApplicationData.h +++ b/apps/DoseTool/DoseToolApplicationData.h @@ -1,79 +1,79 @@ // ----------------------------------------------------------------------- // 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: 1070 $ (last changed revision) -// @date $Date: 2015-08-19 14:50:28 +0200 (Mi, 19 Aug 2015) $ (last change date) -// @author $Author: floca $ (last changed by) +// @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) */ #ifndef __DOSETOOL_APPLICATION_DATA_H #define __DOSETOOL_APPLICATION_DATA_H #include #include "rttbDoseAccessorInterface.h" #include "rttbStructureSetGeneratorInterface.h" #include "DoseToolCmdLineParser.h" namespace rttb { namespace apps { namespace doseTool { /*! @class ApplicationData @brief Class for storing all relevant variables needed in DoseTool */ class ApplicationData { public: /**Vector of arguments used to specify the loading style (always the first argument) * and, if needed, additional arguments for the specified loading style (e.g. location of the * Virtuos plan file for the Virtuos IO style). */ typedef std::vector LoadingStyleArgType; core::DoseAccessorInterface::DoseAccessorPointer _dose; core::StructureSetGeneratorInterface::StructureSetPointer _struct; std::string _structNameRegex; std::vector _structIndices; std::vector _structNames; std::string _doseFileName; std::string _structFileName; LoadingStyleArgType _doseLoadStyle; LoadingStyleArgType _structLoadStyle; bool _computeComplexDoseStatistics; DoseTypeGy _prescribedDose; std::string _doseStatisticOutputFileName; bool _allowSelfIntersection; bool _multipleStructsMode; bool _computeDVH; bool _computeDoseStatistics; std::string _dvhOutputFilename; /*! @brief Resets the variables. _prescribedDose is set to 1.0 because it produces no exception then (as it is not needed). Consistency checks are done in DoseToolCmdLineParser::validateInput() */ void reset(); ApplicationData(); }; /*! @brief Reads the necessary arguments from the DoseToolCmdLineParser and writes them in the respective variables of ApplicationData. */ void populateAppData(boost::shared_ptr argParser, ApplicationData& appData); } } } #endif diff --git a/apps/DoseTool/DoseToolCmdLineParser.cpp b/apps/DoseTool/DoseToolCmdLineParser.cpp index 4cf4342..047a7fa 100644 --- a/apps/DoseTool/DoseToolCmdLineParser.cpp +++ b/apps/DoseTool/DoseToolCmdLineParser.cpp @@ -1,184 +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: 1221 $ (last changed revision) -// @date $Date: 2015-12-01 13:43:31 +0100 (Di, 01 Dez 2015) $ (last change date) +// @version $Revision: 1374 $ (last changed revision) +// @date $Date: 2016-05-30 14:15:42 +0200 (Mo, 30 Mai 2016) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "DoseToolCmdLineParser.h" namespace rttb { namespace apps { namespace doseTool { DoseToolCmdLineParser::DoseToolCmdLineParser(int argc, const char** argv, const std::string& name, - const std::string& version) : - CmdLineParserBase(name, version) + const std::string& version, bool virtuosSupport) : + CmdLineParserBase(name, version), _virtuosSupport(virtuosSupport) { typedef double DoseTypeGy; addOption(OPTION_DOSE_FILE, OPTION_GROUP_REQUIRED, "The name of the dose file. Can be omitted if used as " "positional argument (see above).", 'd', true); addOption(OPTION_STRUCT_FILE, OPTION_GROUP_REQUIRED, "The name of the struct file. Can be omitted if used as " "positional argument (see above).", 's', true); addOptionWithDefaultValue(OPTION_STRUCT_NAME, OPTION_GROUP_REQUIRED, "The name of the struct as regular expression. Can be omitted if used as " "positional argument or with itk struct loadingStyle (see above).", "", "", 'n', true); addPositionalOption(OPTION_DOSE_FILE, 1); addPositionalOption(OPTION_STRUCT_FILE, 1); addPositionalOption(OPTION_STRUCT_NAME, 1); addPositionalOption(OPTION_DOSE_STATISTICS, 1); std::vector defaultLoadingStyle; defaultLoadingStyle.push_back("dicom"); + std::string doseLoadStyleDescription = "\"dicom\": normal dicom dose\n" + "\"itk\": use itk image loading\n\"helax\": load a helax dose (choosing this style, the dose path should only be a directory)."; + + + if (_virtuosSupport) + { + doseLoadStyleDescription += "\n" + "\"virtuos\": load of a virtuos dose (This style is a multi argument. The second argument specifies the virtuos plan file, e.g. : \"--" + + OPTION_DOSE_LOAD_STYLE + " virtuos myFavorite.pln\")"; + } + addOptionWithDefaultValue >(OPTION_DOSE_LOAD_STYLE, OPTION_GROUP_REQUIRED, - "The loading style for the dose. Available styles are:\n" - "\"dicom\": normal dicom dose\n" - "\"virtuos\": load of a virtuos dose (This style is a multi argument. The second argument specifies the virtuos plan file, e.g. : \"--" - + OPTION_DOSE_LOAD_STYLE + " virtuos myFavorite.pln\")\n" - "\"itk\": use itk image loading\n\"helax\": load a helax dose (choosing this style, the dose path should only be a directory).", + doseLoadStyleDescription, defaultLoadingStyle, defaultLoadingStyle.at(0), 't', true, true); + + std::string structLoadStyleDescription = "\"dicom\": normal dicom dose\n" + "\"itk\": use itk image loading\""; + + if (_virtuosSupport) + { + structLoadStyleDescription += "\n" + "\"virtuos\": load of a virtuos struct file (This style is a multi argument. The second argument specifies the ctx file, e.g. : \"--" + + OPTION_STRUCT_LOAD_STYLE + " virtuos myImage.ctx\")"; + } + addOptionWithDefaultValue >(OPTION_STRUCT_LOAD_STYLE, - OPTION_GROUP_REQUIRED, - "The loading style for the dose. Available styles are:\n" - "\"dicom\": normal dicom dose\n" - "\"virtuos\": load of a virtuos dose (This style is a multi argument. The second argument specifies the virtuos plan file, e.g. : \"--" - + OPTION_DOSE_LOAD_STYLE + " virtuos myFavorite.pln\")\n" - "\"itk\": use itk image loading.", + OPTION_GROUP_REQUIRED, structLoadStyleDescription, defaultLoadingStyle, defaultLoadingStyle.at(0), 'u', true, true); addOption(OPTION_DOSE_STATISTICS, OPTION_GROUP_OPTIONAL, "If dose statistics should be computed. The argument is the output file. Can be omitted if used as " "positional argument (see above).", 'y'); addOption(OPTION_DVH, OPTION_GROUP_OPTIONAL, "If the DVH should be computed. The argument is the output file", 'z'); addOption(OPTION_COMPLEX_STATISTICS, OPTION_GROUP_OPTIONAL, "If the complex dose statistics (Dx, Vx, MOHx, MOCx, MaxOHx, MinOCx) should be computed.", 'x'); addOption(OPTION_PRESCRIBED_DOSE, OPTION_GROUP_OPTIONAL, "The prescribed dose in Gy.", 'p'); addOption(OPTION_ALLOW_SELF_INTERSECTION_STRUCT, OPTION_GROUP_OPTIONAL, "If a struct file contains self intersecting contours: Allow the processing of these structures and ignore potential problems." "WARNING: only use this parameter if you know what you are doing.", 'a'); addOption(OPTION_MULTIPLE_STRUCTS_MODE, OPTION_GROUP_OPTIONAL, "If the regex agrees with multiple structs: write a dose statistic for every struct file." "The struct name will be appended to the chosen output filename.", 'm'); parse(argc, argv); } void DoseToolCmdLineParser::validateInput() const { std::vector doseLoadStyle = get >(OPTION_DOSE_LOAD_STYLE); std::string doseLoadStyleAbbreviation = doseLoadStyle.at(0); - if (doseLoadStyleAbbreviation != "dicom" && doseLoadStyleAbbreviation != "virtuos" + if (doseLoadStyleAbbreviation != "dicom" && (!_virtuosSupport || doseLoadStyleAbbreviation != "virtuos") && doseLoadStyleAbbreviation != "itk" && doseLoadStyleAbbreviation != "helax") { throw cmdlineparsing::InvalidConstraintException("Unknown load style for dose file:" + doseLoadStyleAbbreviation + ".\nPlease refer to the help for valid loading style settings."); } - if (doseLoadStyleAbbreviation == "virtuos") + if (_virtuosSupport && doseLoadStyleAbbreviation == "virtuos") { if (doseLoadStyle.size() < 2) { throw cmdlineparsing::InvalidConstraintException("Cannot load virtuos dose. Plan file is missing. Specify plan file as 2nd io style argument."); } } std::vector structLoadStyle = get >(OPTION_STRUCT_LOAD_STYLE); std::string structLoadStyleAbbreviation = structLoadStyle.at(0); - if (structLoadStyleAbbreviation != "dicom" && structLoadStyleAbbreviation != "virtuos" + if (structLoadStyleAbbreviation != "dicom" && (!_virtuosSupport || structLoadStyleAbbreviation != "virtuos") && structLoadStyleAbbreviation != "itk") { throw cmdlineparsing::InvalidConstraintException("Unknown load style for struct file:" + structLoadStyleAbbreviation + ".\nPlease refer to the help for valid loading style settings."); } - if (structLoadStyleAbbreviation == "dicom" || structLoadStyleAbbreviation == "virtuos" + if (structLoadStyleAbbreviation == "dicom" || (_virtuosSupport && structLoadStyleAbbreviation == "virtuos") || structLoadStyleAbbreviation == "helax") { if (get(OPTION_STRUCT_NAME) == "") { throw cmdlineparsing::InvalidConstraintException("The struct name (--" + OPTION_STRUCT_NAME + ") has to be defined for dicom, virtuos or helax struct files."); } } - if (structLoadStyleAbbreviation == "virtuos") + if (_virtuosSupport && structLoadStyleAbbreviation == "virtuos") { if (structLoadStyle.size() < 2) { throw cmdlineparsing::InvalidConstraintException("Cannot load virtuos struct file. CTX file is missing. Specify CTX file as 2nd io style argument."); } } if (!isSet(OPTION_DVH) && !isSet(OPTION_DOSE_STATISTICS)) { throw cmdlineparsing::InvalidConstraintException("Neither the Dose statistics (--" + OPTION_DOSE_STATISTICS + "), nor the DVH (--" + OPTION_DVH + ") option was used."); } if (isSet(OPTION_DOSE_STATISTICS) && isSet(OPTION_COMPLEX_STATISTICS)) { if (!isSet(OPTION_PRESCRIBED_DOSE)) { throw cmdlineparsing::InvalidConstraintException("The prescribed dose (--" + OPTION_PRESCRIBED_DOSE + ") has to be set for computation of complex dose statistics."); } else { if (get(OPTION_PRESCRIBED_DOSE) <= 0) { throw cmdlineparsing::InvalidConstraintException("The prescribed dose (--" + OPTION_PRESCRIBED_DOSE + ") has to be >0!"); } } } } void DoseToolCmdLineParser::printHelp() const { cmdlineparsing::CmdLineParserBase::printHelp(); std::cout << "Example:" << std::endl << std::endl; std::cout << m_programName << " dose.dcm struct.dcm Liver result.xml --" + OPTION_DVH + " dvh.xml" << std::endl << std::endl; std::cout << "This will calculate the Dose statistic for liver using \"dose.dcm\" and the struct file \"struct.dcm\" and will write the dose statistics to \"result.xml\". " " The DVH is computed as well, its values are written to \"dvh.xml\". " << std::endl; } } } } diff --git a/apps/DoseTool/DoseToolCmdLineParser.h b/apps/DoseTool/DoseToolCmdLineParser.h index 6632b50..d63c693 100644 --- a/apps/DoseTool/DoseToolCmdLineParser.h +++ b/apps/DoseTool/DoseToolCmdLineParser.h @@ -1,66 +1,68 @@ // ----------------------------------------------------------------------- // 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) +// @version $Revision: 1374 $ (last changed revision) +// @date $Date: 2016-05-30 14:15:42 +0200 (Mo, 30 Mai 2016) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #ifndef __DOSETOOL_CMD_LINE_PARSER #define __DOSETOOL_CMD_LINE_PARSER #include "CmdLineParserBase.h" namespace rttb { namespace apps { namespace doseTool { /*! @class BioModelCmdLineParser @brief Argument parsing is parametrized here based on ArgParserLib @see cmdlineparsing::CmdLineParserBase */ class DoseToolCmdLineParser : public cmdlineparsing::CmdLineParserBase { public: DoseToolCmdLineParser(int argc, const char** argv, const std::string& name, - const std::string& version); + const std::string& version, bool virtuosSupport = false); void validateInput() const; void printHelp() const; // Option groups const std::string OPTION_GROUP_REQUIRED = "Required Arguments"; const std::string OPTION_GROUP_OPTIONAL = "Optional Arguments"; // Parameters const std::string OPTION_DOSE_FILE = "doseFile"; const std::string OPTION_STRUCT_FILE = "structFile"; const std::string OPTION_STRUCT_NAME = "structName"; const std::string OPTION_DOSE_STATISTICS = "doseStatistics"; const std::string OPTION_DVH = "DVH"; const std::string OPTION_DOSE_LOAD_STYLE = "doseLoadStyle"; const std::string OPTION_STRUCT_LOAD_STYLE = "structLoadStyle"; const std::string OPTION_COMPLEX_STATISTICS = "complexStatistics"; const std::string OPTION_PRESCRIBED_DOSE = "prescribedDose"; const std::string OPTION_ALLOW_SELF_INTERSECTION_STRUCT = "allowSelfIntersection"; const std::string OPTION_MULTIPLE_STRUCTS_MODE = "multipleStructsMode"; + + bool _virtuosSupport; }; } } } #endif \ No newline at end of file diff --git a/apps/DoseTool/DoseToolHelper.cpp b/apps/DoseTool/DoseToolHelper.cpp index 8ee44e5..a6a9166 100644 --- a/apps/DoseTool/DoseToolHelper.cpp +++ b/apps/DoseTool/DoseToolHelper.cpp @@ -1,369 +1,336 @@ // ----------------------------------------------------------------------- // 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: 1334 $ (last changed revision) -// @date $Date: 2016-04-22 11:13:22 +0200 (Fr, 22 Apr 2016) $ (last change date) +// @version $Revision: 1374 $ (last changed revision) +// @date $Date: 2016-05-30 14:15:42 +0200 (Mo, 30 Mai 2016) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "DoseToolHelper.h" #include "boost/make_shared.hpp" #include "boost/shared_ptr.hpp" #include "boost/property_tree/ptree.hpp" #include "boost/filesystem.hpp" #include "rttbExceptionMacros.h" -#include "rttbVirtuosPlanFileDoseAccessorGenerator.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomHelaxFileDoseAccessorGenerator.h" #include "rttbITKImageFileAccessorGenerator.h" #include "rttbStructureSetGeneratorInterface.h" #include "rttbDicomFileStructureSetGenerator.h" -#include "rttbVirtuosFileStructureSetGenerator.h" #include "rttbITKImageFileMaskAccessorGenerator.h" #include "rttbDVHCalculator.h" #include "rttbDVHXMLFileWriter.h" #include "rttbDoseStatisticsCalculator.h" #include "rttbBoostMaskAccessor.h" #include "rttbGenericMaskedDoseIterator.h" #include "rttbDoseStatisticsXMLWriter.h" #include "rttbVOIindexIdentifier.h" rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::doseTool::loadDose(const std::string& fileName, const rttb::apps::doseTool::ApplicationData::LoadingStyleArgType& args) { rttb::core::DoseAccessorInterface::DoseAccessorPointer result; std::cout << std::endl << "read dose file... "; if (args.empty() || args[0] == "dicom") { std::cout << "use RTTB dicom IO... "; result = loadDicomDose(fileName); } else if (args[0] == "helax") { std::cout << "use RTTB Helax IO... "; result = loadHelaxDose(fileName); } else if (args[0] == "itk") { std::cout << "use RTTB itk IO... "; result = loadITKDose(fileName); } - else if (args[0] == "virtuos") - { - if (args.size() < 2) - { - rttbDefaultExceptionStaticMacro( << - "Cannot load virtuos dose. Plan file is missing. Specify plan file as 2nd io stlye argument."); - } - - std::cout << "use RTTB virtuos IO... " << std::endl; - std::cout << " virtuos plan file: " << args[1] << " ... "; - result = loadVirtuosDose(fileName, args[1]); - } else { rttbDefaultExceptionStaticMacro( << "Unknown io style selected. Cannot load data. Selected style: " << args[0]); } std::cout << "done." << std::endl; return result; -}; +} rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::doseTool::loadDicomDose(const std::string& fileName) { rttb::io::dicom::DicomFileDoseAccessorGenerator generator(fileName); return generator.generateDoseAccessor(); -}; +} rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::doseTool::loadHelaxDose(const std::string& path) { rttb::io::helax::DicomHelaxFileDoseAccessorGenerator generator(path); return generator.generateDoseAccessor(); -}; +} rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::doseTool::loadITKDose(const std::string& fileName) { rttb::io::itk::ITKImageFileAccessorGenerator generator(fileName); return generator.generateDoseAccessor(); -}; +} -rttb::core::DoseAccessorInterface::DoseAccessorPointer -rttb::apps::doseTool::loadVirtuosDose(const std::string& fileName, const std::string& planFileName) -{ - rttb::io::virtuos::VirtuosPlanFileDoseAccessorGenerator generator(fileName, planFileName); - return generator.generateDoseAccessor(); -}; rttb::core::StructureSetGeneratorInterface::StructureSetPointer rttb::apps::doseTool::loadStruct( const std::string& fileName, const ApplicationData::LoadingStyleArgType& args, const std::string& structNameRegex) { rttb::core::StructureSetGeneratorInterface::StructureSetPointer result; std::cout << std::endl << "read struct file... "; if (args.empty() || args[0] == "dicom") { std::cout << "use RTTB dicom IO... "; - result = loadDicomStruct(fileName, structNameRegex); - } - else if (args[0] == "virtuos") - { - std::cout << "use RTTB virtuos IO... " << std::endl; - std::cout << " virtuos CTX file: " << args[1] << " ... "; - result = loadVirtuosStruct(fileName, args[1]); + result = loadDicomStruct(fileName, structNameRegex); } else { rttbDefaultExceptionStaticMacro( << "Unknown io style selected. Cannot load data. Selected style: " << args[0]); } std::cout << "done." << std::endl; return result; } rttb::core::StructureSetGeneratorInterface::StructureSetPointer rttb::apps::doseTool::loadDicomStruct( -const std::string& fileName, const std::string& structNameRegex) + const std::string& fileName, const std::string& structNameRegex) { rttb::io::dicom::DicomFileStructureSetGenerator generator(fileName); - if (!structNameRegex.empty()) - { - generator.setStructureLableFilterActive(true); - generator.setFilterRegEx(structNameRegex); - } - return generator.generateStructureSet(); -} + if (!structNameRegex.empty()) + { + generator.setStructureLableFilterActive(true); + generator.setFilterRegEx(structNameRegex); + } -rttb::core::StructureSetGeneratorInterface::StructureSetPointer -rttb::apps::doseTool::loadVirtuosStruct( - const std::string& fileName, const std::string& ctxFileName) -{ - rttb::io::virtuos::VirtuosFileStructureSetGenerator generator(fileName, ctxFileName.c_str()); return generator.generateStructureSet(); } void rttb::apps::doseTool::processData(rttb::apps::doseTool::ApplicationData& appData) { std::cout << std::endl << "generating masks... "; std::vector maskAccessorPtrVector = generateMasks( appData); std::cout << "done." << std::endl; for (size_t i = 0; i < maskAccessorPtrVector.size(); i++) { core::DoseIteratorInterface::DoseIteratorPointer spDoseIterator(generateMaskedDoseIterator( maskAccessorPtrVector.at(i), appData._dose)); if (appData._computeDoseStatistics) { std::cout << std::endl << "computing dose statistics... "; algorithms::DoseStatistics::DoseStatisticsPointer statistics = calculateDoseStatistics( spDoseIterator, appData._computeComplexDoseStatistics, appData._prescribedDose); std::cout << "done." << std::endl; std::cout << std::endl << "writing dose statistics to file... "; std::string outputFilename; if (appData._multipleStructsMode) { outputFilename = assembleFilenameWithStruct(appData._doseStatisticOutputFileName, appData._structNames.at(i)); } else { outputFilename = appData._doseStatisticOutputFileName; } writeDoseStatisticsFile(statistics, outputFilename, appData._structNames.at(i), appData); std::cout << "done." << std::endl; } if (appData._computeDVH) { std::cout << std::endl << "computing DVH... "; core::DVH::DVHPointer dvh = calculateDVH(spDoseIterator, appData._struct->getUID(), appData._dose->getUID()); std::cout << "done." << std::endl; std::cout << std::endl << "writing DVH to file... "; std::string outputFilename; if (appData._multipleStructsMode) { outputFilename = assembleFilenameWithStruct(appData._dvhOutputFilename, appData._structNames.at(i)); } else { outputFilename = appData._dvhOutputFilename; } writeDVHFile(dvh, outputFilename); std::cout << "done." << std::endl; } } } std::vector rttb::apps::doseTool::generateMasks( rttb::apps::doseTool::ApplicationData& appData) { std::vector maskAccessorPtrVector; if (appData._structLoadStyle.front() == "itk") { maskAccessorPtrVector.push_back(rttb::io::itk::ITKImageFileMaskAccessorGenerator( appData._structFileName).generateMaskAccessor()); } else { std::vector foundIndices = rttb::masks::VOIindexIdentifier::getIndicesByVoiRegex( appData._struct, appData._structNameRegex); std::vector relevantIndices; if (appData._multipleStructsMode) { relevantIndices = foundIndices; } else { if (!foundIndices.empty()) { relevantIndices.push_back(foundIndices.front()); } } appData._structIndices = relevantIndices; bool strict = !appData._allowSelfIntersection; for (size_t i = 0; i < appData._structIndices.size(); i++) { maskAccessorPtrVector.push_back( boost::make_shared (appData._struct->getStructure(appData._structIndices.at(i)), appData._dose->getGeometricInfo(), strict)); maskAccessorPtrVector.at(i)->updateMask(); appData._structNames.push_back(appData._struct->getStructure(appData._structIndices.at( i))->getLabel()); } } return maskAccessorPtrVector; } rttb::core::DoseIteratorInterface::DoseIteratorPointer rttb::apps::doseTool::generateMaskedDoseIterator( rttb::core::MaskAccessorInterface::MaskAccessorPointer maskAccessorPtr, rttb::core::DoseAccessorInterface::DoseAccessorPointer doseAccessorPtr) { boost::shared_ptr maskedDoseIterator = boost::make_shared(maskAccessorPtr, doseAccessorPtr); rttb::core::DoseIteratorInterface::DoseIteratorPointer doseIterator(maskedDoseIterator); return doseIterator; } rttb::algorithms::DoseStatistics::DoseStatisticsPointer rttb::apps::doseTool::calculateDoseStatistics( core::DoseIteratorInterface::DoseIteratorPointer doseIterator, bool calculateComplexDoseStatistics, DoseTypeGy prescribedDose) { rttb::algorithms::DoseStatisticsCalculator doseStatsCalculator(doseIterator); if (calculateComplexDoseStatistics) { return doseStatsCalculator.calculateDoseStatistics(prescribedDose); } else { return doseStatsCalculator.calculateDoseStatistics(); } } rttb::core::DVH::DVHPointer rttb::apps::doseTool::calculateDVH( core::DoseIteratorInterface::DoseIteratorPointer doseIterator, IDType structUID, IDType doseUID) { rttb::core::DVHCalculator calc(doseIterator, structUID, doseUID); rttb::core::DVH::DVHPointer dvh = calc.generateDVH(); return dvh; } void rttb::apps::doseTool::writeDoseStatisticsFile( rttb::algorithms::DoseStatistics::DoseStatisticsPointer statistics, const std::string& filename, const std::string& structName, rttb::apps::doseTool::ApplicationData& appData) { boost::property_tree::ptree originalTree = rttb::io::other::writeDoseStatistics(statistics); //add config part to xml originalTree.add("statistics.config.requestedStructRegex", appData._structNameRegex); originalTree.add("statistics.config.structName", structName); originalTree.add("statistics.config.doseUID", appData._dose->getUID()); originalTree.add("statistics.config.doseFile", appData._doseFileName); originalTree.add("statistics.config.structFile", appData._structFileName); boost::property_tree::ptree reorderedTree, configTree, resultsTree; configTree = originalTree.get_child("statistics.config"); resultsTree = originalTree.get_child("statistics.results"); reorderedTree.add_child("statistics.config", configTree); reorderedTree.add_child("statistics.results", resultsTree); boost::property_tree::write_xml(filename, reorderedTree, std::locale(), boost::property_tree::xml_writer_make_settings('\t', 1)); } std::string rttb::apps::doseTool::assembleFilenameWithStruct(const std::string& originalFilename, const std::string& structName) { boost::filesystem::path originalFile(originalFilename); std::string newFilename = originalFile.stem().string() + "_" + structName + originalFile.extension().string(); boost::filesystem::path newFile(originalFile.parent_path() / newFilename); return newFile.string(); } void rttb::apps::doseTool::writeDVHFile(core::DVH::DVHPointer dvh, const std::string& filename) { DVHType typeCum = { DVHType::Cumulative }; rttb::io::other::DVHXMLFileWriter dvhWriter(filename, typeCum); dvhWriter.writeDVH(dvh); } diff --git a/apps/DoseTool/DoseToolHelper.h b/apps/DoseTool/DoseToolHelper.h index 399667e..efbace2 100644 --- a/apps/DoseTool/DoseToolHelper.h +++ b/apps/DoseTool/DoseToolHelper.h @@ -1,134 +1,119 @@ // ----------------------------------------------------------------------- // 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: 1315 $ (last changed revision) -// @date $Date: 2016-04-12 14:18:24 +0200 (Di, 12 Apr 2016) $ (last change date) -// @author $Author: floca $ (last changed by) +// @version $Revision: 1374 $ (last changed revision) +// @date $Date: 2016-05-30 14:15:42 +0200 (Mo, 30 Mai 2016) $ (last change date) +// @author $Author: hentsch $ (last changed by) */ #ifndef __DOSETOOL_HELPER_H #define __DOSETOOL_HELPER_H #include "DoseToolApplicationData.h" #include "rttbDoseAccessorInterface.h" #include "rttbDoseIteratorInterface.h" #include "rttbMaskAccessorInterface.h" #include "rttbDoseStatistics.h" #include "rttbDVH.h" namespace rttb { namespace apps { namespace doseTool { /*! @brief loads a dose from a file based on the loadingStyle. @exception Throws an rttb::Exception if loading fails */ core::DoseAccessorInterface::DoseAccessorPointer loadDose(const std::string& fileName, const rttb::apps::doseTool::ApplicationData::LoadingStyleArgType& args); /*! @brief loads a dicom dose from a file. @exception Throws an rttb::Exception if loading fails @sa DicomFileDoseAccessorGenerator */ core::DoseAccessorInterface::DoseAccessorPointer loadDicomDose(const std::string& fileName); /*! @brief loads a helax dose from a file. @exception Throws an rttb::Exception if loading fails @sa DicomHelaxFileDoseAccessorGenerator */ core::DoseAccessorInterface::DoseAccessorPointer loadHelaxDose(const std::string& path); /*! @brief loads an itk dose from a file. @exception Throws an rttb::Exception if loading fails. @details Might be of all formats that ITK know (*.mhd, *.nrrd, ...). The absolute image values are taken as dose. @sa ITKImageFileAccessorGenerator */ core::DoseAccessorInterface::DoseAccessorPointer loadITKDose(const std::string& fileName); - /*! @brief loads a virtuos dose from a file. - @exception Throws an rttb::Exception if loading fails - @sa VirtuosPlanFileDoseAccessorGenerator - */ - core::DoseAccessorInterface::DoseAccessorPointer loadVirtuosDose(const std::string& fileName, - const std::string& planFileName); - /*! @brief loads a struct from a file based on the loadingStyle. - You may pass a structure name regex. If is not empty, it will be used to filter structure in the - loading process. Only structures with a name matching the reg ex will be loaded. This speeds up the - loading process significantly if you need only one structure out of a structure set. + You may pass a structure name regex. If is not empty, it will be used to filter structure in the + loading process. Only structures with a name matching the reg ex will be loaded. This speeds up the + loading process significantly if you need only one structure out of a structure set. @exception Throws an rttb::Exception if loading fails @details voxelized itk images are read in generateMask() directly */ core::StructureSetGeneratorInterface::StructureSetPointer loadStruct(const std::string& fileName, - const rttb::apps::doseTool::ApplicationData::LoadingStyleArgType& args, const std::string& structNameRegex = ""); + const rttb::apps::doseTool::ApplicationData::LoadingStyleArgType& args, const std::string& structNameRegex = ""); /*! @brief loads a dicom struct from a file. - You may pass a structure name regex. If is not empty, it will be used to filter structure in the - loading process. Only structures with a name matching the reg ex will be loaded. This speeds up the - loading process significantly if you need only one structure out of a structure set. + You may pass a structure name regex. If is not empty, it will be used to filter structure in the + loading process. Only structures with a name matching the reg ex will be loaded. This speeds up the + loading process significantly if you need only one structure out of a structure set. @exception Throws an rttb::Exception if loading fails @sa DicomFileStructureSetGenerator */ core::StructureSetGeneratorInterface::StructureSetPointer loadDicomStruct( - const std::string& fileName, const std::string& structNameRegex = ""); - - /*! @brief loads a virtuos struct from a file. - @exception Throws an rttb::Exception if loading fails - @sa VirtuosPlanFileDoseAccessorGenerator - */ - core::StructureSetGeneratorInterface::StructureSetPointer loadVirtuosStruct( - const std::string& fileName, - const std::string& ctxFileName); + const std::string& fileName, const std::string& structNameRegex = ""); /*! @brief Contains the business logic of processing all information to calculate the dose statistics and writing them to an xml file. @details Uses appData for the input data and the correct configuration. */ void processData(ApplicationData& appData); /*! @brief Generates a mask from the struct file by using the boostAccessor. In case of itk image, it directly loads the voxelized image. */ std::vector generateMasks( ApplicationData& appData); algorithms::DoseStatistics::DoseStatisticsPointer calculateDoseStatistics( core::DoseIteratorInterface::DoseIteratorPointer doseIterator, bool calculateComplexDoseStatistics, DoseTypeGy prescribedDose); core::DVH::DVHPointer calculateDVH(core::DoseIteratorInterface::DoseIteratorPointer doseIterator, IDType structUID, IDType doseUID); /*! @brief Writes the dose statistics as XML to a file @details adds a .... part to the RTTB generated xml where the used files and struct names are stored. */ void writeDoseStatisticsFile(algorithms::DoseStatistics::DoseStatisticsPointer statistics, const std::string& filename, const std::string& structName, rttb::apps::doseTool::ApplicationData& appData); void writeDVHFile(core::DVH::DVHPointer dvh, const std::string& filename); core::DoseIteratorInterface::DoseIteratorPointer generateMaskedDoseIterator( core::MaskAccessorInterface::MaskAccessorPointer maskAccessorPtr, core::DoseAccessorInterface::DoseAccessorPointer doseAccessorPtr); std::string assembleFilenameWithStruct(const std::string& originalFilename, const std::string& structName); } } } #endif diff --git a/apps/DoseTool4V/CMakeLists.txt b/apps/DoseTool4V/CMakeLists.txt new file mode 100644 index 0000000..3daddfd --- /dev/null +++ b/apps/DoseTool4V/CMakeLists.txt @@ -0,0 +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") +ENDIF() diff --git a/apps/DoseTool4V/DoseTool4V.cpp b/apps/DoseTool4V/DoseTool4V.cpp new file mode 100644 index 0000000..5e1ecc0 --- /dev/null +++ b/apps/DoseTool4V/DoseTool4V.cpp @@ -0,0 +1,161 @@ +// ----------------------------------------------------------------------- +// 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: 1315 $ (last changed revision) +// @date $Date: 2016-04-12 14:18:24 +0200 (Di, 12 Apr 2016) $ (last change date) +// @author $Author: floca $ (last changed by) +*/ + +#include "../DoseTool/DoseToolApplicationData.h" +#include "../DoseTool/DoseToolHelper.h" +#include "../DoseTool/DoseToolCmdLineParser.h" +#include "DoseTool4VHelper.h" + +#include "boost/shared_ptr.hpp" +#include "boost/make_shared.hpp" + +#include "RTToolboxConfigure.h" + +#include "rttbException.h" + +rttb::apps::doseTool::ApplicationData appData; + +int main(int argc, const char** argv) +{ + int result = 0; + + boost::shared_ptr argParser; + + try + { + std::string appName = "DoseTool4V"; + std::string appVersion = RTTB_FULL_VERSION_STRING; + + argParser = boost::make_shared(argc, argv, appName, + appVersion, true); + } + catch (const std::exception& e) + { + std::cerr << e.what() << std::endl; + return 5; + } + + // This is vital. The application needs to exit if the "help" or "version" parameter is set + // because this means the other parameters won't be parsed. + + if (argParser->isSet(argParser->OPTION_HELP) || argParser->isSet(argParser->OPTION_VERSION)) + { + return 0; + } + + rttb::apps::doseTool::populateAppData(argParser, appData); + + std::cout << std::endl << "*******************************************" << std::endl; + std::cout << "Dose file: " << appData._doseFileName << std::endl; + std::cout << "Struct file: " << appData._structFileName << std::endl; + std::cout << "Struct name: " << appData._structNameRegex << std::endl; + + if (appData._computeDoseStatistics) + { + std::cout << "Dose statistic output file: " << appData._doseStatisticOutputFileName << std::endl; + std::cout << "Compute complex statistics: " << appData._computeComplexDoseStatistics << std::endl; + + if (appData._computeComplexDoseStatistics) + { + std::cout << "Prescribed dose: " << appData._prescribedDose << std::endl; + } + + std::cout << "Allow self intersections: " << appData._allowSelfIntersection << std::endl; + } + + if (appData._computeDVH) + { + std::cout << "DVH output file: " << appData._dvhOutputFilename << std::endl; + } + + try + { + appData._dose = rttb::apps::doseTool4V::loadDose(appData._doseFileName, appData._doseLoadStyle); + } + catch (rttb::core::Exception& e) + { + std::cerr << "RTTB Error!!!" << std::endl; + std::cerr << e.what() << std::endl; + return 1; + } + catch (const std::exception& e) + { + std::cerr << "Error!!!" << std::endl; + std::cerr << e.what() << std::endl; + return 1; + } + catch (...) + { + std::cerr << "Error!!! unknown error while reading dose image." << std::endl; + return 1; + } + + //loading of structure file not necessary in ITK case as it can be used directly as mask input. + if (appData._structLoadStyle.front() != "itk") + { + try + { + appData._struct = rttb::apps::doseTool4V::loadStruct(appData._structFileName, + appData._structLoadStyle, appData._structNameRegex); + } + catch (rttb::core::Exception& e) + { + std::cerr << "RTTB Error!!!" << std::endl; + std::cerr << e.what() << std::endl; + return 2; + } + catch (const std::exception& e) + { + std::cerr << "Error!!!" << std::endl; + std::cerr << e.what() << std::endl; + return 2; + } + catch (...) + { + std::cerr << "Error!!! unknown error while reading struct image." << std::endl; + return 2; + } + } + + try + { + rttb::apps::doseTool::processData(appData); + } + catch (rttb::core::Exception& e) + { + std::cerr << "RTTB Error!!!" << std::endl; + std::cerr << e.what() << std::endl; + return 3; + } + catch (std::exception& e) + { + std::cerr << "Error!!!" << std::endl; + std::cerr << e.what() << std::endl; + return 3; + } + catch (...) + { + std::cerr << "Error!!! unknown error while processing the data or writing the image." << std::endl; + return 3; + } + + return result; +} diff --git a/apps/BioModelCalc/BioModelCalcHelper.cpp b/apps/DoseTool4V/DoseTool4VHelper.cpp similarity index 54% copy from apps/BioModelCalc/BioModelCalcHelper.cpp copy to apps/DoseTool4V/DoseTool4VHelper.cpp index b833eaf..ff1d530 100644 --- a/apps/BioModelCalc/BioModelCalcHelper.cpp +++ b/apps/DoseTool4V/DoseTool4VHelper.cpp @@ -1,152 +1,161 @@ // ----------------------------------------------------------------------- // 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) +// @version $Revision: 1334 $ (last changed revision) +// @date $Date: 2016-04-22 11:13:22 +0200 (Fr, 22 Apr 2016) $ (last change date) // @author $Author: hentsch $ (last changed by) */ -#include "BioModelCalcHelper.h" - -#include "boost/make_shared.hpp" -#include "boost/shared_ptr.hpp" +#include "DoseTool4VHelper.h" #include "rttbExceptionMacros.h" -#include "rttbVirtuosPlanFileDoseAccessorGenerator.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomHelaxFileDoseAccessorGenerator.h" #include "rttbITKImageFileAccessorGenerator.h" -#include "rttbITKImageAccessorConverter.h" -#include "rttbImageWriter.h" -#include "rttbLQModelAccessor.h" +#include "rttbVirtuosPlanFileDoseAccessorGenerator.h" +#include "rttbDicomFileStructureSetGenerator.h" +#include "rttbVirtuosFileStructureSetGenerator.h" rttb::core::DoseAccessorInterface::DoseAccessorPointer -rttb::apps::bioModelCalc::loadDose(const std::string& fileName, - const rttb::apps::bioModelCalc::ApplicationData::LoadingStyleArgType& args) +rttb::apps::doseTool4V::loadDose(const std::string& fileName, +const LoadingStyleArgType& args) { rttb::core::DoseAccessorInterface::DoseAccessorPointer result; std::cout << std::endl << "read dose file... "; if (args.empty() || args[0] == "dicom") { std::cout << "use RTTB dicom IO... "; result = loadDicomDose(fileName); } else if (args[0] == "helax") { std::cout << "use RTTB Helax IO... "; result = loadHelaxDose(fileName); } else if (args[0] == "itk") { std::cout << "use RTTB itk IO... "; result = loadITKDose(fileName); } else if (args[0] == "virtuos") { if (args.size() < 2) { rttbDefaultExceptionStaticMacro( << "Cannot load virtuos dose. Plan file is missing. Specify plan file as 2nd io stlye argument."); } std::cout << "use RTTB virtuos IO... " << std::endl; std::cout << " virtuos plan file: " << args[1] << " ... "; result = loadVirtuosDose(fileName, args[1]); } else { rttbDefaultExceptionStaticMacro( << "Unknown io style selected. Cannot load data. Selected style: " << args[0]); } std::cout << "done." << std::endl; return result; -}; +} rttb::core::DoseAccessorInterface::DoseAccessorPointer -rttb::apps::bioModelCalc::loadDicomDose(const std::string& fileName) +rttb::apps::doseTool4V::loadDicomDose(const std::string& fileName) { rttb::io::dicom::DicomFileDoseAccessorGenerator generator(fileName); return generator.generateDoseAccessor(); -}; +} rttb::core::DoseAccessorInterface::DoseAccessorPointer -rttb::apps::bioModelCalc::loadHelaxDose(const std::string& path) +rttb::apps::doseTool4V::loadHelaxDose(const std::string& path) { rttb::io::helax::DicomHelaxFileDoseAccessorGenerator generator(path); return generator.generateDoseAccessor(); -}; +} rttb::core::DoseAccessorInterface::DoseAccessorPointer -rttb::apps::bioModelCalc::loadITKDose(const std::string& fileName) +rttb::apps::doseTool4V::loadITKDose(const std::string& fileName) { rttb::io::itk::ITKImageFileAccessorGenerator generator(fileName); return generator.generateDoseAccessor(); -}; +} rttb::core::DoseAccessorInterface::DoseAccessorPointer -rttb::apps::bioModelCalc::loadVirtuosDose(const std::string& fileName, - const std::string& planFileName) +rttb::apps::doseTool4V::loadVirtuosDose(const std::string& fileName, const std::string& planFileName) { rttb::io::virtuos::VirtuosPlanFileDoseAccessorGenerator generator(fileName, planFileName); return generator.generateDoseAccessor(); -}; - +} -void -rttb::apps::bioModelCalc::processData(rttb::apps::bioModelCalc::ApplicationData& appData) +rttb::core::StructureSetGeneratorInterface::StructureSetPointer rttb::apps::doseTool4V::loadStruct( + const std::string& fileName, const LoadingStyleArgType& args, + const std::string& structNameRegex) { - rttb::core::DoseAccessorInterface::DoseAccessorPointer outputAccessor; - - std::cout << std::endl << "generate biomodel... "; - auto bioModelAccessor = generateBioModel(appData._dose, appData._model, appData._modelParameters, - appData._doseScaling); - std::cout << "done." << std::endl; - std::cout << std::endl << "generate output image... "; - io::itk::ITKImageAccessorConverter converter(bioModelAccessor); - converter.setFailOnInvalidIDs(true); - converter.process(); - io::itk::ITKImageAccessorConverter::ITKImageType::Pointer itkImage = converter.getITKImage(); - std::cout << "done." << std::endl; - std::cout << std::endl << "write output image... "; - io::itk::ImageWriter writer(appData._outputFileName, itkImage); - writer.writeFile(); - std::cout << "done." << std::endl; -}; + rttb::core::StructureSetGeneratorInterface::StructureSetPointer result; + std::cout << std::endl << "read struct file... "; -rttb::core::AccessorInterface::AccessorPointer rttb::apps::bioModelCalc::generateBioModel( - rttb::core::DoseAccessorInterface::DoseAccessorPointer dose, const std::string& model, - const std::vector& modelParameters, double doseScaling) -{ - if (model == "LQ") + if (args.empty() || args[0] == "dicom") { - return boost::make_shared(dose, modelParameters.at(0), - modelParameters.at(1), - doseScaling); + std::cout << "use RTTB dicom IO... "; + result = loadDicomStruct(fileName, structNameRegex); + } + else if (args[0] == "virtuos") + { + std::cout << "use RTTB virtuos IO... " << std::endl; + std::cout << " virtuos CTX file: " << args[1] << " ... "; + result = loadVirtuosStruct(fileName, args[1]); } else { - rttbDefaultExceptionStaticMacro( << "Unknown model selected. Cannot load data. Selected model: " - << model); + rttbDefaultExceptionStaticMacro( << "Unknown io style selected. Cannot load data. Selected style: " + << args[0]); + } + + std::cout << "done." << std::endl; + + return result; +} + +rttb::core::StructureSetGeneratorInterface::StructureSetPointer +rttb::apps::doseTool4V::loadDicomStruct( +const std::string& fileName, const std::string& structNameRegex) +{ + rttb::io::dicom::DicomFileStructureSetGenerator generator(fileName); + + if (!structNameRegex.empty()) + { + generator.setStructureLableFilterActive(true); + generator.setFilterRegEx(structNameRegex); } + + return generator.generateStructureSet(); } +rttb::core::StructureSetGeneratorInterface::StructureSetPointer +rttb::apps::doseTool4V::loadVirtuosStruct( + const std::string& fileName, const std::string& ctxFileName) +{ + rttb::io::virtuos::VirtuosFileStructureSetGenerator generator(fileName, ctxFileName.c_str()); + return generator.generateStructureSet(); +} + + diff --git a/apps/DoseTool4V/DoseTool4VHelper.h b/apps/DoseTool4V/DoseTool4VHelper.h new file mode 100644 index 0000000..99ed01b --- /dev/null +++ b/apps/DoseTool4V/DoseTool4VHelper.h @@ -0,0 +1,97 @@ +// ----------------------------------------------------------------------- +// 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: 1315 $ (last changed revision) +// @date $Date: 2016-04-12 14:18:24 +0200 (Di, 12 Apr 2016) $ (last change date) +// @author $Author: floca $ (last changed by) +*/ + +#ifndef __DOSETOOL4V_HELPER_H +#define __DOSETOOL4V_HELPER_H + +#include "rttbDoseAccessorInterface.h" +#include "rttbStructureSetGeneratorInterface.h" + +namespace rttb +{ + namespace apps + { + namespace doseTool4V + { + typedef std::vector LoadingStyleArgType; + /*! @brief loads a dose from a file based on the loadingStyle. + @exception Throws an rttb::Exception if loading fails + */ + core::DoseAccessorInterface::DoseAccessorPointer loadDose(const std::string& fileName, + const LoadingStyleArgType& args); + + /*! @brief loads a dicom dose from a file. + @exception Throws an rttb::Exception if loading fails + @sa DicomFileDoseAccessorGenerator + */ + core::DoseAccessorInterface::DoseAccessorPointer loadDicomDose(const std::string& fileName); + /*! @brief loads a helax dose from a file. + @exception Throws an rttb::Exception if loading fails + @sa DicomHelaxFileDoseAccessorGenerator + */ + core::DoseAccessorInterface::DoseAccessorPointer loadHelaxDose(const std::string& path); + /*! @brief loads an itk dose from a file. + @exception Throws an rttb::Exception if loading fails. + @details Might be of all formats that ITK know (*.mhd, *.nrrd, ...). The absolute image values are taken as dose. + @sa ITKImageFileAccessorGenerator + */ + core::DoseAccessorInterface::DoseAccessorPointer loadITKDose(const std::string& fileName); + + /*! @brief loads a virtuos dose from a file. + @exception Throws an rttb::Exception if loading fails + @sa VirtuosPlanFileDoseAccessorGenerator + */ + core::DoseAccessorInterface::DoseAccessorPointer loadVirtuosDose(const std::string& fileName, + const std::string& planFileName); + + /*! @brief loads a struct from a file based on the loadingStyle. + You may pass a structure name regex. If is not empty, it will be used to filter structure in the + loading process. Only structures with a name matching the reg ex will be loaded. This speeds up the + loading process significantly if you need only one structure out of a structure set. + @exception Throws an rttb::Exception if loading fails + @details voxelized itk images are read in generateMask() directly + */ + core::StructureSetGeneratorInterface::StructureSetPointer loadStruct(const std::string& fileName, + const LoadingStyleArgType& args, const std::string& structNameRegex = ""); + + /*! @brief loads a dicom struct from a file. + You may pass a structure name regex. If is not empty, it will be used to filter structure in the + loading process. Only structures with a name matching the reg ex will be loaded. This speeds up the + loading process significantly if you need only one structure out of a structure set. + @exception Throws an rttb::Exception if loading fails + @sa DicomFileStructureSetGenerator + */ + core::StructureSetGeneratorInterface::StructureSetPointer loadDicomStruct( + const std::string& fileName, const std::string& structNameRegex = ""); + + /*! @brief loads a virtuos struct from a file. + @exception Throws an rttb::Exception if loading fails + @sa VirtuosPlanFileDoseAccessorGenerator + */ + core::StructureSetGeneratorInterface::StructureSetPointer loadVirtuosStruct( + const std::string& fileName, + const std::string& ctxFileName); + } + } +} + + +#endif diff --git a/apps/DoseTool4V/files.cmake b/apps/DoseTool4V/files.cmake new file mode 100644 index 0000000..1783e7d --- /dev/null +++ b/apps/DoseTool4V/files.cmake @@ -0,0 +1,13 @@ +SET(CPP_FILES +DoseTool4V.cpp +DoseTool4VHelper.cpp +../DoseTool/DoseToolHelper.cpp +../DoseTool/DoseToolApplicationData.cpp +../DoseTool/DoseToolCmdLineParser.cpp +) + +SET(H_FILES +DoseTool4VHelper.h +../DoseTool/DoseToolApplicationData.h +../DoseTool/DoseToolCmdLineParser.h +) diff --git a/cmake/PackageDepends/RTTB_VirtuosIO_Config.cmake b/cmake/PackageDepends/RTTB_VirtuosIO_Config.cmake index 5acd6f0..29c88c5 100644 --- a/cmake/PackageDepends/RTTB_VirtuosIO_Config.cmake +++ b/cmake/PackageDepends/RTTB_VirtuosIO_Config.cmake @@ -1,17 +1,17 @@ #----------------------------------------------------------------------------- # Find Virtuos IO #----------------------------------------------------------------------------- FIND_PACKAGE(VirtuosIOCore) IF(VirtuosIOCore_FOUND) INCLUDE(${VirtuosIOCore_USE_FILE}) ELSE(VirtuosIOCore_FOUND) MESSAGE(FATAL_ERROR "Cannot build without VirtuosIOCore. Please set VirtuosIOCore_DIR.") ENDIF(VirtuosIOCore_FOUND) LIST(APPEND ALL_INCLUDE_DIRECTORIES ${VirtuosIOCore_INCLUDE_DIRS}) LIST(APPEND ALL_LIBRARIES VirtuosIO) -LINK_DIRECTORIES(${VirtuosIOCore_LIBRARY_DIRS}) +LINK_DIRECTORIES(${VirtuosIOCore_LIBRARY_DIRS}) # include path to gzip/gunzip diff --git a/code/core/rttbBaseType.h b/code/core/rttbBaseType.h index 5096805..7ab06dd 100644 --- a/code/core/rttbBaseType.h +++ b/code/core/rttbBaseType.h @@ -1,742 +1,743 @@ // ----------------------------------------------------------------------- // 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 __BASE_TYPE_NEW_H #define __BASE_TYPE_NEW_H #include #include #include #include #include #include #include #include #include #include namespace rttb { const double errorConstant = 1e-5; + const double reducedErrorConstant = 0.0001; typedef unsigned short UnsignedIndex1D; /*! @class UnsignedIndex2D @brief 2D index. */ class UnsignedIndex2D: public boost::numeric::ublas::vector { public: UnsignedIndex2D() : boost::numeric::ublas::vector(2) {} UnsignedIndex2D(const UnsignedIndex1D value) : boost::numeric::ublas::vector(2, value) {} const UnsignedIndex1D x() const { return (*this)(0); } const UnsignedIndex1D y() const { return (*this)(1); } }; /*! @class UnsignedIndex3D @brief 3D index. */ class UnsignedIndex3D: public boost::numeric::ublas::vector { public: UnsignedIndex3D() : boost::numeric::ublas::vector(3) {} UnsignedIndex3D(const UnsignedIndex1D value) : boost::numeric::ublas::vector(3, value) {} UnsignedIndex3D(const UnsignedIndex1D xValue, const UnsignedIndex1D yValue, const UnsignedIndex1D zValue) : boost::numeric::ublas::vector(3, xValue) { (*this)(1) = yValue; (*this)(2) = zValue; } const UnsignedIndex1D x() const { return (*this)(0); } const UnsignedIndex1D y() const { return (*this)(1); } const UnsignedIndex1D z() const { return (*this)(2); } friend bool operator==(const UnsignedIndex3D& gi1, const UnsignedIndex3D& gi2) { if (gi1.size() != gi2.size()) { return false; } for (size_t i = 0; i < gi1.size(); i++) { if (gi1(i) != gi2(i)) { return false; } } return true; } friend std::ostream& operator<<(std::ostream& s, const UnsignedIndex3D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; return s; } }; typedef std::list UnsignedIndexList; typedef std::string FileNameString; typedef std::string ContourGeometricTypeString; typedef double WorldCoordinate; /*! @class WorldCoordinate2D @brief 2D coordinate in real world coordinates. */ class WorldCoordinate2D: public boost::numeric::ublas::vector { public: WorldCoordinate2D() : boost::numeric::ublas::vector (2) {} WorldCoordinate2D(const WorldCoordinate value) : boost::numeric::ublas::vector(2, value) {} WorldCoordinate2D(const WorldCoordinate xValue, const WorldCoordinate yValue) : boost::numeric::ublas::vector(2, xValue) { (*this)(1) = yValue; } const WorldCoordinate x() const { return (*this)(0); } const WorldCoordinate y() const { return (*this)(1); } const std::string toString() const { std::stringstream ss; ss << x() << ' ' << y(); return ss.str(); } friend bool operator==(const WorldCoordinate2D& wc1, const WorldCoordinate2D& wc2) { if (wc1.size() != wc2.size()) { return false; } for (size_t i = 0; i < wc1.size(); i++) { if (wc1(i) != wc2(i)) { return false; } } return true; } }; /*! @class WorldCoordinate3D @brief 3D coordinate in real world coordinates. */ class WorldCoordinate3D: public boost::numeric::ublas::vector { public: WorldCoordinate3D() : boost::numeric::ublas::vector(3) {} WorldCoordinate3D(const WorldCoordinate value) : boost::numeric::ublas::vector(3, value) {} WorldCoordinate3D(const WorldCoordinate xValue, const WorldCoordinate yValue, const WorldCoordinate zValue) : boost::numeric::ublas::vector(3, xValue) { (*this)(1) = yValue; (*this)(2) = zValue; } WorldCoordinate3D(const WorldCoordinate3D& w): boost::numeric::ublas::vector(3) { (*this)(0) = w.x(); (*this)(1) = w.y(); (*this)(2) = w.z(); } const WorldCoordinate x() const { return (*this)(0); } const WorldCoordinate y() const { return (*this)(1); } const WorldCoordinate z() const { return (*this)(2); } //vector cross product (not included in boost.ublas) WorldCoordinate3D cross(WorldCoordinate3D aVector) const { WorldCoordinate3D result; WorldCoordinate x = (*this)(0); WorldCoordinate y = (*this)(1); WorldCoordinate z = (*this)(2); result(0) = y * aVector(2) - z * aVector(1); result(1) = z * aVector(0) - x * aVector(2); result(2) = x * aVector(1) - y * aVector(0); return result; } WorldCoordinate2D getXY() const { WorldCoordinate2D result; result(0) = (*this)(0); result(1) = (*this)(1); return result; } const std::string toString() const { std::stringstream ss; ss << x() << ' ' << y() << ' ' << z(); return ss.str(); } WorldCoordinate3D& operator=(const WorldCoordinate3D& wc) { (*this)(0) = wc.x(); (*this)(1) = wc.y(); (*this)(2) = wc.z(); return (*this); } WorldCoordinate3D& operator=(const boost::numeric::ublas::vector wc) { (*this)(0) = wc(0); (*this)(1) = wc(1); (*this)(2) = wc(2); return (*this); } WorldCoordinate3D operator-(const boost::numeric::ublas::vector wc) { return WorldCoordinate3D((*this)(0) - wc(0), (*this)(1) - wc(1), (*this)(2) - wc(2)); } WorldCoordinate3D operator+(const boost::numeric::ublas::vector wc) { return WorldCoordinate3D((*this)(0) + wc(0), (*this)(1) + wc(1), (*this)(2) + wc(2)); } friend bool operator==(const WorldCoordinate3D& wc1, const WorldCoordinate3D& wc2) { if (wc1.size() != wc2.size()) { return false; } for (size_t i = 0; i < wc1.size(); i++) { if (wc1(i) != wc2(i)) { return false; } } return true; } bool equalsAlmost(const WorldCoordinate3D& another, double errorConstant = 1e-5) const { if (size() != another.size()) { return false; } double dist = norm_2(*this - another); return dist < errorConstant; } friend std::ostream& operator<<(std::ostream& s, const WorldCoordinate3D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; return s; } }; typedef WorldCoordinate3D DoubleVoxelGridIndex3D; typedef UnsignedIndex3D ImageSize; /*! @deprecated Use OrientationMatrix instead. */ typedef WorldCoordinate3D ImageOrientation; typedef double GridVolumeType; /*! @class SpacingVectorType3D @brief 3D spacing vector. @pre values of this vector may not be negative. */ class SpacingVectorType3D: public boost::numeric::ublas::vector { public: SpacingVectorType3D() : boost::numeric::ublas::vector(3) {} SpacingVectorType3D(const GridVolumeType value) : boost::numeric::ublas::vector(3, value) {} SpacingVectorType3D(const GridVolumeType xValue, const GridVolumeType yValue, const GridVolumeType zValue) : boost::numeric::ublas::vector(3, xValue) { (*this)(1) = yValue; (*this)(2) = zValue; } SpacingVectorType3D(const SpacingVectorType3D& w): boost::numeric::ublas::vector(3) { (*this)(0) = w.x(); (*this)(1) = w.y(); (*this)(2) = w.z(); } const GridVolumeType x() const { return (*this)(0); } const GridVolumeType y() const { return (*this)(1); } const GridVolumeType z() const { return (*this)(2); } const std::string toString() const { std::stringstream ss; ss << x() << ' ' << y() << ' ' << z(); return ss.str(); } SpacingVectorType3D& operator=(const SpacingVectorType3D& wc) { (*this)(0) = wc.x(); (*this)(1) = wc.y(); (*this)(2) = wc.z(); return (*this); } SpacingVectorType3D& operator=(const WorldCoordinate3D& wc) { (*this)(0) = GridVolumeType(wc.x()); (*this)(1) = GridVolumeType(wc.y()); (*this)(2) = GridVolumeType(wc.z()); return (*this); } SpacingVectorType3D& operator=(const boost::numeric::ublas::vector wc) { (*this)(0) = wc(0); (*this)(1) = wc(1); (*this)(2) = wc(2); return (*this); } friend bool operator==(const SpacingVectorType3D& wc1, const SpacingVectorType3D& wc2) { if (wc1.size() != wc2.size()) { return false; } for (size_t i = 0; i < wc1.size(); i++) { if (wc1(i) != wc2(i)) { return false; } } return true; } bool equalsAlmost(const SpacingVectorType3D& another, double errorConstant) const { if ((*this).size() != another.size()) { return false; } double dist = norm_2(*this - another); return dist < errorConstant; } friend std::ostream& operator<<(std::ostream& s, const SpacingVectorType3D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; return s; } }; /*! @class OrientationMatrix @brief Used to store image orientation information */ class OrientationMatrix : public boost::numeric::ublas::matrix { public: /*! The default constructor generates a 3x3 unit matrix */ OrientationMatrix() : boost::numeric::ublas::matrix(3, 3, 0) { for (std::size_t m = 0; m < (*this).size1(); m++) { (*this)(m, m) = 1; } } OrientationMatrix(const WorldCoordinate value) : boost::numeric::ublas::matrix(3, 3, value) {} bool equalsAlmost(const OrientationMatrix& anOrientationMatrix, double errorConstant) const { if (anOrientationMatrix.size1() == (*this).size1()) { if (anOrientationMatrix.size2() == (*this).size2()) { for (std::size_t m = 0; m < anOrientationMatrix.size1(); m++) { for (std::size_t n = 0; n < anOrientationMatrix.size2(); n++) { if ((abs((*this)(m, n) - anOrientationMatrix(m, n)) > errorConstant)) { return false; } } }// end element comparison } else { return false; } } else { return false; } return true; } friend bool operator==(const OrientationMatrix& om1, const OrientationMatrix& om2) { return om1.equalsAlmost(om2, 0.0); } friend std::ostream& operator<<(std::ostream& s, const OrientationMatrix& anOrientationMatrix) { s << "[ "; for (std::size_t m = 0; m < anOrientationMatrix.size1(); m++) { s << "[ "; for (std::size_t n = 0; n < anOrientationMatrix.size2(); n++) { if (n == 0) { s << anOrientationMatrix(m, n); } else { s << ", " << anOrientationMatrix(m, n); } } s << " ]"; } s << " ]"; return s; } }; /*! base for 2D and 3D VoxelIndex; Therefore required beside VoxelGridID */ typedef unsigned int GridIndexType; /*! @class VoxelGridIndex3D @brief 3D voxel grid index. */ class VoxelGridIndex3D: public boost::numeric::ublas::vector { public: VoxelGridIndex3D() : boost::numeric::ublas::vector(3) {} VoxelGridIndex3D(const GridIndexType value) : boost::numeric::ublas::vector(3, value) {} VoxelGridIndex3D(const GridIndexType xValue, const GridIndexType yValue, const GridIndexType zValue) : boost::numeric::ublas::vector(3, xValue) { (*this)(1) = yValue; (*this)(2) = zValue; } const GridIndexType x() const { return (*this)(0); } const GridIndexType y() const { return (*this)(1); } const GridIndexType z() const { return (*this)(2); } const std::string toString() const { std::stringstream ss; ss << x() << ' ' << y() << ' ' << z(); return ss.str(); } VoxelGridIndex3D& operator=(const UnsignedIndex3D& ui) { (*this)(0) = ui(0); (*this)(1) = ui(1); (*this)(2) = ui(2); return (*this); } friend bool operator==(const VoxelGridIndex3D& gi1, const VoxelGridIndex3D& gi2) { if (gi1.size() != gi2.size()) { return false; } for (size_t i = 0; i < gi1.size(); i++) { if (gi1(i) != gi2(i)) { return false; } } return true; } friend std::ostream& operator<<(std::ostream& s, const VoxelGridIndex3D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; return s; } }; /*! @class VoxelGridIndex3D @brief 2D voxel grid index. */ class VoxelGridIndex2D: public boost::numeric::ublas::vector { public: VoxelGridIndex2D() : boost::numeric::ublas::vector(2) {} VoxelGridIndex2D(const GridIndexType value) : boost::numeric::ublas::vector(2, value) {} VoxelGridIndex2D(const GridIndexType xValue, const GridIndexType yValue) : boost::numeric::ublas::vector(2, xValue) { (*this)(1) = yValue; } const GridIndexType x() const { return (*this)(0); } const GridIndexType y() const { return (*this)(1); } const std::string toString() const { std::stringstream ss; ss << x() << ' ' << y(); return ss.str(); } friend bool operator==(const VoxelGridIndex2D& gi1, const VoxelGridIndex2D& gi2) { if (gi1.size() != gi2.size()) { return false; } for (size_t i = 0; i < gi1.size(); i++) { if (gi1(i) != gi2(i)) { return false; } } return true; } friend std::ostream& operator<<(std::ostream& s, const VoxelGridIndex2D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << " ]"; return s; } }; typedef long GridSizeType; typedef int VoxelGridID; //starts from 0 and is continuously counting all positions on the grid typedef int VoxelGridDimensionType; typedef boost::numeric::ublas::vector VoxelGridDimensionVectorType; typedef double FractionType, VoxelSizeType, DVHVoxelNumber; typedef double DoseCalcType, DoseTypeGy, GenericValueType, DoseVoxelVolumeType, VolumeType, GridVolumeType, VoxelNumberType, BEDType, LQEDType; typedef std::string IDType; typedef std::string StructureLabel; struct DVHRole { enum Type { TargetVolume = 1, HealthyTissue = 2, WholeVolume = 4, UserDefined = 128 } Type; }; struct DVHType { enum Type { Differential = 1, Cumulative = 2 } Type; }; typedef std::string PatientInfoString; typedef std::string TimeString; typedef std::string FileNameType; typedef std::vector PolygonType; typedef std::vector PolygonSequenceType; typedef double IndexValueType; typedef double DoseStatisticType; typedef std::string DBStringType; typedef std::string VirtuosFileNameString, DICOMRTFileNameString; typedef unsigned short Uint16; struct Area2D { WorldCoordinate x_begin; WorldCoordinate x_end; WorldCoordinate y_begin; WorldCoordinate y_end; VoxelGridIndex2D index_begin; VoxelGridIndex2D index_end; void Init() { x_begin = -1000000; x_end = -1000000; y_begin = -1000000; y_end = -1000000; index_begin(0) = 0; index_begin(1) = 0; index_end(0) = 0; index_end(1) = 0; } }; struct Segment2D { WorldCoordinate2D begin; WorldCoordinate2D end; }; struct Segment3D { WorldCoordinate3D begin; WorldCoordinate3D end; }; typedef int DistributionType; typedef std::string PathType; typedef std::string XMLString, StatisticsString; }//end: namespace rttb #endif diff --git a/code/io/CMakeLists.txt b/code/io/CMakeLists.txt index 4c8436b..95ce070 100644 --- a/code/io/CMakeLists.txt +++ b/code/io/CMakeLists.txt @@ -1,22 +1,24 @@ MESSAGE (STATUS "processing RTToolbox io") ADD_SUBDIRECTORY (other) OPTION(BUILD_IO_Dicom "Determine if the IO class wrappers for DICOM format will be generated." ON) IF(BUILD_IO_Dicom) ADD_SUBDIRECTORY(dicom) OPTION(BUILD_IO_HELAX "Determine if the IO class wrappers for HELAX format will be generated." OFF) IF(BUILD_IO_HELAX) ADD_SUBDIRECTORY(helax) ENDIF(BUILD_IO_HELAX) ENDIF(BUILD_IO_Dicom) OPTION(BUILD_IO_ITK "Determine if the IO class wrappers for ITK image formats will be generated." OFF) IF(BUILD_IO_ITK) ADD_SUBDIRECTORY(itk) ENDIF(BUILD_IO_ITK) -OPTION(BUILD_IO_Virtuos "Determine if the IO class wrappers for Virtuos format will be generated." OFF) -IF(BUILD_IO_Virtuos) - ADD_SUBDIRECTORY(virtuos) -ENDIF(BUILD_IO_Virtuos) +IF (RTTB_VIRTUOS_SUPPORT) + OPTION(BUILD_IO_Virtuos "Determine if the IO class wrappers for Virtuos format will be generated." OFF) + IF(BUILD_IO_Virtuos) + ADD_SUBDIRECTORY(virtuos) + ENDIF(BUILD_IO_Virtuos) +ENDIF() diff --git a/testing/apps/DoseTool/CMakeLists.txt b/testing/apps/DoseTool/CMakeLists.txt index e7352c3..6f2bbcd 100644 --- a/testing/apps/DoseTool/CMakeLists.txt +++ b/testing/apps/DoseTool/CMakeLists.txt @@ -1,42 +1,46 @@ #----------------------------------------------------------------------------- # 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") + SET(DOSETOOL4VEXE "DoseTool4V.exe") ELSE (WIN32) SET(DOSETOOLEXE "./DoseTool") + SET(DOSETOOL4VEXE "./DoseTool4V") ENDIF (WIN32) ADD_TEST(DoseToolBasicUsageTest ${DOSETOOL_TEST} DoseToolBasicUsageTest ${DOSETOOLEXE}) ADD_TEST(DoseToolInvalidParametersTest ${DOSETOOL_TEST} DoseToolInvalidParametersTest ${DOSETOOLEXE}) -ADD_TEST(DoseToolVirtuosDoseVirtuosStructTest ${DOSETOOL_TEST} DoseToolVirtuosDoseTest ${DOSETOOLEXE} "${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac101.dos.gz" "${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac101.pln" - "${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac000.vdx" "${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac000.ctx.gz" "DARM" - "${TEST_DATA_ROOT}/DoseStatistics/virtuos.xml" "${TEST_DATA_ROOT}/DoseStatistics/virtuosComplex.xml") +IF(RTTB_VIRTUOS_SUPPORT AND BUILD_IO_Virtuos) + ADD_TEST(DoseToolVirtuosDoseVirtuosStructTest ${DOSETOOL_TEST} DoseToolVirtuosDoseTest ${DOSETOOL4VEXE} "${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac101.dos.gz" "${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac101.pln" + "${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac000.vdx" "${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac000.ctx.gz" "DARM" + "${TEST_DATA_ROOT}/DoseStatistics/virtuos.xml" "${TEST_DATA_ROOT}/DoseStatistics/virtuosComplex.xml") + ADD_TEST(DoseToolITKDoseVirtuosStructTest ${DOSETOOL_TEST} DoseToolITKDoseTest ${DOSETOOL4VEXE} "${TEST_DATA_ROOT}/ITK/virtuosTestDose.mhd" "${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac000.vdx" + "${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac000.ctx.gz" "DARM" "${TEST_DATA_ROOT}/DoseStatistics/itkVirtuosStruct.xml" "${TEST_DATA_ROOT}/DoseStatistics/itkVirtuosStructComplex.xml") +ENDIF() ADD_TEST(DoseToolDicomDoseDicomStructTest ${DOSETOOL_TEST} DoseToolDicomDoseTest ${DOSETOOLEXE} "${TEST_DATA_ROOT}/DICOM/TestDose/dicompylerTestDose.dcm" "${TEST_DATA_ROOT}/DICOM/StructureSet/rtss.dcm" "Nodes" "${TEST_DATA_ROOT}/DoseStatistics/dicom.xml" "${TEST_DATA_ROOT}/TestDVH/dicompylerDVH.xml" "${TEST_DATA_ROOT}/DoseStatistics/dicomComplex.xml") ADD_TEST(DoseToolITKDoseDicomStructTest ${DOSETOOL_TEST} DoseToolITKDoseTest ${DOSETOOLEXE} "${TEST_DATA_ROOT}/ITK/dicompylerTestDose.mhd" "${TEST_DATA_ROOT}/DICOM/StructureSet/rtss.dcm" "" "Nodes" "${TEST_DATA_ROOT}/DoseStatistics/itkDicomStruct.xml" "${TEST_DATA_ROOT}/DoseStatistics/itkDicomStructComplex.xml") -ADD_TEST(DoseToolITKDoseVirtuosStructTest ${DOSETOOL_TEST} DoseToolITKDoseTest ${DOSETOOLEXE} "${TEST_DATA_ROOT}/ITK/virtuosTestDose.mhd" "${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac000.vdx" - "${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac000.ctx.gz" "DARM" "${TEST_DATA_ROOT}/DoseStatistics/itkVirtuosStruct.xml" "${TEST_DATA_ROOT}/DoseStatistics/itkVirtuosStructComplex.xml") ADD_TEST(DoseToolDicomDoseDicomStructRegexTest ${DOSETOOL_TEST} DoseToolRegexTest ${DOSETOOLEXE} "${TEST_DATA_ROOT}/DICOM/TestDose/dicompylerTestDose.dcm" "dicom" "${TEST_DATA_ROOT}/DICOM/StructureSet/rtss.dcm" "dicom" "Nodes|Heart" "${TEST_DATA_ROOT}/DoseStatistics/dicom.xml" "${TEST_DATA_ROOT}/DoseStatistics/dicom_heart.xml") ADD_TEST(DoseToolDVHTest ${DOSETOOL_TEST} DoseToolDVHTest ${DOSETOOLEXE} "${TEST_DATA_ROOT}/DICOM/TestDose/dicompylerTestDose.dcm" "${TEST_DATA_ROOT}/DICOM/StructureSet/rtss.dcm" "Nodes" "${TEST_DATA_ROOT}/TestDVH/dicompylerDVH.xml") RTTB_CREATE_APPLICATION_TESTS(DoseTool PACKAGE_DEPENDS Litmus BoostBinaries) diff --git a/testing/apps/DoseTool/DoseToolInvalidParametersTest.cpp b/testing/apps/DoseTool/DoseToolInvalidParametersTest.cpp index bec104f..ebbee85 100644 --- a/testing/apps/DoseTool/DoseToolInvalidParametersTest.cpp +++ b/testing/apps/DoseTool/DoseToolInvalidParametersTest.cpp @@ -1,109 +1,109 @@ // ----------------------------------------------------------------------- // 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: 771 $ (last changed revision) -// @date $Date: 2014-09-25 14:41:34 +0200 (Do, 25 Sep 2014) $ (last change date) -// @author $Author: zhangl $ (last changed by) +// @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 #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 DoseToolInvalidParametersTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string doseToolExecutable; if (argc > 1) { doseToolExecutable = argv[1]; } boost::filesystem::path callingPath(_callingAppPath); std::string doseToolExeWithPath = callingPath.parent_path().string() + "/" + doseToolExecutable; //call with too few parameters std::string toofewParametersCommand = doseToolExeWithPath; toofewParametersCommand += " -d test"; toofewParametersCommand += " -s test"; std::cout << "Command line call: " + toofewParametersCommand << std::endl; CHECK_EQUAL(system(toofewParametersCommand.c_str()) != 0, true); toofewParametersCommand = doseToolExeWithPath; toofewParametersCommand += " -s test"; toofewParametersCommand += " -n test"; std::cout << "Command line call: " + toofewParametersCommand << std::endl; CHECK_EQUAL(system(toofewParametersCommand.c_str()) != 0, true); toofewParametersCommand = doseToolExeWithPath; toofewParametersCommand += " test"; toofewParametersCommand += " test"; std::cout << "Command line call: " + toofewParametersCommand << std::endl; CHECK_EQUAL(system(toofewParametersCommand.c_str()) != 0, true); toofewParametersCommand = doseToolExeWithPath; toofewParametersCommand += " -d test"; toofewParametersCommand += " -s test"; toofewParametersCommand += " -n test"; std::cout << "Command line call: " + toofewParametersCommand << std::endl; CHECK_EQUAL(system(toofewParametersCommand.c_str()) != 0, true); //call with invalid dose load option std::string minimalCLI = doseToolExeWithPath + " test test test "; std::string invalidDoseLoadOption = minimalCLI; invalidDoseLoadOption += "-t wrongOption"; std::cout << "Command line call: " + invalidDoseLoadOption << std::endl; CHECK_EQUAL(system(invalidDoseLoadOption.c_str()) != 0, true); //call with invalid struct load option std::string invalidStructLoadOption = minimalCLI; invalidStructLoadOption += "-u wrongOption"; std::cout << "Command line call: " + invalidStructLoadOption << std::endl; CHECK_EQUAL(system(invalidStructLoadOption.c_str()) != 0, true); //call with virtuos dose load option, but without plan/ctx std::string invalidVirtuosDoseLoadOption = minimalCLI; invalidVirtuosDoseLoadOption += "-u virtuos"; std::cout << "Command line call: " + invalidVirtuosDoseLoadOption << std::endl; CHECK_EQUAL(system(invalidVirtuosDoseLoadOption.c_str()) != 0, true); std::string invalidVirtuosStructLoadOption = minimalCLI; invalidVirtuosStructLoadOption += "-t virtuos"; std::cout << "Command line call: " + invalidVirtuosStructLoadOption << std::endl; CHECK_EQUAL(system(invalidVirtuosStructLoadOption.c_str()) != 0, true); //call with complex dose statistics, but without prescribed dose std::string complexDoseWithoutPrescribedDoseCommand = minimalCLI; complexDoseWithoutPrescribedDoseCommand += "-x"; std::cout << "Command line call: " + complexDoseWithoutPrescribedDoseCommand << std::endl; CHECK_EQUAL(system(complexDoseWithoutPrescribedDoseCommand.c_str()) != 0, true); RETURN_AND_REPORT_TEST_SUCCESS; } } //namespace testing } //namespace rttb diff --git a/testing/apps/DoseTool/DoseToolRegexTest.cpp b/testing/apps/DoseTool/DoseToolRegexTest.cpp index 5226155..73e6cca 100644 --- a/testing/apps/DoseTool/DoseToolRegexTest.cpp +++ b/testing/apps/DoseTool/DoseToolRegexTest.cpp @@ -1,144 +1,144 @@ // ----------------------------------------------------------------------- // 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: 771 $ (last changed revision) -// @date $Date: 2014-09-25 14:41:34 +0200 (Do, 25 Sep 2014) $ (last change date) -// @author $Author: zhangl $ (last changed by) +// @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 #include #include #include "litCheckMacros.h" #include "boost/filesystem.hpp" #include "boost/algorithm/string.hpp" namespace rttb { namespace testing { //path to the current running directory. DoseTool is in the same directory (Debug/Release) extern const char* _callingAppPath; static std::string readFile(const std::string& filename); int DoseToolRegexTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string doseToolExecutable; std::string doseFilename; std::string doseLoadStyle; std::string structFilename; std::string structLoadStyle; std::string structName; std::string referenceXMLFilename; std::string referenceXMLFilename2; boost::filesystem::path callingPath(_callingAppPath); if (argc > 8) { doseToolExecutable = argv[1]; doseFilename = argv[2]; doseLoadStyle = argv[3]; structFilename = argv[4]; structLoadStyle = argv[5]; structName = argv[6]; referenceXMLFilename = argv[7]; referenceXMLFilename2 = argv[8]; } std::string doseToolExeWithPath = callingPath.parent_path().string() + "/" + doseToolExecutable; std::string defaultOutputFilename = "regexOutput.xml"; std::string defaultExpectedOutputFilename = "regexOutput_Nodes.xml"; std::string defaultExpectedOutputFilename2 = "regexOutput_Heart.xml"; std::string baseCommand = doseToolExeWithPath; baseCommand += " -d " + doseFilename; baseCommand += " -t " + doseLoadStyle; baseCommand += " -s " + structFilename; baseCommand += " -u " + structLoadStyle; baseCommand += " -n \"" + structName + "\""; baseCommand += " -y " + defaultOutputFilename; std::cout << "Command line call: " + baseCommand << std::endl; CHECK_EQUAL(system(baseCommand.c_str()), 0); CHECK_EQUAL(boost::filesystem::exists(defaultOutputFilename), true); CHECK_EQUAL(boost::filesystem::exists(defaultExpectedOutputFilename), false); CHECK_EQUAL(boost::filesystem::exists(defaultExpectedOutputFilename2), false); CHECK_EQUAL(std::remove(defaultOutputFilename.c_str()), 0); std::string defaultDoseStatisticsCommand = baseCommand + " -m"; std::cout << "Command line call: " + defaultDoseStatisticsCommand << std::endl; CHECK_EQUAL(system(defaultDoseStatisticsCommand.c_str()), 0); //check if two file were written CHECK_EQUAL(boost::filesystem::exists(defaultExpectedOutputFilename), true); CHECK_EQUAL(boost::filesystem::exists(defaultExpectedOutputFilename2), true); //check if file is the same than reference file std::string defaultAsIs = readFile(defaultExpectedOutputFilename); std::string defaultExpected = readFile(referenceXMLFilename); //add doseFile and structFile std::string emptyDoseFileTag = ""; std::string validDoseFileTag = "" + doseFilename + ""; boost::replace_all(defaultExpected, emptyDoseFileTag, validDoseFileTag); std::string emptyStructFileTag = ""; std::string validStructFileTag = "" + structFilename + ""; boost::replace_all(defaultExpected, emptyStructFileTag, validStructFileTag); std::string requestedStructRegexTag = "Nodes"; std::string validStructRegexTag = "" + structName + ""; boost::replace_all(defaultExpected, requestedStructRegexTag, validStructRegexTag); CHECK_EQUAL(defaultAsIs, defaultExpected); //add doseFile and structFile std::string default2AsIs = readFile(defaultExpectedOutputFilename2); std::string default2Expected = readFile(referenceXMLFilename2); boost::replace_all(default2Expected, emptyDoseFileTag, validDoseFileTag); boost::replace_all(default2Expected, emptyStructFileTag, validStructFileTag); requestedStructRegexTag = "Heart"; validStructRegexTag = "" + structName + ""; boost::replace_all(default2Expected, requestedStructRegexTag, validStructRegexTag); CHECK_EQUAL(default2AsIs, default2Expected); //delete file again CHECK_EQUAL(std::remove(defaultExpectedOutputFilename.c_str()), 0); CHECK_EQUAL(std::remove(defaultExpectedOutputFilename2.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; } } //namespace testing } //namespace rttb diff --git a/testing/apps/DoseTool/DoseToolTests.cpp b/testing/apps/DoseTool/DoseToolTests.cpp index 18276bf..eab725b 100644 --- a/testing/apps/DoseTool/DoseToolTests.cpp +++ b/testing/apps/DoseTool/DoseToolTests.cpp @@ -1,73 +1,80 @@ // ----------------------------------------------------------------------- // 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: 771 $ (last changed revision) -// @date $Date: 2014-09-25 14:41:34 +0200 (Do, 25 Sep 2014) $ (last change date) -// @author $Author: zhangl $ (last changed by) +// @version $Revision: 1374 $ (last changed revision) +// @date $Date: 2016-05-30 14:15:42 +0200 (Mo, 30 Mai 2016) $ (last change date) +// @author $Author: hentsch $ (last changed by) */ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called registerTests() #if defined(_MSC_VER) #pragma warning ( disable : 4786 ) #endif #include "litMultiTestsMain.h" +#include "RTToolboxConfigure.h" + namespace rttb { namespace testing { const char* _callingAppPath = NULL; void registerTests() { LIT_REGISTER_TEST(DoseToolBasicUsageTest); LIT_REGISTER_TEST(DoseToolInvalidParametersTest); - LIT_REGISTER_TEST(DoseToolVirtuosDoseTest); + + if (RTTB_VIRTUOS_SUPPORT) + { + LIT_REGISTER_TEST(DoseToolVirtuosDoseTest); + } + LIT_REGISTER_TEST(DoseToolDicomDoseTest); LIT_REGISTER_TEST(DoseToolITKDoseTest); LIT_REGISTER_TEST(DoseToolRegexTest); LIT_REGISTER_TEST(DoseToolDVHTest); } } //namespace testing } //namespace map int main(int argc, char* argv[]) { int result = 0; rttb::testing::registerTests(); if (argc > 0) { rttb::testing::_callingAppPath = argv[0]; } try { result = lit::multiTestsMain(argc, argv); } catch (...) { result = -1; } return result; } diff --git a/testing/apps/DoseTool/files.cmake b/testing/apps/DoseTool/files.cmake index 56313aa..c912a7f 100644 --- a/testing/apps/DoseTool/files.cmake +++ b/testing/apps/DoseTool/files.cmake @@ -1,13 +1,18 @@ + + SET(CPP_FILES DoseToolBasicUsageTest.cpp DoseToolInvalidParametersTest.cpp - DoseToolVirtuosDoseTest.cpp DoseToolDicomDoseTest.cpp DoseToolITKDoseTest.cpp DoseToolRegexTest.cpp DoseToolDVHTest.cpp DoseToolTests.cpp ) + +IF (RTTB_VIRTUOS_SUPPORT AND BUILD_IO_Virtuos) + SET(CPP_FILES ${CPP_FILES} DoseToolVirtuosDoseTest.cpp) +ENDIF() SET(H_FILES ) diff --git a/testing/examples/CMakeLists.txt b/testing/examples/CMakeLists.txt index e443665..c5bfc0c 100644 --- a/testing/examples/CMakeLists.txt +++ b/testing/examples/CMakeLists.txt @@ -1,41 +1,48 @@ #----------------------------------------------------------------------------- # 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}/TestDVH/dvh_PTV_HIT.txt" "${TEST_DATA_ROOT}/TestDVH/dvh_test_HT1.txt" "${TEST_DATA_ROOT}/TestDVH/dvh_test_HT2.txt" "${TEST_DATA_ROOT}/TestDVH/dvh_test_HT3.txt" "${TEST_DATA_ROOT}/TestDVH/dvh_test_TV.txt" "${TEST_DATA_ROOT}/TestDVH/dvh_virtuos_diff_trunk6.txt" "${TEST_DATA_ROOT}/TestDVH/dvh_virtuos_diff_trunk8.txt") ADD_TEST(DVHCalculatorExampleTest ${CORE_TEST_EXAMPLES} DVHCalculatorExampleTest "${TEST_DATA_ROOT}/DICOM/StructureSet/RS1.3.6.1.4.1.2452.6.841242143.1311652612.1170940299.4217870819.dcm" "${TEST_DATA_ROOT}/DICOM/TestDose/ConstantTwoGridScaling.dcm" "${TEST_DATA_ROOT}/DICOM/TestDose/ConstantTwoGridScaling05.dcm" "${TEST_DATA_ROOT}/DICOM/TestDose/ConstantFiftyGridScaling01.dcm") ADD_TEST(RTDoseIndexTest ${CORE_TEST_EXAMPLES} RTDoseIndexTest "${TEST_DATA_ROOT}/TestDVH/dvh_test_TV.txt" "${TEST_DATA_ROOT}/TestDVH/dvh_test_HT1.txt" "${TEST_DATA_ROOT}/TestDVH/dvh_test_HT2.txt" "${TEST_DATA_ROOT}/TestDVH/dvh_test_HT3.txt") -ADD_TEST(RTDoseStatisticsTest ${CORE_TEST_EXAMPLES} RTDoseStatisticsTest -"${TEST_DATA_ROOT}/DICOM/TestDose/ConstantTwo_withDoseGridScaling.dcm" -"${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac101.dos.gz" -"${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac000.vdx" -"${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac101.pln") +ADD_TEST(RTDoseStatisticsDicomTest ${CORE_TEST_EXAMPLES} RTDoseStatisticsDicomTest +"${TEST_DATA_ROOT}/DICOM/TestDose/ConstantTwo_withDoseGridScaling.dcm") +IF(RTTB_VIRTUOS_SUPPORT AND BUILD_IO_Virtuos) + ADD_TEST(RTDoseStatisticsVirtuosTest ${CORE_TEST_EXAMPLES} RTDoseStatisticsVirtuosTest + "${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac101.dos.gz" + "${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac000.vdx" + "${TEST_DATA_ROOT}/Virtuos/prostate_ac/prostate_ac101.pln") +ENDIF() ADD_TEST(RTDVHTest ${CORE_TEST_EXAMPLES} RTDVHTest "${TEST_DATA_ROOT}/TestDVH/dvh_test.txt") ADD_TEST(DVHCalculatorExampleTest ${CORE_TEST_EXAMPLES} DVHCalculatorExampleTest "${TEST_DATA_ROOT}/DICOM/StructureSet/RS1.3.6.1.4.1.2452.6.841242143.1311652612.1170940299.4217870819.dcm" "${TEST_DATA_ROOT}/DICOM/TestDose/ConstantTwo_withDoseGridScaling.dcm" "${TEST_DATA_ROOT}/DICOM/TestDose/LinearIncrease3D.dcm" "${TEST_DATA_ROOT}/DICOM/TestDose/LinearIncreaseX.dcm") ADD_TEST(RTBioModelScatterPlotExampleTest ${CORE_TEST_EXAMPLES} RTBioModelScatterPlotExampleTest "${TEST_DATA_ROOT}/TestDVH/dvh_PTV_HIT.txt" "${TEST_DATA_ROOT}/TestDVH/dvh_test_HT1.txt" "${TEST_DATA_ROOT}/TestDVH/dvh_test_TV.txt") ADD_TEST(VoxelizationValidationTest ${CORE_TEST_EXAMPLES} VoxelizationValidationTest "${TEST_DATA_ROOT}/DICOM/StructureSet/RS1.3.6.1.4.1.2452.6.841242143.1311652612.1170940299.4217870819.dcm" "${TEST_DATA_ROOT}/DICOM/TestDose/LinearIncrease3D.dcm" "${TEST_DATA_ROOT}/BoostMask/" "${TEST_DATA_ROOT}/OTBMask/" "${TEST_DATA_ROOT}/BoostMaskRedesign/") -RTTB_CREATE_TEST_MODULE(rttbExamples DEPENDS RTTBCore RTTBAlgorithms RTTBMasks RTTBOTBMask RTTBBoostMask RTTBIndices RTTBDicomIO RTTBVirtuosIO RTTBITKIO RTTBOtherIO RTTBModels PACKAGE_DEPENDS Litmus) +IF(RTTB_VIRTUOS_SUPPORT AND BUILD_IO_Virtuos) + RTTB_CREATE_TEST_MODULE(rttbExamples DEPENDS RTTBCore RTTBAlgorithms RTTBMasks RTTBOTBMask RTTBBoostMask RTTBIndices RTTBDicomIO RTTBVirtuosIO RTTBITKIO RTTBOtherIO RTTBModels PACKAGE_DEPENDS Litmus) +ELSE() + RTTB_CREATE_TEST_MODULE(rttbExamples DEPENDS RTTBCore RTTBAlgorithms RTTBMasks RTTBOTBMask RTTBBoostMask RTTBIndices RTTBDicomIO RTTBITKIO RTTBOtherIO RTTBModels PACKAGE_DEPENDS Litmus) +ENDIF() diff --git a/testing/examples/RTDoseStatisticsDicomTest.cpp b/testing/examples/RTDoseStatisticsDicomTest.cpp new file mode 100644 index 0000000..540c25f --- /dev/null +++ b/testing/examples/RTDoseStatisticsDicomTest.cpp @@ -0,0 +1,118 @@ +// ----------------------------------------------------------------------- +// 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) +*/ + +// this file defines the rttbCoreTests for the test driver +// and all it expects is that you have a function called RegisterTests + +#include +#include + +#include "litCheckMacros.h" + +#include "rttbDoseStatistics.h" +#include "rttbDoseStatisticsCalculator.h" +#include "rttbDicomDoseAccessor.h" +#include "rttbDicomFileDoseAccessorGenerator.h" +#include "rttbBoostMaskAccessor.h" +#include "rttbGenericMaskedDoseIterator.h" +#include "rttbGenericDoseIterator.h" +#include "rttbBaseType.h" + +namespace rttb +{ + namespace testing + { + + + /*! @brief RTDoseStatisticsTest. Max, min, mean, standard deviation, variance, Vx, Dx, MOHx, MOCx, MaxOHx, + MinOCx are tested. Test if calculation in new architecture returns similar results to the original implementation. + + WARNING: The values for comparison need to be adjusted if the input files are changed!*/ + + int RTDoseStatisticsDicomTest(int argc, char* argv[]) + { + PREPARE_DEFAULT_TEST_REPORTING; + std::string RTDOSE_FILENAME; + + if (argc > 1) + { + RTDOSE_FILENAME = argv[1]; + } + else + { + std::cout << "at least one arguments required for RTDoseStatisticsDicomTest" << std::endl; + return -1; + } + + double expectedVal = 5.64477e-005; + double volume = 24120.; + + typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; + typedef core::GenericDoseIterator::DoseIteratorPointer DoseIteratorPointer; + typedef algorithms::DoseStatisticsCalculator::ResultListPointer ResultListPointer; + + io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1(RTDOSE_FILENAME.c_str()); + DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); + + //create corresponding DoseIterator + ::boost::shared_ptr spDoseIteratorTmp = + ::boost::make_shared(doseAccessor1); + DoseIteratorPointer spDoseIterator(spDoseIteratorTmp); + rttb::algorithms::DoseStatisticsCalculator doseStatisticsCalculator(spDoseIterator); + + std::vector precomputedDoseValues; + precomputedDoseValues.push_back(0); + precomputedDoseValues.push_back(0.5); + precomputedDoseValues.push_back(1); + std::vector precomputedVolumeValues; + precomputedVolumeValues.push_back(20000 / volume); + precomputedVolumeValues.push_back(1); + + rttb::algorithms::DoseStatistics::DoseStatisticsPointer doseStatistics = + doseStatisticsCalculator.calculateDoseStatistics(precomputedDoseValues, precomputedVolumeValues); + + CHECK_CLOSE(doseStatistics->getMean(), expectedVal, errorConstant); + CHECK_CLOSE(doseStatistics->getStdDeviation(), 0, errorConstant); + CHECK_CLOSE(doseStatistics->getVariance(), 0, errorConstant); + + double dummy; + DoseTypeGy vx = doseStatistics->getVx(expectedVal, true, dummy); + CHECK_EQUAL(vx, doseStatistics->getVx(0)); + CHECK_CLOSE(expectedVal, doseStatistics->getDx(vx), reducedErrorConstant); + + CHECK_CLOSE(doseStatistics->getMaximum(), expectedVal, errorConstant); + + CHECK_CLOSE(doseStatistics->getMinimum(), expectedVal, errorConstant); + ResultListPointer minListPtr = doseStatistics->getMinimumVoxelPositions(); + ResultListPointer maxListPtr = doseStatistics->getMaximumVoxelPositions(); + CHECK_EQUAL(maxListPtr->size(), 10); + CHECK_EQUAL(minListPtr->size(), 10); + + CHECK_CLOSE(doseStatistics->getDx(24120), doseStatistics->getMinimum(), 0.001); + CHECK_CLOSE(doseStatistics->getMOHx(24120), doseStatistics->getMean(), reducedErrorConstant); + CHECK_CLOSE(doseStatistics->getMOCx(20000), doseStatistics->getMean(), reducedErrorConstant); + CHECK_CLOSE(doseStatistics->getMinOCx(20000), doseStatistics->getMean(), reducedErrorConstant); + + RETURN_AND_REPORT_TEST_SUCCESS; + } + + }//testing +}//rttb diff --git a/testing/examples/RTDoseStatisticsTest.cpp b/testing/examples/RTDoseStatisticsVirtuosTest.cpp similarity index 55% rename from testing/examples/RTDoseStatisticsTest.cpp rename to testing/examples/RTDoseStatisticsVirtuosTest.cpp index e3d5818..81b29be 100644 --- a/testing/examples/RTDoseStatisticsTest.cpp +++ b/testing/examples/RTDoseStatisticsVirtuosTest.cpp @@ -1,206 +1,138 @@ // ----------------------------------------------------------------------- // 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) +// @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) */ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests #include #include #include "litCheckMacros.h" #include "rttbDoseStatistics.h" #include "rttbDoseStatisticsCalculator.h" -#include "rttbDicomDoseAccessor.h" -#include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbVirtuosPlanFileDoseAccessorGenerator.h" #include "rttbVirtuosFileStructureSetGenerator.h" #include "rttbBoostMaskAccessor.h" #include "rttbGenericMaskedDoseIterator.h" #include "rttbGenericDoseIterator.h" #include "rttbBaseType.h" namespace rttb { namespace testing { - PREPARE_DEFAULT_TEST_REPORTING; + /*! @brief RTDoseStatisticsTest. Max, min, mean, standard deviation, variance, Vx, Dx, MOHx, MOCx, MaxOHx, MinOCx are tested. Test if calculation in new architecture returns similar results to the original implementation. WARNING: The values for comparison need to be adjusted if the input files are changed!*/ - const double reducedErrorConstant = 0.0001; - const double expectedVal = 5.64477e-005; - const double volume = 24120.; - - void testWithDummyDoseData(const std::string& doseFilename); - void testWithRealVirtuosDoseDataAndStructure(const std::string& doseFilename, - const std::string& structFilename, - const std::string& planFilename, unsigned int structureNr); - int RTDoseStatisticsTest(int argc, char* argv[]) + int RTDoseStatisticsVirtuosTest(int argc, char* argv[]) { - + PREPARE_DEFAULT_TEST_REPORTING; std::string RTDOSE_FILENAME; - std::string RTDOSE2_FILENAME; std::string RTSTRUCT_FILENAME; std::string RTPLAN_FILENAME; - if (argc > 4) + if (argc > 3) { RTDOSE_FILENAME = argv[1]; - RTDOSE2_FILENAME = argv[2]; - RTSTRUCT_FILENAME = argv[3]; - RTPLAN_FILENAME = argv[4]; + RTSTRUCT_FILENAME = argv[2]; + RTPLAN_FILENAME = argv[3]; } else { - std::cout << "at least four arguments required for RTDoseStatisticsTest" << std::endl; + std::cout << "at least three arguments required for RTDoseStatisticsVirtuosTest" << std::endl; return -1; } - testWithDummyDoseData(RTDOSE_FILENAME); //Structure 2 is RUECKENMARK - testWithRealVirtuosDoseDataAndStructure(RTDOSE2_FILENAME, RTSTRUCT_FILENAME, RTPLAN_FILENAME, 2); - - RETURN_AND_REPORT_TEST_SUCCESS; - } - - void testWithDummyDoseData(const std::string& doseFilename) - { - typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; - typedef core::GenericDoseIterator::DoseIteratorPointer DoseIteratorPointer; - typedef algorithms::DoseStatisticsCalculator::ResultListPointer ResultListPointer; - - io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1(doseFilename.c_str()); - DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); - - //create corresponding DoseIterator - ::boost::shared_ptr spDoseIteratorTmp = - ::boost::make_shared(doseAccessor1); - DoseIteratorPointer spDoseIterator(spDoseIteratorTmp); - rttb::algorithms::DoseStatisticsCalculator doseStatisticsCalculator(spDoseIterator); - - std::vector precomputedDoseValues; - precomputedDoseValues.push_back(0); - precomputedDoseValues.push_back(0.5); - precomputedDoseValues.push_back(1); - std::vector precomputedVolumeValues; - precomputedVolumeValues.push_back(20000 / volume); - precomputedVolumeValues.push_back(1); - - rttb::algorithms::DoseStatistics::DoseStatisticsPointer doseStatistics = - doseStatisticsCalculator.calculateDoseStatistics(precomputedDoseValues, precomputedVolumeValues); - - CHECK_CLOSE(doseStatistics->getMean(), expectedVal, errorConstant); - CHECK_CLOSE(doseStatistics->getStdDeviation(), 0, errorConstant); - CHECK_CLOSE(doseStatistics->getVariance(), 0, errorConstant); - - double dummy; - DoseTypeGy vx = doseStatistics->getVx(expectedVal, true, dummy); - CHECK_EQUAL(vx, doseStatistics->getVx(0)); - CHECK_CLOSE(expectedVal, doseStatistics->getDx(vx), reducedErrorConstant); - - CHECK_CLOSE(doseStatistics->getMaximum(), expectedVal, errorConstant); - - CHECK_CLOSE(doseStatistics->getMinimum(), expectedVal, errorConstant); - ResultListPointer minListPtr = doseStatistics->getMinimumVoxelPositions(); - ResultListPointer maxListPtr = doseStatistics->getMaximumVoxelPositions(); - CHECK_EQUAL(maxListPtr->size(), 10); - CHECK_EQUAL(minListPtr->size(), 10); - - CHECK_CLOSE(doseStatistics->getDx(24120), doseStatistics->getMinimum(), 0.001); - CHECK_CLOSE(doseStatistics->getMOHx(24120), doseStatistics->getMean(), reducedErrorConstant); - CHECK_CLOSE(doseStatistics->getMOCx(20000), doseStatistics->getMean(), reducedErrorConstant); - CHECK_CLOSE(doseStatistics->getMinOCx(20000), doseStatistics->getMean(), reducedErrorConstant); - } - - void testWithRealVirtuosDoseDataAndStructure(const std::string& doseFilename, - const std::string& structFilename, - const std::string& planFilename, unsigned int structureNr) - { typedef core::GenericDoseIterator::DoseIteratorPointer DoseIteratorPointer; typedef core::GenericMaskedDoseIterator::MaskAccessorPointer MaskAccessorPointer; typedef rttb::algorithms::DoseStatistics::DoseStatisticsPointer DoseStatisticsPointer; typedef core::DoseIteratorInterface::DoseAccessorPointer DoseAccessorPointer; typedef core::StructureSetGeneratorInterface::StructureSetPointer StructureSetPointer; typedef algorithms::DoseStatisticsCalculator::ResultListPointer ResultListPointer; DoseAccessorPointer virtuosDoseAccessor = io::virtuos::VirtuosPlanFileDoseAccessorGenerator( - doseFilename.c_str(), - planFilename.c_str()).generateDoseAccessor(); + RTDOSE_FILENAME.c_str(), + RTPLAN_FILENAME.c_str()).generateDoseAccessor(); StructureSetPointer virtuosStructureSet = io::virtuos::VirtuosFileStructureSetGenerator( - structFilename.c_str(), doseFilename.c_str()).generateStructureSet(); + RTSTRUCT_FILENAME.c_str(), RTDOSE_FILENAME.c_str()).generateStructureSet(); boost::shared_ptr spOTBMaskAccessorVirtuos = - boost::make_shared(virtuosStructureSet->getStructure(structureNr), + boost::make_shared(virtuosStructureSet->getStructure(2), virtuosDoseAccessor->getGeometricInfo()); spOTBMaskAccessorVirtuos->updateMask(); MaskAccessorPointer spMaskAccessor(spOTBMaskAccessorVirtuos); //create corresponding MaskedDoseIterator boost::shared_ptr spMaskedDoseIteratorTmp = boost::make_shared(spMaskAccessor, virtuosDoseAccessor); DoseIteratorPointer spMaskedDoseIterator(spMaskedDoseIteratorTmp); rttb::algorithms::DoseStatisticsCalculator doseStatisticsCalculatorVirtuos(spMaskedDoseIterator); DoseStatisticsPointer doseStatisticsVirtuos = doseStatisticsCalculatorVirtuos.calculateDoseStatistics(true); //comparison values computed with "old" DoseStatistics implementation CHECK_CLOSE(doseStatisticsVirtuos->getMinimum(), 6.4089, reducedErrorConstant); CHECK_CLOSE(doseStatisticsVirtuos->getMaximum(), 39.0734, reducedErrorConstant); CHECK_CLOSE(doseStatisticsVirtuos->getMean(), 22.5779, reducedErrorConstant); CHECK_CLOSE(doseStatisticsVirtuos->getStdDeviation(), 6.28857, reducedErrorConstant); ResultListPointer maxPositions = doseStatisticsVirtuos->getMaximumVoxelPositions(); ResultListPointer minPositions = doseStatisticsVirtuos->getMinimumVoxelPositions(); CHECK_EQUAL(maxPositions->size(), 1); CHECK_EQUAL(minPositions->size(), 1); CHECK_EQUAL(maxPositions->begin()->first, doseStatisticsVirtuos->getMaximum()); CHECK_EQUAL(maxPositions->begin()->second, 3570772); CHECK_EQUAL(minPositions->begin()->first, doseStatisticsVirtuos->getMinimum()); CHECK_EQUAL(minPositions->begin()->second, 3571264); CHECK_CLOSE(doseStatisticsVirtuos->getDx(0.02 * doseStatisticsVirtuos->getVolume()), 31.8358, reducedErrorConstant); CHECK_CLOSE(doseStatisticsVirtuos->getVx(0.9 * doseStatisticsVirtuos->getMaximum()), 0.471747, reducedErrorConstant); CHECK_CLOSE(doseStatisticsVirtuos->getMOHx(0.1 * doseStatisticsVirtuos->getVolume()), 31.3266, reducedErrorConstant); CHECK_CLOSE(doseStatisticsVirtuos->getMOCx(0.05 * doseStatisticsVirtuos->getVolume()), 9.01261, reducedErrorConstant); CHECK_CLOSE(doseStatisticsVirtuos->getMaxOHx(0.95 * doseStatisticsVirtuos->getVolume()), 10.3764, reducedErrorConstant); CHECK_CLOSE(doseStatisticsVirtuos->getMinOCx(0.98 * doseStatisticsVirtuos->getVolume()), 31.8373, reducedErrorConstant); + + RETURN_AND_REPORT_TEST_SUCCESS; + } }//testing }//rttb diff --git a/testing/examples/files.cmake b/testing/examples/files.cmake index 58f3bf0..afb95f3 100644 --- a/testing/examples/files.cmake +++ b/testing/examples/files.cmake @@ -1,17 +1,23 @@ +SET(DOSESTATISTICSVIRTUOSTEST "") +IF(RTTB_VIRTUOS_SUPPORT AND BUILD_IO_Virtuos) + SET(DOSESTATISTICSVIRTUOSTEST "RTDoseStatisticsVirtuosTest.cpp") +ENDIF() + SET(CPP_FILES RTBioModelExampleTest.cpp RTBioModelScatterPlotExampleTest.cpp RTDoseIndexTest.cpp - RTDoseStatisticsTest.cpp + RTDoseStatisticsDicomTest.cpp + ${DOSESTATISTICSVIRTUOSTEST} RTDVHTest.cpp DVHCalculatorExampleTest.cpp DVHCalculatorComparisonTest.cpp ../models/rttbScatterTester.cpp rttbTestExamples.cpp VoxelizationValidationTest.cpp ) SET(H_FILES ../models/rttbScatterTester.h ) diff --git a/testing/examples/rttbTestExamples.cpp b/testing/examples/rttbTestExamples.cpp index abc8840..6595247 100644 --- a/testing/examples/rttbTestExamples.cpp +++ b/testing/examples/rttbTestExamples.cpp @@ -1,68 +1,76 @@ // ----------------------------------------------------------------------- // 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) */ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests #if defined(_MSC_VER) #pragma warning ( disable : 4786 ) #endif #include "litMultiTestsMain.h" +#include "RTToolboxConfigure.h" + namespace rttb { namespace testing { void registerTests() { LIT_REGISTER_TEST(RTBioModelExampleTest); LIT_REGISTER_TEST(DVHCalculatorExampleTest); LIT_REGISTER_TEST(RTDVHTest); LIT_REGISTER_TEST(RTDoseIndexTest); - LIT_REGISTER_TEST(RTDoseStatisticsTest); + + if (RTTB_VIRTUOS_SUPPORT) + { + LIT_REGISTER_TEST(RTDoseStatisticsVirtuosTest); + } + + LIT_REGISTER_TEST(RTDoseStatisticsDicomTest); LIT_REGISTER_TEST(RTBioModelScatterPlotExampleTest); LIT_REGISTER_TEST(VoxelizationValidationTest); } } } int main(int argc, char* argv[]) { int result = 0; rttb::testing::registerTests(); try { result = lit::multiTestsMain(argc, argv); } catch (const std::exception& /*e*/) { result = -1; } catch (...) { result = -1; } return result; } diff --git a/testing/io/CMakeLists.txt b/testing/io/CMakeLists.txt index 757c3db..6b0166b 100644 --- a/testing/io/CMakeLists.txt +++ b/testing/io/CMakeLists.txt @@ -1,26 +1,23 @@ MESSAGE (STATUS "Process All IO Tests...") #----------------------------------------------------------------------------- # Include sub directories #----------------------------------------------------------------------------- ADD_SUBDIRECTORY (other) IF(BUILD_IO_Dicom) ADD_SUBDIRECTORY(dicom) IF(BUILD_IO_HELAX) ADD_SUBDIRECTORY(helax) ENDIF(BUILD_IO_HELAX) ENDIF(BUILD_IO_Dicom) IF(BUILD_IO_ITK) ADD_SUBDIRECTORY(itk) ENDIF(BUILD_IO_ITK) - IF(BUILD_IO_Virtuos) - ADD_SUBDIRECTORY(virtuos) - ENDIF(BUILD_IO_Virtuos) - - - +IF(BUILD_IO_Virtuos) +ADD_SUBDIRECTORY(virtuos) +ENDIF(BUILD_IO_Virtuos) \ No newline at end of file