diff --git a/CMakeLists.txt b/CMakeLists.txt index 4fb292e..9f1a9ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,324 +1,323 @@ #----------------------------------------------------------------------------- # This is the root RTToolbox CMakeList file. #----------------------------------------------------------------------------- PROJECT(RTToolbox) CMAKE_MINIMUM_REQUIRED(VERSION 3.1) # RTToolbox version number. SET(RTToolbox_VERSION_MAJOR "5") SET(RTToolbox_VERSION_MINOR "1") SET(RTToolbox_VERSION_PATCH "0") # Version string should not include patch level. The major.minor is # enough to distinguish available features of the toolbox. SET(RTToolbox_VERSION_STRING "${RTToolbox_VERSION_MAJOR}.${RTToolbox_VERSION_MINOR}") SET(RTToolbox_FULL_VERSION_STRING "${RTToolbox_VERSION_MAJOR}.${RTToolbox_VERSION_MINOR}.${RTToolbox_VERSION_PATCH}") # default build type SET(CMAKE_BUILD_TYPE Release) MARK_AS_ADVANCED(BUILD_SHARED_LIBS) IF (WIN32) IF (MSVC_VERSION LESS 1800) MESSAGE(FATAL_ERROR "RTToolbox requires at least Visual Studio 2013.") ENDIF() add_definitions(-D_SCL_SECURE_NO_WARNINGS) ELSE (WIN32) IF (CMAKE_COMPILER_IS_GNUCC) IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 5.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.0) MESSAGE(AUTHOR_WARNING "RTToolbox requires at leas GCC 4.8. GCC 5.x and 6.x were not tested. You are using GCC " ${CMAKE_CXX_COMPILER_VERSION} ". This compiler version might not work.") ENDIF() ENDIF() ENDIF(WIN32) IF(COMMAND CMAKE_POLICY) # Enable old CMake behaviour when dealing with export_library_dependencies(). # This is necessary to avoid warnings in CMake versions # greater than 3.0 # See http://www.cmake.org/cmake/help/v3.0/policy/CMP0033.html CMAKE_POLICY(SET CMP0033 OLD) IF(POLICY CMP0062) CMAKE_POLICY(SET CMP0062 OLD) ENDIF() ENDIF(COMMAND CMAKE_POLICY) #----------------------------------------------------------------------------- # CMake Function(s) and Macro(s) #----------------------------------------------------------------------------- include(cmake/MacroParseArguments.cmake) include(cmake/rttbMacroCreateModuleConf.cmake) include(cmake/rttbMacroCreateModule.cmake) include(cmake/rttbMacroCreateApplication.cmake) include(cmake/rttbMacroCheckModule.cmake) include(cmake/rttbMacroUseModule.cmake) include(cmake/rttbMacroCreateTestModule.cmake) include(cmake/rttbFunctionOrganizeSources.cmake) include(cmake/rttbMacroCreateApplicationTests.cmake) #----------------------------------------------------------------------------- # Basis config RTTB module infrastructure #----------------------------------------------------------------------------- set(RTTB_MODULES_CONF_DIR ${RTToolbox_BINARY_DIR}/modulesConf CACHE INTERNAL "Modules Conf") set(RTTB_MODULES_PACKAGE_DEPENDS_DIR ${RTToolbox_SOURCE_DIR}/cmake/PackageDepends) set(MODULES_PACKAGE_DEPENDS_DIRS ${RTTB_MODULES_PACKAGE_DEPENDS_DIR}) #----------------------------------------------------------------------------- # Testing setup # Configure Dart testing support. This should be done before any # MESSAGE(FATAL_ERROR ...) commands are invoked. #----------------------------------------------------------------------------- #build no tests as default OPTION(BUILD_TESTING "build tests" OFF) IF(BUILD_TESTING) SET(CTEST_NEW_FORMAT 1) INCLUDE(CTest) ENABLE_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 (NOT RTTB_CXX_STANDARD) set(RTTB_CXX_STANDARD 11) ENDIF (NOT RTTB_CXX_STANDARD) set(CMAKE_CXX_STANDARD ${RTTB_CXX_STANDARD} CACHE STRING "") set(CMAKE_CXX_STANDARD_REQUIRED 1) OPTION(CMAKE_CXX_EXTENSIONS "" ON) MARK_AS_ADVANCED(CMAKE_CXX_STANDARD CMAKE_CXX_STANDARD_REQUIRED CMAKE_CXX_EXTENSIONS) 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) 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}) #Raise warning level (MSVC has W3 default warning level) IF (WIN32) IF(NOT BUILD_SHARED_LIBS) set(CMAKE_CXX_FLAGS "/W4 /EHsc") ENDIF() ELSE() IF (CMAKE_COMPILER_IS_GNUCC) set(CMAKE_CXX_FLAGS "-W4") ENDIF() ENDIF() 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_All_Modules "All modules will be built" OFF) OPTION(BUILD_Apps "Determine if the CLI applications will be generated." OFF) MESSAGE (STATUS "generating Project RTToolbox") ADD_SUBDIRECTORY (code) IF (BUILD_Apps) ADD_SUBDIRECTORY (apps) ENDIF() IF (BUILD_TESTING) ADD_SUBDIRECTORY (testing) ENDIF (BUILD_TESTING) ADD_SUBDIRECTORY (documentation) #----------------------------------------------------------------------------- # Help other projects use RTToolbox. #----------------------------------------------------------------------------- EXPORT(PACKAGE RTToolbox) # Copy the UseRTToolbox.cmake file to the binary tree for backward compatability. CONFIGURE_FILE(${RTToolbox_SOURCE_DIR}/UseRTToolbox.cmake.in ${RTToolbox_BINARY_DIR}/UseRTToolbox.cmake COPYONLY IMMEDIATE) # Save library dependencies. EXPORT_LIBRARY_DEPENDENCIES(${RTToolbox_BINARY_DIR}/RTToolboxLibraryDepends.cmake) # Create the RTToolboxConfig.cmake file containing the RTToolbox configuration. INCLUDE (${RTToolbox_SOURCE_DIR}/rttbGenerateRTToolboxConfig.cmake) IF(NOT RTToolbox_INSTALL_NO_DEVELOPMENT) INSTALL(FILES ${RTToolbox_BINARY_DIR}/RTToolboxConfig.cmake ${RTToolbox_BINARY_DIR}/RTToolboxTargets.cmake ${RTToolbox_BINARY_DIR}/RTToolboxLibraryDepends.cmake ${RTToolbox_BINARY_DIR}/UseRTToolbox.cmake DESTINATION ${RTTOOLBOX_INSTALL_PACKAGE_DIR} COMPONENT Development ) ENDIF(NOT RTToolbox_INSTALL_NO_DEVELOPMENT) diff --git a/apps/DoseAcc/DoseAccHelper.cpp b/apps/DoseAcc/DoseAccHelper.cpp index 6e07b45..f8e197b 100644 --- a/apps/DoseAcc/DoseAccHelper.cpp +++ b/apps/DoseAcc/DoseAccHelper.cpp @@ -1,240 +1,231 @@ // ----------------------------------------------------------------------- // 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: 1132 $ (last changed revision) // @date $Date: 2015-10-06 14:48:56 +0200 (Di, 06 Okt 2015) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "DoseAccHelper.h" #include "boost/make_shared.hpp" #include "mapRegistrationFileReader.h" #include "rttbExceptionMacros.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomHelaxFileDoseAccessorGenerator.h" #include "rttbITKImageAccessorConverter.h" #include "rttbSimpleMappableDoseAccessor.h" #include "rttbMatchPointTransformation.h" #include "rttbLinearInterpolation.h" #include "rttbNearestNeighborInterpolation.h" #include "rttbRosuMappableDoseAccessor.h" #include "rttbITKImageFileAccessorGenerator.h" #include "rttbArithmetic.h" #include "rttbBinaryFunctorAccessor.h" #include "rttbImageWriter.h" rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::doseAcc::loadDose(const std::string& fileName, const rttb::apps::doseAcc::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 { 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::doseAcc::loadDicomDose(const std::string& fileName) { rttb::io::dicom::DicomFileDoseAccessorGenerator generator(fileName); return generator.generateDoseAccessor(); }; rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::doseAcc::loadHelaxDose(const std::string& path) { rttb::io::helax::DicomHelaxFileDoseAccessorGenerator generator(path); return generator.generateDoseAccessor(); }; rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::doseAcc::loadITKDose(const std::string& fileName) { rttb::io::itk::ITKImageFileAccessorGenerator generator(fileName); return generator.generateDoseAccessor(); }; rttb::apps::doseAcc::ApplicationData::RegistrationType::Pointer rttb::apps::doseAcc::loadRegistration(const std::string& fileName) { map::io::RegistrationFileReader::Pointer spRegReader = map::io::RegistrationFileReader::New(); map::io::RegistrationFileReader::LoadedRegistrationPointer spReg; std::cout << std::endl << "read registration file... "; spReg = spRegReader->read(fileName); std::cout << "done." << std::endl; ApplicationData::RegistrationType::Pointer resultPtr = dynamic_cast(spReg.GetPointer()); if (resultPtr.IsNull()) { rttbDefaultExceptionStaticMacro( << "Loaded registration cannot be used. Only 3D 3D registrations are allowed."); } return resultPtr; }; rttb::core::DoseAccessorInterface::DoseAccessorPointer generateNNMappableAccessor( const rttb::core::GeometricInfo& geoInfoTargetImage, const rttb::core::DoseAccessorInterface::DoseAccessorPointer doseMovingImage, const rttb::interpolation::TransformationInterface::Pointer aTransformation) { - rttb::interpolation::InterpolationBase::Pointer interpolate = - rttb::interpolation::NearestNeighborInterpolation::Pointer(new - rttb::interpolation::NearestNeighborInterpolation()); + auto interpolate = boost::make_shared(); - return rttb::core::DoseAccessorInterface::DoseAccessorPointer( - new rttb::interpolation::SimpleMappableDoseAccessor(geoInfoTargetImage, doseMovingImage, - aTransformation, interpolate)); + return boost::make_shared(geoInfoTargetImage, doseMovingImage, + aTransformation, interpolate); } rttb::core::DoseAccessorInterface::DoseAccessorPointer generateLinearMappableAccessor( const rttb::core::GeometricInfo& geoInfoTargetImage, const rttb::core::DoseAccessorInterface::DoseAccessorPointer doseMovingImage, const rttb::interpolation::TransformationInterface::Pointer aTransformation) { - rttb::interpolation::InterpolationBase::Pointer interpolate = - rttb::interpolation::LinearInterpolation::Pointer(new - rttb::interpolation::LinearInterpolation()); + auto interpolate = boost::make_shared(); - return rttb::core::DoseAccessorInterface::DoseAccessorPointer( - new rttb::interpolation::SimpleMappableDoseAccessor(geoInfoTargetImage, doseMovingImage, - aTransformation, interpolate)); + return boost::make_shared(geoInfoTargetImage, doseMovingImage, + aTransformation, interpolate); } rttb::core::DoseAccessorInterface::DoseAccessorPointer generateRosuMappableAccessor( const rttb::core::GeometricInfo& geoInfoTargetImage, const rttb::core::DoseAccessorInterface::DoseAccessorPointer doseMovingImage, const rttb::interpolation::TransformationInterface::Pointer aTransformation) { - return rttb::core::DoseAccessorInterface::DoseAccessorPointer( - new rttb::interpolation::RosuMappableDoseAccessor(geoInfoTargetImage, doseMovingImage, - aTransformation)); + return boost::make_shared(geoInfoTargetImage, doseMovingImage, + aTransformation); } /**Private helper function for processData(). Generates a suitable output accessor * (depending on the configuration in appData a suitable accessor pipeline is established) * which performs the accumulation of the doses and returns the output.to */ rttb::core::DoseAccessorInterface::DoseAccessorPointer assembleOutputAccessor(rttb::apps::doseAcc::ApplicationData& appData) { rttb::core::DoseAccessorInterface::DoseAccessorPointer dose2Accessor = appData._dose2; if (appData._spReg.IsNotNull()) { - rttb::interpolation::TransformationInterface::Pointer transform = - rttb::interpolation::TransformationInterface::Pointer(new - rttb::interpolation::MatchPointTransformation(appData._spReg)); + auto transform = boost::make_shared(appData._spReg); if (appData._interpolatorName == "rosu") { dose2Accessor = generateRosuMappableAccessor(appData._dose1->getGeometricInfo(), appData._dose2, transform); } else if (appData._interpolatorName == "nn") { dose2Accessor = generateNNMappableAccessor(appData._dose1->getGeometricInfo(), appData._dose2, transform); } else if (appData._interpolatorName == "linear") { dose2Accessor = generateLinearMappableAccessor(appData._dose1->getGeometricInfo(), appData._dose2, transform); } else { rttbDefaultExceptionStaticMacro( << "Unkown interpolation type selected. Cannot map dose. Interpolation type: " << appData._interpolatorName); } } rttb::core::DoseAccessorInterface::DoseAccessorPointer outputAccessor; if (appData._operator == "+") { rttb::algorithms::arithmetic::doseOp::AddWeighted addOp(appData._weightDose1, appData._weightDose2); outputAccessor = boost::make_shared >(appData._dose1, dose2Accessor, addOp); } else if (appData._operator == "*") { outputAccessor = boost::make_shared > (appData._dose1, dose2Accessor, rttb::algorithms::arithmetic::doseOp::Multiply()); } else { rttbDefaultExceptionStaticMacro( << "Unkown operator selected. Cannot map dose. Operator: " << appData._interpolatorName); } return outputAccessor; } void rttb::apps::doseAcc::processData(rttb::apps::doseAcc::ApplicationData& appData) { rttb::core::DoseAccessorInterface::DoseAccessorPointer outputAccessor = assembleOutputAccessor( appData); std::cout << std::endl << "generate output image... "; io::itk::ITKImageAccessorConverter converter(outputAccessor); 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.GetPointer()); writer.writeFile(); std::cout << "done." << std::endl; }; diff --git a/apps/DoseMap/DoseMapHelper.cpp b/apps/DoseMap/DoseMapHelper.cpp index 69d9260..9327e63 100644 --- a/apps/DoseMap/DoseMapHelper.cpp +++ b/apps/DoseMap/DoseMapHelper.cpp @@ -1,184 +1,179 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1127 $ (last changed revision) // @date $Date: 2015-10-01 13:33:33 +0200 (Do, 01 Okt 2015) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "DoseMapHelper.h" +#include + #include "mapRegistrationFileReader.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomHelaxFileDoseAccessorGenerator.h" #include "rttbITKImageAccessorConverter.h" #include "rttbSimpleMappableDoseAccessor.h" #include "rttbMatchPointTransformation.h" #include "rttbLinearInterpolation.h" #include "rttbNearestNeighborInterpolation.h" #include "rttbRosuMappableDoseAccessor.h" #include "rttbITKImageFileAccessorGenerator.h" #include "rttbArithmetic.h" #include "rttbBinaryFunctorAccessor.h" #include "rttbExceptionMacros.h" #include "rttbImageWriter.h" rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::doseMap::loadDose(const std::string& fileName, const rttb::apps::doseMap::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 { 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::doseMap::loadDicomDose(const std::string& fileName) { rttb::io::dicom::DicomFileDoseAccessorGenerator generator(fileName); return generator.generateDoseAccessor(); }; rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::doseMap::loadHelaxDose(const std::string& path) { rttb::io::helax::DicomHelaxFileDoseAccessorGenerator generator(path); return generator.generateDoseAccessor(); }; rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::doseMap::loadITKDose(const std::string& fileName) { rttb::io::itk::ITKImageFileAccessorGenerator generator(fileName); return generator.generateDoseAccessor(); }; rttb::apps::doseMap::ApplicationData::RegistrationType::Pointer rttb::apps::doseMap::loadRegistration(const std::string& fileName) { map::io::RegistrationFileReader::Pointer spRegReader = map::io::RegistrationFileReader::New(); map::io::RegistrationFileReader::LoadedRegistrationPointer spReg; std::cout << std::endl << "read registration file... "; spReg = spRegReader->read(fileName); std::cout << "done." << std::endl; ApplicationData::RegistrationType::Pointer resultPtr = dynamic_cast(spReg.GetPointer()); if (resultPtr.IsNull()) { mapDefaultExceptionStaticMacro( << "Loaded registration cannot be used. Only 3D 3D registrations are allowed."); } return resultPtr; }; /**Private helper function for processData(). Generates a suitable output accessor * (depending on the configuration in appData a suitable accessor pipeline is established) * which performs the accumulation of the doses and returns the output.to */ rttb::core::DoseAccessorInterface::DoseAccessorPointer assembleOutputAccessor(rttb::apps::doseMap::ApplicationData& appData) { rttb::core::DoseAccessorInterface::DoseAccessorPointer outputAccessor = appData._inputDose; - rttb::interpolation::TransformationInterface::Pointer transform = - rttb::interpolation::TransformationInterface::Pointer(new - rttb::interpolation::MatchPointTransformation(appData._spReg)); + auto transform = boost::make_shared(appData._spReg); if (appData._interpolatorName == "rosu") { - outputAccessor = rttb::core::DoseAccessorInterface::DoseAccessorPointer( - new rttb::interpolation::RosuMappableDoseAccessor(appData._refDose->getGeometricInfo(), - appData._inputDose, transform)); + outputAccessor = boost::make_shared(appData._refDose->getGeometricInfo(), + appData._inputDose, transform); } else { - rttb::interpolation::InterpolationBase::Pointer interpolate = - rttb::interpolation::LinearInterpolation::Pointer(new - rttb::interpolation::LinearInterpolation()); + rttb::interpolation::InterpolationBase::Pointer interpolate = boost::make_shared(); if (appData._interpolatorName == "nn") { - interpolate = rttb::interpolation::NearestNeighborInterpolation::Pointer(new - rttb::interpolation::NearestNeighborInterpolation()); + interpolate = boost::make_shared(); } else if (appData._interpolatorName != "linear") { mapDefaultExceptionStaticMacro( << "Unkown interpolation type selected. Cannot map dose. Interpolation type: " << appData._interpolatorName); } - outputAccessor = rttb::core::DoseAccessorInterface::DoseAccessorPointer( - new rttb::interpolation::SimpleMappableDoseAccessor(appData._refDose->getGeometricInfo(), - appData._inputDose, transform, interpolate)); + outputAccessor = boost::make_shared(appData._refDose->getGeometricInfo(), + appData._inputDose, transform, interpolate); } return outputAccessor; } void rttb::apps::doseMap::processData(rttb::apps::doseMap::ApplicationData& appData) { rttb::core::DoseAccessorInterface::DoseAccessorPointer outputAccessor = assembleOutputAccessor( appData); std::cout << std::endl << "generate output image... "; io::itk::ITKImageAccessorConverter converter(outputAccessor); 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.GetPointer()); writer.writeFile(); std::cout << "done." << std::endl; }; diff --git a/code/interpolation/rttbInterpolationBase.cpp b/code/interpolation/rttbInterpolationBase.cpp index d2651e3..966b6d8 100644 --- a/code/interpolation/rttbInterpolationBase.cpp +++ b/code/interpolation/rttbInterpolationBase.cpp @@ -1,197 +1,197 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include #include #include "rttbInterpolationBase.h" #include "rttbInvalidParameterException.h" #include "rttbNullPointerException.h" #include "rttbMappingOutsideOfImageException.h" namespace rttb { namespace interpolation { void InterpolationBase::setAccessorPointer(const AccessorPointer originalData) { if (originalData != NULL) { _spOriginalData = originalData; } else { throw core::NullPointerException("originalDose is NULL!"); } }; void InterpolationBase::getNeighborhoodVoxelValues( const WorldCoordinate3D& aWorldCoordinate, - unsigned int neighborhood, boost::array& target, + unsigned int neighborhood, std::array& target, boost::shared_ptr values) const { if (_spOriginalData == NULL) { throw core::NullPointerException("originalDose is NULL!"); } //Determine target (abs(desired worldCoordinate- corner pixel world coordinate/pixel spacing) and values of corner pixels (from originalDose) VoxelGridIndex3D aIndex; if (_spOriginalData->getGeometricInfo().worldCoordinateToIndex(aWorldCoordinate, aIndex)) { //determine just the nearest voxel to the world coordinate if (neighborhood == 0) { values[0] = _spOriginalData->getValueAt(aIndex); } //determine the 8 voxels around the world coordinate else if (neighborhood == 8) { std::list cornerPoints; WorldCoordinate3D theNextVoxel; _spOriginalData->getGeometricInfo().indexToWorldCoordinate(aIndex, theNextVoxel); SpacingVectorType3D pixelSpacing = (_spOriginalData->getGeometricInfo()).getSpacing(); VoxelGridIndex3D leftTopFrontCoordinate; //find the voxel with the smallest coordinate values in each dimension. This defines the standard cube for (unsigned int i = 0; i < 3; i++) { if (aWorldCoordinate[i] < theNextVoxel[i]) { if (aIndex[i] > 0) { leftTopFrontCoordinate[i] = aIndex[i] - 1; target[i] = (aWorldCoordinate[i] - (theNextVoxel[i] - pixelSpacing[i])) / pixelSpacing[i]; } //@todo: see T22315 else { leftTopFrontCoordinate[i] = aIndex[i]; target[i] = (aWorldCoordinate[i] - (theNextVoxel[i] - pixelSpacing[i])) / pixelSpacing[i]; } } else { leftTopFrontCoordinate[i] = aIndex[i]; target[i] = (aWorldCoordinate[i] - theNextVoxel[i]) / pixelSpacing[i]; } } for (unsigned int zIncr = 0; zIncr < 2; zIncr++) { for (unsigned int yIncr = 0; yIncr < 2; yIncr++) { for (unsigned int xIncr = 0; xIncr < 2; xIncr++) { cornerPoints.push_back(VoxelGridIndex3D(leftTopFrontCoordinate[0] + xIncr, leftTopFrontCoordinate[1] + yIncr, leftTopFrontCoordinate[2] + zIncr)); } } } //target range has to be always [0,1] for (unsigned int i = 0; i < 3; i++) { assert(target[i] >= 0.0 && target[i] <= 1.0); } unsigned int count = 0; //now just get the values of all (dose) voxels and store them in values for (auto cornerPointsIterator = cornerPoints.begin(); cornerPointsIterator != cornerPoints.end(); ++cornerPointsIterator, ++count) { if (_spOriginalData->getGeometricInfo().isInside(*cornerPointsIterator)) { values[count] = _spOriginalData->getValueAt(*cornerPointsIterator); } else { //outside value! boundary treatment values[count] = getNearestInsideVoxelValue(*cornerPointsIterator); } assert(values[count] != -1); } } else { throw core::InvalidParameterException("neighborhoods other than 0 and 8 not yet supported in Interpolation"); } } else { throw core::MappingOutsideOfImageException("Error in conversion from world coordinates to index"); } } DoseTypeGy InterpolationBase::getNearestInsideVoxelValue(const VoxelGridIndex3D& currentVoxelIndex) const { VoxelGridIndex3D voxelChangedXYZ[] = {currentVoxelIndex, currentVoxelIndex, currentVoxelIndex, currentVoxelIndex, currentVoxelIndex, currentVoxelIndex, currentVoxelIndex}; unsigned int runningIndex; //x,y,z for (runningIndex = 0; runningIndex < 3; ++runningIndex) { voxelChangedXYZ[runningIndex][runningIndex] -= 1; } //xy voxelChangedXYZ[runningIndex][0] -= 1; voxelChangedXYZ[runningIndex][1] -= 1; ++runningIndex; //xz voxelChangedXYZ[runningIndex][0] -= 1; voxelChangedXYZ[runningIndex][2] -= 1; ++runningIndex; //yz voxelChangedXYZ[runningIndex][1] -= 1; voxelChangedXYZ[runningIndex][2] -= 1; ++runningIndex; //xyz voxelChangedXYZ[runningIndex][0] -= 1; voxelChangedXYZ[runningIndex][1] -= 1; voxelChangedXYZ[runningIndex][2] -= 1; ++runningIndex; unsigned int replacementVoxelIndex = 0; while (replacementVoxelIndex < runningIndex) { if (_spOriginalData->getGeometricInfo().validIndex(voxelChangedXYZ[replacementVoxelIndex])) { return _spOriginalData->getValueAt(voxelChangedXYZ[replacementVoxelIndex]); } ++replacementVoxelIndex; } return -1; } }//end namespace core }//end namespace rttb diff --git a/code/interpolation/rttbInterpolationBase.h b/code/interpolation/rttbInterpolationBase.h index 78f2db2..24ab397 100644 --- a/code/interpolation/rttbInterpolationBase.h +++ b/code/interpolation/rttbInterpolationBase.h @@ -1,91 +1,91 @@ // ----------------------------------------------------------------------- // 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 __INTERPOLATION_BASE_H #define __INTERPOLATION_BASE_H #include -#include +#include #include "rttbAccessorInterface.h" #include "RTTBInterpolationExports.h" namespace rttb { namespace interpolation { /*! @class InterpolationBase @brief Base class for interpolation. @ingroup interpolation */ class RTTBInterpolation_EXPORT InterpolationBase { public: typedef boost::shared_ptr Pointer; typedef rttb::core::AccessorInterface::AccessorPointer AccessorPointer; /*! @brief Constructor */ InterpolationBase() {}; /*! @brief Virtual destructor of base class */ virtual ~InterpolationBase() {}; /*! @brief Sets the AccessorPointer @pre originalData initialized @exception core::NullPointerException if originalData==NULL */ void setAccessorPointer(const AccessorPointer originalData); /*! @brief Returns the interpolated value for the given world coordinate */ virtual DoseTypeGy getValue(const WorldCoordinate3D& aWorldCoordinate) const = 0; protected: AccessorPointer _spOriginalData; /*! @brief determines voxels in a certain neighborhood of a physical based coordinate and converts in a standard cube with corner points [0 0 0], [1 0 0], [0 1 0], [1 1 0], [0 0 1], [1 0 1], [0 1 1], [1 1 1]. @param aWorldCoordinate the coordinate where to start @param neighborhood voxel around coordinate (currently only 0 and 8 implemented) @param target coordinates inside the standard cube with values [0 1] in each dimension. @param values dose values at all corner points of the standard cube. Is of type boost:shared_ptr[neighborhood] - @pre target and values have to be correctly initialized (e.g. boost::array target = {0.0, 0.0, 0.0}; boost::shared_ptr values(new DoseTypeGy[8]()); where 8 is neighborhood) + @pre target and values have to be correctly initialized (e.g. std::array target = {0.0, 0.0, 0.0}; boost::shared_ptr values(new DoseTypeGy[8]()); where 8 is neighborhood) @exception core::InvalidParameterException if neighborhood =! 0 && !=8 @exception core::MappingOutsideOfImageException if initial mapping of aWorldCoordinate is outside image @exception core::NullPointerException if dose is NULL */ void getNeighborhoodVoxelValues(const WorldCoordinate3D& aWorldCoordinate, - unsigned int neighborhood, boost::array& target, + unsigned int neighborhood, std::array& target, boost::shared_ptr values) const; /*! @brief returns the nearest inside voxel value @pre the voxelGridIndex is outside the image and voxelGridIndex>image.size() for all dimensions. Also voxelGridIndex[]>=0 for all dimensions @note used for virtually expanding the image by one voxel as edge handling */ DoseTypeGy getNearestInsideVoxelValue(const VoxelGridIndex3D& currentVoxelIndex) const; }; } } #endif diff --git a/code/interpolation/rttbLinearInterpolation.cpp b/code/interpolation/rttbLinearInterpolation.cpp index 60a1ae1..c2bb553 100644 --- a/code/interpolation/rttbLinearInterpolation.cpp +++ b/code/interpolation/rttbLinearInterpolation.cpp @@ -1,57 +1,59 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include "rttbLinearInterpolation.h" +#include + namespace rttb { namespace interpolation { - DoseTypeGy LinearInterpolation::trilinear(boost::array target, + DoseTypeGy LinearInterpolation::trilinear(std::array target, boost::shared_ptr values) const { //4 linear interpolation in x direction DoseTypeGy c_00 = values[0] * (1.0 - target[0]) + values[1] * target[0]; DoseTypeGy c_10 = values[2] * (1.0 - target[0]) + values[3] * target[0]; DoseTypeGy c_01 = values[4] * (1.0 - target[0]) + values[5] * target[0]; DoseTypeGy c_11 = values[6] * (1.0 - target[0]) + values[7] * target[0]; //combine result in y direction DoseTypeGy c_0 = c_00 * (1.0 - target[1]) + c_10 * target[1]; DoseTypeGy c_1 = c_01 * (1.0 - target[1]) + c_11 * target[1]; //finally incorporate z direction return (c_0 * (1.0 - target[2]) + c_1 * target[2]); } DoseTypeGy LinearInterpolation::getValue(const WorldCoordinate3D& aWorldCoordinate) const { //proper initialization of target and values - boost::array target = {0.0, 0.0, 0.0}; - boost::shared_ptr values(new DoseTypeGy[8]()); + std::array target = {0.0, 0.0, 0.0}; + auto values = boost::make_shared(8); getNeighborhoodVoxelValues(aWorldCoordinate, 8, target, values); return trilinear(target, values); } } } diff --git a/code/interpolation/rttbLinearInterpolation.h b/code/interpolation/rttbLinearInterpolation.h index 1731a34..e357cd5 100644 --- a/code/interpolation/rttbLinearInterpolation.h +++ b/code/interpolation/rttbLinearInterpolation.h @@ -1,62 +1,62 @@ // ----------------------------------------------------------------------- // 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 __LINEAR_INTERPOLATION_H #define __LINEAR_INTERPOLATION_H -#include +#include #include "rttbInterpolationBase.h" #include "RTTBInterpolationExports.h" namespace rttb { namespace interpolation { /*! @class LinearInterpolation @brief Linear interpolation. @ingroup interpolation */ class RTTBInterpolation_EXPORT LinearInterpolation : public InterpolationBase { public: /*! @brief Constructor */ LinearInterpolation() {}; /*! @brief Returns the interpolated value */ DoseTypeGy getValue(const WorldCoordinate3D& aWorldCoordinate) const; private: /*! @brief Trilinar interpolation @sa InterpolationBase for details about target and values @note Source: http://en.wikipedia.org/wiki/Trilinear_interpolation */ - DoseTypeGy trilinear(boost::array target, boost::shared_ptr values) const; + DoseTypeGy trilinear(std::array target, boost::shared_ptr values) const; }; } } #endif diff --git a/code/interpolation/rttbNearestNeighborInterpolation.cpp b/code/interpolation/rttbNearestNeighborInterpolation.cpp index 69edbf0..1d89f6d 100644 --- a/code/interpolation/rttbNearestNeighborInterpolation.cpp +++ b/code/interpolation/rttbNearestNeighborInterpolation.cpp @@ -1,40 +1,41 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include "rttbNearestNeighborInterpolation.h" -#include +#include +#include namespace rttb { namespace interpolation { DoseTypeGy NearestNeighborInterpolation::getValue(const WorldCoordinate3D& aWorldCoordinate) const { //proper initialization of target and values (although target is irrelevant in nearest neighbor case) - boost::array target = {0.0, 0.0, 0.0}; - boost::shared_ptr values(new DoseTypeGy[8]()); + std::array target = {0.0, 0.0, 0.0}; + auto values = boost::make_shared(8); getNeighborhoodVoxelValues(aWorldCoordinate, 0, target, values); return values[0]; } } } diff --git a/code/interpolation/rttbRosuMappableDoseAccessor.cpp b/code/interpolation/rttbRosuMappableDoseAccessor.cpp index fe2f2c6..466c403 100644 --- a/code/interpolation/rttbRosuMappableDoseAccessor.cpp +++ b/code/interpolation/rttbRosuMappableDoseAccessor.cpp @@ -1,174 +1,176 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include "rttbRosuMappableDoseAccessor.h" + +#include + #include "rttbNullPointerException.h" #include "rttbMappingOutsideOfImageException.h" #include "rttbLinearInterpolation.h" namespace rttb { namespace interpolation { RosuMappableDoseAccessor::RosuMappableDoseAccessor(const core::GeometricInfo& geoInfoTargetImage, const DoseAccessorPointer doseMovingImage, const TransformationPointer aTransformation, bool acceptPadding, DoseTypeGy defaultOutsideValue): MappableDoseAccessorInterface(geoInfoTargetImage, doseMovingImage, aTransformation, acceptPadding, defaultOutsideValue) { //define linear interpolation - InterpolationBase::Pointer interpolationLinear = InterpolationBase::Pointer( - new LinearInterpolation()); + auto interpolationLinear = ::boost::make_shared(); _spInterpolation = interpolationLinear; _spInterpolation->setAccessorPointer(_spOriginalDoseDataMovingImage); } GenericValueType RosuMappableDoseAccessor::getValueAt(const VoxelGridID aID) const { VoxelGridIndex3D aVoxelGridIndex3D; if (_geoInfoTargetImage.convert(aID, aVoxelGridIndex3D)) { return getValueAt(aVoxelGridIndex3D); } else { if (_acceptPadding) { return _defaultOutsideValue; } else { throw core::MappingOutsideOfImageException("Error in conversion from index to world coordinates"); return -1; } } } GenericValueType RosuMappableDoseAccessor::getValueAt(const VoxelGridIndex3D& aIndex) const { //Transform requested voxel coordinates of original image into world coordinates with RTTB WorldCoordinate3D worldCoordinateTarget; if (_geoInfoTargetImage.indexToWorldCoordinate(aIndex, worldCoordinateTarget)) { std::vector octants = getOctants(worldCoordinateTarget); if (octants.size() > 2) { DoseTypeGy interpolatedDoseValue = 0.0; //get trilinear interpolation value of every octant point for (std::vector::const_iterator octantIterator = octants.begin(); octantIterator != octants.end(); ++octantIterator) { //transform coordinates WorldCoordinate3D worldCoordinateMoving; WorldCoordinate3D worldCoordinateTargetOctant = *octantIterator; _spTransformation->transformInverse(worldCoordinateTargetOctant, worldCoordinateMoving); try { interpolatedDoseValue += _spInterpolation->getValue(worldCoordinateMoving); } //Mapped outside of image? Check if padding is allowed catch (core::MappingOutsideOfImageException& /*e*/) { if (_acceptPadding) { interpolatedDoseValue += _defaultOutsideValue; } else { throw core::MappingOutsideOfImageException("Mapping outside of image"); } } catch (core::Exception& e) { std::cout << e.what() << std::endl; return -1; } } return interpolatedDoseValue / (DoseTypeGy)octants.size(); } else { if (_acceptPadding) { return _defaultOutsideValue; } else { throw core::MappingOutsideOfImageException("Too many samples are mapped outside the image!"); return -1; } } } else { if (_acceptPadding) { return _defaultOutsideValue; } else { throw core::MappingOutsideOfImageException("Error in conversion from index to world coordinates"); return -1; } } } std::vector RosuMappableDoseAccessor::getOctants( const WorldCoordinate3D& aCoordinate) const { std::vector octants; SpacingVectorType3D spacingTargetImage = _geoInfoTargetImage.getSpacing(); core::GeometricInfo geometricInfoDoseData = _spOriginalDoseDataMovingImage->getGeometricInfo(); //as the corner point is the coordinate of the voxel (grid), 0.25 and 0.75 are the center of the subvoxels for (double xOct = -0.25; xOct <= 0.25; xOct += 0.5) { for (double yOct = -0.25; yOct <= 0.25; yOct += 0.5) { for (double zOct = -0.25; zOct <= 0.25; zOct += 0.5) { WorldCoordinate3D aWorldCoordinate(aCoordinate.x() + (xOct * spacingTargetImage.x()), aCoordinate.y() + (yOct * spacingTargetImage.y()), aCoordinate.z() + (zOct * spacingTargetImage.z())); if (geometricInfoDoseData.isInside(aWorldCoordinate)) { octants.push_back(aWorldCoordinate); } } } } return octants; } }//end namespace interpolation }//end namespace rttb diff --git a/code/interpolation/rttbSimpleMappableDoseAccessor.h b/code/interpolation/rttbSimpleMappableDoseAccessor.h index b8508b4..c7dabee 100644 --- a/code/interpolation/rttbSimpleMappableDoseAccessor.h +++ b/code/interpolation/rttbSimpleMappableDoseAccessor.h @@ -1,78 +1,78 @@ // ----------------------------------------------------------------------- // 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 __SIMPLE_MAPPABLE_DOSE_ACCESSOR_H #define __SIMPLE_MAPPABLE_DOSE_ACCESSOR_H #include +#include #include "rttbInterpolationBase.h" #include "rttbLinearInterpolation.h" #include "rttbTransformationInterface.h" #include "rttbMappableDoseAccessorInterface.h" #include "RTTBInterpolationExports.h" namespace rttb { namespace interpolation { /*! @class SimpleMappableDoseAccessor @brief Class for dose mapping based on simple trilinear interpolation @ingroup interpolation */ class RTTBInterpolation_EXPORT SimpleMappableDoseAccessor : public MappableDoseAccessorInterface { private: InterpolationBase::Pointer _spInterpolation; public: typedef boost::shared_ptr Pointer; /*! @brief Constructor. Just hands values over to base class constructor. @param aInterpolation the used interpolation. @sa MappableDoseAccessorBase */ SimpleMappableDoseAccessor(const core::GeometricInfo& geoInfoTargetImage, const DoseAccessorPointer doseMovingImage, const TransformationInterface::Pointer aTransformation, - const InterpolationBase::Pointer aInterpolation = ::boost::shared_ptr - (new LinearInterpolation()), + const InterpolationBase::Pointer aInterpolation = ::boost::make_shared(), bool acceptPadding = true, DoseTypeGy defaultOutsideValue = 0.0); /*! @brief Virtual destructor of class */ virtual ~SimpleMappableDoseAccessor() {}; /*! @brief Returns the dose for a given voxel grid id. Plain trilinear interpolation is performed. @sa getDoseAt(const VoxelGridIndex3D& aIndex) */ GenericValueType getValueAt(const VoxelGridID aID) const; /*! @brief Returns the dose for a given voxel grid index. Plain trilinear interpolation is performed. @return the dose or if (isOutside==true && _acceptPadding==true) then _defaultValue @exception core::MappingOutsideOfImageException if the point is mapped outside and if _acceptPadding==false, possibly returning _defaultValue) */ GenericValueType getValueAt(const VoxelGridIndex3D& aIndex) const; }; } } #endif diff --git a/code/io/itk/rttbITKImageMaskAccessor.cpp b/code/io/itk/rttbITKImageMaskAccessor.cpp index 4011781..718588a 100644 --- a/code/io/itk/rttbITKImageMaskAccessor.cpp +++ b/code/io/itk/rttbITKImageMaskAccessor.cpp @@ -1,177 +1,177 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include #include #include "rttbITKImageMaskAccessor.h" #include "rttbGeometricInfo.h" #include "rttbInvalidDoseException.h" namespace rttb { namespace io { namespace itk { ITKImageMaskAccessor::ITKImageMaskAccessor(ITKMaskImageType::ConstPointer aMaskImage) : _mask(aMaskImage) { if (_mask.IsNull()) { throw core::InvalidDoseException("Mask image = 0!") ; } assembleGeometricInfo(); } ITKImageMaskAccessor::~ITKImageMaskAccessor() { }; bool ITKImageMaskAccessor::assembleGeometricInfo() { _geoInfo = boost::make_shared(); _geoInfo->setSpacing(SpacingVectorType3D(_mask->GetSpacing()[0], _mask->GetSpacing()[1], _mask->GetSpacing()[2])); if (_geoInfo->getSpacing()[0] == 0 || _geoInfo->getSpacing()[1] == 0 || _geoInfo->getSpacing()[2] == 0) { throw core::InvalidDoseException("Pixel spacing = 0!"); } _geoInfo->setImagePositionPatient(WorldCoordinate3D(_mask->GetOrigin()[0], _mask->GetOrigin()[1], _mask->GetOrigin()[2])); OrientationMatrix OM(0); for (unsigned int col = 0; col < 3; ++col) { for (unsigned int row = 0; row < 3; ++row) { OM(col, row) = _mask->GetDirection()(col, row); } } _geoInfo->setOrientationMatrix(OM); _geoInfo->setNumColumns(_mask->GetLargestPossibleRegion().GetSize()[0]); _geoInfo->setNumRows(_mask->GetLargestPossibleRegion().GetSize()[1]); _geoInfo->setNumSlices(_mask->GetLargestPossibleRegion().GetSize()[2]); if (_geoInfo->getNumColumns() == 0 || _geoInfo->getNumRows() == 0 || _geoInfo->getNumSlices() == 0) { throw core::InvalidDoseException("Empty mask!") ; } return true; } void ITKImageMaskAccessor::updateMask() { return; } ITKImageMaskAccessor::MaskVoxelListPointer ITKImageMaskAccessor::getRelevantVoxelVector() { updateMask(); _relevantVoxelVector = getRelevantVoxelVector(0); return _relevantVoxelVector; } ITKImageMaskAccessor::MaskVoxelListPointer ITKImageMaskAccessor::getRelevantVoxelVector( float lowerThreshold) { - MaskVoxelListPointer filteredVoxelVectorPointer(new MaskVoxelList); + auto filteredVoxelVectorPointer = boost::make_shared(); updateMask(); unsigned int size = _geoInfo->getNumColumns() * _geoInfo->getNumRows() * _geoInfo->getNumSlices(); filteredVoxelVectorPointer->reserve(size); for (unsigned int gridIndex = 0 ; gridIndex < size; gridIndex++) { core::MaskVoxel currentVoxel = core::MaskVoxel(gridIndex); if (getMaskAt(gridIndex, currentVoxel)) { if (currentVoxel.getRelevantVolumeFraction() > lowerThreshold) { filteredVoxelVectorPointer->push_back(currentVoxel); } } } return filteredVoxelVectorPointer; } bool ITKImageMaskAccessor::getMaskAt(VoxelGridID aID, core::MaskVoxel& voxel) const { VoxelGridIndex3D aVoxelGridIndex; if (_geoInfo->convert(aID, aVoxelGridIndex)) { return getMaskAt(aVoxelGridIndex, voxel); } else { return false; } } bool ITKImageMaskAccessor::getMaskAt(const VoxelGridIndex3D& aIndex, core::MaskVoxel& voxel) const { voxel.setRelevantVolumeFraction(0); if (_geoInfo->validIndex(aIndex)) { const ITKMaskImageType::IndexType pixelIndex = {{aIndex[0], aIndex[1], aIndex[2]}}; double value = _mask->GetPixel(pixelIndex); VoxelGridID gridId; _geoInfo->convert(aIndex, gridId); if (value >= 0 && value <= 1) { voxel.setRelevantVolumeFraction(value); return true; } else { std::cerr << "The pixel value of the mask should be >=0 and <=1!" << std::endl; return false; } } else { return false; } } const core::GeometricInfo& ITKImageMaskAccessor::getGeometricInfo() const { return *_geoInfo; }; } } } diff --git a/code/io/other/rttbDoseStatisticsXMLReader.cpp b/code/io/other/rttbDoseStatisticsXMLReader.cpp index f03f19c..eb1e369 100644 --- a/code/io/other/rttbDoseStatisticsXMLReader.cpp +++ b/code/io/other/rttbDoseStatisticsXMLReader.cpp @@ -1,219 +1,215 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1328 $ (last changed revision) // @date $Date: 2016-04-22 09:50:01 +0200 (Fr, 22 Apr 2016) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include #include #include #include #include #include #include "rttbDoseStatisticsXMLReader.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace io { namespace other { typedef boost::shared_ptr DoseStatisticsPtr; DoseStatisticsXMLReader::DoseStatisticsXMLReader(const std::string& filename) : _filename(filename), _newFile(true) { } DoseStatisticsXMLReader::~DoseStatisticsXMLReader() { } void DoseStatisticsXMLReader::setFilename(const std::string& filename) { _filename = filename; _newFile = true; } DoseStatisticsPtr DoseStatisticsXMLReader::generateDoseStatistic() { if (_newFile) { this->createDoseStatistic(); } return _doseStatistic; } void DoseStatisticsXMLReader::createDoseStatistic() { boost::property_tree::ptree pt; // Load the XML file into the property tree. If reading fails // (cannot open file, parse error), an exception is thrown. try { read_xml(_filename, pt); } catch (boost::property_tree::xml_parser_error& /*e*/) { throw rttb::core::InvalidParameterException("DoseStatistics file name invalid: could not open the xml file!"); } // data to fill the parameter for the DoseStatistics std::string name; std::string datum; unsigned int x; std::pair voxelid; std::vector < std::pair> vec; //initialize all parameters for the DoseStatistics double minimum=-1; double maximum=-1; double numVoxels=-1; double volume=-1; double referenceDose = -1; double mean=-1; double stdDeviation=-1; boost::shared_ptr > > minimumVoxelPositions = nullptr; boost::shared_ptr > > maximumVoxelPositions = nullptr; std::map Dx; std::map Vx; std::map MOHx; std::map MOCx; std::map MaxOHx; std::map MinOCx; BOOST_FOREACH(boost::property_tree::ptree::value_type & data, pt.get_child("statistics.results")) { datum = data.second.data(); BOOST_FOREACH(boost::property_tree::ptree::value_type & middle, data.second) { BOOST_FOREACH(boost::property_tree::ptree::value_type & innernode, middle.second) { std::string mia = innernode.first; if (innernode.first == "name") { name = innernode.second.data(); } else if (innernode.first == "voxelGridID") { boost::replace_all(datum, "\r\n", ""); boost::replace_all(datum, "\n", ""); boost::trim(datum); voxelid.first = boost::lexical_cast(datum); voxelid.second = boost::lexical_cast(innernode.second.data()); vec.push_back(voxelid); } else if (innernode.first == "x") { x = boost::lexical_cast(innernode.second.data()); } } } // fill with the extracted data if (name == "numberOfVoxels") { numVoxels = boost::lexical_cast(datum); } else if (name == "volume") { volume = boost::lexical_cast(datum); } else if (name == "referenceDose") { referenceDose = boost::lexical_cast(datum); } else if (name == "mean") { mean = boost::lexical_cast(datum); } else if (name == "standardDeviation") { stdDeviation = boost::lexical_cast(datum); } else if (name == "minimum") { minimum = boost::lexical_cast(datum); if (!vec.empty()) { minimumVoxelPositions = boost::make_shared>>(vec); vec.clear(); } } else if (name == "maximum") { maximum = boost::lexical_cast(datum); if (!vec.empty()) { maximumVoxelPositions = boost::make_shared>>(vec); vec.clear(); } } else if (name == "Dx") { Dx[boost::lexical_cast(x)*volume / 100] = boost::lexical_cast(datum); } else if (name == "Vx") { Vx[boost::lexical_cast(x)*referenceDose / 100] = boost::lexical_cast(datum); } else if (name == "MOHx") { MOHx[boost::lexical_cast(x)*volume / 100] = boost::lexical_cast(datum); } else if (name == "MOCx") { MOCx[boost::lexical_cast(x)*volume / 100] = boost::lexical_cast(datum); } else if (name == "MaxOHx") { MaxOHx[boost::lexical_cast(x)*volume / 100] = boost::lexical_cast(datum); } else if (name == "MinOCx") { MinOCx[boost::lexical_cast(x)*volume / 100] = boost::lexical_cast(datum); } } // make DoseStatistcs - //boost::make_shared is desireable here, but for VS2010 this doesn't work - //see http://stackoverflow.com/questions/19310062/error-no-instance-of-overloaded-function-stdmake-shared-matches-the-argumen - _doseStatistic = boost::shared_ptr(new - rttb::algorithms::DoseStatistics( + _doseStatistic = boost::make_shared( minimum, maximum, mean, stdDeviation, numVoxels, volume, minimumVoxelPositions, - maximumVoxelPositions - , Dx, Vx, MOHx, MOCx, MaxOHx, MinOCx, referenceDose)); + maximumVoxelPositions , Dx, Vx, MOHx, MOCx, MaxOHx, MinOCx, referenceDose); } }//end namespace other }//end namespace io }//end namespace rttb diff --git a/code/masks/boost/rttbBoostMaskAccessor.cpp b/code/masks/boost/rttbBoostMaskAccessor.cpp index cbb480b..8942498 100644 --- a/code/masks/boost/rttbBoostMaskAccessor.cpp +++ b/code/masks/boost/rttbBoostMaskAccessor.cpp @@ -1,162 +1,162 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include "rttbBoostMaskAccessor.h" #include "rttbBoostMask.h" #include #include #include #include namespace rttb { namespace masks { namespace boost { BoostMaskAccessor::BoostMaskAccessor(StructTypePointer aStructurePointer, const core::GeometricInfo& aGeometricInfo, bool strict) : _spStructure(aStructurePointer), _geoInfo(aGeometricInfo), _strict(strict) { _spRelevantVoxelVector = MaskVoxelListPointer(); //generate new structure set uid ::boost::uuids::uuid id; ::boost::uuids::random_generator generator; id = generator(); std::stringstream ss; ss << id; _maskUID = "BoostMask_" + ss.str(); } BoostMaskAccessor::~BoostMaskAccessor() { }; void BoostMaskAccessor::updateMask() { MaskVoxelList newRelevantVoxelVector; if (_spRelevantVoxelVector) { return; // already calculated } BoostMask mask(::boost::make_shared(_geoInfo), _spStructure, _strict); _spRelevantVoxelVector = mask.getRelevantVoxelVector(); } BoostMaskAccessor::MaskVoxelListPointer BoostMaskAccessor::getRelevantVoxelVector() { // if not already generated start voxelization here updateMask(); return _spRelevantVoxelVector; } BoostMaskAccessor::MaskVoxelListPointer BoostMaskAccessor::getRelevantVoxelVector( float lowerThreshold) { - MaskVoxelListPointer filteredVoxelVectorPointer(new MaskVoxelList); + auto filteredVoxelVectorPointer = ::boost::make_shared(); updateMask(); // filter relevant voxels BoostMaskAccessor::MaskVoxelList::iterator it = _spRelevantVoxelVector->begin(); while (it != _spRelevantVoxelVector->end()) { if ((*it).getRelevantVolumeFraction() > lowerThreshold) { filteredVoxelVectorPointer->push_back(*it); } ++it; } // if mask calculation was not successful this is empty! return filteredVoxelVectorPointer; } bool BoostMaskAccessor::getMaskAt(VoxelGridID aID, core::MaskVoxel& voxel) const { //initialize return voxel voxel.setRelevantVolumeFraction(0); //check if ID is valid if (!_geoInfo.validID(aID)) { return false; } //determine how a given voxel on the dose grid is masked if (_spRelevantVoxelVector) { BoostMaskAccessor::MaskVoxelList::iterator it = _spRelevantVoxelVector->begin(); while (it != _spRelevantVoxelVector->end()) { if ((*it).getVoxelGridID() == aID) { voxel = (*it); return true; } ++it; } } // returns false if mask was not calculated without triggering calculation (otherwise not const!) else { return false; } return false; } bool BoostMaskAccessor::getMaskAt(const VoxelGridIndex3D& aIndex, core::MaskVoxel& voxel) const { //convert VoxelGridIndex3D to VoxelGridID VoxelGridID aVoxelGridID; if (_geoInfo.convert(aIndex, aVoxelGridID)) { return getMaskAt(aVoxelGridID, voxel); } else { return false; } } const core::GeometricInfo& BoostMaskAccessor::getGeometricInfo() const { return _geoInfo; }; } } } \ No newline at end of file diff --git a/code/masks/rttbGenericMutableMaskAccessor.cpp b/code/masks/rttbGenericMutableMaskAccessor.cpp index 89d59b6..1627595 100644 --- a/code/masks/rttbGenericMutableMaskAccessor.cpp +++ b/code/masks/rttbGenericMutableMaskAccessor.cpp @@ -1,179 +1,179 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include "rttbGenericMutableMaskAccessor.h" #include "rttbMaskVoxel.h" #include "rttbNullPointerException.h" #include #include #include #include namespace rttb { namespace masks { GenericMutableMaskAccessor::GenericMutableMaskAccessor(const core::GeometricInfo& aGeometricInfo) : _geoInfo(aGeometricInfo), _spRelevantVoxelVector(MaskVoxelListPointer()) { //generate new structure set uid boost::uuids::uuid id; boost::uuids::random_generator generator; id = generator(); std::stringstream ss; ss << id; _maskUID = "GenericMutableMask_" + ss.str(); } GenericMutableMaskAccessor::~GenericMutableMaskAccessor() {} void GenericMutableMaskAccessor::updateMask() {} GenericMutableMaskAccessor::MaskVoxelListPointer GenericMutableMaskAccessor::getRelevantVoxelVector() { return _spRelevantVoxelVector; } GenericMutableMaskAccessor::MaskVoxelListPointer GenericMutableMaskAccessor::getRelevantVoxelVector( float lowerThreshold) { - MaskVoxelListPointer filteredVoxelVectorPointer(new MaskVoxelList); + auto filteredVoxelVectorPointer = boost::make_shared(); // filter relevant voxels GenericMutableMaskAccessor::MaskVoxelList::iterator it = _spRelevantVoxelVector->begin(); while (it != _spRelevantVoxelVector->end()) { if ((*it).getRelevantVolumeFraction() > lowerThreshold) { filteredVoxelVectorPointer->push_back(*it); } ++it; } // if mask calculation was not successful this is empty! return filteredVoxelVectorPointer; } bool GenericMutableMaskAccessor::getMaskAt(VoxelGridID aID, core::MaskVoxel& voxel) const { //initialize return voxel voxel.setRelevantVolumeFraction(0); //check if ID is valid if (!_geoInfo.validID(aID)) { return false; } //determine how a given voxel on the dose grid is masked if (_spRelevantVoxelVector) { GenericMutableMaskAccessor::MaskVoxelList::iterator it = _spRelevantVoxelVector->begin(); while (it != _spRelevantVoxelVector->end()) { if ((*it).getVoxelGridID() == aID) { voxel = (*it); return true; } ++it; } //aID is not in mask voxel.setRelevantVolumeFraction(0); } return false; } bool GenericMutableMaskAccessor::getMaskAt(const VoxelGridIndex3D& aIndex, core::MaskVoxel& voxel) const { //convert VoxelGridIndex3D to VoxelGridID VoxelGridID aVoxelGridID; if (_geoInfo.convert(aIndex, aVoxelGridID)) { return getMaskAt(aVoxelGridID, voxel); } else { return false; } } void GenericMutableMaskAccessor::setMaskAt(VoxelGridID aID, const core::MaskVoxel& voxel) { //check if ID is valid if (!_geoInfo.validID(aID)) { return; } //determine how a given voxel on the dose grid is masked if (_spRelevantVoxelVector) { GenericMutableMaskAccessor::MaskVoxelList::iterator it = _spRelevantVoxelVector->begin(); while (it != _spRelevantVoxelVector->end()) { if ((*it).getVoxelGridID() == aID) { (*it) = voxel; return; } ++it; } //not sID is not found in existing voxels _spRelevantVoxelVector->push_back(voxel); } } void GenericMutableMaskAccessor::setMaskAt(const VoxelGridIndex3D& aIndex, const core::MaskVoxel& voxel) { //convert VoxelGridIndex3D to VoxelGridID VoxelGridID aVoxelGridID; if (_geoInfo.convert(aIndex, aVoxelGridID)) { setMaskAt(aVoxelGridID, voxel); } } void GenericMutableMaskAccessor::setRelevantVoxelVector(MaskVoxelListPointer aVoxelListPointer) { _spRelevantVoxelVector = MaskVoxelListPointer(aVoxelListPointer); } } } \ No newline at end of file diff --git a/testing/algorithms/BinaryFunctorAccessorTest.cpp b/testing/algorithms/BinaryFunctorAccessorTest.cpp index 2b2fade..8abb4d9 100644 --- a/testing/algorithms/BinaryFunctorAccessorTest.cpp +++ b/testing/algorithms/BinaryFunctorAccessorTest.cpp @@ -1,135 +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$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include #include #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbDoseAccessorInterface.h" #include "rttbDicomDoseAccessor.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbArithmetic.h" #include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" #include "rttbBinaryFunctorAccessor.h" namespace rttb { namespace testing { typedef core::DoseAccessorInterface::DoseAccessorPointer DoseAccessorPointer; typedef algorithms::BinaryFunctorAccessor BinaryFunctorAccessorAddType; typedef algorithms::BinaryFunctorAccessor BinaryFunctorAccessorAddWeightedType; /*! @brief BinaryFunctorAccessorTest - tests functors of two accessors 1) test constructor 2) test getDoseAt */ int BinaryFunctorAccessorTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string RTDOSE_FILENAME; std::string RTDOSE2_FILENAME; if (argc > 1) { RTDOSE_FILENAME = argv[1]; } if (argc > 2) { RTDOSE2_FILENAME = argv[2]; } DoseAccessorPointer spDoseAccessorNull; DoseAccessorPointer spDoseAccessor = io::dicom::DicomFileDoseAccessorGenerator( RTDOSE_FILENAME.c_str()).generateDoseAccessor(); DoseAccessorPointer spDoseAccessor2 = io::dicom::DicomFileDoseAccessorGenerator( RTDOSE2_FILENAME.c_str()).generateDoseAccessor(); algorithms::arithmetic::doseOp::Add addOP; algorithms::arithmetic::doseOp::AddWeighted addWeightedOP(1.0, 10.0); algorithms::arithmetic::doseOp::AddWeighted addWeightedTwoOP(2.0, 2.0); //1) Check constructor CHECK_THROW_EXPLICIT(BinaryFunctorAccessorAddType(spDoseAccessorNull, spDoseAccessor, addOP), core::NullPointerException); CHECK_THROW_EXPLICIT(BinaryFunctorAccessorAddType(spDoseAccessor, spDoseAccessorNull, addOP), core::NullPointerException); CHECK_THROW_EXPLICIT(BinaryFunctorAccessorAddType(spDoseAccessorNull, spDoseAccessorNull, addOP), core::NullPointerException); CHECK_THROW_EXPLICIT(BinaryFunctorAccessorAddType(spDoseAccessor, spDoseAccessor2, addOP), core::InvalidParameterException); CHECK_NO_THROW(BinaryFunctorAccessorAddType(spDoseAccessor, spDoseAccessor, addOP)); CHECK_NO_THROW(BinaryFunctorAccessorAddWeightedType(spDoseAccessor, spDoseAccessor, addWeightedOP)); - boost::shared_ptr spBinaryFunctorDoseAccessorAdd( - new BinaryFunctorAccessorAddType(spDoseAccessor, spDoseAccessor, addOP)); - boost::shared_ptr spBinaryFunctorDoseAccessorAddWeighted( - new BinaryFunctorAccessorAddWeightedType(spDoseAccessor, spDoseAccessor, addWeightedOP)); - boost::shared_ptr - spBinaryFunctorDoseAccessorAddWeightedTwo(new BinaryFunctorAccessorAddWeightedType( - spDoseAccessor, spDoseAccessor, addWeightedTwoOP)); + auto spBinaryFunctorDoseAccessorAdd = boost::make_shared(spDoseAccessor, spDoseAccessor, addOP); + auto spBinaryFunctorDoseAccessorAddWeighted = boost::make_shared(spDoseAccessor, spDoseAccessor, addWeightedOP); + auto spBinaryFunctorDoseAccessorAddWeightedTwo = boost::make_shared(spDoseAccessor, spDoseAccessor, addWeightedTwoOP); //2) Test getDoseAt() int lastIndex = spBinaryFunctorDoseAccessorAdd->getGeometricInfo().getNumberOfVoxels() - 1; VoxelGridID aId[3] = { 5, 6067, lastIndex }; VoxelGridIndex3D aIndex[3] = {VoxelGridIndex3D(5, 0, 0), VoxelGridIndex3D(37, 0, 2), VoxelGridIndex3D(spBinaryFunctorDoseAccessorAdd->getGeometricInfo().getNumColumns() - 1, spBinaryFunctorDoseAccessorAdd->getGeometricInfo().getNumRows() - 1, spBinaryFunctorDoseAccessorAdd->getGeometricInfo().getNumSlices() - 1)}; for (int i = 0; i < 3; ++i) { CHECK_EQUAL(spBinaryFunctorDoseAccessorAdd->getValueAt(aId[i]), 4.0); CHECK_EQUAL(spBinaryFunctorDoseAccessorAddWeighted->getValueAt(aId[i]), 22.0); CHECK_EQUAL(spBinaryFunctorDoseAccessorAdd->getValueAt(aIndex[i]), spBinaryFunctorDoseAccessorAdd->getValueAt(aId[i])); CHECK_EQUAL(spBinaryFunctorDoseAccessorAddWeighted->getValueAt(aIndex[i]), spBinaryFunctorDoseAccessorAddWeighted->getValueAt(aId[i])); CHECK_EQUAL(spBinaryFunctorDoseAccessorAdd->getValueAt(aId[i]) * 2.0, spBinaryFunctorDoseAccessorAddWeightedTwo->getValueAt(aId[i])); } VoxelGridID aIdInvalid(spBinaryFunctorDoseAccessorAdd->getGeometricInfo().getNumberOfVoxels()); VoxelGridIndex3D aIndexInvalid(spBinaryFunctorDoseAccessorAdd->getGeometricInfo().getNumColumns(), spBinaryFunctorDoseAccessorAdd->getGeometricInfo().getNumRows(), spBinaryFunctorDoseAccessorAdd->getGeometricInfo().getNumSlices()); CHECK_EQUAL(spBinaryFunctorDoseAccessorAdd->getValueAt(aIdInvalid), -1.0); CHECK_EQUAL(spBinaryFunctorDoseAccessorAdd->getValueAt(aIndexInvalid), -1.0); CHECK_EQUAL(spBinaryFunctorDoseAccessorAddWeighted->getValueAt(aIdInvalid), -1.0); CHECK_EQUAL(spBinaryFunctorDoseAccessorAddWeighted->getValueAt(aIndexInvalid), -1.0); RETURN_AND_REPORT_TEST_SUCCESS; } } } \ No newline at end of file diff --git a/testing/core/DummyMaskAccessor.cpp b/testing/core/DummyMaskAccessor.cpp index 623ee1f..46eba43 100644 --- a/testing/core/DummyMaskAccessor.cpp +++ b/testing/core/DummyMaskAccessor.cpp @@ -1,162 +1,162 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include #include #include #include #include "DummyMaskAccessor.h" #include "rttbNullPointerException.h" namespace rttb { namespace testing { DummyMaskAccessor::DummyMaskAccessor(const core::GeometricInfo& aGeometricInfo) { _spRelevantVoxelVector = MaskVoxelListPointer(); _geoInfo = aGeometricInfo; boost::uuids::uuid id; boost::uuids::random_generator generator; id = generator(); std::stringstream ss; ss << id; _maskUID = "DummyMask_" + ss.str(); } DummyMaskAccessor::DummyMaskAccessor(const core::GeometricInfo& aGeometricInfo, MaskVoxelListPointer voxelListPtr) { _spRelevantVoxelVector = voxelListPtr; _geoInfo = aGeometricInfo; boost::uuids::uuid id; boost::uuids::random_generator generator; id = generator(); std::stringstream ss; ss << id; _maskUID = "DummyMask_" + ss.str(); } void DummyMaskAccessor::updateMask() { MaskVoxelList newRelevantVoxelVector; if (_spRelevantVoxelVector) { return; } for (int i = 0; i < _geoInfo.getNumberOfVoxels(); i++) { if ((double(rand()) / RAND_MAX) > 0.5) { core::MaskVoxel newMaskVoxel(i); newMaskVoxel.setRelevantVolumeFraction((double(rand()) / RAND_MAX)); newRelevantVoxelVector.push_back(newMaskVoxel); } } _spRelevantVoxelVector = boost::make_shared(newRelevantVoxelVector); return; } DummyMaskAccessor::MaskVoxelListPointer DummyMaskAccessor::getRelevantVoxelVector() { updateMask(); return _spRelevantVoxelVector; } DummyMaskAccessor::MaskVoxelListPointer DummyMaskAccessor::getRelevantVoxelVector( float lowerThreshold) { - MaskVoxelListPointer filteredVoxelVectorPointer(new MaskVoxelList); + auto filteredVoxelVectorPointer = boost::make_shared(); updateMask(); DummyMaskAccessor::MaskVoxelList::iterator it = _spRelevantVoxelVector->begin(); while (it != _spRelevantVoxelVector->end()) { if ((*it).getRelevantVolumeFraction() > lowerThreshold) { filteredVoxelVectorPointer->push_back(*it); } ++it; } return filteredVoxelVectorPointer; } bool DummyMaskAccessor::getMaskAt(VoxelGridID aID, core::MaskVoxel& voxel) const { voxel.setRelevantVolumeFraction(0); if (!_geoInfo.validID(aID)) { return false; } if (_spRelevantVoxelVector) { DummyMaskAccessor::MaskVoxelList::iterator it = _spRelevantVoxelVector->begin(); while (it != _spRelevantVoxelVector->end()) { if ((*it).getVoxelGridID() == aID) { voxel = (*it); return true; } ++it; } } else { return false; } return false; } bool DummyMaskAccessor::getMaskAt(const VoxelGridIndex3D& aIndex, core::MaskVoxel& voxel) const { VoxelGridID aVoxelGridID; if (_geoInfo.convert(aIndex, aVoxelGridID)) { return getMaskAt(aVoxelGridID, voxel); } else { return false; } } } } \ No newline at end of file diff --git a/testing/interpolation/InterpolationITKTransformation/SimpleMappableDoseAccessorWithITKTest.cpp b/testing/interpolation/InterpolationITKTransformation/SimpleMappableDoseAccessorWithITKTest.cpp index 5606149..fac1e66 100644 --- a/testing/interpolation/InterpolationITKTransformation/SimpleMappableDoseAccessorWithITKTest.cpp +++ b/testing/interpolation/InterpolationITKTransformation/SimpleMappableDoseAccessorWithITKTest.cpp @@ -1,192 +1,178 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbGenericDoseIterator.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbSimpleMappableDoseAccessor.h" #include "rttbNearestNeighborInterpolation.h" #include "rttbLinearInterpolation.h" #include "rttbTransformationInterface.h" #include "rttbITKTransformation.h" #include "rttbNullPointerException.h" #include "itkTranslationTransform.h" namespace rttb { namespace testing { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef rttb::interpolation::SimpleMappableDoseAccessor SimpleMappableDoseAccessor; typedef rttb::interpolation::NearestNeighborInterpolation NearestNeighborInterpolation; typedef rttb::interpolation::LinearInterpolation LinearInterpolation; typedef rttb::interpolation::TransformationInterface TransformationInterface; typedef rttb::interpolation::ITKTransformation ITKTransformation; typedef itk::TranslationTransform TranslationTransformType; /*! @brief SimpleMappableDoseAccessorWithITKTest - test the API of SimpleMappableDoseAccessor with ITK transformation 1) Test constructor 2) test getDoseAt() a) with Identity transform b) with translation transform */ int SimpleMappableDoseAccessorWithITKTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string RTDOSE_FILENAME_CONSTANT_TWO; std::string RTDOSE_FILENAME_INCREASE_X; if (argc > 2) { RTDOSE_FILENAME_CONSTANT_TWO = argv[1]; RTDOSE_FILENAME_INCREASE_X = argv[2]; } else { std::cout << "at least two parameters for SimpleMappableDoseAccessorWithITKTest are expected" << std::endl; return -1; } const double doseGridScaling = 2.822386e-005; rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1( RTDOSE_FILENAME_CONSTANT_TWO.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator2( RTDOSE_FILENAME_INCREASE_X.c_str()); DoseAccessorPointer doseAccessor2(doseAccessorGenerator2.generateDoseAccessor()); core::GeometricInfo doseAccessor1GeometricInfo = doseAccessor1->getGeometricInfo(); - NearestNeighborInterpolation::Pointer interpolationNN = - NearestNeighborInterpolation::Pointer(new NearestNeighborInterpolation()); - LinearInterpolation::Pointer interpolationLinear = LinearInterpolation::Pointer - (new LinearInterpolation()); - - //auto transformITKIdentity = TransformationInterface::Pointer(new ITKTransformation( - // IdentityTransformType::New())); + auto interpolationNN = boost::make_shared(); + auto interpolationLinear = boost::make_shared(); TranslationTransformType::Pointer transformITKIdentityTemporary = TranslationTransformType::New(); TranslationTransformType::OutputVectorType translationIdentity; translationIdentity[0] = 0.0; translationIdentity[1] = 0.0; translationIdentity[2] = 0.0; transformITKIdentityTemporary->Translate(translationIdentity); - TransformationInterface::Pointer transformITKIdentity = TransformationInterface::Pointer( - new ITKTransformation( - transformITKIdentityTemporary)); + auto transformITKIdentity = boost::make_shared(transformITKIdentityTemporary); TranslationTransformType::Pointer transformITKTranslationTemporary = TranslationTransformType::New(); TranslationTransformType::OutputVectorType translation; translation[0] = 5.0; translation[1] = 5.0; translation[2] = 5.0; transformITKTranslationTemporary->Translate(translation); - TransformationInterface::Pointer transformITKTranslation = TransformationInterface::Pointer( - new ITKTransformation( - transformITKTranslationTemporary)); - - SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorITKIdentity = - SimpleMappableDoseAccessor::Pointer( - new SimpleMappableDoseAccessor( - doseAccessor1GeometricInfo, doseAccessor2, transformITKIdentity, interpolationLinear)); - SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorITKTranslation = - SimpleMappableDoseAccessor::Pointer( - new SimpleMappableDoseAccessor( - doseAccessor1GeometricInfo, doseAccessor2, transformITKTranslation, interpolationLinear)); + auto transformITKTranslation = boost::make_shared(transformITKTranslationTemporary); + + auto aSimpleMappableDoseAccessorITKIdentity = boost::make_shared(doseAccessor1GeometricInfo, doseAccessor2, transformITKIdentity, interpolationLinear); + + auto aSimpleMappableDoseAccessorITKTranslation = boost::make_shared(doseAccessor1GeometricInfo, doseAccessor2, transformITKTranslation, interpolationLinear); //1) Test constructor CHECK_NO_THROW(SimpleMappableDoseAccessor( doseAccessor1GeometricInfo, doseAccessor2, transformITKIdentity, interpolationLinear)); CHECK_NO_THROW(SimpleMappableDoseAccessor( doseAccessor1GeometricInfo, doseAccessor2, transformITKTranslation, interpolationLinear)); CHECK_NO_THROW(ITKTransformation(transformITKTranslationTemporary.GetPointer())); CHECK_THROW_EXPLICIT(ITKTransformation(NULL), core::NullPointerException); //2) test getDoseAt() // a) with Identity transform //test valid voxels std::vector voxelsAsIndexToTest; std::vector expectedValues; voxelsAsIndexToTest.push_back(VoxelGridIndex3D(5, 9, 8)); voxelsAsIndexToTest.push_back(VoxelGridIndex3D(22, 15, 10)); voxelsAsIndexToTest.push_back(VoxelGridIndex3D(30, 20, 7)); expectedValues.push_back(5.0 * doseGridScaling); expectedValues.push_back(22.0 * doseGridScaling); expectedValues.push_back(30.0 * doseGridScaling); //convert VoxelGridIndex3D to VoxelGridID for (size_t i = 0; i < voxelsAsIndexToTest.size(); i++) { VoxelGridID currentId; doseAccessor1GeometricInfo.convert(voxelsAsIndexToTest.at(i), currentId); //test if the expected interpolation values are computed CHECK_EQUAL(aSimpleMappableDoseAccessorITKIdentity->getValueAt(voxelsAsIndexToTest.at(i)), expectedValues.at(i)); //test if getDoseAt(VoxelGridIndex3D) and getDoseAt(VoxelGridD) lead to the same results CHECK_EQUAL(aSimpleMappableDoseAccessorITKIdentity->getValueAt(voxelsAsIndexToTest.at(i)), aSimpleMappableDoseAccessorITKIdentity->getValueAt(currentId)); } //no tests with invalid IDs, this has been done already tested in SimpleMappableDoseAccessorTest //b) with translation transform //translation of one voxel in each direction expectedValues.clear(); expectedValues.push_back(6.0 * doseGridScaling); expectedValues.push_back(23.0 * doseGridScaling); expectedValues.push_back(31.0 * doseGridScaling); for (size_t i = 0; i < voxelsAsIndexToTest.size(); i++) { VoxelGridID currentId; doseAccessor1GeometricInfo.convert(voxelsAsIndexToTest.at(i), currentId); //test if the expected interpolation values are computed CHECK_EQUAL(aSimpleMappableDoseAccessorITKTranslation->getValueAt(voxelsAsIndexToTest.at(i)), expectedValues.at(i)); //test if getDoseAt(VoxelGridIndex3D) and getDoseAt(VoxelGridD) lead to the same results CHECK_EQUAL(aSimpleMappableDoseAccessorITKTranslation->getValueAt(voxelsAsIndexToTest.at(i)), aSimpleMappableDoseAccessorITKTranslation->getValueAt(currentId)); } RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/interpolation/InterpolationMatchPointTransformation/SimpleMappableDoseAccessorWithMatchPointTest.cpp b/testing/interpolation/InterpolationMatchPointTransformation/SimpleMappableDoseAccessorWithMatchPointTest.cpp index 62cae6f..8061d48 100644 --- a/testing/interpolation/InterpolationMatchPointTransformation/SimpleMappableDoseAccessorWithMatchPointTest.cpp +++ b/testing/interpolation/InterpolationMatchPointTransformation/SimpleMappableDoseAccessorWithMatchPointTest.cpp @@ -1,257 +1,239 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbGenericDoseIterator.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbSimpleMappableDoseAccessor.h" #include "rttbNearestNeighborInterpolation.h" #include "rttbLinearInterpolation.h" #include "rttbGeometricInfo.h" #include "rttbTransformationInterface.h" #include "rttbMatchPointTransformation.h" #include "rttbNullPointerException.h" #include "registrationTest.h" #include "simpleRegistrationWorkflow.h" namespace rttb { namespace testing { static const unsigned int TargetDimension3D = 3; static const unsigned int MovingDimension3D = 3; typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef rttb::interpolation::SimpleMappableDoseAccessor SimpleMappableDoseAccessor; typedef map::core::RegistrationTest Registration3D3DTypeTest; typedef Registration3D3DTypeTest::Pointer Registration3D3DTypeTestPointer; typedef map::core::Registration Registration3D3DType; typedef Registration3D3DType::Pointer Registration3D3DPointer; typedef rttb::interpolation::NearestNeighborInterpolation NearestNeighborInterpolation; typedef rttb::interpolation::LinearInterpolation LinearInterpolation; typedef rttb::interpolation::TransformationInterface TransformationInterface; typedef rttb::interpolation::MatchPointTransformation MatchPointTransformation; /*! @brief SimpleMappableDoseAccessorWithMatchPointTest - test the API of SimpleMappableDoseAccessor with MatchPoint transform 1) Test constructor 2) test getDoseAt() a) with Identity transform b) with translation transform [3) test with rigid registration optional (if filenames are given as argument)] */ int SimpleMappableDoseAccessorWithMatchPointTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string RTDOSE_FILENAME_CONSTANT_TWO; std::string RTDOSE_FILENAME_INCREASE_X; std::string RTDOSE_FILENAME_REALISTIC = ""; std::string CT_PLANNING = ""; std::string CT_FRACTION = ""; if (argc > 2) { RTDOSE_FILENAME_CONSTANT_TWO = argv[1]; RTDOSE_FILENAME_INCREASE_X = argv[2]; } else { std::cout << "at least two parameters for SimpleMappableDoseAccessorWithMatchPointTest are expected" << std::endl; return -1; } if (argc > 5) { RTDOSE_FILENAME_REALISTIC = argv[3]; CT_PLANNING = argv[4]; CT_FRACTION = argv[5]; } rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1( RTDOSE_FILENAME_CONSTANT_TWO.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); DoseAccessorPointer doseAccessorNull; rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator2( RTDOSE_FILENAME_INCREASE_X.c_str()); DoseAccessorPointer doseAccessor2(doseAccessorGenerator2.generateDoseAccessor()); core::GeometricInfo doseAccessor1GeometricInfo = doseAccessor1->getGeometricInfo(); Registration3D3DTypeTestPointer registration = Registration3D3DTypeTest::New(); double translation[] = {0.0, 0.0, 0.0}; registration->_translation = translation; registration->_limitedTarget = false; - NearestNeighborInterpolation::Pointer interpolationNN = - NearestNeighborInterpolation::Pointer(new NearestNeighborInterpolation()); - LinearInterpolation::Pointer interpolationLinear = LinearInterpolation::Pointer - (new LinearInterpolation()); + auto interpolationNN = ::boost::make_shared(); + auto interpolationLinear = ::boost::make_shared(); NearestNeighborInterpolation::Pointer interpolationNull; - TransformationInterface::Pointer transformMP = TransformationInterface::Pointer( - new MatchPointTransformation( - registration.GetPointer())); + auto transformMP = ::boost::make_shared(registration.GetPointer()); - SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorMPIdentityLinear = - SimpleMappableDoseAccessor::Pointer( - new SimpleMappableDoseAccessor( - doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationLinear)); - SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorMPIdentityNN = - SimpleMappableDoseAccessor::Pointer( - new SimpleMappableDoseAccessor( - doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationNN)); + auto aSimpleMappableDoseAccessorMPIdentityLinear = ::boost::make_shared(doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationLinear); + auto aSimpleMappableDoseAccessorMPIdentityNN = ::boost::make_shared(doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationNN); //1) Test constructor CHECK_NO_THROW(SimpleMappableDoseAccessor( doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationLinear)); CHECK_NO_THROW(SimpleMappableDoseAccessor( doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationNN)); CHECK_NO_THROW(MatchPointTransformation(registration.GetPointer())); CHECK_THROW_EXPLICIT(MatchPointTransformation(NULL), core::NullPointerException); //2) test getDoseAt() // a) with Identity transform double vectorDoseAccessorStartEnd = 0.0; while (vectorDoseAccessorStartEnd <= 1.0) { VoxelGridID runningID = (VoxelGridID)(vectorDoseAccessorStartEnd * (double)aSimpleMappableDoseAccessorMPIdentityLinear->getGridSize()); CHECK_EQUAL(aSimpleMappableDoseAccessorMPIdentityLinear->getValueAt(runningID), doseAccessor2->getValueAt(runningID)); CHECK_EQUAL(aSimpleMappableDoseAccessorMPIdentityNN->getValueAt(runningID), doseAccessor2->getValueAt(runningID)); vectorDoseAccessorStartEnd += 0.1; } // b) with translation transform //Second: Translation (5mm/5mm/5mm) --> in voxel: (1/1/1) as pixelspacing = 5 mm translation[0] = translation[1] = translation[2] = 5.0; registration->_translation = translation; - SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorMPTranslationLinear = - SimpleMappableDoseAccessor::Pointer(new SimpleMappableDoseAccessor( - doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationLinear)); - SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorMPTranslationNN = - SimpleMappableDoseAccessor::Pointer( - new SimpleMappableDoseAccessor( - doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationNN)); + auto aSimpleMappableDoseAccessorMPTranslationLinear = boost::make_shared(doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationLinear); + auto aSimpleMappableDoseAccessorMPTranslationNN = boost::make_shared(doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationNN); rttb::VoxelGridIndex3D aIndexBeforeTransformation(0, 0, 0); rttb::VoxelGridIndex3D aIndexAfterTransformation(1, 1, 1); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationLinear->getValueAt(aIndexBeforeTransformation), doseAccessor2->getValueAt(aIndexAfterTransformation)); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationNN->getValueAt(aIndexBeforeTransformation), doseAccessor2->getValueAt(aIndexAfterTransformation)); rttb::VoxelGridIndex3D aIndexBeforeTransformation2(20, 10, 10); rttb::VoxelGridIndex3D aIndexAfterTransformation2(21, 11, 11); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationLinear->getValueAt(aIndexBeforeTransformation2), doseAccessor2->getValueAt(aIndexAfterTransformation2)); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationNN->getValueAt(aIndexBeforeTransformation2), doseAccessor2->getValueAt(aIndexAfterTransformation2)); rttb::VoxelGridIndex3D aIndexBeforeTransformation3( aSimpleMappableDoseAccessorMPTranslationLinear->getGeometricInfo().getNumColumns() - 2, aSimpleMappableDoseAccessorMPTranslationLinear->getGeometricInfo().getNumRows() - 2, aSimpleMappableDoseAccessorMPTranslationLinear->getGeometricInfo().getNumSlices() - 2); rttb::VoxelGridIndex3D aIndexAfterTransformation3( aSimpleMappableDoseAccessorMPTranslationLinear->getGeometricInfo().getNumColumns() - 1, aSimpleMappableDoseAccessorMPTranslationLinear->getGeometricInfo().getNumRows() - 1, aSimpleMappableDoseAccessorMPTranslationLinear->getGeometricInfo().getNumSlices() - 1); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationLinear->getValueAt(aIndexBeforeTransformation3), doseAccessor2->getValueAt(aIndexAfterTransformation3)); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationNN->getValueAt(aIndexBeforeTransformation3), doseAccessor2->getValueAt(aIndexAfterTransformation3)); if (RTDOSE_FILENAME_REALISTIC != "" && CT_FRACTION != "" && CT_PLANNING != "") { //3) test with rigid registration //realistic background: registration from BP-CT to fraction CT, apply on planning dose that is based on BP-CT (proof of concept) //Target image: fraction CT, Moving image: planning CT simpleRegistrationWorkflow prepareRegistrationRealisticScenario(CT_FRACTION, CT_PLANNING, true); Registration3D3DPointer registrationRealisticScenario = prepareRegistrationRealisticScenario.getRegistration(); - TransformationInterface::Pointer transformRealistic = TransformationInterface::Pointer( - new MatchPointTransformation( - registrationRealisticScenario)); + auto transformRealistic = boost::make_shared(registrationRealisticScenario); io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator3(RTDOSE_FILENAME_REALISTIC.c_str()); DoseAccessorPointer doseAccessor3(doseAccessorGenerator3.generateDoseAccessor()); core::GeometricInfo geoInfoRealistic; geoInfoRealistic.setNumColumns( prepareRegistrationRealisticScenario.getTargetImage()->GetLargestPossibleRegion().GetSize()[0]); geoInfoRealistic.setNumRows( prepareRegistrationRealisticScenario.getTargetImage()->GetLargestPossibleRegion().GetSize()[1]); geoInfoRealistic.setNumSlices( prepareRegistrationRealisticScenario.getTargetImage()->GetLargestPossibleRegion().GetSize()[2]); //Dose is related to BP-CT, map dose to fraction CT geometry - SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorRealisticScenarioLinear = - SimpleMappableDoseAccessor::Pointer(new SimpleMappableDoseAccessor(geoInfoRealistic, - doseAccessor3, transformRealistic, interpolationLinear)); + auto aSimpleMappableDoseAccessorRealisticScenarioLinear = boost::make_shared(geoInfoRealistic, + doseAccessor3, transformRealistic, interpolationLinear); //combination of 0, size/2 and size to check as coordinates std::vector coordinatesToCheckX, coordinatesToCheckY, coordinatesToCheckZ; coordinatesToCheckX.push_back(0); coordinatesToCheckX.push_back(geoInfoRealistic.getNumColumns() / 2); coordinatesToCheckX.push_back(geoInfoRealistic.getNumColumns() - 1); coordinatesToCheckY.push_back(0); coordinatesToCheckY.push_back(geoInfoRealistic.getNumRows() / 2); coordinatesToCheckY.push_back(geoInfoRealistic.getNumRows() - 1); coordinatesToCheckZ.push_back(0); coordinatesToCheckZ.push_back(geoInfoRealistic.getNumSlices() / 2); coordinatesToCheckZ.push_back(geoInfoRealistic.getNumSlices() - 1); //Pixels are inside the fraction CT image and mapping should work (even if they map outside of doseAccessor3) for (size_t i = 0; i < coordinatesToCheckX.size(); ++i) { for (size_t j = 0; j < coordinatesToCheckY.size(); ++j) { for (size_t k = 0; k < coordinatesToCheckZ.size(); ++k) { CHECK_NO_THROW(aSimpleMappableDoseAccessorRealisticScenarioLinear->getValueAt(VoxelGridIndex3D( coordinatesToCheckX.at(i), coordinatesToCheckY.at(j), coordinatesToCheckZ.at(k)))); } } } } RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/interpolation/InterpolationTest.cpp b/testing/interpolation/InterpolationTest.cpp index 00042fd..24724cb 100644 --- a/testing/interpolation/InterpolationTest.cpp +++ b/testing/interpolation/InterpolationTest.cpp @@ -1,219 +1,214 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include #include +#include #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbNearestNeighborInterpolation.h" #include "rttbLinearInterpolation.h" #include "rttbDicomDoseAccessor.h" #include "rttbGenericDoseIterator.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbNullPointerException.h" #include "rttbMappingOutsideOfImageException.h" namespace rttb { namespace testing { typedef rttb::interpolation::NearestNeighborInterpolation NearestNeighborInterpolation; typedef rttb::interpolation::LinearInterpolation LinearInterpolation; typedef rttb::core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; /*! @brief InterpolationTest - tests only interpolation 1) test both interpolation types with simple image (Dose = 2) 2) test both interpolation types with increasing x image values image (Dose = y value) 3) test exception handling */ int InterpolationTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string RTDOSE_FILENAME_CONSTANT_TWO; std::string RTDOSE_FILENAME_INCREASE_X; if (argc > 2) { RTDOSE_FILENAME_CONSTANT_TWO = argv[1]; RTDOSE_FILENAME_INCREASE_X = argv[2]; } else { std::cout << "at least two parameters for InterpolationTest expected" << std::endl; return -1; } rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1( RTDOSE_FILENAME_CONSTANT_TWO.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); DoseAccessorPointer doseAccessorNull; rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator2( RTDOSE_FILENAME_INCREASE_X.c_str()); DoseAccessorPointer doseAccessor2(doseAccessorGenerator2.generateDoseAccessor()); //doseAccessor1 is used as dose image - boost::shared_ptr interpolationNN = - boost::shared_ptr(new NearestNeighborInterpolation()); + auto interpolationNN = boost::make_shared(); interpolationNN->setAccessorPointer(doseAccessor1); - boost::shared_ptr interpolationLinear = boost::shared_ptr - (new LinearInterpolation()); + auto interpolationLinear = boost::make_shared(); interpolationLinear->setAccessorPointer(doseAccessor1); //doseAccessor2 is used as dose image. //RTDOSE_FILENAME_INCREASE_X and RTDOSE_FILENAME_CONSTANT_TWO have the same GeometricInfo - boost::shared_ptr interpolationNN2 = - boost::shared_ptr(new NearestNeighborInterpolation()); + auto interpolationNN2 = boost::make_shared(); interpolationNN2->setAccessorPointer(doseAccessor2); - boost::shared_ptr interpolationLinear2 = - boost::shared_ptr(new LinearInterpolation()); + auto interpolationLinear2 = boost::make_shared(); interpolationLinear2->setAccessorPointer(doseAccessor2); - boost::shared_ptr interpolationNullNN = - boost::shared_ptr(new NearestNeighborInterpolation()); - boost::shared_ptr interpolationNullLinear = - boost::shared_ptr(new LinearInterpolation()); + auto interpolationNullNN = boost::make_shared(); + auto interpolationNullLinear = boost::make_shared(); rttb::WorldCoordinate3D imagePositionPatient = doseAccessor1->getGeometricInfo().getImagePositionPatient(); rttb::SpacingVectorType3D pixelSpacing = doseAccessor1->getGeometricInfo().getSpacing(); unsigned int size[] = {doseAccessor1->getGeometricInfo().getNumColumns(), doseAccessor1->getGeometricInfo().getNumRows(), doseAccessor1->getGeometricInfo().getNumSlices()}; //Which voxels to check is irrelevant. The following three situations are checked: // - exactly in-between two voxels: v_i=(0.5*v1 + 0.5*v2) --> target 0.5 // - the middle of a voxel: v_i = 1*v1 --> target 0 (semantically equivalent with target 1 and left/right flipped) // - 10% shifted from the middle: v_i=0.1*v1 + 0.9*v2 --> target 0.9 std::vector coordinatesX; coordinatesX.push_back(imagePositionPatient.x() - (pixelSpacing.x() * 0.5)); coordinatesX.push_back(imagePositionPatient.x() + 5 * pixelSpacing.x()); coordinatesX.push_back(imagePositionPatient.x() + 9.9 * pixelSpacing.x()); std::vector coordinatesY; coordinatesY.push_back(imagePositionPatient.y() - (pixelSpacing.y() * 0.5)); coordinatesY.push_back(imagePositionPatient.y() + 5 * pixelSpacing.y()); coordinatesY.push_back(imagePositionPatient.x() + 9.9 * pixelSpacing.y()); std::vector coordinatesZ; coordinatesZ.push_back(imagePositionPatient.z() - (pixelSpacing.z() * 0.5)); coordinatesZ.push_back(imagePositionPatient.z() + 5 * pixelSpacing.z()); coordinatesZ.push_back(imagePositionPatient.z() + 9.9 * pixelSpacing.z()); std::vector coordinatesToCheck; for (int x = 0; x < coordinatesX.size(); x++) { for (int y = 0; y < coordinatesY.size(); y++) { for (int z = 0; z < coordinatesZ.size(); z++) { coordinatesToCheck.push_back(rttb::WorldCoordinate3D(coordinatesX.at(x), coordinatesY.at(y), coordinatesZ.at(z))); } } } rttb::WorldCoordinate3D positionOutsideOfImageLeft = imagePositionPatient - rttb::WorldCoordinate3D( pixelSpacing.x() * 2.0, pixelSpacing.y() * 2.0, pixelSpacing.z() * 2.0); rttb::WorldCoordinate3D positionOutsideOfImageRight = imagePositionPatient + rttb::WorldCoordinate3D(size[0] * pixelSpacing.x(), size[1] * pixelSpacing.y(), size[2] * pixelSpacing.z()); //precomputed values for Nearest neighbor + Linear interpolator double expectedDoseIncreaseXNearest[27]; double expectedDoseIncreaseXLinear[27]; for (int i = 0; i < 27; i++) { if (i < 9) { expectedDoseIncreaseXNearest[i] = 0.0; expectedDoseIncreaseXLinear[i] = 1.41119e-005; } else if (i < 18) { expectedDoseIncreaseXNearest[i] = 0.000141119; expectedDoseIncreaseXLinear[i] = 0.000141119; } else { expectedDoseIncreaseXNearest[i] = 0.000282239; expectedDoseIncreaseXLinear[i] = 0.000279416; } } //TEST 1) RTDOSE_FILENAME_CONSTANT_TWO contains Dose 2.0 Gy for each pixel, so for every interpolation, 2.0 has to be the result std::vector::const_iterator iterCoordinates = coordinatesToCheck.cbegin(); while (iterCoordinates != coordinatesToCheck.cend()) { CHECK_EQUAL(interpolationNN->getValue(*iterCoordinates), 2.0); CHECK_EQUAL(interpolationLinear->getValue(*iterCoordinates), 2.0); ++iterCoordinates; } //TEST 2) RTDOSE_FILENAME_INCREASE_X contains a Dose gradient file, correct interpolation values have been computed manually. To avoid floating point inaccuracy, CHECK_CLOSE is used iterCoordinates = coordinatesToCheck.cbegin(); unsigned int index = 0; while (iterCoordinates != coordinatesToCheck.cend() && index < 27) { CHECK_CLOSE(interpolationNN2->getValue(*iterCoordinates), expectedDoseIncreaseXNearest[index], errorConstant); CHECK_CLOSE(interpolationLinear2->getValue(*iterCoordinates), expectedDoseIncreaseXLinear[index], errorConstant); ++iterCoordinates; ++index; } //TEST 3) Exception handling //Check that core::MappingOutOfImageException is thrown if requested position is outside image CHECK_THROW_EXPLICIT(interpolationNN->getValue(positionOutsideOfImageLeft), core::MappingOutsideOfImageException); CHECK_THROW_EXPLICIT(interpolationNN->getValue(positionOutsideOfImageRight), core::MappingOutsideOfImageException); CHECK_THROW_EXPLICIT(interpolationLinear->getValue(positionOutsideOfImageLeft), core::MappingOutsideOfImageException); CHECK_THROW_EXPLICIT(interpolationLinear->getValue(positionOutsideOfImageRight), core::MappingOutsideOfImageException); //Check that core::NullPointerException is thrown if Null Pointers are given to interpolator CHECK_THROW_EXPLICIT(interpolationNullLinear->setAccessorPointer(doseAccessorNull), core::NullPointerException); CHECK_THROW_EXPLICIT(interpolationNullNN->setAccessorPointer(doseAccessorNull), core::NullPointerException); CHECK_THROW_EXPLICIT(interpolationNullLinear->getValue(coordinatesToCheck.front()), core::NullPointerException); CHECK_THROW_EXPLICIT(interpolationNullNN->getValue(coordinatesToCheck.front()), core::NullPointerException); //Check that no exception is thrown otherwise - CHECK_NO_THROW(boost::shared_ptr(new NearestNeighborInterpolation())); - CHECK_NO_THROW(boost::shared_ptr(new LinearInterpolation())); + CHECK_NO_THROW(boost::make_shared()); + CHECK_NO_THROW(boost::make_shared()); RETURN_AND_REPORT_TEST_SUCCESS; } } } diff --git a/testing/interpolation/RosuMappableDoseAccessorTest.cpp b/testing/interpolation/RosuMappableDoseAccessorTest.cpp index fa9b3d8..268f964 100644 --- a/testing/interpolation/RosuMappableDoseAccessorTest.cpp +++ b/testing/interpolation/RosuMappableDoseAccessorTest.cpp @@ -1,153 +1,150 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include "litCheckMacros.h" +#include + #include "rttbBaseType.h" #include "rttbGenericDoseIterator.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbRosuMappableDoseAccessor.h" #include "DummyTransformation.h" #include "rttbNullPointerException.h" #include "rttbMappingOutsideOfImageException.h" namespace rttb { namespace testing { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef rttb::interpolation::RosuMappableDoseAccessor RosuMappableDoseAccessor; typedef rttb::interpolation::TransformationInterface TransformationInterface; /*! @brief RosuMappableDoseAccessorTest - test the API of RosuMappableDoseAccessor 1) Constructor 2) test getDoseAt() */ int RosuMappableDoseAccessorTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string RTDOSE_FILENAME_CONSTANT_TWO; std::string RTDOSE_FILENAME_INCREASE_X; if (argc > 2) { RTDOSE_FILENAME_CONSTANT_TWO = argv[1]; RTDOSE_FILENAME_INCREASE_X = argv[2]; } else { std::cout << "at least two parameters for RosuMappableDoseAccessorTest are expected" << std::endl; return -1; } const double doseGridScaling = 2.822386e-005; rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1( RTDOSE_FILENAME_CONSTANT_TWO.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator2( RTDOSE_FILENAME_INCREASE_X.c_str()); DoseAccessorPointer doseAccessor2(doseAccessorGenerator2.generateDoseAccessor()); DoseAccessorPointer doseAccessorNull; - auto transformDummy = TransformationInterface::Pointer(new DummyTransformation()); + auto transformDummy = boost::make_shared(); TransformationInterface::Pointer transformNull; - auto aRosuMappableDoseAccessorDefault = - RosuMappableDoseAccessor::Pointer(new RosuMappableDoseAccessor( - doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy)); - - auto aRosuMappableDoseAccessorNoPadding = - RosuMappableDoseAccessor::Pointer(new RosuMappableDoseAccessor( - doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, false)); + auto aRosuMappableDoseAccessorDefault = boost::make_shared(doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy); + auto aRosuMappableDoseAccessorNoPadding = boost::make_shared(doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, false); //1) Constructor CHECK_NO_THROW(RosuMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy)); CHECK_NO_THROW(RosuMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, false)); CHECK_NO_THROW(RosuMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, true, 5.0)); CHECK_THROW_EXPLICIT(RosuMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessorNull, transformDummy), core::NullPointerException); CHECK_THROW_EXPLICIT(RosuMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessor2, transformNull), core::NullPointerException); CHECK_THROW_EXPLICIT(RosuMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessorNull, transformNull), core::NullPointerException); //2) test getDoseAt() std::vector voxelsAsIndexToTest; std::vector voxelsAsIdToTest; std::vector expectedValues; voxelsAsIndexToTest.push_back(VoxelGridIndex3D(5, 9, 8)); voxelsAsIndexToTest.push_back(VoxelGridIndex3D(22, 15, 10)); voxelsAsIndexToTest.push_back(VoxelGridIndex3D(30, 20, 7)); expectedValues.push_back(5.0 * doseGridScaling); expectedValues.push_back(22.0 * doseGridScaling); expectedValues.push_back(30.0 * doseGridScaling); //convert VoxelGridIndex3D to VoxelGridID for (int i = 0; i < voxelsAsIndexToTest.size(); i++) { VoxelGridID currentId; doseAccessor1->getGeometricInfo().convert(voxelsAsIndexToTest.at(i), currentId); voxelsAsIdToTest.push_back(currentId); } for (int i = 0; i < voxelsAsIndexToTest.size(); i++) { //test if the expected interpolation values are computed CHECK_CLOSE(aRosuMappableDoseAccessorDefault->getValueAt(voxelsAsIndexToTest.at(i)), expectedValues.at(i), errorConstant); //test if getDoseAt(VoxelGridIndex3D) and getDoseAt(VoxelGridD) lead to the same results CHECK_EQUAL(aRosuMappableDoseAccessorDefault->getValueAt(voxelsAsIndexToTest.at(i)), aRosuMappableDoseAccessorDefault->getValueAt(voxelsAsIdToTest.at(i))); } //test invalid voxels VoxelGridID invalidID(doseAccessor1->getGeometricInfo().getNumberOfVoxels() + 1); VoxelGridIndex3D invalidIndex(doseAccessor1->getGeometricInfo().getNumColumns() + 1, doseAccessor1->getGeometricInfo().getNumRows() + 1, doseAccessor1->getGeometricInfo().getNumSlices() + 1); CHECK_EQUAL(aRosuMappableDoseAccessorDefault->getValueAt(invalidID), 0.0); CHECK_EQUAL(aRosuMappableDoseAccessorDefault->getValueAt(invalidIndex), 0.0); CHECK_THROW_EXPLICIT(aRosuMappableDoseAccessorNoPadding->getValueAt(invalidID), core::MappingOutsideOfImageException); CHECK_THROW_EXPLICIT(aRosuMappableDoseAccessorNoPadding->getValueAt(invalidIndex), core::MappingOutsideOfImageException); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/interpolation/SimpleMappableDoseAccessorTest.cpp b/testing/interpolation/SimpleMappableDoseAccessorTest.cpp index 451d743..93086da 100644 --- a/testing/interpolation/SimpleMappableDoseAccessorTest.cpp +++ b/testing/interpolation/SimpleMappableDoseAccessorTest.cpp @@ -1,168 +1,168 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include "boost/make_shared.hpp" #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbGenericDoseIterator.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbSimpleMappableDoseAccessor.h" #include "rttbNearestNeighborInterpolation.h" #include "rttbLinearInterpolation.h" #include "rttbTransformationInterface.h" #include "DummyTransformation.h" #include "rttbNullPointerException.h" #include "rttbMappingOutsideOfImageException.h" namespace rttb { namespace testing { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef rttb::interpolation::SimpleMappableDoseAccessor SimpleMappableDoseAccessor; typedef rttb::interpolation::TransformationInterface TransformationInterface; typedef rttb::interpolation::LinearInterpolation LinearInterpolation; typedef rttb::interpolation::NearestNeighborInterpolation NearestNeighborInterpolation; /*! @brief SimpleMappableDoseAccessorTest - test the API of SimpleMappableDoseAccessor 1) Test constructor 2) test getDoseAt() */ int SimpleMappableDoseAccessorTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string RTDOSE_FILENAME_CONSTANT_TWO; std::string RTDOSE_FILENAME_INCREASE_X; if (argc > 2) { RTDOSE_FILENAME_CONSTANT_TWO = argv[1]; RTDOSE_FILENAME_INCREASE_X = argv[2]; } else { std::cout << "at least two parameters for SimpleMappableDoseAccessorTest are expected" << std::endl; return -1; } const double doseGridScaling = 2.822386e-005; rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1( RTDOSE_FILENAME_CONSTANT_TWO.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); core::GeometricInfo doseAccessor1GeometricInfo = doseAccessor1->getGeometricInfo(); rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator2( RTDOSE_FILENAME_INCREASE_X.c_str()); DoseAccessorPointer doseAccessor2(doseAccessorGenerator2.generateDoseAccessor()); DoseAccessorPointer doseAccessorNull; - TransformationInterface::Pointer transformDummy = boost::make_shared(); + TransformationInterface::Pointer transformDummy = boost::make_shared(); TransformationInterface::Pointer transformNull; - NearestNeighborInterpolation::Pointer interpolationNN = boost::make_shared(); - LinearInterpolation::Pointer interpolationLinear = boost::make_shared(); - boost::shared_ptr interpolationNull; + auto interpolationNN = boost::make_shared(); + auto interpolationLinear = boost::make_shared(); + boost::shared_ptr interpolationNull; - SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorDefault = boost::make_shared( + auto aSimpleMappableDoseAccessorDefault = boost::make_shared( doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy); - SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorNoPadding = boost::make_shared( + auto aSimpleMappableDoseAccessorNoPadding = boost::make_shared( doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, interpolationLinear, false); //1) Test constructor CHECK_NO_THROW(SimpleMappableDoseAccessor( doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy)); CHECK_NO_THROW(SimpleMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, interpolationLinear)); CHECK_NO_THROW(SimpleMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, interpolationLinear, false)); CHECK_NO_THROW(SimpleMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, interpolationLinear, true, 5.0)); CHECK_NO_THROW(SimpleMappableDoseAccessor(doseAccessor1GeometricInfo, doseAccessor2, transformDummy, interpolationNN)); CHECK_THROW_EXPLICIT(SimpleMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessorNull, transformDummy, interpolationLinear), core::NullPointerException); CHECK_THROW_EXPLICIT(SimpleMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessor2, transformNull, interpolationLinear), core::NullPointerException); CHECK_THROW_EXPLICIT(SimpleMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessorNull, transformNull, interpolationLinear), core::NullPointerException); CHECK_THROW_EXPLICIT(SimpleMappableDoseAccessor(doseAccessor1GeometricInfo, doseAccessor2, transformDummy, interpolationNull), core::NullPointerException); //2) test getGeometricInfo(), getGridSize(), getDoseUID() function CHECK_EQUAL(aSimpleMappableDoseAccessorDefault->getGeometricInfo(), doseAccessor1->getGeometricInfo()); CHECK_EQUAL(aSimpleMappableDoseAccessorDefault->getGridSize(), doseAccessor1->getGeometricInfo().getNumberOfVoxels()); CHECK_EQUAL(aSimpleMappableDoseAccessorDefault->getUID(), doseAccessor2->getUID()); //3) test getDoseAt() //test valid voxels std::vector voxelsAsIndexToTest; std::vector expectedValues; voxelsAsIndexToTest.push_back(VoxelGridIndex3D(5, 9, 8)); voxelsAsIndexToTest.push_back(VoxelGridIndex3D(22, 15, 10)); voxelsAsIndexToTest.push_back(VoxelGridIndex3D(30, 20, 7)); expectedValues.push_back(5.0 * doseGridScaling); expectedValues.push_back(22.0 * doseGridScaling); expectedValues.push_back(30.0 * doseGridScaling); for (int i = 0; i < voxelsAsIndexToTest.size(); i++) { VoxelGridID currentId; doseAccessor1GeometricInfo.convert(voxelsAsIndexToTest.at(i), currentId); //test if the expected interpolation values are computed CHECK_EQUAL(aSimpleMappableDoseAccessorDefault->getValueAt(currentId), expectedValues.at(i)); //test if getDoseAt(VoxelGridIndex3D) and getDoseAt(VoxelGridD) lead to the same results CHECK_EQUAL(aSimpleMappableDoseAccessorDefault->getValueAt(currentId), aSimpleMappableDoseAccessorDefault->getValueAt(voxelsAsIndexToTest.at(i))); } //test invalid voxels VoxelGridID invalidID(doseAccessor1GeometricInfo.getNumberOfVoxels() + 1); VoxelGridIndex3D invalidIndex(doseAccessor1GeometricInfo.getNumColumns() + 1, doseAccessor1GeometricInfo.getNumRows() + 1, doseAccessor1GeometricInfo.getNumSlices() + 1); CHECK_EQUAL(aSimpleMappableDoseAccessorDefault->getValueAt(invalidID), 0.0); CHECK_EQUAL(aSimpleMappableDoseAccessorDefault->getValueAt(invalidIndex), 0.0); CHECK_THROW_EXPLICIT(aSimpleMappableDoseAccessorNoPadding->getValueAt(invalidID), core::MappingOutsideOfImageException); CHECK_THROW_EXPLICIT(aSimpleMappableDoseAccessorNoPadding->getValueAt(invalidIndex), core::MappingOutsideOfImageException); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb