diff --git a/CMakeLists.txt b/CMakeLists.txt index bf61d17..f337274 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,281 +1,285 @@ #----------------------------------------------------------------------------- # This is the root RTToolbox CMakeList file. #----------------------------------------------------------------------------- PROJECT(RTToolbox) CMAKE_MINIMUM_REQUIRED(VERSION 2.8) IF(CMAKE_BACKWARDS_COMPATIBILITY GREATER 2.8) SET(CMAKE_BACKWARDS_COMPATIBILITY 2.8 CACHE STRING "Latest version of CMake when this project was released." FORCE) ENDIF(CMAKE_BACKWARDS_COMPATIBILITY GREATER 2.8) # RTToolbox version number. SET(RTToolbox_VERSION_MAJOR "2") SET(RTToolbox_VERSION_MINOR "0") SET(RTToolbox_VERSION_PATCH "0") # Version string should not include patch level. The major.minor is # enough to distinguish available features of the toolbox. SET(RTToolbox_VERSION_STRING "${RTToolbox_VERSION_MAJOR}.${RTToolbox_VERSION_MINOR}") SET(RTToolbox_FULL_VERSION_STRING "${RTToolbox_VERSION_MAJOR}.${RTToolbox_VERSION_MINOR}.${RTToolbox_VERSION_PATCH}") # default build type SET(CMAKE_BUILD_TYPE Release) IF (WIN32) OPTION(BUILD_SHARED_LIBS "Build MatchPoint with shared libraries." OFF) ELSE (WIN32) OPTION(BUILD_SHARED_LIBS "Build MatchPoint with shared libraries." ON) ENDIF (WIN32) MARK_AS_ADVANCED(BUILD_SHARED_LIBS) +IF (WIN32) +add_definitions(-D_SCL_SECURE_NO_WARNINGS) +ENDIF(WIN32) + IF(BUILD_SHARED_LIBS) IF(WIN32) MESSAGE(FATAL_ERROR "RTToolbox currently does not support a dynamic build on Windows. We are working on that...") ENDIF(WIN32) ELSE(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(BUILD_SHARED_LIBS) message(STATUS ${CMAKE_BUILD_TYPE}) #----------------------------------------------------------------------------- # 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) #----------------------------------------------------------------------------- # Basis config RTTB module infrastructure #----------------------------------------------------------------------------- set(RTTB_MODULES_CONF_DIR ${RTToolbox_BINARY_DIR}/modulesConf CACHE INTERNAL "Modules Conf") set(RTTB_MODULES_PACKAGE_DEPENDS_DIR ${RTToolbox_SOURCE_DIR}/cmake/PackageDepends) set(MODULES_PACKAGE_DEPENDS_DIRS ${RTTB_MODULES_PACKAGE_DEPENDS_DIR}) #----------------------------------------------------------------------------- # Testing setup # Configure Dart testing support. This should be done before any # MESSAGE(FATAL_ERROR ...) commands are invoked. #----------------------------------------------------------------------------- SET(CTEST_NEW_FORMAT 1) INCLUDE(CTest) ENABLE_TESTING() IF(BUILD_TESTING) CONFIGURE_FILE(${RTToolbox_SOURCE_DIR}/cmake/RemoveTemporaryFiles.cmake.in ${RTToolbox_BINARY_DIR}/cmake/RemoveTemporaryFiles.cmake @ONLY IMMEDIATE) CONFIGURE_FILE(${RTToolbox_SOURCE_DIR}/cmake/rttbSampleBuildTest.cmake.in ${RTToolbox_BINARY_DIR}/cmake/rttbSampleBuildTest.cmake @ONLY) CONFIGURE_FILE(${RTToolbox_SOURCE_DIR}/cmake/CTestCustom.ctest.in ${RTToolbox_BINARY_DIR}/cmake/CTestCustom.ctest @ONLY) FILE(WRITE ${RTToolbox_BINARY_DIR}/CTestCustom.cmake "INCLUDE(\"${RTToolbox_BINARY_DIR}/cmake/CTestCustom.ctest\")\n") SET(BUILDNAME "${BUILDNAME}" CACHE STRING "Name of build on the dashboard") MARK_AS_ADVANCED(BUILDNAME) ENDIF(BUILD_TESTING) #----------------------------------------------------------------------------- # Output directories. #----------------------------------------------------------------------------- IF(NOT LIBRARY_OUTPUT_PATH) SET (LIBRARY_OUTPUT_PATH ${RTToolbox_BINARY_DIR}/bin CACHE PATH "Single output directory for building all libraries.") ENDIF(NOT LIBRARY_OUTPUT_PATH) IF(NOT EXECUTABLE_OUTPUT_PATH) SET (EXECUTABLE_OUTPUT_PATH ${RTToolbox_BINARY_DIR}/bin CACHE PATH "Single output directory for building all executables.") ENDIF(NOT EXECUTABLE_OUTPUT_PATH) MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH) MARK_AS_ADVANCED(LIBRARY_OUTPUT_PATH EXECUTABLE_OUTPUT_PATH) SET(RTToolbox_LIBRARY_PATH "${LIBRARY_OUTPUT_PATH}") SET(RTToolbox_EXECUTABLE_PATH "${EXECUTABLE_OUTPUT_PATH}") #----------------------------------------------------------------------------- # Find Doxygen. #----------------------------------------------------------------------------- FIND_PROGRAM(DOXYGEN_EXECUTABLE "doxygen") #----------------------------------------------------------------------------- # Installation vars. # RTToolbox_INSTALL_BIN_DIR - binary dir (executables) # RTToolbox_INSTALL_LIB_DIR - library dir (libs) # RTToolbox_INSTALL_INCLUDE_DIR - include dir (headers) # RTToolbox_INSTALL_NO_DEVELOPMENT - do not install development files # RTToolbox_INSTALL_NO_RUNTIME - do not install runtime files # RTToolbox_INSTALL_NO_DOCUMENTATION - do not install documentation files # Remark: needs directory are stored with no leading slash (CMake 2.4 and newer) #----------------------------------------------------------------------------- IF(NOT RTTOOLBOX_INSTALL_BIN_DIR) SET(RTTOOLBOX_INSTALL_BIN_DIR "bin") ENDIF(NOT RTTOOLBOX_INSTALL_BIN_DIR) IF(NOT RTTOOLBOX_INSTALL_LIB_DIR) SET(RTTOOLBOX_INSTALL_LIB_DIR "lib") ENDIF(NOT RTTOOLBOX_INSTALL_LIB_DIR) IF(NOT RTTOOLBOX_INSTALL_PACKAGE_DIR) SET(RTTOOLBOX_INSTALL_PACKAGE_DIR "lib") ENDIF(NOT RTTOOLBOX_INSTALL_PACKAGE_DIR) IF(NOT RTTOOLBOX_INSTALL_INCLUDE_DIR) SET(RTTOOLBOX_INSTALL_INCLUDE_DIR "include") ENDIF(NOT RTTOOLBOX_INSTALL_INCLUDE_DIR) IF(NOT RTTOOLBOX_INSTALL_NO_DEVELOPMENT) SET(RTTOOLBOX_INSTALL_NO_DEVELOPMENT 0) ENDIF(NOT RTTOOLBOX_INSTALL_NO_DEVELOPMENT) IF(NOT RTTOOLBOX_INSTALL_NO_RUNTIME) SET(RTTOOLBOX_INSTALL_NO_RUNTIME 0) ENDIF(NOT RTTOOLBOX_INSTALL_NO_RUNTIME) IF(NOT RTTOOLBOX_INSTALL_NO_DOCUMENTATION) SET(RTTOOLBOX_INSTALL_NO_DOCUMENTATION 0) ENDIF(NOT RTTOOLBOX_INSTALL_NO_DOCUMENTATION) SET(RTTOOLBOX_INSTALL_NO_LIBRARIES) IF(RTTOOLBOX_BUILD_SHARED_LIBS) IF(RTTOOLBOX_INSTALL_NO_RUNTIME AND RTTOOLBOX_INSTALL_NO_DEVELOPMENT) SET(RTTOOLBOX_INSTALL_NO_LIBRARIES 1) ENDIF(RTTOOLBOX_INSTALL_NO_RUNTIME AND RTTOOLBOX_INSTALL_NO_DEVELOPMENT) ELSE(RTTOOLBOX_BUILD_SHARED_LIBS) IF(RTTOOLBOX_INSTALL_NO_DEVELOPMENT) SET(RTTOOLBOX_INSTALL_NO_LIBRARIES 1) ENDIF(RTTOOLBOX_INSTALL_NO_DEVELOPMENT) ENDIF(RTTOOLBOX_BUILD_SHARED_LIBS) # set RTToolbox_DIR so it can be used by subprojects SET(RTToolbox_DIR "${CMAKE_BINARY_DIR}" CACHE INTERNAL "RTToolbox dir to be used by subprojects") #----------------------------------------------------------------------------- # DCMTK MT-Flag treat #----------------------------------------------------------------------------- option(RTTB_DCMTK_COMPLIANCE_ENFORCE_MT "This enforces the whole RTToolbox to be compiled with /MT,/MTd to be compliant with DCMTK" OFF) string(FIND ${CMAKE_GENERATOR} "Visual Studio" RTTB_VS_USED) if(RTTB_DCMTK_COMPLIANCE_ENFORCE_MT AND RTTB_VS_USED EQUAL 0) message(STATUS "Enforce DCMTK compliance: /MT and /MTd flags are used") string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG}) message(STATUS "CMAKE_C_FLAGS_DEBUG set to: ${CMAKE_C_FLAGS_DEBUG}") string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE}) message(STATUS "CMAKE_C_FLAGS_RELEASE set to: ${CMAKE_C_FLAGS_RELEASE}") string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_MINSIZEREL ${CMAKE_C_FLAGS_MINSIZEREL}) message(STATUS "CMAKE_C_FLAGS_MINSIZEREL set to: ${CMAKE_C_FLAGS_MINSIZEREL}") string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELWITHDEBINFO}) message(STATUS "CMAKE_C_FLAGS_RELWITHDEBINFO set to: ${CMAKE_C_FLAGS_RELWITHDEBINFO}") string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) message(STATUS "CMAKE_CXX_FLAGS_DEBUG set to: ${CMAKE_CXX_FLAGS_DEBUG}") string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE}) message(STATUS "CMAKE_CXX_FLAGS_RELEASE set to: ${CMAKE_CXX_FLAGS_RELEASE}") string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS_MINSIZEREL}) message(STATUS "CMAKE_CXX_FLAGS_MINSIZEREL set to: ${CMAKE_CXX_FLAGS_MINSIZEREL}") string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}) message(STATUS "CMAKE_CXX_FLAGS_RELWITHDEBINFO set to: ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") endif() #----------------------------------------------------------------------------- # Advanced RTToolbox configuration #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # RTToolbox build configuration options. IF (WIN32) OPTION(BUILD_SHARED_LIBS "Build RTToolbox with shared libraries." OFF) ELSE (WIN32) OPTION(BUILD_SHARED_LIBS "Build RTToolbox with shared libraries." ON) ENDIF (WIN32) SET(RTToolbox_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS}) IF(NOT RTToolbox_NO_LIBRARY_VERSION) # This setting of SOVERSION assumes that any API change # will increment either the minor or major version number of RTToolbox. SET(RTToolbox_LIBRARY_PROPERTIES VERSION "${RTToolbox_VERSION_MAJOR}.${RTToolbox_VERSION_MINOR}.${RTToolbox_VERSION_PATCH}" SOVERSION "${RTToolbox_VERSION_MAJOR}.${RTToolbox_VERSION_MINOR}" ) ENDIF(NOT RTToolbox_NO_LIBRARY_VERSION) #----------------------------------------------------------------------------- # Configure files with settings for use by the build. # #----------------------------------------------------------------------------- CONFIGURE_FILE(${RTToolbox_SOURCE_DIR}/RTToolboxConfigure.h.in ${RTToolbox_BINARY_DIR}/RTToolboxConfigure.h) IF(NOT RTTOOLBOX_INSTALL_NO_DEVELOPMENT) INSTALL(FILES ${RTToolbox_BINARY_DIR}/RTToolboxConfigure.h DESTINATION ${RTTOOLBOX_INSTALL_INCLUDE_DIR} COMPONENT Development) ENDIF(NOT RTTOOLBOX_INSTALL_NO_DEVELOPMENT) #----------------------------------------------------------------------------- # The entire RTToolbox tree should use the same include path #----------------------------------------------------------------------------- #Default include dir. Others dirs will be defined by activated subprojects INCLUDE_DIRECTORIES(${RTToolbox_BINARY_DIR}) LINK_DIRECTORIES(${LIBARY_OUTPUT_PATH}) #Prepare the correct target information export by the subprojects SET(RTToolbox_TARGETS_FILE "${RTToolbox_BINARY_DIR}/RTToolboxTargets.cmake") FILE(WRITE ${RTToolbox_TARGETS_FILE} "# Generated by CMake, do not edit!") #----------------------------------------------------------------------------- # Dispatch the build into the proper subdirectories. #----------------------------------------------------------------------------- MESSAGE (STATUS "generating Project RTToolboxt") ADD_SUBDIRECTORY (code) ADD_SUBDIRECTORY (demoapps) 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/code/algorithms/rttbDoseStatistics.cpp b/code/algorithms/rttbDoseStatistics.cpp index 05bd378..ac63f89 100644 --- a/code/algorithms/rttbDoseStatistics.cpp +++ b/code/algorithms/rttbDoseStatistics.cpp @@ -1,387 +1,453 @@ // ----------------------------------------------------------------------- // 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 #include #include #include #include "rttbDoseStatistics.h" #include "rttbNullPointerException.h" #include "rttbInvalidDoseException.h" -namespace rttb{ +namespace rttb +{ - namespace algorithms{ + namespace algorithms + { DoseStatistics::DoseStatistics() - { - initSuccess=false; - } + { + initSuccess = false; + } DoseStatistics::DoseStatistics(DoseIteratorPointer aDoseIterator) - { - _doseIterator=aDoseIterator; - initSuccess=false; + { + _doseIterator = aDoseIterator; + initSuccess = false; this->init(); - } + } void DoseStatistics::setDoseIterator(DoseIteratorPointer aDoseIterator) - { - _doseIterator=aDoseIterator; - initSuccess=false; + { + _doseIterator = aDoseIterator; + initSuccess = false; this->init(); - } + } DoseStatistics::DoseIteratorPointer DoseStatistics::getDoseIterator() const - { + { return _doseIterator; - } + } - bool DoseStatistics::init() { + bool DoseStatistics::init() + { - if(!_doseIterator) - { + if (!_doseIterator) + { throw core::NullPointerException("_doseIterator must not be NULL!"); - } + } doseVector.clear(); voxelProportionVector.clear(); - std::multimap doseValueVSIndexMap; + std::multimap doseValueVSIndexMap; std::vector voxelProportionVectorTemp; - this->_maximum=0; - this->_mean=0; - this->_stdDeviation=0; - this->_variance=0; + this->_maximum = 0; + this->_mean = 0; + this->_stdDeviation = 0; + this->_variance = 0; - float sum=0; - _numVoxels=0; - float squareSum=0; + float sum = 0; + _numVoxels = 0; + float squareSum = 0; _doseIterator->reset(); - int i=0; + int i = 0; DoseTypeGy doseValue = 0; - while(_doseIterator->isPositionValid()) - { + + while (_doseIterator->isPositionValid()) + { doseValue = _doseIterator->getCurrentDoseValue(); - if(i==0) - { - _minimum=doseValue; - } + if (i == 0) + { + _minimum = doseValue; + } - rttb::FractionType voxelProportion=_doseIterator->getCurrentRelevantVolumeFraction(); - sum+=doseValue*voxelProportion; - _numVoxels+=voxelProportion; - squareSum+=doseValue*doseValue*voxelProportion; - if(doseValue>this->_maximum) - { - _maximum=doseValue; - } - else if(doseValue_minimum) - { - _minimum=doseValue; - } + rttb::FractionType voxelProportion = _doseIterator->getCurrentRelevantVolumeFraction(); + sum += doseValue * voxelProportion; + _numVoxels += voxelProportion; + squareSum += doseValue * doseValue * voxelProportion; + + if (doseValue > this->_maximum) + { + _maximum = doseValue; + } + else if (doseValue < this->_minimum) + { + _minimum = doseValue; + } voxelProportionVectorTemp.push_back(voxelProportion); - doseValueVSIndexMap.insert(std::pair(doseValue,i)); + doseValueVSIndexMap.insert(std::pair(doseValue, i)); i++; _doseIterator->next(); - } - if(_numVoxels!=0) - { - _mean=sum/_numVoxels; - _variance=(squareSum/_numVoxels-_mean*_mean); + } + + if (_numVoxels != 0) + { + _mean = sum / _numVoxels; + _variance = (squareSum / _numVoxels - _mean * _mean); + if (_variance < errorConstant) - { + { _stdDeviation = 0; - } + } else - { - _stdDeviation=pow(_variance,0.5); - } + { + _stdDeviation = pow(_variance, 0.5); } + } //sort dose values and corresponding volume fractions in member variables - std::multimap::iterator it; - for(it=doseValueVSIndexMap.begin();it!=doseValueVSIndexMap.end();++it) - { + std::multimap::iterator it; + + for (it = doseValueVSIndexMap.begin(); it != doseValueVSIndexMap.end(); ++it) + { doseVector.push_back((float)(*it).first); voxelProportionVector.push_back(voxelProportionVectorTemp.at((*it).second)); - } + } - initSuccess=true; + initSuccess = true; return true; + } + + double DoseStatistics::getNumberOfVoxels() + { + if (!initSuccess) + { + throw core::InvalidDoseException("DoseStatistics is not initialized: set dose using setDoseIterator()! "); } - double DoseStatistics::getNumberOfVoxels(){ - if(!initSuccess) - { - throw core::InvalidDoseException("DoseStatistics is not initialized: set dose using setDoseIterator()! "); - } return _numVoxels; + } + + DoseStatisticType DoseStatistics::getMaximum(ResultListPointer maxVoxelVector) const + { + if (!initSuccess) + { + throw core::InvalidDoseException("DoseStatistics is not initialized: set dose using setDoseIterator()! "); + } - DoseStatisticType DoseStatistics::getMaximum(ResultListPointer maxVoxelVector) const{ - if(!initSuccess){ - throw core::InvalidDoseException("DoseStatistics is not initialized: set dose using setDoseIterator()! "); - - } - if (maxVoxelVector==NULL){ + if (maxVoxelVector == NULL) + { throw core::NullPointerException("resultsVector must not be NULL! "); - } - if(maxVoxelVector->size()==0){ + } + + if (maxVoxelVector->size() == 0) + { this->_doseIterator->reset(); - DoseTypeGy doseValue=0; - while(_doseIterator->isPositionValid()) - { + DoseTypeGy doseValue = 0; + + while (_doseIterator->isPositionValid()) + { doseValue = _doseIterator->getCurrentDoseValue(); - if(doseValue==_maximum) - { + + if (doseValue == _maximum) + { VoxelGridID currentID = _doseIterator->getCurrentVoxelGridID(); - std::pair voxel (doseValue,currentID); + std::pair voxel(doseValue, currentID); maxVoxelVector->push_back(voxel); - } - _doseIterator->next(); } + + _doseIterator->next(); } - return _maximum; } - DoseStatisticType DoseStatistics::getMinimum(ResultListPointer minVoxelVector, int number) const{ - if(!initSuccess) - { + return _maximum; + } + + DoseStatisticType DoseStatistics::getMinimum(ResultListPointer minVoxelVector, int number) const + { + if (!initSuccess) + { throw core::InvalidDoseException("DoseStatistics is not initialized: set dose using setDoseIterator()! "); - } - if (minVoxelVector==NULL) - { + } + + if (minVoxelVector == NULL) + { throw core::NullPointerException("resultsVector must not be NULL! "); - } + } + /*! @todo: Architecture Annotation: Finding the positions for the minimum only once reduces computation time, but will require sensible use by the programmers. To be save the output vector - minVoxelVector will be always cleared here to garantee that no false values are - presented. This change may be revoced to increase computation speed later on + minVoxelVector will be always cleared here to garantee that no false values are + presented. This change may be revoced to increase computation speed later on (only compute if(minVoxelVector->size()==0)). */ minVoxelVector->clear(); - int count=0; + int count = 0; this->_doseIterator->reset(); DoseTypeGy doseValue = 0; - while(_doseIterator->isPositionValid() && countisPositionValid() && count < number) + { doseValue = _doseIterator->getCurrentDoseValue(); - if(doseValue==_minimum){ + + if (doseValue == _minimum) + { VoxelGridID currentID = _doseIterator->getCurrentVoxelGridID(); - std::pair voxel (doseValue,currentID); + std::pair voxel(doseValue, currentID); minVoxelVector->push_back(voxel); count++; - } - _doseIterator->next(); } - return _minimum; + + _doseIterator->next(); } - DoseStatisticType DoseStatistics::getMean() const{ - if(!initSuccess) - { + return _minimum; + } + + DoseStatisticType DoseStatistics::getMean() const + { + if (!initSuccess) + { throw core::InvalidDoseException("DoseStatistics is not initialized: set dose using setDoseIterator()! "); - } - return _mean; } - DoseStatisticType DoseStatistics::getStdDeviation() const{ - if(!initSuccess) - { + return _mean; + } + + DoseStatisticType DoseStatistics::getStdDeviation() const + { + if (!initSuccess) + { throw core::InvalidDoseException("DoseStatistics is not initialized: set dose using setDoseIterator()! "); - } - return _stdDeviation; } - DoseStatisticType DoseStatistics::getVariance() const{ - if(!initSuccess) - { + return _stdDeviation; + } + + DoseStatisticType DoseStatistics::getVariance() const + { + if (!initSuccess) + { throw core::InvalidDoseException("DoseStatistics is not initialized: set dose using setDoseIterator()! "); - } - return _variance; } - VolumeType DoseStatistics::getVx(DoseTypeGy xDoseAbsolute) const{ - rttb::FractionType count=0; + return _variance; + } + + VolumeType DoseStatistics::getVx(DoseTypeGy xDoseAbsolute) const + { + rttb::FractionType count = 0; _doseIterator->reset(); DoseTypeGy currentDose = 0; - while(_doseIterator->isPositionValid()) - { + + while (_doseIterator->isPositionValid()) + { currentDose = _doseIterator->getCurrentDoseValue(); - if(currentDose>=xDoseAbsolute) - { - count+=_doseIterator->getCurrentRelevantVolumeFraction(); - } - _doseIterator->next(); + + if (currentDose >= xDoseAbsolute) + { + count += _doseIterator->getCurrentRelevantVolumeFraction(); } - return count*this->_doseIterator->getCurrentVoxelVolume(); + + _doseIterator->next(); } - DoseTypeGy DoseStatistics::getDx(DoseTypeGy xVolumeAbsolute) const{ - double noOfVoxel=xVolumeAbsolute/_doseIterator->getCurrentVoxelVolume(); - DoseTypeGy resultDose=0; + return count * this->_doseIterator->getCurrentVoxelVolume(); + } - double countVoxels=0; - int i=doseVector.size()-1; - for(;i>=0;i--){ - countVoxels+=voxelProportionVector.at(i); - if(countVoxels>=noOfVoxel) - { - break; - } - } - if(i>=0) + DoseTypeGy DoseStatistics::getDx(DoseTypeGy xVolumeAbsolute) const + { + double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); + DoseTypeGy resultDose = 0; + + double countVoxels = 0; + int i = doseVector.size() - 1; + + for (; i >= 0; i--) + { + countVoxels += voxelProportionVector.at(i); + + if (countVoxels >= noOfVoxel) { - resultDose=doseVector.at(i); + break; } + } + + if (i >= 0) + { + resultDose = doseVector.at(i); + } else - { - resultDose=_minimum; - } + { + resultDose = _minimum; + } return resultDose; - } + } - DoseTypeGy DoseStatistics::getMOHx(DoseTypeGy xVolumeAbsolute) const{ - double noOfVoxel=xVolumeAbsolute/_doseIterator->getCurrentVoxelVolume(); - double countVoxels=0; - double sum=0; + DoseTypeGy DoseStatistics::getMOHx(DoseTypeGy xVolumeAbsolute) const + { + double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); - if(noOfVoxel==0) - { + + if (noOfVoxel == 0) + { return 0; - } - else{ - for(int i=doseVector.size()-1;i>=0;i--) + } + else + { + double countVoxels = 0; + double sum = 0; + + for (int i = doseVector.size() - 1; i >= 0; i--) + { + double voxelProportion = voxelProportionVector.at(i); + countVoxels += voxelProportion; + sum += doseVector.at(i) * voxelProportion; + + if (countVoxels >= noOfVoxel) { - double voxelProportion=voxelProportionVector.at(i); - countVoxels+=voxelProportion; - sum+=doseVector.at(i)*voxelProportion; - if(countVoxels>=noOfVoxel) - { break; - } } - return (DoseTypeGy)(sum/noOfVoxel); } + + return (DoseTypeGy)(sum / noOfVoxel); } + } - DoseTypeGy DoseStatistics::getMOCx(DoseTypeGy xVolumeAbsolute) const{ - double noOfVoxel=xVolumeAbsolute/_doseIterator->getCurrentVoxelVolume(); - double countVoxels=0; - double sum=0; + DoseTypeGy DoseStatistics::getMOCx(DoseTypeGy xVolumeAbsolute) const + { + double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); - if(noOfVoxel==0) - { + + if (noOfVoxel == 0) + { return 0; - } + } else + { + double countVoxels = 0; + double sum = 0; + std::vector::const_iterator it = doseVector.begin(); + std::vector::const_iterator itD = voxelProportionVector.begin(); + + for (; it != doseVector.end(); ++it, ++itD) { - std::vector::const_iterator it=doseVector.begin(); - std::vector::const_iterator itD=voxelProportionVector.begin(); + double voxelProportion = *itD; + countVoxels += voxelProportion; + sum += (*it) * voxelProportion; - for(;it!=doseVector.end();it++,itD++) + if (countVoxels >= noOfVoxel) { - double voxelProportion=*itD; - countVoxels+=voxelProportion; - sum+=(*it)*voxelProportion; - if(countVoxels>=noOfVoxel) - { break; - } } - return (DoseTypeGy)(sum/noOfVoxel); } + + return (DoseTypeGy)(sum / noOfVoxel); } + } + + DoseTypeGy DoseStatistics::getMaxOHx(DoseTypeGy xVolumeAbsolute) const + { + double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); + DoseTypeGy resultDose = 0; + + double countVoxels = 0; + int i = doseVector.size() - 1; - DoseTypeGy DoseStatistics::getMaxOHx(DoseTypeGy xVolumeAbsolute) const{ - double noOfVoxel=xVolumeAbsolute/_doseIterator->getCurrentVoxelVolume(); - DoseTypeGy resultDose=0; + for (; i >= 0; i--) + { + countVoxels += voxelProportionVector.at(i); - double countVoxels=0; - int i=doseVector.size()-1; - for(;i>=0;i--) + if (countVoxels >= noOfVoxel) { - countVoxels+=voxelProportionVector.at(i); - if(countVoxels>=noOfVoxel) - { break; - } } - if(i-1>=0) - { - resultDose=doseVector.at(i-1); - } - return resultDose; } - DoseTypeGy DoseStatistics::getMinOCx(DoseTypeGy xVolumeAbsolute) const{ - double noOfVoxel=xVolumeAbsolute/_doseIterator->getCurrentVoxelVolume(); - DoseTypeGy resultDose=0; + if (i - 1 >= 0) + { + resultDose = doseVector.at(i - 1); + } + + return resultDose; + } + + DoseTypeGy DoseStatistics::getMinOCx(DoseTypeGy xVolumeAbsolute) const + { + double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); + DoseTypeGy resultDose = 0; + + double countVoxels = 0; + std::vector::const_iterator it = doseVector.begin(); + std::vector::const_iterator itD = voxelProportionVector.begin(); - double countVoxels=0; - std::vector::const_iterator it=doseVector.begin(); - std::vector::const_iterator itD=voxelProportionVector.begin(); - for(;itD!=voxelProportionVector.end();itD++,it++) + for (; itD != voxelProportionVector.end(); ++itD, ++it) + { + countVoxels += *itD; + + if (countVoxels >= noOfVoxel) { - countVoxels+=*itD; - if(countVoxels>=noOfVoxel) - { break; - } } - if(it!=doseVector.end()) + } + + if (it != doseVector.end()) + { + ++it; + + if (it != doseVector.end()) { - it++; - if(it!=doseVector.end()) - { - resultDose=*it; - } - else - { - resultDose=(DoseTypeGy)_maximum; - } + resultDose = *it; } - else + else { - resultDose=(DoseTypeGy)_maximum; + resultDose = (DoseTypeGy)_maximum; } - return resultDose; } + else + { + resultDose = (DoseTypeGy)_maximum; + } + + return resultDose; + } - }//end namespace algorithms - }//end namespace rttb + }//end namespace algorithms +}//end namespace rttb diff --git a/code/core/rttbBaseType.h b/code/core/rttbBaseType.h index 041bd02..3161aee 100644 --- a/code/core/rttbBaseType.h +++ b/code/core/rttbBaseType.h @@ -1,719 +1,720 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #ifndef __BASE_TYPE_NEW_H #define __BASE_TYPE_NEW_H #include #include #include #include #include #include #include #include #include #include namespace rttb { const double errorConstant = 1e-5; typedef unsigned short UnsignedIndex1D; /*! @class UnsignedIndex2D @brief 2D index. @todo Both UnsignedIndex2D and VoxelGridIndex2D required? */ class UnsignedIndex2D: public boost::numeric::ublas::vector - { - public: - UnsignedIndex2D() : boost::numeric::ublas::vector(2) {} + { + public: + UnsignedIndex2D() : boost::numeric::ublas::vector(2) {} UnsignedIndex2D(const UnsignedIndex1D value) : boost::numeric::ublas::vector(2, value) {} const UnsignedIndex1D x() const { return (*this)(0); } const UnsignedIndex1D y() const { return (*this)(1); } - }; + }; /*! @class UnsignedIndex3D @brief 3D index. @todo Both UnsignedIndex3D and VoxelGridIndex3D required? */ class UnsignedIndex3D: public boost::numeric::ublas::vector - { - public: - UnsignedIndex3D() : boost::numeric::ublas::vector(3) {} + { + public: + UnsignedIndex3D() : boost::numeric::ublas::vector(3) {} UnsignedIndex3D(const UnsignedIndex1D value) : boost::numeric::ublas::vector(3, value) {} UnsignedIndex3D(const UnsignedIndex1D xValue, const UnsignedIndex1D yValue, const UnsignedIndex1D zValue) - :boost::numeric::ublas::vector(3, xValue) - { - (*this)(1) = yValue; - (*this)(2) = zValue; - } + : boost::numeric::ublas::vector(3, xValue) + { + (*this)(1) = yValue; + (*this)(2) = zValue; + } const UnsignedIndex1D x() const { return (*this)(0); - } + } const UnsignedIndex1D y() const { return (*this)(1); } const UnsignedIndex1D z() const { return (*this)(2); } friend bool operator==(const UnsignedIndex3D& gi1, const UnsignedIndex3D& gi2) { - if (gi1.size()!=gi2.size()) - { - return false; - } - - for (int i = 0; i < gi1.size(); i++) - { - if (gi1(i)!=gi2(i)) - { - return false; - } - } + if (gi1.size() != gi2.size()) + { + return false; + } - return true; + for (int i = 0; i < gi1.size(); i++) + { + if (gi1(i) != gi2(i)) + { + return false; } + } + + return true; + } friend std::ostream& operator<<(std::ostream& s, const UnsignedIndex3D& aVector) { - s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; - return s; - } - }; + s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; + return s; + } + }; typedef std::list UnsignedIndexList; typedef std::string FileNameString; typedef std::string ContourGeometricTypeString; typedef double WorldCoordinate; /*! @class WorldCoordinate2D @brief 2D coordinate in real world coordinates. */ class WorldCoordinate2D: public boost::numeric::ublas::vector - { - public: - WorldCoordinate2D() : boost::numeric::ublas::vector (2) {} + { + public: + WorldCoordinate2D() : boost::numeric::ublas::vector (2) {} WorldCoordinate2D(const WorldCoordinate value) : boost::numeric::ublas::vector(2, value) {} - WorldCoordinate2D( const WorldCoordinate xValue, const WorldCoordinate yValue) + WorldCoordinate2D(const WorldCoordinate xValue, const WorldCoordinate yValue) : boost::numeric::ublas::vector(2, xValue) { (*this)(1) = yValue; } const WorldCoordinate x() const { return (*this)(0); } const WorldCoordinate y() const { return (*this)(1); } - const std::string toString() const - { - std::stringstream ss; - ss << x() <<' '<< y(); - return ss.str(); - } + const std::string toString() const + { + std::stringstream ss; + ss << x() << ' ' << y(); + return ss.str(); + } friend bool operator==(const WorldCoordinate2D& wc1, const WorldCoordinate2D& wc2) { - if (wc1.size()!=wc2.size()) - { - return false; - } + if (wc1.size() != wc2.size()) + { + return false; + } - for (int i = 0; i < wc1.size(); i++) - { + for (int i = 0; i < wc1.size(); i++) + { if (wc1(i) != wc2(i)) { - return false; - } - } - - return true; + return false; } - }; + } + + return true; + } + }; /*! @class WorldCoordinate3D @brief 3D coordinate in real world coordinates. */ class WorldCoordinate3D: public boost::numeric::ublas::vector - { - public: - WorldCoordinate3D() : boost::numeric::ublas::vector(3) {} + { + public: + WorldCoordinate3D() : boost::numeric::ublas::vector(3) {} WorldCoordinate3D(const WorldCoordinate value) : boost::numeric::ublas::vector(3, value) {} WorldCoordinate3D(const WorldCoordinate xValue, const WorldCoordinate yValue, const WorldCoordinate zValue) - :boost::numeric::ublas::vector(3, xValue) - { - (*this)(1) = yValue; - (*this)(2) = zValue; - } + : boost::numeric::ublas::vector(3, xValue) + { + (*this)(1) = yValue; + (*this)(2) = zValue; + } WorldCoordinate3D(const WorldCoordinate3D& w): boost::numeric::ublas::vector(3) { - (*this)(0) = w.x(); - (*this)(1) = w.y(); - (*this)(2) = w.z(); - } + (*this)(0) = w.x(); + (*this)(1) = w.y(); + (*this)(2) = w.z(); + } const WorldCoordinate x() const { return (*this)(0); } const WorldCoordinate y() const { return (*this)(1); } const WorldCoordinate z() const { return (*this)(2); } - //vector cross product (not included in boost.ublas) + //vector cross product (not included in boost.ublas) WorldCoordinate3D cross(WorldCoordinate3D aVector) const { - WorldCoordinate3D result; - WorldCoordinate x = (*this)(0); - WorldCoordinate y = (*this)(1); - WorldCoordinate z = (*this)(2); + WorldCoordinate3D result; + WorldCoordinate x = (*this)(0); + WorldCoordinate y = (*this)(1); + WorldCoordinate z = (*this)(2); - result(0) = y*aVector(2)-z*aVector(1); - result(1) = z*aVector(0)-x*aVector(2); - result(2) = x*aVector(1)-y*aVector(0); + result(0) = y * aVector(2) - z * aVector(1); + result(1) = z * aVector(0) - x * aVector(2); + result(2) = x * aVector(1) - y * aVector(0); - return result; - } + return result; + } WorldCoordinate2D getXY() const { - WorldCoordinate2D result; + WorldCoordinate2D result; - result(0) = (*this)(0); - result(1) = (*this)(1); + result(0) = (*this)(0); + result(1) = (*this)(1); - return result; - } + return result; + } - const std::string toString() const - { - std::stringstream ss; - ss << x() <<' '<< y() <<' '<< z(); - return ss.str(); - } + const std::string toString() const + { + std::stringstream ss; + ss << x() << ' ' << y() << ' ' << z(); + return ss.str(); + } WorldCoordinate3D& operator=(const WorldCoordinate3D& wc) { - (*this)(0) = wc.x(); - (*this)(1) = wc.y(); - (*this)(2) = wc.z(); - return (*this); - } + (*this)(0) = wc.x(); + (*this)(1) = wc.y(); + (*this)(2) = wc.z(); + return (*this); + } WorldCoordinate3D& operator=(const boost::numeric::ublas::vector wc) { - (*this)(0) = wc(0); - (*this)(1) = wc(1); - (*this)(2) = wc(2); - return (*this); - } + (*this)(0) = wc(0); + (*this)(1) = wc(1); + (*this)(2) = wc(2); + return (*this); + } WorldCoordinate3D operator-(const boost::numeric::ublas::vector wc) { - return WorldCoordinate3D ((*this)(0) - wc(0),(*this)(1) - wc(1),(*this)(2) - wc(2)); - } + return WorldCoordinate3D((*this)(0) - wc(0), (*this)(1) - wc(1), (*this)(2) - wc(2)); + } WorldCoordinate3D operator+(const boost::numeric::ublas::vector wc) { - return WorldCoordinate3D ((*this)(0) + wc(0),(*this)(1) + wc(1),(*this)(2) + wc(2)); - } + return WorldCoordinate3D((*this)(0) + wc(0), (*this)(1) + wc(1), (*this)(2) + wc(2)); + } friend bool operator==(const WorldCoordinate3D& wc1, const WorldCoordinate3D& wc2) { - if (wc1.size()!=wc2.size()) - { - return false; - } - - for (int i = 0; i < wc1.size(); i++) - { - if (wc1(i)!=wc2(i)) - { - return false; - } - } + if (wc1.size() != wc2.size()) + { + return false; + } - return true; + for (int i = 0; i < wc1.size(); i++) + { + if (wc1(i) != wc2(i)) + { + return false; } + } + + return true; + } friend std::ostream& operator<<(std::ostream& s, const WorldCoordinate3D& aVector) { - s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; - return s; - } + s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; + return s; + } - }; + }; typedef UnsignedIndex3D ImageSize; /*! @deprecated Use OrientationMatrix instead. */ typedef WorldCoordinate3D ImageOrientation; typedef double GridVolumeType; - + /*! @class SpacingVectorType3D @brief 3D spacing vector. @pre values of this vector may not be negative. @todo should SpacingVectorType/GridVolumeType be forced to be non-negative? If yes add corresponding tests */ class SpacingVectorType3D: public boost::numeric::ublas::vector - { - public: - SpacingVectorType3D() : boost::numeric::ublas::vector(3) {} + { + public: + SpacingVectorType3D() : boost::numeric::ublas::vector(3) {} SpacingVectorType3D(const GridVolumeType value) : boost::numeric::ublas::vector(3, value) {} SpacingVectorType3D(const GridVolumeType xValue, const GridVolumeType yValue, const GridVolumeType zValue) : boost::numeric::ublas::vector(3, xValue) { - (*this)(1) = yValue; - (*this)(2) = zValue; - } + (*this)(1) = yValue; + (*this)(2) = zValue; + } SpacingVectorType3D(const SpacingVectorType3D& w): boost::numeric::ublas::vector(3) { - (*this)(0) = w.x(); - (*this)(1) = w.y(); - (*this)(2) = w.z(); - } + (*this)(0) = w.x(); + (*this)(1) = w.y(); + (*this)(2) = w.z(); + } const GridVolumeType x() const { return (*this)(0); } const GridVolumeType y() const { return (*this)(1); } const GridVolumeType z() const { return (*this)(2); } - const std::string toString() const - { - std::stringstream ss; - ss << x() <<' '<< y() <<' '<< z(); - return ss.str(); - } + const std::string toString() const + { + std::stringstream ss; + ss << x() << ' ' << y() << ' ' << z(); + return ss.str(); + } SpacingVectorType3D& operator=(const SpacingVectorType3D& wc) { - (*this)(0) = wc.x(); - (*this)(1) = wc.y(); - (*this)(2) = wc.z(); - return (*this); - } + (*this)(0) = wc.x(); + (*this)(1) = wc.y(); + (*this)(2) = wc.z(); + return (*this); + } SpacingVectorType3D& operator=(const WorldCoordinate3D& wc) { - (*this)(0) = GridVolumeType(wc.x()); - (*this)(1) = GridVolumeType(wc.y()); - (*this)(2) = GridVolumeType(wc.z()); - return (*this); - } + (*this)(0) = GridVolumeType(wc.x()); + (*this)(1) = GridVolumeType(wc.y()); + (*this)(2) = GridVolumeType(wc.z()); + return (*this); + } SpacingVectorType3D& operator=(const boost::numeric::ublas::vector wc) { - (*this)(0) = wc(0); - (*this)(1) = wc(1); - (*this)(2) = wc(2); - return (*this); - } + (*this)(0) = wc(0); + (*this)(1) = wc(1); + (*this)(2) = wc(2); + return (*this); + } friend bool operator==(const SpacingVectorType3D& wc1, const SpacingVectorType3D& wc2) { - if (wc1.size()!=wc2.size()) - { - return false; - } - - for (int i = 0; i < wc1.size(); i++) - { - if (wc1(i)!=wc2(i)) - { - return false; - } - } + if (wc1.size() != wc2.size()) + { + return false; + } - return true; + for (int i = 0; i < wc1.size(); i++) + { + if (wc1(i) != wc2(i)) + { + return false; } + } + + return true; + } friend std::ostream& operator<<(std::ostream& s, const SpacingVectorType3D& aVector) { - s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; - return s; - } - }; + s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; + return s; + } + }; /*! @class OrientationMatrix @brief Used to store image orientation information @todo should OrientationMatrix be forced to be non-negative? If yes add corresponding tests */ class OrientationMatrix : public boost::numeric::ublas::matrix - { - public: - /*! The default constructor generates a 3x3 unit matrix - */ + { + public: + /*! The default constructor generates a 3x3 unit matrix + */ OrientationMatrix() : boost::numeric::ublas::matrix(3, 3, 0) { for (std::size_t m = 0; m < (*this).size1(); m++) { - (*this)(m,m) = 1; - } - } + (*this)(m, m) = 1; + } + } OrientationMatrix(const WorldCoordinate value) : boost::numeric::ublas::matrix(3, 3, value) {} bool equal(const OrientationMatrix& anOrientationMatrix) const { - if (anOrientationMatrix.size1()==(*this).size1()) + if (anOrientationMatrix.size1() == (*this).size1()) + { + if (anOrientationMatrix.size2() == (*this).size2()) + { + for (std::size_t m = 0; m < anOrientationMatrix.size1(); m++) { - if (anOrientationMatrix.size2()==(*this).size2()) + for (std::size_t n = 0; n < anOrientationMatrix.size2(); n++) { - for (std::size_t m = 0; m < anOrientationMatrix.size1(); m++) + if (!((*this)(m, n) == anOrientationMatrix(m, n))) { - for (std::size_t n = 0; n < anOrientationMatrix.size2(); n++) - { - if (!((*this)(m,n) == anOrientationMatrix(m,n))) - { - return false; - } - } - }// end element comparison - } - else - { - return false; + return false; + } } - } - else - { + }// end element comparison + } + else + { return false; - } - - return true; } + } + else + { + return false; + } + + return true; + } friend bool operator==(const OrientationMatrix& om1, const OrientationMatrix& om2) { return om1.equal(om2); } friend std::ostream& operator<<(std::ostream& s, const OrientationMatrix& anOrientationMatrix) { + s << "[ "; + + for (std::size_t m = 0; m < anOrientationMatrix.size1(); m++) + { s << "[ "; - for (std::size_t m = 0; m < anOrientationMatrix.size1(); m++) + for (std::size_t n = 0; n < anOrientationMatrix.size2(); n++) + { + if (n == 0) { - s << "[ "; - - for (std::size_t n = 0; n < anOrientationMatrix.size2(); n++) - { - if (n==0) - { - s << anOrientationMatrix(m,n); - } - else - { - s << ", " << anOrientationMatrix(m,n); - } - } - - s << " ]"; + s << anOrientationMatrix(m, n); } + else + { + s << ", " << anOrientationMatrix(m, n); + } + } s << " ]"; - return s; - } - }; + } + + s << " ]"; + return s; + } + }; - /*! base for 2D and 3D VoxelIndex; Therefore required beside VoxelGridID + /*! base for 2D and 3D VoxelIndex; Therefore required beside VoxelGridID */ - typedef unsigned int GridIndexType; + typedef unsigned int GridIndexType; /*! @class VoxelGridIndex3D @brief 3D voxel grid index. */ class VoxelGridIndex3D: public boost::numeric::ublas::vector - { - public: - VoxelGridIndex3D() : boost::numeric::ublas::vector(3) {} + { + public: + VoxelGridIndex3D() : boost::numeric::ublas::vector(3) {} VoxelGridIndex3D(const GridIndexType value) : boost::numeric::ublas::vector(3, value) {} - VoxelGridIndex3D( const GridIndexType xValue, const GridIndexType yValue, const GridIndexType zValue) + VoxelGridIndex3D(const GridIndexType xValue, const GridIndexType yValue, const GridIndexType zValue) : boost::numeric::ublas::vector(3, xValue) { - (*this)(1) = yValue; - (*this)(2) = zValue; - } + (*this)(1) = yValue; + (*this)(2) = zValue; + } const GridIndexType x() const { return (*this)(0); } const GridIndexType y() const { return (*this)(1); } const GridIndexType z() const { return (*this)(2); } const std::string toString() const { - std::stringstream ss; - ss << x() <<' '<< y() <<' '<< z(); - return ss.str(); - } + std::stringstream ss; + ss << x() << ' ' << y() << ' ' << z(); + return ss.str(); + } - VoxelGridIndex3D& operator=(const UnsignedIndex3D ui) + VoxelGridIndex3D& operator=(const UnsignedIndex3D& ui) { - (*this)(0) = ui(0); - (*this)(1) = ui(1); - (*this)(2) = ui(2); - return (*this); - } + (*this)(0) = ui(0); + (*this)(1) = ui(1); + (*this)(2) = ui(2); + return (*this); + } friend bool operator==(const VoxelGridIndex3D& gi1, const VoxelGridIndex3D& gi2) { - if (gi1.size()!=gi2.size()) - { - return false; - } + if (gi1.size() != gi2.size()) + { + return false; + } - for (int i = 0; i < gi1.size(); i++) - { + for (int i = 0; i < gi1.size(); i++) + { if (gi1(i) != gi2(i)) { - return false; - } - } - - return true; + return false; } + } + + return true; + } friend std::ostream& operator<<(std::ostream& s, const VoxelGridIndex3D& aVector) { - s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; - return s; - } - }; + s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; + return s; + } + }; /*! @class VoxelGridIndex3D @brief 2D voxel grid index. */ class VoxelGridIndex2D: public boost::numeric::ublas::vector - { - public: - VoxelGridIndex2D() : boost::numeric::ublas::vector(2) {} + { + public: + VoxelGridIndex2D() : boost::numeric::ublas::vector(2) {} VoxelGridIndex2D(const GridIndexType value) : boost::numeric::ublas::vector(2, value) {} - VoxelGridIndex2D( const GridIndexType xValue, const GridIndexType yValue) + VoxelGridIndex2D(const GridIndexType xValue, const GridIndexType yValue) : boost::numeric::ublas::vector(2, xValue) { (*this)(1) = yValue; } const GridIndexType x() const { return (*this)(0); } const GridIndexType y() const { return (*this)(1); } - const std::string toString() const - { - std::stringstream ss; - ss << x() <<' '<< y(); - return ss.str(); - } + const std::string toString() const + { + std::stringstream ss; + ss << x() << ' ' << y(); + return ss.str(); + } friend bool operator==(const VoxelGridIndex2D& gi1, const VoxelGridIndex2D& gi2) { - if (gi1.size()!=gi2.size()) - { - return false; - } - - for (int i = 0; i < gi1.size(); i++) - { - if (gi1(i)!=gi2(i)) - { - return false; - } - } + if (gi1.size() != gi2.size()) + { + return false; + } - return true; + for (int i = 0; i < gi1.size(); i++) + { + if (gi1(i) != gi2(i)) + { + return false; } + } + + return true; + } friend std::ostream& operator<<(std::ostream& s, const VoxelGridIndex2D& aVector) { - s << "[ " << aVector(0) << ", " << aVector(1) << " ]"; - return s; - } - }; + s << "[ " << aVector(0) << ", " << aVector(1) << " ]"; + return s; + } + }; typedef long GridSizeType; typedef int VoxelGridID; //starts from 0 and is continuously counting all positions on the grid - typedef int VoxelGridDimensionType; + typedef int VoxelGridDimensionType; - typedef boost::numeric::ublas::vector VoxelGridDimensionVectorType; + typedef boost::numeric::ublas::vector VoxelGridDimensionVectorType; typedef double FractionType, VoxelSizeType, DVHVoxelNumber; - typedef double DoseCalcType, DoseTypeGy, DoseVoxelVolumeType, VolumeType, GridVolumeType, VoxelNumberType, BEDType, LQEDType; + typedef double DoseCalcType, DoseTypeGy, DoseVoxelVolumeType, VolumeType, GridVolumeType, VoxelNumberType, BEDType, + LQEDType; typedef std::string IDType; typedef std::string StructureLabel; struct DVHRole { enum Type { TargetVolume = 1, HealthyTissue = 2, WholeVolume = 4, UserDefined = 128 } Type; }; struct DVHType - { - enum Type - { - Differential = 1, - Cumulative = 2 - } Type; - }; + { + enum Type + { + Differential = 1, + Cumulative = 2 + } Type; + }; typedef std::string PatientInfoString; typedef std::string TimeString; typedef std::string FileNameType; - typedef std::vector PolygonType; + typedef std::vector PolygonType; typedef std::vector PolygonSequenceType; typedef double IndexValueType; typedef double DoseStatisticType; typedef std::string DBStringType; typedef std::string VirtuosFileNameString, DICOMRTFileNameString; typedef unsigned short Uint16; struct Area2D { WorldCoordinate x_begin; WorldCoordinate x_end; WorldCoordinate y_begin; WorldCoordinate y_end; VoxelGridIndex2D index_begin; - VoxelGridIndex2D index_end; + VoxelGridIndex2D index_end; void Init() { x_begin = -1000000; x_end = -1000000; y_begin = -1000000; - y_end = -1000000; + y_end = -1000000; index_begin(0) = 0; - index_begin(1) = 0; - index_end(0) = 0; - index_end(1) = 0; - } - }; + index_begin(1) = 0; + index_end(0) = 0; + index_end(1) = 0; + } + }; struct Segment2D { WorldCoordinate2D begin; WorldCoordinate2D end; - }; + }; struct Segment3D { WorldCoordinate3D begin; WorldCoordinate3D end; - }; + }; typedef int DistributionType; typedef std::string PathType; typedef std::string XMLString, StatisticsString; - }//end: namespace rttb +}//end: namespace rttb #endif diff --git a/code/core/rttbDVH.cpp b/code/core/rttbDVH.cpp index f43adb8..79379c2 100644 --- a/code/core/rttbDVH.cpp +++ b/code/core/rttbDVH.cpp @@ -1,371 +1,414 @@ // ----------------------------------------------------------------------- // 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 "rttbDVH.h" #include "rttbException.h" #include "rttbInvalidParameterException.h" -namespace rttb{ - namespace core{ +namespace rttb +{ + namespace core + { - DVH::~DVH(){} + DVH::~DVH() {} - DVH::DVH(const DataDifferentialType& aDataDifferential, const DoseTypeGy& aDeltaD, const DoseVoxelVolumeType& aDeltaV, - IDType aStructureID, IDType aDoseID): _deltaD(aDeltaD), _deltaV(aDeltaV), _structureID(aStructureID), + DVH::DVH(const DataDifferentialType& aDataDifferential, const DoseTypeGy& aDeltaD, const DoseVoxelVolumeType& aDeltaV, + IDType aStructureID, IDType aDoseID): _deltaD(aDeltaD), _deltaV(aDeltaV), _structureID(aStructureID), _doseID(aDoseID), _voxelizationID("NONE") - { + { _dataDifferential.clear(); _dataDifferential = aDataDifferential; this->init(); - } + } - DVH::DVH(const DataDifferentialType& aDataDifferential, DoseTypeGy aDeltaD, DoseVoxelVolumeType aDeltaV, - IDType aStructureID, IDType aDoseID, IDType aVoxelizationID): _deltaD(aDeltaD), _deltaV(aDeltaV), + DVH::DVH(const DataDifferentialType& aDataDifferential, DoseTypeGy aDeltaD, DoseVoxelVolumeType aDeltaV, + IDType aStructureID, IDType aDoseID, IDType aVoxelizationID): _deltaD(aDeltaD), _deltaV(aDeltaV), _structureID(aStructureID), _doseID(aDoseID), _voxelizationID(aVoxelizationID) - { + { _dataDifferential.clear(); _dataDifferential = aDataDifferential; this->init(); - } + } - DVH::DVH(const DVH ©){ - _deltaD=copy._deltaD; - _deltaV=copy._deltaV; - _structureID=copy._structureID; - _doseID=copy._doseID; - _voxelizationID=copy._voxelizationID; - _label=copy._label; + DVH::DVH(const DVH& copy) : _structureID(copy._structureID), _doseID(copy._doseID), + _voxelizationID(copy._voxelizationID), _label(copy._label) + { + _deltaD = copy._deltaD; + _deltaV = copy._deltaV; _dataDifferential.clear(); _dataDifferential = copy._dataDifferential; this->init(); - } + } - DVH &DVH::operator=(const DVH ©) - { + DVH& DVH::operator=(const DVH& copy) + { if (this != ©) - { - _deltaD=copy._deltaD; - _deltaV=copy._deltaV; - _structureID=copy._structureID; - _doseID=copy._doseID; - _voxelizationID=copy._voxelizationID; - _label=copy._label; + { + _deltaD = copy._deltaD; + _deltaV = copy._deltaV; + _structureID = copy._structureID; + _doseID = copy._doseID; + _voxelizationID = copy._voxelizationID; + _label = copy._label; _dataDifferential.clear(); _dataDifferential = copy._dataDifferential; - } + } + this->init(); return *this; - } + } - bool operator==(const DVH &aDVH, const DVH &otherDVH){ + bool operator==(const DVH& aDVH, const DVH& otherDVH) + { if (aDVH.getStructureID() != otherDVH.getStructureID()) - { + { return false; - } + } + if (aDVH.getDoseID() != otherDVH.getDoseID()) - { + { return false; - } + } + if (aDVH.getVoxelizationID() != otherDVH.getVoxelizationID()) - { + { return false; - } + } + if (aDVH.getNumberOfVoxels() != otherDVH.getNumberOfVoxels()) - { + { return false; - } - return true; } - std::ostream& operator<<(std::ostream& s, const DVH &aDVH){ - s << "[ " << aDVH.getStructureID() << ", " << aDVH.getDoseID() << ", " << aDVH.getVoxelizationID() << ", " < DVH::getDataDifferential(bool relativeVolume) const + { + if (!relativeVolume) { - if(!relativeVolume) - { - return _dataDifferential; - } + return _dataDifferential; + } else - { + { return _dataDifferentialRelative; - } } + } - DoseVoxelVolumeType DVH::getDeltaV() const{ + DoseVoxelVolumeType DVH::getDeltaV() const + { return _deltaV; - } + } - DoseTypeGy DVH::getDeltaD() const{ + DoseTypeGy DVH::getDeltaD() const + { return _deltaD; - } + } - IDType DVH::getDoseID() const{ + IDType DVH::getDoseID() const + { return this->_doseID; - } + } - IDType DVH::getStructureID() const{ + IDType DVH::getStructureID() const + { return this->_structureID; - } + } - IDType DVH::getVoxelizationID() const{ + IDType DVH::getVoxelizationID() const + { return this->_voxelizationID; - } + } - void DVH::setDoseID(IDType aDoseID){_doseID=aDoseID;} + void DVH::setDoseID(IDType aDoseID) + { + _doseID = aDoseID; + } - void DVH::setStructureID(IDType aStrID){_structureID=aStrID;} + void DVH::setStructureID(IDType aStrID) + { + _structureID = aStrID; + } - DoseStatisticType DVH::getMaximum() const{ + DoseStatisticType DVH::getMaximum() const + { return _maximum; - } + } - DoseStatisticType DVH::getMinimum() const{ + DoseStatisticType DVH::getMinimum() const + { return _minimum; - } + } - DoseStatisticType DVH::getMean() const{ + DoseStatisticType DVH::getMean() const + { return _mean; - } + } - DVHVoxelNumber DVH::getNumberOfVoxels() const{ + DVHVoxelNumber DVH::getNumberOfVoxels() const + { return _numberOfVoxels; - } + } - DoseStatisticType DVH::getStdDeviation() const{ + DoseStatisticType DVH::getStdDeviation() const + { return _stdDeviation; - } + } - DoseStatisticType DVH::getVariance() const{ + DoseStatisticType DVH::getVariance() const + { return _variance; - } + } - void DVH::init() { - if(_deltaD==0 || _deltaV==0) - { + void DVH::init() + { + if (_deltaD == 0 || _deltaV == 0) + { throw InvalidParameterException("DVH init error: neither _deltaD nor _deltaV must be zero!"); - } - if(this->_dataDifferential.empty()) - { + } + + if (this->_dataDifferential.empty()) + { throw InvalidParameterException("DVH init error: data differential is empty!"); - } + } - double sum=0; - double squareSum=0; - _numberOfVoxels=0; - _maximum=0; - _minimum=0; + double sum = 0; + double squareSum = 0; + _numberOfVoxels = 0; + _maximum = 0; + _minimum = 0; _dataCumulative.clear(); this->_dataCumulativeRelative.clear(); this->_dataDifferentialRelative.clear(); DataDifferentialType::iterator it; - int i=0; - for(it=_dataDifferential.begin();it!=_dataDifferential.end(); it++) - { - _numberOfVoxels+=(*it); + int i = 0; - if((*it)>0) - { - _maximum=(i+0.5)*this->_deltaD; - } + for (it = _dataDifferential.begin(); it != _dataDifferential.end(); ++it) + { + _numberOfVoxels += (*it); - if((_minimum==0.0f) && ((*it)>0)) - { - _minimum=(i+0.5)*this->_deltaD; - } + if ((*it) > 0) + { + _maximum = (i + 0.5) * this->_deltaD; + } - sum+=(*it)*(i+0.5)*this->_deltaD; + if ((_minimum == 0.0f) && ((*it) > 0)) + { + _minimum = (i + 0.5) * this->_deltaD; + } - squareSum+=(*it)*pow((i+0.5)*this->_deltaD,2); + sum += (*it) * (i + 0.5) * this->_deltaD; + + squareSum += (*it) * pow((i + 0.5) * this->_deltaD, 2); i++; - } + } - _mean=sum/_numberOfVoxels; + _mean = sum / _numberOfVoxels; - for(it=_dataDifferential.begin();it!=_dataDifferential.end(); it++) - { - DoseCalcType datai=((*it)*1.0/_numberOfVoxels); + for (it = _dataDifferential.begin(); it != _dataDifferential.end(); ++it) + { + DoseCalcType datai = ((*it) * 1.0 / _numberOfVoxels); _dataDifferentialRelative.push_back(datai); - } + } - _variance=(squareSum/_numberOfVoxels-_mean*_mean); - _stdDeviation=pow(_variance,0.5); + _variance = (squareSum / _numberOfVoxels - _mean * _mean); + _stdDeviation = pow(_variance, 0.5); - _dataCumulative=this->calcCumulativeDVH(); - } + _dataCumulative = this->calcCumulativeDVH(); + } std::deque DVH::calcCumulativeDVH(bool relativeVolume) - { + { _dataCumulative.clear(); _dataCumulativeRelative.clear(); DoseCalcType cumulativeDVHi = 0; - DataDifferentialType::iterator it; - size_t size=_dataDifferential.size(); - for(int i=0;igetNumberOfVoxels()); - } } - if(!relativeVolume) + else { - return _dataCumulative; + _dataCumulativeRelative.push_front(cumulativeDVHi / this->getNumberOfVoxels()); } + } + + if (!relativeVolume) + { + return _dataCumulative; + } else - { + { return _dataCumulativeRelative; - } } + } - DoseStatisticType DVH::getMedian() const{ + DoseStatisticType DVH::getMedian() const + { - double median_voxel=0; - int median_i=0; + double median_voxel = 0; + int median_i = 0; - for(GridIndexType i=0;i_dataDifferential.size();i++) + for (GridIndexType i = 0; i < this->_dataDifferential.size(); i++) + { + if (median_voxel < (_numberOfVoxels - median_voxel)) { - if(median_voxel<(_numberOfVoxels-median_voxel)) - { - median_voxel+=_dataDifferential[i]; - median_i=i; - } + median_voxel += _dataDifferential[i]; + median_i = i; } - double median=(median_i+0.5)*this->_deltaD; - return median; } - DoseStatisticType DVH::getModal() const{ + double median = (median_i + 0.5) * this->_deltaD; + return median; + } + + DoseStatisticType DVH::getModal() const + { - double modal_voxel=0; - int modal_i=0; + double modal_voxel = 0; + int modal_i = 0; - for(GridIndexType i=0;i_dataDifferential.size();i++) + for (GridIndexType i = 0; i < this->_dataDifferential.size(); i++) + { + if (modal_voxel < _dataDifferential[i]) { - if(modal_voxel<_dataDifferential[i]) - { - modal_voxel=_dataDifferential[i]; - modal_i=i; - } + modal_voxel = _dataDifferential[i]; + modal_i = i; } - double modal=(modal_i+0.5)*this->_deltaD; - return modal; } - VolumeType DVH::getVx(DoseTypeGy xDoseAbsolute){ + double modal = (modal_i + 0.5) * this->_deltaD; + return modal; + } - GridIndexType i=static_cast(xDoseAbsolute/_deltaD); + VolumeType DVH::getVx(DoseTypeGy xDoseAbsolute) + { - if(i<_dataCumulative.size()) - { - VolumeType vx=(_dataCumulative.at(i)); - vx = (vx*this->_deltaV); + GridIndexType i = static_cast(xDoseAbsolute / _deltaD); + + if (i < _dataCumulative.size()) + { + VolumeType vx = (_dataCumulative.at(i)); + vx = (vx * this->_deltaV); return vx; - } - else if(i<_dataCumulativeRelative.size()) - { - VolumeType vx=(_dataCumulativeRelative.at(i)); - vx = (vx*this->_deltaV); + } + else if (i < _dataCumulativeRelative.size()) + { + VolumeType vx = (_dataCumulativeRelative.at(i)); + vx = (vx * this->_deltaV); return vx; - } + } else - { + { return 0; - } } + } + + DoseTypeGy DVH::getDx(VolumeType xVolumeAbsolute) + { - DoseTypeGy DVH::getDx(VolumeType xVolumeAbsolute){ + GridIndexType i = 0; - GridIndexType i=0; if (!_dataCumulative.empty()) + { + for (; i < _dataCumulative.size(); i++) { - for(; i<_dataCumulative.size();i++) + double volumeAbsoluteI = _dataCumulative[i] * this->_deltaV; + + if (xVolumeAbsolute > volumeAbsoluteI) { - double volumeAbsoluteI=_dataCumulative[i]*this->_deltaV; - if(xVolumeAbsolute>volumeAbsoluteI) - { break; - } } } - else + } + else + { + for (; i < _dataCumulativeRelative.size(); i++) { - for(; i<_dataCumulativeRelative.size();i++) + double volumeAbsoluteI = _dataCumulativeRelative[i] * this->_deltaV; + + if (xVolumeAbsolute / this->getNumberOfVoxels() > volumeAbsoluteI) { - double volumeAbsoluteI=_dataCumulativeRelative[i]*this->_deltaV; - if(xVolumeAbsolute/this->getNumberOfVoxels()>volumeAbsoluteI) - { break; - } } } - if(i<=_dataCumulative.size() && i>0) - { - DoseTypeGy dx=(i-1)*this->_deltaD; + } + + if (i <= _dataCumulative.size() && i > 0) + { + DoseTypeGy dx = (i - 1) * this->_deltaD; return dx; - } - else if(i<_dataCumulativeRelative.size()&& i>0) - { - DoseTypeGy dx=(i-1)*this->_deltaD; + } + else if (i < _dataCumulativeRelative.size() && i > 0) + { + DoseTypeGy dx = (i - 1) * this->_deltaD; return dx; - } + } else - { + { return 0; - } } + } - VolumeType DVH::getAbsoluteVolume(int relativePercent){ - return (relativePercent*getNumberOfVoxels()*getDeltaV()/100.0); - } + VolumeType DVH::getAbsoluteVolume(int relativePercent) + { + return (relativePercent * getNumberOfVoxels() * getDeltaV() / 100.0); + } - void DVH::setLabel(StructureLabel aLabel){ - _label=aLabel; - } + void DVH::setLabel(StructureLabel aLabel) + { + _label = aLabel; + } - StructureLabel DVH::getLabel() const{ + StructureLabel DVH::getLabel() const + { return _label; - } + } - }//end namespace core + }//end namespace core }//end namespace rttb diff --git a/code/core/rttbDVHCalculator.cpp b/code/core/rttbDVHCalculator.cpp index 17e60ec..660b391 100644 --- a/code/core/rttbDVHCalculator.cpp +++ b/code/core/rttbDVHCalculator.cpp @@ -1,114 +1,130 @@ // ----------------------------------------------------------------------- // 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 "rttbDVHCalculator.h" #include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" #include "rttbMaskedDoseIteratorInterface.h" -namespace rttb{ - namespace core{ +namespace rttb +{ + namespace core + { + + DVHCalculator::DVHCalculator(DoseIteratorPointer aDoseIterator, const IDType& aStructureID, const IDType& aDoseID, + DoseTypeGy aDeltaD, const int aNumberOfBins) + { + if (!aDoseIterator) + { + throw NullPointerException("aDoseIterator must not be NULL! "); + } - DVHCalculator::DVHCalculator(DoseIteratorPointer aDoseIterator,const IDType aStructureID,const IDType aDoseID, - DoseTypeGy aDeltaD, const int aNumberOfBins){ - if(!aDoseIterator) - { - throw NullPointerException("aDoseIterator must not be NULL! "); - } - _doseIteratorPtr=aDoseIterator; - _structureID=aStructureID; - _doseID=aDoseID; + _doseIteratorPtr = aDoseIterator; + _structureID = aStructureID; + _doseID = aDoseID; - if(aNumberOfBins<=0 || aDeltaD<0 ) - { - throw InvalidParameterException("aNumberOfBins/aDeltaD must be >0! "); - } + if (aNumberOfBins <= 0 || aDeltaD < 0) + { + throw InvalidParameterException("aNumberOfBins/aDeltaD must be >0! "); + } + + _numberOfBins = aNumberOfBins; + _deltaD = aDeltaD; - _numberOfBins=aNumberOfBins; - _deltaD=aDeltaD; + if (_deltaD == 0) + { + aDoseIterator->reset(); + DoseTypeGy max = 0; - if(_deltaD==0) + while (aDoseIterator->isPositionValid()) { - aDoseIterator->reset(); - DoseTypeGy max=0; DoseTypeGy currentVal = 0; - while(aDoseIterator->isPositionValid()) - { - currentVal = aDoseIterator->getCurrentDoseValue(); - if(currentVal>max) - { - max=currentVal; - } - aDoseIterator->next(); - } - _deltaD=(max*1.5/_numberOfBins); + currentVal = aDoseIterator->getCurrentDoseValue(); - if(_deltaD==0) + if (currentVal > max) { - _deltaD=0.1; + max = currentVal; } + + aDoseIterator->next(); + } + + _deltaD = (max * 1.5 / _numberOfBins); + + if (_deltaD == 0) + { + _deltaD = 0.1; } + } } - DVHCalculator::~DVHCalculator(){} + DVHCalculator::~DVHCalculator() {} - DVHCalculator::DVHPointer DVHCalculator::generateDVH(){ + DVHCalculator::DVHPointer DVHCalculator::generateDVH() + { - std::deque dataDifferential(_numberOfBins,0); + std::deque dataDifferential(_numberOfBins, 0); // calculate DVH _doseIteratorPtr->reset(); - DoseTypeGy currentVal = 0; - while(_doseIteratorPtr->isPositionValid()) + + while (_doseIteratorPtr->isPositionValid()) { - FractionType voxelProportion=_doseIteratorPtr->getCurrentRelevantVolumeFraction(); + DoseTypeGy currentVal = 0; + FractionType voxelProportion = _doseIteratorPtr->getCurrentRelevantVolumeFraction(); currentVal = _doseIteratorPtr->getCurrentDoseValue(); - int dose_bin = static_cast(currentVal/_deltaD); + int dose_bin = static_cast(currentVal / _deltaD); - if(dose_bin < _numberOfBins) + if (dose_bin < _numberOfBins) { - dataDifferential[dose_bin]+=voxelProportion; + dataDifferential[dose_bin] += voxelProportion; } - else{ + else + { throw InvalidParameterException("_numberOfBins is too small: dose bin out of bounds! "); } + _doseIteratorPtr->next(); } + if (boost::dynamic_pointer_cast(_doseIteratorPtr)) { - _dvh=boost::make_shared(dataDifferential,_deltaD,_doseIteratorPtr->getCurrentVoxelVolume(),_structureID,_doseID, _doseIteratorPtr->getVoxelizationID()); + _dvh = boost::make_shared(dataDifferential, _deltaD, _doseIteratorPtr->getCurrentVoxelVolume(), _structureID, + _doseID, _doseIteratorPtr->getVoxelizationID()); } - else{ - _dvh=boost::make_shared(dataDifferential,_deltaD,_doseIteratorPtr->getCurrentVoxelVolume(),_structureID,_doseID); + else + { + _dvh = boost::make_shared(dataDifferential, _deltaD, _doseIteratorPtr->getCurrentVoxelVolume(), _structureID, + _doseID); } return _dvh; } }//end namespace core }//end namespace rttb diff --git a/code/core/rttbDVHCalculator.h b/code/core/rttbDVHCalculator.h index 55d774a..ebae9d6 100644 --- a/code/core/rttbDVHCalculator.h +++ b/code/core/rttbDVHCalculator.h @@ -1,74 +1,77 @@ // ----------------------------------------------------------------------- // 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 __DVH_CALCULATOR_H #define __DVH_CALCULATOR_H #include #include #include #include "rttbBaseType.h" #include "rttbDoseIteratorInterface.h" #include "rttbMaskedDoseIteratorInterface.h" #include "rttbDVH.h" #include "rttbDVHGeneratorInterface.h" -namespace rttb{ - namespace core{ +namespace rttb +{ + namespace core + { /*! @class DVHCalculator @brief Calculates a DVH for a given DoseIterator. */ class DVHCalculator: public DVHGeneratorInterface - { - public: - typedef core::DoseIteratorInterface::DoseIteratorPointer DoseIteratorPointer; - typedef core::MaskedDoseIteratorInterface::MaskedDoseIteratorPointer MaskedDoseIteratorPointer; + { + public: + typedef core::DoseIteratorInterface::DoseIteratorPointer DoseIteratorPointer; + typedef core::MaskedDoseIteratorInterface::MaskedDoseIteratorPointer MaskedDoseIteratorPointer; - DoseIteratorPointer _doseIteratorPtr; - IDType _structureID; - IDType _doseID; - DoseTypeGy _deltaD; - int _numberOfBins; + DoseIteratorPointer _doseIteratorPtr; + IDType _structureID; + IDType _doseID; + DoseTypeGy _deltaD; + int _numberOfBins; - /*! @brief Constructor. - @param aDeltaD the absolute dose value in Gy for dose_bin [i,i+1). Optional, if aDeltaD==0, - it will be calculated using aDeltaD=max(aDoseIterator)*1.5/aNumberOfBins - @exception InvalidParameterException throw if _numberOfBins<=0 or _deltaD<0 - */ - DVHCalculator(DoseIteratorPointer aDoseIterator, const IDType aStructureID,const IDType aDoseID, const DoseTypeGy aDeltaD=0, const int aNumberOfBins=201); + /*! @brief Constructor. + @param aDeltaD the absolute dose value in Gy for dose_bin [i,i+1). Optional, if aDeltaD==0, + it will be calculated using aDeltaD=max(aDoseIterator)*1.5/aNumberOfBins + @exception InvalidParameterException throw if _numberOfBins<=0 or _deltaD<0 + */ + DVHCalculator(DoseIteratorPointer aDoseIterator, const IDType& aStructureID, const IDType& aDoseID, + const DoseTypeGy aDeltaD = 0, const int aNumberOfBins = 201); - ~DVHCalculator(); + ~DVHCalculator(); - /*! @brief Generate DVH - @return Return new shared pointer of DVH. - @exception InvalidParameterException throw if _numberOfBins invalid: - _numberOfBins must be > max(aDoseIterator)/aDeltaD! - */ - DVHPointer generateDVH(); - - }; - } + /*! @brief Generate DVH + @return Return new shared pointer of DVH. + @exception InvalidParameterException throw if _numberOfBins invalid: + _numberOfBins must be > max(aDoseIterator)/aDeltaD! + */ + DVHPointer generateDVH(); + }; } +} + #endif diff --git a/code/core/rttbDVHSet.cpp b/code/core/rttbDVHSet.cpp index dec2cfc..34d6b23 100644 --- a/code/core/rttbDVHSet.cpp +++ b/code/core/rttbDVHSet.cpp @@ -1,175 +1,220 @@ // ----------------------------------------------------------------------- // 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 "rttbDVHSet.h" #include "rttbInvalidParameterException.h" -namespace rttb{ - namespace core{ - - DVHSet::DVHSet(IDType aStructureSetID, IDType aDoseID){ - this->_structureSetID=aStructureSetID; - this->_doseID=aDoseID; - } - - DVHSet::DVHSet(DVHSetType aDVHTVSet, DVHSetType aDVHHTSet, IDType aStructureSetID, IDType aDoseID){ - _dvhHTSet=aDVHHTSet; - _dvhTVSet=aDVHTVSet; - this->_structureSetID=aStructureSetID; - this->_doseID=aDoseID; - } +namespace rttb +{ + namespace core + { + + DVHSet::DVHSet(IDType aStructureSetID, IDType aDoseID) : _structureSetID(aStructureSetID), _doseID(aDoseID) {} + + DVHSet::DVHSet(DVHSetType aDVHTVSet, DVHSetType aDVHHTSet, IDType aStructureSetID, IDType aDoseID) + { + _dvhHTSet = aDVHHTSet; + _dvhTVSet = aDVHTVSet; + this->_structureSetID = aStructureSetID; + this->_doseID = aDoseID; + } - DVHSet::DVHSet(DVHSetType aDVHTVSet, DVHSetType aDVHHTSet, DVHSetType aDVHWVSet, IDType aStructureSetID, IDType aDoseID){ - _dvhHTSet=aDVHHTSet; - _dvhTVSet=aDVHTVSet; - _dvhWVSet=aDVHWVSet; - this->_structureSetID=aStructureSetID; - this->_doseID=aDoseID; - } + DVHSet::DVHSet(DVHSetType aDVHTVSet, DVHSetType aDVHHTSet, DVHSetType aDVHWVSet, IDType aStructureSetID, IDType aDoseID) + { + _dvhHTSet = aDVHHTSet; + _dvhTVSet = aDVHTVSet; + _dvhWVSet = aDVHWVSet; + this->_structureSetID = aStructureSetID; + this->_doseID = aDoseID; + } - std::size_t DVHSet::size() const{ - return _dvhHTSet.size()+_dvhTVSet.size()+_dvhWVSet.size(); - } + std::size_t DVHSet::size() const + { + return _dvhHTSet.size() + _dvhTVSet.size() + _dvhWVSet.size(); + } - void DVHSet::setStrSetID(IDType aStrSetID){_structureSetID=aStrSetID;} - void DVHSet::setDoseID(IDType aDoseID){_doseID=aDoseID;} + void DVHSet::setStrSetID(IDType aStrSetID) + { + _structureSetID = aStrSetID; + } + void DVHSet::setDoseID(IDType aDoseID) + { + _doseID = aDoseID; + } - IDType DVHSet::getStrSetID() const{return _structureSetID;} - IDType DVHSet::getDoseID() const{return _doseID;} + IDType DVHSet::getStrSetID() const + { + return _structureSetID; + } + IDType DVHSet::getDoseID() const + { + return _doseID; + } - DVH* DVHSet::getDVH(IDType structureID){ + DVH* DVHSet::getDVH(IDType structureID) + { DVHSetType::iterator itTV = _dvhTVSet.begin(); - for(;itTV!=_dvhTVSet.end();itTV++){ - if((*(itTV)).getStructureID()==structureID) - { + + for (; itTV != _dvhTVSet.end(); ++itTV) + { + if ((*(itTV)).getStructureID() == structureID) + { return &(*itTV); - } } + } DVHSetType::iterator itHT = _dvhHTSet.begin(); - for(;itHT!=_dvhHTSet.end();itHT++){ - if((*(itHT)).getStructureID()==structureID) - { + + for (; itHT != _dvhHTSet.end(); ++itHT) + { + if ((*(itHT)).getStructureID() == structureID) + { return &(*itHT); - } } + } DVHSetType::iterator itWV = _dvhWVSet.begin(); - for(;itWV!=_dvhWVSet.end();itWV++){ - if((*(itWV)).getStructureID()==structureID) - { + + for (; itWV != _dvhWVSet.end(); ++itWV) + { + if ((*(itWV)).getStructureID() == structureID) + { return &(*itWV); - } } - std::cout << "No DVH with the structure id: "<getHealthyTissueVolume(aDoseAbsolute)+this->getTargetVolume(aDoseAbsolute); + VolumeType DVHSet::getWholeVolume(DoseTypeGy aDoseAbsolute) const + { + VolumeType volume = this->getHealthyTissueVolume(aDoseAbsolute) + this->getTargetVolume(aDoseAbsolute); return volume; - } + } - VolumeType DVHSet::getHealthyTissueVolume(DoseTypeGy aDoseAbsolute) const{ + VolumeType DVHSet::getHealthyTissueVolume(DoseTypeGy aDoseAbsolute) const + { DVHSetType::const_iterator itHT = _dvhHTSet.begin(); - VolumeType volume=0; - VolumeType testVol=0; - while(itHT!=_dvhHTSet.end()){ + VolumeType volume = 0; - DVH dvh=*(itHT); + while (itHT != _dvhHTSet.end()) + { + VolumeType testVol = 0; + DVH dvh = *(itHT); testVol = dvh.getVx(aDoseAbsolute); - if (testVol>=0) - { - volume+=testVol; - } - itHT++; + + if (testVol >= 0) + { + volume += testVol; } - return volume; + ++itHT; } - VolumeType DVHSet::getTargetVolume(DoseTypeGy aDoseAbsolute) const{ + return volume; + + } + + VolumeType DVHSet::getTargetVolume(DoseTypeGy aDoseAbsolute) const + { DVHSetType::const_iterator itTV = _dvhTVSet.begin(); - VolumeType volume=0; - VolumeType testVol=0; - while(itTV!=_dvhTVSet.end()){ - DVH dvh=*(itTV); + VolumeType volume = 0; + + while (itTV != _dvhTVSet.end()) + { + VolumeType testVol = 0; + DVH dvh = *(itTV); testVol = dvh.getVx(aDoseAbsolute); - if (testVol>=0) - { - volume+=testVol; - } - itTV++; + + if (testVol >= 0) + { + volume += testVol; } - return volume; + + ++itTV; } - bool operator==(const DVHSet &aDVHSet, const DVHSet &otherDVHSet){ + return volume; + } + + bool operator==(const DVHSet& aDVHSet, const DVHSet& otherDVHSet) + { if (aDVHSet.getStrSetID() != otherDVHSet.getStrSetID()) - { + { return false; - } + } + if (aDVHSet.getDoseID() != otherDVHSet.getDoseID()) - { + { return false; - } + } + if (aDVHSet.size() != otherDVHSet.size()) - { + { return false; - } - return true; } - std::ostream& operator<<(std::ostream& s, const DVHSet &aDVHSet){ + return true; + } + + std::ostream& operator<<(std::ostream& s, const DVHSet& aDVHSet) + { s << "[ " << aDVHSet.getStrSetID() << ", " << aDVHSet.getDoseID() << " ]"; return s; - } + } - std::ostream& operator<<(std::ostream& s, const DVHSet::DVHSetType &aDVHSet){ + std::ostream& operator<<(std::ostream& s, const DVHSet::DVHSetType& aDVHSet) + { s << "[ "; - for( int i = 0; i < aDVHSet.size();i++){ + + for (int i = 0; i < aDVHSet.size(); i++) + { s << aDVHSet.at(i); - } - s << " ]"; - return s; } + s << " ]"; + return s; } + } +} diff --git a/code/core/rttbGeometricInfo.cpp b/code/core/rttbGeometricInfo.cpp index e20ab5e..efb2a14 100644 --- a/code/core/rttbGeometricInfo.cpp +++ b/code/core/rttbGeometricInfo.cpp @@ -1,303 +1,303 @@ // ----------------------------------------------------------------------- // 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 "rttbGeometricInfo.h" namespace rttb { namespace core { void GeometricInfo::setSpacing(const SpacingVectorType3D& aSpacingVector) { _spacing = aSpacingVector; } const SpacingVectorType3D& GeometricInfo::getSpacing() const { return _spacing; } void GeometricInfo::setImagePositionPatient(const WorldCoordinate3D& aImagePositionPatient) { _imagePositionPatient = aImagePositionPatient; } const WorldCoordinate3D& GeometricInfo::getImagePositionPatient() const { return _imagePositionPatient; } - void GeometricInfo::setOrientationMatrix(const OrientationMatrix anOrientationMatrix) + void GeometricInfo::setOrientationMatrix(const OrientationMatrix& anOrientationMatrix) { _orientationMatrix = anOrientationMatrix; computeInvertOrientation(); } bool GeometricInfo::computeInvertOrientation() { typedef boost::numeric::ublas::permutation_matrix pmatrix; boost::numeric::ublas::matrix A(_orientationMatrix); // create a permutation matrix for the LU-factorization pmatrix pm(A.size1()); size_t res = boost::numeric::ublas::lu_factorize(A, pm); if (res != 0) { return false; } _invertedOrientationMatrix.assign(boost::numeric::ublas::identity_matrix (A.size1())); // backsubstitute to get the inverse boost::numeric::ublas::lu_substitute(A, pm, _invertedOrientationMatrix); return true; } const ImageOrientation GeometricInfo::getImageOrientationRow() const { ImageOrientation _imageOrientationRow(0); _imageOrientationRow(0) = _orientationMatrix(0, 0); _imageOrientationRow(1) = _orientationMatrix(1, 0); _imageOrientationRow(2) = _orientationMatrix(2, 0); return _imageOrientationRow; } const ImageOrientation GeometricInfo::getImageOrientationColumn() const { ImageOrientation _imageOrientationColumn(0); _imageOrientationColumn(0) = _orientationMatrix(0, 1); _imageOrientationColumn(1) = _orientationMatrix(1, 1); _imageOrientationColumn(2) = _orientationMatrix(2, 1); return _imageOrientationColumn; } void GeometricInfo::setPixelSpacingRow(const GridVolumeType aValue) { _spacing(0) = aValue; } const GridVolumeType GeometricInfo::getPixelSpacingRow() const { return _spacing(0); } void GeometricInfo::setPixelSpacingColumn(const GridVolumeType aValue) { _spacing(1) = aValue; } const GridVolumeType GeometricInfo::getPixelSpacingColumn() const { return _spacing(1); } void GeometricInfo::setSliceThickness(const GridVolumeType aValue) { _spacing(2) = aValue; } const GridVolumeType GeometricInfo::getSliceThickness() const { return _spacing(2); } - void GeometricInfo::setImageSize(const ImageSize aSize) + void GeometricInfo::setImageSize(const ImageSize& aSize) { setNumColumns(aSize(0)); setNumRows(aSize(1)); setNumSlices(aSize(2)); } const ImageSize GeometricInfo::getImageSize() const { return ImageSize(getNumColumns(), getNumRows(), getNumSlices()); } void GeometricInfo::setNumColumns(const VoxelGridDimensionType aValue) { _numberOfColumns = aValue; } const VoxelGridDimensionType GeometricInfo::getNumColumns() const { return _numberOfColumns; } void GeometricInfo::setNumRows(const VoxelGridDimensionType aValue) { _numberOfRows = aValue; } const VoxelGridDimensionType GeometricInfo::getNumRows() const { return _numberOfRows; } void GeometricInfo::setNumSlices(const VoxelGridDimensionType aValue) { _numberOfFrames = aValue; } const VoxelGridDimensionType GeometricInfo::getNumSlices() const { return _numberOfFrames; } bool operator==(const GeometricInfo& gInfo, const GeometricInfo& gInfo1) { return (gInfo.getImagePositionPatient() == gInfo1.getImagePositionPatient() && gInfo.getOrientationMatrix() == gInfo1.getOrientationMatrix() && gInfo.getSpacing() == gInfo1.getSpacing() && gInfo.getNumColumns() == gInfo1.getNumColumns() && gInfo.getNumRows() == gInfo1.getNumRows() && gInfo.getNumSlices() == gInfo1.getNumSlices()); } bool GeometricInfo::worldCoordinateToIndex(const WorldCoordinate3D& aWorldCoordinate, VoxelGridIndex3D& aIndex) const { WorldCoordinate3D temp; temp = aWorldCoordinate - _imagePositionPatient; boost::numeric::ublas::vector temp2 = boost::numeric::ublas::prod( _invertedOrientationMatrix, temp); boost::numeric::ublas::vector resultS = boost::numeric::ublas::element_div(temp2, _spacing); aIndex = VoxelGridIndex3D(GridIndexType(resultS(0) + 0.5), GridIndexType(resultS(1) + 0.5), GridIndexType(resultS(2) + 0.5)); return isInside(aIndex); } bool GeometricInfo::indexToWorldCoordinate(const VoxelGridIndex3D& aIndex, WorldCoordinate3D& aWorldCoordinate) const { WorldCoordinate3D centerVoxel(aIndex(0) - 0.5, aIndex(1) - 0.5, aIndex(2) - 0.5); boost::numeric::ublas::vector resultS = boost::numeric::ublas::element_prod( centerVoxel, _spacing); boost::numeric::ublas::vector result = boost::numeric::ublas::prod( _orientationMatrix, resultS); aWorldCoordinate = result + _imagePositionPatient; return isInside(aIndex); } bool GeometricInfo::isInside(const VoxelGridIndex3D& aIndex) const { return (aIndex(0) >= 0 && aIndex(1) >= 0 && aIndex(2) >= 0 && aIndex(0) < static_cast(_numberOfColumns) && aIndex(1) < static_cast(_numberOfRows) && aIndex(2) < static_cast(_numberOfFrames)); } bool GeometricInfo::isInside(const WorldCoordinate3D& aWorldCoordinate) { VoxelGridIndex3D currentIndex; return (worldCoordinateToIndex(aWorldCoordinate, currentIndex)); } const GridSizeType GeometricInfo::getNumberOfVoxels() const { return _numberOfRows * _numberOfColumns * _numberOfFrames; } bool GeometricInfo::convert(const VoxelGridID& gridID, VoxelGridIndex3D& gridIndex) const { if (validID(gridID)) { gridIndex(0) = gridID % getNumColumns(); VoxelGridID tempID = (gridID - gridIndex.x()) / getNumColumns(); gridIndex(1) = tempID % getNumRows(); gridIndex(2) = (tempID - gridIndex.y()) / getNumRows(); return true; } return false; } bool GeometricInfo::convert(const VoxelGridIndex3D& gridIndex, VoxelGridID& gridID) const { if ((gridIndex.x() >= static_cast(getNumColumns())) || (gridIndex.y() >= static_cast(getNumRows())) || (gridIndex.z() >= static_cast(getNumSlices()))) { return false; } else { gridID = gridIndex.z() * getNumColumns() * getNumRows() + gridIndex.y() * getNumColumns() + gridIndex.x(); return validID(gridID); } } bool GeometricInfo::validID(const VoxelGridID aID) const { return (aID >= 0 && aID < getNumberOfVoxels()); } bool GeometricInfo::validIndex(const VoxelGridIndex3D& aIndex) const { VoxelGridID aID; if (!convert(aIndex, aID)) { return false; } else { return validID(aID); } } std::ostream& operator<<(std::ostream& s, const GeometricInfo& anGeometricInfo) { s << "[ " << anGeometricInfo.getImagePositionPatient() << "; " << anGeometricInfo.getOrientationMatrix() << "; " << anGeometricInfo.getSpacing() << "; " << "; " << anGeometricInfo.getNumColumns() << "; " << anGeometricInfo.getNumRows() << "; " << anGeometricInfo.getNumSlices() << " ]"; return s; } }//end namespace core }//end namespace rttb diff --git a/code/core/rttbGeometricInfo.h b/code/core/rttbGeometricInfo.h index 140d1c5..82f0f52 100644 --- a/code/core/rttbGeometricInfo.h +++ b/code/core/rttbGeometricInfo.h @@ -1,176 +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) */ #ifndef __GEOMETRIC_INFO_NEW_H #define __GEOMETRIC_INFO_NEW_H #include #include #include #include #include "rttbBaseType.h" namespace rttb { namespace core { /*! @brief GeometricInfo objects contain all the information required for transformations between voxel grid coordinates and world coordinates. Corresponding converter functions are also available. @note ITK Pixel Indexing used (http://www.itk.org/Doxygen45/html/classitk_1_1Image.html): The Index type reverses the order so that with Index[0] = col, Index[1] = row, Index[2] = slice. @todo Similarity for core::GeometricInfo needs to be defined. Orientation of the world matrix needs to be the same, but the extend of the grid may differ. This is for example the case if the slice thickness is different in Dose and Mask. This may cause a difference in the grid extend. */ class GeometricInfo { private: WorldCoordinate3D _imagePositionPatient; OrientationMatrix _orientationMatrix; OrientationMatrix _invertedOrientationMatrix; SpacingVectorType3D _spacing; VoxelGridDimensionType _numberOfColumns; VoxelGridDimensionType _numberOfRows; VoxelGridDimensionType _numberOfFrames; /* @brief Matrix inversion routine. Uses lu_factorize and lu_substitute in uBLAS to invert a matrix http://savingyoutime.wordpress.com/2009/09/21/c-matrix-inversion-boostublas/ */ bool computeInvertOrientation(); public: /*! @brief Constructor, initializes orientation matrix, spacing vector and patient position with zeros. */ - GeometricInfo() : _orientationMatrix(0), _spacing(0), _imagePositionPatient(0) {} + GeometricInfo() : _orientationMatrix(0), _spacing(0), _imagePositionPatient(0), _numberOfFrames(0), _numberOfRows(0), + _numberOfColumns(0) {} void setSpacing(const SpacingVectorType3D& aSpacingVector); const SpacingVectorType3D& getSpacing() const; void setImagePositionPatient(const WorldCoordinate3D& aImagePositionPatient); const WorldCoordinate3D& getImagePositionPatient() const; - void setOrientationMatrix(const OrientationMatrix anOrientationMatrix); + void setOrientationMatrix(const OrientationMatrix& anOrientationMatrix); const OrientationMatrix getOrientationMatrix() const { return _orientationMatrix; }; /*! @brief Returns the 1st row of the OrientationMatrix. @deprecated please use getOrientationMatrix() (x,0) instead*/ const ImageOrientation getImageOrientationRow() const; /*! @brief Returns the 2nd row of the OrientationMatrix. @deprecated please use getOrientationMatrix() (x,1) instead*/ const ImageOrientation getImageOrientationColumn() const; void setPixelSpacingRow(const GridVolumeType aValue); /*! @brief Returns the spacing in the x-dimension (rows) of the data grid. @deprecated please use getSpacing() (0) instead*/ const GridVolumeType getPixelSpacingRow() const; void setPixelSpacingColumn(const GridVolumeType aValue); /*! @brief Returns the spacing in the y-dimension (columns) of the data grid. @deprecated please use getSpacing() (1) instead*/ const GridVolumeType getPixelSpacingColumn() const; void setSliceThickness(const GridVolumeType aValue); /*! @brief Returns the spacing in the z-dimension (slices) of the data grid. @deprecated please use getSpacing() (2) instead*/ const GridVolumeType getSliceThickness() const; - void setImageSize(const ImageSize aSize); + void setImageSize(const ImageSize& aSize); const ImageSize getImageSize() const; void setNumColumns(const VoxelGridDimensionType aValue); const VoxelGridDimensionType getNumColumns() const; void setNumRows(const VoxelGridDimensionType aValue); const VoxelGridDimensionType getNumRows() const; void setNumSlices(const VoxelGridDimensionType aValue); const VoxelGridDimensionType getNumSlices() const; /*! @brief determines equality of two GeometricInfo objects. @todo Should equality be less restrictive and allow similar Orientation (different values) or equal orientation and different extend in world coordinates/different grid size */ friend bool operator==(const GeometricInfo& gInfo, const GeometricInfo& gInfo1); /*! @brief convert world coordinates to voxel grid index. The conversion of values is done even if the target index is not inside the given voxel grid (return false). If the target is inside the grid return true. */ bool worldCoordinateToIndex(const WorldCoordinate3D& aWorldCoordinate, - VoxelGridIndex3D& aIndex) const; + VoxelGridIndex3D& aIndex) const; /*! @brief voxel grid index to convert world coordinates. The conversion of values is done even if the target is not inside the given voxel grid (return false). If the target is inside the voxel grid return true. */ bool indexToWorldCoordinate(const VoxelGridIndex3D& aIndex , - WorldCoordinate3D& aWorldCoordinate) const; + WorldCoordinate3D& aWorldCoordinate) const; /*! @brief check if a given voxel grid index is inside the given voxel grid.*/ bool isInside(const VoxelGridIndex3D& aIndex) const; /*! @brief check if a given world coordinate is inside the given voxel grid.*/ bool isInside(const WorldCoordinate3D& aWorldCoordinate); const GridSizeType getNumberOfVoxels() const; bool convert(const VoxelGridID& gridID, VoxelGridIndex3D& gridIndex) const; bool convert(const VoxelGridIndex3D& gridIndex, VoxelGridID& gridID) const; /*! @brief test if given ID is inside current dose grid */ bool validID(const VoxelGridID aID) const; /*! @brief test if given index is inside current dose grid */ bool validIndex(const VoxelGridIndex3D& aIndex) const; /*!@ brief generates string stream representation of the GeometricInfo object. */ friend std::ostream& operator<<(std::ostream& s, const GeometricInfo& anGeometricInfo); }; } } #endif \ No newline at end of file diff --git a/code/core/rttbStructure.cpp b/code/core/rttbStructure.cpp index 839cd73..e011e16 100644 --- a/code/core/rttbStructure.cpp +++ b/code/core/rttbStructure.cpp @@ -1,140 +1,157 @@ // ----------------------------------------------------------------------- // 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 #include #include "rttbStructure.h" #include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" -namespace rttb{ - namespace core{ +namespace rttb +{ + namespace core + { /*! Compares two polygons in the same plane. Helper function for sorting of polygons. */ - bool comparePolygon(PolygonType A, PolygonType B){ + bool comparePolygon(PolygonType A, PolygonType B) + { PolygonType::iterator it; - for(it=A.begin();it!=A.end();it++) + + for (it = A.begin(); it != A.end(); ++it) + { + if ((*it)(2) != A.at(0)(2)) { - if((*it)(2)!=A.at(0)(2)) - { - throw std::range_error("Error: A must in the same _z plane!"); - } + throw std::range_error("Error: A must in the same _z plane!"); } + } + PolygonType::iterator it2; - for(it2=B.begin();it2!=B.end();it2++) - { - if((*it2)(2)!=B.at(0)(2)) - { - throw std::range_error("Error: B must in the same _z plane!"); - } - } - if(A.size()==0 || B.size()==0) + + for (it2 = B.begin(); it2 != B.end(); ++it2) + { + if ((*it2)(2) != B.at(0)(2)) { - throw std::range_error("Error: A and B must not be empty!"); + throw std::range_error("Error: B must in the same _z plane!"); } - return (A.at(0)(2)_structureVector=copy.getStructureVector(); - this->_strUID=copy.getUID(); - this->_label=copy.getLabel(); - } + Structure::Structure(const Structure& copy) : _structureVector(copy.getStructureVector()), _strUID(copy.getUID()), + _label(copy.getLabel()) + { + } - Structure::~Structure(){} + Structure::~Structure() {} - const PolygonSequenceType& Structure::getStructureVector() const{ + const PolygonSequenceType& Structure::getStructureVector() const + { return _structureVector; - } + } - - int Structure::getNumberOfEndpoints() const{ - int count=0; + + int Structure::getNumberOfEndpoints() const + { + int count = 0; PolygonSequenceType::const_iterator itVV; - for(itVV=_structureVector.begin();itVV!=_structureVector.end();itVV++){ - count+=(int)(*itVV).size(); - } - return count; + + for (itVV = _structureVector.begin(); itVV != _structureVector.end(); ++itVV) + { + count += (int)(*itVV).size(); } - IDType Structure::getUID() const{ + return count; + } + + IDType Structure::getUID() const + { return _strUID; - } + } - void Structure::setUID(const IDType aUID){ - _strUID=aUID; - } + void Structure::setUID(const IDType& aUID) + { + _strUID = aUID; + } - void Structure::setLabel(const StructureLabel aLabel){ - _label=aLabel; - } + void Structure::setLabel(const StructureLabel& aLabel) + { + _label = aLabel; + } - StructureLabel Structure::getLabel() const{ + StructureLabel Structure::getLabel() const + { return _label; - } + } - }//end namespace core - }//end namespace rttb + }//end namespace core +}//end namespace rttb diff --git a/code/core/rttbStructure.h b/code/core/rttbStructure.h index 9ac2671..eb99dfd 100644 --- a/code/core/rttbStructure.h +++ b/code/core/rttbStructure.h @@ -1,105 +1,107 @@ // ----------------------------------------------------------------------- // 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) */ /* Changes in Architecture: This class should be universally used independent of the origin of the Structures. All UID references are omitted. */ #ifndef __STRUCTURE_H #define __STRUCTURE_H #include #include #include #include "rttbBaseType.h" -namespace rttb{ +namespace rttb +{ - namespace core{ + namespace core + { /*! @class Structure @brief This is a class representing a RT Structure */ class Structure - { - public: - typedef boost::shared_ptr StructTypePointer; - private: - /*! @brief WorldCoordinate3D in mm - */ - PolygonSequenceType _structureVector; + { + public: + typedef boost::shared_ptr StructTypePointer; + private: + /*! @brief WorldCoordinate3D in mm + */ + PolygonSequenceType _structureVector; - /*! @brief Contour Geometric Type using DICOM-RT definition (3006,0042). - * POINT: indicates that the contour is a single point, defining a specific location of significance. - * OPEN_PLANAR: indicates that the last vertex shall not be connected to the first point, and that all points - * in Contour Data (3006,0050) shall be coplanar. - * OPEN_NONPLANAR: indicates that the last vertex shall not be connected to the first point, and that the points - * in Contour Data(3006,0050) may be non-coplanar. - * CLOSED_PLANAR: indicates that the last point shall be connected to the first point, where the first point is - * not repeated in the Contour Data. All points in Contour Data (3006,0050) shall be coplanar. - */ - std::vector _contourGeometricTypeVector; + /*! @brief Contour Geometric Type using DICOM-RT definition (3006,0042). + * POINT: indicates that the contour is a single point, defining a specific location of significance. + * OPEN_PLANAR: indicates that the last vertex shall not be connected to the first point, and that all points + * in Contour Data (3006,0050) shall be coplanar. + * OPEN_NONPLANAR: indicates that the last vertex shall not be connected to the first point, and that the points + * in Contour Data(3006,0050) may be non-coplanar. + * CLOSED_PLANAR: indicates that the last point shall be connected to the first point, where the first point is + * not repeated in the Contour Data. All points in Contour Data (3006,0050) shall be coplanar. + */ + std::vector _contourGeometricTypeVector; - /*! @brief Structure UID*/ - IDType _strUID; + /*! @brief Structure UID*/ + IDType _strUID; - /*! @brief Structure Label*/ - StructureLabel _label; + /*! @brief Structure Label*/ + StructureLabel _label; - public: - /*! @brief Structure Standard Constructor - uid will be randomly generated using boost::uuid library at first. To change the uid using setUID(). - */ - Structure(); + public: + /*! @brief Structure Standard Constructor + uid will be randomly generated using boost::uuid library at first. To change the uid using setUID(). + */ + Structure(); - /*! @brief Structure Constructor - uid will be randomly generated using boost::uuid library at first. To change the uid using setUID(). - */ - Structure(PolygonSequenceType strVector); + /*! @brief Structure Constructor + uid will be randomly generated using boost::uuid library at first. To change the uid using setUID(). + */ + Structure(PolygonSequenceType strVector); - Structure(const Structure& copy); + Structure(const Structure& copy); - ~Structure(); + ~Structure(); - const PolygonSequenceType& getStructureVector() const; + const PolygonSequenceType& getStructureVector() const; - /*! @brief Get the number of end points (points that define the polygon) of all contours of the structure. - */ - int getNumberOfEndpoints() const; + /*! @brief Get the number of end points (points that define the polygon) of all contours of the structure. + */ + int getNumberOfEndpoints() const; - IDType getUID() const; + IDType getUID() const; - void setUID(const IDType aUID); + void setUID(const IDType& aUID); - void setLabel(const StructureLabel aLabel); + void setLabel(const StructureLabel& aLabel); - StructureLabel getLabel() const; + StructureLabel getLabel() const; - }; - }//end namespace core - }//end namespace rttb + }; + }//end namespace core +}//end namespace rttb #endif diff --git a/code/io/helax/rttbDicomHelaxDoseAccessor.cpp b/code/io/helax/rttbDicomHelaxDoseAccessor.cpp index f0baed0..a0487fe 100644 --- a/code/io/helax/rttbDicomHelaxDoseAccessor.cpp +++ b/code/io/helax/rttbDicomHelaxDoseAccessor.cpp @@ -1,322 +1,325 @@ // ----------------------------------------------------------------------- // 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 "boost/filesystem/operations.hpp" #include "boost/filesystem/path.hpp" #include "boost/progress.hpp" #include #include "rttbDicomHelaxDoseAccessor.h" #include "rttbInvalidDoseException.h" #include "rttbDcmrtException.h" #include "rttbIndexOutOfBoundsException.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace io { namespace helax { DicomHelaxDoseAccessor::~DicomHelaxDoseAccessor() { } DicomHelaxDoseAccessor::DicomHelaxDoseAccessor(std::vector aDICOMRTDoseVector) { for (int i = 0; i < aDICOMRTDoseVector.size(); i++) { _doseVector.push_back(aDICOMRTDoseVector.at(i)); } this->begin(); } bool DicomHelaxDoseAccessor::begin() { if (_doseVector.size() == 0) { throw core::InvalidParameterException(" The size of aDICOMRTDoseVector is 0!"); } assembleGeometricInfo(); _doseData.clear(); OFString doseGridScalingStr; - char* pEnd; _doseVector.at(0)->getDoseGridScaling( doseGridScalingStr);//get the first dose grid scaling as _doseGridScaling try { _doseGridScaling = boost::lexical_cast(doseGridScalingStr.c_str()); } catch (boost::bad_lexical_cast&) { throw core::InvalidDoseException("Dose grid scaling not readable or = 0!") ; } for (int i = 0; i < _doseVector.size(); i++) { DRTDoseIODPtr dose = _doseVector.at(i); OFString currentDoseGridScalingStr; dose->getDoseGridScaling(currentDoseGridScalingStr); double currentDoseGridScaling; try { currentDoseGridScaling = boost::lexical_cast(currentDoseGridScalingStr.c_str()); } catch (boost::bad_lexical_cast&) { throw core::InvalidDoseException("Dose grid scaling not readable or = 0!") ; } OFCondition status; DcmFileFormat fileformat; DcmItem doseitem; status = dose->write(doseitem); if (status.good()) { unsigned long count; const Uint16* pixelData; status = doseitem.findAndGetUint16Array(DcmTagKey(0x7fe0, 0x0010), pixelData, &count); if (status.good()) { for (unsigned int i = 0; i < static_cast(_geoInfo.getNumColumns()*_geoInfo.getNumRows()); i++) { this->_doseData.push_back(pixelData[i]*currentDoseGridScaling / _doseGridScaling); //recalculate dose data } } else { throw dicom::DcmrtException("Read Pixel Data (7FE0,0010) failed!"); } } else { throw dicom::DcmrtException("Read DICOM-RT Dose file failed!"); } } return true; } bool DicomHelaxDoseAccessor::assembleGeometricInfo() { DRTDoseIODPtr dose = _doseVector.at(0); Uint16 temp = 0; dose->getColumns(temp); _geoInfo.setNumColumns(temp); temp = 0; dose->getRows(temp); _geoInfo.setNumRows(temp); OFString numberOfFramesStr; dose->getNumberOfFrames(numberOfFramesStr); if (!numberOfFramesStr.empty()) { _geoInfo.setNumSlices(boost::lexical_cast(numberOfFramesStr.c_str())); } else { _geoInfo.setNumSlices((VoxelGridDimensionType)_doseVector.size()); } if (_geoInfo.getNumColumns() == 0 || _geoInfo.getNumRows() == 0 || _geoInfo.getNumSlices() == 0) { throw core::InvalidDoseException("Empty dicom dose!") ; } OFString imageOrientationRowX; dose->getImageOrientationPatient(imageOrientationRowX, 0); OFString imageOrientationRowY; dose->getImageOrientationPatient(imageOrientationRowY, 1); OFString imageOrientationRowZ; dose->getImageOrientationPatient(imageOrientationRowZ, 2); OFString imageOrientationColumnX; dose->getImageOrientationPatient(imageOrientationColumnX, 3); OFString imageOrientationColumnY; dose->getImageOrientationPatient(imageOrientationColumnY, 4); OFString imageOrientationColumnZ; dose->getImageOrientationPatient(imageOrientationColumnZ, 5); WorldCoordinate3D imageOrientationRow; WorldCoordinate3D imageOrientationColumn; try - { - imageOrientationRow(0) = boost::lexical_cast(imageOrientationRowX.c_str()); - imageOrientationRow(1) = boost::lexical_cast(imageOrientationRowY.c_str()); - imageOrientationRow(2) = boost::lexical_cast(imageOrientationRowZ.c_str()); - - imageOrientationColumn(0) = boost::lexical_cast(imageOrientationColumnX.c_str()); - imageOrientationColumn(1) = boost::lexical_cast(imageOrientationColumnY.c_str()); - imageOrientationColumn(2) = boost::lexical_cast(imageOrientationColumnZ.c_str()); + { + imageOrientationRow(0) = boost::lexical_cast(imageOrientationRowX.c_str()); + imageOrientationRow(1) = boost::lexical_cast(imageOrientationRowY.c_str()); + imageOrientationRow(2) = boost::lexical_cast(imageOrientationRowZ.c_str()); + + imageOrientationColumn(0) = boost::lexical_cast(imageOrientationColumnX.c_str()); + imageOrientationColumn(1) = boost::lexical_cast(imageOrientationColumnY.c_str()); + imageOrientationColumn(2) = boost::lexical_cast(imageOrientationColumnZ.c_str()); } catch (boost::bad_lexical_cast&) { throw core::InvalidDoseException("boost::lexical_cast ImageOrientation failed! Can not read image orientation X/Y/Z!") ; } OrientationMatrix orientation; orientation(0, 0) = imageOrientationRow.x(); orientation(1, 0) = imageOrientationRow.y(); orientation(2, 0) = imageOrientationRow.z(); orientation(0, 1) = imageOrientationColumn.x(); orientation(1, 1) = imageOrientationColumn.y(); orientation(2, 1) = imageOrientationColumn.z(); WorldCoordinate3D perpendicular = imageOrientationRow.cross(imageOrientationColumn); orientation(0, 2) = perpendicular.x(); orientation(1, 2) = perpendicular.y(); orientation(2, 2) = perpendicular.z(); _geoInfo.setOrientationMatrix(orientation); OFString imagePositionX; dose->getImagePositionPatient(imagePositionX, 0); OFString imagePositionY; dose->getImagePositionPatient(imagePositionY, 1); OFString imagePositionZ; dose->getImagePositionPatient(imagePositionZ, 2); WorldCoordinate3D imagePositionPatient; try { imagePositionPatient(0) = boost::lexical_cast(imagePositionX.c_str()); imagePositionPatient(1) = boost::lexical_cast(imagePositionY.c_str()); imagePositionPatient(2) = boost::lexical_cast(imagePositionZ.c_str()); } catch (boost::bad_lexical_cast&) { throw core::InvalidDoseException("boost::lexical_cast ImagePosition failed! Can not read image position X/Y/Z!") ; } _geoInfo.setImagePositionPatient(imagePositionPatient); SpacingVectorType3D spacingVector; OFString pixelSpacingRowStr; dose->getPixelSpacing(pixelSpacingRowStr, 0); OFString pixelSpacingColumnStr; dose->getPixelSpacing(pixelSpacingColumnStr, 1); try { spacingVector(1) = boost::lexical_cast(pixelSpacingRowStr.c_str()); spacingVector(0) = boost::lexical_cast(pixelSpacingColumnStr.c_str()); } catch (boost::bad_lexical_cast&) { throw core::InvalidDoseException("Can not read Pixel Spacing Row/Column!") ; } _geoInfo.setSpacing(spacingVector); if (_geoInfo.getPixelSpacingRow() == 0 || _geoInfo.getPixelSpacingColumn() == 0) { throw core::InvalidDoseException("Pixel spacing not readable or = 0!"); } OFString sliceThicknessStr; dose->getSliceThickness(sliceThicknessStr); + try { spacingVector(2) = boost::lexical_cast(sliceThicknessStr.c_str()); } catch (boost::bad_lexical_cast&) { - spacingVector(2) = 0 ;//if no information about slice thickness, set to 0 and calculate it using z coordinate difference between 1. and 2. dose + spacingVector(2) = 0 + ;//if no information about slice thickness, set to 0 and calculate it using z coordinate difference between 1. and 2. dose } if (spacingVector(2) == 0) { if (_doseVector.size() > 1) { DRTDoseIODPtr dose2 = _doseVector.at(1);//get the 2. dose OFString imagePositionZ2; dose2->getImagePositionPatient(imagePositionZ2, 2); - try{ - spacingVector(2) = boost::lexical_cast(imagePositionZ2.c_str())- imagePositionPatient(2);//caculate slicethickness + try + { + spacingVector(2) = boost::lexical_cast(imagePositionZ2.c_str()) - imagePositionPatient( + 2); //caculate slicethickness } catch (boost::bad_lexical_cast&) { throw core::InvalidDoseException("Can not read image position Z of the 2. dose!"); } } else { std::cerr << "sliceThickness == 0! It will be replaced with pixelSpacingRow=" << _geoInfo.getPixelSpacingRow() << "!" << std::endl; spacingVector(2) = spacingVector(0); } } _geoInfo.setSpacing(spacingVector); return true; } DoseTypeGy DicomHelaxDoseAccessor::getDoseAt(const VoxelGridID aID) const { return _doseData.at(aID) * _doseGridScaling; } DoseTypeGy DicomHelaxDoseAccessor::getDoseAt(const VoxelGridIndex3D& aIndex) const { VoxelGridID aVoxelGridID; if (_geoInfo.convert(aIndex, aVoxelGridID)) { return getDoseAt(aVoxelGridID); } else { return -1; } } } } } diff --git a/code/io/itk/rttbGenericImageReader.cpp b/code/io/itk/rttbGenericImageReader.cpp index 2a5ba87..a926fdd 100644 --- a/code/io/itk/rttbGenericImageReader.cpp +++ b/code/io/itk/rttbGenericImageReader.cpp @@ -1,305 +1,302 @@ // ----------------------------------------------------------------------- // MatchPoint - DKFZ translational registration framework // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See mapCopyright.txt or // http://www.dkfz.de/en/sidt/projects/MatchPoint/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) // Subversion HeadURL: $HeadURL: https://svn/sbr/Sources/SBR-Projects/MatchPoint/trunk/Code/IO/source/mapGenericImageReader.cpp $ */ #include "rttbGenericImageReader.h" namespace rttb { namespace io { namespace itk { void GenericImageReader::load() { _spImage = NULL; FileNameString probeFileName = this->_fileName; if (this->_seriesReadStyle == ImageSeriesReadStyle::Numeric) { typedef ::itk::NumericSeriesFileNames NamesType; NamesType::Pointer names = NamesType::New(); names->SetStartIndex(1); names->SetEndIndex(1); names->SetSeriesFormat(this->_fileName.c_str()); probeFileName = names->GetFileNames()[0]; } ::itk::ImageIOBase::Pointer imageIO = ::itk::ImageIOFactory::CreateImageIO(probeFileName.c_str(), ::itk::ImageIOFactory::ReadMode); if (!imageIO) { throw ::itk::ExceptionObject("No ImageIO found for given file. Please check if the file exists and has a supported format. File:" + probeFileName); } // Now that we found the appropriate ImageIO class, ask it to // read the meta data from the image file. imageIO->SetFileName(probeFileName.c_str()); imageIO->ReadImageInformation(); this->_loadedComponentType = imageIO->GetComponentType(); this->_loadedPixelType = imageIO->GetPixelType(); if (this->_loadedPixelType == ::itk::ImageIOBase::RGB && imageIO->GetNumberOfComponents() == 1) { //if only one channel per pixel handle as scalar as long as RGB etc. is not supported this->_loadedPixelType = ::itk::ImageIOBase::SCALAR; } this->_loadedComponentTypeStr = imageIO->GetComponentTypeAsString(this->_loadedComponentType); this->_loadedPixelTypeStr = imageIO->GetPixelTypeAsString(this->_loadedPixelType); this->_loadedDimensions = imageIO->GetNumberOfDimensions(); if (this->_seriesReadStyle == ImageSeriesReadStyle::Numeric && this->_loadedDimensions == 2) { this->_loadedDimensions = 3; //it is a stack of 2D images -> 3D } if (this->_loadedDimensions < 2 || this->_loadedDimensions > 3) { throw ::itk::ExceptionObject("The file uses a number of dimensions that is not supported in this application. Only dim<=3 supported "); } switch (_loadedPixelType) { case ::itk::ImageIOBase::SCALAR: { if (this->_loadedDimensions == 2) { loadScalar<2>(); } else { loadScalar<3>(); } break; } default: { throw ::itk::ExceptionObject("The file uses a pixel type that is not supported in this application. Only SCALAR pixel type supported "); } } _upToDate = true; }; template void GenericImageReader:: loadScalar() { // Use the pixel type to instantiate the appropriate reader switch (this->_loadedComponentType) { case ::itk::ImageIOBase::UCHAR: { this->_spImage = readImage(_fileName, _seriesReadStyle, false, 0, 0, _upperSeriesLimit, &_dictionaryArray); break; } case ::itk::ImageIOBase::CHAR: { this->_spImage = readImage(_fileName, _seriesReadStyle, false, 0, 0, _upperSeriesLimit, &_dictionaryArray); break; } case ::itk::ImageIOBase::USHORT: { this->_spImage = readImage(_fileName, _seriesReadStyle, false, 0, 0, _upperSeriesLimit, &_dictionaryArray); break; } case ::itk::ImageIOBase::SHORT: { this->_spImage = readImage(_fileName, _seriesReadStyle, false, 0, 0, _upperSeriesLimit, &_dictionaryArray); break; } case ::itk::ImageIOBase::UINT: { this->_spImage = readImage(_fileName, _seriesReadStyle, false, 0, 0, _upperSeriesLimit, &_dictionaryArray); break; } case ::itk::ImageIOBase::INT: { this->_spImage = readImage(_fileName, _seriesReadStyle, false, 0, 0, _upperSeriesLimit, &_dictionaryArray); break; } case ::itk::ImageIOBase::ULONG: { this->_spImage = readImage(_fileName, _seriesReadStyle, false, 0, 0, _upperSeriesLimit, &_dictionaryArray); break; } case ::itk::ImageIOBase::LONG: { this->_spImage = readImage(_fileName, _seriesReadStyle, false, 0, 0, _upperSeriesLimit, &_dictionaryArray); break; } case ::itk::ImageIOBase::FLOAT: { this->_spImage = readImage(_fileName, _seriesReadStyle, false, 0, 0, _upperSeriesLimit, &_dictionaryArray); break; } case ::itk::ImageIOBase::DOUBLE: { this->_spImage = readImage(_fileName, _seriesReadStyle, false, 0, 0, _upperSeriesLimit, &_dictionaryArray); break; } default: { throw ::itk::ExceptionObject("The file uses a pixel component type that is not supported in this application. ComponentType: " + this->_loadedComponentTypeStr); } } }; const FileNameString& GenericImageReader:: getFileName() const { return _fileName; }; void GenericImageReader:: setFileName(const FileNameString& fileName) { if (fileName != _fileName) { _upToDate = false; _fileName = fileName; } } const unsigned int GenericImageReader:: getUpperSeriesLimit() const { return _upperSeriesLimit; }; void GenericImageReader:: setUpperSeriesLimit(const unsigned int upperLimit) { if (upperLimit != _upperSeriesLimit) { _upToDate = false; _upperSeriesLimit = upperLimit; }; }; const ImageSeriesReadStyle::Type GenericImageReader:: getSeriesReadStyle() const { return _seriesReadStyle; }; void GenericImageReader:: setSeriesReadStyle(ImageSeriesReadStyle::Type readStyle) { if (readStyle != _seriesReadStyle) { _upToDate = false; _seriesReadStyle = readStyle; }; }; GenericImageReader::GenericOutputImageType* GenericImageReader:: GetOutput(unsigned int& loadedDimensions, LoadedPixelType& loadedPixelType, LoadedComponentType& loadedComponentType) { if (!_upToDate) { load(); loadedPixelType = _loadedPixelType; loadedComponentType = _loadedComponentType; loadedDimensions = _loadedDimensions; }; return _spImage; }; GenericImageReader:: - GenericImageReader() + GenericImageReader() : _fileName(), _upperSeriesLimit(255), _upToDate(false), + _seriesReadStyle(ImageSeriesReadStyle::Default) { - _fileName = ""; - _upperSeriesLimit = 255; - _upToDate = false; - _seriesReadStyle = ImageSeriesReadStyle::Default; }; GenericImageReader:: ~GenericImageReader() { }; const GenericImageReader::MetaDataDictionaryArrayType& GenericImageReader:: getMetaDictionaryArray() { return _dictionaryArray; }; }//end namespace itk }//end namespace io }//end namespace rttb diff --git a/code/io/itk/rttbImageReader.tpp b/code/io/itk/rttbImageReader.tpp index 9e07f23..cf71e4f 100644 --- a/code/io/itk/rttbImageReader.tpp +++ b/code/io/itk/rttbImageReader.tpp @@ -1,534 +1,533 @@ // ----------------------------------------------------------------------- // MatchPoint - DKFZ translational registration framework // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See mapCopyright.txt or // http://www.dkfz.de/en/sidt/projects/MatchPoint/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) // Subversion HeadURL: $HeadURL: https://svn/sbr/Sources/SBR-Projects/MatchPoint/trunk/Code/IO/include/mapImageReader.tpp $ */ #ifndef __RTTB_IMAGE_READER_TPP #define __RTTB_IMAGE_READER_TPP #include "rttbImageReader.h" #include "rttbFileDispatch.h" #ifdef RTTB_DISABLE_ITK_IO_FACTORY_AUTO_REGISTER #undef ITK_IO_FACTORY_REGISTER_MANAGER -#endif //RTTB_DISABLE_ITK_IO_FACTORY_AUTO_REGISTER +#endif RTTB_DISABLE_ITK_IO_FACTORY_AUTO_REGISTER #include "itkImageFileReader.h" #include "itkImageFileWriter.h" #include "itkImageSeriesReader.h" #include "itkImageSeriesWriter.h" #include "itkNumericSeriesFileNames.h" #include "itkGDCMSeriesFileNames.h" #include "itkRescaleIntensityImageFilter.h" #include "itkCastImageFilter.h" #include "itkFixedArray.h" #include "itksys/SystemTools.hxx" #include #include namespace rttb { namespace io { namespace itk { template void ImageReader:: load2D() { typedef ::itk::ImageFileReader< InputImageType > ImageReaderType; typedef ::itk::RescaleIntensityImageFilter< InputImageType, InputImageType > RescaleFilterType; typedef ::itk::CastImageFilter< InputImageType, OutputImageType > CastFilterType; typename CastFilterType::Pointer imageCaster = CastFilterType::New(); typename ImageReaderType::Pointer imageReader = ImageReaderType::New(); typename RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New(); rescaleFilter->SetOutputMinimum(static_cast(_rescaleMin)); rescaleFilter->SetOutputMaximum(static_cast(_rescaleMax)); imageReader->SetFileName(_fileName.c_str()); rescaleFilter->SetInput(imageReader->GetOutput()); if (_rescaleImage) { imageCaster->SetInput(rescaleFilter->GetOutput()); } else { imageCaster->SetInput(imageReader->GetOutput()); } _spImage = imageCaster->GetOutput(); imageCaster->Update(); _dictionaryArray.clear(); _dictionaryArray.push_back(imageReader->GetImageIO()->GetMetaDataDictionary()); _upToDate = true; }; template const typename ImageReader::MetaDataDictionaryArrayType& ImageReader:: getMetaDictionaryArray() { return _dictionaryArray; }; template void ImageReader:: copyMetaDictionaryArray(const ITKMetaDataDictionaryArray* fromArray, MetaDataDictionaryArrayType& toArray) { toArray.clear(); ITKMetaDataDictionaryArray::const_iterator itr = fromArray->begin(); ITKMetaDataDictionaryArray::const_iterator end = fromArray->end(); while (itr != end) { toArray.push_back(*(*itr)); ++itr; } }; template typename ::itk::ImageSource::InputImageType>::Pointer ImageReader:: prepareNumericSource() const { //mumeric series image reader typedef ::itk::ImageSeriesReader< InputImageType > SeriesReaderType; typedef ::itk::NumericSeriesFileNames NamesType; typename SeriesReaderType::Pointer seriesReader = SeriesReaderType::New(); NamesType::Pointer names = NamesType::New(); names->SetStartIndex(1); names->SetEndIndex(_upperSeriesLimit); names->SetSeriesFormat(_fileName.c_str()); seriesReader->SetFileNames(names->GetFileNames()); if (seriesReader->GetFileNames().size() == 0) { throw ::itk::ExceptionObject("Image reader is not correctly configured. Preparing a series reading of a numeric source no(!) files were found."); } typename ::itk::ImageSource::InputImageType>::Pointer genericReader = seriesReader.GetPointer(); return genericReader; }; template typename ::itk::ImageSource::InputImageType>::Pointer ImageReader:: prepareDICOMSource() const { //ITK > v4.3.x removed old DICOMSeriesFileNames. Thus currently only support GDCM as source by default return prepareGDCMSource(); /**@TODO Add support for DCMTKSeriesFileNames too*/ }; template typename ::itk::ImageSource::InputImageType>::Pointer ImageReader:: prepareGDCMSource() const { core::FileDispatch dispatch(_fileName); FileNameString dir = dispatch.getPath(); FileNameString strippedFileName = dispatch.getFullName(); typedef ::itk::GDCMSeriesFileNames NamesGeneratorType; NamesGeneratorType::Pointer nameGenerator = NamesGeneratorType::New(); nameGenerator->SetInputDirectory(dir); nameGenerator->SetUseSeriesDetails(true); ::itk::FilenamesContainer fileNames; if (strippedFileName.empty()) { std::cerr << "No file name specified. Use first DICOM series found in directory." << std::endl; fileNames = nameGenerator->GetInputFileNames(); } else { ::itk::SerieUIDContainer seriesUIDs = nameGenerator->GetSeriesUIDs(); std::cerr << "Checking found DICOM series." << std::endl; //check the found series for the filename to pick the right series correlated to the passed filename while (seriesUIDs.size() > 0) { fileNames = nameGenerator->GetFileNames(seriesUIDs.back()); std::cerr << "Checking series: " << seriesUIDs.back() << " (file count: " << fileNames.size() << ")" << std::endl; seriesUIDs.pop_back(); for (::itk::SerieUIDContainer::const_iterator pos = fileNames.begin(); pos != fileNames.end(); ++pos) { if (pos->find(strippedFileName) != FileNameString::npos) { //this series containes the passed filename -> //we have the right block of files -> we are done. std::cerr << "Found right series!" << std::endl; seriesUIDs.clear(); break; } } } } typedef ::itk::ImageSeriesReader< InputImageType > SeriesReaderType; typename SeriesReaderType::Pointer seriesReader = SeriesReaderType::New(); seriesReader->SetFileNames(fileNames); if (seriesReader->GetFileNames().size() == 0) { throw ::itk::ExceptionObject("Image reader is not correctly configured. Preparing a series reading of a DICOM source no(!) dicom files were found. search location: " + _fileName); } typename ::itk::ImageSource::InputImageType>::Pointer genericReader = seriesReader.GetPointer(); return genericReader; }; template typename ::itk::ImageSource::InputImageType>::Pointer ImageReader:: prepareNormalSource() const { //Normal image reader (no series read style) typedef ::itk::ImageFileReader< InputImageType > ImageReaderType; typename ImageReaderType::Pointer imageReader = ImageReaderType::New(); imageReader->SetFileName(_fileName.c_str()); typename ::itk::ImageSource::InputImageType>::Pointer genericReader = imageReader.GetPointer(); return genericReader; }; template void ImageReader:: load3D() { core::FileDispatch dispatch(_fileName); FileNameString sTemp = dispatch.getExtension(); - FileNameString sDir = dispatch.getPath(); //Convert to lowercase - for (FileNameString::iterator spos = sTemp.begin(); spos != sTemp.end(); spos++) + for (FileNameString::iterator spos = sTemp.begin(); spos != sTemp.end(); ++spos) { (*spos) = std::tolower((*spos), std::locale("")); } typedef ::itk::RescaleIntensityImageFilter< InputImageType, InputImageType > RescaleFilterType; typedef ::itk::CastImageFilter< InputImageType, OutputImageType > CastFilterType; typename CastFilterType::Pointer imageCaster = CastFilterType::New(); typename RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New(); typename ::itk::ImageSource::Pointer spReader; rescaleFilter->SetOutputMinimum(static_cast(_rescaleMin)); rescaleFilter->SetOutputMaximum(static_cast(_rescaleMax)); if (_seriesReadStyle == ImageSeriesReadStyle::Numeric) { spReader = prepareNumericSource(); } else if (_seriesReadStyle == ImageSeriesReadStyle::Dicom) { spReader = prepareDICOMSource(); } else if (_seriesReadStyle == ImageSeriesReadStyle::GDCM) { spReader = prepareGDCMSource(); } else if (_seriesReadStyle == ImageSeriesReadStyle::Default) { bool isDir = itksys::SystemTools::FileIsDirectory(_fileName.c_str()); if (isDir || sTemp == ".dcm" || sTemp == ".ima") { spReader = prepareDICOMSource(); } else { spReader = prepareNormalSource(); } } else { //style is none spReader = prepareNormalSource(); } if (_rescaleImage) { rescaleFilter->SetInput(spReader->GetOutput()); imageCaster->SetInput(rescaleFilter->GetOutput()); } else { imageCaster->SetInput(spReader->GetOutput()); } imageCaster->Update(); _spImage = imageCaster->GetOutput(); typedef ::itk::ImageFileReader< InputImageType > ImageReaderType; typedef ::itk::ImageSeriesReader< InputImageType > ImageSeriesReaderType; ImageReaderType* pFileReader = dynamic_cast(spReader.GetPointer()); ImageSeriesReaderType* pSeriesReader = dynamic_cast(spReader.GetPointer()); if (pFileReader) { _dictionaryArray.clear(); _dictionaryArray.push_back(pFileReader->GetImageIO()->GetMetaDataDictionary()); } else if (pSeriesReader) { copyMetaDictionaryArray(pSeriesReader->GetMetaDataDictionaryArray(), _dictionaryArray); } else { throw ::itk::ExceptionObject("Image reader is not valid. Internal reader seams not to be itk::ImageFileReader or itk::ImageSeriesReader."); } _upToDate = true; }; template const FileNameString& ImageReader:: getFileName() const { return _fileName; }; template void ImageReader:: setFileName(const FileNameString& fileName) { if (fileName != _fileName) { _upToDate = false; _fileName = fileName; } } template const typename ImageReader::RescaleValueType& ImageReader:: getRescaleMinimum() const { return _rescaleMin; }; template void ImageReader:: setRescaleMinimum(const RescaleValueType& dRescaleMin) { if (dRescaleMin != _rescaleMin) { _upToDate = false; _rescaleMin = dRescaleMin; }; }; template const typename ImageReader::RescaleValueType& ImageReader:: getRescaleMaximum() const { return _rescaleMax; }; template void ImageReader:: setRescaleMaximum(const RescaleValueType& dRescaleMax) { if (dRescaleMax != _rescaleMax) { _upToDate = false; _rescaleMax = dRescaleMax; }; }; template const bool ImageReader:: getRescaleImage() const { return _rescaleImage; }; template void ImageReader:: setRescaleImage(const bool rescaleImage) { if (rescaleImage != _rescaleImage) { _upToDate = false; _rescaleImage = rescaleImage; }; }; template const unsigned int ImageReader:: getUpperSeriesLimit() const { return _upperSeriesLimit; }; template void ImageReader:: setUpperSeriesLimit(const unsigned int upperLimit) { if (upperLimit != _upperSeriesLimit) { _upToDate = false; _upperSeriesLimit = upperLimit; }; }; template const ImageSeriesReadStyle::Type ImageReader:: getSeriesReadStyle() const { return _seriesReadStyle; }; template void ImageReader:: setSeriesReadStyle(ImageSeriesReadStyle::Type readStyle) { if (readStyle != _seriesReadStyle) { _upToDate = false; _seriesReadStyle = readStyle; }; }; template typename ImageReader::OutputImageType* ImageReader:: GetOutput(void) { if (!_upToDate) { switch (OutputImageType::GetImageDimension()) { case 2: load2D(); break; case 3: load3D(); break; default: throw ::itk::ExceptionObject("Image reader only accepts 2 or 3 dimensional images."); }; }; return _spImage; }; template ImageReader:: ImageReader() { _fileName = ""; _upperSeriesLimit = 255; _upToDate = false; _rescaleImage = false; _rescaleMax = 255; _rescaleMin = 0; _seriesReadStyle = ImageSeriesReadStyle::Default; }; template ImageReader:: ~ImageReader() { }; template typename ImageReader::OutputImageType::Pointer readImage( const FileNameString& fileName, ImageSeriesReadStyle::Type readStyle, bool rescaleImage, typename ImageReader::RescaleValueType rescaleMin, typename ImageReader::RescaleValueType rescaleMax, unsigned int upperNumericSeriesLimit, typename ImageReader::MetaDataDictionaryArrayType* pLoadedDictArray) { ImageReader reader; reader.setFileName(fileName); reader.setSeriesReadStyle(readStyle); reader.setRescaleImage(rescaleImage); reader.setRescaleMaximum(rescaleMax); reader.setRescaleMinimum(rescaleMin); reader.setUpperSeriesLimit(upperNumericSeriesLimit); typename ImageReader::OutputImageType::Pointer spResult = reader.GetOutput(); if (pLoadedDictArray) { *pLoadedDictArray = reader.getMetaDictionaryArray(); }; return spResult; }; } } } #endif diff --git a/code/io/other/rttbDVHTxtFileReader.cpp b/code/io/other/rttbDVHTxtFileReader.cpp index a126a4a..ba3590d 100644 --- a/code/io/other/rttbDVHTxtFileReader.cpp +++ b/code/io/other/rttbDVHTxtFileReader.cpp @@ -1,225 +1,226 @@ // ----------------------------------------------------------------------- // 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 #include "rttbDVHTxtFileReader.h" #include "rttbInvalidParameterException.h" #include "rttbBaseType.h" namespace rttb { namespace io { namespace other { DVHTxtFileReader::DVHTxtFileReader(FileNameString aFileName) { _fileName = aFileName; _resetFile = true; } DVHTxtFileReader::~DVHTxtFileReader() {} void DVHTxtFileReader::resetFileName(FileNameString aFileName) { _fileName = aFileName; _resetFile = true; } void DVHTxtFileReader::createDVH() { std::ifstream dvh_ifstr(this->_fileName.c_str(), std::ios::in); std::string structureLabel; std::string dvhType; int numberOfBins; DoseTypeGy prescribedDose; - double _estimated_max_dose_prescribed_dose_ratio; + double estimated_max_dose_prescribed_dose_ratio; int voxelsInStructure; std::deque dataDifferential; std::deque dataCumulative; DoseTypeGy deltaD = 0; DoseVoxelVolumeType deltaV = 0; IDType strID; IDType doseID; if (!dvh_ifstr.is_open()) { throw core::InvalidParameterException("DVH file name invalid: could not open the dvh file!"); } else { bool data_begin = false; while (!dvh_ifstr.eof()) { std::string line; std::getline(dvh_ifstr, line); if (line.find("DVH Data:") != std::string::npos) { data_begin = true; } if (data_begin && (line.find(",") != std::string::npos)) { std::stringstream ss(line.substr(line.find(",") + 1)); DoseCalcType dvh_i; ss >> dvh_i; if (dvhType == "DIFFERENTIAL") { dataDifferential.push_back(dvh_i); } else if (dvhType == "CUMULATIVE") { dataCumulative.push_back(dvh_i); } } if (line.find("DeltaD: ") != std::string::npos) { std::stringstream ss(line.substr(8)); ss >> deltaD; } if (line.find("DeltaV: ") != std::string::npos) { std::stringstream ss(line.substr(8)); ss >> deltaV; } if (line.find("StructureID: ") != std::string::npos) { std::stringstream ss(line.substr(13)); ss >> strID; } if (line.find("DoseID: ") != std::string::npos) { std::stringstream ss(line.substr(8)); ss >> doseID; } if (line.find("Number of bins: ") != std::string::npos) { std::stringstream ss(line.substr(16)); ss >> numberOfBins; } if (line.find("Structure Label: ") != std::string::npos) { std::stringstream ss(line.substr(17)); ss >> structureLabel; } if (line.find("DVH Type: ") != std::string::npos) { std::stringstream ss(line.substr(10)); ss >> dvhType; } if (line.find("Prescribed Dose: ") != std::string::npos) { std::stringstream ss(line.substr(17)); ss >> prescribedDose; } if (line.find("Estimated_max_dose_prescribed_dose_ratio: ") != std::string::npos) { std::stringstream ss(line.substr(42)); - ss >> _estimated_max_dose_prescribed_dose_ratio; + ss >> estimated_max_dose_prescribed_dose_ratio; } if (line.find("Voxels In Structure: ") != std::string::npos) { std::stringstream ss(line.substr(21)); ss >> voxelsInStructure; } } } numberOfBins = std::max(dataDifferential.size(), dataCumulative.size()); if (dvhType == "CUMULATIVE") { DoseCalcType differentialDVHi = 0; std::deque::iterator it; - for (it = dataCumulative.begin(); it != dataCumulative.end(); it++) + for (it = dataCumulative.begin(); it != dataCumulative.end(); ++it) { if (dataDifferential.size() == numberOfBins - 1) { differentialDVHi = *it; } else { differentialDVHi = *it - *(it + 1); } + dataDifferential.push_back(differentialDVHi); } } if (numberOfBins == 0) { throw core::InvalidParameterException("Invalid dvh file: empty dvh data!"); } if (deltaD == 0) { - deltaD = prescribedDose * _estimated_max_dose_prescribed_dose_ratio / numberOfBins; + deltaD = prescribedDose * estimated_max_dose_prescribed_dose_ratio / numberOfBins; } if (deltaV == 0) { deltaV = 0.027; } if (deltaD == 0 || deltaV == 0) { throw core::InvalidParameterException("Invalid dvh file: deltaD or deltaV must not be zero!"); } _dvh = boost::make_shared(dataDifferential, deltaD, deltaV, strID, doseID); _resetFile = false; } DVHTxtFileReader::DVHPointer DVHTxtFileReader::generateDVH() { if (_resetFile) { this->createDVH(); } return _dvh; } }//end namepsace other }//end namespace io }//end namespace rttb diff --git a/code/io/other/rttbDVHXMLFileReader.cpp b/code/io/other/rttbDVHXMLFileReader.cpp index 8f25c67..e9e8126 100644 --- a/code/io/other/rttbDVHXMLFileReader.cpp +++ b/code/io/other/rttbDVHXMLFileReader.cpp @@ -1,134 +1,148 @@ // ----------------------------------------------------------------------- // 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 #include #include "rttbDVHXMLFileReader.h" #include "rttbInvalidParameterException.h" #include "rttbBaseType.h" -namespace rttb{ - namespace io{ - namespace other{ - - DVHXMLFileReader::DVHXMLFileReader(FileNameString aFileName){ - _fileName=aFileName; - _resetFile=true; +namespace rttb +{ + namespace io + { + namespace other + { + + DVHXMLFileReader::DVHXMLFileReader(FileNameString aFileName) + { + _fileName = aFileName; + _resetFile = true; } - DVHXMLFileReader::~DVHXMLFileReader(){} + DVHXMLFileReader::~DVHXMLFileReader() {} - void DVHXMLFileReader::resetFileName(FileNameString aFileName){ - _fileName=aFileName; - _resetFile=true; + void DVHXMLFileReader::resetFileName(FileNameString aFileName) + { + _fileName = aFileName; + _resetFile = true; } - void DVHXMLFileReader::createDVH(){ + void DVHXMLFileReader::createDVH() + { using boost::property_tree::ptree; ptree pt; // Load the XML file into the property tree. If reading fails // (cannot open file, parse error), an exception is thrown. - try{ + try + { read_xml(_fileName, pt); } - catch(boost::property_tree::xml_parser_error &e){ + catch (boost::property_tree::xml_parser_error& /*e*/) + { throw rttb::core::InvalidParameterException("DVH file name invalid: could not open the xml file!"); } - std::string structureLabel; std::string dvhType; int numberOfBins; - DoseTypeGy prescribedDose; - double _estimated_max_dose_prescribed_dose_ratio; - int voxelsInStructure; - std::deque dataDifferential; - std::deque dataCumulative; - - DoseTypeGy deltaD=0; - DoseVoxelVolumeType deltaV=0; + std::deque dataDifferential, dataCumulative; + + DoseTypeGy deltaD = 0; + DoseVoxelVolumeType deltaV = 0; IDType strID; IDType doseID; - - dvhType=pt.get("dvh.type"); - deltaD=pt.get("dvh.deltaD"); - deltaV=pt.get("dvh.deltaV"); - strID=pt.get("dvh.structureID"); - doseID=pt.get("dvh.doseID"); - - if(dvhType!="DIFFERENTIAL" && dvhType!="CUMULATIVE"){ + + dvhType = pt.get("dvh.type"); + deltaD = pt.get("dvh.deltaD"); + deltaV = pt.get("dvh.deltaV"); + strID = pt.get("dvh.structureID"); + doseID = pt.get("dvh.doseID"); + + if (dvhType != "DIFFERENTIAL" && dvhType != "CUMULATIVE") + { throw core::InvalidParameterException("DVH Type invalid! Only: DIFFERENTIAL/CUMULATIVE!"); } - int count=0; - BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt.get_child("dvh.data")){ - if(count%2==1){ - if(dvhType=="DIFFERENTIAL"){ - dataDifferential.push_back( boost::lexical_cast(v.second.data())); - + int count = 0; + BOOST_FOREACH(boost::property_tree::ptree::value_type & v, pt.get_child("dvh.data")) + { + if (count % 2 == 1) + { + if (dvhType == "DIFFERENTIAL") + { + dataDifferential.push_back(boost::lexical_cast(v.second.data())); + } - else if(dvhType=="CUMULATIVE"){ + else if (dvhType == "CUMULATIVE") + { dataCumulative.push_back(boost::lexical_cast(v.second.data())); } } + count++; } - numberOfBins=std::max(dataDifferential.size(),dataCumulative.size()); + numberOfBins = std::max(dataDifferential.size(), dataCumulative.size()); - if(dvhType=="CUMULATIVE")//dataDifferential should be calculated + if (dvhType == "CUMULATIVE") //dataDifferential should be calculated { DoseCalcType differentialDVHi = 0; std::deque::iterator it; - for(it=dataCumulative.begin();it!=dataCumulative.end();it++ ) + for (it = dataCumulative.begin(); it != dataCumulative.end(); ++it) { - if(dataDifferential.size()==numberOfBins-1) + if (dataDifferential.size() == numberOfBins - 1) { - differentialDVHi=*it; + differentialDVHi = *it; } - else{ - differentialDVHi = *it-*(it+1); + else + { + differentialDVHi = *it - *(it + 1); } + dataDifferential.push_back(differentialDVHi); } } - - _dvh=boost::make_shared(dataDifferential,deltaD,deltaV,strID,doseID); - _resetFile=false; + + _dvh = boost::make_shared(dataDifferential, deltaD, deltaV, strID, doseID); + _resetFile = false; } - DVHXMLFileReader::DVHPointer DVHXMLFileReader::generateDVH(){ - if(_resetFile){ + DVHXMLFileReader::DVHPointer DVHXMLFileReader::generateDVH() + { + if (_resetFile) + { this->createDVH(); } + return _dvh; } }//end namepsace other }//end namespace io }//end namespace rttb diff --git a/code/io/other/rttbDoseStatisticsXMLWriter.cpp b/code/io/other/rttbDoseStatisticsXMLWriter.cpp index 28fdc65..88beb4e 100644 --- a/code/io/other/rttbDoseStatisticsXMLWriter.cpp +++ b/code/io/other/rttbDoseStatisticsXMLWriter.cpp @@ -1,380 +1,380 @@ // ----------------------------------------------------------------------- // 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 "rttbDoseStatisticsXMLWriter.h" #include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" #include "rttbException.h" #include "boost/lexical_cast.hpp" namespace rttb { namespace io { namespace other { static const std::string xmlattrTag = ".x"; static const std::string statisticsTag = "statistics"; static const std::string columnSeparator = "@"; boost::property_tree::ptree writeDoseStatistics(DoseStatisticsPtr aDoseStatistics, DoseTypeGy aReferenceDose) { using boost::property_tree::ptree; ptree pt; rttb::core::DoseIteratorInterface::DoseIteratorPointer spDoseIterator = aDoseStatistics->getDoseIterator(); rttb::core::DoseIteratorInterface::DoseAccessorPointer spDoseAccessor = spDoseIterator->getDoseAccessor(); boost::shared_ptr< std::vector > > myResultPairs = boost::make_shared< std::vector > >(); ResultListPointer spMyResultPairs(myResultPairs); boost::shared_ptr< std::vector > > myResultPairs2 = boost::make_shared< std::vector > >(); ResultListPointer spMyResultPairs2(myResultPairs2); pt.put(statisticsTag + ".numberOfVoxels", aDoseStatistics->getNumberOfVoxels()); pt.put(statisticsTag + ".volume", aDoseStatistics->getVx(0)); pt.put(statisticsTag + ".minimum", aDoseStatistics->getMinimum(spMyResultPairs)); std::vector >::iterator pairIt = spMyResultPairs->begin(); int count = 0; for (; pairIt != spMyResultPairs->end() && count < 100 ; ++pairIt) //output max. 100 minimum { VoxelGridID voxelID = pairIt->second; pt.add(statisticsTag + ".minimum.voxelGridID", voxelID); VoxelGridIndex3D voxelIndex3D; spDoseAccessor->getGeometricInfo().convert(voxelID, voxelIndex3D); std::string voxelIndex3DStr; voxelIndex3DStr = boost::lexical_cast(voxelIndex3D.x()) + "," + boost::lexical_cast(voxelIndex3D.y()) + "," + boost::lexical_cast(voxelIndex3D.z()); pt.add(statisticsTag + ".minimum.voxelIndex3D", voxelIndex3DStr); WorldCoordinate3D worldCoor; spDoseAccessor->getGeometricInfo().indexToWorldCoordinate(voxelIndex3D, worldCoor); std::string worldCoorStr; worldCoorStr = boost::lexical_cast(worldCoor.x()) + "," + boost::lexical_cast(worldCoor.y()) + "," + boost::lexical_cast(worldCoor.z()); pt.add(statisticsTag + ".minimum.worldCoordinate", worldCoorStr); count++; } pt.put(statisticsTag + ".maximum", aDoseStatistics->getMaximum(spMyResultPairs2)); std::vector >::iterator pairIt2 = spMyResultPairs2->begin(); count = 0; for (; pairIt2 != spMyResultPairs2->end() && count < 100; ++pairIt2) //output max. 100 maximum { VoxelGridID voxelID = pairIt2->second; pt.add(statisticsTag + ".maximum.voxelGridID", voxelID); VoxelGridIndex3D voxelIndex3D; spDoseAccessor->getGeometricInfo().convert(voxelID, voxelIndex3D); std::string voxelIndex3DStr; voxelIndex3DStr = boost::lexical_cast(voxelIndex3D.x()) + "," + boost::lexical_cast(voxelIndex3D.y()) + "," + boost::lexical_cast(voxelIndex3D.z()); pt.add(statisticsTag + ".maximum.voxelIndex3D", voxelIndex3DStr); WorldCoordinate3D worldCoor; spDoseAccessor->getGeometricInfo().indexToWorldCoordinate(voxelIndex3D, worldCoor); std::string worldCoorStr; worldCoorStr = boost::lexical_cast(worldCoor.x()) + "," + boost::lexical_cast(worldCoor.y()) + "," + boost::lexical_cast(worldCoor.z()); pt.add(statisticsTag + ".maximum.worldCoordinate", worldCoorStr); count ++; } pt.put(statisticsTag + ".mean", aDoseStatistics->getMean()); pt.put(statisticsTag + ".standardDeviation", aDoseStatistics->getStdDeviation()); pt.put(statisticsTag + ".variance", aDoseStatistics->getVariance()); /*to do: x should be defined based on the user's feedback*/ //Dx boost::property_tree::ptree dxNode1; boost::property_tree::ptree dxNode2; boost::property_tree::ptree dxNode3; boost::property_tree::ptree dxNode4; boost::property_tree::ptree dxNode5; boost::property_tree::ptree dxNode6; double absoluteVolume = aDoseStatistics->getVx(0); dxNode1.put("", aDoseStatistics->getDx(absoluteVolume * 0.02)); dxNode2.put("", aDoseStatistics->getDx(absoluteVolume * 0.05)); dxNode3.put("", aDoseStatistics->getDx(absoluteVolume * 0.10)); dxNode4.put("", aDoseStatistics->getDx(absoluteVolume * 0.90)); dxNode5.put("", aDoseStatistics->getDx(absoluteVolume * 0.95)); dxNode6.put("", aDoseStatistics->getDx(absoluteVolume * 0.98)); dxNode1.put(xmlattrTag, 2); dxNode2.put(xmlattrTag, 5); dxNode3.put(xmlattrTag, 10); dxNode4.put(xmlattrTag, 90); dxNode5.put(xmlattrTag, 95); dxNode6.put(xmlattrTag, 98); pt.add_child(statisticsTag + ".Dx", dxNode1); pt.add_child(statisticsTag + ".Dx", dxNode2); pt.add_child(statisticsTag + ".Dx", dxNode3); pt.add_child(statisticsTag + ".Dx", dxNode4); pt.add_child(statisticsTag + ".Dx", dxNode5); pt.add_child(statisticsTag + ".Dx", dxNode6); if (aReferenceDose <= 0) { throw core::InvalidParameterException("aReferenceDose should be >0!"); } //Vx boost::property_tree::ptree vxNode1; boost::property_tree::ptree vxNode2; boost::property_tree::ptree vxNode3; boost::property_tree::ptree vxNode4; boost::property_tree::ptree vxNode5; boost::property_tree::ptree vxNode6; vxNode1.put("", aDoseStatistics->getVx(aReferenceDose * 0.02)); vxNode2.put("", aDoseStatistics->getVx(aReferenceDose * 0.05)); vxNode3.put("", aDoseStatistics->getVx(aReferenceDose * 0.10)); vxNode4.put("", aDoseStatistics->getVx(aReferenceDose * 0.90)); vxNode5.put("", aDoseStatistics->getVx(aReferenceDose * 0.95)); vxNode6.put("", aDoseStatistics->getVx(aReferenceDose * 0.98)); vxNode1.put(xmlattrTag, 2); vxNode2.put(xmlattrTag, 5); vxNode3.put(xmlattrTag, 10); vxNode4.put(xmlattrTag, 90); vxNode5.put(xmlattrTag, 95); vxNode6.put(xmlattrTag, 98); pt.add_child(statisticsTag + ".Vx", vxNode1); pt.add_child(statisticsTag + ".Vx", vxNode2); pt.add_child(statisticsTag + ".Vx", vxNode3); pt.add_child(statisticsTag + ".Vx", vxNode4); pt.add_child(statisticsTag + ".Vx", vxNode5); pt.add_child(statisticsTag + ".Vx", vxNode6); //MOHx boost::property_tree::ptree mohxNode1; boost::property_tree::ptree mohxNode2; boost::property_tree::ptree mohxNode3; mohxNode1.put("", aDoseStatistics->getMOHx(absoluteVolume * 0.02)); mohxNode2.put("", aDoseStatistics->getMOHx(absoluteVolume * 0.05)); mohxNode3.put("", aDoseStatistics->getMOHx(absoluteVolume * 0.10)); mohxNode1.put(xmlattrTag, 2); mohxNode2.put(xmlattrTag, 5); mohxNode3.put(xmlattrTag, 10); pt.add_child(statisticsTag + ".MOHx", mohxNode1); pt.add_child(statisticsTag + ".MOHx", mohxNode2); pt.add_child(statisticsTag + ".MOHx", mohxNode3); //MOCx boost::property_tree::ptree mocxNode1; boost::property_tree::ptree mocxNode2; boost::property_tree::ptree mocxNode3; mocxNode1.put("", aDoseStatistics->getMOCx(absoluteVolume * 0.02)); mocxNode2.put("", aDoseStatistics->getMOCx(absoluteVolume * 0.05)); mocxNode3.put("", aDoseStatistics->getMOCx(absoluteVolume * 0.10)); mocxNode1.put(xmlattrTag, 2); mocxNode2.put(xmlattrTag, 5); mocxNode3.put(xmlattrTag, 10); pt.add_child(statisticsTag + ".MOCx", mocxNode1); pt.add_child(statisticsTag + ".MOCx", mocxNode2); pt.add_child(statisticsTag + ".MOCx", mocxNode3); //MaxOHx boost::property_tree::ptree maxohxNode1; boost::property_tree::ptree maxohxNode2; boost::property_tree::ptree maxohxNode3; maxohxNode1.put("", aDoseStatistics->getMaxOHx(absoluteVolume * 0.02)); maxohxNode2.put("", aDoseStatistics->getMaxOHx(absoluteVolume * 0.05)); maxohxNode3.put("", aDoseStatistics->getMaxOHx(absoluteVolume * 0.10)); maxohxNode1.put(xmlattrTag, 2); maxohxNode2.put(xmlattrTag, 5); maxohxNode3.put(xmlattrTag, 10); pt.add_child(statisticsTag + ".MaxOHx", maxohxNode1); pt.add_child(statisticsTag + ".MaxOHx", maxohxNode2); pt.add_child(statisticsTag + ".MaxOHx", maxohxNode3); //MinOCx boost::property_tree::ptree minocxNode1; boost::property_tree::ptree minocxNode2; boost::property_tree::ptree minocxNode3; minocxNode1.put("", aDoseStatistics->getMinOCx(absoluteVolume * 0.02)); minocxNode2.put("", aDoseStatistics->getMinOCx(absoluteVolume * 0.05)); minocxNode3.put("", aDoseStatistics->getMinOCx(absoluteVolume * 0.10)); minocxNode1.put(xmlattrTag, 2); minocxNode2.put(xmlattrTag, 5); minocxNode3.put(xmlattrTag, 10); pt.add_child(statisticsTag + ".MinOCx", minocxNode1); pt.add_child(statisticsTag + ".MinOCx", minocxNode2); pt.add_child(statisticsTag + ".MinOCx", minocxNode3); return pt; } void writeDoseStatistics(DoseStatisticsPtr aDoseStatistics, FileNameString aFileName, DoseTypeGy aReferenceDose) { boost::property_tree::ptree pt = writeDoseStatistics(aDoseStatistics, aReferenceDose); try { boost::property_tree::xml_parser::write_xml(aFileName, pt); } - catch (boost::property_tree::xml_parser_error& e) + catch (boost::property_tree::xml_parser_error& /*e*/) { throw core::InvalidParameterException("Write xml failed: xml_parser_error!"); } } XMLString writerDoseStatisticsToString(DoseStatisticsPtr aDoseStatistics, DoseTypeGy aReferenceDose) { boost::property_tree::ptree pt = writeDoseStatistics(aDoseStatistics, aReferenceDose); std::stringstream sstr; try { boost::property_tree::xml_parser::write_xml(sstr, pt); } - catch (boost::property_tree::xml_parser_error& e) + catch (boost::property_tree::xml_parser_error& /*e*/) { throw core::InvalidParameterException("Write xml to string failed: xml_parser_error!"); } return sstr.str(); } StatisticsString writerDoseStatisticsToTableString(DoseStatisticsPtr aDoseStatistics, DoseTypeGy aReferenceDose) { std::stringstream sstr; rttb::core::DoseIteratorInterface::DoseIteratorPointer spDoseIterator = aDoseStatistics->getDoseIterator(); rttb::core::DoseIteratorInterface::DoseAccessorPointer spDoseAccessor = spDoseIterator->getDoseAccessor(); boost::shared_ptr< std::vector > > myResultPairs = boost::make_shared< std::vector > >(); ResultListPointer spMyResultPairs(myResultPairs); boost::shared_ptr< std::vector > > myResultPairs2 = boost::make_shared< std::vector > >(); ResultListPointer spMyResultPairs2(myResultPairs2); sstr << aDoseStatistics->getVx(0) * 1000 << columnSeparator; // cm3 to mm3 sstr << aDoseStatistics->getMaximum(spMyResultPairs2) << columnSeparator; sstr << aDoseStatistics->getMinimum(spMyResultPairs) << columnSeparator; sstr << aDoseStatistics->getMean() << columnSeparator; sstr << aDoseStatistics->getStdDeviation() << columnSeparator; sstr << aDoseStatistics->getVariance() << columnSeparator; /*to do: x should be defined based on the user's feedback*/ if (aReferenceDose <= 0) { throw core::InvalidParameterException("aReferenceDose should be >0!"); } //Vx sstr << aDoseStatistics->getVx(aReferenceDose * 0.02) * 1000 << columnSeparator; // cm3 to mm3 sstr << aDoseStatistics->getVx(aReferenceDose * 0.05) * 1000 << columnSeparator; // cm3 to mm3 sstr << aDoseStatistics->getVx(aReferenceDose * 0.10) * 1000 << columnSeparator; // cm3 to mm3 sstr << aDoseStatistics->getVx(aReferenceDose * 0.90) * 1000 << columnSeparator; // cm3 to mm3 sstr << aDoseStatistics->getVx(aReferenceDose * 0.95) * 1000 << columnSeparator; // cm3 to mm3 sstr << aDoseStatistics->getVx(aReferenceDose * 0.98) * 1000 << columnSeparator; // cm3 to mm3 //Dx double absoluteVolume = aDoseStatistics->getVx(0); sstr << aDoseStatistics->getDx(absoluteVolume * 0.02) << columnSeparator; sstr << aDoseStatistics->getDx(absoluteVolume * 0.05) << columnSeparator; sstr << aDoseStatistics->getDx(absoluteVolume * 0.10) << columnSeparator; sstr << aDoseStatistics->getDx(absoluteVolume * 0.90) << columnSeparator; sstr << aDoseStatistics->getDx(absoluteVolume * 0.95) << columnSeparator; sstr << aDoseStatistics->getDx(absoluteVolume * 0.98) << columnSeparator; //MOHx sstr << aDoseStatistics->getMOHx(absoluteVolume * 0.02) << columnSeparator; sstr << aDoseStatistics->getMOHx(absoluteVolume * 0.05) << columnSeparator; sstr << aDoseStatistics->getMOHx(absoluteVolume * 0.10) << columnSeparator; //MOCx sstr << aDoseStatistics->getMOCx(absoluteVolume * 0.02) << columnSeparator; sstr << aDoseStatistics->getMOCx(absoluteVolume * 0.05) << columnSeparator; sstr << aDoseStatistics->getMOCx(absoluteVolume * 0.10) << columnSeparator; //MaxOHx sstr << aDoseStatistics->getMaxOHx(absoluteVolume * 0.02) << columnSeparator; sstr << aDoseStatistics->getMaxOHx(absoluteVolume * 0.05) << columnSeparator; sstr << aDoseStatistics->getMaxOHx(absoluteVolume * 0.10) << columnSeparator; //MinOCx sstr << aDoseStatistics->getMinOCx(absoluteVolume * 0.02) << columnSeparator; sstr << aDoseStatistics->getMinOCx(absoluteVolume * 0.05) << columnSeparator; sstr << aDoseStatistics->getMinOCx(absoluteVolume * 0.10) << columnSeparator; return sstr.str(); } } } } \ No newline at end of file diff --git a/code/io/virtuos/rttbVirtuosDoseAccessor.cpp b/code/io/virtuos/rttbVirtuosDoseAccessor.cpp index 90f6e3f..d302bc4 100644 --- a/code/io/virtuos/rttbVirtuosDoseAccessor.cpp +++ b/code/io/virtuos/rttbVirtuosDoseAccessor.cpp @@ -1,230 +1,230 @@ // ----------------------------------------------------------------------- // 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 "rttbVirtuosDoseAccessor.h" #include "rttbNullPointerException.h" #include "rttbInvalidDoseException.h" #include "rttbInvalidParameterException.h" #include "rttbIndexOutOfBoundsException.h" //VIRTUOS #include "pln1file.h" #include "plt_type.h" #include "rtp_type.h" namespace rttb { namespace io { namespace virtuos { VirtuosDoseAccessor::~VirtuosDoseAccessor() { if (_freeVirtuosData) { this->freeVirtuosData(); } } VirtuosDoseAccessor::VirtuosDoseAccessor(Cubeinfo* aPointerOnVirtuosCube, bool freeVirtuosData, DoseTypeGy normalizationDose, DoseTypeGy prescribedDose): _pPointerOnVirtuosCube(new Cubeinfo*), _freeVirtuosData(freeVirtuosData), _doseGridScaling(0), _doseUID(""), _doseScalingFactor(0) { //initialize cube pointer *_pPointerOnVirtuosCube = create_cubeinfo(0); *_pPointerOnVirtuosCube = aPointerOnVirtuosCube; _prescribedDose = prescribedDose; _normalizationDose = normalizationDose; if (_prescribedDose == 0) { _prescribedDose = 1; } if (_normalizationDose == 0) { _normalizationDose = 1; } _doseScalingFactor = _prescribedDose / _normalizationDose; std::cout << "Prescribed dose: " << _prescribedDose << std::endl; std::cout << "Normalization dose: " << _normalizationDose << std::endl; //dose import this->begin(); } - bool VirtuosDoseAccessor::begin() + void VirtuosDoseAccessor::begin() { if (!_pPointerOnVirtuosCube) { throw core::NullPointerException(" *_pPointerOnVirtuosCube must not be NULL!"); } assembleGeometricInfo(); //load data if ((*_pPointerOnVirtuosCube)->data_type == 1) { this->importPixelData(); } else if ((*_pPointerOnVirtuosCube)->data_type == 2) { this->importPixelData(); } else { throw core::InvalidParameterException(" cube has wrong data type!"); } } template void VirtuosDoseAccessor::importPixelData() { doseData.clear(); int dimX = (*_pPointerOnVirtuosCube)->dimx; int dimY = (*_pPointerOnVirtuosCube)->dimy; int dimZ = (*_pPointerOnVirtuosCube)->dimz; GridVolumeType pixelSpacing = (*_pPointerOnVirtuosCube)->pixdist; GridVolumeType sliceThickness = (*_pPointerOnVirtuosCube)->slicedist; TPixelType** * access_pointer = (TPixelType***)(*_pPointerOnVirtuosCube)->cube_direct_access; for (int k = 0; k < dimZ; k++) { for (int j = 0; j < dimY; j++) { for (int i = 0; i < dimX; i++) { TPixelType voxel_value = access_pointer[k][j][i]; doseData.push_back(voxel_value * _doseScalingFactor); } }//end for j }//end for k } void VirtuosDoseAccessor::assembleGeometricInfo() { if (!_pPointerOnVirtuosCube) { throw core::NullPointerException(" _pPointerOnVirtuosCube must not be NULL!"); } _geoInfo.setNumColumns((*_pPointerOnVirtuosCube)->dimx); _geoInfo.setNumRows((*_pPointerOnVirtuosCube)->dimy); _geoInfo.setNumSlices((*_pPointerOnVirtuosCube)->dimz); if (_geoInfo.getNumColumns() == 0 || _geoInfo.getNumRows() == 0 || _geoInfo.getNumSlices() == 0) { throw core::InvalidDoseException("Empty Virtuos dose!") ; } OrientationMatrix orientation; _geoInfo.setOrientationMatrix(orientation); WorldCoordinate3D imagePositionPatient; imagePositionPatient(0) = (*this->_pPointerOnVirtuosCube)->pixdist / 2; imagePositionPatient(1) = (*this->_pPointerOnVirtuosCube)->pixdist / 2; if (!((*this->_pPointerOnVirtuosCube)->pos_list)) { throw core::InvalidDoseException("Empty Virtuos dose!") ; } imagePositionPatient(2) = (*this->_pPointerOnVirtuosCube)->pos_list[0].position; _geoInfo.setImagePositionPatient(imagePositionPatient); SpacingVectorType3D spacingVector; spacingVector(0) = (*_pPointerOnVirtuosCube)->pixdist; spacingVector(1) = (*_pPointerOnVirtuosCube)->pixdist; _geoInfo.setSpacing(spacingVector); if (_geoInfo.getPixelSpacingRow() == 0 || _geoInfo.getPixelSpacingColumn() == 0) { throw core::InvalidDoseException("Pixel spacing = 0!"); } spacingVector(2) = (*_pPointerOnVirtuosCube)->slicedist; if (spacingVector(2) == 0) { std::cerr << "sliceThickness == 0! It will be replaced with pixelSpacingRow=" << _geoInfo.getPixelSpacingRow() << "!" << std::endl; spacingVector(2) = spacingVector(0); } _geoInfo.setSpacing(spacingVector); } DoseTypeGy VirtuosDoseAccessor::getDoseAt(const VoxelGridID aID) const { return doseData.at(aID); } DoseTypeGy VirtuosDoseAccessor::getDoseAt(const VoxelGridIndex3D& aIndex) const { VoxelGridID aVoxelGridID; if (_geoInfo.convert(aIndex, aVoxelGridID)) { return getDoseAt(aVoxelGridID); } else { return -1; } } void VirtuosDoseAccessor::freeVirtuosData() { if (*(this->_pPointerOnVirtuosCube) != NULL) { closecube((*(this->_pPointerOnVirtuosCube))); nc_free_cubeinfo((*(this->_pPointerOnVirtuosCube))); delete this->_pPointerOnVirtuosCube; // initialize attributes again //this->_pPointerOnVirtuosCube = new Cubeinfo*; //*(this->_pPointerOnVirtuosCube) = create_cubeinfo(0); } } } } } diff --git a/code/io/virtuos/rttbVirtuosDoseAccessor.h b/code/io/virtuos/rttbVirtuosDoseAccessor.h index 8876c15..bdcf93d 100644 --- a/code/io/virtuos/rttbVirtuosDoseAccessor.h +++ b/code/io/virtuos/rttbVirtuosDoseAccessor.h @@ -1,129 +1,129 @@ // ----------------------------------------------------------------------- // 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 __VIRTUOS_DOSE_ACCESSOR_H #define __VIRTUOS_DOSE_ACCESSOR_H #include #include #include #include "rttbDoseAccessorInterface.h" #include "rttbGeometricInfo.h" #include "rttbBaseType.h" #include "ncfile.h" namespace rttb { namespace io { namespace virtuos { /*! @class VirtuosDoseAccessor @brief This class gives access to dose information from Virtuos Cubeinfo */ class VirtuosDoseAccessor: public core::DoseAccessorInterface { private: Cubeinfo** _pPointerOnVirtuosCube; /*! absolute Gy dose/doseGridScaling*/ std::vector doseData; double _doseGridScaling; IDType _doseUID; DoseTypeGy _prescribedDose; DoseTypeGy _normalizationDose; DoseTypeGy _doseScalingFactor; bool _freeVirtuosData;//if virtuos cube info should be closed /*! close virtuos data cube. */ void freeVirtuosData(); /*! load actual pixel data from virtuos cube to doseData. TPixelType is usually int but may be float for special virtuos cubes (data_type = 2). @pre virtuos cube contains data (dimensions are at least 1) */ template void importPixelData(); protected: /*! @brief import dose data and relevant geometric information @throw NullPointerException Thrown if _pPointerOnVirtuosCube is NULL @throw InvalidDoseException Thrown if one dimension of the virtuos cube is zero @throw InvalidParameterException Thrown if _pPointerOnVirtuosCube is invalid */ - bool begin(); + void begin(); /*! @brief get all required geometrical data from virtuos cube */ void assembleGeometricInfo(); public: ~VirtuosDoseAccessor(); /*! @brief Constructor. Initialisation with a Cubeinfo pointer. @param normalizationDose is defined as (prescribedDose*1000)/maxDoseInGy. Default is 1 Gy. @param prescribedDose the does that was planned in the reference point in Gy. Default is 1 Gy. @param freeVirtuoData If virtuos cube info should be closed, freeVirtuosData should be true. @throw NullPointerException Thrown if _pPointerOnVirtuosCube is NULL @throw InvalidDoseException Thrown if one dimension of the virtuos cube is zero @throw InvalidParameterException Thrown if aPointerOnVirtuosCube is invalid */ VirtuosDoseAccessor(Cubeinfo* aPointerOnVirtuosCube, bool freeVirtuosData, DoseTypeGy normalizationDose = 1, DoseTypeGy prescribedDose = 1); DoseTypeGy getDoseAt(const VoxelGridID aID) const; /*! @return dose value at given grid position. If position is invalid return -1 */ DoseTypeGy getDoseAt(const VoxelGridIndex3D& aIndex) const; const IDType getDoseUID() const { return _doseUID; }; const DoseTypeGy getPrescribedDose() const { return _prescribedDose; }; const DoseTypeGy getNormalizationDose() const { return _normalizationDose; }; }; } } } #endif diff --git a/code/io/virtuos/rttbVirtuosFileStructureSetGenerator.cpp b/code/io/virtuos/rttbVirtuosFileStructureSetGenerator.cpp index e71b8b4..4453304 100644 --- a/code/io/virtuos/rttbVirtuosFileStructureSetGenerator.cpp +++ b/code/io/virtuos/rttbVirtuosFileStructureSetGenerator.cpp @@ -1,200 +1,236 @@ // ----------------------------------------------------------------------- // 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 #include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" #include "rttbStructure.h" #include "rttbVirtuosFileStructureSetGenerator.h" -namespace rttb{ - namespace io{ - namespace virtuos{ - - VirtuosFileStructureSetGenerator::VirtuosFileStructureSetGenerator(FileNameType aVirtuosVDXFileName, FileNameType aVirtuosCTXFileName) +namespace rttb +{ + namespace io + { + namespace virtuos + { + + VirtuosFileStructureSetGenerator::VirtuosFileStructureSetGenerator(FileNameType aVirtuosVDXFileName, + FileNameType aVirtuosCTXFileName) : _pPointerOnVirtuosCube(new Cubeinfo*), _patient(NULL) - { - _VDXFileName=aVirtuosVDXFileName; - _CTXFileName=aVirtuosCTXFileName; + { + _VDXFileName = aVirtuosVDXFileName; + _CTXFileName = aVirtuosCTXFileName; //check if file names are valid - if (!boost::filesystem::exists(_VDXFileName)){ + if (!boost::filesystem::exists(_VDXFileName)) + { throw core::InvalidParameterException("invalid vdx file name"); } - if (!boost::filesystem::exists(_CTXFileName)){ + + if (!boost::filesystem::exists(_CTXFileName)) + { throw core::InvalidParameterException("invalid ctx file name"); } + *_pPointerOnVirtuosCube = create_cubeinfo(0); this->initializeVirtuosCube(_CTXFileName); - + } VirtuosFileStructureSetGenerator::~VirtuosFileStructureSetGenerator() { - if(this->_patient!=NULL) + if (this->_patient != NULL) { delete this->_patient; } + closecube((*(this->_pPointerOnVirtuosCube))); nc_free_cubeinfo((*(this->_pPointerOnVirtuosCube))); delete this->_pPointerOnVirtuosCube; } - void VirtuosFileStructureSetGenerator::importStructureSet(FileNameType aVirtuosVDXFileName, FileNameType aVirtuosCTXFileName) + void VirtuosFileStructureSetGenerator::importStructureSet(FileNameType aVirtuosVDXFileName, + FileNameType aVirtuosCTXFileName) { //check file name - if(aVirtuosCTXFileName.empty() || aVirtuosVDXFileName.empty()) + if (aVirtuosCTXFileName.empty() || aVirtuosVDXFileName.empty()) + { throw core::InvalidParameterException("Virtuos VDX/CTX file name must not be empty!"); + } + int vdxPosition = aVirtuosVDXFileName.find(".vdx"); - if(vdxPosition == std::string::npos) + + if (vdxPosition == std::string::npos) + { throw core::InvalidParameterException("Virtuos VDX file name must be *.vdx!"); + } //get patientFileName, patientDataPath for Virtuos function std::string patientFileName, patientName, patientDataPath; - patientFileName.assign(aVirtuosVDXFileName,aVirtuosVDXFileName.find_last_of("/")+1, aVirtuosVDXFileName.length()); - patientName.assign(patientFileName,0,patientFileName.find_first_of(".")); - patientDataPath.assign(aVirtuosVDXFileName,0,aVirtuosVDXFileName.find_last_of("/")+1); + patientFileName.assign(aVirtuosVDXFileName, aVirtuosVDXFileName.find_last_of("/") + 1, aVirtuosVDXFileName.length()); + patientName.assign(patientFileName, 0, patientFileName.find_first_of(".")); + patientDataPath.assign(aVirtuosVDXFileName, 0, aVirtuosVDXFileName.find_last_of("/") + 1); //Virtuos: voi create voi model - int errorcode = voi_create_voi_model_dirolab(patientName.c_str(),patientDataPath.c_str(),0, this->_patient); + int errorcode = voi_create_voi_model_dirolab(patientName.c_str(), patientDataPath.c_str(), 0, this->_patient); + //@todo soll wohl trotz Fehler weiter laufen (vgl. alte Implementierung) - if(errorcode!=0) { + if (errorcode != 0) + { //throw std::string ("Virtuos Routines unable to create VOI Model! "); - std::cerr << "voi_create_voi_model_dirolab error: error code "<_patient); + errorcode = voi_read_vdx_version_2_for_DIROlab(patientFileName.c_str(), patientDataPath.c_str(), this->_patient); //@todo soll wohl trotz Fehler weiter laufen (vgl. alte Implementierung) - if(errorcode!=0){ + if (errorcode != 0) + { //throw std::string ("voi_read_vdx_version_2_for_DIROlab failed! "); - std::cerr << "voi_read_vdx_version_2_for_DIROlab error: error code "<_patient->getNumberOfVois(); + int numberOfVois = this->_patient->getNumberOfVois(); - float firstSliceInFrame=(*_pPointerOnVirtuosCube)->pos_list[0].position; + float firstSliceInFrame = (*_pPointerOnVirtuosCube)->pos_list[0].position; - double sliceThickness=(*_pPointerOnVirtuosCube)->slicedist; + double sliceThickness = (*_pPointerOnVirtuosCube)->slicedist; - float lastSliceInFrame=((*_pPointerOnVirtuosCube)->dimz-1)*sliceThickness+firstSliceInFrame; + float lastSliceInFrame = ((*_pPointerOnVirtuosCube)->dimz - 1) * sliceThickness + firstSliceInFrame; - for(int currentVoiNumber = 0; currentVoiNumber < numberOfVois; currentVoiNumber++) + for (int currentVoiNumber = 0; currentVoiNumber < numberOfVois; currentVoiNumber++) { - std::string voiName =""; + std::string voiName = ""; char tmpVoiName[1024]; - voi_get_voi_name_by_index_dirolab(currentVoiNumber,1024,tmpVoiName,this->_patient); + voi_get_voi_name_by_index_dirolab(currentVoiNumber, 1024, tmpVoiName, this->_patient); voiName.assign(tmpVoiName); /* prepare contour extraction */ D3PointList* contours = NULL; contours = d3_list_create(1000000); - D3Point origin = {0,0,0}, y_axis_point = {0,0,0}, x_axis_point = {0,0,0}; + D3Point origin = {0, 0, 0}, y_axis_point = {0, 0, 0}, x_axis_point = {0, 0, 0}; int maxNumberOfContours = 100000; - int *pNoOFContours = &maxNumberOfContours; + int* pNoOFContours = &maxNumberOfContours; PolygonSequenceType polygonSequence; - for(float z=firstSliceInFrame; z<=lastSliceInFrame; z+=sliceThickness){ + + for (float z = firstSliceInFrame; z <= lastSliceInFrame; z += sliceThickness) + { origin.x = 0.0; origin.y = 0.0; origin.z = z ; x_axis_point.x = 1.0; x_axis_point.y = 0.0; x_axis_point.z = z ; y_axis_point.x = 0.0; y_axis_point.y = 1.0; y_axis_point.z = z; *pNoOFContours = 100000; //<-- reason is the next function call - int errorcode = voi_get_CT_contours_dirolab(voiName.c_str(), origin, x_axis_point, y_axis_point, pNoOFContours, &contours, 1,this->_patient); + voi_get_CT_contours_dirolab(voiName.c_str(), origin, x_axis_point, y_axis_point, pNoOFContours, &contours, 1, + this->_patient); - for(int i=0;i<*pNoOFContours; i++){ + for (int i = 0; i < *pNoOFContours; i++) + { PolygonType polygon; - for(int j=0;j spStruct = boost::make_shared(polygonSequence); spStruct->setLabel(voiName); _strVector.push_back(spStruct); }//end for currentVoiNumber } void VirtuosFileStructureSetGenerator::initializeVirtuosCube(FileNameType aVirtuosCTXFileName) { - if(aVirtuosCTXFileName.empty()){ - throw core::InvalidParameterException("Empty File Name");} + if (aVirtuosCTXFileName.empty()) + { + throw core::InvalidParameterException("Empty File Name"); + } int gzPosition = aVirtuosCTXFileName.find(".gz"); - if(gzPosition != std::string::npos){ + + if (gzPosition != std::string::npos) + { aVirtuosCTXFileName.erase(gzPosition, aVirtuosCTXFileName.length()); } + nc_init_cubeinfo(*_pPointerOnVirtuosCube); int opencubeErrorCode = opencube(aVirtuosCTXFileName.c_str() , *_pPointerOnVirtuosCube); - if(opencubeErrorCode != 0) - { + + if (opencubeErrorCode != 0) + { std::stringstream opencubeErrorCodeAsStringStream; - opencubeErrorCodeAsStringStream<dimx == 0 || (*_pPointerOnVirtuosCube)->dimy == 0 || (*_pPointerOnVirtuosCube)->dimz == 0){ + if ((*_pPointerOnVirtuosCube)->dimx == 0 || (*_pPointerOnVirtuosCube)->dimy == 0 + || (*_pPointerOnVirtuosCube)->dimz == 0) + { throw core::InvalidParameterException("Invalid Cube dimension: dimX/dimY/dimZ must not be zero! "); } } - VirtuosFileStructureSetGenerator::StructureSetPointer VirtuosFileStructureSetGenerator::generateStructureSet(){ - + VirtuosFileStructureSetGenerator::StructureSetPointer VirtuosFileStructureSetGenerator::generateStructureSet() + { + this->importStructureSet(_VDXFileName, _CTXFileName); return boost::make_shared(_strVector); } }//end namespace virtuos }//end namespace io }//end namespace rttb diff --git a/code/masks/rttbGenericMutableMaskAccessor.cpp b/code/masks/rttbGenericMutableMaskAccessor.cpp index 07cc417..ee4c285 100644 --- a/code/masks/rttbGenericMutableMaskAccessor.cpp +++ b/code/masks/rttbGenericMutableMaskAccessor.cpp @@ -1,178 +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 "rttbGenericMutableMaskAccessor.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); // filter relevant voxels GenericMutableMaskAccessor::MaskVoxelList::iterator it = _spRelevantVoxelVector->begin(); while (it != _spRelevantVoxelVector->end()) { if ((*it).getRelevantVolumeFraction() > lowerThreshold) { filteredVoxelVectorPointer->push_back(*it); } - 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++; + ++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++; + ++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/code/models/rttbBioModel.h b/code/models/rttbBioModel.h index 00c318d..4ba5115 100644 --- a/code/models/rttbBioModel.h +++ b/code/models/rttbBioModel.h @@ -1,90 +1,92 @@ // ----------------------------------------------------------------------- // 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 __BIO_MODEL_H #define __BIO_MODEL_H #include "rttbBaseType.h" #include "rttbDVH.h" #include "rttbBaseTypeModels.h" -namespace rttb{ +namespace rttb +{ - namespace models{ + namespace models + { /*! @class BioModel @brief This is the interface class for biological models */ class BioModel - { - public: - typedef std::vector ParamVectorType; - typedef core::DVH::DVHPointer DVHPointer; + { + public: + typedef std::vector ParamVectorType; + typedef core::DVH::DVHPointer DVHPointer; - protected: - DVHPointer _dvh; + protected: + DVHPointer _dvh; - BioModelValueType _value; + BioModelValueType _value; - /*! @brief Calculate the model value - @param doseFactor scaling factor for the dose. The model calculation will use the dvh with each di=old - di*doseFactor. - */ - virtual BioModelValueType calcModel(const double doseFactor=1)=0; + /*! @brief Calculate the model value + @param doseFactor scaling factor for the dose. The model calculation will use the dvh with each di=old + di*doseFactor. + */ + virtual BioModelValueType calcModel(const double doseFactor = 1) = 0; - public: - BioModel(): _value(0){}; - BioModel(DVHPointer aDvh): _dvh(aDvh), _value(0){}; + public: + BioModel(): _value(0) {}; + BioModel(DVHPointer aDvh): _dvh(aDvh), _value(0) {}; - /*! @brief Start the calculation. If any parameter changed, init() should be called again and return =true - before getValue() is called! - @return Return true if successful - */ - bool init(const double doseFactor=1); + /*! @brief Start the calculation. If any parameter changed, init() should be called again and return =true + before getValue() is called! + @return Return true if successful + */ + bool init(const double doseFactor = 1); - /*! @param aDVH must be a DVH calculated by a cumulative dose distribution, not a fraction DVH! - */ - void setDVH(const DVHPointer aDVH); + /*! @param aDVH must be a DVH calculated by a cumulative dose distribution, not a fraction DVH! + */ + void setDVH(const DVHPointer aDVH); - const DVHPointer getDVH() const; + const DVHPointer getDVH() const; - /*! @brief Set parameter vector, where index of vector is the parameter ID. - */ - virtual void setParameterVector(const ParamVectorType aParameterVector)=0; + /*! @brief Set parameter vector, where index of vector is the parameter ID. + */ + virtual void setParameterVector(const ParamVectorType& aParameterVector) = 0; - virtual void setParameterByID(const int aParamId, const BioModelParamType aValue)=0; + virtual void setParameterByID(const int aParamId, const BioModelParamType aValue) = 0; - /*! @brief Get parameter by ID. - @return Return -1 if ID is not found. - */ - virtual const int getParameterID(const std::string aParamName) const=0; + /*! @brief Get parameter by ID. + @return Return -1 if ID is not found. + */ + virtual const int getParameterID(const std::string& aParamName) const = 0; - /*! @brief Get the value of biological model - @pre init() must be called and =true! - */ - const BioModelValueType getValue() const; - }; + /*! @brief Get the value of biological model + @pre init() must be called and =true! + */ + const BioModelValueType getValue() const; + }; - }//end namespace models - }//end namespace rttb + }//end namespace models +}//end namespace rttb #endif diff --git a/code/models/rttbBioModelScatterPlots.cpp b/code/models/rttbBioModelScatterPlots.cpp index e85d567..0918a14 100644 --- a/code/models/rttbBioModelScatterPlots.cpp +++ b/code/models/rttbBioModelScatterPlots.cpp @@ -1,221 +1,219 @@ // ----------------------------------------------------------------------- // 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 "rttbBioModelScatterPlots.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace models { /* Initiate Random Number generator with current time */ boost::random::mt19937 rng(static_cast(time(0))); /* Generate random number between 0 and 1 */ boost::random::uniform_01 uniDist(rng); ScatterPlotType getScatterPlotVary1Parameter(BioModel& aModel, int aParamId, BioModelParamType aMean, BioModelParamType aVariance, DoseTypeGy aNormalisationDose, int numberOfPoints, DoseTypeGy aMinDose, DoseTypeGy aMaxDose) { ScatterPlotType scatterPlotData; if (aVariance == 0) { //set to small positive value to avoid negative infinity! aVariance = 1e-30; } if (aMaxDose <= aMinDose) { throw core::InvalidParameterException("Parameter invalid: aMaxDose must be > aMinDose!"); } if (aNormalisationDose <= 0) { throw core::InvalidParameterException("Parameter invalid: aNormalisationDose must be > 0!"); } /* Choose Normal Distribution */ boost::random::normal_distribution gaussian_dist(0, aVariance); /* Create a Gaussian Random Number generator * by binding with previously defined * normal distribution object */ boost::random::variate_generator > generator( rng, gaussian_dist); - double paramValue; - double probability; int i = 0; while (i < numberOfPoints) { + double paramValue, probability; double randomValue = generator(); paramValue = randomValue + aMean; probability = normal_pdf(randomValue, aVariance); if (probability > 1) { probability = 1; } //randomly select a dose between aMinDose and aMaxDose double dose = uniDist() * (aMaxDose - aMinDose) + aMinDose; if (probability > 0) { try { aModel.setParameterByID(aParamId, paramValue); aModel.init(dose / aNormalisationDose); double value = aModel.getValue(); std::pair modelProbPair = std::make_pair(value, probability); scatterPlotData.insert(std::pair >(dose, modelProbPair)); i++; } - catch (core::InvalidParameterException e) + catch (core::InvalidParameterException& /*e*/) { //repeat evaluation to guarantee the correct number of scatter values continue; } } } return scatterPlotData; } double normal_pdf(double aValue, double aVariance) { static const float inv_sqrt_2pi = 0.3989422804014327; double a = (aValue) / aVariance; return inv_sqrt_2pi / aVariance * std::exp(-0.5f * a * a); } ScatterPlotType getScatterPlotVaryParameters(BioModel& aModel, std::vector aParamIdVec, BioModel::ParamVectorType aMeanVec, BioModel::ParamVectorType aVarianceVec, DoseTypeGy aNormalisationDose, int numberOfPoints, DoseTypeGy aMinDose, DoseTypeGy aMaxDose) { ScatterPlotType scatterPlotData; if (aMaxDose <= aMinDose) { throw core::InvalidParameterException("Parameter invalid: aMaxDose must be > aMinDose!"); } if (aNormalisationDose <= 0) { throw core::InvalidParameterException("Parameter invalid: aNormalisationDose must be > 0!"); } //all input vectors need to have the same size if (((aVarianceVec.size() != aMeanVec.size()) || (aVarianceVec.size() != aParamIdVec.size()))) { throw core::InvalidParameterException("Parameter vectors have different sizes!"); } for (GridIndexType v = 0; v < aVarianceVec.size(); v++) { //set to small positive value to avoid negative infinity! if (aVarianceVec.at(v) == 0) { aVarianceVec.at(v) = 1e-30; } } double paramValue; - double probability; // vary all parameters for each scattered point int i = 0; while (i < numberOfPoints) { - probability = 1; + double probability = 1; for (GridIndexType j = 0; j < aParamIdVec.size(); j++) { /* Choose Normal Distribution */ boost::random::normal_distribution gaussian_dist(0, aVarianceVec.at(j)); /* Create a Gaussian Random Number generator * by binding with previously defined * normal distribution object */ boost::random::variate_generator > generator( rng, gaussian_dist); double randomValue = generator(); paramValue = randomValue + aMeanVec.at(j); if (aVarianceVec.at(j) != 0) { /* calculate combined probability */ probability = probability * normal_pdf(randomValue, aVarianceVec.at(j)); } else { throw core::InvalidParameterException("Parameter invalid: Variance should not be 0!"); } aModel.setParameterByID(aParamIdVec.at(j), paramValue); } //randomly select a dose between aMinDose and aMaxDose double dose = uniDist() * (aMaxDose - aMinDose) + aMinDose; if (probability > 0) { try { aModel.init(dose / aNormalisationDose); double value = aModel.getValue(); std::pair modelProbPair = std::make_pair(value, probability); scatterPlotData.insert(std::pair >(dose, modelProbPair)); i++; } - catch (core::InvalidParameterException e) + catch (core::InvalidParameterException& /*e*/) { //repeat evaluation to guarantee the correct number of scatter values continue; } } } return scatterPlotData; } }//end namespace models }//end namespace rttb diff --git a/code/models/rttbDvhBasedModels.cpp b/code/models/rttbDvhBasedModels.cpp index 932d2df..26e8dd3 100644 --- a/code/models/rttbDvhBasedModels.cpp +++ b/code/models/rttbDvhBasedModels.cpp @@ -1,153 +1,173 @@ // ----------------------------------------------------------------------- // 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 "rttbDvhBasedModels.h" #include "rttbInvalidParameterException.h" -namespace rttb{ - namespace models{ - DoseStatisticType getEUD(const DVHPointer dvh, const DoseCalcType aA) { - if(aA==0) +namespace rttb +{ + namespace models + { + DoseStatisticType getEUD(const DVHPointer dvh, const DoseCalcType aA) + { + if (aA == 0) { throw core::InvalidParameterException("Parameter invalid: aA should not be zero!"); } + DataDifferentialType dataDifferential = dvh->getDataDifferential(); - if(dataDifferential.empty()) + + if (dataDifferential.empty()) { throw core::InvalidParameterException("Parameter invalid: DVH data differential should not be empty!"); } - double eud=0; + double eud = 0; DoseTypeGy deltaD = dvh->getDeltaD(); DVHVoxelNumber numberOfVoxels = dvh->getNumberOfVoxels(); - for(GridIndexType i=0; i dataBED; - std::map dataBEDRelative; + BEDDVHType calcBEDDVH(const DVHPointer dvh, const int numberOfFractions, const DoseCalcType alpha_beta, + const bool relativeVolume) + { + std::map dataBED; + std::map dataBEDRelative; DataDifferentialType dataDifferential = dvh->getDataDifferential(); - if(dataDifferential.empty()) + + if (dataDifferential.empty()) { throw core::InvalidParameterException("Parameter invalid: DVH data differential should not be empty!"); } - if(alpha_beta<=0) + + if (alpha_beta <= 0) { throw core::InvalidParameterException("Parameter invalid: alpha_beta must be >0!"); } - if(numberOfFractions<=0) + + if (numberOfFractions <= 0) { throw core::InvalidParameterException("Parameter invalid: numberOfFractions must be >1! The dvh should be an accumulated-dvh of all fractions, not a single fraction-dvh!"); } DoseTypeGy deltaD = dvh->getDeltaD(); DVHVoxelNumber numberOfVoxels = dvh->getNumberOfVoxels(); std::deque::iterator it; - int i=0; + int i = 0; - for(it=dataDifferential.begin();it!=dataDifferential.end();it++ ) + for (it = dataDifferential.begin(); it != dataDifferential.end(); ++it) { - DoseTypeGy doseGyi=((i+0.5)*deltaD); - DoseTypeGy bedi=0; - bedi=(doseGyi*(1+doseGyi/(numberOfFractions*alpha_beta))); - if(!relativeVolume) + DoseTypeGy doseGyi = ((i + 0.5) * deltaD); + DoseTypeGy bedi = 0; + bedi = (doseGyi * (1 + doseGyi / (numberOfFractions * alpha_beta))); + + if (!relativeVolume) { - dataBED.insert(std::pair(bedi,(*it))); + dataBED.insert(std::pair(bedi, (*it))); } else { - dataBEDRelative.insert(std::pair(bedi,(*it)/numberOfVoxels)); + dataBEDRelative.insert(std::pair(bedi, (*it) / numberOfVoxels)); } + i++; } - if(!relativeVolume) + if (!relativeVolume) { return dataBED; } else { return dataBEDRelative; } } - LQEDDVHType calcLQED2DVH(const DVHPointer dvh, const int numberOfFractions, const DoseCalcType alpha_beta, const bool relativeVolume) { - std::map dataLQED2; - std::map dataLQED2Relative; + LQEDDVHType calcLQED2DVH(const DVHPointer dvh, const int numberOfFractions, const DoseCalcType alpha_beta, + const bool relativeVolume) + { + std::map dataLQED2; + std::map dataLQED2Relative; DataDifferentialType dataDifferential = dvh->getDataDifferential(); - if(dataDifferential.empty()) + + if (dataDifferential.empty()) { throw core::InvalidParameterException("Parameter invalid: DVH data differential should not be empty!"); } - if(alpha_beta<=0) + + if (alpha_beta <= 0) { throw core::InvalidParameterException("Parameter invalid: alpha_beta must be >0!"); } - if(numberOfFractions<=1) + + if (numberOfFractions <= 1) { throw core::InvalidParameterException("Parameter invalid: numberOfFractions must be >1! The dvh should be an accumulated-dvh of all fractions, not a single fraction-dvh!"); } DoseTypeGy deltaD = dvh->getDeltaD(); DVHVoxelNumber numberOfVoxels = dvh->getNumberOfVoxels(); std::deque::iterator it; - int i=0; + int i = 0; - for(it=dataDifferential.begin();it!=dataDifferential.end();it++ ) + for (it = dataDifferential.begin(); it != dataDifferential.end(); ++it) { - DoseTypeGy doseGyi=((i+0.5)*deltaD); - DoseTypeGy lqed2i=0; - lqed2i=(doseGyi*((alpha_beta+doseGyi/numberOfFractions)/(alpha_beta+2))); + DoseTypeGy doseGyi = ((i + 0.5) * deltaD); + DoseTypeGy lqed2i = 0; + lqed2i = (doseGyi * ((alpha_beta + doseGyi / numberOfFractions) / (alpha_beta + 2))); - if(!relativeVolume) + if (!relativeVolume) { - dataLQED2.insert(std::pair(lqed2i,*it)); + dataLQED2.insert(std::pair(lqed2i, *it)); } else { - dataLQED2Relative.insert(std::pair(lqed2i,(*it)/numberOfVoxels)); + dataLQED2Relative.insert(std::pair(lqed2i, (*it) / numberOfVoxels)); } + i++; } - if(!relativeVolume) + if (!relativeVolume) { return dataLQED2; } else { return dataLQED2Relative; } } } } \ No newline at end of file diff --git a/code/models/rttbIntegration.cpp b/code/models/rttbIntegration.cpp index 6cbb314..b5ef825 100644 --- a/code/models/rttbIntegration.cpp +++ b/code/models/rttbIntegration.cpp @@ -1,155 +1,190 @@ // ----------------------------------------------------------------------- // 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 "rttbIntegration.h" #include "rttbInvalidParameterException.h" -namespace rttb{ - namespace models{ +namespace rttb +{ + namespace models + { - double tcpModelFunctor::calculate(double x) const{ - if(x==0) - x=1e-30; + double tcpModelFunctor::calculate(double x) const + { + if (x == 0) + { + x = 1e-30; + } - return tcpFunction(a+(1-x)/x,params)/(x*x); + return tcpFunction(a + (1 - x) / x, params) / (x * x); } - double LkbModelFunctor::calculate(double x) const{ - if(x==0) - x=1e-30; - return lkbFunction(b-(1-x)/x)/(x*x); + double LkbModelFunctor::calculate(double x) const + { + if (x == 0) + { + x = 1e-30; + } + + return lkbFunction(b - (1 - x) / x) / (x * x); } - double tcpFunction(double x, const TcpParams& tcp_params){ - double alphaVariance=tcp_params.alphaVariance; - if(alphaVariance==0) - alphaVariance=1e-30; + double tcpFunction(double x, const TcpParams& tcp_params) + { + double alphaVariance = tcp_params.alphaVariance; - double f=exp(-pow((x-tcp_params.alphaMean)/alphaVariance,2)/2); - double tmp,tmp1,tmp2,tmp3; - for(int i=0;i(BMFunction,aNew,bNew); + return iterativeIntegration(BMFunction, aNew, bNew); } - double lkbFunction(double x){ + double lkbFunction(double x) + { - double tmp = -pow(x,2)/2; + double tmp = -pow(x, 2) / 2; double step = exp(tmp); return step; } - double integrateLKB(double b){ + double integrateLKB(double b) + { - double aNew=1e-30; - double bNew=1.0; + double aNew = 1e-30; + double bNew = 1.0; LkbModelFunctor BMFunction; - BMFunction.b=b; + BMFunction.b = b; - return iterativeIntegration(BMFunction,aNew,bNew); + return iterativeIntegration(BMFunction, aNew, bNew); } //returns the nth stage of refinement of the extended trapezoidal rule template integrationType trapzd(const FunctorType& BMfunction, integrationType a, integrationType b, int stepNum) { - integrationType x, tnm, sum, del; - int it, j; static integrationType result; - if(stepNum==1) - result = 0.5*(b-a)*(BMfunction.calculate(a)+BMfunction.calculate(b)); - else{ - for(it=1,j=1;j - integrationType iterativeIntegration(const FunctorType& BMfunction, integrationType a, integrationType b){ - integrationType s = 0.0; - integrationType st = 0.0; + integrationType iterativeIntegration(const FunctorType& BMfunction, integrationType a, integrationType b) + { integrationType ost = 0.0; integrationType os = 0.0; int maxSteps = 50; double eps = 1e-6; int i = 1; - for(; i <= maxSteps; ++i){ - - st = trapzd(BMfunction,a,b,i); - s = (4.0*st-ost)/3.0; + + for (; i <= maxSteps; ++i) + { + integrationType st = trapzd(BMfunction, a, b, i); + integrationType s = (4.0 * st - ost) / 3.0; + if (i > 5) { - if(fabs(s-os) #include #include #include #include -#define _USE_MATH_DEFINES +#define _USE_MATH_DEFINES #include #include "rttbIntegration.h" #include "rttbNTCPLKBModel.h" #include "rttbDvhBasedModels.h" #include "rttbInvalidParameterException.h" #include "rttbExceptionMacros.h" -namespace rttb{ +namespace rttb +{ - namespace models{ - NTCPLKBModel::NTCPLKBModel():NTCPModel(), _m(0), _a(0) {} + namespace models + { + NTCPLKBModel::NTCPLKBModel(): NTCPModel(), _m(0), _a(0) {} NTCPLKBModel::NTCPLKBModel(DVHPointer aDvh, BioModelParamType aD50, BioModelParamType aM, BioModelParamType aA): - NTCPModel(aDvh, aD50), _m(aM), _a(aA){} + NTCPModel(aDvh, aD50), _m(aM), _a(aA) {} - void NTCPLKBModel::setA(const BioModelParamType aA){ - _a=aA; + void NTCPLKBModel::setA(const BioModelParamType aA) + { + _a = aA; } - const BioModelParamType NTCPLKBModel::getA(){return _a;} + const BioModelParamType NTCPLKBModel::getA() + { + return _a; + } - void NTCPLKBModel::setM(const BioModelParamType aM){ - _m=aM; + void NTCPLKBModel::setM(const BioModelParamType aM) + { + _m = aM; } - const BioModelParamType NTCPLKBModel::getM(){return _m;} + const BioModelParamType NTCPLKBModel::getM() + { + return _m; + } - void NTCPLKBModel::setParameterVector(const ParamVectorType aParameterVector){ - if(aParameterVector.size()!=3) - { - throw core::InvalidParameterException("Parameter invalid: aParameterVector.size must be 3! "); - } + void NTCPLKBModel::setParameterVector(const ParamVectorType& aParameterVector) + { + if (aParameterVector.size() != 3) + { + throw core::InvalidParameterException("Parameter invalid: aParameterVector.size must be 3! "); + } else - { - _d50=aParameterVector.at(0); - _m=aParameterVector.at(1); - _a=aParameterVector.at(2); - } + { + _d50 = aParameterVector.at(0); + _m = aParameterVector.at(1); + _a = aParameterVector.at(2); } + } - void NTCPLKBModel::setParameterByID(const int aParamId, const BioModelParamType aValue){ - if(aParamId==0) - { - _d50=aValue; - } - else if(aParamId==1) - { - _m=aValue; - } - else if(aParamId==2) - { - _a=aValue; - } + void NTCPLKBModel::setParameterByID(const int aParamId, const BioModelParamType aValue) + { + if (aParamId == 0) + { + _d50 = aValue; + } + else if (aParamId == 1) + { + _m = aValue; + } + else if (aParamId == 2) + { + _a = aValue; + } else - { - throw core::InvalidParameterException("Parameter invalid: aParamID must be 0(for d50) or 1(for m) or 2(for a)! "); - } + { + throw core::InvalidParameterException("Parameter invalid: aParamID must be 0(for d50) or 1(for m) or 2(for a)! "); } + } - const int NTCPLKBModel::getParameterID(const std::string aParamName) const{ - if(aParamName=="d50") - { + const int NTCPLKBModel::getParameterID(const std::string& aParamName) const + { + if (aParamName == "d50") + { return 0; - } - else if(aParamName=="m") - { + } + else if (aParamName == "m") + { return 1; - } - else if(aParamName=="a") - { + } + else if (aParamName == "a") + { return 2; - } + } else - { - rttbExceptionMacro(core::InvalidParameterException, << "Parameter name "<getDataDifferential(),(DoseTypeGy)(_dvh->getDeltaD()*doseFactor), - _dvh->getDeltaV(),"temporary","temporary"); + core::DVH variantDVH = core::DVH(_dvh->getDataDifferential(), (DoseTypeGy)(_dvh->getDeltaD() * doseFactor), + _dvh->getDeltaV(), "temporary", "temporary"); boost::shared_ptr spDVH = boost::make_shared(variantDVH); - double eud=getEUD(spDVH,this->_a); + double eud = getEUD(spDVH, this->_a); //_m must not be zero - double t=(eud-this->_d50)/(this->_m*this->_d50); - double value=1/pow(2*M_PI, 0.5); + double t = (eud - this->_d50) / (this->_m * this->_d50); + double value = 1 / pow(2 * M_PI, 0.5); double result = integrateLKB(t); - if (result != -100){ - value*=result; + if (result != -100) + { + value *= result; return value; - } - else{ + } + else + { return false; - } } + } - }//end namespace models + }//end namespace models }//end namespace rttb diff --git a/code/models/rttbNTCPLKBModel.h b/code/models/rttbNTCPLKBModel.h index 89530b7..c6382e8 100644 --- a/code/models/rttbNTCPLKBModel.h +++ b/code/models/rttbNTCPLKBModel.h @@ -1,99 +1,101 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #ifndef __NTCP_LKB_MODEL_H #define __NTCP_LKB_MODEL_H #include #include #include "rttbBaseType.h" #include "rttbNTCPModel.h" #include "rttbBaseTypeModels.h" -namespace rttb{ +namespace rttb +{ - namespace models{ + namespace models + { /*! @class NTCPLKBModel - @brief This class represents a NTCP(Normal Tissue Complication Probability) LKB model - (Lyman 1985, Kutcher and Burman 1989) + @brief This class represents a NTCP(Normal Tissue Complication Probability) LKB model + (Lyman 1985, Kutcher and Burman 1989) @see NTCPModel */ class NTCPLKBModel: public NTCPModel - { - public: - typedef NTCPModel::ParamVectorType ParamVectorType; - typedef NTCPModel::DVHPointer DVHPointer; + { + public: + typedef NTCPModel::ParamVectorType ParamVectorType; + typedef NTCPModel::DVHPointer DVHPointer; - private: - /*! The steepness of the dose-response curve. Must not be zero on model evaluation. - */ - BioModelParamType _m; + private: + /*! The steepness of the dose-response curve. Must not be zero on model evaluation. + */ + BioModelParamType _m; - /*! Tumor or normal tissue-specific parameter that describes the dose–volume effect, - e.g. -10 for prostate (Wu 2002). Must not be zero on model evaluation, because EUD calculation will fail. - */ - BioModelParamType _a; + /*! Tumor or normal tissue-specific parameter that describes the dose–volume effect, + e.g. -10 for prostate (Wu 2002). Must not be zero on model evaluation, because EUD calculation will fail. + */ + BioModelParamType _a; - protected: - /*! @brief Calculate the model value - * @param doseFactor: scaling factor for the dose. The model calculation will use the dvh with each di=old di*doseFactor. - * @throw if either _a or _m is zero for the model calculation - */ - BioModelValueType calcModel(const double doseFactor=1); + protected: + /*! @brief Calculate the model value + * @param doseFactor: scaling factor for the dose. The model calculation will use the dvh with each di=old di*doseFactor. + * @throw if either _a or _m is zero for the model calculation + */ + BioModelValueType calcModel(const double doseFactor = 1); - public: - NTCPLKBModel(); + public: + NTCPLKBModel(); - NTCPLKBModel(DVHPointer aDvh, BioModelParamType aD50, BioModelParamType aM, BioModelParamType aA); + NTCPLKBModel(DVHPointer aDvh, BioModelParamType aD50, BioModelParamType aM, BioModelParamType aA); - void setM(const BioModelParamType aM); + void setM(const BioModelParamType aM); - const BioModelParamType getM(); + const BioModelParamType getM(); - void setA(const BioModelParamType aA); + void setA(const BioModelParamType aA); - const BioModelParamType getA(); + const BioModelParamType getA(); - /*! @brief Set parameter with ID. "d50":0,"m":1,"a":2 - @exception InvalidParameterException Thrown if aParamId is not 0 or 1 or 2. - */ - virtual void setParameterByID(const int aParamId, const BioModelParamType aValue); + /*! @brief Set parameter with ID. "d50":0,"m":1,"a":2 + @exception InvalidParameterException Thrown if aParamId is not 0 or 1 or 2. + */ + virtual void setParameterByID(const int aParamId, const BioModelParamType aValue); - /*! @brief Set parameter vector, where index of vector is the parameter ID. "d50":0,"m":1,"a":2 - @exception InvalidParameterException Thrown if aParamterVector.size()!=3. - */ - virtual void setParameterVector(const ParamVectorType aParameterVector); + /*! @brief Set parameter vector, where index of vector is the parameter ID. "d50":0,"m":1,"a":2 + @exception InvalidParameterException Thrown if aParamterVector.size()!=3. + */ + virtual void setParameterVector(const ParamVectorType& aParameterVector); - /*! @brief Get parameter ID. "d50":0,"m":1,"a":2 - @return 0 for "d50", 1 for "m", 2 for "a" - @exception InvalidParameterException Thrown if aParamName is not d50 or m or a. - */ - virtual const int getParameterID(const std::string aParamName) const; - }; + /*! @brief Get parameter ID. "d50":0,"m":1,"a":2 + @return 0 for "d50", 1 for "m", 2 for "a" + @exception InvalidParameterException Thrown if aParamName is not d50 or m or a. + */ + virtual const int getParameterID(const std::string& aParamName) const; + }; - } } +} #endif diff --git a/code/models/rttbNTCPRSModel.cpp b/code/models/rttbNTCPRSModel.cpp index 911e8ec..6d908ba 100644 --- a/code/models/rttbNTCPRSModel.cpp +++ b/code/models/rttbNTCPRSModel.cpp @@ -1,129 +1,152 @@ // ----------------------------------------------------------------------- // 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 -#define _USE_MATH_DEFINES +#define _USE_MATH_DEFINES #include #include "rttbNTCPRSModel.h" #include "rttbInvalidParameterException.h" #include "rttbExceptionMacros.h" -namespace rttb{ +namespace rttb +{ - namespace models{ - NTCPRSModel::NTCPRSModel():NTCPModel(), _gamma(0), _s(0){} + namespace models + { + NTCPRSModel::NTCPRSModel(): NTCPModel(), _gamma(0), _s(0) {} NTCPRSModel::NTCPRSModel(DVHPointer aDvh, BioModelParamType aD50, BioModelParamType aGamma, BioModelParamType aS): - NTCPModel(aDvh, aD50), _gamma(aGamma), _s(aS){} + NTCPModel(aDvh, aD50), _gamma(aGamma), _s(aS) {} - void NTCPRSModel::setGamma(const BioModelParamType aGamma){_gamma=aGamma;} + void NTCPRSModel::setGamma(const BioModelParamType aGamma) + { + _gamma = aGamma; + } - const BioModelParamType NTCPRSModel::getGamma(){return _gamma;} + const BioModelParamType NTCPRSModel::getGamma() + { + return _gamma; + } - void NTCPRSModel::setS(const BioModelParamType aS){ - _s=aS; + void NTCPRSModel::setS(const BioModelParamType aS) + { + _s = aS; } - const BioModelParamType NTCPRSModel::getS(){return _s;} + const BioModelParamType NTCPRSModel::getS() + { + return _s; + } - void NTCPRSModel::setParameterVector(const ParamVectorType aParameterVector){ - if(aParameterVector.size()!=3) - { + void NTCPRSModel::setParameterVector(const ParamVectorType& aParameterVector) + { + if (aParameterVector.size() != 3) + { throw core::InvalidParameterException("Parameter invalid: aParameterVector.size must be 3! "); - } + } else - { - _d50=aParameterVector.at(0); - _gamma=aParameterVector.at(1); - _s=aParameterVector.at(2); - } + { + _d50 = aParameterVector.at(0); + _gamma = aParameterVector.at(1); + _s = aParameterVector.at(2); } + } - void NTCPRSModel::setParameterByID(const int aParamId, const BioModelParamType aValue){ - if(aParamId==0) - { - _d50=aValue; - } - else if(aParamId==1) - { - _gamma=aValue; - } - else if(aParamId==2) - { - _s=aValue; - } + void NTCPRSModel::setParameterByID(const int aParamId, const BioModelParamType aValue) + { + if (aParamId == 0) + { + _d50 = aValue; + } + else if (aParamId == 1) + { + _gamma = aValue; + } + else if (aParamId == 2) + { + _s = aValue; + } else - { - throw core::InvalidParameterException("Parameter invalid: aParamID must be 0(for d50) or 1(for gamma) or 2(for s)! "); - } - + { + throw core::InvalidParameterException("Parameter invalid: aParamID must be 0(for d50) or 1(for gamma) or 2(for s)! "); } - const int NTCPRSModel::getParameterID(const std::string aParamName) const{ - if(aParamName=="d50") - { + } + + const int NTCPRSModel::getParameterID(const std::string& aParamName) const + { + if (aParamName == "d50") + { return 0; - } - else if(aParamName=="gamma") - { + } + else if (aParamName == "gamma") + { return 1; - } - else if(aParamName=="s") - { + } + else if (aParamName == "s") + { return 2; - } + } else - { - rttbExceptionMacro(core::InvalidParameterException, << "Parameter name "<_gamma*(1-dose/this->_d50))); + return pow(2, -exp(M_E * this->_gamma * (1 - dose / this->_d50))); + } + + BioModelValueType NTCPRSModel::calcModel(double doseFactor) + { + if (_d50 == 0) + { + throw core::InvalidParameterException("d50 must not be zero"); } - BioModelValueType NTCPRSModel::calcModel(double doseFactor){ - if (_d50==0){ - throw core::InvalidParameterException("d50 must not be zero"); - } - if (_s==0){ - throw core::InvalidParameterException("s must not be zero"); - } - - std::deque dataDifferential=this->_dvh->getDataDifferential(); - double ntcp=1; - for(GridIndexType i=0; ipoissonModel(i*this->_dvh->getDeltaD()*doseFactor),this->_s); - - double vi=dataDifferential[i]/this->_dvh->getNumberOfVoxels(); - ntcp*=pow((1-pd),vi); - } - //_s must not be zero - return (BioModelValueType)(pow((1-ntcp),1/this->_s)); + if (_s == 0) + { + throw core::InvalidParameterException("s must not be zero"); + } + + std::deque dataDifferential = this->_dvh->getDataDifferential(); + double ntcp = 1; + + for (GridIndexType i = 0; i < dataDifferential.size(); i++) + { + double pd = pow(this->poissonModel(i * this->_dvh->getDeltaD() * doseFactor), this->_s); + + double vi = dataDifferential[i] / this->_dvh->getNumberOfVoxels(); + ntcp *= pow((1 - pd), vi); } - }//end namespace models - }//end namespace rttb + //_s must not be zero + return (BioModelValueType)(pow((1 - ntcp), 1 / this->_s)); + } + + }//end namespace models +}//end namespace rttb diff --git a/code/models/rttbNTCPRSModel.h b/code/models/rttbNTCPRSModel.h index 05e12d8..b0ab272 100644 --- a/code/models/rttbNTCPRSModel.h +++ b/code/models/rttbNTCPRSModel.h @@ -1,104 +1,106 @@ // ----------------------------------------------------------------------- // 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 __NTCP_RS_MODEL_H #define __NTCP_RS_MODEL_H #include #include #include "rttbBaseType.h" #include "rttbNTCPModel.h" #include "rttbBaseTypeModels.h" -namespace rttb{ +namespace rttb +{ - namespace models{ + namespace models + { /*! @class NTCPRSModel @brief This class represents a NTCP(Normal Tissue Complication Probability) relative seriality model (Källman 1992) @see NTCPModel */ class NTCPRSModel: public NTCPModel - { - public: - typedef NTCPModel::ParamVectorType ParamVectorType; - typedef NTCPModel::DVHPointer DVHPointer; + { + public: + typedef NTCPModel::ParamVectorType ParamVectorType; + typedef NTCPModel::DVHPointer DVHPointer; - private: - /*! _gamma The normalised dose-response gradient, values between 1.7 and 2.0 are typical for human tumours. - (Källman 1992) - */ - BioModelParamType _gamma; + private: + /*! _gamma The normalised dose-response gradient, values between 1.7 and 2.0 are typical for human tumours. + (Källman 1992) + */ + BioModelParamType _gamma; - /*! _s The relative seriality factor, e.g. s=3.4 for the esophagus (highly serial structure) and s=0.0061 - for the lung(highly parallel structure). Must not be zero on model evaluation. - */ - BioModelParamType _s; + /*! _s The relative seriality factor, e.g. s=3.4 for the esophagus (highly serial structure) and s=0.0061 + for the lung(highly parallel structure). Must not be zero on model evaluation. + */ + BioModelParamType _s; - const double poissonModel(const double dose); + const double poissonModel(const double dose); - protected: - /*! @brief Calculate the model value - @param doseFactor scaling factor for the dose. The model calculation will use the dvh with each di=old di*doseFactor. - @throw if either _s or _d50 is zero for the model calculation. - */ - BioModelValueType calcModel(const double doseFactor=1); + protected: + /*! @brief Calculate the model value + @param doseFactor scaling factor for the dose. The model calculation will use the dvh with each di=old di*doseFactor. + @throw if either _s or _d50 is zero for the model calculation. + */ + BioModelValueType calcModel(const double doseFactor = 1); - public: - NTCPRSModel(); + public: + NTCPRSModel(); - /*!@brief Constructor initializing all member variables with given parameters. - */ - NTCPRSModel(DVHPointer aDvh, BioModelParamType aD50, BioModelParamType aGamma, BioModelParamType aS); + /*!@brief Constructor initializing all member variables with given parameters. + */ + NTCPRSModel(DVHPointer aDvh, BioModelParamType aD50, BioModelParamType aGamma, BioModelParamType aS); - void setGamma(const BioModelParamType aGamma); + void setGamma(const BioModelParamType aGamma); - const BioModelParamType getGamma(); + const BioModelParamType getGamma(); - void setS(const BioModelParamType aS); + void setS(const BioModelParamType aS); - const BioModelParamType getS(); + const BioModelParamType getS(); - /*! @brief Set parameter with ID. "d50":0,"gamma":1,"s":2 - @exception InvalidParameterException Thrown if aParamId is not 0 or 1 or 2. - */ - virtual void setParameterByID(const int aParamId, const BioModelParamType aValue); + /*! @brief Set parameter with ID. "d50":0,"gamma":1,"s":2 + @exception InvalidParameterException Thrown if aParamId is not 0 or 1 or 2. + */ + virtual void setParameterByID(const int aParamId, const BioModelParamType aValue); - /*! @brief Set parameter vector, where index of vector is the parameter Id. - "d50":0,"gamma":1,"s":2 - @exception InvalidParameterException Thrown if aParamterVector.size()!=3. - */ - virtual void setParameterVector(const ParamVectorType aParameterVector); + /*! @brief Set parameter vector, where index of vector is the parameter Id. + "d50":0,"gamma":1,"s":2 + @exception InvalidParameterException Thrown if aParamterVector.size()!=3. + */ + virtual void setParameterVector(const ParamVectorType& aParameterVector); - /*! @brief Get parameter ID. "d50":0,"gamma":1,"s":2 - @return 0 for "d50", 1 for "gamma", 2 for "s" - @exception InvalidParameterException Thrown if aParamName is not d50 or gamma or s. - */ - virtual const int getParameterID(const std::string aParamName) const; - }; + /*! @brief Get parameter ID. "d50":0,"gamma":1,"s":2 + @return 0 for "d50", 1 for "gamma", 2 for "s" + @exception InvalidParameterException Thrown if aParamName is not d50 or gamma or s. + */ + virtual const int getParameterID(const std::string& aParamName) const; + }; - } } +} #endif diff --git a/code/models/rttbTCPLQModel.cpp b/code/models/rttbTCPLQModel.cpp index 9bddc66..3c69723 100644 --- a/code/models/rttbTCPLQModel.cpp +++ b/code/models/rttbTCPLQModel.cpp @@ -1,235 +1,273 @@ // ----------------------------------------------------------------------- // 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 -#define _USE_MATH_DEFINES +#define _USE_MATH_DEFINES #include #include #include #include #include "rttbTCPLQModel.h" #include "rttbDvhBasedModels.h" #include "rttbBaseTypeModels.h" #include "rttbIntegration.h" #include "rttbInvalidParameterException.h" #include "rttbExceptionMacros.h" -namespace rttb{ +namespace rttb +{ - namespace models{ + namespace models + { - TCPLQModel::TCPLQModel(): TCPModel(),_alphaMean(0), _alphaVariance(0), _alpha_beta(0), _rho(0){} + TCPLQModel::TCPLQModel(): TCPModel(), _alphaMean(0), _alphaVariance(0), _alpha_beta(0), _rho(0) {} - TCPLQModel::TCPLQModel(DVHPointer aDVH, BioModelParamType aAlphaMean, BioModelParamType aBeta, BioModelParamType aRho, - int aNumberOfFractions): TCPModel(aDVH,aNumberOfFractions),_alphaMean(aAlphaMean), _alphaVariance(0), - _alpha_beta(aAlphaMean/aBeta), _rho(aRho){} + TCPLQModel::TCPLQModel(DVHPointer aDVH, BioModelParamType aAlphaMean, BioModelParamType aBeta, BioModelParamType aRho, + int aNumberOfFractions): TCPModel(aDVH, aNumberOfFractions), _alphaMean(aAlphaMean), _alphaVariance(0), + _alpha_beta(aAlphaMean / aBeta), _rho(aRho) {} - TCPLQModel::TCPLQModel(DVHPointer aDVH, BioModelParamType aRho, int aNumberOfFractions, BioModelParamType aAlpha_Beta, - BioModelParamType aAlphaMean, BioModelParamType aAlphaVariance): TCPModel(aDVH,aNumberOfFractions),_alphaMean(aAlphaMean), - _alphaVariance(aAlphaVariance), _alpha_beta(aAlpha_Beta), _rho(aRho){} + TCPLQModel::TCPLQModel(DVHPointer aDVH, BioModelParamType aRho, int aNumberOfFractions, BioModelParamType aAlpha_Beta, + BioModelParamType aAlphaMean, BioModelParamType aAlphaVariance): TCPModel(aDVH, aNumberOfFractions), + _alphaMean(aAlphaMean), + _alphaVariance(aAlphaVariance), _alpha_beta(aAlpha_Beta), _rho(aRho) {} - void TCPLQModel::setParameters(const BioModelParamType aAlphaMean, const BioModelParamType aAlpha_Beta, - const BioModelParamType aRho, const BioModelParamType aAlphaVariance){ - _alphaMean=aAlphaMean; - _alphaVariance=aAlphaVariance; - _alpha_beta=aAlpha_Beta; - _rho=aRho; + void TCPLQModel::setParameters(const BioModelParamType aAlphaMean, const BioModelParamType aAlpha_Beta, + const BioModelParamType aRho, const BioModelParamType aAlphaVariance) + { + _alphaMean = aAlphaMean; + _alphaVariance = aAlphaVariance; + _alpha_beta = aAlpha_Beta; + _rho = aRho; //reset _value, because parameters have changed. - _value=0; - } - - void TCPLQModel::setAlpha(const BioModelParamType aAlphaMean, const BioModelParamType aAlphaVariance){ - _alphaVariance=aAlphaVariance; - _alphaMean=aAlphaMean; - } + _value = 0; + } + + void TCPLQModel::setAlpha(const BioModelParamType aAlphaMean, const BioModelParamType aAlphaVariance) + { + _alphaVariance = aAlphaVariance; + _alphaMean = aAlphaMean; + } + + void TCPLQModel::setAlphaBeta(const BioModelParamType aAlpha_Beta) + { + _alpha_beta = aAlpha_Beta; + } + + void TCPLQModel::setRho(const BioModelParamType aRho) + { + _rho = aRho; + } + + const BioModelParamType TCPLQModel::getAlpahBeta() + { + return _alpha_beta; + } + + const BioModelParamType TCPLQModel::getAlphaMean() + { + return _alphaMean; + } + + const BioModelParamType TCPLQModel::getAlphaVariance() + { + return _alphaVariance; + } + + const BioModelParamType TCPLQModel::getRho() + { + return _rho; + } + + long double TCPLQModel::calcTCPi(BioModelParamType aRho, BioModelParamType aAlphaMean, double vj, double bedj) + { + return exp(-aRho * vj * exp(-aAlphaMean * bedj)); + } + + long double TCPLQModel::calcTCP(std::map aBEDDVH, BioModelParamType aRho, + BioModelParamType aAlphaMean, double aDeltaV) + { + std::map::iterator it; + long double tcp = 1; - void TCPLQModel::setAlphaBeta(const BioModelParamType aAlpha_Beta){ - _alpha_beta=aAlpha_Beta; + for (it = aBEDDVH.begin(); it != aBEDDVH.end(); ++it) + { + long double tcpi = this->calcTCPi(aRho, aAlphaMean, (*it).second * aDeltaV, (*it).first); + tcp = tcp * tcpi; } - void TCPLQModel::setRho(const BioModelParamType aRho){_rho=aRho;} - - const BioModelParamType TCPLQModel::getAlpahBeta(){return _alpha_beta;} - - const BioModelParamType TCPLQModel::getAlphaMean(){return _alphaMean;} - - const BioModelParamType TCPLQModel::getAlphaVariance(){return _alphaVariance;} + return tcp; + } - const BioModelParamType TCPLQModel::getRho(){return _rho;} + long double TCPLQModel::calcTCPAlphaNormalDistribution(std::map aBEDDVH, + BioModelParamType aRho, BioModelParamType aAlphaMean, + BioModelParamType aAlphaVariance, double aDeltaV) + { - long double TCPLQModel::calcTCPi(BioModelParamType aRho, BioModelParamType aAlphaMean, double vj, double bedj){ - return exp(-aRho*vj*exp(-aAlphaMean*bedj)); - } - - long double TCPLQModel::calcTCP(std::map aBEDDVH, BioModelParamType aRho, - BioModelParamType aAlphaMean, double aDeltaV){ std::map::iterator it; - long double tcp=1; - for(it=aBEDDVH.begin(); it!=aBEDDVH.end();it++) - { - long double tcpi=this->calcTCPi(aRho,aAlphaMean,(*it).second*aDeltaV,(*it).first); - tcp=tcp*tcpi; - } - return tcp; + std::vector volumeV2; + std::vector bedV2; + int i = 0; + + for (it = aBEDDVH.begin(); it != aBEDDVH.end(); ++it) + { + volumeV2.push_back((*it).second * aDeltaV); + bedV2.push_back((*it).first); + i++; } - long double TCPLQModel::calcTCPAlphaNormalDistribution(std::map aBEDDVH, - BioModelParamType aRho, BioModelParamType aAlphaMean, - BioModelParamType aAlphaVariance, double aDeltaV){ + struct TcpParams params = {aAlphaMean, aAlphaVariance, aRho, volumeV2, bedV2}; - std::map::iterator it; - int bedSize=aBEDDVH.size(); - std::vector volumeV2; - std::vector bedV2; - int i=0; - for(it=aBEDDVH.begin();it!=aBEDDVH.end();it++) - { - volumeV2.push_back((*it).second*aDeltaV); - bedV2.push_back((*it).first); - i++; - } + double result = integrateTCP(0, params); - struct TcpParams params={aAlphaMean,aAlphaVariance,aRho,volumeV2,bedV2}; - - double result = integrateTCP(0, params); - - if(result == -100) - { - std::cerr << "Integration error!\n"; - return -1; - } - else{ - long double tcp=1/(pow(2*M_PI, 0.5)*_alphaVariance)*result; + if (result == -100) + { + std::cerr << "Integration error!\n"; + return -1; + } + else + { + long double tcp = 1 / (pow(2 * M_PI, 0.5) * _alphaVariance) * result; - return tcp; - } + return tcp; } + } - BioModelValueType TCPLQModel::calcModel(const double doseFactor){ - core::DVH variantDVH=core::DVH(_dvh->getDataDifferential(),(DoseTypeGy)(_dvh->getDeltaD()*doseFactor), - _dvh->getDeltaV(),"temporary","temporary"); + BioModelValueType TCPLQModel::calcModel(const double doseFactor) + { + core::DVH variantDVH = core::DVH(_dvh->getDataDifferential(), (DoseTypeGy)(_dvh->getDeltaD() * doseFactor), + _dvh->getDeltaV(), "temporary", "temporary"); boost::shared_ptr spDVH = boost::make_shared(variantDVH); - BioModelValueType value=0; - if(_alphaVariance==0){ - if(_alphaMean<=0 && _alpha_beta<=0 && _rho<=0 ) - { - throw core::InvalidParameterException("Parameter invalid: alpha, alpha/beta, rho and number of fractions must >0!"); - } - if(_numberOfFractions<=1){ - throw core::InvalidParameterException("Parameter invalid: numberOfFractions must be >1! The dvh should be an accumulated-dvh of all fractions, not a single fraction-dvh!"); - } + BioModelValueType value = 0; - long double tcp=1; - std::map dataBED=calcBEDDVH(spDVH,_numberOfFractions, _alpha_beta); - - value=(BioModelValueType)this->calcTCP(dataBED,_rho,_alphaMean,variantDVH.getDeltaV()); - return value; + if (_alphaVariance == 0) + { + if (_alphaMean <= 0 && _alpha_beta <= 0 && _rho <= 0) + { + throw core::InvalidParameterException("Parameter invalid: alpha, alpha/beta, rho and number of fractions must >0!"); } - //if alpha normal distribution - else { - if(this->_alpha_beta<=0 && this->_alphaMean<=0 && this->_alphaVariance<0 && _rho<=0 && _numberOfFractions<=0) - { - throw core::InvalidParameterException("Parameter invalid: alpha/beta, alphaMean, rho and number of fractions must >0!"); - } - if(_numberOfFractions<=1){ + if (_numberOfFractions <= 1) + { throw core::InvalidParameterException("Parameter invalid: numberOfFractions must be >1! The dvh should be an accumulated-dvh of all fractions, not a single fraction-dvh!"); } - std::map dataBED=calcBEDDVH(spDVH,_numberOfFractions, _alpha_beta); - value=(BioModelValueType)(this->calcTCPAlphaNormalDistribution(dataBED,_rho,_alphaMean,_alphaVariance, - variantDVH.getDeltaV())); + std::map dataBED = calcBEDDVH(spDVH, _numberOfFractions, _alpha_beta); + + value = (BioModelValueType)this->calcTCP(dataBED, _rho, _alphaMean, variantDVH.getDeltaV()); return value; - } } - void TCPLQModel::setParameterVector(const ParamVectorType aParameterVector){ - if(aParameterVector.size()!=4) - { - throw core::InvalidParameterException("Parameter invalid: aParameterVector.size must be 4! "); - } + //if alpha normal distribution else + { + if (this->_alpha_beta <= 0 && this->_alphaMean <= 0 && this->_alphaVariance < 0 && _rho <= 0 && _numberOfFractions <= 0) { - _alphaMean=aParameterVector.at(0); - _alphaVariance=aParameterVector.at(1); - _alpha_beta=aParameterVector.at(2); - _rho=aParameterVector.at(3); + throw core::InvalidParameterException("Parameter invalid: alpha/beta, alphaMean, rho and number of fractions must >0!"); } - } - void TCPLQModel::setParameterByID(const int aParamId, const BioModelParamType aValue){ - if(aParamId==0) - { - _alphaMean=aValue; - } - else if(aParamId==1) + if (_numberOfFractions <= 1) { - _alphaVariance=aValue; - } - else if(aParamId==2) - { - _alpha_beta=aValue; - } - else if(aParamId==3) - { - _rho=aValue; + throw core::InvalidParameterException("Parameter invalid: numberOfFractions must be >1! The dvh should be an accumulated-dvh of all fractions, not a single fraction-dvh!"); } + + std::map dataBED = calcBEDDVH(spDVH, _numberOfFractions, _alpha_beta); + value = (BioModelValueType)(this->calcTCPAlphaNormalDistribution(dataBED, _rho, _alphaMean, _alphaVariance, + variantDVH.getDeltaV())); + return value; + } + } + + void TCPLQModel::setParameterVector(const ParamVectorType& aParameterVector) + { + if (aParameterVector.size() != 4) + { + throw core::InvalidParameterException("Parameter invalid: aParameterVector.size must be 4! "); + } else - { - throw core::InvalidParameterException("Parameter invalid: aParamID must be 0(alphaMean) or 1(alphaVariance) or 2(alpha_beta) or 3(rho)! "); - } + { + _alphaMean = aParameterVector.at(0); + _alphaVariance = aParameterVector.at(1); + _alpha_beta = aParameterVector.at(2); + _rho = aParameterVector.at(3); + } + } + void TCPLQModel::setParameterByID(const int aParamId, const BioModelParamType aValue) + { + if (aParamId == 0) + { + _alphaMean = aValue; + } + else if (aParamId == 1) + { + _alphaVariance = aValue; + } + else if (aParamId == 2) + { + _alpha_beta = aValue; + } + else if (aParamId == 3) + { + _rho = aValue; + } + else + { + throw core::InvalidParameterException("Parameter invalid: aParamID must be 0(alphaMean) or 1(alphaVariance) or 2(alpha_beta) or 3(rho)! "); } - const int TCPLQModel::getParameterID(const std::string aParamName) const{ - if(aParamName=="alphaMean") - { + } + + const int TCPLQModel::getParameterID(const std::string& aParamName) const + { + if (aParamName == "alphaMean") + { return 0; - } - else if(aParamName=="alphaVariance") - { + } + else if (aParamName == "alphaVariance") + { return 1; - } - else if(aParamName=="alpha_beta") - { + } + else if (aParamName == "alpha_beta") + { return 2; - } - else if(aParamName=="rho") - { + } + else if (aParamName == "rho") + { return 3; - } + } else - { - rttbExceptionMacro(core::InvalidParameterException, << "Parameter name "< #include #include #include "rttbBaseType.h" #include "rttbTCPModel.h" #include "rttbBaseTypeModels.h" -namespace rttb{ +namespace rttb +{ - namespace models{ + namespace models + { /*! @class TCPLQModel - @brief This class represents a TCP(Tumor Control Probability) LQ model (Nahum and Sanchez-Nieto 2001, - Hall and Giaccia 2006) + @brief This class represents a TCP(Tumor Control Probability) LQ model (Nahum and Sanchez-Nieto 2001, + Hall and Giaccia 2006) @see TCPModel */ class TCPLQModel: public TCPModel - { - public: - typedef TCPModel::ParamVectorType ParamVectorType; - typedef TCPModel::DVHPointer DVHPointer; - - private: - /*! @brief Calculate intermediate tcp using alpha constant. This is a helper function for calcTCP() - @see calcTCP - */ - long double calcTCPi(BioModelParamType aRho, BioModelParamType aAlphaMean, double vj, double bedj); - - /*! @brief Calculate tcp using alpha constant. - */ - long double calcTCP(std::map aBEDDVH, BioModelParamType aRho, - BioModelParamType aAlphaMean, double aDeltaV); - - /*! @brief Calculate tcp using a normal distribution for alpha. - */ - long double calcTCPAlphaNormalDistribution(std::map aBEDDVH, - BioModelParamType aRho, BioModelParamType aAlphaMean, - BioModelParamType aAlphaVariance, double aDeltaV); - - protected: - BioModelParamType _alphaMean; - - BioModelParamType _alphaVariance; - - BioModelParamType _alpha_beta; - - /*! Roh is the initial clonogenic cell density - */ - BioModelParamType _rho; - - - /*! @brief Calculate the model value - @param doseFactor scaling factor for prescribed dose. The model calculation will use the dvh - with each di=old di*doseFactor. - @pre _alphaMean >0 - @pre _alphaVariance >= 0 - @pre _alpha_beta > 0 - @pre _rho > 0 + { + public: + typedef TCPModel::ParamVectorType ParamVectorType; + typedef TCPModel::DVHPointer DVHPointer; + + private: + /*! @brief Calculate intermediate tcp using alpha constant. This is a helper function for calcTCP() + @see calcTCP + */ + long double calcTCPi(BioModelParamType aRho, BioModelParamType aAlphaMean, double vj, double bedj); + + /*! @brief Calculate tcp using alpha constant. + */ + long double calcTCP(std::map aBEDDVH, BioModelParamType aRho, + BioModelParamType aAlphaMean, double aDeltaV); + + /*! @brief Calculate tcp using a normal distribution for alpha. + */ + long double calcTCPAlphaNormalDistribution(std::map aBEDDVH, + BioModelParamType aRho, BioModelParamType aAlphaMean, + BioModelParamType aAlphaVariance, double aDeltaV); + + protected: + BioModelParamType _alphaMean; + + BioModelParamType _alphaVariance; + + BioModelParamType _alpha_beta; + + /*! Roh is the initial clonogenic cell density + */ + BioModelParamType _rho; + + + /*! @brief Calculate the model value + @param doseFactor scaling factor for prescribed dose. The model calculation will use the dvh + with each di=old di*doseFactor. + @pre _alphaMean >0 + @pre _alphaVariance >= 0 + @pre _alpha_beta > 0 + @pre _rho > 0 @pre _numberOfFractions > 1 - @exception InvalidParameterException Thrown if parameters were not set correctly. - */ - BioModelValueType calcModel(const double doseFactor=1); + @exception InvalidParameterException Thrown if parameters were not set correctly. + */ + BioModelValueType calcModel(const double doseFactor = 1); - public: - TCPLQModel(); + public: + TCPLQModel(); - /*! @brief Constructor initializes member variables with given parameters. + /*! @brief Constructor initializes member variables with given parameters. @pre aAlphaMean >0 @pre aBeta > 0 @pre aRho > 0 @pre aNumberOfFractions > 1 - */ - TCPLQModel(DVHPointer aDVH, BioModelParamType aAlphaMean, BioModelParamType aBeta, BioModelParamType aRho, - int aNumberOfFractions); + */ + TCPLQModel(DVHPointer aDVH, BioModelParamType aAlphaMean, BioModelParamType aBeta, BioModelParamType aRho, + int aNumberOfFractions); - /*! @brief Constructor for alpha distribution initializes member variables with given parameters. + /*! @brief Constructor for alpha distribution initializes member variables with given parameters. @pre aAlphaMean >0 @pre aAlphaVariance >0 @pre aAlpha_Beta > 0 @pre aRho > 0 @pre aNumberOfFractions > 1 - */ - TCPLQModel(DVHPointer aDVH, BioModelParamType aRho, int aNumberOfFractions, BioModelParamType aAlpha_Beta, - BioModelParamType aAlphaMean, BioModelParamType aAlphaVariance); + */ + TCPLQModel(DVHPointer aDVH, BioModelParamType aRho, int aNumberOfFractions, BioModelParamType aAlpha_Beta, + BioModelParamType aAlphaMean, BioModelParamType aAlphaVariance); - const BioModelParamType getRho(); + const BioModelParamType getRho(); - void setRho(const BioModelParamType aRho); + void setRho(const BioModelParamType aRho); - const BioModelParamType getAlphaMean(); + const BioModelParamType getAlphaMean(); - const BioModelParamType getAlphaVariance(); + const BioModelParamType getAlphaVariance(); - /*! @brief The distribution of the parameter alpha, which is characteristic for a population of cells, - is described by the its mean and variance. If alpha is constant the variance is 0. - @param aAlphaVariance The variance of alpha can be given, the default value is 0 resulting in constant - alpha. - */ - void setAlpha(const BioModelParamType aAlphaMean, const BioModelParamType aAlphaVariance=0); + /*! @brief The distribution of the parameter alpha, which is characteristic for a population of cells, + is described by the its mean and variance. If alpha is constant the variance is 0. + @param aAlphaVariance The variance of alpha can be given, the default value is 0 resulting in constant + alpha. + */ + void setAlpha(const BioModelParamType aAlphaMean, const BioModelParamType aAlphaVariance = 0); - const BioModelParamType getAlpahBeta(); + const BioModelParamType getAlpahBeta(); - void setAlphaBeta(const BioModelParamType aAlpha_Beta); + void setAlphaBeta(const BioModelParamType aAlpha_Beta); - /*! @brief Set parameters for the TCP model. _value will be reset to 0. - @param aAlpha_Beta alpha/beta constant . - @param aAlphaMean mean of alpha distribution. - @param aAlphaVariance variance of alpha distribution. - */ - void setParameters(const BioModelParamType aAlphaMean, const BioModelParamType aAlpha_Beta, - const BioModelParamType aRho, const BioModelParamType aAlphaVariance=0); + /*! @brief Set parameters for the TCP model. _value will be reset to 0. + @param aAlpha_Beta alpha/beta constant . + @param aAlphaMean mean of alpha distribution. + @param aAlphaVariance variance of alpha distribution. + */ + void setParameters(const BioModelParamType aAlphaMean, const BioModelParamType aAlpha_Beta, + const BioModelParamType aRho, const BioModelParamType aAlphaVariance = 0); - /*! @brief Set parameter with ID. "alphaMean":0,"alphaVariance":1,"alpha_beta":2, "rho":3 - @exception InvalidParameterException Thrown if aParamId is not 0 or 1 or 2 or 3. - */ - virtual void setParameterByID(const int aParamId, const BioModelParamType aValue); + /*! @brief Set parameter with ID. "alphaMean":0,"alphaVariance":1,"alpha_beta":2, "rho":3 + @exception InvalidParameterException Thrown if aParamId is not 0 or 1 or 2 or 3. + */ + virtual void setParameterByID(const int aParamId, const BioModelParamType aValue); - /*! @brief Set parameter vector, where index of vector is the parameter id. - "alphaMean":0,"alphaVariance":1,"alpha_beta":2, "rho":3 - @exception InvalidParameterException Thrown if aParamterVector.size()!=4. - */ - virtual void setParameterVector(const ParamVectorType aParameterVector); + /*! @brief Set parameter vector, where index of vector is the parameter id. + "alphaMean":0,"alphaVariance":1,"alpha_beta":2, "rho":3 + @exception InvalidParameterException Thrown if aParamterVector.size()!=4. + */ + virtual void setParameterVector(const ParamVectorType& aParameterVector); - /*! @brief Get parameter id. "alphaMean":0,"alphaVariance":1,"alpha_beta":2, "rho":3 - @return 0 for "alphaMean", 1 for "alphaVariance", 2 for "alpha_beta", 3 for "rho" - @exception InvalidParameterException Thrown if aParamName is not alphaMean or alphaVariance or alpha_beta or rho. - */ - virtual const int getParameterID(const std::string aParamName) const; - }; + /*! @brief Get parameter id. "alphaMean":0,"alphaVariance":1,"alpha_beta":2, "rho":3 + @return 0 for "alphaMean", 1 for "alphaVariance", 2 for "alpha_beta", 3 for "rho" + @exception InvalidParameterException Thrown if aParamName is not alphaMean or alphaVariance or alpha_beta or rho. + */ + virtual const int getParameterID(const std::string& aParamName) const; + }; - }//end algorithms + }//end algorithms }//end rttb #endif diff --git a/testing/core/DVHSetTest.cpp b/testing/core/DVHSetTest.cpp index 731b0d1..4ad4577 100644 --- a/testing/core/DVHSetTest.cpp +++ b/testing/core/DVHSetTest.cpp @@ -1,168 +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 #include #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbDVH.h" #include "rttbDVHSet.h" #include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" #include "DummyDVHGenerator.h" -namespace rttb{ - namespace testing{ +namespace rttb +{ + namespace testing + { typedef core::DVHSet::DVHSetType DVHSetType; /*! @brief DVHTest - test the API of DVH 1) test constructors (values as expected?) 2) test size 3) test set/getIDs 4) test insert/retrieve individual DVHs 5) test getDVHSet 6) test getVolume */ - int DVHSetTest(int argc, char* argv[] ) - { + int DVHSetTest(int argc, char* argv[]) + { PREPARE_DEFAULT_TEST_REPORTING; const IDType structureSetID = "myStructureSet"; const IDType structureIDPrefix = "myStructure"; const IDType doseID = "myDose"; - const IDType voxelizationID = "myVoxelization"; - DummyDVHGenerator dvhGenerator; + DummyDVHGenerator dvhGenerator; DVHSetType tvSet; - IDType structureID = structureIDPrefix+"_TV_"; - for(int i = 0; i < 3; i++){ - tvSet.push_back(dvhGenerator.generateDVH(structureID+ boost::lexical_cast(i),doseID)); - } + IDType structureID = structureIDPrefix + "_TV_"; + + for (int i = 0; i < 3; i++) + { + tvSet.push_back(dvhGenerator.generateDVH(structureID + boost::lexical_cast(i), doseID)); + } + DVHSetType htSet; - structureID = structureIDPrefix+"_HT_"; - for(int i = 0; i < 5; i++){ - htSet.push_back(dvhGenerator.generateDVH(structureID+ boost::lexical_cast(i),doseID)); - } + structureID = structureIDPrefix + "_HT_"; + + for (int i = 0; i < 5; i++) + { + htSet.push_back(dvhGenerator.generateDVH(structureID + boost::lexical_cast(i), doseID)); + } + DVHSetType wvSet; - structureID = structureIDPrefix+"_WV_"; - for(int i = 0; i < 1; i++){ - wvSet.push_back(dvhGenerator.generateDVH(structureID+ boost::lexical_cast(i),doseID)); - } + structureID = structureIDPrefix + "_WV_"; + + for (int i = 0; i < 1; i++) + { + wvSet.push_back(dvhGenerator.generateDVH(structureID + boost::lexical_cast(i), doseID)); + } //1) test constructors (values as expected?) CHECK_NO_THROW(core::DVHSet(structureSetID, doseID)); CHECK_NO_THROW(core::DVHSet(tvSet, htSet, structureSetID, doseID)); CHECK_NO_THROW(core::DVHSet(tvSet, htSet, wvSet, structureSetID, doseID)); //2) test size core::DVHSet myDvhSet1(structureSetID, doseID); - CHECK_EQUAL(myDvhSet1.size(),0); + CHECK_EQUAL(myDvhSet1.size(), 0); core::DVHSet myDvhSet2(tvSet, htSet, structureSetID, doseID); - CHECK_EQUAL(myDvhSet2.size(),tvSet.size()+htSet.size()); + CHECK_EQUAL(myDvhSet2.size(), tvSet.size() + htSet.size()); core::DVHSet myDvhSet3(tvSet, htSet, wvSet, structureSetID, doseID); - CHECK_EQUAL(myDvhSet3.size(),tvSet.size()+htSet.size()+wvSet.size()); + CHECK_EQUAL(myDvhSet3.size(), tvSet.size() + htSet.size() + wvSet.size()); //3) test set/getIDs const IDType newStructureSetID = "myNewStructureSet"; const IDType newDoseID = "myNewDose"; - CHECK_EQUAL(myDvhSet1.getStrSetID(),structureSetID); - CHECK_EQUAL(myDvhSet1.getDoseID(),doseID); + CHECK_EQUAL(myDvhSet1.getStrSetID(), structureSetID); + CHECK_EQUAL(myDvhSet1.getDoseID(), doseID); CHECK_NO_THROW(myDvhSet1.setStrSetID(newStructureSetID)); CHECK_NO_THROW(myDvhSet1.setDoseID(newDoseID)); - CHECK_EQUAL(myDvhSet1.getStrSetID(),newStructureSetID); - CHECK_EQUAL(myDvhSet1.getDoseID(),newDoseID); + CHECK_EQUAL(myDvhSet1.getStrSetID(), newStructureSetID); + CHECK_EQUAL(myDvhSet1.getDoseID(), newDoseID); - CHECK_EQUAL(myDvhSet3.getStrSetID(),structureSetID); - CHECK_EQUAL(myDvhSet3.getDoseID(),doseID); + CHECK_EQUAL(myDvhSet3.getStrSetID(), structureSetID); + CHECK_EQUAL(myDvhSet3.getDoseID(), doseID); CHECK_NO_THROW(myDvhSet3.setStrSetID(newStructureSetID)); CHECK_NO_THROW(myDvhSet3.setDoseID(newDoseID)); - CHECK_EQUAL(myDvhSet3.getStrSetID(),newStructureSetID); - CHECK_EQUAL(myDvhSet3.getDoseID(),newDoseID); + CHECK_EQUAL(myDvhSet3.getStrSetID(), newStructureSetID); + CHECK_EQUAL(myDvhSet3.getDoseID(), newDoseID); //4) test insert/retrieve individual DVHs DVHRole roleTV = {DVHRole::TargetVolume}; - structureID = structureIDPrefix+"_TV_"; - core::DVH tv = dvhGenerator.generateDVH(structureID+ boost::lexical_cast(tvSet.size()),doseID); - CHECK_EQUAL(myDvhSet1.size(),0); + structureID = structureIDPrefix + "_TV_"; + core::DVH tv = dvhGenerator.generateDVH(structureID + boost::lexical_cast(tvSet.size()), doseID); + CHECK_EQUAL(myDvhSet1.size(), 0); CHECK_NO_THROW(myDvhSet1.insert(tv, roleTV)); - CHECK_EQUAL(myDvhSet1.size(),1); + CHECK_EQUAL(myDvhSet1.size(), 1); std::size_t currentSize = myDvhSet2.size(); CHECK_NO_THROW(myDvhSet2.insert(tv, roleTV)); - CHECK_EQUAL(myDvhSet2.size(),currentSize+1); + CHECK_EQUAL(myDvhSet2.size(), currentSize + 1); DVHRole roleHT = {DVHRole::HealthyTissue}; - structureID = structureIDPrefix+"_HT_"; - core::DVH ht = dvhGenerator.generateDVH(structureID+ boost::lexical_cast(htSet.size()),doseID); - CHECK_EQUAL(myDvhSet1.size(),1); + structureID = structureIDPrefix + "_HT_"; + core::DVH ht = dvhGenerator.generateDVH(structureID + boost::lexical_cast(htSet.size()), doseID); + CHECK_EQUAL(myDvhSet1.size(), 1); CHECK_NO_THROW(myDvhSet1.insert(ht, roleHT)); - CHECK_EQUAL(myDvhSet1.size(),2); + CHECK_EQUAL(myDvhSet1.size(), 2); currentSize = myDvhSet2.size(); CHECK_NO_THROW(myDvhSet2.insert(ht, roleHT)); - CHECK_EQUAL(myDvhSet2.size(),currentSize+1); + CHECK_EQUAL(myDvhSet2.size(), currentSize + 1); DVHRole roleWV = {DVHRole::WholeVolume}; - structureID = structureIDPrefix+"_wv_"; - IDType testID = structureID+ boost::lexical_cast(wvSet.size()); - core::DVH wv = dvhGenerator.generateDVH(structureID+ boost::lexical_cast(wvSet.size()),doseID); - CHECK_EQUAL(myDvhSet1.size(),2); + structureID = structureIDPrefix + "_wv_"; + IDType testID = structureID + boost::lexical_cast(wvSet.size()); + core::DVH wv = dvhGenerator.generateDVH(structureID + boost::lexical_cast(wvSet.size()), doseID); + CHECK_EQUAL(myDvhSet1.size(), 2); CHECK_NO_THROW(myDvhSet1.insert(wv, roleWV)); - CHECK_EQUAL(myDvhSet1.size(),3); + CHECK_EQUAL(myDvhSet1.size(), 3); currentSize = myDvhSet2.size(); CHECK_NO_THROW(myDvhSet2.insert(wv, roleWV)); - CHECK_EQUAL(myDvhSet2.size(),currentSize+1); + CHECK_EQUAL(myDvhSet2.size(), currentSize + 1); //5) test getDVHSet core::DVH* dvhPtr = myDvhSet1.getDVH(testID); - CHECK_EQUAL(*dvhPtr,wv); + CHECK_EQUAL(*dvhPtr, wv); - dvhPtr = myDvhSet3.getDVH(structureIDPrefix+"_TV_0"); - CHECK_EQUAL(*dvhPtr,tvSet.at(0)); + dvhPtr = myDvhSet3.getDVH(structureIDPrefix + "_TV_0"); + CHECK_EQUAL(*dvhPtr, tvSet.at(0)); - dvhPtr = myDvhSet3.getDVH(structureIDPrefix+"_TV_2"); - CHECK_EQUAL(*dvhPtr,tvSet.at(2)); + dvhPtr = myDvhSet3.getDVH(structureIDPrefix + "_TV_2"); + CHECK_EQUAL(*dvhPtr, tvSet.at(2)); DVHSetType tvTest = myDvhSet3.getTargetVolumeSet(); - CHECK_EQUAL(tvTest,tvSet); + CHECK_EQUAL(tvTest, tvSet); DVHSetType htTest = myDvhSet3.getHealthyTissueSet(); - CHECK_EQUAL(htTest,htSet); + CHECK_EQUAL(htTest, htSet); - DVHSetType wvTest = myDvhSet3.getWholeVolumeSet(); - CHECK_EQUAL(wvTest,wvSet); + DVHSetType wvTest = myDvhSet3.getWholeVolumeSet(); + CHECK_EQUAL(wvTest, wvSet); //6) test getVolume DoseTypeGy aDoseAbsolute = 10; - CHECK_EQUAL(0,myDvhSet3.getHealthyTissueVolume(aDoseAbsolute)); - CHECK_EQUAL(0,myDvhSet3.getTargetVolume(aDoseAbsolute)); - CHECK_EQUAL(0,myDvhSet3.getWholeVolume(aDoseAbsolute)); + CHECK_EQUAL(0, myDvhSet3.getHealthyTissueVolume(aDoseAbsolute)); + CHECK_EQUAL(0, myDvhSet3.getTargetVolume(aDoseAbsolute)); + CHECK_EQUAL(0, myDvhSet3.getWholeVolume(aDoseAbsolute)); RETURN_AND_REPORT_TEST_SUCCESS; - } + } - }//end namespace testing - }//end namespace rttb + }//end namespace testing +}//end namespace rttb diff --git a/testing/core/DummyDVHGenerator.cpp b/testing/core/DummyDVHGenerator.cpp index 7abd3c4..b23e32a 100644 --- a/testing/core/DummyDVHGenerator.cpp +++ b/testing/core/DummyDVHGenerator.cpp @@ -1,85 +1,109 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include #include "DummyDVHGenerator.h" -namespace rttb{ - namespace testing{ +namespace rttb +{ + namespace testing + { DummyDVHGenerator::DummyDVHGenerator(): _binSize(DoseTypeGy(0.1)), _voxelVolume(8), _value(0) { /* initialize random seed: */ - srand (time(NULL)); + srand(static_cast(time(NULL))); }; - core::DVH DummyDVHGenerator::generateDVH(IDType structureID,IDType doseID){ + core::DVH DummyDVHGenerator::generateDVH(IDType structureID, IDType doseID) + { core::DVH::DataDifferentialType aDataDifferential; - for(int i = 0; i < 100; i++){ - _value = DoseCalcType((double(rand())/RAND_MAX)*1000); + + for (int i = 0; i < 100; i++) + { + _value = DoseCalcType((double(rand()) / RAND_MAX) * 1000); //cut off values to avoid problems on comparisson with reimported values after //writing to file. - _value = floor(_value *1000000)/1000000; - aDataDifferential.push_back( _value ); - } - return core::DVH(aDataDifferential, _binSize, _voxelVolume, structureID, doseID); + _value = floor(_value * 1000000) / 1000000; + aDataDifferential.push_back(_value); } - core::DVH DummyDVHGenerator::generateDVH(IDType structureID,IDType doseID, DoseCalcType value){ + return core::DVH(aDataDifferential, _binSize, _voxelVolume, structureID, doseID); + } + + core::DVH DummyDVHGenerator::generateDVH(IDType structureID, IDType doseID, DoseCalcType value) + { _value = value; - + core::DVH::DataDifferentialType aDataDifferential; - for(int i = 0; i < 100; i++){ - aDataDifferential.push_back( _value ); - } + + for (int i = 0; i < 100; i++) + { + aDataDifferential.push_back(_value); + } + return core::DVH(aDataDifferential, _binSize, _voxelVolume, structureID, doseID); } - core::DVH DummyDVHGenerator::generateDVH(IDType structureID,IDType doseID, DoseCalcType minValue, DoseCalcType maxValue){ - _voxelVolume = 0.2*0.2*0.4; + core::DVH DummyDVHGenerator::generateDVH(IDType structureID, IDType doseID, DoseCalcType minValue, + DoseCalcType maxValue) + { + _voxelVolume = 0.2 * 0.2 * 0.4; bool decrease = false; - + core::DVH::DataDifferentialType aDataDifferential; - for(int i = 0; i <= 200; i++){ - if ((i > 20) && (i < 180)){ - if ((_value == 0) && (!decrease)) { - _value = DoseCalcType((double(rand())/RAND_MAX)*10)+minValue; + + for (int i = 0; i <= 200; i++) + { + if ((i > 20) && (i < 180)) + { + if ((_value == 0) && (!decrease)) + { + _value = DoseCalcType((double(rand()) / RAND_MAX) * 10) + minValue; } - else if (!decrease){ - _value = _value + DoseCalcType((double(rand())/RAND_MAX)*(maxValue/10)); + else if (!decrease) + { + _value = _value + DoseCalcType((double(rand()) / RAND_MAX) * (maxValue / 10)); } - if ( (_value > maxValue) || (decrease) ){ + + if ((_value > maxValue) || (decrease)) + { decrease = true; - _value = _value - DoseCalcType((double(rand())/RAND_MAX)*(maxValue/3)); + _value = _value - DoseCalcType((double(rand()) / RAND_MAX) * (maxValue / 3)); } - if (_value < 0) { + + if (_value < 0) + { _value = 0; } } - else{ + else + { _value = 0; } - aDataDifferential.push_back( _value ); + + aDataDifferential.push_back(_value); } + return core::DVH(aDataDifferential, _binSize, _voxelVolume, structureID, doseID); } } } \ No newline at end of file diff --git a/testing/core/DummyStructure.cpp b/testing/core/DummyStructure.cpp index 74c5eee..cd5c3e5 100644 --- a/testing/core/DummyStructure.cpp +++ b/testing/core/DummyStructure.cpp @@ -1,603 +1,635 @@ // ----------------------------------------------------------------------- // 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 "DummyStructure.h" #include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" #include "rttbInvalidDoseException.h" -namespace rttb{ - namespace testing{ +namespace rttb +{ + namespace testing + { - DummyStructure::~DummyStructure(){} + DummyStructure::~DummyStructure() {} - DummyStructure::DummyStructure(const core::GeometricInfo& aGeoInfo){ - _geoInfo = aGeoInfo; - } + DummyStructure::DummyStructure(const core::GeometricInfo& aGeoInfo) + { + _geoInfo = aGeoInfo; + } - core::Structure DummyStructure::CreateRectangularStructureCentered(GridIndexType zPlane){ + core::Structure DummyStructure::CreateRectangularStructureCentered(GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(2,1); - VoxelGridIndex2D another_i2(5,1); - VoxelGridIndex2D another_i3(5,5); - VoxelGridIndex2D another_i4(2,5); + VoxelGridIndex2D another_i1(2, 1); + VoxelGridIndex2D another_i2(5, 1); + VoxelGridIndex2D another_i3(5, 5); + VoxelGridIndex2D another_i4(2, 5); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); - another_voxelVector.push_back(another_i4); - PolygonType another_polygon1 = another_cts.createPolygonCenter( another_voxelVector , zPlane ); + another_voxelVector.push_back(another_i4); + PolygonType another_polygon1 = another_cts.createPolygonCenter(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure_rectangular_centered = core::Structure( another_polySeq ); + core::Structure test_structure_rectangular_centered = core::Structure(another_polySeq); return test_structure_rectangular_centered; - } + } - core::Structure DummyStructure::CreateRectangularStructureCenteredRotatedIntermediatePlacement(GridIndexType zPlane){ + core::Structure DummyStructure::CreateRectangularStructureCenteredRotatedIntermediatePlacement(GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(5,1); - VoxelGridIndex2D another_i2(8,4); - VoxelGridIndex2D another_i3(5,7); - VoxelGridIndex2D another_i4(2,4); + VoxelGridIndex2D another_i1(5, 1); + VoxelGridIndex2D another_i2(8, 4); + VoxelGridIndex2D another_i3(5, 7); + VoxelGridIndex2D another_i4(2, 4); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); - another_voxelVector.push_back(another_i4); - PolygonType another_polygon1 = another_cts.createPolygonBetweenUpperLeftAndCenter( another_voxelVector , zPlane ); + another_voxelVector.push_back(another_i4); + PolygonType another_polygon1 = another_cts.createPolygonBetweenUpperLeftAndCenter(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); return test_structure; - } + } - core::Structure DummyStructure::CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRight(GridIndexType zPlane){ + core::Structure DummyStructure::CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRight( + GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(5,1); - VoxelGridIndex2D another_i2(8,4); - VoxelGridIndex2D another_i3(5,7); - VoxelGridIndex2D another_i4(2,4); + VoxelGridIndex2D another_i1(5, 1); + VoxelGridIndex2D another_i2(8, 4); + VoxelGridIndex2D another_i3(5, 7); + VoxelGridIndex2D another_i4(2, 4); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); - another_voxelVector.push_back(another_i4); - PolygonType another_polygon1 = another_cts.createPolygonBetweenLowerRightAndCenter( another_voxelVector , zPlane ); + another_voxelVector.push_back(another_i4); PolygonSequenceType another_polySeq; - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); return test_structure; - } + } - core::Structure DummyStructure::CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRightCounterClock(GridIndexType zPlane){ + core::Structure DummyStructure::CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRightCounterClock( + GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(2,4); - VoxelGridIndex2D another_i2(5,7); - VoxelGridIndex2D another_i3(8,4); - VoxelGridIndex2D another_i4(5,1); + VoxelGridIndex2D another_i1(2, 4); + VoxelGridIndex2D another_i2(5, 7); + VoxelGridIndex2D another_i3(8, 4); + VoxelGridIndex2D another_i4(5, 1); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); - another_voxelVector.push_back(another_i4); - PolygonType another_polygon1 = another_cts.createPolygonBetweenLowerRightAndCenter( another_voxelVector , zPlane ); + another_voxelVector.push_back(another_i4); + PolygonType another_polygon1 = another_cts.createPolygonBetweenLowerRightAndCenter(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); return test_structure; - } + } - core::Structure DummyStructure::CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRightCounterClockIntermediatePoints(GridIndexType zPlane){ + core::Structure + DummyStructure::CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRightCounterClockIntermediatePoints( + GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(2,4); - VoxelGridIndex2D another_i2(5,7); - VoxelGridIndex2D another_i3(8,4); - VoxelGridIndex2D another_i4(5,1); + VoxelGridIndex2D another_i1(2, 4); + VoxelGridIndex2D another_i2(5, 7); + VoxelGridIndex2D another_i3(8, 4); + VoxelGridIndex2D another_i4(5, 1); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); - another_voxelVector.push_back(another_i4); - PolygonType another_polygon1 = another_cts.createPolygonIntermediatePoints( another_voxelVector , zPlane ); + another_voxelVector.push_back(another_i4); + PolygonType another_polygon1 = another_cts.createPolygonIntermediatePoints(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); return test_structure; - } + } - core::Structure DummyStructure::CreateTestStructureSeveralSeperateSectionsInsideOneVoxel(GridIndexType zPlane){ + core::Structure DummyStructure::CreateTestStructureSeveralSeperateSectionsInsideOneVoxel(GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(2,2); + VoxelGridIndex2D another_i1(2, 2); another_voxelVector.push_back(another_i1); - PolygonType another_polygon1 = another_cts.createStructureSeveralSectionsInsideOneVoxelA( another_voxelVector , zPlane ); + PolygonType another_polygon1 = another_cts.createStructureSeveralSectionsInsideOneVoxelA(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); - return test_structure; - } + return test_structure; + } - core::Structure DummyStructure::CreateTestStructureSelfTouchingA(GridIndexType zPlane){ + core::Structure DummyStructure::CreateTestStructureSelfTouchingA(GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(2,2); + VoxelGridIndex2D another_i1(2, 2); another_voxelVector.push_back(another_i1); - PolygonType another_polygon1 = another_cts.createStructureSelfTouchingA( another_voxelVector , zPlane ); + PolygonType another_polygon1 = another_cts.createStructureSelfTouchingA(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); - return test_structure; - } + return test_structure; + } - core::Structure DummyStructure::CreateTestStructureIntersectingTwoPolygonsInDifferentSlices(GridIndexType zPlane1, GridIndexType zPlane2){ + core::Structure DummyStructure::CreateTestStructureIntersectingTwoPolygonsInDifferentSlices(GridIndexType zPlane1, + GridIndexType zPlane2) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); CreateTestStructure one_more_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(2,4); - VoxelGridIndex2D another_i2(8,4); - VoxelGridIndex2D another_i3(8,6); - VoxelGridIndex2D another_i4(2,6); + VoxelGridIndex2D another_i1(2, 4); + VoxelGridIndex2D another_i2(8, 4); + VoxelGridIndex2D another_i3(8, 6); + VoxelGridIndex2D another_i4(2, 6); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); - another_voxelVector.push_back(another_i4); - PolygonType another_polygon1 = another_cts.createPolygonCenter( another_voxelVector , zPlane1 ); + another_voxelVector.push_back(another_i4); + PolygonType another_polygon1 = another_cts.createPolygonCenter(another_voxelVector , zPlane1); std::vector one_more_voxelVector; - VoxelGridIndex2D one_more_i1(3,5); - VoxelGridIndex2D one_more_i2(9,5); - VoxelGridIndex2D one_more_i3(9,7); - VoxelGridIndex2D one_more_i4(3,7); + VoxelGridIndex2D one_more_i1(3, 5); + VoxelGridIndex2D one_more_i2(9, 5); + VoxelGridIndex2D one_more_i3(9, 7); + VoxelGridIndex2D one_more_i4(3, 7); one_more_voxelVector.push_back(one_more_i1); one_more_voxelVector.push_back(one_more_i2); one_more_voxelVector.push_back(one_more_i3); - one_more_voxelVector.push_back(one_more_i4); - PolygonType another_polygon2 = one_more_cts.createPolygonCenter( one_more_voxelVector , zPlane2 ); + one_more_voxelVector.push_back(one_more_i4); + PolygonType another_polygon2 = one_more_cts.createPolygonCenter(one_more_voxelVector , zPlane2); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); - another_polySeq.push_back( another_polygon2 ); + another_polySeq.push_back(another_polygon1); + another_polySeq.push_back(another_polygon2); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); - return test_structure; - } + return test_structure; + } - core::Structure DummyStructure::CreateTestStructureIntersectingTwoPolygons(GridIndexType zPlane){ + core::Structure DummyStructure::CreateTestStructureIntersectingTwoPolygons(GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); CreateTestStructure one_more_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(2,4); - VoxelGridIndex2D another_i2(8,4); - VoxelGridIndex2D another_i3(8,6); - VoxelGridIndex2D another_i4(2,6); + VoxelGridIndex2D another_i1(2, 4); + VoxelGridIndex2D another_i2(8, 4); + VoxelGridIndex2D another_i3(8, 6); + VoxelGridIndex2D another_i4(2, 6); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); - another_voxelVector.push_back(another_i4); - PolygonType another_polygon1 = another_cts.createPolygonCenter( another_voxelVector , zPlane ); + another_voxelVector.push_back(another_i4); + PolygonType another_polygon1 = another_cts.createPolygonCenter(another_voxelVector , zPlane); std::vector one_more_voxelVector; - VoxelGridIndex2D one_more_i1(3,5); - VoxelGridIndex2D one_more_i2(9,5); - VoxelGridIndex2D one_more_i3(9,7); - VoxelGridIndex2D one_more_i4(3,7); + VoxelGridIndex2D one_more_i1(3, 5); + VoxelGridIndex2D one_more_i2(9, 5); + VoxelGridIndex2D one_more_i3(9, 7); + VoxelGridIndex2D one_more_i4(3, 7); one_more_voxelVector.push_back(one_more_i1); one_more_voxelVector.push_back(one_more_i2); one_more_voxelVector.push_back(one_more_i3); - one_more_voxelVector.push_back(one_more_i4); - PolygonType another_polygon2 = one_more_cts.createPolygonCenter( one_more_voxelVector , zPlane ); + one_more_voxelVector.push_back(one_more_i4); + PolygonType another_polygon2 = one_more_cts.createPolygonCenter(one_more_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); - another_polySeq.push_back( another_polygon2 ); + another_polySeq.push_back(another_polygon1); + another_polySeq.push_back(another_polygon2); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); return test_structure; - } + } - core::Structure DummyStructure::CreateTestStructureIntersecting(GridIndexType zPlane){ + core::Structure DummyStructure::CreateTestStructureIntersecting(GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(2,4); - VoxelGridIndex2D another_i2(8,4); - VoxelGridIndex2D another_i3(2,6); - VoxelGridIndex2D another_i4(8,6); + VoxelGridIndex2D another_i1(2, 4); + VoxelGridIndex2D another_i2(8, 4); + VoxelGridIndex2D another_i3(2, 6); + VoxelGridIndex2D another_i4(8, 6); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); - another_voxelVector.push_back(another_i4); - PolygonType another_polygon1 = another_cts.createPolygonCenter( another_voxelVector , zPlane ); + another_voxelVector.push_back(another_i4); + PolygonType another_polygon1 = another_cts.createPolygonCenter(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); - return test_structure; - } + return test_structure; + } - core::Structure DummyStructure::CreateTestStructureInsideInsideTouches(GridIndexType zPlane){ + core::Structure DummyStructure::CreateTestStructureInsideInsideTouches(GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(3,4); - VoxelGridIndex2D another_i2(2,8); - VoxelGridIndex2D another_i3(4,8); + VoxelGridIndex2D another_i1(3, 4); + VoxelGridIndex2D another_i2(2, 8); + VoxelGridIndex2D another_i3(4, 8); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); - PolygonType another_polygon1 = another_cts.createPolygonUpperCenter( another_voxelVector , zPlane ); + PolygonType another_polygon1 = another_cts.createPolygonUpperCenter(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); return test_structure; - } + } - core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesRotatedPointDoubeled(GridIndexType zPlane){ + core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesRotatedPointDoubeled(GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(2,4); - VoxelGridIndex2D another_i4(2,4); - VoxelGridIndex2D another_i2(4,4); - VoxelGridIndex2D another_i3(3,8); + VoxelGridIndex2D another_i1(2, 4); + VoxelGridIndex2D another_i4(2, 4); + VoxelGridIndex2D another_i2(4, 4); + VoxelGridIndex2D another_i3(3, 8); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i4); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); - PolygonType another_polygon1 = another_cts.createPolygonUpperCenter( another_voxelVector , zPlane ); + PolygonType another_polygon1 = another_cts.createPolygonUpperCenter(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); - return test_structure; - } + return test_structure; + } - core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesCounterClockRotatedOnePointFivePi(GridIndexType zPlane){ + core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesCounterClockRotatedOnePointFivePi( + GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(3,5); - VoxelGridIndex2D another_i2(3,5); - VoxelGridIndex2D another_i3(7,6); - VoxelGridIndex2D another_i4(7,6); - VoxelGridIndex2D another_i5(7,4); - VoxelGridIndex2D another_i6(7,4); + VoxelGridIndex2D another_i1(3, 5); + VoxelGridIndex2D another_i2(3, 5); + VoxelGridIndex2D another_i3(7, 6); + VoxelGridIndex2D another_i4(7, 6); + VoxelGridIndex2D another_i5(7, 4); + VoxelGridIndex2D another_i6(7, 4); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); another_voxelVector.push_back(another_i5); another_voxelVector.push_back(another_i6); - PolygonType another_polygon1 = another_cts.createPolygonLeftEdgeMiddle( another_voxelVector , zPlane ); + PolygonType another_polygon1 = another_cts.createPolygonLeftEdgeMiddle(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); - return test_structure; - } + return test_structure; + } - core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesCounterClockRotatedQuaterPi(GridIndexType zPlane){ + core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesCounterClockRotatedQuaterPi(GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(7,5); - VoxelGridIndex2D another_i2(7,5); - VoxelGridIndex2D another_i3(3,6); - VoxelGridIndex2D another_i4(3,6); - VoxelGridIndex2D another_i5(3,4); - VoxelGridIndex2D another_i6(3,4); + VoxelGridIndex2D another_i1(7, 5); + VoxelGridIndex2D another_i2(7, 5); + VoxelGridIndex2D another_i3(3, 6); + VoxelGridIndex2D another_i4(3, 6); + VoxelGridIndex2D another_i5(3, 4); + VoxelGridIndex2D another_i6(3, 4); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); another_voxelVector.push_back(another_i5); another_voxelVector.push_back(another_i6); - PolygonType another_polygon1 = another_cts.createPolygonLeftEdgeMiddle( another_voxelVector , zPlane ); + PolygonType another_polygon1 = another_cts.createPolygonLeftEdgeMiddle(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); - return test_structure; - } + return test_structure; + } - core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesRotatedQuaterPi(GridIndexType zPlane){ + core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesRotatedQuaterPi(GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(3,4); - VoxelGridIndex2D another_i2(3,4); - VoxelGridIndex2D another_i3(3,6); - VoxelGridIndex2D another_i4(3,6); - VoxelGridIndex2D another_i5(7,5); - VoxelGridIndex2D another_i6(7,5); + VoxelGridIndex2D another_i1(3, 4); + VoxelGridIndex2D another_i2(3, 4); + VoxelGridIndex2D another_i3(3, 6); + VoxelGridIndex2D another_i4(3, 6); + VoxelGridIndex2D another_i5(7, 5); + VoxelGridIndex2D another_i6(7, 5); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); another_voxelVector.push_back(another_i5); another_voxelVector.push_back(another_i6); - PolygonType another_polygon1 = another_cts.createPolygonLeftEdgeMiddle( another_voxelVector , zPlane ); + PolygonType another_polygon1 = another_cts.createPolygonLeftEdgeMiddle(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); - return test_structure; - } + return test_structure; + } - core::Structure DummyStructure::CreateTestStructureCircle(GridIndexType zPlane){ + core::Structure DummyStructure::CreateTestStructureCircle(GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(4,4); + VoxelGridIndex2D another_i1(4, 4); another_voxelVector.push_back(another_i1); - PolygonType another_polygon1 = another_cts.createPolygonCircle( another_voxelVector , zPlane ); + PolygonType another_polygon1 = another_cts.createPolygonCircle(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); - return test_structure; - } + return test_structure; + } - core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesUpperRight(GridIndexType zPlane){ + core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesUpperRight(GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(3,4); - VoxelGridIndex2D another_i3(4,5); - VoxelGridIndex2D another_i5(5,3); + VoxelGridIndex2D another_i1(3, 4); + VoxelGridIndex2D another_i3(4, 5); + VoxelGridIndex2D another_i5(5, 3); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i5); - PolygonType another_polygon1 = another_cts.createPolygonLeftUpper( another_voxelVector , zPlane ); + PolygonType another_polygon1 = another_cts.createPolygonLeftUpper(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); - return test_structure; - } + return test_structure; + } - core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesLowerRight(GridIndexType zPlane){ + core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesLowerRight(GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(2,2); - VoxelGridIndex2D another_i2(2,2); - VoxelGridIndex2D another_i3(3,1); - VoxelGridIndex2D another_i4(3,1); - VoxelGridIndex2D another_i5(4,3); - VoxelGridIndex2D another_i6(4,3); + VoxelGridIndex2D another_i1(2, 2); + VoxelGridIndex2D another_i2(2, 2); + VoxelGridIndex2D another_i3(3, 1); + VoxelGridIndex2D another_i4(3, 1); + VoxelGridIndex2D another_i5(4, 3); + VoxelGridIndex2D another_i6(4, 3); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); another_voxelVector.push_back(another_i5); another_voxelVector.push_back(another_i6); - PolygonType another_polygon1 = another_cts.createPolygonLeftUpper( another_voxelVector , zPlane ); + PolygonType another_polygon1 = another_cts.createPolygonLeftUpper(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); - return test_structure; - } + return test_structure; + } - core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesLowerLeft(GridIndexType zPlane){ + core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesLowerLeft(GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(3,3); - VoxelGridIndex2D another_i2(3,3); - VoxelGridIndex2D another_i3(4,4); - VoxelGridIndex2D another_i4(4,4); - VoxelGridIndex2D another_i5(2,5); - VoxelGridIndex2D another_i6(2,5); + VoxelGridIndex2D another_i1(3, 3); + VoxelGridIndex2D another_i2(3, 3); + VoxelGridIndex2D another_i3(4, 4); + VoxelGridIndex2D another_i4(4, 4); + VoxelGridIndex2D another_i5(2, 5); + VoxelGridIndex2D another_i6(2, 5); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); another_voxelVector.push_back(another_i5); another_voxelVector.push_back(another_i6); - PolygonType another_polygon1 = another_cts.createPolygonLeftUpper( another_voxelVector , zPlane ); + PolygonType another_polygon1 = another_cts.createPolygonLeftUpper(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); - return test_structure; - } + return test_structure; + } - core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesUpperLeft(GridIndexType zPlane){ + core::Structure DummyStructure::CreateTestStructureInsideInsideTouchesUpperLeft(GridIndexType zPlane) + { CreateTestStructure another_cts = CreateTestStructure(_geoInfo); std::vector another_voxelVector; - VoxelGridIndex2D another_i1(5,5); - VoxelGridIndex2D another_i2(5,5); - VoxelGridIndex2D another_i3(4,6); - VoxelGridIndex2D another_i4(4,6); - VoxelGridIndex2D another_i5(3,4); - VoxelGridIndex2D another_i6(3,4); + VoxelGridIndex2D another_i1(5, 5); + VoxelGridIndex2D another_i2(5, 5); + VoxelGridIndex2D another_i3(4, 6); + VoxelGridIndex2D another_i4(4, 6); + VoxelGridIndex2D another_i5(3, 4); + VoxelGridIndex2D another_i6(3, 4); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); another_voxelVector.push_back(another_i4); another_voxelVector.push_back(another_i5); another_voxelVector.push_back(another_i6); - PolygonType another_polygon1 = another_cts.createPolygonLeftUpper( another_voxelVector , zPlane ); + PolygonType another_polygon1 = another_cts.createPolygonLeftUpper(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); - return test_structure; - } + return test_structure; + } - void DummyStructure::ShowTestStructure( core::Structure aStructure ){ + void DummyStructure::ShowTestStructure(core::Structure aStructure) + { WorldCoordinate3D aPoint(0); - PolygonSequenceType strVector =aStructure.getStructureVector(); + PolygonSequenceType strVector = aStructure.getStructureVector(); - for( unsigned int struct_index = 0 ; struct_index < strVector.size() ; struct_index++ ){ + for (unsigned int struct_index = 0 ; struct_index < strVector.size() ; struct_index++) + { - for( int point_index = 0 ; point_index < strVector.at(struct_index).size() ; point_index++ ){ + for (int point_index = 0 ; point_index < strVector.at(struct_index).size() ; point_index++) + { - aPoint = strVector.at(struct_index).at( point_index ); + aPoint = strVector.at(struct_index).at(point_index); - std::cout<< " aPoint.x " << aPoint.x() < another_voxelVector; - VoxelGridIndex2D another_i1(5,1); - VoxelGridIndex2D another_i2(8,4); - VoxelGridIndex2D another_i3(5,7); - VoxelGridIndex2D another_i4(2,4); + VoxelGridIndex2D another_i1(5, 1); + VoxelGridIndex2D another_i2(8, 4); + VoxelGridIndex2D another_i3(5, 7); + VoxelGridIndex2D another_i4(2, 4); another_voxelVector.push_back(another_i1); another_voxelVector.push_back(another_i2); another_voxelVector.push_back(another_i3); - another_voxelVector.push_back(another_i4); - PolygonType another_polygon1 = another_cts.createPolygonLeftUpper( another_voxelVector , zPlane ); + another_voxelVector.push_back(another_i4); + PolygonType another_polygon1 = another_cts.createPolygonLeftUpper(another_voxelVector , zPlane); PolygonSequenceType another_polySeq; - another_polySeq.push_back( another_polygon1 ); + another_polySeq.push_back(another_polygon1); - core::Structure test_structure = core::Structure( another_polySeq ); + core::Structure test_structure = core::Structure(another_polySeq); return test_structure; - } + } - }//testing - }//rttb + }//testing +}//rttb diff --git a/testing/examples/DVHCalculatorComparisonTest.cpp b/testing/examples/DVHCalculatorComparisonTest.cpp index dbf2447..e562487 100644 --- a/testing/examples/DVHCalculatorComparisonTest.cpp +++ b/testing/examples/DVHCalculatorComparisonTest.cpp @@ -1,373 +1,373 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html [^] // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests #include #include #include #include "litCheckMacros.h" #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmrt/drtdose.h" #include "dcmtk/dcmrt/drtstrct.h" #include "rttbBaseType.h" #include "rttbDVHCalculator.h" #include "rttbGenericMaskedDoseIterator.h" #include "rttbGenericDoseIterator.h" #include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" #include "rttbDicomDoseAccessor.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomFileStructureSetGenerator.h" #include "rttbOTBMaskAccessor.h" #include "rttbDVHTxtFileReader.h" namespace rttb { namespace testing { /*! @brief DVHCalculatorTest. Test if calculation in new architecture returns similar results to the original implementation. WARNING: The values for comparison need to be adjusted if the input files are changed! This test can be used to get more detailed information, but it will always fail, because differences in voxelization accuracy, especially the ones caused by the change from double to float precission will not cause considerable deviations in the structure sizes, which correspond to considerable differences in the calculated DVHs. Even in double precission differences up to 0.005 between values from old and new implementation can occure. */ int DVHCalculatorComparisonTest(int argc, char* argv[]) { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef core::GenericMaskedDoseIterator::MaskAccessorPointer MaskAccessorPointer; typedef core::DVHCalculator::DoseIteratorPointer DoseIteratorPointer; typedef core::StructureSetGeneratorInterface::StructureSetPointer StructureSetPointer; PREPARE_DEFAULT_TEST_REPORTING; //ARGUMENTS: 1: structure file name // 2: dose1 file name // 3: dose2 file name // 4: dose3 file name std::string RTSTRUCT_FILENAME; std::string RTDOSE_FILENAME; std::string RTDOSE2_FILENAME; std::string RTDOSE3_FILENAME; std::string COMPARISON_DVH_FOLDER; if (argc > 1) { RTSTRUCT_FILENAME = argv[1]; } if (argc > 2) { RTDOSE_FILENAME = argv[2]; } if (argc > 3) { RTDOSE2_FILENAME = argv[3]; } if (argc > 4) { RTDOSE3_FILENAME = argv[4]; } if (argc > 5) { COMPARISON_DVH_FOLDER = argv[5]; } OFCondition status; DcmFileFormat fileformat; /* read dicom-rt dose */ ::DRTDoseIOD rtdose1; io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1(RTDOSE_FILENAME.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); //create a vector of MaskAccessors (one for each structure) StructureSetPointer rtStructureSet = io::dicom::DicomFileStructureSetGenerator( RTSTRUCT_FILENAME.c_str()).generateStructureSet(); std::vector rtStructSetMaskAccessorVec; ::DRTDoseIOD rtdose2; io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator2(RTDOSE2_FILENAME.c_str()); DoseAccessorPointer doseAccessor2(doseAccessorGenerator2.generateDoseAccessor()); ::DRTDoseIOD rtdose3; io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator3(RTDOSE3_FILENAME.c_str()); DoseAccessorPointer doseAccessor3(doseAccessorGenerator3.generateDoseAccessor()); double maxDifference = 0; double difference = 0; double minDifference = 1000; clock_t start(clock()); if (rtStructureSet->getNumberOfStructures() > 0) { for (int j = 0; j < rtStructureSet->getNumberOfStructures(); j++) { //create MaskAccessor boost::shared_ptr spOTBMaskAccessor = boost::make_shared(rtStructureSet->getStructure(j), doseAccessor1->getGeometricInfo()); spOTBMaskAccessor->updateMask(); MaskAccessorPointer spMaskAccessor(spOTBMaskAccessor); //create corresponding MaskedDoseIterator boost::shared_ptr spMaskedDoseIteratorTmp = boost::make_shared(spMaskAccessor, doseAccessor1); DoseIteratorPointer spMaskedDoseIterator(spMaskedDoseIteratorTmp); //store MaskAccessor rtStructSetMaskAccessorVec.push_back(spMaskAccessor); rttb::core::DVHCalculator calc(spMaskedDoseIterator, (rtStructureSet->getStructure(j))->getUID(), doseAccessor1->getDoseUID()); std::string dvhFileName = "dvh1"; std::string label = (rtStructureSet->getStructure(j))->getLabel(); dvhFileName.append(label); if (dvhFileName.find("/") != std::string::npos) { dvhFileName.replace(dvhFileName.find("/"), 1, ""); } std::cout << "=== Dose 1: " << label << "===" << std::endl; rttb::io::other::DVHTxtFileReader dvhOriginalReader = rttb::io::other::DVHTxtFileReader( COMPARISON_DVH_FOLDER + dvhFileName + ".txt"); rttb::core::DVH dvhOrig = *(dvhOriginalReader.generateDVH()); rttb::core::DVH::DataDifferentialType dvhOrigData = dvhOrig.getDataDifferential(); rttb::core::DVH dvh = *(calc.generateDVH()); rttb::core::DVH::DataDifferentialType dvhData = dvh.getDataDifferential(); CHECK_EQUAL(dvhOrig, dvh); CHECK_CLOSE(dvhOrig.getMaximum(), dvh.getMaximum(), errorConstant); CHECK_CLOSE(dvhOrig.getMinimum(), dvh.getMinimum(), errorConstant); CHECK_CLOSE(dvhOrig.getMean(), dvh.getMean(), errorConstant); rttb::core::DVH::DataDifferentialType::iterator it; rttb::core::DVH::DataDifferentialType::iterator itOrig; itOrig = dvhOrigData.begin(); - for (it = dvhData.begin(); it != dvhData.end(), itOrig != dvhOrigData.end(); ++it, ++itOrig) + for (it = dvhData.begin(); it != dvhData.end() || itOrig != dvhOrigData.end(); ++it, ++itOrig) { CHECK_CLOSE(*(itOrig), *(it), errorConstant); std::cout << std::setprecision(20) << "difference: " << abs(*(itOrig) - * (it)) << std::endl; difference = abs(*(itOrig) - * (it)); if (difference < minDifference) { minDifference = difference; } if (difference > maxDifference) { maxDifference = difference; } } } } clock_t finish(clock()); std::cout << std::setprecision(20) << "max(difference): " << maxDifference << std::endl; std::cout << std::setprecision(20) << "min(difference): " << minDifference << std::endl; std::cout << "DVH Calculation time: " << finish - start << " ms" << std::endl; maxDifference = 0; minDifference = 1000; clock_t start2(clock()); for (int j = 0; j < rtStructSetMaskAccessorVec.size(); j++) { //create corresponding MaskedDoseIterator boost::shared_ptr spMaskedDoseIteratorTmp = boost::make_shared(rtStructSetMaskAccessorVec.at(j), doseAccessor2); DoseIteratorPointer spMaskedDoseIterator(spMaskedDoseIteratorTmp); rttb::core::DVHCalculator calc(spMaskedDoseIterator, (rtStructureSet->getStructure(j))->getUID(), doseAccessor2->getDoseUID()); std::string dvhFileName = "dvh2"; std::string label = (rtStructureSet->getStructure(j))->getLabel(); dvhFileName.append(label); if (dvhFileName.find("/") != std::string::npos) { dvhFileName.replace(dvhFileName.find("/"), 1, ""); } std::cout << "=== Dose 2: " << label << "===" << std::endl; rttb::io::other::DVHTxtFileReader dvhOriginalReader = rttb::io::other::DVHTxtFileReader( COMPARISON_DVH_FOLDER + dvhFileName + ".txt"); rttb::core::DVH dvhOrig = *(dvhOriginalReader.generateDVH()); rttb::core::DVH::DataDifferentialType dvhOrigData = dvhOrig.getDataDifferential(); rttb::core::DVH dvh = *(calc.generateDVH()); rttb::core::DVH::DataDifferentialType dvhData = dvh.getDataDifferential(); CHECK_EQUAL(dvhOrig, dvh); CHECK_CLOSE(dvhOrig.getMaximum(), dvh.getMaximum(), errorConstant); CHECK_CLOSE(dvhOrig.getMinimum(), dvh.getMinimum(), errorConstant); CHECK_CLOSE(dvhOrig.getMean(), dvh.getMean(), errorConstant); rttb::core::DVH::DataDifferentialType::iterator it; rttb::core::DVH::DataDifferentialType::iterator itOrig; itOrig = dvhOrigData.begin(); - for (it = dvhData.begin(); it != dvhData.end(), itOrig != dvhOrigData.end(); ++it, ++itOrig) + for (it = dvhData.begin(); it != dvhData.end() || itOrig != dvhOrigData.end(); ++it, ++itOrig) { CHECK_CLOSE(*(itOrig), *(it), errorConstant); std::cout << std::setprecision(20) << "difference: " << abs(*(itOrig) - * (it)) << std::endl; difference = abs(*(itOrig) - * (it)); if (difference > 10) { std::cout << "large difference: " << abs(*(itOrig) - * (it)) << " = " << *(itOrig) << " - " << * (it) << std::endl; } if (difference < minDifference) { minDifference = difference; } if (difference > maxDifference) { maxDifference = difference; } } } clock_t finish2(clock()); std::cout << std::setprecision(20) << "max(difference): " << maxDifference << std::endl; std::cout << std::setprecision(20) << "min(difference): " << minDifference << std::endl; std::cout << "Reset dose 2, DVH Calculation time: " << finish2 - start2 << " ms" << std::endl; maxDifference = 0; minDifference = 1000; clock_t start3(clock()); for (int j = 0; j < rtStructSetMaskAccessorVec.size(); j++) { //create corresponding MaskedDoseIterator boost::shared_ptr spMaskedDoseIteratorTmp = boost::make_shared(rtStructSetMaskAccessorVec.at(j), doseAccessor3); DoseIteratorPointer spMaskedDoseIterator(spMaskedDoseIteratorTmp); rttb::core::DVHCalculator calc(spMaskedDoseIterator, (rtStructureSet->getStructure(j))->getUID(), doseAccessor3->getDoseUID()); std::string dvhFileName = "dvh3"; std::string label = (rtStructureSet->getStructure(j))->getLabel(); dvhFileName.append(label); if (dvhFileName.find("/") != std::string::npos) { dvhFileName.replace(dvhFileName.find("/"), 1, ""); } std::cout << "=== Dose 3: " << label << "===" << std::endl; rttb::io::other::DVHTxtFileReader dvhOriginalReader = rttb::io::other::DVHTxtFileReader( COMPARISON_DVH_FOLDER + dvhFileName + ".txt"); rttb::core::DVH dvhOrig = *(dvhOriginalReader.generateDVH()); rttb::core::DVH::DataDifferentialType dvhOrigData = dvhOrig.getDataDifferential(); rttb::core::DVH dvh = *(calc.generateDVH()); rttb::core::DVH::DataDifferentialType dvhData = dvh.getDataDifferential(); CHECK_EQUAL(dvhOrig, dvh); CHECK_CLOSE(dvhOrig.getMaximum(), dvh.getMaximum(), errorConstant); CHECK_CLOSE(dvhOrig.getMinimum(), dvh.getMinimum(), errorConstant); CHECK_CLOSE(dvhOrig.getMean(), dvh.getMean(), errorConstant); rttb::core::DVH::DataDifferentialType::iterator it; rttb::core::DVH::DataDifferentialType::iterator itOrig; itOrig = dvhOrigData.begin(); - for (it = dvhData.begin(); it != dvhData.end(), itOrig != dvhOrigData.end(); ++it, ++itOrig) + for (it = dvhData.begin(); it != dvhData.end() || itOrig != dvhOrigData.end(); ++it, ++itOrig) { CHECK_CLOSE(*(itOrig), *(it), errorConstant); std::cout << std::setprecision(20) << "difference: " << abs(*(itOrig) - * (it)) << std::endl; if (difference > 10) { std::cout << "large difference: " << abs(*(itOrig) - * (it)) << " = " << *(itOrig) << " - " << * (it) << std::endl; } difference = abs(*(itOrig) - * (it)); if (difference < minDifference) { minDifference = difference; } if (difference > maxDifference) { maxDifference = difference; } } } clock_t finish3(clock()); std::cout << std::setprecision(20) << "max(difference): " << maxDifference << std::endl; std::cout << std::setprecision(20) << "min(difference): " << minDifference << std::endl; std::cout << "Reset dose 3, DVH Calculation time: " << finish3 - start3 << " ms" << std::endl; RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/examples/rttbTestExamples.cpp b/testing/examples/rttbTestExamples.cpp index 68e034b..ceb4a27 100644 --- a/testing/examples/rttbTestExamples.cpp +++ b/testing/examples/rttbTestExamples.cpp @@ -1,71 +1,67 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html [^] // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests #if defined(_MSC_VER) #pragma warning ( disable : 4786 ) #endif #include "litMultiTestsMain.h" namespace rttb { namespace testing { void registerTests() { LIT_REGISTER_TEST(RTBioModelExampleTest); LIT_REGISTER_TEST(DVHCalculatorExampleTest); LIT_REGISTER_TEST(RTDVHTest); LIT_REGISTER_TEST(RTDoseIndexTest); LIT_REGISTER_TEST(RTDoseStatisticsTest); LIT_REGISTER_TEST(RTBioModelScatterPlotExampleTest); - } } } int main(int argc, char* argv[]) { int result = 0; rttb::testing::registerTests(); try { result = lit::multiTestsMain(argc, argv); } - catch (const std::exception& e) + catch (const std::exception& /*e*/) { - // std::cerr << "RTToolbox test driver caught an exception:\n"; - // std::cerr << e.what() << "\n"; result = -1; } catch (...) { - //std::cerr << "RTToolbox test driver caught an unknown exception!!!\n"; result = -1; } return result; } diff --git a/testing/masks/rttbMasksTests.cpp b/testing/masks/rttbMasksTests.cpp index aeb91ef..b55efc5 100644 --- a/testing/masks/rttbMasksTests.cpp +++ b/testing/masks/rttbMasksTests.cpp @@ -1,61 +1,63 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests #if defined(_MSC_VER) #pragma warning ( disable : 4786 ) #endif -#include "litMultiTestsMain.h" +#include "litMultiTestsMain.h" -namespace rttb{ - namespace testing{ +namespace rttb +{ + namespace testing + { void registerTests() - { + { LIT_REGISTER_TEST(OTBMaskAccessorTest); - } } } +} int main(int argc, char* argv[]) - { +{ int result = 0; rttb::testing::registerTests(); try - { - result = lit::multiTestsMain(argc,argv); - } - catch(const std::exception& e) - { + { + result = lit::multiTestsMain(argc, argv); + } + catch (const std::exception& /*e*/) + { result = -1; - } - catch(...) - { + } + catch (...) + { result = -1; - } + } return result; - } +} diff --git a/testing/models/DummyModel.cpp b/testing/models/DummyModel.cpp index 4b4aabf..e641f4b 100644 --- a/testing/models/DummyModel.cpp +++ b/testing/models/DummyModel.cpp @@ -1,101 +1,112 @@ // ----------------------------------------------------------------------- // 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 "DummyModel.h" -namespace rttb{ - namespace models{ - DummyModel::DummyModel(DVHPointer aDvh): BioModel(aDvh){ +namespace rttb +{ + namespace models + { + DummyModel::DummyModel(DVHPointer aDvh): BioModel(aDvh) + { _calcCount = 0; _setParam1Count = 0; _setParam2Count = 0; _setParam3Count = 0; } - BioModelValueType DummyModel::calcModel(const double doseFactor){ + BioModelValueType DummyModel::calcModel(const double doseFactor) + { _calcCount++; _value = doseFactor; return _value; } - void DummyModel::setParameterVector(const ParamVectorType aParameterVector){ - if(aParameterVector.size()!=3) + void DummyModel::setParameterVector(const ParamVectorType& aParameterVector) + { + if (aParameterVector.size() != 3) { - std::cerr<<"aParameterVector.size must be 3! Nothing will be done."<