diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index c1b92f0..1d0ddd8 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -1,26 +1,26 @@ MESSAGE(STATUS "processing RTToolbox code") ADD_SUBDIRECTORY(core) ADD_SUBDIRECTORY(algorithms) + +OPTION(BUILD_Interpolation "Determine if the dose interpolation classes will be generated." ON) +IF(BUILD_All_Modules OR BUILD_Interpolation) + ADD_SUBDIRECTORY(interpolation) + SET(BUILD_Interpolation ON CACHE BOOL ON FORCE) +ENDIF() + ADD_SUBDIRECTORY(indices) OPTION(BUILD_Models "Determine if the model classes will be generated." OFF) IF(BUILD_All_Modules OR BUILD_Models) ADD_SUBDIRECTORY(models) SET(BUILD_Models ON CACHE BOOL ON FORCE) ENDIF() OPTION(BUILD_Masks "Determine if the mask classes will be generated." ON) IF(BUILD_All_Modules OR BUILD_Masks) ADD_SUBDIRECTORY(masks) SET(BUILD_Masks ON CACHE BOOL ON FORCE) ENDIF() ADD_SUBDIRECTORY(io) - -OPTION(BUILD_Interpolation "Determine if the dose interpolation classes will be generated." OFF) -IF(BUILD_All_Modules OR BUILD_Interpolation) - ADD_SUBDIRECTORY(interpolation) - SET(BUILD_Interpolation ON CACHE BOOL ON FORCE) -ENDIF() - - +ADD_SUBDIRECTORY(testhelper) diff --git a/code/core/files.cmake b/code/core/files.cmake index 3180ba9..c864ffa 100644 --- a/code/core/files.cmake +++ b/code/core/files.cmake @@ -1,59 +1,60 @@ SET(CPP_FILES rttbAccessorWithGeoInfoBase.cpp rttbDoseIteratorInterface.cpp rttbDVH.cpp rttbDVHCalculator.cpp rttbDVHSet.cpp rttbGenericDoseIterator.cpp rttbGenericMaskedDoseIterator.cpp rttbGeometricInfo.cpp rttbMaskedDoseIteratorInterface.cpp rttbMaskVoxel.cpp rttbStructure.cpp rttbStructureSet.cpp rttbStrVectorStructureSetGenerator.cpp rttbUtils.cpp rttbMutableMaskAccessorInterface.cpp + rttbMutableDoseAccessorInterface.cpp ) SET(H_FILES rttbAccessorInterface.h rttbAccessorWithGeoInfoBase.h rttbBaseType.h rttbDataNotAvailableException.h rttbDoseAccessorInterface.h rttbDoseIteratorInterface.h rttbDoseAccessorGeneratorBase.h rttbDoseAccessorGeneratorInterface.h rttbDVH.h rttbDVHCalculator.h rttbDVHGeneratorInterface.h rttbDVHSet.h rttbException.h rttbExceptionMacros.h rttbGenericDoseIterator.h rttbGenericMaskedDoseIterator.h rttbGeometricInfo.h rttbIndexConversionInterface.h rttbIndexOutOfBoundsException.h rttbInvalidDoseException.h rttbInvalidParameterException.h rttbMappingOutsideOfImageException.h rttbMaskAccessorGeneratorBase.h rttbMaskAccessorGeneratorInterface.h rttbMaskAccessorInterface.h rttbMaskAccessorProcessorBase.h rttbMaskAccessorProcessorInterface.h rttbMaskedDoseIteratorInterface.h rttbMaskVoxel.h rttbMutableDoseAccessorInterface.h rttbMutableMaskAccessorInterface.h rttbNullPointerException.h rttbPaddingException.h rttbStructure.h rttbStructureSet.h rttbStructureSetGeneratorInterface.h rttbStrVectorStructureSetGenerator.h rttbUtils.h rttbCommon.h ) diff --git a/code/core/rttbBaseType.h b/code/core/rttbBaseType.h index 7b5e336..e18ba5f 100644 --- a/code/core/rttbBaseType.h +++ b/code/core/rttbBaseType.h @@ -1,613 +1,614 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #ifndef __BASE_TYPE_NEW_H #define __BASE_TYPE_NEW_H #include #include #include #include #include #include #include #include #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { const double errorConstant = 1e-5; const double reducedErrorConstant = 0.0001; using Index1D = unsigned short; /*! @class Index3D @brief 3D index. */ class Index3D: public boost::numeric::ublas::vector { public: Index3D() : boost::numeric::ublas::vector(3,0) {} explicit Index3D(const Index1D value) : boost::numeric::ublas::vector(3, value) {} Index3D(const Index1D xValue, const Index1D yValue, const Index1D zValue) : boost::numeric::ublas::vector(3, xValue) { (*this)(1) = yValue; (*this)(2) = zValue; } const Index1D x() const { return (*this)(0); } const Index1D y() const { return (*this)(1); } const Index1D z() const { return (*this)(2); } friend bool operator==(const Index3D& gi1, const Index3D& gi2) { if (gi1.size() != gi2.size()) { return false; } for (size_t i = 0; i < gi1.size(); i++) { if (gi1(i) != gi2(i)) { return false; } } return true; } friend std::ostream& operator<<(std::ostream& s, const Index3D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; return s; } }; using IndexList = std::list; using FileNameString = std::string; using ContourGeometricTypeString = std::string; using WorldCoordinate = double; /*! @class WorldCoordinate3D @brief 3D coordinate in real world coordinates like in DICOM to define ImagePositionPatient. */ class WorldCoordinate3D: public boost::numeric::ublas::vector { public: WorldCoordinate3D() : boost::numeric::ublas::vector(3,0) {} explicit WorldCoordinate3D(const WorldCoordinate value) : boost::numeric::ublas::vector(3, value) {} WorldCoordinate3D(const WorldCoordinate xValue, const WorldCoordinate yValue, const WorldCoordinate zValue) : boost::numeric::ublas::vector(3, xValue) { (*this)(1) = yValue; (*this)(2) = zValue; } + WorldCoordinate3D(const WorldCoordinate3D& w): boost::numeric::ublas::vector(3) { (*this)(0) = w.x(); (*this)(1) = w.y(); (*this)(2) = w.z(); } const WorldCoordinate x() const { return (*this)(0); } const WorldCoordinate y() const { return (*this)(1); } const WorldCoordinate z() const { return (*this)(2); } //vector cross product (not included in boost.ublas) - WorldCoordinate3D cross(WorldCoordinate3D aVector) const + WorldCoordinate3D cross(const WorldCoordinate3D& aVector) const { WorldCoordinate3D result; WorldCoordinate x = (*this)(0); WorldCoordinate y = (*this)(1); WorldCoordinate z = (*this)(2); result(0) = y * aVector(2) - z * aVector(1); result(1) = z * aVector(0) - x * aVector(2); result(2) = x * aVector(1) - y * aVector(0); return result; } const std::string toString() const { std::string s = std::to_string(x()) + " " + std::to_string(y()) + " " + std::to_string(z()); return s; } WorldCoordinate3D& operator=(const WorldCoordinate3D& wc) { (*this)(0) = wc.x(); (*this)(1) = wc.y(); (*this)(2) = wc.z(); return (*this); } - WorldCoordinate3D& operator=(const boost::numeric::ublas::vector wc) + WorldCoordinate3D& operator=(const boost::numeric::ublas::vector& wc) { (*this)(0) = wc(0); (*this)(1) = wc(1); (*this)(2) = wc(2); return (*this); } - WorldCoordinate3D operator-(const boost::numeric::ublas::vector wc) + WorldCoordinate3D operator-(const boost::numeric::ublas::vector& wc) const { return WorldCoordinate3D((*this)(0) - wc(0), (*this)(1) - wc(1), (*this)(2) - wc(2)); } - WorldCoordinate3D operator+(const boost::numeric::ublas::vector wc) + WorldCoordinate3D operator+(const boost::numeric::ublas::vector& wc) const { return WorldCoordinate3D((*this)(0) + wc(0), (*this)(1) + wc(1), (*this)(2) + wc(2)); } friend bool operator==(const WorldCoordinate3D& wc1, const WorldCoordinate3D& wc2) { if (wc1.size() != wc2.size()) { return false; } for (size_t i = 0; i < wc1.size(); i++) { if (wc1(i) != wc2(i)) { return false; } } return true; } bool equalsAlmost(const WorldCoordinate3D& another, double errorConstantWC = 1e-5) const { if (size() != another.size()) { return false; } double dist = norm_2(*this - another); return dist < errorConstantWC; } friend std::ostream& operator<<(std::ostream& s, const WorldCoordinate3D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; return s; } }; /* ! @brief continuous index */ using ContinuousVoxelGridIndex3D = rttb::WorldCoordinate3D; using ImageSize = rttb::Index3D; using GridVolumeType = double; /*! @class SpacingVectorType3D @brief 3D spacing vector. @pre values of this vector may not be negative. */ class SpacingVectorType3D: public boost::numeric::ublas::vector { public: SpacingVectorType3D() : boost::numeric::ublas::vector(3,0) {} explicit SpacingVectorType3D(const GridVolumeType value) : boost::numeric::ublas::vector(3, value) { if (value < 0) { throw std::invalid_argument("received negative value"); } } SpacingVectorType3D(const GridVolumeType xValue, const GridVolumeType yValue, const GridVolumeType zValue) : boost::numeric::ublas::vector(3) { if (xValue < 0 || yValue < 0 || zValue < 0) { throw std::invalid_argument("received negative value"); } (*this)(0) = xValue; (*this)(1) = yValue; (*this)(2) = zValue; } SpacingVectorType3D(const SpacingVectorType3D& w) : SpacingVectorType3D(w.x(), w.y(), 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::string s = std::to_string(x()) + " " + std::to_string(y()) + " " + std::to_string(z()); return s; } SpacingVectorType3D& operator=(const SpacingVectorType3D& wc) { (*this)(0) = wc.x(); (*this)(1) = wc.y(); (*this)(2) = wc.z(); return (*this); } SpacingVectorType3D& operator=(const WorldCoordinate3D& wc) { (*this)(0) = GridVolumeType(wc.x()); (*this)(1) = GridVolumeType(wc.y()); (*this)(2) = GridVolumeType(wc.z()); return (*this); } SpacingVectorType3D& operator=(const boost::numeric::ublas::vector wc) { (*this)(0) = wc(0); (*this)(1) = wc(1); (*this)(2) = wc(2); return (*this); } friend bool operator==(const SpacingVectorType3D& wc1, const SpacingVectorType3D& wc2) { if (wc1.size() != wc2.size()) { return false; } for (size_t i = 0; i < wc1.size(); i++) { if (wc1(i) != wc2(i)) { return false; } } return true; } bool equalsAlmost(const SpacingVectorType3D& another, double errorConstantSV = 1e-5) const { if ((*this).size() != another.size()) { return false; } double dist = norm_2(*this - another); return dist < errorConstantSV; } friend std::ostream& operator<<(std::ostream& s, const SpacingVectorType3D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; return s; } }; /*! @class OrientationMatrix @brief Used to store image orientation information */ class OrientationMatrix : public boost::numeric::ublas::matrix { public: /*! The default constructor generates a 3x3 unit matrix */ OrientationMatrix() : boost::numeric::ublas::matrix(3, 3, 0) { for (std::size_t m = 0; m < (*this).size1(); m++) { (*this)(m, m) = 1; } } explicit OrientationMatrix(const WorldCoordinate value) : boost::numeric::ublas::matrix(3, 3, value) {} bool equalsAlmost(const OrientationMatrix& anOrientationMatrix, double errorConstantOM=1e-5) const { if (anOrientationMatrix.size1() == (*this).size1()) { if (anOrientationMatrix.size2() == (*this).size2()) { for (std::size_t m = 0; m < anOrientationMatrix.size1(); m++) { for (std::size_t n = 0; n < anOrientationMatrix.size2(); n++) { if ((std::abs((*this)(m, n) - anOrientationMatrix(m, n)) > errorConstantOM)) { return false; } } }// end element comparison } else { return false; } } else { return false; } return true; } friend bool operator==(const OrientationMatrix& om1, const OrientationMatrix& om2) { return om1.equalsAlmost(om2, 0.0); } friend std::ostream& operator<<(std::ostream& s, const OrientationMatrix& anOrientationMatrix) { s << "[ "; for (std::size_t m = 0; m < anOrientationMatrix.size1(); m++) { s << "[ "; for (std::size_t n = 0; n < anOrientationMatrix.size2(); n++) { if (n == 0) { s << anOrientationMatrix(m, n); } else { s << ", " << anOrientationMatrix(m, n); } } s << " ]"; } s << " ]"; return s; } }; /*! base for 2D and 3D VoxelIndex; Therefore required beside VoxelGridID */ using GridIndexType = unsigned int; /*! @class VoxelGridIndex3D @brief 3D voxel grid index in a discret geometry (matrix/image). @details analogous to DICOM where ImagePositionPatient gives the position of the center of the first coordinate (0/0/0) */ class VoxelGridIndex3D: public boost::numeric::ublas::vector { public: VoxelGridIndex3D() : boost::numeric::ublas::vector(3,0) {} explicit VoxelGridIndex3D(const GridIndexType value) : boost::numeric::ublas::vector(3, value) {} VoxelGridIndex3D(const GridIndexType xValue, const GridIndexType yValue, const GridIndexType zValue) : boost::numeric::ublas::vector(3, xValue) { (*this)(1) = yValue; (*this)(2) = zValue; } const GridIndexType x() const { return (*this)(0); } const GridIndexType y() const { return (*this)(1); } const GridIndexType z() const { return (*this)(2); } const std::string toString() const { std::string s = std::to_string(x()) + " " + std::to_string(y()) + " " + std::to_string(z()); return s; } VoxelGridIndex3D& operator=(const Index3D& ui) { (*this)(0) = ui(0); (*this)(1) = ui(1); (*this)(2) = ui(2); return (*this); } friend bool operator==(const VoxelGridIndex3D& gi1, const VoxelGridIndex3D& gi2) { if (gi1.size() != gi2.size()) { return false; } for (size_t i = 0; i < gi1.size(); i++) { if (gi1(i) != gi2(i)) { return false; } } return true; } friend std::ostream& operator<<(std::ostream& s, const VoxelGridIndex3D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; return s; } }; /*! @class VoxelGridIndex3D @brief 2D voxel grid index. */ class VoxelGridIndex2D: public boost::numeric::ublas::vector { public: VoxelGridIndex2D() : boost::numeric::ublas::vector(2,0) {} explicit VoxelGridIndex2D(const GridIndexType value) : boost::numeric::ublas::vector(2, value) {} VoxelGridIndex2D(const GridIndexType xValue, const GridIndexType yValue) : boost::numeric::ublas::vector(2, xValue) { (*this)(1) = yValue; } const GridIndexType x() const { return (*this)(0); } const GridIndexType y() const { return (*this)(1); } const std::string toString() const { std::string s = std::to_string(x()) + " " + std::to_string(y()); return s; } friend bool operator==(const VoxelGridIndex2D& gi1, const VoxelGridIndex2D& gi2) { if (gi1.size() != gi2.size()) { return false; } for (size_t i = 0; i < gi1.size(); i++) { if (gi1(i) != gi2(i)) { return false; } } return true; } friend std::ostream& operator<<(std::ostream& s, const VoxelGridIndex2D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << " ]"; return s; } }; using GridSizeType = long; using VoxelGridID = int; //starts from 0 and is continuously counting all positions on the grid using VoxelGridDimensionType = unsigned int; typedef double FractionType, DVHVoxelNumber; typedef double DoseCalcType, DoseTypeGy, GenericValueType, DoseVoxelVolumeType, VolumeType, GridVolumeType, PercentType, VoxelNumberType, BEDType, LQEDType; using IDType = std::string; using StructureLabel = std::string; struct DVHRole { enum Type { TargetVolume = 1, HealthyTissue = 2, WholeVolume = 4, UserDefined = 128 } Type; }; struct DVHType { enum Type { Differential = 1, Cumulative = 2 } Type; }; using FileNameType = std::string; using PolygonType = std::vector; using PolygonSequenceType = std::vector; using IndexValueType = double; using DoseStatisticType = double; using DICOMRTFileNameString = std::string; using Uint16 = unsigned short; typedef std::string XMLString, StatisticsString; }//end: namespace rttb #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbGeometricInfo.cpp b/code/core/rttbGeometricInfo.cpp index c1ba2ca..4cbf198 100644 --- a/code/core/rttbGeometricInfo.cpp +++ b/code/core/rttbGeometricInfo.cpp @@ -1,304 +1,311 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include "rttbGeometricInfo.h" #include #include #include +#include +#include namespace rttb { namespace core { + GeometricInfo::Pointer GeometricInfo::clone() const + { + return boost::make_shared(*this); + }; + 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) { _orientationMatrix = anOrientationMatrix; computeInvertOrientation(); } bool GeometricInfo::computeInvertOrientation() { using pmatrix = boost::numeric::ublas::permutation_matrix; 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; } void GeometricInfo::setImageSize(const ImageSize& aSize) { setNumColumns(aSize(0)); setNumRows(aSize(1)); setNumSlices(aSize(2)); } const ImageSize GeometricInfo::getImageSize() const { return ImageSize(static_cast(getNumColumns()), static_cast(getNumRows()), static_cast(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::equalsAlmost(const GeometricInfo& another, double errorConstantGI /*= 1e-5*/) const { return (getImagePositionPatient().equalsAlmost(another.getImagePositionPatient(), errorConstantGI) && getOrientationMatrix().equalsAlmost(another.getOrientationMatrix(), errorConstantGI) && getSpacing().equalsAlmost(another.getSpacing(), errorConstantGI) && getNumColumns() == another.getNumColumns() && getNumRows() == another.getNumRows() && getNumSlices() == another.getNumSlices()); } bool GeometricInfo::worldCoordinateToContinuousIndex(const WorldCoordinate3D& aWorldCoordinate, ContinuousVoxelGridIndex3D& aIndex) const { WorldCoordinate3D distanceToIP; distanceToIP = aWorldCoordinate - _imagePositionPatient; boost::numeric::ublas::vector result = boost::numeric::ublas::prod( _invertedOrientationMatrix, distanceToIP); boost::numeric::ublas::vector resultS = boost::numeric::ublas::element_div(result, _spacing); aIndex = ContinuousVoxelGridIndex3D(resultS(0), resultS(1), resultS(2)); //if we convert ContinuousVoxelGridIndex3D (double) to VoxelGridIndex3D (unsigned int), we can't find out if it's negative. //So we have to check before. if (aIndex(0) < -0.5 || aIndex(1) < -0.5 || aIndex(2) < -0.5){ return false; } else { //check if it is inside VoxelGridIndex3D indexInt = VoxelGridIndex3D(GridIndexType(aIndex(0) + 0.5), GridIndexType(aIndex(1) + 0.5), GridIndexType(aIndex(2) + 0.5)); return isInside(indexInt); } } bool GeometricInfo::worldCoordinateToIndex(const WorldCoordinate3D& aWorldCoordinate, VoxelGridIndex3D& aIndex) const { ContinuousVoxelGridIndex3D doubleIndex; bool inside = worldCoordinateToContinuousIndex(aWorldCoordinate, doubleIndex); aIndex = VoxelGridIndex3D(GridIndexType(doubleIndex(0)+0.5), GridIndexType(doubleIndex(1)+0.5), GridIndexType(doubleIndex(2)+0.5)); return inside; } bool GeometricInfo::continuousIndexToWorldCoordinate(const ContinuousVoxelGridIndex3D& aIndex, WorldCoordinate3D& aWorldCoordinate) const { boost::numeric::ublas::vector resultS = boost::numeric::ublas::element_prod( aIndex, _spacing); boost::numeric::ublas::vector result = boost::numeric::ublas::prod( _orientationMatrix, resultS); aWorldCoordinate = result + _imagePositionPatient; //if we convert ContinuousVoxelGridIndex3D (double) to VoxelGridIndex3D (unsigned int), we can't find out if it's negative. //So we have to check before. if (aIndex(0) < -0.5 || aIndex(1) < -0.5 || aIndex(2) < -0.5){ return false; } else { VoxelGridIndex3D indexInt = VoxelGridIndex3D(GridIndexType(aIndex(0) + 0.5), GridIndexType(aIndex(1) + 0.5), GridIndexType(aIndex(2) + 0.5)); return isInside(indexInt); } } bool GeometricInfo::indexToWorldCoordinate(const VoxelGridIndex3D& aIndex, WorldCoordinate3D& aWorldCoordinate) const { ContinuousVoxelGridIndex3D indexDouble = ContinuousVoxelGridIndex3D(aIndex(0), aIndex(1), aIndex(2)); return continuousIndexToWorldCoordinate(indexDouble, aWorldCoordinate); } 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) const { VoxelGridIndex3D currentIndex; return (worldCoordinateToIndex(aWorldCoordinate, currentIndex)); } const GridSizeType GeometricInfo::getNumberOfVoxels() const { auto nVoxels = static_cast(_numberOfRows * _numberOfColumns * _numberOfFrames); return nVoxels; } 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 68d57c3..c7ce3b2 100644 --- a/code/core/rttbGeometricInfo.h +++ b/code/core/rttbGeometricInfo.h @@ -1,187 +1,192 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #ifndef __GEOMETRIC_INFO_NEW_H #define __GEOMETRIC_INFO_NEW_H #include #include #include "rttbBaseType.h" #include #include "rttbCommon.h" #include "RTTBCoreExports.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif 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. */ class RTTBCore_EXPORT GeometricInfo { public: rttbClassMacroNoParent(GeometricInfo) private: WorldCoordinate3D _imagePositionPatient{ 0 }; OrientationMatrix _orientationMatrix{ 0 }; OrientationMatrix _invertedOrientationMatrix{ 0 }; SpacingVectorType3D _spacing{ 0 }; VoxelGridDimensionType _numberOfColumns{0}; VoxelGridDimensionType _numberOfRows{0}; VoxelGridDimensionType _numberOfFrames{0}; /* @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() = default; + GeometricInfo(const GeometricInfo& source) = default; + + /**Returns a clone of the current instance*/ + GeometricInfo::Pointer clone() const; + void setSpacing(const SpacingVectorType3D& aSpacingVector); const SpacingVectorType3D& getSpacing() const; void setImagePositionPatient(const WorldCoordinate3D& aImagePositionPatient); const WorldCoordinate3D& getImagePositionPatient() const; void setOrientationMatrix(const OrientationMatrix& anOrientationMatrix); const OrientationMatrix getOrientationMatrix() const { return _orientationMatrix; }; 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. */ friend bool RTTBCore_EXPORT operator == (const GeometricInfo& gInfo, const GeometricInfo& gInfo1); bool equalsAlmost(const GeometricInfo& another, double errorConstantGI = 1e-5) const; /*! @brief converts world coordinates to voxel grid index. @details the voxels world coordinates are defined by spacing, orientation and imagePositionPatient. (-0.5/-0.5/-0.5) --> (0/0/0) and (0.4999/0.4999/0.4999) --> (0/0/0) define the outer coordinates of a voxel with spacing=1, orientation= x y z (identity matrix) and imagePositionPatient=(0/0/0). @sa WorldCoordinate3D VoxelGridIndex3D @note The conversion of values is done even if the target index is not inside the given voxel grid. @returns false if aWorldCoordinate is outside the voxel grid, true otherwise. */ bool worldCoordinateToIndex(const WorldCoordinate3D& aWorldCoordinate, VoxelGridIndex3D& aIndex) const; /*! @brief converts world coordinates to double geometry coordinate. @details This is needed because of a double precision voxel coordinate system for voxelization. The world coordinate of the image position patient is the center of the first voxel (0.0/0.0/0.0). (-0.5/-0.5/-0.5) --> (-0.5/-0.5/-0.5) and (0.4999/0.4999/0.4999) --> (0.4999/0.4999/0.4999) with spacing=1, orientation= x y z (identity matrix) and imagePositionPatient=(0/0/0). @sa WorldCoordinate3D, ContinuousVoxelGridIndex3D @note The conversion of values is done even if the target index is not inside the given voxel grid. @returns false if aWorldCoordinate is outside the voxel grid, true otherwise. */ bool worldCoordinateToContinuousIndex(const WorldCoordinate3D& aWorldCoordinate, ContinuousVoxelGridIndex3D& aIndex) const; /*! @brief converts double geometry coordinate to world coordinates. @details This is needed because of a double precision voxel coordinate system for voxelization. The world coordinate of the image position patient is the center of the first voxel (0.0/0.0/0.0). (-0.5/-0.5/-0.5) --> (-0.5/-0.5/-0.5) and (5.5/3.2/1.0) --> (5.5/3.2/1.0) with spacing=1, orientation= x y z (identity matrix) and imagePositionPatient=(0/0/0). @sa ContinuousVoxelGridIndex3D, WorldCoordinate3D @note The conversion of values is done even if the target index is not inside the given voxel grid. @returns false if aWorldCoordinate is outside the voxel grid, true otherwise. */ bool continuousIndexToWorldCoordinate(const ContinuousVoxelGridIndex3D& aIndex, WorldCoordinate3D& aWorldCoordinate) const; /*! @brief convert voxel grid index to world coordinates @details The world coordinate of the image position patient (center of the first voxel) is the center of the first voxel (0.0/0.0/0.0) (0/0/0) --> (0.0/0.0/0.0) and (1/1/2) --> (1.0/1.0/2.0) with spacing=1, orientation= x y z (identity matrix) and imagePositionPatient=(0/0/0). Thus, the center of the voxel is taken and converted. @sa VoxelGridIndex3D, WorldCoordinate3D @note The conversion of values is done even if the target index is not inside the given voxel grid. @returns false if aWorldCoordinate is outside the voxel grid, true otherwise. */ bool indexToWorldCoordinate(const VoxelGridIndex3D& aIndex, 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; 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. */ RTTBCore_EXPORT std::ostream& operator << (std::ostream& s, const GeometricInfo& anGeometricInfo); } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/testing/core/DummyInhomogeneousDoseAccessor.cpp b/code/core/rttbMutableDoseAccessorInterface.cpp similarity index 62% copy from testing/core/DummyInhomogeneousDoseAccessor.cpp copy to code/core/rttbMutableDoseAccessorInterface.cpp index 0087e28..1a425c9 100644 --- a/testing/core/DummyInhomogeneousDoseAccessor.cpp +++ b/code/core/rttbMutableDoseAccessorInterface.cpp @@ -1,37 +1,21 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ -#include "DummyInhomogeneousDoseAccessor.h" -namespace rttb -{ - namespace testing - { +#include "rttbMutableDoseAccessorInterface.h" - DummyInhomogeneousDoseAccessor::~DummyInhomogeneousDoseAccessor() {} - - DummyInhomogeneousDoseAccessor::DummyInhomogeneousDoseAccessor() : DummyDoseAccessor() - { - } - - - - bool DummyInhomogeneousDoseAccessor::isGridHomogeneous() const - { - return false; - } - - }//end namespace testing -}//end namespace rttb \ No newline at end of file +//This file was added, because on windows some compiler +//do not export the class symbols correctly if only the +//header is specified. diff --git a/code/indices/CMakeLists.txt b/code/indices/CMakeLists.txt index ddb0812..fbffc97 100644 --- a/code/indices/CMakeLists.txt +++ b/code/indices/CMakeLists.txt @@ -1,2 +1 @@ -RTTB_CREATE_MODULE(RTTBIndices - DEPENDS PUBLIC RTTBCore) \ No newline at end of file +RTTB_CREATE_MODULE(RTTBIndices DEPENDS PUBLIC RTTBCore RTTBInterpolation) diff --git a/code/indices/files.cmake b/code/indices/files.cmake index 6f42e98..4b96429 100644 --- a/code/indices/files.cmake +++ b/code/indices/files.cmake @@ -1,19 +1,23 @@ SET(CPP_FILES rttbConformalIndex.cpp rttbConformationNumber.cpp rttbConformityIndex.cpp rttbCoverageIndex.cpp rttbDoseIndex.cpp rttbDvhBasedDoseIndex.cpp rttbHomogeneityIndex.cpp + rttbSpatialDoseIndex.cpp + rttbGammaIndex.cpp ) SET(H_FILES rttbConformalIndex.h rttbConformationNumber.h rttbConformityIndex.h rttbCoverageIndex.h rttbDoseIndex.h rttbDvhBasedDoseIndex.h rttbHomogeneityIndex.h + rttbSpatialDoseIndex.h + rttbGammaIndex.h ) diff --git a/code/indices/rttbGammaIndex.cpp b/code/indices/rttbGammaIndex.cpp new file mode 100644 index 0000000..9463f55 --- /dev/null +++ b/code/indices/rttbGammaIndex.cpp @@ -0,0 +1,288 @@ +// ----------------------------------------------------------------------- +// 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. +// +//------------------------------------------------------------------------ + +#include "rttbGammaIndex.h" +#include "rttbExceptionMacros.h" +#include "rttbNullPointerException.h" +#include "rttbIndexOutOfBoundsException.h" +#include "rttbInvalidDoseException.h" +#include "rttbLinearInterpolation.h" + +#include + +namespace rttb +{ + namespace indices + { + GammaIndex::DTAPreComputation::DTAPreComputation(WorldCoordinate3D pos, DTAValueType disPen, DTAValueType zeroDoseDiffPen): searchPosition(pos), distancePenalty(disPen), penaltyWithZeroDoseDiff(zeroDoseDiffPen) + { + } + + GammaIndex::GammaIndex(core::DoseAccessorInterface::ConstPointer dose, + core::DoseAccessorInterface::ConstPointer referenceDose) : SpatialDoseIndex(dose), _referenceDose(referenceDose) + { + if (nullptr == referenceDose) + { + rttbExceptionMacro(core::NullPointerException, << "referenceDose must not be nullptr!"); + } + + _indexGeometry = dose->getGeometricInfo().clone(); + setDoseInterpolator(nullptr); + setReferenceDoseInterpolator(nullptr); + this->UpdatePrecomputedDistancePenalties(); + } + + GammaIndex::GammaIndex(core::DoseAccessorInterface::ConstPointer dose, + core::DoseAccessorInterface::ConstPointer referenceDose, + core::GeometricInfo indexGeometry) : SpatialDoseIndex(dose), _referenceDose(referenceDose) + { + if (nullptr == referenceDose) + { + rttbExceptionMacro(core::NullPointerException, << "referenceDose must not be nullptr!"); + } + + _indexGeometry = indexGeometry.clone(); + setDoseInterpolator(nullptr); + setReferenceDoseInterpolator(nullptr); + this->UpdatePrecomputedDistancePenalties(); + } + + const core::GeometricInfo& GammaIndex::getGeometricInfo() const + { + return *_indexGeometry; + } + + GenericValueType GammaIndex::getValueAt(const VoxelGridID aID) const + { + VoxelGridIndex3D gridIndex; + if (!_indexGeometry->convert(aID, gridIndex)) + { + rttbExceptionMacro(core::IndexOutOfBoundsException, << "Cannot get gamma index by grid ID. ID is not valid for geometric info of the gamma index. Invalid ID: " << aID); + } + return this->getValueAt(gridIndex); + } + + GenericValueType GammaIndex::getValueAt(const VoxelGridIndex3D& aIndex) const + { + WorldCoordinate3D aPoint; + if (!_indexGeometry->indexToWorldCoordinate(aIndex, aPoint)) + { + rttbExceptionMacro(core::IndexOutOfBoundsException, << "Cannot get gamma index by grid index. Grid index is not valid for geometric info of the gamma index. Invalid grid index: " << aIndex); + } + return computeValueAndPosition(aPoint).first; + } + + GenericValueType GammaIndex::getValueAt(const WorldCoordinate3D& aPoint) const + { + if (!_indexGeometry->isInside(aPoint)) + { + rttbExceptionMacro(core::IndexOutOfBoundsException, << "Cannot get gamma index by point. Point is not valid for geometric info of the gamma index. Invalid point: " << aPoint); + } + + return computeValueAndPosition(aPoint).first; + } + + const IDType GammaIndex::getUID() const + { + std::stringstream uidStream; + uidStream << "gammaindex." << _dta << "." << _samplingStepSizes << "." << _ddt << "." << _useLocalDose << "." << _globalDose << "_" << _dose->getUID() << "_" << _referenceDose->getUID(); + return uidStream.str(); + } + + void GammaIndex::setDoseInterpolator(interpolation::InterpolationBase::Pointer interpolator) + { + if (nullptr == interpolator) + { + _doseInterpolator = ::boost::make_shared(); + } + else + { + _doseInterpolator = interpolator; + } + _doseInterpolator->setAccessorPointer(_dose); + } + + interpolation::InterpolationBase::ConstPointer GammaIndex::getDoseInterpolator() const + { + return _doseInterpolator; + }; + + void GammaIndex::setReferenceDoseInterpolator(interpolation::InterpolationBase::Pointer interpolator) + { + if (nullptr == interpolator) + { + _referenceDoseInterpolator = ::boost::make_shared(); + } + else + { + _referenceDoseInterpolator = interpolator; + } + _referenceDoseInterpolator->setAccessorPointer(_referenceDose); + } + + interpolation::InterpolationBase::ConstPointer GammaIndex::getReferenceDoseInterpolator() const + { + return _referenceDoseInterpolator; + } + + void GammaIndex::setDistanceToAgreementThreshold(DTAValueType dta) + { + if (dta != _dta) + { + _dta = dta; + this->UpdatePrecomputedDistancePenalties(); + } + } + + GammaIndex::DTAValueType GammaIndex::getDistanceToAgreementThreshold() const + { + return _dta; + } + + void GammaIndex::setDoseDifferenceThreshold(DDTValueType ddt) + { + _ddt = ddt; + } + + GammaIndex::DDTValueType GammaIndex::getDoseDifferenceThreshold() const + { + return _ddt; + } + + void GammaIndex::setSearchSamplingRate(double rateX, double rateY, double rateZ) + { + _samplingStepSizes = SpacingVectorType3D(rateX, rateY, rateZ); + this->UpdatePrecomputedDistancePenalties(); + } + + SpacingVectorType3D GammaIndex::getSearchSamplingRate() const + { + return _samplingStepSizes; + } + + void GammaIndex::setUseLocalDose(bool useLocalDose) + { + _useLocalDose = useLocalDose; + } + + bool GammaIndex::getUseLocalDose() const + { + return _useLocalDose; + } + + void GammaIndex::setGlobalDose(DoseTypeGy globalDose) + { + _globalDose = globalDose; + } + + DoseTypeGy GammaIndex::getGlobalDose() const + { + return _globalDose; + } + + void GammaIndex::UpdatePrecomputedDistancePenalties() + { + + DATPreComputationVectorType newPenalties; + + int min[3]; + int max[3]; + + min[0] = -1 * static_cast(_dta / _samplingStepSizes.x() + std::numeric_limits::epsilon()); + max[0] = static_cast(_dta / _samplingStepSizes.x() + std::numeric_limits::epsilon()); + + min[1] = -1 * static_cast(_dta / _samplingStepSizes.y() + std::numeric_limits::epsilon()); + max[1] = static_cast(_dta / _samplingStepSizes.y() + std::numeric_limits::epsilon()); + + min[2] = -1 * static_cast(_dta / _samplingStepSizes.z() + std::numeric_limits::epsilon()); + max[2] = static_cast(_dta / _samplingStepSizes.z() + std::numeric_limits::epsilon()); + + /*We add the penalty for the search center (measured point) + explicitly at the beginning to check it first. This allows + us to shortcut in cases where the measured point equals the + expected or is very close.*/ + newPenalties.emplace_back(WorldCoordinate3D(0., 0., 0.), 0., 0.); + + for (int iX = min[0]; iX <= max[0]; ++iX) + { + const WorldCoordinate x = _samplingStepSizes.x() * iX; + for (int iY = min[1]; iY <= max[1]; ++iY) + { + const WorldCoordinate y = _samplingStepSizes.y() * iY; + for (int iZ = min[2]; iZ <= max[2]; ++iZ) + { + const WorldCoordinate z = _samplingStepSizes.z() * iZ; + WorldCoordinate3D newPos = { x,y,z }; + + const auto newDistance = boost::numeric::ublas::norm_2(newPos); + const auto penalty = (newDistance * newDistance) / (_dta * _dta); + if (penalty > 0 && penalty <= 1) + { //we skip the origin (penalty == 0) as it was added before the loop + //and we skip every point that would not pass because the dta penalty is to high (>1) + newPenalties.emplace_back(newPos, penalty, std::sqrt(penalty)); + } + } + } + } + _precomputedDistancePenalties = newPenalties; + } + + std::pair GammaIndex::computeValueAndPosition(const WorldCoordinate3D& aPoint) const + { + const auto measuredDose = _doseInterpolator->getValue(aPoint); + + const DoseTypeGy doseThresholdGy = ((_useLocalDose) ? measuredDose : _globalDose) * _ddt; + const DoseTypeGy doseThresholdGySquared = doseThresholdGy*doseThresholdGy; + + if (0. == doseThresholdGySquared) + { + // This is likely to occur if a mask is applied before + // but should in general not occur if dose values inside the mask are given + return std::make_pair(std::nan(""),WorldCoordinate3D(0.)); + } + + std::pair bestFinding; + bestFinding.second = WorldCoordinate3D(std::numeric_limits::max()); + bestFinding.first = std::numeric_limits::max(); + + for (const auto& distancePenalty : _precomputedDistancePenalties) + { + if (distancePenalty.penaltyWithZeroDoseDiff < bestFinding.first) + { //search position could beat the best finding -> evaluate it + const WorldCoordinate3D refPoint = aPoint + distancePenalty.searchPosition; + + if (_referenceDose->getGeometricInfo().isInside(refPoint)) + { //needed refpoint is part reference dose geometry -> go on + const auto refDose = _referenceDoseInterpolator->getValue(refPoint); + const auto doseDifferenceSquared = std::pow(refDose - measuredDose, 2); + const auto dosePenalty = doseDifferenceSquared / doseThresholdGySquared; + const GenericValueType penalty = std::sqrt(distancePenalty.distancePenalty + dosePenalty); + + if (penalty < bestFinding.first) + { + //gamma index value is limited to 1.0 based on the literature + bestFinding.first = std::min(penalty, 1.0); + bestFinding.second = distancePenalty.searchPosition; + } + } + } + } + return bestFinding; + } + + } +} + + diff --git a/code/indices/rttbGammaIndex.h b/code/indices/rttbGammaIndex.h new file mode 100644 index 0000000..1646d29 --- /dev/null +++ b/code/indices/rttbGammaIndex.h @@ -0,0 +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. +// +//------------------------------------------------------------------------ + +#ifndef __GAMMA_INDEX_H +#define __GAMMA_INDEX_H + +#include + +#include "rttbSpatialDoseIndex.h" +#include "rttbInterpolationBase.h" +#include "RTTBIndicesExports.h" + +namespace rttb +{ + namespace indices + { + /*! @class GammaIndex + @brief TODO + @ingroup indices + */ + class RTTBIndices_EXPORT GammaIndex : public SpatialDoseIndex + { + public: + rttbClassMacro(GammaIndex, SpatialDoseIndex); + + /**Type used to specify the distance to agreement in mm.*/ + using DTAValueType = double; + /**Type used to specify the dose difference threshold in fractions (0= 0% and 0.5=50%).*/ + using DDTValueType = double; + + + /** Constructor that uses takes the dose and reference dose to compute the + gamma index. As geometric info (spatial resolution) of the index the geometric + info of dose will be used. + @pre dose must point to a valid instance. + @pre referenceDose must point to a valid instance.*/ + GammaIndex(core::DoseAccessorInterface::ConstPointer dose, + core::DoseAccessorInterface::ConstPointer referenceDose); + + /** Constructor that allows to explicitly allows to specify the geometric info + of the index (e.g. if you want to have the index in another resolution. + @pre dose must point to a valid instance. + @pre referenceDose must point to a valid instance.*/ + GammaIndex(core::DoseAccessorInterface::ConstPointer dose, + core::DoseAccessorInterface::ConstPointer referenceDose, + core::GeometricInfo indexGeometry); + + virtual ~GammaIndex() = default; + + GenericValueType getValueAt(const VoxelGridID aID) const override; + + GenericValueType getValueAt(const VoxelGridIndex3D& aIndex) const override; + + GenericValueType getValueAt(const WorldCoordinate3D& aPoint) const; + + const IDType getUID() const override; + + const core::GeometricInfo& getGeometricInfo() const override; + + /**Allows to specify the interpolator that should be used if dose should be sampled. + If no interpolator is defined (nullptr), a LinarInterpolator will be used + (this is also the default after index construction). + Remark: After setting the interpolator, the index assumes that it takes control over + the interpolator and set the input accessor. Please do not change the state of the + interpolator in the lifetime of the index instance that took over control. Otherwise + strange side effects could happen in the computation.*/ + void setDoseInterpolator(interpolation::InterpolationBase::Pointer interpolator); + interpolation::InterpolationBase::ConstPointer getDoseInterpolator() const; + + /**Allows to specify the interpolator that should be used if referenceDose should be sampled. + If no interpolator is defined (nullptr), a LinarInterpolator will be used + (this is also the default after index construction). + Remark: After setting the interpolator, the index assumes that it takes control over + the interpolator and set the input accessor. Please do not change the state of the + interpolator in the lifetime of the index instance that took over control. Otherwise + strange side effects could happen in the computation.*/ + void setReferenceDoseInterpolator(interpolation::InterpolationBase::Pointer interpolator); + interpolation::InterpolationBase::ConstPointer getReferenceDoseInterpolator() const; + + void setDistanceToAgreementThreshold(DTAValueType dta); + DTAValueType getDistanceToAgreementThreshold() const; + + void setDoseDifferenceThreshold(DDTValueType ddt); + DDTValueType getDoseDifferenceThreshold() const; + + void setSearchSamplingRate(double rateX, double rateY, double rateZ); + SpacingVectorType3D getSearchSamplingRate() const; + + void setUseLocalDose(bool useLocalDose); + bool getUseLocalDose() const; + + void setGlobalDose(DoseTypeGy globalDose); + DoseTypeGy getGlobalDose() const; + + protected: + + /** GeometricInfo that should be used for the index. Either the geometric info + of the dose or a user defined geometric info.*/ + core::GeometricInfo::ConstPointer _indexGeometry; + + /** Reference dose used to compare the computed dose with.*/ + core::DoseAccessorInterface::ConstPointer _referenceDose; + + /** Interpolator used when the index needs to access values of _dose*/ + interpolation::InterpolationBase::Pointer _doseInterpolator; + /** Interpolator used when the index needs to access values of _referenceDose*/ + interpolation::InterpolationBase::Pointer _referenceDoseInterpolator; + + /** Distance to aggreement (DTA) threshold for the gamma index comutation. Specified in mm. + It also specified the search range radius (in mm) arround the the center point (world coordinates) + requested for the index value.*/ + DTAValueType _dta = 3.; + + /** dose difference as fraction (0= 0% and 0.5=50%) that is the threshold*/ + DDTValueType _ddt = 0.03; + + /** To calculate the gamma index one has to sample the reference dose within the DTA. This + variable controls how dense the sampling is within the Dit is sampled a Distance to aggreement (DTA) threshold for the gamma index comutation. Specified in mm.*/ + SpacingVectorType3D _samplingStepSizes = { 1.0,1.0,1.0 }; + + /** */ + bool _useLocalDose = true; + + DoseTypeGy _globalDose = 0.; + + /** Internal helper that stores a search position vector that has been + computed given the specified distance to aggreement and the search sampling rate.*/ + struct DTAPreComputation + { + /** The search position is relative to the "measured" point for which + the gamma index should be computed. Thus search position(0, 0, 0) is + the "measured" point itself.*/ + WorldCoordinate3D searchPosition; + + /** The precomputed distance penalty part of the penalty formular.*/ + DTAValueType distancePenalty = 0.0; + + /** The complete penalty for the seach position, assuming that the dose + difference penalty is 0. This the sqrt(distancePenalty).*/ + DTAValueType penaltyWithZeroDoseDiff = 0.0; + + DTAPreComputation(WorldCoordinate3D pos, DTAValueType disPen, DTAValueType zeroDoseDiffPen); + DTAPreComputation() = default; + }; + + using DATPreComputationVectorType = std::vector< DTAPreComputation >; + /** Collection of all precomputed search positions and there penalties.*/ + DATPreComputationVectorType _precomputedDistancePenalties; + + /** function can be called to update the _precomputedDistancePenalties given the current + index settings. After the update only search position are in _precomputedDistancePenalties, + that do not fail the DTA.\n + The implementation makes use of the fact that the distance penalty + part of the gamma index does not depend on the dose distribution itself, and can be + precomputed for any dose distribution and any search position as soon as DTA and sampling rate + is defined.*/ + void UpdatePrecomputedDistancePenalties(); + + std::pair computeValueAndPosition(const WorldCoordinate3D& aPoint) const; + }; + } +} + + +#endif diff --git a/testing/core/DummyInhomogeneousDoseAccessor.cpp b/code/indices/rttbSpatialDoseIndex.cpp similarity index 58% copy from testing/core/DummyInhomogeneousDoseAccessor.cpp copy to code/indices/rttbSpatialDoseIndex.cpp index 0087e28..8d632ba 100644 --- a/testing/core/DummyInhomogeneousDoseAccessor.cpp +++ b/code/indices/rttbSpatialDoseIndex.cpp @@ -1,37 +1,41 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -#include "DummyInhomogeneousDoseAccessor.h" +#include "rttbSpatialDoseIndex.h" +#include "rttbExceptionMacros.h" +#include "rttbNullPointerException.h" namespace rttb { - namespace testing - { - - DummyInhomogeneousDoseAccessor::~DummyInhomogeneousDoseAccessor() {} - - DummyInhomogeneousDoseAccessor::DummyInhomogeneousDoseAccessor() : DummyDoseAccessor() - { - } - + namespace indices + { + SpatialDoseIndex::SpatialDoseIndex(core::DoseAccessorInterface::ConstPointer aDose) + : _dose(aDose) + { + if (nullptr == aDose) + { + rttbExceptionMacro(core::NullPointerException, "aDose must not be nullptr!"); + } + } - bool DummyInhomogeneousDoseAccessor::isGridHomogeneous() const + const core::GeometricInfo& SpatialDoseIndex::getGeometricInfo() const { - return false; + return _dose->getGeometricInfo(); } + } +} + - }//end namespace testing -}//end namespace rttb \ No newline at end of file diff --git a/code/indices/rttbSpatialDoseIndex.h b/code/indices/rttbSpatialDoseIndex.h new file mode 100644 index 0000000..c80f43e --- /dev/null +++ b/code/indices/rttbSpatialDoseIndex.h @@ -0,0 +1,56 @@ +// ----------------------------------------------------------------------- +// 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. +// +//------------------------------------------------------------------------ + +#ifndef __SPATIAL_DOSE_INDEX_H +#define __SPATIAL_DOSE_INDEX_H + +#include "rttbDoseAccessorInterface.h" + +#include "RTTBIndicesExports.h" + +namespace rttb +{ + namespace indices + { + /*! @class SpatialDoseIndex + @brief This is the base class for indicies that are computed on spatialy resolved + dose distributions (e.g. gamma index). + In contrast to other "normal" DVH based indices that are not spatialy resolved (like + e.g. ConformityIndex), these type of indices are computed on a spatialy resolved dose + distribution for specifeid points in space. Thus this index type itself has a geometry + info and is spatialy distributed. + @ingroup indices + */ + class RTTBIndices_EXPORT SpatialDoseIndex : public core::AccessorInterface + { + public: + rttbClassMacro(SpatialDoseIndex, AccessorInterface); + + const core::GeometricInfo& getGeometricInfo() const override; + + protected: + + /*! @brief Constructor with the referece dose. + @pre dose pointer must be valid.*/ + SpatialDoseIndex(core::DoseAccessorInterface::ConstPointer aDose); + virtual ~SpatialDoseIndex() = default; + + core::DoseAccessorInterface::ConstPointer _dose; + }; + } +} + + +#endif diff --git a/code/interpolation/ITKTransformation/CMakeLists.txt b/code/interpolation/ITKTransformation/CMakeLists.txt index ca64739..75a601b 100644 --- a/code/interpolation/ITKTransformation/CMakeLists.txt +++ b/code/interpolation/ITKTransformation/CMakeLists.txt @@ -1,2 +1,2 @@ RTTB_CREATE_MODULE(RTTBInterpolationITKTransformation - DEPENDS PUBLIC RTTBCore RTTBInterpolation RTTBITKIO PACKAGE_DEPENDS PUBLIC ITK) \ No newline at end of file + DEPENDS PUBLIC RTTBCore RTTBInterpolation PACKAGE_DEPENDS PUBLIC ITK) \ No newline at end of file diff --git a/code/interpolation/rttbInterpolationBase.cpp b/code/interpolation/rttbInterpolationBase.cpp index 282bb3f..0e5cc56 100644 --- a/code/interpolation/rttbInterpolationBase.cpp +++ b/code/interpolation/rttbInterpolationBase.cpp @@ -1,191 +1,196 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include #include #include "rttbInterpolationBase.h" #include "rttbInvalidParameterException.h" #include "rttbNullPointerException.h" #include "rttbMappingOutsideOfImageException.h" namespace rttb { namespace interpolation { void InterpolationBase::setAccessorPointer(core::AccessorInterface::ConstPointer originalData) { if (originalData != nullptr) { _spOriginalData = originalData; } else { throw core::NullPointerException("originalDose is nullptr!"); } }; + core::AccessorInterface::ConstPointer InterpolationBase::getAccessorPointer() const + { + return _spOriginalData; + } + void InterpolationBase::getNeighborhoodVoxelValues( const WorldCoordinate3D& aWorldCoordinate, unsigned int neighborhood, std::array& target, boost::shared_ptr values) const { if (_spOriginalData == nullptr) { throw core::NullPointerException("originalDose is nullptr!"); } //Determine target (abs(desired worldCoordinate- corner pixel world coordinate/pixel spacing) and values of corner pixels (from originalDose) VoxelGridIndex3D aIndex; if (_spOriginalData->getGeometricInfo().worldCoordinateToIndex(aWorldCoordinate, aIndex)) { //determine just the nearest voxel to the world coordinate if (neighborhood == 0) { values[0] = _spOriginalData->getValueAt(aIndex); } //determine the 8 voxels around the world coordinate else if (neighborhood == 8) { std::list cornerPoints; WorldCoordinate3D theNextVoxel; _spOriginalData->getGeometricInfo().indexToWorldCoordinate(aIndex, theNextVoxel); SpacingVectorType3D pixelSpacing = (_spOriginalData->getGeometricInfo()).getSpacing(); VoxelGridIndex3D leftTopFrontCoordinate; //find the voxel with the smallest coordinate values in each dimension. This defines the standard cube for (unsigned int i = 0; i < 3; i++) { if (aWorldCoordinate[i] < theNextVoxel[i]) { if (aIndex[i] > 0) { leftTopFrontCoordinate[i] = aIndex[i] - 1; target[i] = (aWorldCoordinate[i] - (theNextVoxel[i] - pixelSpacing[i])) / pixelSpacing[i]; } //@todo: see T22315 else { leftTopFrontCoordinate[i] = aIndex[i]; target[i] = (aWorldCoordinate[i] - (theNextVoxel[i] - pixelSpacing[i])) / pixelSpacing[i]; } } else { leftTopFrontCoordinate[i] = aIndex[i]; target[i] = (aWorldCoordinate[i] - theNextVoxel[i]) / pixelSpacing[i]; } } for (unsigned int zIncr = 0; zIncr < 2; zIncr++) { for (unsigned int yIncr = 0; yIncr < 2; yIncr++) { for (unsigned int xIncr = 0; xIncr < 2; xIncr++) { cornerPoints.emplace_back(leftTopFrontCoordinate[0] + xIncr, leftTopFrontCoordinate[1] + yIncr, leftTopFrontCoordinate[2] + zIncr); } } } //target range has to be always [0,1] for (unsigned int i = 0; i < 3; i++) { assert(target[i] >= 0.0 && target[i] <= 1.0); } unsigned int count = 0; //now just get the values of all (dose) voxels and store them in values for (auto cornerPointsIterator = cornerPoints.begin(); cornerPointsIterator != cornerPoints.end(); ++cornerPointsIterator, ++count) { if (_spOriginalData->getGeometricInfo().isInside(*cornerPointsIterator)) { values[count] = _spOriginalData->getValueAt(*cornerPointsIterator); } else { //outside value! boundary treatment values[count] = getNearestInsideVoxelValue(*cornerPointsIterator); } assert(values[count] != -1); } } else { throw core::InvalidParameterException("neighborhoods other than 0 and 8 not yet supported in Interpolation"); } } else { throw core::MappingOutsideOfImageException("Error in conversion from world coordinates to index"); } } DoseTypeGy InterpolationBase::getNearestInsideVoxelValue(const VoxelGridIndex3D& currentVoxelIndex) const { VoxelGridIndex3D voxelChangedXYZ[] = {currentVoxelIndex, currentVoxelIndex, currentVoxelIndex, currentVoxelIndex, currentVoxelIndex, currentVoxelIndex, currentVoxelIndex}; unsigned int runningIndex; //x,y,z for (runningIndex = 0; runningIndex < 3; ++runningIndex) { voxelChangedXYZ[runningIndex][runningIndex] -= 1; } //xy voxelChangedXYZ[runningIndex][0] -= 1; voxelChangedXYZ[runningIndex][1] -= 1; ++runningIndex; //xz voxelChangedXYZ[runningIndex][0] -= 1; voxelChangedXYZ[runningIndex][2] -= 1; ++runningIndex; //yz voxelChangedXYZ[runningIndex][1] -= 1; voxelChangedXYZ[runningIndex][2] -= 1; ++runningIndex; //xyz voxelChangedXYZ[runningIndex][0] -= 1; voxelChangedXYZ[runningIndex][1] -= 1; voxelChangedXYZ[runningIndex][2] -= 1; ++runningIndex; unsigned int replacementVoxelIndex = 0; while (replacementVoxelIndex < runningIndex) { if (_spOriginalData->getGeometricInfo().validIndex(voxelChangedXYZ[replacementVoxelIndex])) { return _spOriginalData->getValueAt(voxelChangedXYZ[replacementVoxelIndex]); } ++replacementVoxelIndex; } return -1; } }//end namespace core }//end namespace rttb diff --git a/code/interpolation/rttbInterpolationBase.h b/code/interpolation/rttbInterpolationBase.h index 990f775..f77c8ed 100644 --- a/code/interpolation/rttbInterpolationBase.h +++ b/code/interpolation/rttbInterpolationBase.h @@ -1,94 +1,96 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #ifndef __INTERPOLATION_BASE_H #define __INTERPOLATION_BASE_H #include #include #include #include "rttbAccessorInterface.h" #include "RTTBInterpolationExports.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace interpolation { /*! @class InterpolationBase @brief Base class for interpolation. @ingroup interpolation */ class RTTBInterpolation_EXPORT InterpolationBase { public: rttbClassMacroNoParent(InterpolationBase) /*! @brief Constructor */ InterpolationBase() = default; /*! @brief Virtual destructor of base class */ virtual ~InterpolationBase() = default; /*! @brief Sets the AccessorPointer @pre originalData initialized @exception core::NullPointerException if originalData==nullptr */ void setAccessorPointer(core::AccessorInterface::ConstPointer originalData); + core::AccessorInterface::ConstPointer getAccessorPointer() const; + /*! @brief Returns the interpolated value for the given world coordinate */ virtual DoseTypeGy getValue(const WorldCoordinate3D& aWorldCoordinate) const = 0; protected: rttb::core::AccessorInterface::ConstPointer _spOriginalData; /*! @brief determines voxels in a certain neighborhood of a physical based coordinate and converts in a standard cube with corner points [0 0 0], [1 0 0], [0 1 0], [1 1 0], [0 0 1], [1 0 1], [0 1 1], [1 1 1]. @param aWorldCoordinate the coordinate where to start @param neighborhood voxel around coordinate (currently only 0 and 8 implemented) @param target coordinates inside the standard cube with values [0 1] in each dimension. @param values dose values at all corner points of the standard cube. Is of type boost:shared_ptr[neighborhood] @pre target and values have to be correctly initialized (e.g. std::array target = {0.0, 0.0, 0.0}; boost::shared_ptr values(new DoseTypeGy[8]()); where 8 is neighborhood) @exception core::InvalidParameterException if neighborhood =! 0 && !=8 @exception core::MappingOutsideOfImageException if initial mapping of aWorldCoordinate is outside image @exception core::NullPointerException if dose is nullptr */ void getNeighborhoodVoxelValues(const WorldCoordinate3D& aWorldCoordinate, unsigned int neighborhood, std::array& target, boost::shared_ptr values) const; /*! @brief returns the nearest inside voxel value @pre the voxelGridIndex is outside the image and voxelGridIndex>image.size() for all dimensions. Also voxelGridIndex[]>=0 for all dimensions @note used for virtually expanding the image by one voxel as edge handling */ DoseTypeGy getNearestInsideVoxelValue(const VoxelGridIndex3D& currentVoxelIndex) const; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/testhelper/CMakeLists.txt b/code/testhelper/CMakeLists.txt new file mode 100644 index 0000000..ef7e69d --- /dev/null +++ b/code/testhelper/CMakeLists.txt @@ -0,0 +1,2 @@ +RTTB_CREATE_MODULE(RTTBTestHelper DEPENDS RTTBCore RTTBAlgorithms RTTBInterpolation PACKAGE_DEPENDS Boost) + diff --git a/testing/core/CreateTestStructure.cpp b/code/testhelper/CreateTestStructure.cpp similarity index 97% rename from testing/core/CreateTestStructure.cpp rename to code/testhelper/CreateTestStructure.cpp index 0682d37..1edea7c 100644 --- a/testing/core/CreateTestStructure.cpp +++ b/code/testhelper/CreateTestStructure.cpp @@ -1,681 +1,681 @@ -// ----------------------------------------------------------------------- -// 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. -// -//------------------------------------------------------------------------ - -// this file defines the rttbCoreTests for the test driver -// and all it expects is that you have a function called RegisterTests - -#include - -#include "CreateTestStructure.h" -#include "rttbNullPointerException.h" -#include "rttbInvalidParameterException.h" -#include "rttbInvalidDoseException.h" - -namespace rttb -{ - - namespace testing - { - - CreateTestStructure::~CreateTestStructure() {} - - CreateTestStructure::CreateTestStructure(const core::GeometricInfo& aGeoInfo) - { - _geoInfo = aGeoInfo; - } - - PolygonType CreateTestStructure::createPolygonLeftUpper(std::vector aVoxelVector, - GridIndexType sliceNumber) - { - - PolygonType polygon; - - for (size_t i = 0; i < aVoxelVector.size(); i++) - { - VoxelGridIndex3D voxelIndex; - voxelIndex(0) = (aVoxelVector.at(i)).x(); - voxelIndex(1) = (aVoxelVector.at(i)).y(); - voxelIndex(2) = sliceNumber; - - WorldCoordinate3D p1; - _geoInfo.indexToWorldCoordinate(voxelIndex, p1); - - polygon.push_back(p1); - std::cout << "(" << p1.x() << "," << p1.y() << "," << p1.z() << ")" << "; "; - } - - std::cout << std::endl; - return polygon; - } - - PolygonType CreateTestStructure::createPolygonCenter(std::vector aVoxelVector, - GridIndexType sliceNumber) - { - PolygonType polygon; - - for (size_t i = 0; i < aVoxelVector.size(); i++) - { - VoxelGridIndex3D voxelIndex; - voxelIndex(0) = (aVoxelVector.at(i)).x(); - voxelIndex(1) = (aVoxelVector.at(i)).y(); - voxelIndex(2) = sliceNumber; - - WorldCoordinate3D p1; - _geoInfo.indexToWorldCoordinate(voxelIndex, p1); - - WorldCoordinate3D p; - p(0) = p1.x() ; - p(1) = p1.y() ; - //This can be done directly for x/y coordinates, but not for z. Thus, we do it in this function. - p(2) = p1.z() - _geoInfo.getSpacing().z() / 2; - - polygon.push_back(p); - } - - return polygon; - } - - PolygonType CreateTestStructure::createPolygonCenterOnPlaneCenter(std::vector aVoxelVector, - GridIndexType sliceNumber) - { - - PolygonType polygon; - - for (size_t i = 0; i < aVoxelVector.size(); i++) - { - VoxelGridIndex3D voxelIndex; - ContinuousVoxelGridIndex3D indexDouble = ContinuousVoxelGridIndex3D((aVoxelVector.at(i)).x(), (aVoxelVector.at(i)).y(), - sliceNumber); - - WorldCoordinate3D p1; - _geoInfo.continuousIndexToWorldCoordinate(indexDouble, p1); - - polygon.push_back(p1); - } - - return polygon; - } - - - PolygonType CreateTestStructure::createPolygonBetweenUpperLeftAndCenter( - std::vector aVoxelVector, GridIndexType sliceNumber) - { - - PolygonType polygon; - - for (size_t i = 0; i < aVoxelVector.size(); i++) - { - VoxelGridIndex3D voxelIndex; - voxelIndex(0) = (aVoxelVector.at(i)).x(); - voxelIndex(1) = (aVoxelVector.at(i)).y(); - voxelIndex(2) = sliceNumber; - - WorldCoordinate3D p1; - _geoInfo.indexToWorldCoordinate(voxelIndex, p1); - SpacingVectorType3D delta = _geoInfo.getSpacing(); - - WorldCoordinate3D p; - p(0) = p1.x() + delta.x() / 4; - p(1) = p1.y() + delta.y() / 4; - p(2) = p1.z(); - - polygon.push_back(p); - std::cout << "(" << p.x() << "," << p.y() << "," << p.z() << ")" << "; "; - } - - std::cout << std::endl; - return polygon; - } - - - PolygonType CreateTestStructure::createPolygonBetweenLowerRightAndCenter( - std::vector aVoxelVector, GridIndexType sliceNumber) - { - - PolygonType polygon; - - for (size_t i = 0; i < aVoxelVector.size(); i++) - { - VoxelGridIndex3D voxelIndex; - voxelIndex(0) = (aVoxelVector.at(i)).x(); - voxelIndex(1) = (aVoxelVector.at(i)).y(); - voxelIndex(2) = sliceNumber; - - WorldCoordinate3D p1; - _geoInfo.indexToWorldCoordinate(voxelIndex, p1); - SpacingVectorType3D delta = _geoInfo.getSpacing(); - - WorldCoordinate3D p; - p(0) = p1.x() + delta.x() * 0.75; - p(1) = p1.y() + delta.y() * 0.75; - p(2) = p1.z(); - - polygon.push_back(p); - std::cout << "(" << p.x() << "," << p.y() << "," << p.z() << ")" << "; "; - } - - std::cout << std::endl; - return polygon; - } - - - PolygonType CreateTestStructure::createPolygonLeftEdgeMiddle(std::vector - aVoxelVector, GridIndexType sliceNumber) - { - - PolygonType polygon; - - for (size_t i = 0; i < aVoxelVector.size(); i++) - { - VoxelGridIndex3D voxelIndex; - voxelIndex(0) = (aVoxelVector.at(i)).x(); - voxelIndex(1) = (aVoxelVector.at(i)).y(); - voxelIndex(2) = sliceNumber; - - WorldCoordinate3D p1; - _geoInfo.indexToWorldCoordinate(voxelIndex, p1); - SpacingVectorType3D delta = _geoInfo.getSpacing(); - - WorldCoordinate3D p; - p(0) = p1.x(); - p(1) = p1.y() + delta.y() * 0.5; - p(2) = p1.z(); - - polygon.push_back(p); - std::cout << "(" << p.x() << "," << p.y() << "," << p.z() << ")" << "; "; - } - - std::cout << std::endl; - return polygon; - } - - - - PolygonType CreateTestStructure::createPolygonUpperCenter(std::vector - aVoxelVector, GridIndexType sliceNumber) - { - - PolygonType polygon; - - for (size_t i = 0; i < aVoxelVector.size(); i++) - { - VoxelGridIndex3D voxelIndex; - voxelIndex(0) = (aVoxelVector.at(i)).x(); - voxelIndex(1) = (aVoxelVector.at(i)).y(); - voxelIndex(2) = sliceNumber; - - WorldCoordinate3D p1; - _geoInfo.indexToWorldCoordinate(voxelIndex, p1); - SpacingVectorType3D delta = _geoInfo.getSpacing(); - - WorldCoordinate3D p; - p(0) = p1.x() + delta.x() * 0.5; - p(1) = p1.y(); - p(2) = p1.z(); - - polygon.push_back(p); - std::cout << "(" << p.x() << "," << p.y() << "," << p.z() << ")" << "; "; - } - - std::cout << std::endl; - return polygon; - } - - - - PolygonType CreateTestStructure::createPolygonIntermediatePoints(std::vector - aVoxelVector, GridIndexType sliceNumber) - { - - PolygonType polygon; - - for (size_t i = 0; i < aVoxelVector.size(); i++) - { - VoxelGridIndex3D voxelIndex; - VoxelGridIndex3D voxelIndex2; - - voxelIndex(0) = (aVoxelVector.at(i)).x(); - voxelIndex(1) = (aVoxelVector.at(i)).y(); - voxelIndex(2) = sliceNumber; - - if (i < (aVoxelVector.size() - 1)) - { - voxelIndex2(0) = (aVoxelVector.at(i + 1)).x(); - voxelIndex2(1) = (aVoxelVector.at(i + 1)).y(); - voxelIndex2(2) = sliceNumber; - } - else - { - voxelIndex2(0) = (aVoxelVector.at(0)).x(); - voxelIndex2(1) = (aVoxelVector.at(0)).y(); - voxelIndex2(2) = sliceNumber; - } - - WorldCoordinate3D p1; - _geoInfo.indexToWorldCoordinate(voxelIndex, p1); - SpacingVectorType3D delta = _geoInfo.getSpacing(); - - WorldCoordinate3D p2; - _geoInfo.indexToWorldCoordinate(voxelIndex2, p2); - SpacingVectorType3D delta2 = _geoInfo.getSpacing(); - - WorldCoordinate3D wp1; - wp1(0) = p1.x() + delta.x() * 0.75; - wp1(1) = p1.y() + delta.y() * 0.75; - wp1(2) = p1.z(); - - WorldCoordinate3D wp2; - wp2(0) = p2.x() + delta.x() * 0.75; - wp2(1) = p2.y() + delta.y() * 0.75; - wp2(2) = p2.z(); - - polygon.push_back(wp1); - - double diffX = (wp2.x() - wp1.x()) / 1000.0; - double diffY = (wp2.y() - wp1.y()) / 1000.0; - - WorldCoordinate3D wp_intermediate; - wp_intermediate(0) = 0; - wp_intermediate(1) = 0; - - for (int j = 0; j < 1000; j++) - { - wp_intermediate(0) = wp1.x() + j * diffX; - wp_intermediate(1) = wp1.y() + j * diffY; - - polygon.push_back(wp_intermediate); - } - } - - std::cout << std::endl; - return polygon; - } - - PolygonType CreateTestStructure::createPolygonCircle(std::vector aVoxelVector, - GridIndexType sliceNumber) - { - - PolygonType polygon; - - if (aVoxelVector.size() > 0) - { - unsigned int i = 0; - - VoxelGridIndex3D voxelIndex; - - voxelIndex(0) = (aVoxelVector.at(i)).x(); - voxelIndex(1) = (aVoxelVector.at(i)).y(); - voxelIndex(2) = sliceNumber; - - WorldCoordinate3D p1; - _geoInfo.indexToWorldCoordinate(voxelIndex, p1); - SpacingVectorType3D delta = _geoInfo.getSpacing(); - - WorldCoordinate3D wp1; - wp1(0) = p1.x(); - wp1(1) = p1.y(); - wp1(2) = p1.z(); - - WorldCoordinate3D wp_intermediate; - wp_intermediate(0) = 0; - wp_intermediate(1) = 0; - wp_intermediate(2) = p1.z(); - - double radius = 2 * delta.x(); - double frac_radius = (radius * 0.001); - - double correct_y = (delta.x() / delta.y()); - - for (unsigned int j = 0; j <= 1000; j++) - { - double y_offset = sqrt((radius * radius) - ((frac_radius * j) * (frac_radius * j))); - - wp_intermediate(0) = wp1.x() + frac_radius * j; - wp_intermediate(1) = wp1.y() - (y_offset * correct_y); - - polygon.push_back(wp_intermediate); - } - - for (unsigned int j = 1000; j <= 1000; j--) - { - - double y_offset = sqrt((radius * radius) - ((frac_radius * j) * (frac_radius * j))); - - wp_intermediate(0) = wp1.x() + frac_radius * j; - wp_intermediate(1) = wp1.y() + (y_offset * correct_y); - - polygon.push_back(wp_intermediate); - } - - for (unsigned int j = 0; j <= 1000; j++) - { - double y_offset = sqrt((radius * radius) - ((frac_radius * j) * (frac_radius * j))); - - wp_intermediate(0) = wp1.x() - frac_radius * j; - wp_intermediate(1) = wp1.y() + y_offset * correct_y; - - polygon.push_back(wp_intermediate); - } - - for (unsigned int j = 1000; j <= 1000; j--) - { - - double y_offset = sqrt((radius * radius) - ((frac_radius * j) * (frac_radius * j))); - - wp_intermediate(0) = wp1.x() + frac_radius * j; - wp_intermediate(1) = wp1.y() + (y_offset * correct_y); - - polygon.push_back(wp_intermediate); - } - } - - std::cout << std::endl; - return polygon; - } - - PolygonType CreateTestStructure::createStructureSeveralSectionsInsideOneVoxelA( - std::vector aVoxelVector, GridIndexType sliceNumber) - { - - PolygonType polygon; - - if (aVoxelVector.size() > 0) - { - int i = 0; - - VoxelGridIndex3D voxelIndex; - - voxelIndex(0) = (aVoxelVector.at(i)).x(); - voxelIndex(1) = (aVoxelVector.at(i)).y(); - voxelIndex(2) = sliceNumber; - - WorldCoordinate3D p1; - _geoInfo.indexToWorldCoordinate(voxelIndex, p1); - SpacingVectorType3D delta = _geoInfo.getSpacing(); - - WorldCoordinate3D wp1; - wp1(0) = p1.x(); - wp1(1) = p1.y(); - wp1(2) = p1.z(); - - WorldCoordinate3D wp_intermediate; - wp_intermediate(0) = 0; - wp_intermediate(1) = 0; - wp_intermediate(2) = p1.z(); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.25); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.25); - wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); - wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.75); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.75); - wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); - wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 1.25); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 1.25); - wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 1.5); - wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 1.5); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 1.75); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 1.75); - wp_intermediate(1) = wp1.y() + (delta.y() * 3.0); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x(); - wp_intermediate(1) = wp1.y() + (delta.y() * 3.0); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x(); - wp_intermediate(1) = wp1.y() + (delta.y() * 3.0); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x(); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); - - polygon.push_back(wp_intermediate); - } - - std::cout << std::endl; - return polygon; - } - - PolygonType CreateTestStructure::createStructureSelfTouchingA(std::vector - aVoxelVector, GridIndexType sliceNumber) - { - - PolygonType polygon; - - if (aVoxelVector.size() > 0) - { - int i = 0; - - VoxelGridIndex3D voxelIndex; - - voxelIndex(0) = (aVoxelVector.at(i)).x(); - voxelIndex(1) = (aVoxelVector.at(i)).y(); - voxelIndex(2) = sliceNumber; - - WorldCoordinate3D p1; - _geoInfo.indexToWorldCoordinate(voxelIndex, p1); - SpacingVectorType3D delta = _geoInfo.getSpacing(); - - WorldCoordinate3D wp1; - wp1(0) = p1.x(); - wp1(1) = p1.y(); - wp1(2) = p1.z(); - - - WorldCoordinate3D wp_intermediate; - wp_intermediate(0) = 0; - wp_intermediate(1) = 0; - wp_intermediate(2) = p1.z(); - - wp_intermediate(0) = wp1.x(); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); - wp_intermediate(1) = wp1.y(); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); - wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); - wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); - wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x(); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); - - polygon.push_back(wp_intermediate); - } - - std::cout << std::endl; - return polygon; - } - - PolygonType CreateTestStructure::createStructureSelfTouchingB(std::vector - aVoxelVector, GridIndexType sliceNumber) - { - - PolygonType polygon; - - if (aVoxelVector.size() > 0) - { - int i = 0; - - VoxelGridIndex3D voxelIndex; - - voxelIndex(0) = (aVoxelVector.at(i)).x(); - voxelIndex(1) = (aVoxelVector.at(i)).y(); - voxelIndex(2) = sliceNumber; - - WorldCoordinate3D p1; - _geoInfo.indexToWorldCoordinate(voxelIndex, p1); - SpacingVectorType3D delta = _geoInfo.getSpacing(); - - WorldCoordinate3D wp1; - wp1(0) = p1.x(); - wp1(1) = p1.y(); - wp1(2) = p1.z(); - - WorldCoordinate3D wp_intermediate; - wp_intermediate(0) = 0; - wp_intermediate(1) = 0; - wp_intermediate(2) = p1.z(); - - wp_intermediate(0) = wp1.x(); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); - wp_intermediate(1) = wp1.y(); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); - wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); - wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x(); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); - wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); - - polygon.push_back(wp_intermediate); - - wp_intermediate(0) = wp1.x(); - wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); - - polygon.push_back(wp_intermediate); - } - - std::cout << std::endl; - return polygon; - } - - }//testing -}//rttb - +// ----------------------------------------------------------------------- +// 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. +// +//------------------------------------------------------------------------ + +// this file defines the rttbCoreTests for the test driver +// and all it expects is that you have a function called RegisterTests + +#include + +#include "CreateTestStructure.h" +#include "rttbNullPointerException.h" +#include "rttbInvalidParameterException.h" +#include "rttbInvalidDoseException.h" + +namespace rttb +{ + + namespace testing + { + + CreateTestStructure::~CreateTestStructure() {} + + CreateTestStructure::CreateTestStructure(const core::GeometricInfo& aGeoInfo) + { + _geoInfo = aGeoInfo; + } + + PolygonType CreateTestStructure::createPolygonLeftUpper(std::vector aVoxelVector, + GridIndexType sliceNumber) + { + + PolygonType polygon; + + for (size_t i = 0; i < aVoxelVector.size(); i++) + { + VoxelGridIndex3D voxelIndex; + voxelIndex(0) = (aVoxelVector.at(i)).x(); + voxelIndex(1) = (aVoxelVector.at(i)).y(); + voxelIndex(2) = sliceNumber; + + WorldCoordinate3D p1; + _geoInfo.indexToWorldCoordinate(voxelIndex, p1); + + polygon.push_back(p1); + std::cout << "(" << p1.x() << "," << p1.y() << "," << p1.z() << ")" << "; "; + } + + std::cout << std::endl; + return polygon; + } + + PolygonType CreateTestStructure::createPolygonCenter(std::vector aVoxelVector, + GridIndexType sliceNumber) + { + PolygonType polygon; + + for (size_t i = 0; i < aVoxelVector.size(); i++) + { + VoxelGridIndex3D voxelIndex; + voxelIndex(0) = (aVoxelVector.at(i)).x(); + voxelIndex(1) = (aVoxelVector.at(i)).y(); + voxelIndex(2) = sliceNumber; + + WorldCoordinate3D p1; + _geoInfo.indexToWorldCoordinate(voxelIndex, p1); + + WorldCoordinate3D p; + p(0) = p1.x() ; + p(1) = p1.y() ; + //This can be done directly for x/y coordinates, but not for z. Thus, we do it in this function. + p(2) = p1.z() - _geoInfo.getSpacing().z() / 2; + + polygon.push_back(p); + } + + return polygon; + } + + PolygonType CreateTestStructure::createPolygonCenterOnPlaneCenter(std::vector aVoxelVector, + GridIndexType sliceNumber) + { + + PolygonType polygon; + + for (size_t i = 0; i < aVoxelVector.size(); i++) + { + VoxelGridIndex3D voxelIndex; + ContinuousVoxelGridIndex3D indexDouble = ContinuousVoxelGridIndex3D((aVoxelVector.at(i)).x(), (aVoxelVector.at(i)).y(), + sliceNumber); + + WorldCoordinate3D p1; + _geoInfo.continuousIndexToWorldCoordinate(indexDouble, p1); + + polygon.push_back(p1); + } + + return polygon; + } + + + PolygonType CreateTestStructure::createPolygonBetweenUpperLeftAndCenter( + std::vector aVoxelVector, GridIndexType sliceNumber) + { + + PolygonType polygon; + + for (size_t i = 0; i < aVoxelVector.size(); i++) + { + VoxelGridIndex3D voxelIndex; + voxelIndex(0) = (aVoxelVector.at(i)).x(); + voxelIndex(1) = (aVoxelVector.at(i)).y(); + voxelIndex(2) = sliceNumber; + + WorldCoordinate3D p1; + _geoInfo.indexToWorldCoordinate(voxelIndex, p1); + SpacingVectorType3D delta = _geoInfo.getSpacing(); + + WorldCoordinate3D p; + p(0) = p1.x() + delta.x() / 4; + p(1) = p1.y() + delta.y() / 4; + p(2) = p1.z(); + + polygon.push_back(p); + std::cout << "(" << p.x() << "," << p.y() << "," << p.z() << ")" << "; "; + } + + std::cout << std::endl; + return polygon; + } + + + PolygonType CreateTestStructure::createPolygonBetweenLowerRightAndCenter( + std::vector aVoxelVector, GridIndexType sliceNumber) + { + + PolygonType polygon; + + for (size_t i = 0; i < aVoxelVector.size(); i++) + { + VoxelGridIndex3D voxelIndex; + voxelIndex(0) = (aVoxelVector.at(i)).x(); + voxelIndex(1) = (aVoxelVector.at(i)).y(); + voxelIndex(2) = sliceNumber; + + WorldCoordinate3D p1; + _geoInfo.indexToWorldCoordinate(voxelIndex, p1); + SpacingVectorType3D delta = _geoInfo.getSpacing(); + + WorldCoordinate3D p; + p(0) = p1.x() + delta.x() * 0.75; + p(1) = p1.y() + delta.y() * 0.75; + p(2) = p1.z(); + + polygon.push_back(p); + std::cout << "(" << p.x() << "," << p.y() << "," << p.z() << ")" << "; "; + } + + std::cout << std::endl; + return polygon; + } + + + PolygonType CreateTestStructure::createPolygonLeftEdgeMiddle(std::vector + aVoxelVector, GridIndexType sliceNumber) + { + + PolygonType polygon; + + for (size_t i = 0; i < aVoxelVector.size(); i++) + { + VoxelGridIndex3D voxelIndex; + voxelIndex(0) = (aVoxelVector.at(i)).x(); + voxelIndex(1) = (aVoxelVector.at(i)).y(); + voxelIndex(2) = sliceNumber; + + WorldCoordinate3D p1; + _geoInfo.indexToWorldCoordinate(voxelIndex, p1); + SpacingVectorType3D delta = _geoInfo.getSpacing(); + + WorldCoordinate3D p; + p(0) = p1.x(); + p(1) = p1.y() + delta.y() * 0.5; + p(2) = p1.z(); + + polygon.push_back(p); + std::cout << "(" << p.x() << "," << p.y() << "," << p.z() << ")" << "; "; + } + + std::cout << std::endl; + return polygon; + } + + + + PolygonType CreateTestStructure::createPolygonUpperCenter(std::vector + aVoxelVector, GridIndexType sliceNumber) + { + + PolygonType polygon; + + for (size_t i = 0; i < aVoxelVector.size(); i++) + { + VoxelGridIndex3D voxelIndex; + voxelIndex(0) = (aVoxelVector.at(i)).x(); + voxelIndex(1) = (aVoxelVector.at(i)).y(); + voxelIndex(2) = sliceNumber; + + WorldCoordinate3D p1; + _geoInfo.indexToWorldCoordinate(voxelIndex, p1); + SpacingVectorType3D delta = _geoInfo.getSpacing(); + + WorldCoordinate3D p; + p(0) = p1.x() + delta.x() * 0.5; + p(1) = p1.y(); + p(2) = p1.z(); + + polygon.push_back(p); + std::cout << "(" << p.x() << "," << p.y() << "," << p.z() << ")" << "; "; + } + + std::cout << std::endl; + return polygon; + } + + + + PolygonType CreateTestStructure::createPolygonIntermediatePoints(std::vector + aVoxelVector, GridIndexType sliceNumber) + { + + PolygonType polygon; + + for (size_t i = 0; i < aVoxelVector.size(); i++) + { + VoxelGridIndex3D voxelIndex; + VoxelGridIndex3D voxelIndex2; + + voxelIndex(0) = (aVoxelVector.at(i)).x(); + voxelIndex(1) = (aVoxelVector.at(i)).y(); + voxelIndex(2) = sliceNumber; + + if (i < (aVoxelVector.size() - 1)) + { + voxelIndex2(0) = (aVoxelVector.at(i + 1)).x(); + voxelIndex2(1) = (aVoxelVector.at(i + 1)).y(); + voxelIndex2(2) = sliceNumber; + } + else + { + voxelIndex2(0) = (aVoxelVector.at(0)).x(); + voxelIndex2(1) = (aVoxelVector.at(0)).y(); + voxelIndex2(2) = sliceNumber; + } + + WorldCoordinate3D p1; + _geoInfo.indexToWorldCoordinate(voxelIndex, p1); + SpacingVectorType3D delta = _geoInfo.getSpacing(); + + WorldCoordinate3D p2; + _geoInfo.indexToWorldCoordinate(voxelIndex2, p2); + SpacingVectorType3D delta2 = _geoInfo.getSpacing(); + + WorldCoordinate3D wp1; + wp1(0) = p1.x() + delta.x() * 0.75; + wp1(1) = p1.y() + delta.y() * 0.75; + wp1(2) = p1.z(); + + WorldCoordinate3D wp2; + wp2(0) = p2.x() + delta.x() * 0.75; + wp2(1) = p2.y() + delta.y() * 0.75; + wp2(2) = p2.z(); + + polygon.push_back(wp1); + + double diffX = (wp2.x() - wp1.x()) / 1000.0; + double diffY = (wp2.y() - wp1.y()) / 1000.0; + + WorldCoordinate3D wp_intermediate; + wp_intermediate(0) = 0; + wp_intermediate(1) = 0; + + for (int j = 0; j < 1000; j++) + { + wp_intermediate(0) = wp1.x() + j * diffX; + wp_intermediate(1) = wp1.y() + j * diffY; + + polygon.push_back(wp_intermediate); + } + } + + std::cout << std::endl; + return polygon; + } + + PolygonType CreateTestStructure::createPolygonCircle(std::vector aVoxelVector, + GridIndexType sliceNumber) + { + + PolygonType polygon; + + if (aVoxelVector.size() > 0) + { + unsigned int i = 0; + + VoxelGridIndex3D voxelIndex; + + voxelIndex(0) = (aVoxelVector.at(i)).x(); + voxelIndex(1) = (aVoxelVector.at(i)).y(); + voxelIndex(2) = sliceNumber; + + WorldCoordinate3D p1; + _geoInfo.indexToWorldCoordinate(voxelIndex, p1); + SpacingVectorType3D delta = _geoInfo.getSpacing(); + + WorldCoordinate3D wp1; + wp1(0) = p1.x(); + wp1(1) = p1.y(); + wp1(2) = p1.z(); + + WorldCoordinate3D wp_intermediate; + wp_intermediate(0) = 0; + wp_intermediate(1) = 0; + wp_intermediate(2) = p1.z(); + + double radius = 2 * delta.x(); + double frac_radius = (radius * 0.001); + + double correct_y = (delta.x() / delta.y()); + + for (unsigned int j = 0; j <= 1000; j++) + { + double y_offset = sqrt((radius * radius) - ((frac_radius * j) * (frac_radius * j))); + + wp_intermediate(0) = wp1.x() + frac_radius * j; + wp_intermediate(1) = wp1.y() - (y_offset * correct_y); + + polygon.push_back(wp_intermediate); + } + + for (unsigned int j = 1000; j <= 1000; j--) + { + + double y_offset = sqrt((radius * radius) - ((frac_radius * j) * (frac_radius * j))); + + wp_intermediate(0) = wp1.x() + frac_radius * j; + wp_intermediate(1) = wp1.y() + (y_offset * correct_y); + + polygon.push_back(wp_intermediate); + } + + for (unsigned int j = 0; j <= 1000; j++) + { + double y_offset = sqrt((radius * radius) - ((frac_radius * j) * (frac_radius * j))); + + wp_intermediate(0) = wp1.x() - frac_radius * j; + wp_intermediate(1) = wp1.y() + y_offset * correct_y; + + polygon.push_back(wp_intermediate); + } + + for (unsigned int j = 1000; j <= 1000; j--) + { + + double y_offset = sqrt((radius * radius) - ((frac_radius * j) * (frac_radius * j))); + + wp_intermediate(0) = wp1.x() + frac_radius * j; + wp_intermediate(1) = wp1.y() + (y_offset * correct_y); + + polygon.push_back(wp_intermediate); + } + } + + std::cout << std::endl; + return polygon; + } + + PolygonType CreateTestStructure::createStructureSeveralSectionsInsideOneVoxelA( + std::vector aVoxelVector, GridIndexType sliceNumber) + { + + PolygonType polygon; + + if (aVoxelVector.size() > 0) + { + int i = 0; + + VoxelGridIndex3D voxelIndex; + + voxelIndex(0) = (aVoxelVector.at(i)).x(); + voxelIndex(1) = (aVoxelVector.at(i)).y(); + voxelIndex(2) = sliceNumber; + + WorldCoordinate3D p1; + _geoInfo.indexToWorldCoordinate(voxelIndex, p1); + SpacingVectorType3D delta = _geoInfo.getSpacing(); + + WorldCoordinate3D wp1; + wp1(0) = p1.x(); + wp1(1) = p1.y(); + wp1(2) = p1.z(); + + WorldCoordinate3D wp_intermediate; + wp_intermediate(0) = 0; + wp_intermediate(1) = 0; + wp_intermediate(2) = p1.z(); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.25); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.25); + wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); + wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.75); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.75); + wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); + wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 1.25); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 1.25); + wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 1.5); + wp_intermediate(1) = wp1.y() + (delta.y() * 2.75); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 1.5); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 1.75); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 1.75); + wp_intermediate(1) = wp1.y() + (delta.y() * 3.0); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x(); + wp_intermediate(1) = wp1.y() + (delta.y() * 3.0); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x(); + wp_intermediate(1) = wp1.y() + (delta.y() * 3.0); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x(); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.75); + + polygon.push_back(wp_intermediate); + } + + std::cout << std::endl; + return polygon; + } + + PolygonType CreateTestStructure::createStructureSelfTouchingA(std::vector + aVoxelVector, GridIndexType sliceNumber) + { + + PolygonType polygon; + + if (aVoxelVector.size() > 0) + { + int i = 0; + + VoxelGridIndex3D voxelIndex; + + voxelIndex(0) = (aVoxelVector.at(i)).x(); + voxelIndex(1) = (aVoxelVector.at(i)).y(); + voxelIndex(2) = sliceNumber; + + WorldCoordinate3D p1; + _geoInfo.indexToWorldCoordinate(voxelIndex, p1); + SpacingVectorType3D delta = _geoInfo.getSpacing(); + + WorldCoordinate3D wp1; + wp1(0) = p1.x(); + wp1(1) = p1.y(); + wp1(2) = p1.z(); + + + WorldCoordinate3D wp_intermediate; + wp_intermediate(0) = 0; + wp_intermediate(1) = 0; + wp_intermediate(2) = p1.z(); + + wp_intermediate(0) = wp1.x(); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); + wp_intermediate(1) = wp1.y(); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); + wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); + wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); + wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x(); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); + + polygon.push_back(wp_intermediate); + } + + std::cout << std::endl; + return polygon; + } + + PolygonType CreateTestStructure::createStructureSelfTouchingB(std::vector + aVoxelVector, GridIndexType sliceNumber) + { + + PolygonType polygon; + + if (aVoxelVector.size() > 0) + { + int i = 0; + + VoxelGridIndex3D voxelIndex; + + voxelIndex(0) = (aVoxelVector.at(i)).x(); + voxelIndex(1) = (aVoxelVector.at(i)).y(); + voxelIndex(2) = sliceNumber; + + WorldCoordinate3D p1; + _geoInfo.indexToWorldCoordinate(voxelIndex, p1); + SpacingVectorType3D delta = _geoInfo.getSpacing(); + + WorldCoordinate3D wp1; + wp1(0) = p1.x(); + wp1(1) = p1.y(); + wp1(2) = p1.z(); + + WorldCoordinate3D wp_intermediate; + wp_intermediate(0) = 0; + wp_intermediate(1) = 0; + wp_intermediate(2) = p1.z(); + + wp_intermediate(0) = wp1.x(); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); + wp_intermediate(1) = wp1.y(); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 1.0); + wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); + wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x(); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x() + (delta.x() * 0.5); + wp_intermediate(1) = wp1.y() + (delta.y() * 1.0); + + polygon.push_back(wp_intermediate); + + wp_intermediate(0) = wp1.x(); + wp_intermediate(1) = wp1.y() + (delta.y() * 0.5); + + polygon.push_back(wp_intermediate); + } + + std::cout << std::endl; + return polygon; + } + + }//testing +}//rttb + diff --git a/testing/core/CreateTestStructure.h b/code/testhelper/CreateTestStructure.h similarity index 96% rename from testing/core/CreateTestStructure.h rename to code/testhelper/CreateTestStructure.h index cb0631f..a51ccca 100644 --- a/testing/core/CreateTestStructure.h +++ b/code/testhelper/CreateTestStructure.h @@ -1,75 +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. -// -//------------------------------------------------------------------------ - -#include "rttbStructure.h" -#include "rttbBaseType.h" -#include "rttbGeometricInfo.h" - -namespace rttb -{ - namespace testing - { - /*!@class CreateTestStructure - @brief Create dummy structures for testing. - */ - class CreateTestStructure - { - - private: - core::GeometricInfo _geoInfo; - CreateTestStructure() {}; - - public: - ~CreateTestStructure(); - - CreateTestStructure(const core::GeometricInfo& aGeoInfo); - - PolygonType createPolygonLeftUpper(std::vector aVoxelVector, - GridIndexType sliceNumber); - - /*The z coordinate of the polygon is the upper side of the voxel on the slice*/ - PolygonType createPolygonCenter(std::vector aVoxelVector, - GridIndexType sliceNumber); - - /*The z coordinate of the polygon is the center of the voxel on the slice*/ - PolygonType createPolygonCenterOnPlaneCenter(std::vector aVoxelVector, - GridIndexType sliceNumber); - - PolygonType createPolygonBetweenUpperLeftAndCenter(std::vector aVoxelVector, - GridIndexType sliceNumber); - PolygonType createPolygonBetweenLowerRightAndCenter(std::vector aVoxelVector, - GridIndexType sliceNumber); - PolygonType createPolygonIntermediatePoints(std::vector aVoxelVector, - GridIndexType sliceNumber); - PolygonType createPolygonUpperCenter(std::vector aVoxelVector, - GridIndexType sliceNumber); - PolygonType createPolygonLeftEdgeMiddle(std::vector aVoxelVector, - GridIndexType sliceNumber); - - PolygonType createPolygonCircle(std::vector aVoxelVector, - GridIndexType sliceNumber); - - PolygonType createStructureSeveralSectionsInsideOneVoxelA(std::vector - aVoxelVector, GridIndexType sliceNumber); - - PolygonType createStructureSelfTouchingA(std::vector aVoxelVector, - GridIndexType sliceNumber); - - PolygonType createStructureSelfTouchingB(std::vector aVoxelVector, - GridIndexType sliceNumber); - }; - }//testing -}//rttb - +// ----------------------------------------------------------------------- +// 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. +// +//------------------------------------------------------------------------ + +#include "rttbStructure.h" +#include "rttbBaseType.h" +#include "rttbGeometricInfo.h" + +#include "RTTBTestHelperExports.h" + +namespace rttb +{ + namespace testing + { + /*!@class CreateTestStructure + @brief Create dummy structures for testing. + */ + class RTTBTestHelper_EXPORT CreateTestStructure + { + + private: + core::GeometricInfo _geoInfo; + CreateTestStructure() {}; + + public: + ~CreateTestStructure(); + + CreateTestStructure(const core::GeometricInfo& aGeoInfo); + + PolygonType createPolygonLeftUpper(std::vector aVoxelVector, + GridIndexType sliceNumber); + + /*The z coordinate of the polygon is the upper side of the voxel on the slice*/ + PolygonType createPolygonCenter(std::vector aVoxelVector, + GridIndexType sliceNumber); + + /*The z coordinate of the polygon is the center of the voxel on the slice*/ + PolygonType createPolygonCenterOnPlaneCenter(std::vector aVoxelVector, + GridIndexType sliceNumber); + + PolygonType createPolygonBetweenUpperLeftAndCenter(std::vector aVoxelVector, + GridIndexType sliceNumber); + PolygonType createPolygonBetweenLowerRightAndCenter(std::vector aVoxelVector, + GridIndexType sliceNumber); + PolygonType createPolygonIntermediatePoints(std::vector aVoxelVector, + GridIndexType sliceNumber); + PolygonType createPolygonUpperCenter(std::vector aVoxelVector, + GridIndexType sliceNumber); + PolygonType createPolygonLeftEdgeMiddle(std::vector aVoxelVector, + GridIndexType sliceNumber); + + PolygonType createPolygonCircle(std::vector aVoxelVector, + GridIndexType sliceNumber); + + PolygonType createStructureSeveralSectionsInsideOneVoxelA(std::vector + aVoxelVector, GridIndexType sliceNumber); + + PolygonType createStructureSelfTouchingA(std::vector aVoxelVector, + GridIndexType sliceNumber); + + PolygonType createStructureSelfTouchingB(std::vector aVoxelVector, + GridIndexType sliceNumber); + }; + }//testing +}//rttb + diff --git a/testing/core/DummyDVHGenerator.cpp b/code/testhelper/DummyDVHGenerator.cpp similarity index 96% rename from testing/core/DummyDVHGenerator.cpp rename to code/testhelper/DummyDVHGenerator.cpp index 66e1487..c4c9ac5 100644 --- a/testing/core/DummyDVHGenerator.cpp +++ b/code/testhelper/DummyDVHGenerator.cpp @@ -1,104 +1,104 @@ -// ----------------------------------------------------------------------- -// 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. -// -//------------------------------------------------------------------------ - -#include - -#include "DummyDVHGenerator.h" - -namespace rttb -{ - namespace testing - { - - DummyDVHGenerator::DummyDVHGenerator(): _binSize(DoseTypeGy(0.1)), _voxelVolume(8), _value(0) - { - /* initialize random seed: */ - srand(static_cast(time(nullptr))); - }; - - 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); - //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); - } - - 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); - } - - 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; - 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; - } - else if (!decrease) - { - _value = _value + DoseCalcType((double(rand()) / RAND_MAX) * (maxValue / 10)); - } - - if ((_value > maxValue) || (decrease)) - { - decrease = true; - _value = _value - DoseCalcType((double(rand()) / RAND_MAX) * (maxValue / 3)); - } - - if (_value < 0) - { - _value = 0; - } - } - else - { - _value = 0; - } - - aDataDifferential.push_back(_value); - } - - return core::DVH(aDataDifferential, _binSize, _voxelVolume, structureID, doseID); - } - } +// ----------------------------------------------------------------------- +// 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. +// +//------------------------------------------------------------------------ + +#include + +#include "DummyDVHGenerator.h" + +namespace rttb +{ + namespace testing + { + + DummyDVHGenerator::DummyDVHGenerator(): _binSize(DoseTypeGy(0.1)), _voxelVolume(8), _value(0) + { + /* initialize random seed: */ + srand(static_cast(time(nullptr))); + }; + + 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); + //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); + } + + 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); + } + + 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; + 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; + } + else if (!decrease) + { + _value = _value + DoseCalcType((double(rand()) / RAND_MAX) * (maxValue / 10)); + } + + if ((_value > maxValue) || (decrease)) + { + decrease = true; + _value = _value - DoseCalcType((double(rand()) / RAND_MAX) * (maxValue / 3)); + } + + if (_value < 0) + { + _value = 0; + } + } + else + { + _value = 0; + } + + aDataDifferential.push_back(_value); + } + + return core::DVH(aDataDifferential, _binSize, _voxelVolume, structureID, doseID); + } + } } \ No newline at end of file diff --git a/testing/core/DummyDVHGenerator.h b/code/testhelper/DummyDVHGenerator.h similarity index 95% rename from testing/core/DummyDVHGenerator.h rename to code/testhelper/DummyDVHGenerator.h index c65c51e..81b5db6 100644 --- a/testing/core/DummyDVHGenerator.h +++ b/code/testhelper/DummyDVHGenerator.h @@ -1,65 +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. -// -//------------------------------------------------------------------------ - -#ifndef __DUMMY_DVH_GENERATOR_H -#define __DUMMY_DVH_GENERATOR_H - -#include - -#include "rttbDVH.h" -#include "rttbBaseType.h" - -namespace rttb -{ - - namespace testing - { - - /*! @class DummyDVHGenerator - @brief generate DVHs for testing based on a randomly generated dose data vector. - */ - class DummyDVHGenerator - { - private: - DoseTypeGy _binSize; - DoseVoxelVolumeType _voxelVolume; - DoseCalcType _value; - - public: - ~DummyDVHGenerator() {}; - - DummyDVHGenerator(); - - /*! generate a dummy DVH with bin size = 0.1, voxel volume = 8 and 100 entries. - The values of the 100 bins are randomly generated [0,1000]. - */ - core::DVH generateDVH(IDType structureID, IDType doseID); - - /*! generate a dummy DVH with bin size = 0.1, voxel volume = 8 and 100 entries. - The values of the 100 bins all contain the given value. - */ - core::DVH generateDVH(IDType structureID, IDType doseID, DoseCalcType value); - - /*! generate a dummy DVH with bin size = 0.1, voxel volume = 0.016 and 200 entries. - The values of the 200 bins are random values inside the interval defined by minValue and maxValue. - */ - core::DVH generateDVH(IDType structureID, IDType doseID, DoseCalcType minValue, - DoseCalcType maxValue); - - }; - } -} - -#endif +// ----------------------------------------------------------------------- +// 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. +// +//------------------------------------------------------------------------ + +#ifndef __DUMMY_DVH_GENERATOR_H +#define __DUMMY_DVH_GENERATOR_H + +#include + +#include "rttbDVH.h" +#include "rttbBaseType.h" + +#include "RTTBTestHelperExports.h" + +namespace rttb +{ + + namespace testing + { + + /*! @class DummyDVHGenerator + @brief generate DVHs for testing based on a randomly generated dose data vector. + */ + class RTTBTestHelper_EXPORT DummyDVHGenerator + { + private: + DoseTypeGy _binSize; + DoseVoxelVolumeType _voxelVolume; + DoseCalcType _value; + + public: + ~DummyDVHGenerator() {}; + + DummyDVHGenerator(); + + /*! generate a dummy DVH with bin size = 0.1, voxel volume = 8 and 100 entries. + The values of the 100 bins are randomly generated [0,1000]. + */ + core::DVH generateDVH(IDType structureID, IDType doseID); + + /*! generate a dummy DVH with bin size = 0.1, voxel volume = 8 and 100 entries. + The values of the 100 bins all contain the given value. + */ + core::DVH generateDVH(IDType structureID, IDType doseID, DoseCalcType value); + + /*! generate a dummy DVH with bin size = 0.1, voxel volume = 0.016 and 200 entries. + The values of the 200 bins are random values inside the interval defined by minValue and maxValue. + */ + core::DVH generateDVH(IDType structureID, IDType doseID, DoseCalcType minValue, + DoseCalcType maxValue); + + }; + } +} + +#endif diff --git a/testing/core/DummyDoseAccessor.cpp b/code/testhelper/DummyDoseAccessor.cpp similarity index 95% rename from testing/core/DummyDoseAccessor.cpp rename to code/testhelper/DummyDoseAccessor.cpp index d88c09c..2b9d707 100644 --- a/testing/core/DummyDoseAccessor.cpp +++ b/code/testhelper/DummyDoseAccessor.cpp @@ -1,94 +1,94 @@ -// ----------------------------------------------------------------------- -// 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. -// -//------------------------------------------------------------------------ - -#include -#include -#include - -#include "DummyDoseAccessor.h" -#include "rttbNullPointerException.h" -#include "rttbInvalidDoseException.h" -#include "rttbIndexOutOfBoundsException.h" - -namespace rttb -{ - namespace testing - { - - DummyDoseAccessor::~DummyDoseAccessor() {} - - DummyDoseAccessor::DummyDoseAccessor() - { - boost::uuids::uuid id; - boost::uuids::random_generator generator; - id = generator(); - std::stringstream ss; - ss << id; - _doseUID = "DummyDoseAccessor_" + ss.str(); - - assembleGeometricInfo(); - - for (int i = 0; i < _geoInfo.getNumberOfVoxels(); i++) - { - doseData.push_back((double(rand()) / RAND_MAX) * 1000); - } - } - - DummyDoseAccessor::DummyDoseAccessor(const std::vector& aDoseVector, - const core::GeometricInfo& geoInfo) - { - boost::uuids::uuid id; - boost::uuids::random_generator generator; - id = generator(); - std::stringstream ss; - ss << id; - _doseUID = "DummyDoseAccessor_" + ss.str(); - - doseData = aDoseVector; - _geoInfo = geoInfo; - } - - void DummyDoseAccessor::assembleGeometricInfo() { - SpacingVectorType3D aVector(2.5); - _geoInfo.setSpacing(aVector); - WorldCoordinate3D anOtherVector(-25, -2, 35); - _geoInfo.setImagePositionPatient(anOtherVector); - _geoInfo.setNumRows(11); - _geoInfo.setNumColumns(10); - _geoInfo.setNumSlices(10); - - OrientationMatrix unit = OrientationMatrix(); - _geoInfo.setOrientationMatrix(unit); - } - - GenericValueType DummyDoseAccessor::getValueAt(const VoxelGridID aID) const - { - if (!_geoInfo.validID(aID)) - { - throw core::IndexOutOfBoundsException("Not a valid Position!"); - } - - return doseData.at(aID); - } - - GenericValueType DummyDoseAccessor::getValueAt(const VoxelGridIndex3D& aIndex) const - { - VoxelGridID gridID = 0; - _geoInfo.convert(aIndex, gridID); - return getValueAt(gridID); - } - - }//end namespace testing +// ----------------------------------------------------------------------- +// 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. +// +//------------------------------------------------------------------------ + +#include +#include +#include + +#include "DummyDoseAccessor.h" +#include "rttbNullPointerException.h" +#include "rttbInvalidDoseException.h" +#include "rttbIndexOutOfBoundsException.h" + +namespace rttb +{ + namespace testing + { + + DummyDoseAccessor::~DummyDoseAccessor() {} + + DummyDoseAccessor::DummyDoseAccessor() + { + boost::uuids::uuid id; + boost::uuids::random_generator generator; + id = generator(); + std::stringstream ss; + ss << id; + _doseUID = "DummyDoseAccessor_" + ss.str(); + + assembleGeometricInfo(); + + for (int i = 0; i < _geoInfo.getNumberOfVoxels(); i++) + { + doseData.push_back((double(rand()) / RAND_MAX) * 1000); + } + } + + DummyDoseAccessor::DummyDoseAccessor(const std::vector& aDoseVector, + const core::GeometricInfo& geoInfo) + { + boost::uuids::uuid id; + boost::uuids::random_generator generator; + id = generator(); + std::stringstream ss; + ss << id; + _doseUID = "DummyDoseAccessor_" + ss.str(); + + doseData = aDoseVector; + _geoInfo = geoInfo; + } + + void DummyDoseAccessor::assembleGeometricInfo() { + SpacingVectorType3D aVector(2.5); + _geoInfo.setSpacing(aVector); + WorldCoordinate3D anOtherVector(-25, -2, 35); + _geoInfo.setImagePositionPatient(anOtherVector); + _geoInfo.setNumRows(11); + _geoInfo.setNumColumns(10); + _geoInfo.setNumSlices(10); + + OrientationMatrix unit = OrientationMatrix(); + _geoInfo.setOrientationMatrix(unit); + } + + GenericValueType DummyDoseAccessor::getValueAt(const VoxelGridID aID) const + { + if (!_geoInfo.validID(aID)) + { + throw core::IndexOutOfBoundsException("Not a valid Position!"); + } + + return doseData.at(aID); + } + + GenericValueType DummyDoseAccessor::getValueAt(const VoxelGridIndex3D& aIndex) const + { + VoxelGridID gridID = 0; + _geoInfo.convert(aIndex, gridID); + return getValueAt(gridID); + } + + }//end namespace testing }//end namespace rttb \ No newline at end of file diff --git a/testing/core/DummyDoseAccessor.h b/code/testhelper/DummyDoseAccessor.h similarity index 93% rename from testing/core/DummyDoseAccessor.h rename to code/testhelper/DummyDoseAccessor.h index d31a21e..c290e3e 100644 --- a/testing/core/DummyDoseAccessor.h +++ b/code/testhelper/DummyDoseAccessor.h @@ -1,78 +1,80 @@ -// ----------------------------------------------------------------------- -// RTToolbox - DKFZ radiotherapy quantitative evaluation library -// -// Copyright (c) German Cancer Research Center (DKFZ), -// Software development for Integrated Diagnostics and Therapy (SIDT). -// ALL RIGHTS RESERVED. -// See rttbCopyright.txt or -// http://www.dkfz.de/en/sidt/projects/rttb/copyright.html -// -// This software is distributed WITHOUT ANY WARRANTY; without even -// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -// PURPOSE. See the above copyright notices for more information. -// -//------------------------------------------------------------------------ - -#ifndef __DUMMY_DOSE_ACCESSOR_H -#define __DUMMY_DOSE_ACCESSOR_H - -#include - -#include - -#include "rttbAccessorWithGeoInfoBase.h" -#include "rttbGeometricInfo.h" -#include "rttbBaseType.h" - -namespace rttb -{ - namespace testing - { - - /*! @class DummyDoseAccessor - @brief A dummy DoseAccessor for testing filled with random dose values between 0 and 100. - The default grid size is [11,10,5] - */ - class DummyDoseAccessor: public core::AccessorWithGeoInfoBase - { - - private: - /*! vector of dose data(absolute Gy dose/doseGridScaling)*/ - std::vector doseData; - - IDType _doseUID; - - - public: - ~DummyDoseAccessor(); - - /*! @brief A dummy DoseAccessor for testing filled with random dose values between 0 and 100. - The default grid size is [11,10,5] - */ - DummyDoseAccessor(); - - /*! @brief Constructor. - Initialisation of dose with a given vector. - */ - DummyDoseAccessor(const std::vector& aDoseVector, const core::GeometricInfo& geoInfo); - - void assembleGeometricInfo() override; - - const std::vector* getDoseVector() const - { - return &doseData; - }; - - GenericValueType getValueAt(const VoxelGridID aID) const; - - GenericValueType getValueAt(const VoxelGridIndex3D& aIndex) const; - - const IDType getUID() const - { - return _doseUID; - }; - }; - } -} - -#endif +// ----------------------------------------------------------------------- +// 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. +// +//------------------------------------------------------------------------ + +#ifndef __DUMMY_DOSE_ACCESSOR_H +#define __DUMMY_DOSE_ACCESSOR_H + +#include + +#include + +#include "rttbAccessorWithGeoInfoBase.h" +#include "rttbGeometricInfo.h" +#include "rttbBaseType.h" + +#include "RTTBTestHelperExports.h" + +namespace rttb +{ + namespace testing + { + + /*! @class DummyDoseAccessor + @brief A dummy DoseAccessor for testing filled with random dose values between 0 and 100. + The default grid size is [11,10,5] + */ + class RTTBTestHelper_EXPORT DummyDoseAccessor: public core::AccessorWithGeoInfoBase + { + + private: + /*! vector of dose data(absolute Gy dose/doseGridScaling)*/ + std::vector doseData; + + IDType _doseUID; + + + public: + ~DummyDoseAccessor(); + + /*! @brief A dummy DoseAccessor for testing filled with random dose values between 0 and 100. + The default grid size is [11,10,5] + */ + DummyDoseAccessor(); + + /*! @brief Constructor. + Initialisation of dose with a given vector. + */ + DummyDoseAccessor(const std::vector& aDoseVector, const core::GeometricInfo& geoInfo); + + void assembleGeometricInfo() override; + + const std::vector* getDoseVector() const + { + return &doseData; + }; + + GenericValueType getValueAt(const VoxelGridID aID) const; + + GenericValueType getValueAt(const VoxelGridIndex3D& aIndex) const; + + const IDType getUID() const + { + return _doseUID; + }; + }; + } +} + +#endif diff --git a/testing/core/DummyInhomogeneousDoseAccessor.cpp b/code/testhelper/DummyInhomogeneousDoseAccessor.cpp similarity index 100% rename from testing/core/DummyInhomogeneousDoseAccessor.cpp rename to code/testhelper/DummyInhomogeneousDoseAccessor.cpp diff --git a/testing/core/DummyInhomogeneousDoseAccessor.h b/code/testhelper/DummyInhomogeneousDoseAccessor.h similarity index 91% rename from testing/core/DummyInhomogeneousDoseAccessor.h rename to code/testhelper/DummyInhomogeneousDoseAccessor.h index 05a4938..78b7455 100644 --- a/testing/core/DummyInhomogeneousDoseAccessor.h +++ b/code/testhelper/DummyInhomogeneousDoseAccessor.h @@ -1,44 +1,46 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #ifndef __DUMMY_DOSE_INHOMOGENEOUS_ACCESSOR_H #define __DUMMY_DOSE_INHOMOGENEOUS_ACCESSOR_H #include "DummyDoseAccessor.h" +#include "RTTBTestHelperExports.h" + namespace rttb { namespace testing { /*! @class DummyInhomogeneousDoseAccessor @brief A dummy DoseAccessor for testing with inhomogeneous grid */ - class DummyInhomogeneousDoseAccessor: public DummyDoseAccessor + class RTTBTestHelper_EXPORT DummyInhomogeneousDoseAccessor: public DummyDoseAccessor { public: ~DummyInhomogeneousDoseAccessor(); /*! @brief A dummy DoseAccessor for testing filled with random dose values between 0 and 100. The default grid size is [11,10,5] */ DummyInhomogeneousDoseAccessor(); bool isGridHomogeneous() const override; }; } } #endif diff --git a/testing/core/DummyMaskAccessor.cpp b/code/testhelper/DummyMaskAccessor.cpp similarity index 95% rename from testing/core/DummyMaskAccessor.cpp rename to code/testhelper/DummyMaskAccessor.cpp index f6401e7..dc42d0c 100644 --- a/testing/core/DummyMaskAccessor.cpp +++ b/code/testhelper/DummyMaskAccessor.cpp @@ -1,156 +1,156 @@ -// ----------------------------------------------------------------------- -// 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. -// -//------------------------------------------------------------------------ - -#include - -#include -#include -#include - -#include "DummyMaskAccessor.h" -#include "rttbNullPointerException.h" - -namespace rttb -{ - namespace testing - { - - DummyMaskAccessor::DummyMaskAccessor(const core::GeometricInfo& aGeometricInfo) - { - _spRelevantVoxelVector = MaskVoxelListPointer(); - _geoInfo = aGeometricInfo; - - boost::uuids::uuid id; - boost::uuids::random_generator generator; - id = generator(); - std::stringstream ss; - ss << id; - _maskUID = "DummyMask_" + ss.str(); - } - - DummyMaskAccessor::DummyMaskAccessor(const core::GeometricInfo& aGeometricInfo, - MaskVoxelListPointer voxelListPtr) - { - _spRelevantVoxelVector = voxelListPtr; - _geoInfo = aGeometricInfo; - - boost::uuids::uuid id; - boost::uuids::random_generator generator; - id = generator(); - std::stringstream ss; - ss << id; - _maskUID = "DummyMask_" + ss.str(); - } - - void DummyMaskAccessor::updateMask() - { - MaskVoxelList newRelevantVoxelVector; - - if (_spRelevantVoxelVector) - { - return; - } - - for (int i = 0; i < _geoInfo.getNumberOfVoxels(); i++) - { - - if ((double(rand()) / RAND_MAX) > 0.5) - { - core::MaskVoxel newMaskVoxel(i); - newMaskVoxel.setRelevantVolumeFraction((double(rand()) / RAND_MAX)); - - newRelevantVoxelVector.push_back(newMaskVoxel); - } - } - - _spRelevantVoxelVector = boost::make_shared(newRelevantVoxelVector); - return; - } - - DummyMaskAccessor::MaskVoxelListPointer DummyMaskAccessor::getRelevantVoxelVector() - { - updateMask(); - return _spRelevantVoxelVector; - } - - DummyMaskAccessor::MaskVoxelListPointer DummyMaskAccessor::getRelevantVoxelVector( - float lowerThreshold) - { - auto filteredVoxelVectorPointer = boost::make_shared(); - updateMask(); - DummyMaskAccessor::MaskVoxelList::iterator it = _spRelevantVoxelVector->begin(); - - while (it != _spRelevantVoxelVector->end()) - { - if ((*it).getRelevantVolumeFraction() > lowerThreshold) - { - filteredVoxelVectorPointer->push_back(*it); - } - - ++it; - } - - return filteredVoxelVectorPointer; - } - - bool DummyMaskAccessor::getMaskAt(VoxelGridID aID, core::MaskVoxel& voxel) const - { - voxel.setRelevantVolumeFraction(0); - - if (!_geoInfo.validID(aID)) - { - return false; - } - - if (_spRelevantVoxelVector) - { - DummyMaskAccessor::MaskVoxelList::iterator it = _spRelevantVoxelVector->begin(); - - while (it != _spRelevantVoxelVector->end()) - { - if ((*it).getVoxelGridID() == aID) - { - voxel = (*it); - return true; - } - - ++it; - } - } - else - { - return false; - } - - return false; - - } - - bool DummyMaskAccessor::getMaskAt(const VoxelGridIndex3D& aIndex, core::MaskVoxel& voxel) const - { - VoxelGridID aVoxelGridID; - - if (_geoInfo.convert(aIndex, aVoxelGridID)) - { - return getMaskAt(aVoxelGridID, voxel); - } - else - { - return false; - } - } - - } +// ----------------------------------------------------------------------- +// 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. +// +//------------------------------------------------------------------------ + +#include + +#include +#include +#include + +#include "DummyMaskAccessor.h" +#include "rttbNullPointerException.h" + +namespace rttb +{ + namespace testing + { + + DummyMaskAccessor::DummyMaskAccessor(const core::GeometricInfo& aGeometricInfo) + { + _spRelevantVoxelVector = MaskVoxelListPointer(); + _geoInfo = aGeometricInfo; + + boost::uuids::uuid id; + boost::uuids::random_generator generator; + id = generator(); + std::stringstream ss; + ss << id; + _maskUID = "DummyMask_" + ss.str(); + } + + DummyMaskAccessor::DummyMaskAccessor(const core::GeometricInfo& aGeometricInfo, + MaskVoxelListPointer voxelListPtr) + { + _spRelevantVoxelVector = voxelListPtr; + _geoInfo = aGeometricInfo; + + boost::uuids::uuid id; + boost::uuids::random_generator generator; + id = generator(); + std::stringstream ss; + ss << id; + _maskUID = "DummyMask_" + ss.str(); + } + + void DummyMaskAccessor::updateMask() + { + MaskVoxelList newRelevantVoxelVector; + + if (_spRelevantVoxelVector) + { + return; + } + + for (int i = 0; i < _geoInfo.getNumberOfVoxels(); i++) + { + + if ((double(rand()) / RAND_MAX) > 0.5) + { + core::MaskVoxel newMaskVoxel(i); + newMaskVoxel.setRelevantVolumeFraction((double(rand()) / RAND_MAX)); + + newRelevantVoxelVector.push_back(newMaskVoxel); + } + } + + _spRelevantVoxelVector = boost::make_shared(newRelevantVoxelVector); + return; + } + + DummyMaskAccessor::MaskVoxelListPointer DummyMaskAccessor::getRelevantVoxelVector() + { + updateMask(); + return _spRelevantVoxelVector; + } + + DummyMaskAccessor::MaskVoxelListPointer DummyMaskAccessor::getRelevantVoxelVector( + float lowerThreshold) + { + auto filteredVoxelVectorPointer = boost::make_shared(); + updateMask(); + DummyMaskAccessor::MaskVoxelList::iterator it = _spRelevantVoxelVector->begin(); + + while (it != _spRelevantVoxelVector->end()) + { + if ((*it).getRelevantVolumeFraction() > lowerThreshold) + { + filteredVoxelVectorPointer->push_back(*it); + } + + ++it; + } + + return filteredVoxelVectorPointer; + } + + bool DummyMaskAccessor::getMaskAt(VoxelGridID aID, core::MaskVoxel& voxel) const + { + voxel.setRelevantVolumeFraction(0); + + if (!_geoInfo.validID(aID)) + { + return false; + } + + if (_spRelevantVoxelVector) + { + DummyMaskAccessor::MaskVoxelList::iterator it = _spRelevantVoxelVector->begin(); + + while (it != _spRelevantVoxelVector->end()) + { + if ((*it).getVoxelGridID() == aID) + { + voxel = (*it); + return true; + } + + ++it; + } + } + else + { + return false; + } + + return false; + + } + + bool DummyMaskAccessor::getMaskAt(const VoxelGridIndex3D& aIndex, core::MaskVoxel& voxel) const + { + VoxelGridID aVoxelGridID; + + if (_geoInfo.convert(aIndex, aVoxelGridID)) + { + return getMaskAt(aVoxelGridID, voxel); + } + else + { + return false; + } + } + + } } \ No newline at end of file diff --git a/testing/core/DummyMaskAccessor.h b/code/testhelper/DummyMaskAccessor.h similarity index 93% rename from testing/core/DummyMaskAccessor.h rename to code/testhelper/DummyMaskAccessor.h index d2c0466..595b6d2 100644 --- a/testing/core/DummyMaskAccessor.h +++ b/code/testhelper/DummyMaskAccessor.h @@ -1,75 +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. -// -//------------------------------------------------------------------------ - -#ifndef __DUMMY_MASK_ACCESSOR_H -#define __DUMMY_MASK_ACCESSOR_H - -#include - -#include "rttbMaskAccessorInterface.h" -#include "rttbGeometricInfo.h" -#include "rttbBaseType.h" - -namespace rttb -{ - namespace testing - { - - /*! @class DumyMaskAccessor - @brief Create a dummy MaskAccessor for testing. - */ - class DummyMaskAccessor: public core::MaskAccessorInterface - { - public: - typedef core::MaskAccessorInterface::MaskVoxelList MaskVoxelList; - typedef core::MaskAccessorInterface::MaskVoxelListPointer MaskVoxelListPointer; - - private: - /*! vector containing list of mask voxels*/ - MaskVoxelListPointer _spRelevantVoxelVector; - - core::GeometricInfo _geoInfo; - - IDType _maskUID; - - public: - DummyMaskAccessor(const core::GeometricInfo& aGeometricInfo); - DummyMaskAccessor(const core::GeometricInfo& aGeometricInfo, MaskVoxelListPointer voxelListPtr); - ~DummyMaskAccessor() {}; - - void updateMask(); - - const core::GeometricInfo& getGeometricInfo() const - { - return _geoInfo; - }; - - MaskVoxelListPointer getRelevantVoxelVector(); - - MaskVoxelListPointer getRelevantVoxelVector(float lowerThreshold); - - bool getMaskAt(const VoxelGridID aID, core::MaskVoxel& voxel) const; - - bool getMaskAt(const VoxelGridIndex3D& gridIndex, core::MaskVoxel& voxel) const; - - IDType getMaskUID() const - { - return _maskUID; - }; - }; - } -} - -#endif +// ----------------------------------------------------------------------- +// 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. +// +//------------------------------------------------------------------------ + +#ifndef __DUMMY_MASK_ACCESSOR_H +#define __DUMMY_MASK_ACCESSOR_H + +#include + +#include "rttbMaskAccessorInterface.h" +#include "rttbGeometricInfo.h" +#include "rttbBaseType.h" + +#include "RTTBTestHelperExports.h" + +namespace rttb +{ + namespace testing + { + + /*! @class DumyMaskAccessor + @brief Create a dummy MaskAccessor for testing. + */ + class RTTBTestHelper_EXPORT DummyMaskAccessor: public core::MaskAccessorInterface + { + public: + typedef core::MaskAccessorInterface::MaskVoxelList MaskVoxelList; + typedef core::MaskAccessorInterface::MaskVoxelListPointer MaskVoxelListPointer; + + private: + /*! vector containing list of mask voxels*/ + MaskVoxelListPointer _spRelevantVoxelVector; + + core::GeometricInfo _geoInfo; + + IDType _maskUID; + + public: + DummyMaskAccessor(const core::GeometricInfo& aGeometricInfo); + DummyMaskAccessor(const core::GeometricInfo& aGeometricInfo, MaskVoxelListPointer voxelListPtr); + ~DummyMaskAccessor() {}; + + void updateMask(); + + const core::GeometricInfo& getGeometricInfo() const + { + return _geoInfo; + }; + + MaskVoxelListPointer getRelevantVoxelVector(); + + MaskVoxelListPointer getRelevantVoxelVector(float lowerThreshold); + + bool getMaskAt(const VoxelGridID aID, core::MaskVoxel& voxel) const; + + bool getMaskAt(const VoxelGridIndex3D& gridIndex, core::MaskVoxel& voxel) const; + + IDType getMaskUID() const + { + return _maskUID; + }; + }; + } +} + +#endif diff --git a/testing/core/DummyMutableDoseAccessor.cpp b/code/testhelper/DummyMutableDoseAccessor.cpp similarity index 95% rename from testing/core/DummyMutableDoseAccessor.cpp rename to code/testhelper/DummyMutableDoseAccessor.cpp index ed82584..ff539f7 100644 --- a/testing/core/DummyMutableDoseAccessor.cpp +++ b/code/testhelper/DummyMutableDoseAccessor.cpp @@ -1,114 +1,114 @@ -// ----------------------------------------------------------------------- -// 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. -// -//------------------------------------------------------------------------ - -#include -#include -#include - -#include "DummyMutableDoseAccessor.h" -#include "rttbNullPointerException.h" -#include "rttbInvalidDoseException.h" -#include "rttbIndexOutOfBoundsException.h" - -namespace rttb -{ - namespace testing - { - - DummyMutableDoseAccessor::~DummyMutableDoseAccessor() {} - - DummyMutableDoseAccessor::DummyMutableDoseAccessor() - { - boost::uuids::uuid id; - boost::uuids::random_generator generator; - id = generator(); - std::stringstream ss; - ss << id; - _doseUID = "DummyMutableDoseAccessor_" + ss.str(); - - SpacingVectorType3D aVector(2.5); - _geoInfo.setSpacing(aVector); - WorldCoordinate3D anOtherVector(-25, -2, 35); - _geoInfo.setImagePositionPatient(anOtherVector); - _geoInfo.setNumRows(11); - _geoInfo.setNumColumns(10); - _geoInfo.setNumSlices(5); - - OrientationMatrix unit = OrientationMatrix(); - _geoInfo.setOrientationMatrix(unit); - - for (int i = 0; i < _geoInfo.getNumberOfVoxels(); i++) - { - doseData.push_back((double(rand()) / RAND_MAX) * 1000); - } - } - - DummyMutableDoseAccessor::DummyMutableDoseAccessor(const std::vector& aDoseVector, - const core::GeometricInfo& geoInfo) - { - boost::uuids::uuid id; - boost::uuids::random_generator generator; - id = generator(); - std::stringstream ss; - ss << id; - _doseUID = "DummyMutableDoseAccessor_" + ss.str(); - - doseData = aDoseVector; - _geoInfo = geoInfo; - } - - const core::GeometricInfo& - DummyMutableDoseAccessor:: - getGeometricInfo() const - { - return _geoInfo; - } - - GenericValueType DummyMutableDoseAccessor::getValueAt(const VoxelGridID aID) const - { - if (!_geoInfo.validID(aID)) - { - throw core::IndexOutOfBoundsException("Not a valid Position!"); - } - - return doseData.at(aID); - } - - GenericValueType DummyMutableDoseAccessor::getValueAt(const VoxelGridIndex3D& aIndex) const - { - VoxelGridID gridID = 0; - _geoInfo.convert(aIndex, gridID); - return getValueAt(gridID); - } - - void DummyMutableDoseAccessor::setDoseAt(const VoxelGridID aID, DoseTypeGy value) - { - if (!_geoInfo.validID(aID)) - { - throw core::IndexOutOfBoundsException("Not a valid Position!"); - } - - doseData.at(aID) = value; - } - - void DummyMutableDoseAccessor::setDoseAt(const VoxelGridIndex3D& aIndex, DoseTypeGy value) - { - VoxelGridID gridID = 0; - _geoInfo.convert(aIndex, gridID); - setDoseAt(gridID, value); - } - - }//end namespace testing +// ----------------------------------------------------------------------- +// 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. +// +//------------------------------------------------------------------------ + +#include +#include +#include + +#include "DummyMutableDoseAccessor.h" +#include "rttbNullPointerException.h" +#include "rttbInvalidDoseException.h" +#include "rttbIndexOutOfBoundsException.h" + +namespace rttb +{ + namespace testing + { + + DummyMutableDoseAccessor::~DummyMutableDoseAccessor() {} + + DummyMutableDoseAccessor::DummyMutableDoseAccessor() + { + boost::uuids::uuid id; + boost::uuids::random_generator generator; + id = generator(); + std::stringstream ss; + ss << id; + _doseUID = "DummyMutableDoseAccessor_" + ss.str(); + + SpacingVectorType3D aVector(2.5); + _geoInfo.setSpacing(aVector); + WorldCoordinate3D anOtherVector(-25, -2, 35); + _geoInfo.setImagePositionPatient(anOtherVector); + _geoInfo.setNumRows(11); + _geoInfo.setNumColumns(10); + _geoInfo.setNumSlices(5); + + OrientationMatrix unit = OrientationMatrix(); + _geoInfo.setOrientationMatrix(unit); + + for (int i = 0; i < _geoInfo.getNumberOfVoxels(); i++) + { + doseData.push_back((double(rand()) / RAND_MAX) * 1000); + } + } + + DummyMutableDoseAccessor::DummyMutableDoseAccessor(const std::vector& aDoseVector, + const core::GeometricInfo& geoInfo) + { + boost::uuids::uuid id; + boost::uuids::random_generator generator; + id = generator(); + std::stringstream ss; + ss << id; + _doseUID = "DummyMutableDoseAccessor_" + ss.str(); + + doseData = aDoseVector; + _geoInfo = geoInfo; + } + + const core::GeometricInfo& + DummyMutableDoseAccessor:: + getGeometricInfo() const + { + return _geoInfo; + } + + GenericValueType DummyMutableDoseAccessor::getValueAt(const VoxelGridID aID) const + { + if (!_geoInfo.validID(aID)) + { + throw core::IndexOutOfBoundsException("Not a valid Position!"); + } + + return doseData.at(aID); + } + + GenericValueType DummyMutableDoseAccessor::getValueAt(const VoxelGridIndex3D& aIndex) const + { + VoxelGridID gridID = 0; + _geoInfo.convert(aIndex, gridID); + return getValueAt(gridID); + } + + void DummyMutableDoseAccessor::setDoseAt(const VoxelGridID aID, DoseTypeGy value) + { + if (!_geoInfo.validID(aID)) + { + throw core::IndexOutOfBoundsException("Not a valid Position!"); + } + + doseData.at(aID) = value; + } + + void DummyMutableDoseAccessor::setDoseAt(const VoxelGridIndex3D& aIndex, DoseTypeGy value) + { + VoxelGridID gridID = 0; + _geoInfo.convert(aIndex, gridID); + setDoseAt(gridID, value); + } + + }//end namespace testing }//end namespace rttb \ No newline at end of file diff --git a/testing/core/DummyMutableDoseAccessor.h b/code/testhelper/DummyMutableDoseAccessor.h similarity index 93% rename from testing/core/DummyMutableDoseAccessor.h rename to code/testhelper/DummyMutableDoseAccessor.h index f7ceca3..f099ee5 100644 --- a/testing/core/DummyMutableDoseAccessor.h +++ b/code/testhelper/DummyMutableDoseAccessor.h @@ -1,82 +1,84 @@ -// ----------------------------------------------------------------------- -// 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. -// -//------------------------------------------------------------------------ - -#ifndef __DUMMY_MUTABLE_DOSE_ACCESSOR_H -#define __DUMMY_MUTABLE_DOSE_ACCESSOR_H - -#include - -#include "rttbMutableDoseAccessorInterface.h" -#include "rttbGeometricInfo.h" -#include "rttbBaseType.h" - -namespace rttb -{ - namespace testing - { - - /*! @class DummyMutableDoseAccessor - @brief A dummy MutableDoseAccessor for testing filled with random dose values between 0 and 100. - The default grid size is [11,10,5] - */ - class DummyMutableDoseAccessor: public core::MutableDoseAccessorInterface - { - - private: - /*! vector of dose data(absolute Gy dose/doseGridScaling)*/ - std::vector doseData; - - IDType _doseUID; - - core::GeometricInfo _geoInfo; - - public: - ~DummyMutableDoseAccessor(); - - /*! @brief A dummy DummyMutableDoseAccessor for testing filled with random dose values between 0 and 100. - The default grid size is [11,10,5] - */ - DummyMutableDoseAccessor(); - - /*! @brief Constructor. - Initialisation of dose with a given vector. - */ - DummyMutableDoseAccessor(const std::vector& aDoseVector, - const core::GeometricInfo& geoInfo); - - const std::vector* getDoseVector() const - { - return &doseData; - }; - - virtual const core::GeometricInfo& getGeometricInfo() const; - - GenericValueType getValueAt(const VoxelGridID aID) const; - - GenericValueType getValueAt(const VoxelGridIndex3D& aIndex) const; - - void setDoseAt(const VoxelGridID aID, DoseTypeGy value); - - void setDoseAt(const VoxelGridIndex3D& aIndex, DoseTypeGy value); - - const IDType getUID() const - { - return _doseUID; - }; - }; - } -} - -#endif +// ----------------------------------------------------------------------- +// 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. +// +//------------------------------------------------------------------------ + +#ifndef __DUMMY_MUTABLE_DOSE_ACCESSOR_H +#define __DUMMY_MUTABLE_DOSE_ACCESSOR_H + +#include + +#include "rttbMutableDoseAccessorInterface.h" +#include "rttbGeometricInfo.h" +#include "rttbBaseType.h" + +#include "RTTBTestHelperExports.h" + +namespace rttb +{ + namespace testing + { + + /*! @class DummyMutableDoseAccessor + @brief A dummy MutableDoseAccessor for testing filled with random dose values between 0 and 100. + The default grid size is [11,10,5] + */ + class RTTBTestHelper_EXPORT DummyMutableDoseAccessor: public core::MutableDoseAccessorInterface + { + + private: + /*! vector of dose data(absolute Gy dose/doseGridScaling)*/ + std::vector doseData; + + IDType _doseUID; + + core::GeometricInfo _geoInfo; + + public: + ~DummyMutableDoseAccessor(); + + /*! @brief A dummy DummyMutableDoseAccessor for testing filled with random dose values between 0 and 100. + The default grid size is [11,10,5] + */ + DummyMutableDoseAccessor(); + + /*! @brief Constructor. + Initialisation of dose with a given vector. + */ + DummyMutableDoseAccessor(const std::vector& aDoseVector, + const core::GeometricInfo& geoInfo); + + const std::vector* getDoseVector() const + { + return &doseData; + }; + + virtual const core::GeometricInfo& getGeometricInfo() const; + + GenericValueType getValueAt(const VoxelGridID aID) const; + + GenericValueType getValueAt(const VoxelGridIndex3D& aIndex) const; + + void setDoseAt(const VoxelGridID aID, DoseTypeGy value); + + void setDoseAt(const VoxelGridIndex3D& aIndex, DoseTypeGy value); + + const IDType getUID() const + { + return _doseUID; + }; + }; + } +} + +#endif diff --git a/testing/core/DummyStructure.cpp b/code/testhelper/DummyStructure.cpp similarity index 97% rename from testing/core/DummyStructure.cpp rename to code/testhelper/DummyStructure.cpp index 3345ff0..bf018a9 100644 --- a/testing/core/DummyStructure.cpp +++ b/code/testhelper/DummyStructure.cpp @@ -1,742 +1,742 @@ -// ----------------------------------------------------------------------- -// 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. -// -//------------------------------------------------------------------------ - -#include - -#include "DummyStructure.h" -#include "rttbNullPointerException.h" -#include "rttbInvalidParameterException.h" -#include "rttbInvalidDoseException.h" - -namespace rttb -{ - namespace testing - { - - DummyStructure::~DummyStructure() {} - - DummyStructure::DummyStructure(const core::GeometricInfo& aGeoInfo) - { - _geoInfo = aGeoInfo; - } - - 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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure_rectangular_centered = core::Structure(another_polySeq); - - return test_structure_rectangular_centered; - } - - core::Structure DummyStructure::CreateRectangularStructureCenteredContourPlaneThicknessNotEqualDosePlaneThickness(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); - - 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); - - PolygonType another_polygon2 = another_cts.createPolygonCenterOnPlaneCenter(another_voxelVector, zPlane); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - another_polySeq.push_back(another_polygon2); - - core::Structure test_structure_rectangular_centered = core::Structure(another_polySeq); - - return test_structure_rectangular_centered; - } - - core::Structure DummyStructure::CreateRectangularStructureCentered(GridIndexType fromZPlane, GridIndexType toZPlane) - { - 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); - PolygonSequenceType another_polySeq; - - for (unsigned int i = fromZPlane; i <= toZPlane; ++i){ - another_voxelVector.clear(); - 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, i); - - another_polySeq.push_back(another_polygon1); - } - - core::Structure test_structure_rectangular_centered = core::Structure(another_polySeq); - - return test_structure_rectangular_centered; - } - - core::Structure DummyStructure::CreateRectangularStructureCentered(GridIndexType fromZPlane, GridIndexType toZPlane, GridIndexType fromZPlane2, GridIndexType toZPlane2) - { - 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); - PolygonSequenceType another_polySeq; - - for (unsigned int i = fromZPlane; i <= toZPlane; ++i){ - another_voxelVector.clear(); - 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, i); - - another_polySeq.push_back(another_polygon1); - } - - for (unsigned int i = fromZPlane2; i <= toZPlane2; ++i){ - another_voxelVector.clear(); - 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, i); - - another_polySeq.push_back(another_polygon1); - } - - core::Structure test_structure_rectangular_centered = core::Structure(another_polySeq); - - return test_structure_rectangular_centered; - } - - 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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - core::Structure - DummyStructure::CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRight() - { - 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); - - another_voxelVector.push_back(another_i1); - another_voxelVector.push_back(another_i2); - another_voxelVector.push_back(another_i3); - another_voxelVector.push_back(another_i4); - - PolygonSequenceType another_polySeq; - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - 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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - 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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - core::Structure DummyStructure::CreateTestStructureSeveralSeperateSectionsInsideOneVoxel( - GridIndexType zPlane) - { - CreateTestStructure another_cts = CreateTestStructure(_geoInfo); - - std::vector another_voxelVector; - - VoxelGridIndex2D another_i1(2, 2); - - another_voxelVector.push_back(another_i1); - - PolygonType another_polygon1 = another_cts.createStructureSeveralSectionsInsideOneVoxelA( - another_voxelVector , zPlane); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - core::Structure DummyStructure::CreateTestStructureSelfTouchingA(GridIndexType zPlane) - { - CreateTestStructure another_cts = CreateTestStructure(_geoInfo); - - std::vector another_voxelVector; - - VoxelGridIndex2D another_i1(2, 2); - - another_voxelVector.push_back(another_i1); - - PolygonType another_polygon1 = another_cts.createStructureSelfTouchingA(another_voxelVector , - zPlane); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - 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); - - 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); - - 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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - another_polySeq.push_back(another_polygon2); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - 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); - - 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); - - 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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - another_polySeq.push_back(another_polygon2); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - 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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - 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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - 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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - 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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - 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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - 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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - core::Structure DummyStructure::CreateTestStructureCircle(GridIndexType zPlane) - { - CreateTestStructure another_cts = CreateTestStructure(_geoInfo); - - std::vector another_voxelVector; - - VoxelGridIndex2D another_i1(4, 4); - - another_voxelVector.push_back(another_i1); - - PolygonType another_polygon1 = another_cts.createPolygonCircle(another_voxelVector , zPlane); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - 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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - 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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - 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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - 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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - void DummyStructure::ShowTestStructure(core::Structure aStructure) - { - WorldCoordinate3D aPoint(0); - - PolygonSequenceType strVector = aStructure.getStructureVector(); - - for (size_t struct_index = 0 ; struct_index < strVector.size() ; struct_index++) - { - - for (size_t point_index = 0 ; point_index < strVector.at(struct_index).size() ; point_index++) - { - - aPoint = strVector.at(struct_index).at(point_index); - - std::cout << " aPoint.x " << aPoint.x() << std::endl; - std::cout << " aPoint.y " << aPoint.y() << std::endl; - std::cout << " aPoint.z " << aPoint.z() << std::endl; - } - - } - } - - core::Structure DummyStructure::CreateRectangularStructureUpperLeftRotated(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); - - 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); - - PolygonSequenceType another_polySeq; - another_polySeq.push_back(another_polygon1); - - core::Structure test_structure = core::Structure(another_polySeq); - - return test_structure; - } - - }//testing -}//rttb - +// ----------------------------------------------------------------------- +// 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. +// +//------------------------------------------------------------------------ + +#include + +#include "DummyStructure.h" +#include "rttbNullPointerException.h" +#include "rttbInvalidParameterException.h" +#include "rttbInvalidDoseException.h" + +namespace rttb +{ + namespace testing + { + + DummyStructure::~DummyStructure() {} + + DummyStructure::DummyStructure(const core::GeometricInfo& aGeoInfo) + { + _geoInfo = aGeoInfo; + } + + 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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure_rectangular_centered = core::Structure(another_polySeq); + + return test_structure_rectangular_centered; + } + + core::Structure DummyStructure::CreateRectangularStructureCenteredContourPlaneThicknessNotEqualDosePlaneThickness(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); + + 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); + + PolygonType another_polygon2 = another_cts.createPolygonCenterOnPlaneCenter(another_voxelVector, zPlane); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + another_polySeq.push_back(another_polygon2); + + core::Structure test_structure_rectangular_centered = core::Structure(another_polySeq); + + return test_structure_rectangular_centered; + } + + core::Structure DummyStructure::CreateRectangularStructureCentered(GridIndexType fromZPlane, GridIndexType toZPlane) + { + 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); + PolygonSequenceType another_polySeq; + + for (unsigned int i = fromZPlane; i <= toZPlane; ++i){ + another_voxelVector.clear(); + 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, i); + + another_polySeq.push_back(another_polygon1); + } + + core::Structure test_structure_rectangular_centered = core::Structure(another_polySeq); + + return test_structure_rectangular_centered; + } + + core::Structure DummyStructure::CreateRectangularStructureCentered(GridIndexType fromZPlane, GridIndexType toZPlane, GridIndexType fromZPlane2, GridIndexType toZPlane2) + { + 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); + PolygonSequenceType another_polySeq; + + for (unsigned int i = fromZPlane; i <= toZPlane; ++i){ + another_voxelVector.clear(); + 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, i); + + another_polySeq.push_back(another_polygon1); + } + + for (unsigned int i = fromZPlane2; i <= toZPlane2; ++i){ + another_voxelVector.clear(); + 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, i); + + another_polySeq.push_back(another_polygon1); + } + + core::Structure test_structure_rectangular_centered = core::Structure(another_polySeq); + + return test_structure_rectangular_centered; + } + + 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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + core::Structure + DummyStructure::CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRight() + { + 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); + + another_voxelVector.push_back(another_i1); + another_voxelVector.push_back(another_i2); + another_voxelVector.push_back(another_i3); + another_voxelVector.push_back(another_i4); + + PolygonSequenceType another_polySeq; + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + 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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + 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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + core::Structure DummyStructure::CreateTestStructureSeveralSeperateSectionsInsideOneVoxel( + GridIndexType zPlane) + { + CreateTestStructure another_cts = CreateTestStructure(_geoInfo); + + std::vector another_voxelVector; + + VoxelGridIndex2D another_i1(2, 2); + + another_voxelVector.push_back(another_i1); + + PolygonType another_polygon1 = another_cts.createStructureSeveralSectionsInsideOneVoxelA( + another_voxelVector , zPlane); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + core::Structure DummyStructure::CreateTestStructureSelfTouchingA(GridIndexType zPlane) + { + CreateTestStructure another_cts = CreateTestStructure(_geoInfo); + + std::vector another_voxelVector; + + VoxelGridIndex2D another_i1(2, 2); + + another_voxelVector.push_back(another_i1); + + PolygonType another_polygon1 = another_cts.createStructureSelfTouchingA(another_voxelVector , + zPlane); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + 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); + + 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); + + 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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + another_polySeq.push_back(another_polygon2); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + 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); + + 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); + + 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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + another_polySeq.push_back(another_polygon2); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + 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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + 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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + 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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + 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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + 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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + 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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + core::Structure DummyStructure::CreateTestStructureCircle(GridIndexType zPlane) + { + CreateTestStructure another_cts = CreateTestStructure(_geoInfo); + + std::vector another_voxelVector; + + VoxelGridIndex2D another_i1(4, 4); + + another_voxelVector.push_back(another_i1); + + PolygonType another_polygon1 = another_cts.createPolygonCircle(another_voxelVector , zPlane); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + 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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + 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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + 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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + 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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + void DummyStructure::ShowTestStructure(core::Structure aStructure) + { + WorldCoordinate3D aPoint(0); + + PolygonSequenceType strVector = aStructure.getStructureVector(); + + for (size_t struct_index = 0 ; struct_index < strVector.size() ; struct_index++) + { + + for (size_t point_index = 0 ; point_index < strVector.at(struct_index).size() ; point_index++) + { + + aPoint = strVector.at(struct_index).at(point_index); + + std::cout << " aPoint.x " << aPoint.x() << std::endl; + std::cout << " aPoint.y " << aPoint.y() << std::endl; + std::cout << " aPoint.z " << aPoint.z() << std::endl; + } + + } + } + + core::Structure DummyStructure::CreateRectangularStructureUpperLeftRotated(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); + + 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); + + PolygonSequenceType another_polySeq; + another_polySeq.push_back(another_polygon1); + + core::Structure test_structure = core::Structure(another_polySeq); + + return test_structure; + } + + }//testing +}//rttb + diff --git a/testing/core/DummyStructure.h b/code/testhelper/DummyStructure.h similarity index 97% rename from testing/core/DummyStructure.h rename to code/testhelper/DummyStructure.h index 052283f..5e80f14 100644 --- a/testing/core/DummyStructure.h +++ b/code/testhelper/DummyStructure.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. -// -//------------------------------------------------------------------------ - -// this file defines the rttbCoreTests for the test driver -// and all it expects is that you have a function called RegisterTests - -#include "rttbStructure.h" -#include "CreateTestStructure.h" -#include "rttbBaseType.h" -#include "rttbGeometricInfo.h" - -namespace rttb -{ - namespace testing - { - - /*! @class DummyStructure - @brief generate simple geometric testing structures. - The maximal x coordinate used is 9 and the maximal y coordinate is 8. - Make sure the geometricInfo corresponds to a sufficiently large data grid. - @see CreateTestStructures - */ - class DummyStructure - { - - private: - core::GeometricInfo _geoInfo; - - public: - ~DummyStructure(); - - DummyStructure(const core::GeometricInfo& aGeoInfo); - - const core::GeometricInfo& getGeometricInfo() - { - return _geoInfo; - }; - - core::Structure CreateRectangularStructureCentered(GridIndexType zPlane); - - /* Generate rectangular structure for the z slice and another slice between z and z+1. So the structure has a smaller z spacing than the dose - */ - core::Structure CreateRectangularStructureCenteredContourPlaneThicknessNotEqualDosePlaneThickness(GridIndexType zPlane); - - /* Generate rectangular structure for the z slices from fromZPlane(included) to toZPlane(included) - */ - core::Structure CreateRectangularStructureCentered(GridIndexType fromZPlane, GridIndexType toZPlane); - - /* Generate rectangular structure for the z slices from fromZPlane(included) to toZPlane(included) and from fromZPlane2(included) to toZPlane2(included) - */ - core::Structure CreateRectangularStructureCentered(GridIndexType fromZPlane, GridIndexType toZPlane, GridIndexType fromZPlane2, GridIndexType toZPlane2); - - core::Structure CreateTestStructureCircle(GridIndexType zPlane); - - core::Structure CreateRectangularStructureUpperLeftRotated(GridIndexType zPlane); - - core::Structure CreateTestStructureSeveralSeperateSectionsInsideOneVoxel(GridIndexType zPlane); - - core::Structure CreateRectangularStructureCenteredRotatedIntermediatePlacement( - GridIndexType zPlane); - core::Structure CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRight(); - core::Structure - CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRightCounterClock( - GridIndexType zPlane); - core::Structure - CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRightCounterClockIntermediatePoints( - GridIndexType zPlane); - - core::Structure CreateTestStructureSelfTouchingA(GridIndexType zPlane); - - core::Structure CreateTestStructureIntersecting(GridIndexType zPlane); - core::Structure CreateTestStructureIntersectingTwoPolygons(GridIndexType zPlane); - core::Structure CreateTestStructureIntersectingTwoPolygonsInDifferentSlices(GridIndexType zPlane1, - GridIndexType zPlane2); - - core::Structure CreateTestStructureInsideInsideTouches(GridIndexType zPlane); - core::Structure CreateTestStructureInsideInsideTouchesRotatedQuaterPi(GridIndexType zPlane); - core::Structure CreateTestStructureInsideInsideTouchesCounterClockRotatedQuaterPi( - GridIndexType zPlane); - core::Structure CreateTestStructureInsideInsideTouchesCounterClockRotatedOnePointFivePi( - GridIndexType zPlane); - core::Structure CreateTestStructureInsideInsideTouchesRotatedPointDoubeled(GridIndexType zPlane); - - core::Structure CreateTestStructureInsideInsideTouchesUpperLeft(GridIndexType zPlane); - core::Structure CreateTestStructureInsideInsideTouchesLowerLeft(GridIndexType zPlane); - core::Structure CreateTestStructureInsideInsideTouchesLowerRight(GridIndexType zPlane); - core::Structure CreateTestStructureInsideInsideTouchesUpperRight(GridIndexType zPlane); - - void ShowTestStructure(core::Structure aStructure); - }; - }//testing -}//rttb - +// ----------------------------------------------------------------------- +// 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. +// +//------------------------------------------------------------------------ + +// this file defines the rttbCoreTests for the test driver +// and all it expects is that you have a function called RegisterTests + +#include "rttbStructure.h" +#include "CreateTestStructure.h" +#include "rttbBaseType.h" +#include "rttbGeometricInfo.h" + +#include "RTTBTestHelperExports.h" + +namespace rttb +{ + namespace testing + { + + /*! @class DummyStructure + @brief generate simple geometric testing structures. + The maximal x coordinate used is 9 and the maximal y coordinate is 8. + Make sure the geometricInfo corresponds to a sufficiently large data grid. + @see CreateTestStructures + */ + class RTTBTestHelper_EXPORT DummyStructure + { + + private: + core::GeometricInfo _geoInfo; + + public: + ~DummyStructure(); + + DummyStructure(const core::GeometricInfo& aGeoInfo); + + const core::GeometricInfo& getGeometricInfo() + { + return _geoInfo; + }; + + core::Structure CreateRectangularStructureCentered(GridIndexType zPlane); + + /* Generate rectangular structure for the z slice and another slice between z and z+1. So the structure has a smaller z spacing than the dose + */ + core::Structure CreateRectangularStructureCenteredContourPlaneThicknessNotEqualDosePlaneThickness(GridIndexType zPlane); + + /* Generate rectangular structure for the z slices from fromZPlane(included) to toZPlane(included) + */ + core::Structure CreateRectangularStructureCentered(GridIndexType fromZPlane, GridIndexType toZPlane); + + /* Generate rectangular structure for the z slices from fromZPlane(included) to toZPlane(included) and from fromZPlane2(included) to toZPlane2(included) + */ + core::Structure CreateRectangularStructureCentered(GridIndexType fromZPlane, GridIndexType toZPlane, GridIndexType fromZPlane2, GridIndexType toZPlane2); + + core::Structure CreateTestStructureCircle(GridIndexType zPlane); + + core::Structure CreateRectangularStructureUpperLeftRotated(GridIndexType zPlane); + + core::Structure CreateTestStructureSeveralSeperateSectionsInsideOneVoxel(GridIndexType zPlane); + + core::Structure CreateRectangularStructureCenteredRotatedIntermediatePlacement( + GridIndexType zPlane); + core::Structure CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRight(); + core::Structure + CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRightCounterClock( + GridIndexType zPlane); + core::Structure + CreateRectangularStructureCenteredRotatedIntermediatePlacementLowerRightCounterClockIntermediatePoints( + GridIndexType zPlane); + + core::Structure CreateTestStructureSelfTouchingA(GridIndexType zPlane); + + core::Structure CreateTestStructureIntersecting(GridIndexType zPlane); + core::Structure CreateTestStructureIntersectingTwoPolygons(GridIndexType zPlane); + core::Structure CreateTestStructureIntersectingTwoPolygonsInDifferentSlices(GridIndexType zPlane1, + GridIndexType zPlane2); + + core::Structure CreateTestStructureInsideInsideTouches(GridIndexType zPlane); + core::Structure CreateTestStructureInsideInsideTouchesRotatedQuaterPi(GridIndexType zPlane); + core::Structure CreateTestStructureInsideInsideTouchesCounterClockRotatedQuaterPi( + GridIndexType zPlane); + core::Structure CreateTestStructureInsideInsideTouchesCounterClockRotatedOnePointFivePi( + GridIndexType zPlane); + core::Structure CreateTestStructureInsideInsideTouchesRotatedPointDoubeled(GridIndexType zPlane); + + core::Structure CreateTestStructureInsideInsideTouchesUpperLeft(GridIndexType zPlane); + core::Structure CreateTestStructureInsideInsideTouchesLowerLeft(GridIndexType zPlane); + core::Structure CreateTestStructureInsideInsideTouchesLowerRight(GridIndexType zPlane); + core::Structure CreateTestStructureInsideInsideTouchesUpperRight(GridIndexType zPlane); + + void ShowTestStructure(core::Structure aStructure); + }; + }//testing +}//rttb + diff --git a/testing/core/files.cmake b/code/testhelper/files.cmake similarity index 51% copy from testing/core/files.cmake copy to code/testhelper/files.cmake index 612a4d6..e3943bf 100644 --- a/testing/core/files.cmake +++ b/code/testhelper/files.cmake @@ -1,31 +1,19 @@ -SET(CPP_FILES - rttbCoreTests.cpp - DummyDoseAccessor.cpp - DummyInhomogeneousDoseAccessor.cpp - DummyMaskAccessor.cpp - DummyMutableDoseAccessor.cpp - DummyDVHGenerator.cpp - DummyStructure.cpp - CreateTestStructure.cpp - StructureTest.cpp - GeometricInfoTest.cpp - MaskVoxelTest.cpp - GenericDoseIteratorTest.cpp - GenericMaskedDoseIteratorTest.cpp - DVHCalculatorTest.cpp - DVHTest.cpp - DVHSetTest.cpp - StrVectorStructureSetGeneratorTest.cpp - StructureSetTest.cpp - BaseTypeTest.cpp - ) - -SET(H_FILES - DummyStructure.h - CreateTestStructure.h - DummyDoseAccessor.h - DummyInhomogeneousDoseAccessor.h - DummyMaskAccessor.h - DummyMutableDoseAccessor.h - DummyDVHGenerator.h -) +SET(CPP_FILES + DummyDoseAccessor.cpp + DummyInhomogeneousDoseAccessor.cpp + DummyMaskAccessor.cpp + DummyMutableDoseAccessor.cpp + DummyDVHGenerator.cpp + DummyStructure.cpp + CreateTestStructure.cpp + ) + +SET(H_FILES + DummyStructure.h + DummyDoseAccessor.h + DummyInhomogeneousDoseAccessor.h + DummyMaskAccessor.h + DummyMutableDoseAccessor.h + DummyDVHGenerator.h + CreateTestStructure.h +) diff --git a/testing/algorithms/ArithmeticTest.cpp b/testing/algorithms/ArithmeticTest.cpp index bad153d..9f3615e 100644 --- a/testing/algorithms/ArithmeticTest.cpp +++ b/testing/algorithms/ArithmeticTest.cpp @@ -1,352 +1,352 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include #include #include "litCheckMacros.h" #include "rttbBaseType.h" -#include "../core/DummyDoseAccessor.h" -#include "../core/DummyMaskAccessor.h" -#include "../core/DummyMutableDoseAccessor.h" +#include "DummyDoseAccessor.h" +#include "DummyMaskAccessor.h" +#include "DummyMutableDoseAccessor.h" #include "rttbDoseAccessorInterface.h" #include "rttbMutableDoseAccessorInterface.h" #include "rttbMutableMaskAccessorInterface.h" #include "rttbArithmetic.h" #include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" #include "rttbGenericMutableMaskAccessor.h" #include "rttbMaskAccessorInterface.h" namespace rttb { namespace testing { typedef core::DoseAccessorInterface::Pointer DoseAccessorPointer; typedef core::MutableDoseAccessorInterface::Pointer MutableDoseAccessorPointer; typedef DummyMaskAccessor::MaskVoxelListPointer MaskVoxelListPointer; typedef DummyMaskAccessor::MaskVoxelList MaskVoxelList; typedef core::MaskAccessorInterface::Pointer MaskAccessorPointer; typedef core::MutableMaskAccessorInterface::Pointer MutableMaskAccessorPointer; /*! @brief ArithmeticTest - tests arithmetic combinations of accessors 1) test dose-dose operations 2) test dose-mask operations 3) test mask-mask operations 4) test convenience functions */ int ArithmeticTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; // initialize accessors for arithmetic //DOSE: //Null pointers DoseAccessorPointer spDoseNull; MutableDoseAccessorPointer spMutableDoseNull; //dose with random values between 0 and 100 boost::shared_ptr spTestDoseAccessor1 = boost::make_shared(); DoseAccessorPointer spDoseAccessor1(spTestDoseAccessor1); //generate a 2nd dose with fixed values core::GeometricInfo geoInfo = spDoseAccessor1->getGeometricInfo(); DoseTypeGy valFix = 101; // to ensure values are larger than 100 on adding std::vector dose2Vals(geoInfo.getNumberOfVoxels(), valFix); boost::shared_ptr spTestDoseAccessor2 = boost::make_shared (dose2Vals, geoInfo); DoseAccessorPointer spDoseAccessor2(spTestDoseAccessor2); //generate result acessor std::vector doseResultVals(geoInfo.getNumberOfVoxels(), -1); boost::shared_ptr spTestMutableDoseAccessor = boost::make_shared(doseResultVals, geoInfo); MutableDoseAccessorPointer spMutableDoseAccessor(spTestMutableDoseAccessor); // different geometricInfo core::GeometricInfo geoInfo2 = geoInfo; geoInfo2.setNumColumns(5); geoInfo2.setNumRows(5); geoInfo2.setNumSlices(5); std::vector dose3Vals(geoInfo2.getNumberOfVoxels(), valFix); boost::shared_ptr spTestDoseAccessor3 = boost::make_shared (dose3Vals, geoInfo2); DoseAccessorPointer spDoseAccessorDiffGeoInfo(spTestDoseAccessor3); boost::shared_ptr spTestMutableDoseAccessor2 = boost::make_shared(dose3Vals, geoInfo2); MutableDoseAccessorPointer spMutableDoseAccessorDiffGeoInfo(spTestMutableDoseAccessor2); //MASK: //null pointer MaskAccessorPointer spMaskAccessorNull; MutableMaskAccessorPointer spMutableMaskAccessorNull; MaskVoxelList voxelList; FractionType aVolumeFraction = 1; VoxelGridID aVoxelGridID = 10; //generate a dummy mask while (aVoxelGridID < geoInfo.getNumberOfVoxels() && aVoxelGridID <= 30) { voxelList.push_back(core::MaskVoxel(aVoxelGridID, aVolumeFraction)); ++aVoxelGridID; } MaskVoxelListPointer voxelListPtr = boost::make_shared(voxelList); boost::shared_ptr dummyMask1 = boost::make_shared(geoInfo, voxelListPtr); MaskAccessorPointer spMaskAccessor1(dummyMask1); MaskVoxelList voxelList2; aVoxelGridID = 20; //generate a 2nd dummy mask that partly overlaps with the 1st one while (aVoxelGridID < geoInfo.getNumberOfVoxels() && aVoxelGridID <= 40) { voxelList2.push_back(core::MaskVoxel(aVoxelGridID, aVolumeFraction)); ++aVoxelGridID; } MaskVoxelListPointer voxelListPtr2 = boost::make_shared(voxelList2); boost::shared_ptr dummyMask2 = boost::make_shared(geoInfo, voxelListPtr2); MaskAccessorPointer spMaskAccessor2(dummyMask2); // result accessor boost::shared_ptr mMask1 = boost::make_shared(geoInfo); MutableMaskAccessorPointer spMutableMask(mMask1); // different geometricInfo boost::shared_ptr spDummyMaskDiffGeoInfo = boost::make_shared (geoInfo2, voxelListPtr2); MaskAccessorPointer spMaskAccessorDiffGeoInfo(spDummyMaskDiffGeoInfo); boost::shared_ptr mMask2 = boost::make_shared(geoInfo2); MutableMaskAccessorPointer spMutableMaskDiffGeoInfo(mMask2); // 1) test dose-dose operations //ADD algorithms::arithmetic::doseOp::Add addOP; CHECK_NO_THROW(algorithms::arithmetic::arithmetic(spDoseAccessor1, spDoseAccessor2, spMutableDoseAccessor, addOP)); VoxelGridID id = 5; CHECK(spMutableDoseAccessor->getValueAt(id) > 100); CHECK_EQUAL(spDoseAccessor1->getValueAt(id) + valFix, spMutableDoseAccessor->getValueAt(id)); id = 10; CHECK(spMutableDoseAccessor->getValueAt(id) > 100); CHECK_EQUAL(spDoseAccessor1->getValueAt(id) + valFix, spMutableDoseAccessor->getValueAt(id)); //handling exceptions is tested once for dose-dose operations, because this does not change if the operation changes. //handling null pointers CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessor1, spDoseNull, spMutableDoseAccessor, addOP), core::NullPointerException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseNull, spDoseAccessor2, spMutableDoseAccessor, addOP), core::NullPointerException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessor1, spDoseAccessor2, spMutableDoseNull, addOP), core::NullPointerException); //handle different geometricInfos CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessor1, spDoseAccessorDiffGeoInfo, spMutableDoseAccessor, addOP), core::InvalidParameterException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessorDiffGeoInfo, spDoseAccessor2, spMutableDoseAccessor, addOP), core::InvalidParameterException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessor1, spDoseAccessor2, spMutableDoseAccessorDiffGeoInfo, addOP), core::InvalidParameterException); //ADD_WEIGHTED algorithms::arithmetic::doseOp::AddWeighted addWOP(1, 2); CHECK_NO_THROW(algorithms::arithmetic::arithmetic(spDoseAccessor1, spDoseAccessor2, spMutableDoseAccessor, addWOP)); id = 5; CHECK(spMutableDoseAccessor->getValueAt(id) > 201); CHECK_EQUAL(spDoseAccessor1->getValueAt(id) + 2 * valFix, spMutableDoseAccessor->getValueAt(id)); id = 10; CHECK(spMutableDoseAccessor->getValueAt(id) > 201); CHECK_EQUAL(spDoseAccessor1->getValueAt(id) + 2 * valFix, spMutableDoseAccessor->getValueAt(id)); //MULTIPLY algorithms::arithmetic::doseOp::Multiply multiplyOP; CHECK_NO_THROW(algorithms::arithmetic::arithmetic(spDoseAccessor1, spDoseAccessor2, spMutableDoseAccessor, multiplyOP)); id = 5; CHECK(spMutableDoseAccessor->getValueAt(id) > 201); CHECK_EQUAL(spDoseAccessor1->getValueAt(id) * valFix, spMutableDoseAccessor->getValueAt(id)); id = 10; CHECK(spMutableDoseAccessor->getValueAt(id) > 201); CHECK_EQUAL(spDoseAccessor1->getValueAt(id) * valFix, spMutableDoseAccessor->getValueAt(id)); // 2) test dose-mask operations //MULTIPLY algorithms::arithmetic::doseMaskOp::Multiply multOP; CHECK_NO_THROW(algorithms::arithmetic::arithmetic(spDoseAccessor2, spMaskAccessor1, spMutableDoseAccessor, multOP)); core::MaskVoxel mVoxel(0); id = 5; CHECK_EQUAL(0, spMutableDoseAccessor->getValueAt(id)); spMaskAccessor1->getMaskAt(id, mVoxel); CHECK_EQUAL(spMutableDoseAccessor->getValueAt(id), mVoxel.getRelevantVolumeFraction()); id = 15; CHECK_EQUAL(valFix, spMutableDoseAccessor->getValueAt(id)); id = 35; CHECK_EQUAL(0, spMutableDoseAccessor->getValueAt(id)); //handling exceptions is tested once for dose-dose operations, because this does not change if the operation changes. //handling null pointers CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessor1, spMaskAccessorNull, spMutableDoseAccessor, multOP), core::NullPointerException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseNull, spDoseAccessor2, spMutableDoseAccessor, multOP), core::NullPointerException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessor2, spMaskAccessor1, spMutableDoseNull, multOP), core::NullPointerException); //handle different geometricInfos CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessor2, spMaskAccessorDiffGeoInfo, spMutableDoseAccessor, multOP), core::InvalidParameterException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessorDiffGeoInfo, spMaskAccessor1, spMutableDoseAccessor, multOP), core::InvalidParameterException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spDoseAccessor2, spMaskAccessor1, spMutableDoseAccessorDiffGeoInfo, multOP), core::InvalidParameterException); // 3) test mask-mask operations //ADD algorithms::arithmetic::maskOp::Add maskAddOP; CHECK_NO_THROW(algorithms::arithmetic::arithmetic(spMaskAccessor1, spMaskAccessor2, spMutableMask, maskAddOP)); id = 5; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); id = 15; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(1, mVoxel.getRelevantVolumeFraction()); id = 35; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(1, mVoxel.getRelevantVolumeFraction()); id = 45; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); //handling exceptions is tested once for dose-dose operations, because this does not change if the operation changes. //handling null pointers CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spMaskAccessor1, spMaskAccessorNull, spMutableMask, maskAddOP), core::NullPointerException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spMaskAccessorNull, spMaskAccessor2, spMutableMask, maskAddOP), core::NullPointerException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spMaskAccessor1, spMaskAccessor1, spMutableMaskAccessorNull, maskAddOP), core::NullPointerException); //handle different geometricInfos CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spMaskAccessor1, spMaskAccessorDiffGeoInfo, spMutableMask, maskAddOP), core::InvalidParameterException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spMaskAccessorDiffGeoInfo, spMaskAccessor2, spMutableMask, maskAddOP), core::InvalidParameterException); CHECK_THROW_EXPLICIT(algorithms::arithmetic::arithmetic(spMaskAccessor1, spMaskAccessor1, spMutableMaskDiffGeoInfo, maskAddOP), core::InvalidParameterException); //SUBTRACT algorithms::arithmetic::maskOp::Subtract maskSubOP; CHECK_NO_THROW(algorithms::arithmetic::arithmetic(spMaskAccessor1, spMaskAccessor2, spMutableMask, maskSubOP)); id = 5; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); id = 15; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(1, mVoxel.getRelevantVolumeFraction()); id = 35; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); id = 45; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); // 4) test convenience functions // tests are similar to explicit calls CHECK_NO_THROW(algorithms::arithmetic::add(spDoseAccessor1, spDoseAccessor2, spMutableDoseAccessor)); id = 5; CHECK(spMutableDoseAccessor->getValueAt(id) > 100); CHECK_EQUAL(spDoseAccessor1->getValueAt(id) + valFix, spMutableDoseAccessor->getValueAt(id)); id = 10; CHECK(spMutableDoseAccessor->getValueAt(id) > 100); CHECK_EQUAL(spDoseAccessor1->getValueAt(id) + valFix, spMutableDoseAccessor->getValueAt(id)); CHECK_NO_THROW(algorithms::arithmetic::add(spMaskAccessor1, spMaskAccessor2, spMutableMask)); id = 5; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); id = 15; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(1, mVoxel.getRelevantVolumeFraction()); id = 35; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(1, mVoxel.getRelevantVolumeFraction()); id = 45; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); CHECK_NO_THROW(algorithms::arithmetic::subtract(spMaskAccessor1, spMaskAccessor2, spMutableMask)); id = 5; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); id = 15; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(1, mVoxel.getRelevantVolumeFraction()); id = 35; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); id = 45; spMutableMask->getMaskAt(id, mVoxel); CHECK_EQUAL(0, mVoxel.getRelevantVolumeFraction()); CHECK_NO_THROW(algorithms::arithmetic::multiply(spDoseAccessor2, spMaskAccessor1, spMutableDoseAccessor)); id = 5; CHECK_EQUAL(0, spMutableDoseAccessor->getValueAt(id)); spMaskAccessor1->getMaskAt(id, mVoxel); CHECK_EQUAL(spMutableDoseAccessor->getValueAt(id), mVoxel.getRelevantVolumeFraction()); id = 15; CHECK_EQUAL(valFix, spMutableDoseAccessor->getValueAt(id)); id = 35; CHECK_EQUAL(0, spMutableDoseAccessor->getValueAt(id)); RETURN_AND_REPORT_TEST_SUCCESS; } } } \ No newline at end of file diff --git a/testing/algorithms/CMakeLists.txt b/testing/algorithms/CMakeLists.txt index 3ab837c..e15bc43 100644 --- a/testing/algorithms/CMakeLists.txt +++ b/testing/algorithms/CMakeLists.txt @@ -1,20 +1,20 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(ALGORITHMS_TESTS ${EXECUTABLE_OUTPUT_PATH}/${RTToolbox_PREFIX}AlgorithmsTests) SET(ALGORITHMS_HEADER_TEST ${EXECUTABLE_OUTPUT_PATH}/${RTToolbox_PREFIX}AlgorithmsHeaderTest) SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) #----------------------------------------------------------------------------- ADD_TEST(DoseStatisticsTest ${ALGORITHMS_TESTS} DoseStatisticsTest) ADD_TEST(ArithmeticTest ${ALGORITHMS_TESTS} ArithmeticTest) ADD_TEST(DoseStatisticsCalculatorTest ${ALGORITHMS_TESTS} DoseStatisticsCalculatorTest "${TEST_DATA_ROOT}/DoseStatistics/XML/dicom_heartComplex.xml" "${TEST_DATA_ROOT}/Dose/DICOM/dicompylerTestDose.dcm" "${TEST_DATA_ROOT}/StructureSet/DICOM/rtss.dcm") ADD_TEST(BinaryFunctorAccessorTest ${ALGORITHMS_TESTS} BinaryFunctorAccessorTest "${TEST_DATA_ROOT}/Dose/DICOM/ConstantTwo.dcm" "${TEST_DATA_ROOT}/Dose/DICOM/dicompylerTestDose.dcm") -RTTB_CREATE_TEST_MODULE(Algorithms DEPENDS RTTBAlgorithms RTTBMask RTTBDicomIO PACKAGE_DEPENDS Boost Litmus RTTBData DCMTK) +RTTB_CREATE_TEST_MODULE(Algorithms DEPENDS RTTBAlgorithms RTTBTestHelper RTTBMask RTTBDicomIO PACKAGE_DEPENDS Boost Litmus RTTBData DCMTK) diff --git a/testing/algorithms/DoseStatisticsCalculatorTest.cpp b/testing/algorithms/DoseStatisticsCalculatorTest.cpp index 682a124..0758bbb 100644 --- a/testing/algorithms/DoseStatisticsCalculatorTest.cpp +++ b/testing/algorithms/DoseStatisticsCalculatorTest.cpp @@ -1,385 +1,385 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include #include #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbGenericDoseIterator.h" #include "rttbDoseIteratorInterface.h" #include "rttbNullPointerException.h" #include "rttbDoseStatisticsCalculator.h" #include "rttbInvalidDoseException.h" #include "rttbInvalidParameterException.h" #include "rttbDataNotAvailableException.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomFileStructureSetGenerator.h" #include "rttbBoostMaskAccessor.h" #include "rttbGenericMaskedDoseIterator.h" #include "../io/other/CompareDoseStatistic.h" #include "../../code/io/other/rttbDoseStatisticsXMLReader.h" -#include "../core/DummyDoseAccessor.h" +#include "DummyDoseAccessor.h" namespace rttb { namespace testing { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef core::DoseIteratorInterface::Pointer DoseIteratorPointer; typedef rttb::algorithms::DoseStatistics::ResultListPointer ResultListPointer; typedef rttb::algorithms::DoseStatistics::Pointer DoseStatisticsPointer; /*! @brief DoseStatisticsCalculatorTest - test the API of DoseStatisticsCalculator 1) test constructors 2) test setDoseIterator 3) test calculateDoseSatistics 4) get statistical values */ int DoseStatisticsCalculatorTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string referenceXMLFilename; std::string doseFilename, structFilename; boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DoseAccessorPointer spDoseAccessor(spTestDoseAccessor); const std::vector* doseVals = spTestDoseAccessor->getDoseVector(); boost::shared_ptr spTestDoseIterator = boost::make_shared(spDoseAccessor); DoseIteratorPointer spDoseIterator(spTestDoseIterator); DoseIteratorPointer spDoseIteratorNull; if (argc > 3) { referenceXMLFilename = argv[1]; doseFilename = argv[2]; structFilename = argv[3]; } //1) test constructors // the values cannot be accessed from outside, therefore correct default values are not tested CHECK_THROW_EXPLICIT(rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator( spDoseIteratorNull), core::NullPointerException); CHECK_NO_THROW(rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator(spDoseIterator)); rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator(spDoseIterator); //2) test setDoseIterator //3) test calculateDoseStatistics DoseStatisticsPointer theStatistics; //simple dose statistics CHECK_NO_THROW(theStatistics = myDoseStatsCalculator.calculateDoseStatistics()); CHECK_EQUAL(theStatistics->getMinimumVoxelPositions()->empty(), false); CHECK_EQUAL(theStatistics->getMaximumVoxelPositions()->empty(), false); CHECK_EQUAL(theStatistics->getVx().getAllValues().empty(), true); CHECK_EQUAL(theStatistics->getDx().getAllValues().empty(), true); CHECK_EQUAL(theStatistics->getVx().getAllValues().empty(), true); CHECK_EQUAL(theStatistics->getMaxOHx().getAllValues().empty(), true); CHECK_EQUAL(theStatistics->getMOHx().getAllValues().empty(), true); CHECK_EQUAL(theStatistics->getMOCx().getAllValues().empty(), true); CHECK_EQUAL(theStatistics->getMinOCx().getAllValues().empty(), true); //check default values for computeComplexMeasures=true DoseStatisticsPointer theStatisticsDefault; myDoseStatsCalculator.setMultiThreading(true); CHECK_NO_THROW(theStatisticsDefault = myDoseStatsCalculator.calculateDoseStatistics(true)); CHECK_NO_THROW(theStatisticsDefault->getVx().getValue(0.02 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getVx().getValue(0.05 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getVx().getValue(0.1 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getVx().getValue(0.9 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getVx().getValue(0.95 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getVx().getValue(0.98 * theStatisticsDefault->getMaximum())); CHECK_NO_THROW(theStatisticsDefault->getDx().getValue(0.02 * theStatisticsDefault->getVolume())); CHECK_NO_THROW(theStatisticsDefault->getDx().getValue(0.05 * theStatisticsDefault->getVolume())); CHECK_NO_THROW(theStatisticsDefault->getDx().getValue(0.1 * theStatisticsDefault->getVolume())); CHECK_NO_THROW(theStatisticsDefault->getDx().getValue(0.9 * theStatisticsDefault->getVolume())); CHECK_NO_THROW(theStatisticsDefault->getDx().getValue(0.95 * theStatisticsDefault->getVolume())); CHECK_NO_THROW(theStatisticsDefault->getDx().getValue(0.98 * theStatisticsDefault->getVolume())); //check manually set reference dose and the default x values CHECK_NO_THROW(theStatistics = myDoseStatsCalculator.calculateDoseStatistics(100.0)); CHECK_THROW_EXPLICIT(theStatistics->getVx().getValue(0.1 * theStatistics->getMaximum()), core::DataNotAvailableException); CHECK_NO_THROW(theStatistics->getVx().getValue(0.1 * 100.0)); CHECK_NO_THROW(theStatistics->getDx().getValue(0.1 * theStatistics->getVolume())); CHECK_NO_THROW(theStatistics->getDx().getValue(0.9 * theStatistics->getVolume())); CHECK_NO_THROW(theStatistics->getMOHx().getValue(0.95 * theStatistics->getVolume())); CHECK_NO_THROW(theStatistics->getMOCx().getValue(0.98 * theStatistics->getVolume())); CHECK_EQUAL(theStatistics->getReferenceDose(), 100.0); //check manually set x values std::vector precomputeDoseValues, precomputeVolumeValues, additionalValues, faultyValues; precomputeDoseValues.push_back(0.01); precomputeDoseValues.push_back(0.02); precomputeDoseValues.push_back(0.05); precomputeVolumeValues.push_back(0.9); precomputeVolumeValues.push_back(0.95); precomputeVolumeValues.push_back(0.99); additionalValues.push_back(0.03); additionalValues.push_back(0.04); faultyValues.push_back(2); CHECK_THROW_EXPLICIT(theStatistics = myDoseStatsCalculator.calculateDoseStatistics(precomputeDoseValues, faultyValues), core::InvalidParameterException); CHECK_THROW_EXPLICIT(theStatistics = myDoseStatsCalculator.calculateDoseStatistics(faultyValues, precomputeVolumeValues), core::InvalidParameterException); CHECK_NO_THROW(theStatistics = myDoseStatsCalculator.calculateDoseStatistics(precomputeDoseValues, precomputeVolumeValues)); CHECK_NO_THROW(theStatistics->getVx().getValue(0.01 * theStatistics->getMaximum())); CHECK_NO_THROW(theStatistics->getVx().getValue(0.02 * theStatistics->getMaximum())); CHECK_NO_THROW(theStatistics->getVx().getValue(0.05 * theStatistics->getMaximum())); CHECK_THROW_EXPLICIT(theStatistics->getVx().getValue(0.03 * theStatistics->getMaximum()), core::DataNotAvailableException); CHECK_NO_THROW(theStatistics->getDx().getValue(0.9 * theStatistics->getVolume())); CHECK_NO_THROW(theStatistics->getDx().getValue(0.95 * theStatistics->getVolume())); CHECK_NO_THROW(theStatistics->getDx().getValue(0.99 * theStatistics->getVolume())); CHECK_THROW_EXPLICIT(theStatistics->getDx().getValue(0.04 * theStatistics->getVolume()), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(myDoseStatsCalculator.addPrecomputeValues(faultyValues), core::InvalidParameterException); CHECK_NO_THROW(myDoseStatsCalculator.addPrecomputeValues(additionalValues)); CHECK_NO_THROW(myDoseStatsCalculator.recalculateDoseStatistics()); CHECK_NO_THROW(theStatistics->getVx().getValue(0.03 * theStatistics->getMaximum())); CHECK_NO_THROW(theStatistics->getDx().getValue(0.04 * theStatistics->getVolume())); CHECK_EQUAL(theStatistics->getVx().getValue(0.02 * theStatistics->getMaximum()), theStatisticsDefault->getVx().getValue(0.02 * theStatistics->getMaximum())); CHECK_EQUAL(theStatistics->getVx().getValue(0.05 * theStatistics->getMaximum()), theStatisticsDefault->getVx().getValue(0.05 * theStatistics->getMaximum())); CHECK_EQUAL(theStatistics->getDx().getValue(0.9 * theStatistics->getVolume()), theStatisticsDefault->getDx().getValue(0.9 * theStatistics->getVolume())); CHECK_EQUAL(theStatistics->getDx().getValue(0.95 * theStatistics->getVolume()), theStatisticsDefault->getDx().getValue(0.95 * theStatistics->getVolume())); //check manually set reference dose and x values CHECK_NO_THROW(theStatistics = myDoseStatsCalculator.calculateDoseStatistics(precomputeDoseValues, precomputeVolumeValues, 100.0)); CHECK_THROW_EXPLICIT(theStatistics->getVx().getValue(0.01 * theStatistics->getMaximum()), core::DataNotAvailableException); CHECK_NO_THROW(theStatistics->getVx().getValue(0.01 * 100.0)); CHECK_NO_THROW(theStatistics->getDx().getValue(0.9 * theStatistics->getVolume())); CHECK_EQUAL(theStatistics->getReferenceDose(), 100.0); //MOHx, MOCx, MaxOHx and MinOCx are computed analogous to Dx, they will not be checked. //4) get statistical values CHECK_EQUAL(theStatistics->getNumberOfVoxels(), doseVals->size()); //compute simple statistical values (min, mean, max, stddev) for comparison DoseStatisticType maximum = 0; DoseStatisticType minimum = 1000000; DoseStatisticType mean = 0; DoseStatisticType variance = 0; std::vector::const_iterator doseIt = doseVals->begin(); while (doseIt != doseVals->end()) { if (maximum < *doseIt) { maximum = *doseIt; } if (minimum > *doseIt) { minimum = *doseIt; } mean += *doseIt; ++doseIt; } mean /= doseVals->size(); doseIt = doseVals->begin(); while (doseIt != doseVals->end()) { variance += pow(*doseIt - mean, 2); ++doseIt; } variance /= doseVals->size(); DoseStatisticType stdDev = pow(variance, 0.5); //we have some precision problems here... double errorConstantLarger = 1e-2; CHECK_EQUAL(theStatistics->getMaximum(), maximum); CHECK_EQUAL(theStatistics->getMinimum(), minimum); CHECK_CLOSE(theStatistics->getMean(), mean, errorConstantLarger); CHECK_CLOSE(theStatistics->getStdDeviation(), stdDev, errorConstantLarger); CHECK_CLOSE(theStatistics->getVariance(), variance, errorConstantLarger); //check for complex doseStatistics (maximumPositions, minimumPositions, Vx, Dx, MOHx, MOCx, MAXOHx, MinOCx) unsigned int nMax = 0, nMin = 0; doseIt = doseVals->begin(); while (doseIt != doseVals->end()) { if (*doseIt == theStatistics->getMaximum()) { nMax++; } if (*doseIt == theStatistics->getMinimum()) { nMin++; } ++doseIt; } //only 100 positions are stored if (nMax > 100) { nMax = 100; } if (nMin > 100) { nMin = 100; } auto maximaPositions = theStatistics->getMaximumVoxelPositions(); auto minimaPositions = theStatistics->getMinimumVoxelPositions(); CHECK_EQUAL(maximaPositions->size(), nMax); CHECK_EQUAL(minimaPositions->size(), nMin); for (auto maximaPositionsIterator = std::begin(*maximaPositions); maximaPositionsIterator != std::end(*maximaPositions); ++maximaPositionsIterator) { CHECK_EQUAL(maximaPositionsIterator->first, theStatistics->getMaximum()); } for (auto minimaPositionsIterator = std::begin(*minimaPositions); minimaPositionsIterator != std::end(*minimaPositions); ++minimaPositionsIterator) { CHECK_EQUAL(minimaPositionsIterator->first, theStatistics->getMinimum()); } //generate specific example dose maximum = 9.5; minimum = 2.5; mean = 6; int sizeTemplate = 500; std::vector aDoseVector; for (int i = 0; i < sizeTemplate; i++) { aDoseVector.push_back(maximum); aDoseVector.push_back(minimum); } core::GeometricInfo geoInfo = spTestDoseAccessor->getGeometricInfo(); geoInfo.setNumRows(20); geoInfo.setNumColumns(10); geoInfo.setNumSlices(5); boost::shared_ptr spTestDoseAccessor2 = boost::make_shared(aDoseVector, geoInfo); DoseAccessorPointer spDoseAccessor2(spTestDoseAccessor2); boost::shared_ptr spTestDoseIterator2 = boost::make_shared(spDoseAccessor2); DoseIteratorPointer spDoseIterator2(spTestDoseIterator2); rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator2(spDoseIterator2); DoseStatisticsPointer theStatistics3 = myDoseStatsCalculator2.calculateDoseStatistics(); CHECK_EQUAL(theStatistics3->getMaximum(), maximum); CHECK_EQUAL(theStatistics3->getMinimum(), minimum); CHECK_EQUAL(theStatistics3->getMean(), mean); maximaPositions = theStatistics3->getMaximumVoxelPositions(); minimaPositions = theStatistics3->getMinimumVoxelPositions(); CHECK_EQUAL(maximaPositions->empty(), false); CHECK_EQUAL(minimaPositions->empty(), false); for (auto maximaPositionsIterator = std::begin(*maximaPositions); maximaPositionsIterator != std::end(*maximaPositions); ++maximaPositionsIterator) { CHECK_EQUAL(maximaPositionsIterator->first, theStatistics3->getMaximum()); } for (auto minimaPositionsIterator = std::begin(*minimaPositions); minimaPositionsIterator != std::end(*minimaPositions); ++minimaPositionsIterator) { CHECK_EQUAL(minimaPositionsIterator->first, theStatistics3->getMinimum()); } // compare with actual XML io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator(doseFilename.c_str()); core::DoseAccessorInterface::Pointer doseAccessorPointer(doseAccessorGenerator.generateDoseAccessor()); rttb::io::dicom::DicomFileStructureSetGenerator structAccessorGenerator(structFilename.c_str()); structAccessorGenerator.setStructureLabelFilterActive(true); structAccessorGenerator.setFilterRegEx("Heart"); core::StructureSet::Pointer structureSetGeneratorPointer = structAccessorGenerator.generateStructureSet(); CHECK_EQUAL(structureSetGeneratorPointer->getNumberOfStructures(), 1); core::MaskAccessorInterface::Pointer maskAccessorPointer = boost::make_shared (structureSetGeneratorPointer->getStructure(0), doseAccessorPointer->getGeometricInfo(), true); maskAccessorPointer->updateMask(); boost::shared_ptr maskedDoseIterator = boost::make_shared(maskAccessorPointer, doseAccessorPointer); rttb::core::DoseIteratorInterface::Pointer doseIteratorPointer(maskedDoseIterator); rttb::algorithms::DoseStatisticsCalculator doseStatisticsCalculator(doseIteratorPointer); DoseStatisticsPointer doseStatisticsActual = doseStatisticsCalculator.calculateDoseStatistics(14.0); io::other::DoseStatisticsXMLReader readerDefaultExpected(referenceXMLFilename); auto doseStatisticsExpected = readerDefaultExpected.generateDoseStatistic(); CHECK(checkEqualDoseStatistic(doseStatisticsExpected, doseStatisticsActual)); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/algorithms/files.cmake b/testing/algorithms/files.cmake index 1bb9327..fd7a696 100644 --- a/testing/algorithms/files.cmake +++ b/testing/algorithms/files.cmake @@ -1,25 +1,14 @@ SET(CPP_FILES DoseStatisticsTest.cpp DoseStatisticsCalculatorTest.cpp ArithmeticTest.cpp BinaryFunctorAccessorTest.cpp rttbAlgorithmsTests.cpp ../io/other/CompareDoseStatistic.cpp ../../code/io/other/rttbDoseStatisticsXMLReader.cpp - - #include dummy accessor files - ../core/DummyDoseAccessor.cpp - ../core/DummyMaskAccessor.cpp - ../core/DummyMutableDoseAccessor.cpp - ) SET(H_FILES ../io/other/CompareDoseStatistic.h ../../code/io/other/rttbDoseStatisticsXMLReader.h - - #include dummy accessor files - ../core/DummyDoseAccessor.h - ../core/DummyMaskAccessor.h - ../core/DummyMutableDoseAccessor.h ) diff --git a/testing/core/BaseTypeTest.cpp b/testing/core/BaseTypeTest.cpp index 6a24796..7b03dfe 100644 --- a/testing/core/BaseTypeTest.cpp +++ b/testing/core/BaseTypeTest.cpp @@ -1,271 +1,271 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include "litCheckMacros.h" #include "rttbBaseType.h" namespace rttb { namespace testing { /*! @brief BaseTypeTests - tests the API for the classes in baseType 1) Index3D 2) WorldCoordinate3D 3) SpacingVectorType3D 4) OrientationMatrix 5) VoxelGridIndex3D 6) VoxelGridIndex2D */ - int BaseTypeTest(int argc, char* argv[]) + int BaseTypeTest(int /*argc*/, char* /*argv*/[]) { PREPARE_DEFAULT_TEST_REPORTING; //1) Index3D CHECK_NO_THROW(Index3D ui); Index3D emptyIndex3D; CHECK_EQUAL(emptyIndex3D.x(), 0); CHECK_EQUAL(emptyIndex3D.y(), 0); CHECK_EQUAL(emptyIndex3D.z(), 0); CHECK_NO_THROW(Index3D ui(5)); Index3D sameValueIndex(5); CHECK_EQUAL(sameValueIndex.x(), 5); CHECK_EQUAL(sameValueIndex.y(), 5); CHECK_EQUAL(sameValueIndex.z(), 5); CHECK_NO_THROW(Index3D ui(5, 8, 42)); Index3D differentValueIndex(5, 8, 42); CHECK_EQUAL(differentValueIndex.x(), 5); CHECK_EQUAL(differentValueIndex.y(), 8); CHECK_EQUAL(differentValueIndex.z(), 42); Index3D threeDimensionalIndexSame(5, 8, 42); Index3D threeDimensionalIndexDifferent(1, 2, 3); CHECK(differentValueIndex == threeDimensionalIndexSame); CHECK_EQUAL(differentValueIndex == threeDimensionalIndexDifferent, false); CHECK_EQUAL(differentValueIndex == sameValueIndex, false); CHECK_EQUAL(emptyIndex3D == sameValueIndex, false); //2) WorldCoordinate3D CHECK_NO_THROW(WorldCoordinate3D wc); WorldCoordinate3D emptyWC3D; CHECK_EQUAL(emptyWC3D.x(), 0); CHECK_EQUAL(emptyWC3D.y(), 0); CHECK_EQUAL(emptyWC3D.z(), 0); CHECK_NO_THROW(WorldCoordinate3D wc(6.5)); WorldCoordinate3D sameValueWC3D(6.5); CHECK_EQUAL(sameValueWC3D.x(), 6.5); CHECK_EQUAL(sameValueWC3D.y(), 6.5); CHECK_EQUAL(sameValueWC3D.z(), 6.5); CHECK_NO_THROW(WorldCoordinate3D(5.8, 0.1, -2.7)); WorldCoordinate3D differentValueWC3D(5.8, 0.1, -2.7); CHECK_EQUAL(differentValueWC3D.x(), 5.8); CHECK_EQUAL(differentValueWC3D.y(), 0.1); CHECK_EQUAL(differentValueWC3D.z(), -2.7); CHECK_EQUAL(differentValueWC3D.toString(), "5.800000 0.100000 -2.700000"); WorldCoordinate3D differentValueWC3Dsecond(1.5, -3.9, 0.7); WorldCoordinate3D resultWC3DCrossTrue(-10.46, -8.11, -22.77); CHECK_NO_THROW(differentValueWC3D.cross(differentValueWC3Dsecond)); auto resultWC3DCrossComputed = differentValueWC3D.cross(differentValueWC3Dsecond); CHECK_CLOSE(resultWC3DCrossComputed.x(), resultWC3DCrossTrue.x(), errorConstant); CHECK_CLOSE(resultWC3DCrossComputed.y(), resultWC3DCrossTrue.y(), errorConstant); CHECK_CLOSE(resultWC3DCrossComputed.z(), resultWC3DCrossTrue.z(), errorConstant); CHECK_NO_THROW(differentValueWC3Dsecond.cross(differentValueWC3D)); auto resultWC3DCrossComputedOrder = differentValueWC3Dsecond.cross(differentValueWC3D); CHECK_CLOSE(resultWC3DCrossComputed.x(), resultWC3DCrossComputedOrder.x()*-1, errorConstant); CHECK_CLOSE(resultWC3DCrossComputed.y(), resultWC3DCrossComputedOrder.y()*-1, errorConstant); CHECK_CLOSE(resultWC3DCrossComputed.z(), resultWC3DCrossComputedOrder.z()*-1, errorConstant); differentValueWC3D = differentValueWC3Dsecond; CHECK_EQUAL(differentValueWC3D.x(), 1.5); CHECK_EQUAL(differentValueWC3D.y(), -3.9); CHECK_EQUAL(differentValueWC3D.z(), 0.7); boost::numeric::ublas::vector wcUblas(3, 4.5); differentValueWC3D = wcUblas; CHECK_EQUAL(differentValueWC3D.x(), 4.5); CHECK_EQUAL(differentValueWC3D.y(), 4.5); CHECK_EQUAL(differentValueWC3D.z(), 4.5); WorldCoordinate3D WCresultMinus; CHECK_NO_THROW(WCresultMinus = differentValueWC3D- differentValueWC3Dsecond); CHECK_EQUAL(WCresultMinus.x(), differentValueWC3D.x()- differentValueWC3Dsecond.x()); CHECK_EQUAL(WCresultMinus.y(), differentValueWC3D.y() - differentValueWC3Dsecond.y()); CHECK_EQUAL(WCresultMinus.z(), differentValueWC3D.z() - differentValueWC3Dsecond.z()); WorldCoordinate3D WCresultPlus; CHECK_NO_THROW(WCresultPlus = differentValueWC3D + differentValueWC3Dsecond); CHECK_EQUAL(WCresultPlus.x(), differentValueWC3D.x() + differentValueWC3Dsecond.x()); CHECK_EQUAL(WCresultPlus.y(), differentValueWC3D.y() + differentValueWC3Dsecond.y()); CHECK_EQUAL(WCresultPlus.z(), differentValueWC3D.z() + differentValueWC3Dsecond.z()); WorldCoordinate3D sameAsWcUblas(4.5); CHECK_EQUAL(resultWC3DCrossTrue== differentValueWC3Dsecond, false); CHECK_EQUAL(differentValueWC3D == sameAsWcUblas, true); WorldCoordinate3D sameAsWcUblasAlmost(4.5+1e-6, 4.5-1e-6, 4.5+2e-7); CHECK_EQUAL(sameAsWcUblas.equalsAlmost(sameAsWcUblasAlmost), true); CHECK_EQUAL(sameAsWcUblas.equalsAlmost(resultWC3DCrossComputedOrder), false); //3) SpacingVectorType CHECK_NO_THROW(SpacingVectorType3D svt); SpacingVectorType3D emptySvt; CHECK_EQUAL(emptySvt.x(), 0); CHECK_EQUAL(emptySvt.y(), 0); CHECK_EQUAL(emptySvt.z(), 0); CHECK_NO_THROW(SpacingVectorType3D svt(1.5)); CHECK_THROW(SpacingVectorType3D svt(-1.5)); SpacingVectorType3D sameValueSvt(1.5); CHECK_EQUAL(sameValueSvt.x(), 1.5); CHECK_EQUAL(sameValueSvt.y(), 1.5); CHECK_EQUAL(sameValueSvt.z(), 1.5); CHECK_NO_THROW(SpacingVectorType3D svt(1.5, 1.5, 0.5)); CHECK_THROW(SpacingVectorType3D svt(1.5, -1.5, 0.5)); CHECK_THROW(SpacingVectorType3D svt(-1.5, -1.5, -0.5)); SpacingVectorType3D differentValuesSvt(1.5, 1.5, 0.5); CHECK_EQUAL(differentValuesSvt.x(), 1.5); CHECK_EQUAL(differentValuesSvt.y(), 1.5); CHECK_EQUAL(differentValuesSvt.z(), 0.5); SpacingVectorType3D differentValuesSvtChanged(0.5, 0.5, 1.5); CHECK_NO_THROW(SpacingVectorType3D svt(differentValuesSvtChanged)); SpacingVectorType3D svtNew(differentValuesSvtChanged); CHECK_EQUAL(svtNew.x(), 0.5); CHECK_EQUAL(svtNew.y(), 0.5); CHECK_EQUAL(svtNew.z(), 1.5); CHECK_NO_THROW(svtNew = differentValuesSvt); CHECK_EQUAL(svtNew.x(), 1.5); CHECK_EQUAL(svtNew.y(), 1.5); CHECK_EQUAL(svtNew.z(), 0.5); CHECK_NO_THROW(svtNew = differentValueWC3D); CHECK_EQUAL(svtNew.x(), 4.5); CHECK_EQUAL(svtNew.y(), 4.5); CHECK_EQUAL(svtNew.z(), 4.5); boost::numeric::ublas::vector ublasVector(3, 0.5); CHECK_NO_THROW(svtNew = ublasVector); CHECK_EQUAL(svtNew.x(), 0.5); CHECK_EQUAL(svtNew.y(), 0.5); CHECK_EQUAL(svtNew.z(), 0.5); SpacingVectorType3D sameAsUblasVector(0.5); CHECK_EQUAL(svtNew== differentValuesSvtChanged, false); CHECK_EQUAL(svtNew == sameAsUblasVector, true); SpacingVectorType3D almostSameAsUblasVector(0.5+1e-6, 0.5-1e-6,0.5+2e-7); CHECK(svtNew.equalsAlmost(almostSameAsUblasVector)); CHECK_EQUAL(differentValuesSvtChanged.toString(), "0.500000 0.500000 1.500000"); //4) OrientationMatrix CHECK_NO_THROW(OrientationMatrix om); OrientationMatrix om; CHECK_EQUAL(om(0, 0), 1.0); CHECK_EQUAL(om(1, 1), 1.0); CHECK_EQUAL(om(2, 2), 1.0); CHECK_EQUAL(om(0, 1), 0.0); CHECK_EQUAL(om(0, 2), 0.0); CHECK_EQUAL(om(1, 0), 0.0); CHECK_EQUAL(om(1, 2), 0.0); CHECK_EQUAL(om(2, 0), 0.0); CHECK_EQUAL(om(2, 1), 0.0); CHECK_NO_THROW(OrientationMatrix omValue(0.1)); OrientationMatrix omValue(0.1); for (unsigned int i = 0; i < 3; i++) { for (unsigned int j = 0; j < 3; j++) { CHECK_EQUAL(omValue(i, j), 0.1); } } OrientationMatrix omValueAlmost(0.1+1e-6); CHECK_EQUAL(omValue.equalsAlmost(omValueAlmost), true); CHECK_EQUAL(omValue.equalsAlmost(om), false); OrientationMatrix omSame; CHECK_EQUAL(om == omSame, true); CHECK_EQUAL(omValue == omValueAlmost, false); //5) VoxelGridIndex3D CHECK_NO_THROW(VoxelGridIndex3D vgi); VoxelGridIndex3D vgi; - CHECK_EQUAL(vgi.x(), 0); - CHECK_EQUAL(vgi.y(), 0); - CHECK_EQUAL(vgi.z(), 0); + CHECK_EQUAL(vgi.x(), 0u); + CHECK_EQUAL(vgi.y(), 0u); + CHECK_EQUAL(vgi.z(), 0u); CHECK_NO_THROW(VoxelGridIndex3D vgiValue(2)); VoxelGridIndex3D vgiValue(2); - CHECK_EQUAL(vgiValue.x(), 2); - CHECK_EQUAL(vgiValue.y(), 2); - CHECK_EQUAL(vgiValue.z(), 2); + CHECK_EQUAL(vgiValue.x(), 2u); + CHECK_EQUAL(vgiValue.y(), 2u); + CHECK_EQUAL(vgiValue.z(), 2u); CHECK_NO_THROW(VoxelGridIndex3D vgiValueDifferent(2,3,5)); VoxelGridIndex3D vgiValueDifferent(2,3,5); - CHECK_EQUAL(vgiValueDifferent.x(), 2); - CHECK_EQUAL(vgiValueDifferent.y(), 3); - CHECK_EQUAL(vgiValueDifferent.z(), 5); + CHECK_EQUAL(vgiValueDifferent.x(), 2u); + CHECK_EQUAL(vgiValueDifferent.y(), 3u); + CHECK_EQUAL(vgiValueDifferent.z(), 5u); CHECK_EQUAL(vgiValueDifferent.toString(), "2 3 5"); CHECK_NO_THROW(vgiValueDifferent = threeDimensionalIndexSame); - CHECK_EQUAL(vgiValueDifferent.x(), 5); - CHECK_EQUAL(vgiValueDifferent.y(), 8); - CHECK_EQUAL(vgiValueDifferent.z(), 42); + CHECK_EQUAL(vgiValueDifferent.x(), 5u); + CHECK_EQUAL(vgiValueDifferent.y(), 8u); + CHECK_EQUAL(vgiValueDifferent.z(), 42u); VoxelGridIndex3D vgiValueDifferentSame(5, 8, 42); CHECK_EQUAL(vgi==vgiValue, false); CHECK_EQUAL(vgiValueDifferentSame == vgiValueDifferent, true); //6) VoxelGridIndex2D - CHECK_NO_THROW(VoxelGridIndex2D vgi); + CHECK_NO_THROW(VoxelGridIndex2D vgi2Dempty); VoxelGridIndex2D vgi2D; - CHECK_EQUAL(vgi2D.x(), 0); - CHECK_EQUAL(vgi2D.y(), 0); + CHECK_EQUAL(vgi2D.x(), 0u); + CHECK_EQUAL(vgi2D.y(), 0u); CHECK_NO_THROW(VoxelGridIndex2D vgi2DValue(2)); VoxelGridIndex2D vgi2DValue(2); - CHECK_EQUAL(vgi2DValue.x(), 2); - CHECK_EQUAL(vgi2DValue.y(), 2); + CHECK_EQUAL(vgi2DValue.x(), 2u); + CHECK_EQUAL(vgi2DValue.y(), 2u); CHECK_NO_THROW(VoxelGridIndex2D vgi2DValueDifferent(2, 3)); VoxelGridIndex2D vgi2DValueDifferent(2, 3); - CHECK_EQUAL(vgi2DValueDifferent.x(), 2); - CHECK_EQUAL(vgi2DValueDifferent.y(), 3); + CHECK_EQUAL(vgi2DValueDifferent.x(), 2u); + CHECK_EQUAL(vgi2DValueDifferent.y(), 3u); CHECK_EQUAL(vgi2DValueDifferent.toString(), "2 3"); VoxelGridIndex2D vgi2DValueDifferentSame(2, 3); CHECK_EQUAL(vgi2D == vgi2DValueDifferent, false); CHECK_EQUAL(vgi2DValueDifferent == vgi2DValueDifferentSame, true); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb \ No newline at end of file diff --git a/testing/core/CMakeLists.txt b/testing/core/CMakeLists.txt index 77b7708..cb55c82 100644 --- a/testing/core/CMakeLists.txt +++ b/testing/core/CMakeLists.txt @@ -1,29 +1,29 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(CORE_TESTS ${EXECUTABLE_OUTPUT_PATH}/${RTToolbox_PREFIX}CoreTests) SET(CORE_HEADER_TEST ${EXECUTABLE_OUTPUT_PATH}/${RTToolbox_PREFIX}CoreHeaderTest) SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) #----------------------------------------------------------------------------- ADD_TEST(GeometricInfoTest ${CORE_TESTS} GeometricInfoTest) ADD_TEST(MaskVoxelTest ${CORE_TESTS} MaskVoxelTest) ADD_TEST(GenericDoseIteratorTest ${CORE_TESTS} GenericDoseIteratorTest) ADD_TEST(GenericMaskedDoseIteratorTest ${CORE_TESTS} GenericMaskedDoseIteratorTest) ADD_TEST(DVHCalculatorTest ${CORE_TESTS} DVHCalculatorTest) ADD_TEST(DVHTest ${CORE_TESTS} DVHTest) ADD_TEST(DVHSetTest ${CORE_TESTS} DVHSetTest) ADD_TEST(StructureTest ${CORE_TESTS} StructureTest) ADD_TEST(StrVectorStructureSetGeneratorTest ${CORE_TESTS} StrVectorStructureSetGeneratorTest) ADD_TEST(StructureSetTest ${CORE_TESTS} StructureSetTest) ADD_TEST(BaseTypeTest ${CORE_TESTS} BaseTypeTest) -RTTB_CREATE_TEST_MODULE(Core DEPENDS RTTBCore PACKAGE_DEPENDS Boost Litmus) +RTTB_CREATE_TEST_MODULE(Core DEPENDS RTTBCore RTTBTestHelper PACKAGE_DEPENDS Boost Litmus) diff --git a/testing/core/DVHSetTest.cpp b/testing/core/DVHSetTest.cpp index 5c25455..5c53e62 100644 --- a/testing/core/DVHSetTest.cpp +++ b/testing/core/DVHSetTest.cpp @@ -1,201 +1,201 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #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 { 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"; 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)); } DVHSetType htSet; 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)); } //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); core::DVHSet myDvhSet2(tvSet, htSet, structureSetID, doseID); 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()); //3) test set/getIDs const IDType newStructureSetID = "myNewStructureSet"; const IDType newDoseID = "myNewDose"; 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(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); //4) test insert/retrieve individual DVHs DVHRole roleTV = {DVHRole::TargetVolume}; DVHRole roleUser = { DVHRole::UserDefined }; 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); std::size_t currentSize = myDvhSet2.size(); CHECK_NO_THROW(myDvhSet2.insert(tv, roleTV)); CHECK_EQUAL(myDvhSet2.size(), currentSize + 1); CHECK_THROW_EXPLICIT(myDvhSet2.insert(tv, roleUser), core::InvalidParameterException); DVHRole roleHT = {DVHRole::HealthyTissue}; 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); currentSize = myDvhSet2.size(); CHECK_NO_THROW(myDvhSet2.insert(ht, roleHT)); 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); CHECK_NO_THROW(myDvhSet1.insert(wv, roleWV)); CHECK_EQUAL(myDvhSet1.size(), 3); currentSize = myDvhSet2.size(); CHECK_NO_THROW(myDvhSet2.insert(wv, roleWV)); CHECK_EQUAL(myDvhSet2.size(), currentSize + 1); //5) test getDVHSet core::DVH* dvhPtr = myDvhSet1.getDVH(testID); CHECK_EQUAL(*dvhPtr, wv); 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 + "_HT_2"); CHECK_EQUAL(*dvhPtr, htSet.at(2)); dvhPtr = myDvhSet3.getDVH(structureIDPrefix + "_WV_0"); CHECK_EQUAL(*dvhPtr, wvSet.at(0)); dvhPtr = myDvhSet3.getDVH("wrongID"); CHECK(!dvhPtr); DVHSetType tvTest = myDvhSet3.getTargetVolumeSet(); CHECK_EQUAL(tvTest, tvSet); DVHSetType htTest = myDvhSet3.getHealthyTissueSet(); CHECK_EQUAL(htTest, htSet); 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)); //7) Test equality core::DVHSet myDvhSet4(myDvhSet1.getStrSetID(), myDvhSet1.getDoseID()); myDvhSet4.insert(tv, roleTV); myDvhSet4.insert(ht, roleHT); myDvhSet4.insert(wv, roleWV); CHECK_EQUAL(myDvhSet1 == myDvhSet2, false); CHECK_EQUAL(myDvhSet1 == myDvhSet4, true); myDvhSet4.setDoseID("bla"); CHECK_EQUAL(myDvhSet1 == myDvhSet4, false); myDvhSet4.setDoseID(myDvhSet1.getDoseID()); myDvhSet4.insert(tv, roleTV); CHECK_EQUAL(myDvhSet1 == myDvhSet4, false); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/core/GeometricInfoTest.cpp b/testing/core/GeometricInfoTest.cpp index 5e35dfc..c989407 100644 --- a/testing/core/GeometricInfoTest.cpp +++ b/testing/core/GeometricInfoTest.cpp @@ -1,555 +1,570 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbGeometricInfo.h" namespace rttb { namespace testing { /*!@brief GeometricInfoTest - test the API of GeometricInfo @note ITK pixel indexing: Index[0] = col, Index[1] = row, Index[2] = slice. 1) test default constructor (values as expected?) 2) test set/getImagePositionPatient 4) test set/getSpacing 5) test set/getNumColumns/Rows/Slices 6) test get/setOrientationMatrix 8) test operators "==" 9) test equalsAlmost 10) test world to index coordinate conversion 11) test isInside and index to world coordinate conversion 12) test with simple Geometry: isInside, continuousIndexToWorldCoordinate(), worldCoordinateToContinuousIndex(), indexToWorldCoordinate() 13) test getNumberOfVoxels 14) Test convert, validID and validIndex + 15) Cloning of information */ int GeometricInfoTest(int /*argc*/, char* /*argv*/[]) { PREPARE_DEFAULT_TEST_REPORTING; //1) test default constructor (values as expected?) CHECK_NO_THROW(core::GeometricInfo()); core::GeometricInfo geoInfo; SpacingVectorType3D testNullSV(0); WorldCoordinate3D testNullWC(0); OrientationMatrix testNullOM(0); CHECK_EQUAL(testNullSV, geoInfo.getSpacing()); CHECK_EQUAL(testNullWC, geoInfo.getImagePositionPatient()); CHECK_EQUAL(testNullOM, geoInfo.getOrientationMatrix()); //2) test set/getImagePositionPatient WorldCoordinate3D testIPP(1.2, 3.4, 5.6); CHECK_NO_THROW(geoInfo.setImagePositionPatient(testIPP)); geoInfo.setImagePositionPatient(testIPP); CHECK_EQUAL(testIPP, geoInfo.getImagePositionPatient()); //4) test set/getSpacing //negative spacing does not make sense! /*!@is related to #2028 Should SpacingTypeVector/GridVolumeType/OrientationMatrix be forced to be non-negative?*/ SpacingVectorType3D expectedSpacing(4.15, 2.35, 100); expectedSpacing(0) = 4.15; expectedSpacing(1) = 2.35; expectedSpacing(2) = 100; CHECK_NO_THROW(geoInfo.setSpacing(expectedSpacing)); geoInfo.setSpacing(expectedSpacing); CHECK_EQUAL(expectedSpacing, geoInfo.getSpacing()); //5) test set/getNumColumns/Rows/Slices const VoxelGridIndex3D expectedVoxelDims(10, 5, 3); //CHECK_THROW(geoInfo.setNumColumns(1.2)); -> implicit conversion will prevent exception CHECK_NO_THROW(geoInfo.setNumColumns(expectedVoxelDims(0))); geoInfo.setNumColumns(expectedVoxelDims(0)); CHECK_NO_THROW(geoInfo.setNumRows(expectedVoxelDims(1))); geoInfo.setNumRows(expectedVoxelDims(1)); //CHECK_THROW(geoInfo.setNumSlices(4.2)); -> implicit conversion will prevent exception CHECK_NO_THROW(geoInfo.setNumSlices(expectedVoxelDims(2))); geoInfo.setNumSlices(expectedVoxelDims(2)); ImageSize rttbSize = geoInfo.getImageSize(); CHECK_EQUAL(rttbSize(0), geoInfo.getNumColumns()); CHECK_EQUAL(rttbSize(1), geoInfo.getNumRows()); CHECK_EQUAL(rttbSize(2), geoInfo.getNumSlices()); rttbSize = ImageSize(11, 99, 6); core::GeometricInfo geoInfo3; geoInfo3.setImageSize(rttbSize); CHECK_EQUAL(rttbSize(0), geoInfo3.getNumColumns()); CHECK_EQUAL(rttbSize(1), geoInfo3.getNumRows()); CHECK_EQUAL(rttbSize(2), geoInfo3.getNumSlices()); //6) test get/setOrientationMatrix CHECK_EQUAL(testNullOM, geoInfo.getOrientationMatrix()); OrientationMatrix testOM(0); const WorldCoordinate3D testIORow(5.5, 4.7, 3.2); const WorldCoordinate3D testIOColumn(2.5, 1.8, 9.1); WorldCoordinate3D ortho = testIORow.cross(testIOColumn); testOM(0, 0) = testIORow(0); testOM(1, 0) = testIORow(1); testOM(2, 0) = testIORow(2); CHECK_NO_THROW(geoInfo.setOrientationMatrix(testOM)); geoInfo.setOrientationMatrix(testOM); CHECK_EQUAL(testOM, geoInfo.getOrientationMatrix()); testOM(0, 1) = testIOColumn(0); testOM(1, 1) = testIOColumn(1); testOM(2, 1) = testIOColumn(2); CHECK_NO_THROW(geoInfo.setOrientationMatrix(testOM)); geoInfo.setOrientationMatrix(testOM); CHECK_EQUAL(testOM, geoInfo.getOrientationMatrix()); testOM(0, 2) = ortho(0); testOM(1, 2) = ortho(1); testOM(2, 2) = ortho(2); CHECK_NO_THROW(geoInfo.setOrientationMatrix(testOM)); geoInfo.setOrientationMatrix(testOM); CHECK_EQUAL(testOM, geoInfo.getOrientationMatrix()); //8) test operators "==" core::GeometricInfo geoInfo2; CHECK_EQUAL(geoInfo, geoInfo); CHECK(!(geoInfo == geoInfo2)); CHECK_EQUAL(geoInfo.getOrientationMatrix(), testOM); CHECK(!(geoInfo.getOrientationMatrix() == testNullOM)); //9) test equalsALmost OrientationMatrix testOM2 = testOM; SpacingVectorType3D testSPV2 = expectedSpacing; WorldCoordinate3D testIPP2 = testIPP; core::GeometricInfo testGI2, testGIEmpty; testGI2.setImagePositionPatient(testIPP2); testGI2.setOrientationMatrix(testOM2); testGI2.setSpacing(testSPV2); double smallValue = 0.000000001; testOM(0, 0) += smallValue; testSPV2(2) += smallValue; testIPP2(1) += smallValue; core::GeometricInfo testGI2similar; testGI2similar.setImagePositionPatient(testIPP2); testGI2similar.setOrientationMatrix(testOM2); testGI2similar.setSpacing(testSPV2); CHECK_EQUAL(testGI2.equalsAlmost(testGI2similar), true); CHECK_EQUAL(testGI2similar.equalsAlmost(testGI2), true); CHECK_EQUAL(testGI2.equalsAlmost(testGI2similar, smallValue * 0.001), false); CHECK_EQUAL(testGIEmpty.equalsAlmost(testGI2), false); CHECK_EQUAL(testGI2.equalsAlmost(testGIEmpty), false); //10) test world to index coordinate conversion //use unit matrix as orientation matrix CHECK_NO_THROW(geoInfo.setOrientationMatrix(OrientationMatrix())); //origin (inside) WorldCoordinate3D insideTestWC1 = geoInfo.getImagePositionPatient(); //inside const VoxelGridIndex3D expectedIndex(8, 3, 2); WorldCoordinate3D insideTestWC2(expectedIndex(0)*expectedSpacing(0) + testIPP(0), expectedIndex(1)*expectedSpacing(1) + testIPP(1), expectedIndex(2)*expectedSpacing(2) + testIPP(2)); //outside WorldCoordinate3D insideTestWC3(-33.12, 0, 14); // outside (dimension of grid) WorldCoordinate3D insideTestWC4(expectedVoxelDims(0)*expectedSpacing(0) + testIPP(0), expectedVoxelDims(1)*expectedSpacing(1) + testIPP(1), expectedVoxelDims(2)*expectedSpacing(2) + testIPP(2)); CHECK(geoInfo.isInside(insideTestWC1)); CHECK(geoInfo.isInside(insideTestWC2)); CHECK(!(geoInfo.isInside(insideTestWC3))); CHECK(!(geoInfo.isInside(insideTestWC4))); VoxelGridIndex3D testConvert(0); CHECK(geoInfo.worldCoordinateToIndex(insideTestWC1, testConvert)); CHECK(geoInfo.isInside(testConvert)); CHECK_EQUAL(VoxelGridIndex3D(0), testConvert); CHECK(geoInfo.worldCoordinateToIndex(insideTestWC2, testConvert)); CHECK(geoInfo.isInside(testConvert)); CHECK_EQUAL(expectedIndex, testConvert); CHECK(!(geoInfo.worldCoordinateToIndex(insideTestWC3, testConvert))); //CHECK_EQUAL(VoxelGridIndex3D(0),testConvert); //if value is in a negative grid position it will be converted //to a very large unrelated number. CHECK(!(geoInfo.isInside(testConvert))); CHECK(!(geoInfo.worldCoordinateToIndex(insideTestWC4, testConvert))); CHECK_EQUAL(expectedVoxelDims, testConvert); CHECK(!(geoInfo.isInside(testConvert))); //use a more complicated orientation matrix OrientationMatrix newOrientation(0); newOrientation(0, 0) = 0.5; newOrientation(1, 2) = -3; newOrientation(2, 1) = 1; CHECK_NO_THROW(geoInfo.setOrientationMatrix(newOrientation)); testIPP = WorldCoordinate3D(20, 100, -1000); CHECK_NO_THROW(geoInfo.setImagePositionPatient(testIPP)); CHECK_NO_THROW(geoInfo.setSpacing(SpacingVectorType3D(1))); //values for testing were generated with a dedicated MeVisLab routine insideTestWC1 = geoInfo.getImagePositionPatient(); //origin (inside) const VoxelGridIndex3D expectedIndexWC1(0, 0, 0); insideTestWC2 = WorldCoordinate3D(22.5, 97, -998); //inside const VoxelGridIndex3D expectedIndexWC2(5, 2, 1); insideTestWC3 = WorldCoordinate3D(26, 88, -996); //outside const VoxelGridIndex3D expectedIndexWC3(12, 4, 4); insideTestWC4 = WorldCoordinate3D(25, 91, -995); // outside: Grid dimension = [10,5,3] const VoxelGridIndex3D expectedIndexWC4(10, 5, 3); CHECK(geoInfo.isInside(insideTestWC1)); CHECK_EQUAL(geoInfo.isInside(insideTestWC1), geoInfo.isInside(expectedIndexWC1)); CHECK(geoInfo.isInside(insideTestWC2)); CHECK_EQUAL(geoInfo.isInside(insideTestWC2), geoInfo.isInside(expectedIndexWC2)); CHECK(!(geoInfo.isInside(insideTestWC3))); CHECK_EQUAL(geoInfo.isInside(insideTestWC3), geoInfo.isInside(expectedIndexWC3)); CHECK(!(geoInfo.isInside(insideTestWC4))); CHECK_EQUAL(geoInfo.isInside(insideTestWC4), geoInfo.isInside(expectedIndexWC4)); CHECK(geoInfo.worldCoordinateToIndex(insideTestWC1, testConvert)); CHECK(geoInfo.isInside(testConvert)); CHECK_EQUAL(expectedIndexWC1, testConvert); CHECK(geoInfo.worldCoordinateToIndex(insideTestWC2, testConvert)); CHECK(geoInfo.isInside(testConvert)); CHECK_EQUAL(expectedIndexWC2, testConvert); CHECK(!(geoInfo.worldCoordinateToIndex(insideTestWC3, testConvert))); CHECK(!(geoInfo.isInside(testConvert))); CHECK_EQUAL(expectedIndexWC3, testConvert); CHECK(!(geoInfo.worldCoordinateToIndex(insideTestWC4, testConvert))); CHECK(!(geoInfo.isInside(testConvert))); CHECK_EQUAL(expectedIndexWC4, testConvert); //11) test isInside and index to world coordinate conversion //use unit matrix as orientation matrix CHECK_NO_THROW(geoInfo.setOrientationMatrix(OrientationMatrix())); VoxelGridIndex3D insideTest1(0, 0, 0); //origin (inside) VoxelGridIndex3D insideTest2(2, 3, 1); //inside VoxelGridIndex3D insideTest3(0, 6, 14); //outside VoxelGridIndex3D insideTest4 = expectedVoxelDims; // outside CHECK(geoInfo.isInside(insideTest1)); CHECK(geoInfo.isInside(insideTest2)); CHECK(!(geoInfo.isInside(insideTest3))); CHECK(!(geoInfo.isInside(insideTest4))); WorldCoordinate3D testInside(0); CHECK(geoInfo.indexToWorldCoordinate(insideTest1, testInside)); CHECK(geoInfo.isInside(testInside)); //CHECK_EQUAL(geoInfo.getImagePositionPatient(),testInside); //half voxel shift prevents equality! CHECK(geoInfo.indexToWorldCoordinate(insideTest2, testInside)); CHECK(geoInfo.isInside(testInside)); CHECK(!(geoInfo.indexToWorldCoordinate(insideTest3, testInside))); CHECK(!(geoInfo.isInside(testInside))); CHECK(!(geoInfo.indexToWorldCoordinate(insideTest4, testInside))); CHECK(!(geoInfo.isInside(testInside))); WorldCoordinate3D testWorldCoordinate; ContinuousVoxelGridIndex3D testDoubleIndex; ContinuousVoxelGridIndex3D doubleIndex1 = ContinuousVoxelGridIndex3D(0.1, 0, -0.3); const WorldCoordinate3D expectedDoubleIndex1(20.1, 100, -1000.3); ContinuousVoxelGridIndex3D doubleIndex2 = ContinuousVoxelGridIndex3D(11, 6, 15); //outside const WorldCoordinate3D expectedDoubleIndex2(31, 106, -985); ContinuousVoxelGridIndex3D doubleIndex3 = ContinuousVoxelGridIndex3D(10.1, 5.0, 3.0); // outside: Grid dimension = [10,5,3] const WorldCoordinate3D expectedDoubleIndex3(30.1, 105, -997); ContinuousVoxelGridIndex3D doubleIndex4 = ContinuousVoxelGridIndex3D(0.0, 0.0, 0.0); const WorldCoordinate3D expectedDoubleIndex4 = geoInfo.getImagePositionPatient(); //test double index to world coordinate geoInfo.continuousIndexToWorldCoordinate(doubleIndex1, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, expectedDoubleIndex1); geoInfo.continuousIndexToWorldCoordinate(doubleIndex2, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, expectedDoubleIndex2); geoInfo.continuousIndexToWorldCoordinate(doubleIndex3, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, expectedDoubleIndex3); geoInfo.continuousIndexToWorldCoordinate(doubleIndex4, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, expectedDoubleIndex4); geoInfo.worldCoordinateToContinuousIndex(expectedDoubleIndex4, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndex4); geoInfo.worldCoordinateToContinuousIndex(expectedDoubleIndex3, testDoubleIndex); CHECK_CLOSE(testDoubleIndex(0), doubleIndex3(0), errorConstant); CHECK_CLOSE(testDoubleIndex(1), doubleIndex3(1), errorConstant); CHECK_CLOSE(testDoubleIndex(2), doubleIndex3(2), errorConstant); geoInfo.worldCoordinateToContinuousIndex(expectedDoubleIndex2, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndex2); geoInfo.worldCoordinateToContinuousIndex(expectedDoubleIndex1, testDoubleIndex); CHECK_CLOSE(testDoubleIndex(0), doubleIndex1(0), errorConstant); CHECK_CLOSE(testDoubleIndex(1), doubleIndex1(1), errorConstant); CHECK_CLOSE(testDoubleIndex(2), doubleIndex1(2), errorConstant); VoxelGridIndex3D testIntIndex; geoInfo.worldCoordinateToIndex(expectedDoubleIndex4, testIntIndex); CHECK_EQUAL(testIntIndex, insideTest1); geoInfo.worldCoordinateToIndex(expectedDoubleIndex1, testIntIndex); CHECK_EQUAL(testIntIndex, insideTest1); geoInfo.worldCoordinateToIndex(expectedDoubleIndex3, testIntIndex); CHECK_EQUAL(testIntIndex, expectedVoxelDims); //use a more complicated orientation matrix newOrientation = OrientationMatrix(0); newOrientation(0, 0) = 0.5; newOrientation(1, 2) = -3; newOrientation(2, 1) = 1; CHECK_NO_THROW(geoInfo.setOrientationMatrix(newOrientation)); testIPP = WorldCoordinate3D(20, 100, -1000); CHECK_NO_THROW(geoInfo.setImagePositionPatient(testIPP)); CHECK_NO_THROW(geoInfo.setSpacing(SpacingVectorType3D(1))); //values for testing were generated with a dedicated MeVisLab routine //no half voxel shift anymore because we changed indexToWorldCoordinate/worldCoordinateToIndex insideTest1 = VoxelGridIndex3D(0, 0, 0); //origin (inside) const WorldCoordinate3D expectedIndex1(20, 100, -1000); insideTest2 = VoxelGridIndex3D(6, 0, 2); //inside const WorldCoordinate3D expectedIndex2(23, 94, -1000); insideTest3 = VoxelGridIndex3D(11, 6, 15); //outside const WorldCoordinate3D expectedIndex3(25.5, 55, -994); insideTest4 = VoxelGridIndex3D(10, 5, 3); // outside: Grid dimension = [10,5,3] const WorldCoordinate3D expectedIndex4(25, 91, -995); CHECK(geoInfo.isInside(insideTest1)); CHECK_EQUAL(geoInfo.isInside(insideTest1), geoInfo.isInside(expectedIndex1)); CHECK(geoInfo.isInside(insideTest2)); CHECK_EQUAL(geoInfo.isInside(insideTest2), geoInfo.isInside(expectedIndex2)); CHECK(!(geoInfo.isInside(insideTest3))); CHECK_EQUAL(geoInfo.isInside(insideTest3), geoInfo.isInside(expectedIndex3)); CHECK(!(geoInfo.isInside(insideTest4))); CHECK_EQUAL(geoInfo.isInside(insideTest4), geoInfo.isInside(expectedIndex4)); CHECK(geoInfo.indexToWorldCoordinate(insideTest1, testInside)); CHECK(geoInfo.isInside(testInside)); CHECK_EQUAL(expectedIndex1, testInside); CHECK(geoInfo.indexToWorldCoordinate(insideTest2, testInside)); CHECK(geoInfo.isInside(testInside)); CHECK_EQUAL(expectedIndex2, testInside); CHECK(!(geoInfo.indexToWorldCoordinate(insideTest3, testInside))); CHECK(!(geoInfo.isInside(testInside))); CHECK_EQUAL(expectedIndex3, testInside); CHECK(!(geoInfo.indexToWorldCoordinate(insideTest4, testInside))); CHECK(!(geoInfo.isInside(testInside))); CHECK_EQUAL(expectedIndex4, testInside); //12) test with simple Geometry: isInside, continuousIndexToWorldCoordinate(), worldCoordinateToContinuousIndex(), indexToWorldCoordinate() core::GeometricInfo geoInfoSimple; ImageSize rttbSimpleSize = ImageSize(10, 10, 10); geoInfoSimple.setImageSize(rttbSimpleSize); SpacingVectorType3D spacingSimple(1, 1, 1); geoInfoSimple.setSpacing(spacingSimple); OrientationMatrix OMOnes; geoInfoSimple.setOrientationMatrix(OMOnes); const ContinuousVoxelGridIndex3D doubleIndexPixelOutside1 = ContinuousVoxelGridIndex3D(-0.501, 0.0, 0.0); const ContinuousVoxelGridIndex3D doubleIndexPixelOutside2 = ContinuousVoxelGridIndex3D(0.0, 9.501, 0.0); const ContinuousVoxelGridIndex3D doubleIndexPixelZero1 = ContinuousVoxelGridIndex3D(0.0, 0.0, 0.0); const ContinuousVoxelGridIndex3D doubleIndexPixelZero2 = ContinuousVoxelGridIndex3D(-0.5, -0.5, -0.5); const ContinuousVoxelGridIndex3D doubleIndexPixelZero3 = ContinuousVoxelGridIndex3D(0.499999, 0.499999, 0.499999); const ContinuousVoxelGridIndex3D doubleIndexPixelOne1 = ContinuousVoxelGridIndex3D(1.0, 0.0, 0.0); const ContinuousVoxelGridIndex3D doubleIndexPixelOne2 = ContinuousVoxelGridIndex3D(0.5, 0.499999, 0.499999); const ContinuousVoxelGridIndex3D doubleIndexPixelOne3 = ContinuousVoxelGridIndex3D(1.49, -0.5, -0.5); const ContinuousVoxelGridIndex3D doubleIndexPixelLast1 = ContinuousVoxelGridIndex3D(9.0, 9.0, 9.0); const ContinuousVoxelGridIndex3D doubleIndexPixelLast2 = ContinuousVoxelGridIndex3D(9.4999, 9.4999, 9.4999); const ContinuousVoxelGridIndex3D doubleIndexPixelLast3 = ContinuousVoxelGridIndex3D(8.501, 8.501, 8.501); const VoxelGridIndex3D indexPixelOutside = VoxelGridIndex3D(11, 0, 0); const VoxelGridIndex3D indexPixelZero = VoxelGridIndex3D(0, 0, 0); const VoxelGridIndex3D indexPixelOne = VoxelGridIndex3D(1, 0, 0); const VoxelGridIndex3D indexPixelLast = VoxelGridIndex3D(9, 9, 9); const WorldCoordinate3D worldCoordinateOutside1(doubleIndexPixelOutside1(0), doubleIndexPixelOutside1(1), doubleIndexPixelOutside1(2)); const WorldCoordinate3D worldCoordinateOutside2(doubleIndexPixelOutside2(0), doubleIndexPixelOutside2(1), doubleIndexPixelOutside2(2)); const WorldCoordinate3D worldCoordinatePixelZero1(doubleIndexPixelZero1(0), doubleIndexPixelZero1(1), doubleIndexPixelZero1(2)); const WorldCoordinate3D worldCoordinatePixelZero2(doubleIndexPixelZero2(0), doubleIndexPixelZero2(1), doubleIndexPixelZero2(2)); const WorldCoordinate3D worldCoordinatePixelZero3(doubleIndexPixelZero3(0), doubleIndexPixelZero3(1), doubleIndexPixelZero3(2)); const WorldCoordinate3D worldCoordinatePixelOne1(doubleIndexPixelOne1(0), doubleIndexPixelOne1(1), doubleIndexPixelOne1(2)); const WorldCoordinate3D worldCoordinatePixelOne2(doubleIndexPixelOne2(0), doubleIndexPixelOne2(1), doubleIndexPixelOne2(2)); const WorldCoordinate3D worldCoordinatePixelOne3(doubleIndexPixelOne3(0), doubleIndexPixelOne3(1), doubleIndexPixelOne3(2)); const WorldCoordinate3D worldCoordinatePixelLast1(doubleIndexPixelLast1(0), doubleIndexPixelLast1(1), doubleIndexPixelLast1(2)); const WorldCoordinate3D worldCoordinatePixelLast2(doubleIndexPixelLast2(0), doubleIndexPixelLast2(1), doubleIndexPixelLast2(2)); const WorldCoordinate3D worldCoordinatePixelLast3(doubleIndexPixelLast3(0), doubleIndexPixelLast3(1), doubleIndexPixelLast3(2)); bool isInside; isInside = geoInfoSimple.continuousIndexToWorldCoordinate(doubleIndexPixelOutside1, testWorldCoordinate); CHECK(!isInside); isInside = geoInfoSimple.continuousIndexToWorldCoordinate(doubleIndexPixelOutside2, testWorldCoordinate); CHECK(!isInside); isInside = geoInfoSimple.continuousIndexToWorldCoordinate(doubleIndexPixelZero1, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelZero1); CHECK(isInside); isInside = geoInfoSimple.continuousIndexToWorldCoordinate(doubleIndexPixelZero2, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelZero2); CHECK(isInside); isInside = geoInfoSimple.continuousIndexToWorldCoordinate(doubleIndexPixelZero3, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelZero3); CHECK(isInside); isInside = geoInfoSimple.continuousIndexToWorldCoordinate(doubleIndexPixelOne1, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelOne1); CHECK(isInside); isInside = geoInfoSimple.continuousIndexToWorldCoordinate(doubleIndexPixelOne2, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelOne2); CHECK(isInside); isInside = geoInfoSimple.continuousIndexToWorldCoordinate(doubleIndexPixelOne3, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelOne3); CHECK(isInside); isInside = geoInfoSimple.continuousIndexToWorldCoordinate(doubleIndexPixelLast1, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelLast1); CHECK(isInside); isInside = geoInfoSimple.continuousIndexToWorldCoordinate(doubleIndexPixelLast2, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelLast2); CHECK(isInside); isInside = geoInfoSimple.continuousIndexToWorldCoordinate(doubleIndexPixelLast3, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelLast3); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToContinuousIndex(worldCoordinateOutside1, testDoubleIndex); CHECK(!isInside); isInside = geoInfoSimple.worldCoordinateToContinuousIndex(worldCoordinateOutside2, testDoubleIndex); CHECK(!isInside); isInside = geoInfoSimple.worldCoordinateToContinuousIndex(worldCoordinatePixelZero1, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelZero1); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToContinuousIndex(worldCoordinatePixelZero2, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelZero2); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToContinuousIndex(worldCoordinatePixelZero3, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelZero3); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToContinuousIndex(worldCoordinatePixelOne1, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelOne1); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToContinuousIndex(worldCoordinatePixelOne2, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelOne2); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToContinuousIndex(worldCoordinatePixelOne3, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelOne3); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToContinuousIndex(worldCoordinatePixelLast1, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelLast1); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToContinuousIndex(worldCoordinatePixelLast2, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelLast2); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToContinuousIndex(worldCoordinatePixelLast3, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelLast3); CHECK(isInside); isInside = geoInfoSimple.indexToWorldCoordinate(indexPixelOutside, testWorldCoordinate); CHECK(!isInside); isInside = geoInfoSimple.indexToWorldCoordinate(indexPixelZero, testWorldCoordinate); CHECK(isInside); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelZero1); isInside = geoInfoSimple.indexToWorldCoordinate(indexPixelOne, testWorldCoordinate); CHECK(isInside); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelOne1); isInside = geoInfoSimple.indexToWorldCoordinate(indexPixelLast, testWorldCoordinate); CHECK(isInside); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelLast1); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinateOutside1, testIntIndex); CHECK(!isInside); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinateOutside2, testIntIndex); CHECK(!isInside); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelZero1, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelZero); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelZero2, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelZero); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelZero3, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelZero); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelOne1, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelOne); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelOne2, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelOne); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelOne3, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelOne); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelLast1, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelLast); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelLast2, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelLast); isInside = geoInfoSimple.worldCoordinateToIndex(worldCoordinatePixelLast3, testIntIndex); CHECK(isInside); CHECK_EQUAL(testIntIndex, indexPixelLast); //13) test getNumberOfVoxels CHECK_EQUAL(expectedVoxelDims(0)*expectedVoxelDims(1)*expectedVoxelDims(2), geoInfo.getNumberOfVoxels()); //14) Test convert, validID and validIndex geoInfo.setNumColumns(50); geoInfo.setNumRows(30); geoInfo.setNumSlices(40); VoxelGridIndex3D startIndex(0, 0, 0); VoxelGridID startId(0); VoxelGridIndex3D endIndex(geoInfo.getNumColumns() - 1, geoInfo.getNumRows() - 1, geoInfo.getNumSlices() - 1); VoxelGridID endId((geoInfo.getNumColumns()*geoInfo.getNumRows()*geoInfo.getNumSlices()) - 1); VoxelGridIndex3D indexInvalid(geoInfo.getNumColumns(), geoInfo.getNumRows(), geoInfo.getNumSlices()); VoxelGridID idInvalid(geoInfo.getNumColumns()*geoInfo.getNumRows()*geoInfo.getNumSlices()); CHECK(geoInfo.validID(startId)); CHECK(geoInfo.validIndex(startIndex)); VoxelGridIndex3D aIndex(9999999,999999,999999); VoxelGridID aId = 99999999; CHECK(geoInfo.convert(startIndex, aId)); CHECK(geoInfo.convert(startId, aIndex)); CHECK_EQUAL(aId, startId); CHECK_EQUAL(aIndex, startIndex); CHECK(geoInfo.validID(endId)); CHECK(geoInfo.validIndex(endIndex)); CHECK(geoInfo.convert(endIndex, aId)); CHECK(geoInfo.convert(endId, aIndex)); CHECK_EQUAL(aId, endId); CHECK_EQUAL(aIndex, endIndex); CHECK(!geoInfo.validID(idInvalid)); CHECK(!geoInfo.validIndex(indexInvalid)); CHECK(!geoInfo.convert(idInvalid, aIndex)); CHECK(!geoInfo.convert(indexInvalid, aId)); + //15) Test of GeometricInfo cloning + core::GeometricInfo sourceInfo; + sourceInfo.setNumColumns(50); + sourceInfo.setNumRows(30); + sourceInfo.setNumSlices(40); + sourceInfo.setSpacing(expectedSpacing); + sourceInfo.setOrientationMatrix(testOM); + + core::GeometricInfo clone1 = core::GeometricInfo(sourceInfo); + CHECK(clone1 == sourceInfo); + + core::GeometricInfo::Pointer clone2 = sourceInfo.clone(); + CHECK(*clone2 == sourceInfo); + RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/core/files.cmake b/testing/core/files.cmake index 612a4d6..092f4f2 100644 --- a/testing/core/files.cmake +++ b/testing/core/files.cmake @@ -1,31 +1,17 @@ SET(CPP_FILES rttbCoreTests.cpp - DummyDoseAccessor.cpp - DummyInhomogeneousDoseAccessor.cpp - DummyMaskAccessor.cpp - DummyMutableDoseAccessor.cpp - DummyDVHGenerator.cpp - DummyStructure.cpp - CreateTestStructure.cpp StructureTest.cpp GeometricInfoTest.cpp MaskVoxelTest.cpp GenericDoseIteratorTest.cpp GenericMaskedDoseIteratorTest.cpp DVHCalculatorTest.cpp DVHTest.cpp DVHSetTest.cpp StrVectorStructureSetGeneratorTest.cpp StructureSetTest.cpp BaseTypeTest.cpp ) SET(H_FILES - DummyStructure.h - CreateTestStructure.h - DummyDoseAccessor.h - DummyInhomogeneousDoseAccessor.h - DummyMaskAccessor.h - DummyMutableDoseAccessor.h - DummyDVHGenerator.h ) diff --git a/testing/indices/CMakeLists.txt b/testing/indices/CMakeLists.txt index bfe301b..71921fc 100644 --- a/testing/indices/CMakeLists.txt +++ b/testing/indices/CMakeLists.txt @@ -1,32 +1,33 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(INDICES_TESTS ${EXECUTABLE_OUTPUT_PATH}/${RTToolbox_PREFIX}IndicesTests) SET(INDICES_HEADER_TEST ${EXECUTABLE_OUTPUT_PATH}/${RTToolbox_PREFIX}CoreIndicesTest) SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) #----------------------------------------------------------------------------- ADD_TEST(ConformationNumberTest ${INDICES_TESTS} ConformationNumberTest "${TEST_DATA_ROOT}/DVH/XML/dvh_test_TV.xml" "${TEST_DATA_ROOT}/DVH/XML/dvh_test_HT1.xml" "${TEST_DATA_ROOT}/DVH/XML/dvh_test_HT2.xml" "${TEST_DATA_ROOT}/DVH/XML/dvh_test_HT3.xml") ADD_TEST(ConformalIndexTest ${INDICES_TESTS} ConformalIndexTest "${TEST_DATA_ROOT}/DVH/XML/dvh_test_TV.xml" "${TEST_DATA_ROOT}/DVH/XML/dvh_test_HT1.xml" "${TEST_DATA_ROOT}/DVH/XML/dvh_test_HT2.xml" "${TEST_DATA_ROOT}/DVH/XML/dvh_test_HT3.xml") ADD_TEST(ConformityIndexTest ${INDICES_TESTS} ConformityIndexTest "${TEST_DATA_ROOT}/DVH/XML/dvh_test_TV.xml" "${TEST_DATA_ROOT}/DVH/XML/dvh_test_HT1.xml" "${TEST_DATA_ROOT}/DVH/XML/dvh_test_HT2.xml" "${TEST_DATA_ROOT}/DVH/XML/dvh_test_HT3.xml") ADD_TEST(CoverageIndexTest ${INDICES_TESTS} CoverageIndexTest "${TEST_DATA_ROOT}/DVH/XML/dvh_test_TV.xml" "${TEST_DATA_ROOT}/DVH/XML/dvh_test_HT1.xml" "${TEST_DATA_ROOT}/DVH/XML/dvh_test_HT2.xml" "${TEST_DATA_ROOT}/DVH/XML/dvh_test_HT3.xml") ADD_TEST(HomogeneityIndexTest ${INDICES_TESTS} HomogeneityIndexTest "${TEST_DATA_ROOT}/DVH/XML/dvh_test_TV.xml" "${TEST_DATA_ROOT}/DVH/XML/dvh_test_HT1.xml" "${TEST_DATA_ROOT}/DVH/XML/dvh_test_HT2.xml" "${TEST_DATA_ROOT}/DVH/XML/dvh_test_HT3.xml") +ADD_TEST(GammaIndexTest ${INDICES_TESTS} GammaIndexTest) -RTTB_CREATE_TEST_MODULE(Indices DEPENDS RTTBCore RTTBIndices RTTBOtherIO PACKAGE_DEPENDS Boost Litmus) +RTTB_CREATE_TEST_MODULE(Indices DEPENDS RTTBCore RTTBIndices RTTBTestHelper RTTBOtherIO PACKAGE_DEPENDS Boost Litmus) diff --git a/testing/indices/GammaIndexTest.cpp b/testing/indices/GammaIndexTest.cpp new file mode 100644 index 0000000..3428ecc --- /dev/null +++ b/testing/indices/GammaIndexTest.cpp @@ -0,0 +1,318 @@ +// ----------------------------------------------------------------------- +// 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. +// +//------------------------------------------------------------------------ + +// this file defines the rttbCoreTests for the test driver +// and all it expects is that you have a function called RegisterTests + +#include "litCheckMacros.h" + +#include "rttbDoseIndex.h" +#include "rttbBaseType.h" +#include "rttbNullPointerException.h" +#include "rttbGammaIndex.h" +#include "rttbException.h" +#include "rttbInvalidDoseException.h" +#include "rttbNullPointerException.h" +#include "rttbLinearInterpolation.h" +#include "rttbNearestNeighborInterpolation.h" + +#include "DummyDoseAccessor.h" + +#include + +#include +#include + +namespace rttb +{ + namespace testing + { + class IndexFacade { + protected: + + indices::GammaIndex* _index; + + public: + IndexFacade( + indices::GammaIndex* index) { + this->_index = index; + } + ~IndexFacade() {} + /** + * overload [] function + */ + DoseTypeGy operator [](int idx) const { + return _index->getValueAt(idx); + } + }; + + void Test_Initialization() + { + PREPARE_DEFAULT_TEST_REPORTING; + + + core::DoseAccessorInterface::ConstPointer invalidDose; + core::DoseAccessorInterface::ConstPointer simpleDose = boost::make_shared(); + + CHECK_THROW_EXPLICIT(indices::GammaIndex(invalidDose, invalidDose), + core::NullPointerException); + CHECK_THROW_EXPLICIT(indices::GammaIndex(invalidDose, invalidDose,core::GeometricInfo()), + core::NullPointerException); + CHECK_THROW_EXPLICIT(indices::GammaIndex(simpleDose, invalidDose), + core::NullPointerException); + CHECK_THROW_EXPLICIT(indices::GammaIndex(simpleDose, invalidDose, core::GeometricInfo()), + core::NullPointerException); + CHECK_THROW_EXPLICIT(indices::GammaIndex(invalidDose, simpleDose), + core::NullPointerException); + CHECK_THROW_EXPLICIT(indices::GammaIndex(invalidDose, simpleDose, core::GeometricInfo()), + core::NullPointerException); + + core::GeometricInfo geoInfo; + geoInfo.setImageSize({ 2,2,2 }); + geoInfo.setSpacing({ 1,1,1 }); + + core::GeometricInfo geoInfo2; + geoInfo2.setImageSize({ 3,3,3 }); + geoInfo2.setSpacing({ 1,1,1 }); + + core::DoseAccessorInterface::ConstPointer refDose = boost::make_shared(std::vector({ 1,2,3,4,5,6,7,8 }), geoInfo); + + indices::GammaIndex gamma(simpleDose, refDose); + indices::GammaIndex gamma2(simpleDose, refDose, geoInfo2); + + CHECK_EQUAL(simpleDose->getGeometricInfo(), gamma.getGeometricInfo()); + CHECK_EQUAL(geoInfo2, gamma2.getGeometricInfo()); + + //CHECK interpolator setting + CHECK(nullptr != dynamic_cast(gamma.getDoseInterpolator().get())); + CHECK(gamma.getDoseInterpolator()->getAccessorPointer() == simpleDose); + CHECK(nullptr != dynamic_cast(gamma.getReferenceDoseInterpolator().get())); + CHECK(gamma.getReferenceDoseInterpolator()->getAccessorPointer() == refDose); + + auto nnInterpolator = boost::make_shared(); + auto nnInterpolator2 = boost::make_shared(); + + gamma.setDoseInterpolator(nnInterpolator); + CHECK(nnInterpolator == gamma.getDoseInterpolator()); + CHECK(nnInterpolator->getAccessorPointer() == simpleDose); + CHECK(nullptr != dynamic_cast(gamma.getReferenceDoseInterpolator().get())); + + gamma.setReferenceDoseInterpolator(nnInterpolator2); + CHECK(nnInterpolator == gamma.getDoseInterpolator()); + CHECK(nnInterpolator->getAccessorPointer() == simpleDose); + CHECK(nnInterpolator2 == gamma.getReferenceDoseInterpolator()); + CHECK(nnInterpolator2->getAccessorPointer() == refDose); + + gamma.setDoseInterpolator(nullptr); + CHECK(nullptr != dynamic_cast(gamma.getDoseInterpolator().get())); + CHECK(gamma.getDoseInterpolator()->getAccessorPointer() == simpleDose); + CHECK(nnInterpolator2 == gamma.getReferenceDoseInterpolator()); + CHECK(nnInterpolator2->getAccessorPointer() == refDose); + + gamma.setReferenceDoseInterpolator(nullptr); + CHECK(nullptr != dynamic_cast(gamma.getDoseInterpolator().get())); + CHECK(gamma.getDoseInterpolator()->getAccessorPointer() == simpleDose); + CHECK(nullptr != dynamic_cast(gamma.getReferenceDoseInterpolator().get())); + CHECK(gamma.getReferenceDoseInterpolator()->getAccessorPointer() == refDose); + + //CHECK other settings + CHECK_EQUAL(3., gamma.getDistanceToAgreementThreshold()); + CHECK_EQUAL(0.03, gamma.getDoseDifferenceThreshold()); + CHECK_EQUAL(1.0, gamma.getSearchSamplingRate().x()); + CHECK_EQUAL(1.0, gamma.getSearchSamplingRate().y()); + CHECK_EQUAL(1.0, gamma.getSearchSamplingRate().z()); + CHECK_EQUAL(true, gamma.getUseLocalDose()); + CHECK_EQUAL(0., gamma.getGlobalDose()); + + gamma.setDistanceToAgreementThreshold(2.); + CHECK_EQUAL(2., gamma.getDistanceToAgreementThreshold()); + CHECK_EQUAL(0.03, gamma.getDoseDifferenceThreshold()); + CHECK_EQUAL(1.0, gamma.getSearchSamplingRate().x()); + CHECK_EQUAL(1.0, gamma.getSearchSamplingRate().y()); + CHECK_EQUAL(1.0, gamma.getSearchSamplingRate().z()); + CHECK_EQUAL(true, gamma.getUseLocalDose()); + CHECK_EQUAL(0., gamma.getGlobalDose()); + + gamma.setDoseDifferenceThreshold(0.1); + CHECK_EQUAL(2., gamma.getDistanceToAgreementThreshold()); + CHECK_EQUAL(0.1, gamma.getDoseDifferenceThreshold()); + CHECK_EQUAL(1.0, gamma.getSearchSamplingRate().x()); + CHECK_EQUAL(1.0, gamma.getSearchSamplingRate().y()); + CHECK_EQUAL(1.0, gamma.getSearchSamplingRate().z()); + CHECK_EQUAL(true, gamma.getUseLocalDose()); + CHECK_EQUAL(0., gamma.getGlobalDose()); + + gamma.setSearchSamplingRate(3.0,3.0,3.0); + CHECK_EQUAL(2., gamma.getDistanceToAgreementThreshold()); + CHECK_EQUAL(0.1, gamma.getDoseDifferenceThreshold()); + CHECK_EQUAL(3.0, gamma.getSearchSamplingRate().x()); + CHECK_EQUAL(3.0, gamma.getSearchSamplingRate().y()); + CHECK_EQUAL(3.0, gamma.getSearchSamplingRate().z()); + CHECK_EQUAL(true, gamma.getUseLocalDose()); + CHECK_EQUAL(0., gamma.getGlobalDose()); + + gamma.setSearchSamplingRate(1.0, 1.0, 1.0); + gamma.setUseLocalDose(false); + CHECK_EQUAL(2., gamma.getDistanceToAgreementThreshold()); + CHECK_EQUAL(0.1, gamma.getDoseDifferenceThreshold()); + CHECK_EQUAL(1.0, gamma.getSearchSamplingRate().x()); + CHECK_EQUAL(1.0, gamma.getSearchSamplingRate().y()); + CHECK_EQUAL(1.0, gamma.getSearchSamplingRate().z()); + CHECK_EQUAL(false, gamma.getUseLocalDose()); + CHECK_EQUAL(0., gamma.getGlobalDose()); + + gamma.setGlobalDose(42.); + CHECK_EQUAL(2., gamma.getDistanceToAgreementThreshold()); + CHECK_EQUAL(0.1, gamma.getDoseDifferenceThreshold()); + CHECK_EQUAL(1.0, gamma.getSearchSamplingRate().x()); + CHECK_EQUAL(1.0, gamma.getSearchSamplingRate().y()); + CHECK_EQUAL(1.0, gamma.getSearchSamplingRate().z()); + CHECK_EQUAL(false, gamma.getUseLocalDose()); + CHECK_EQUAL(42., gamma.getGlobalDose()); + } + + void Test_Computation() + { + PREPARE_DEFAULT_TEST_REPORTING; + + std::cout << "Test values" << std::endl; + + auto nnInterpolator = boost::make_shared(); + auto nnInterpolator2 = boost::make_shared(); + + OrientationMatrix testOM(0); + testOM(0, 0) = 1.0; + testOM(1, 1) = 1.0; + testOM(2, 2) = 1.0; + + core::GeometricInfo geoInfo_4_05; + geoInfo_4_05.setImageSize({ 8,8,1 }); + geoInfo_4_05.setSpacing({ 1.0,1.0,1.0 }); + geoInfo_4_05.setOrientationMatrix(testOM); + + auto doseValues4 = std::vector({ 4.75, 4.75, 4.75, 4.75,4.75, 4.75, 4.75, 4.75, + 4.80, 4.80, 4.80, 4.80,4.80, 4.80, 4.80, 4.80, + 4.85, 4.85, 4.85, 4.85,4.85, 4.85, 4.85, 4.85, + 4.9 , 4.9 , 4.9 , 4.9 ,4.9 , 4.9 , 4.9 , 4.9 , + 4.95, 4.95, 4.95, 4.95,4.95, 4.95, 4.95, 4.95, + 5., 5., 5., 5., 5., 5., 5., 5., + 5.05, 5.05, 5.05, 5.05, 5.05, 5.05, 5.05, 5.05, + 5.1, 5.1, 5.1, 5.1, 5.1, 5.1, 5.1, 5.1 }); + auto doseRefValues4 = std::vector({ 4.75, 4.8, 4.85, 4.9 , 4.95, 5., 5.05, 5.10, + 4.75, 4.8, 4.85, 4.9 , 4.95, 5., 5.05, 5.10, + 4.75, 4.8, 4.85, 4.9 , 4.95, 5., 5.05, 5.10, + 4.75, 4.8, 4.85, 4.9 , 4.95, 5., 5.05, 5.10, + 4.75, 4.8, 4.85, 4.9 , 4.95, 5., 5.05, 5.10, + 4.75, 4.8, 4.85, 4.9 , 4.95, 5., 5.05, 5.10, + 4.75, 4.8, 4.85, 4.9 , 4.95, 5., 5.05, 5.10, + 4.75, 4.8, 4.85, 4.9 , 4.95, 5., 5.05, 5.10 }); + + core::DoseAccessorInterface::ConstPointer dose4 = boost::make_shared(doseRefValues4, geoInfo_4_05); + core::DoseAccessorInterface::ConstPointer refDose4 = boost::make_shared(doseValues4, geoInfo_4_05); + + //threshold 2 difference 3 spacing 1 + auto result_2_3_1 = std::vector({ + 0, 0.333333, 0.600925, 0.833333, 1, 1, 1, 1, + 0.333333, 0, 0.333333, 0.600925, 0.833333, 1, 1, 1, + 0.600925, 0.333333, 0, 0.333333, 0.600925, 0.833333, 1, 1, + 0.833333, 0.600925, 0.333333, 0, 0.333333, 0.600925, 0.833333, 1, + 1, 0.833333, 0.600925, 0.333333, 0, 0.333333, 0.600925, 0.833333, + 1, 1, 0.833333, 0.600925, 0.333333, 0, 0.333333, 0.600925, + 1, 1, 1, 0.833333, 0.600925, 0.333333, 0, 0.333333, + 1, 1, 1, 1, 0.833333, 0.600925, 0.333333, 0 + }); + + //threshold 2 difference 3 spacing 05 + auto result_2_3_05 = std::vector({ + 0, 0.300463, 0.559017, 0.833333, 1, 1, 1, 1, + 0.300463, 0, 0.300463, 0.559017, 0.833333, 1, 1, 1, + 0.559017, 0.300463, 0, 0.300463, 0.559017, 0.833333, 1, 1, + 0.833333, 0.559017, 0.300463, 0, 0.300463, 0.559017, 0.833333, 1, + 1, 0.833333, 0.559017, 0.300463, 0, 0.300463, 0.559017, 0.833333, + 1, 1, 0.833333, 0.559017, 0.300463, 0, 0.300463, 0.559017, + 1, 1, 1, 0.833333, 0.559017, 0.300463, 0, 0.300463, + 1, 1, 1, 1, 0.833333, 0.559017, 0.300463, 0 + }); + + //threshold 3 difference 3 spacing 1 + auto result_3_3_1 = std::vector({ + 0, 0.333333, 0.471405, 0.745356, 0.942809, 1, 1, 1, + 0.333333, 0, 0.333333, 0.471405, 0.745356, 0.942809, 1, 1, + 0.471405, 0.333333, 0, 0.333333, 0.471405, 0.745356, 0.942809, 1, + 0.745356, 0.471405, 0.333333, 0, 0.333333, 0.471405, 0.745356, 0.942809, + 0.942809, 0.745356, 0.471405, 0.333333, 0, 0.333333, 0.471405, 0.745356, + 1, 0.942809, 0.745356, 0.471405, 0.333333, 0, 0.333333, 0.471405, + 1, 1, 0.942809, 0.745356, 0.471405, 0.333333, 0, 0.333333, + 1, 1, 1, 0.942809, 0.745356, 0.471405, 0.333333, 0 + }); + + indices::GammaIndex gamma1(dose4, refDose4); + gamma1.setDoseInterpolator(nnInterpolator); + gamma1.setReferenceDoseInterpolator(nnInterpolator2); + gamma1.setDistanceToAgreementThreshold(2.0); + gamma1.setDoseDifferenceThreshold(0.03); + gamma1.setSearchSamplingRate(1., 1., 1.); + gamma1.setUseLocalDose(false); + gamma1.setGlobalDose(5.0); + + indices::GammaIndex gamma2(dose4, refDose4); + gamma2.setDoseInterpolator(nnInterpolator); + gamma2.setReferenceDoseInterpolator(nnInterpolator2); + gamma2.setDistanceToAgreementThreshold(2.0); + gamma2.setDoseDifferenceThreshold(0.03); + gamma2.setSearchSamplingRate(.5, .5, .5); + gamma2.setUseLocalDose(false); + gamma2.setGlobalDose(5.0); + + indices::GammaIndex gamma3(dose4, refDose4); + gamma3.setDoseInterpolator(nnInterpolator); + gamma3.setReferenceDoseInterpolator(nnInterpolator2); + gamma3.setDistanceToAgreementThreshold(3.0); + gamma3.setDoseDifferenceThreshold(0.03); + gamma3.setSearchSamplingRate(1., 1., 1.); + gamma3.setUseLocalDose(false); + gamma3.setGlobalDose(5.0); + + std::vector result1,result2,result3; + IndexFacade index1(&gamma1); + IndexFacade index2(&gamma2); + IndexFacade index3(&gamma3); + + for (int i = 0; i < geoInfo_4_05.getNumberOfVoxels(); i++) + { + // std::cout << index[i] << ","; + result1.push_back(index1[i]); + result2.push_back(index2[i]); + result3.push_back(index3[i]); + } + CHECK_ARRAY_CLOSE(result_2_3_1, result1, doseRefValues4.size(), 1.0e-5); + CHECK_ARRAY_CLOSE(result_2_3_05, result2, doseRefValues4.size(),1.0e-5); + CHECK_ARRAY_CLOSE(result_3_3_1, result3, doseRefValues4.size(), 1.0e-5); + } + + /*! @brief Test of GammaIndex.*/ + int GammaIndexTest(int /*argc*/, char* /*argv*/[]) + { + PREPARE_DEFAULT_TEST_REPORTING; + + Test_Initialization(); + Test_Computation(); + + + RETURN_AND_REPORT_TEST_SUCCESS; + } + + }//testing +}//rttb \ No newline at end of file diff --git a/testing/indices/files.cmake b/testing/indices/files.cmake index 27624aa..81004cd 100644 --- a/testing/indices/files.cmake +++ b/testing/indices/files.cmake @@ -1,11 +1,12 @@ SET(CPP_FILES rttbIndicesTests.cpp ConformationNumberTest.cpp ConformalIndexTest.cpp ConformityIndexTest.cpp CoverageIndexTest.cpp HomogeneityIndexTest.cpp + GammaIndexTest.cpp ) SET(H_FILES ) diff --git a/testing/indices/rttbIndicesTests.cpp b/testing/indices/rttbIndicesTests.cpp index e79fc79..44068d4 100644 --- a/testing/indices/rttbIndicesTests.cpp +++ b/testing/indices/rttbIndicesTests.cpp @@ -1,58 +1,59 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ // 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(ConformationNumberTest); LIT_REGISTER_TEST(ConformalIndexTest); LIT_REGISTER_TEST(ConformityIndexTest); LIT_REGISTER_TEST(CoverageIndexTest); LIT_REGISTER_TEST(HomogeneityIndexTest); + LIT_REGISTER_TEST(GammaIndexTest); } } } int main(int argc, char* argv[]) { int result = 0; rttb::testing::registerTests(); try { result = lit::multiTestsMain(argc, argv); } catch (...) { result = -1; } return result; } diff --git a/testing/io/other/CMakeLists.txt b/testing/io/other/CMakeLists.txt index 3c651d3..191f664 100644 --- a/testing/io/other/CMakeLists.txt +++ b/testing/io/other/CMakeLists.txt @@ -1,17 +1,17 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(OTHERIO_TEST ${EXECUTABLE_OUTPUT_PATH}/${RTToolbox_PREFIX}OtherIOTests) SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) #----------------------------------------------------------------------------- ADD_TEST(DoseStatisticsIOTest ${OTHERIO_TEST} DoseStatisticsIOTest) ADD_TEST(DVHXMLIOTest ${OTHERIO_TEST} DVHXMLIOTest) -RTTB_CREATE_TEST_MODULE(OtherIO DEPENDS RTTBOtherIO PACKAGE_DEPENDS Boost|filesystem Litmus RTTBData) +RTTB_CREATE_TEST_MODULE(OtherIO DEPENDS RTTBOtherIO RTTBTestHelper PACKAGE_DEPENDS Boost|filesystem Litmus RTTBData) diff --git a/testing/io/other/DVHXMLIOTest.cpp b/testing/io/other/DVHXMLIOTest.cpp index eb7647c..095ca2b 100644 --- a/testing/io/other/DVHXMLIOTest.cpp +++ b/testing/io/other/DVHXMLIOTest.cpp @@ -1,101 +1,101 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ // 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 "rttbBaseType.h" #include "rttbDVH.h" #include "rttbDVHSet.h" #include "rttbDVHXMLFileReader.h" #include "rttbDVHXMLFileWriter.h" #include "rttbInvalidParameterException.h" #include "rttbNullPointerException.h" -#include "../../core/DummyDVHGenerator.h" +#include "DummyDVHGenerator.h" #include "CompareDVH.h" namespace rttb { namespace testing { /*! @brief DVHXMLIOTest - test the IO for DVH xml data 1) test writing dvh to xml file 2) test reading DVH from xml file */ int DVHXMLIOTest(int argc, char* argv[]) { typedef core::DVH::Pointer DVHPointer; PREPARE_DEFAULT_TEST_REPORTING; /* generate dummy DVH */ const IDType structureIDPrefix = "myStructure"; const IDType doseID = "myDose"; DummyDVHGenerator dvhGenerator; DVHPointer spMyDVH = boost::make_shared(dvhGenerator.generateDVH(structureIDPrefix, doseID)); // 1) test writing DVH to xml file DVHType typeCum = {DVHType::Cumulative}; DVHType typeDiff = {DVHType::Differential}; FileNameString fN1 = "test.xml"; CHECK_NO_THROW(io::other::DVHXMLFileWriter(fN1, typeDiff)); CHECK_NO_THROW(io::other::DVHXMLFileWriter(fN1, typeCum)); io::other::DVHXMLFileWriter dvhWriter(fN1, typeCum); CHECK_EQUAL(fN1, dvhWriter.getFileName()); FileNameString fN2 = "otherFile.xml"; CHECK_NO_THROW(dvhWriter.setFileName(fN2)); CHECK_EQUAL(fN2, dvhWriter.getFileName()); CHECK_EQUAL(DVHType::Cumulative, dvhWriter.getDVHType().Type); CHECK_NO_THROW(dvhWriter.setDVHType(typeDiff)); CHECK_EQUAL(DVHType::Differential, dvhWriter.getDVHType().Type); DVHPointer emptyDvh; CHECK_THROW_EXPLICIT(dvhWriter.writeDVH(emptyDvh), core::NullPointerException); //CHECK_THROW_EXPLICIT(dvhWriter.writeDVH(spMyDVH), core::InvalidParameterException); CHECK_NO_THROW(dvhWriter.setDVHType(typeDiff)); CHECK_NO_THROW(dvhWriter.writeDVH(spMyDVH)); // 2) test reading DVH from xml file io::other::DVHXMLFileReader dvhReader(fN2); DVHPointer importedDVH = dvhReader.generateDVH(); CHECK_EQUAL(*importedDVH, *spMyDVH); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/other/DoseStatisticsIOTest.cpp b/testing/io/other/DoseStatisticsIOTest.cpp index 16ab4c2..930f43a 100644 --- a/testing/io/other/DoseStatisticsIOTest.cpp +++ b/testing/io/other/DoseStatisticsIOTest.cpp @@ -1,131 +1,131 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html [^] // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ // 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 #include #include "litCheckMacros.h" #include "rttbDoseStatistics.h" #include "rttbDoseStatisticsCalculator.h" #include "rttbDoseStatisticsXMLWriter.h" #include "rttbDoseStatisticsXMLReader.h" #include "rttbGenericDoseIterator.h" #include "rttbDoseIteratorInterface.h" #include "rttbInvalidParameterException.h" #include "rttbNullPointerException.h" -#include "../../core/DummyDoseAccessor.h" +#include "DummyDoseAccessor.h" #include "CompareDoseStatistic.h" namespace rttb { namespace testing { /*! @brief DoseStatisticsIOTest - test the DoseStatisticsIO for dose statistics 1) test writing statistics to xml file 2) test reading statistics from XML file and compare DoseStatistics 3) test writing statistics to string */ int DoseStatisticsIOTest(int argc, char* argv[]) { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef core::DoseIteratorInterface::Pointer DoseIteratorPointer; PREPARE_DEFAULT_TEST_REPORTING; /* generate dummy dose */ boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DoseAccessorPointer spDoseAccessor(spTestDoseAccessor); boost::shared_ptr spTestDoseIterator = boost::make_shared(spDoseAccessor); DoseIteratorPointer spDoseIterator(spTestDoseIterator); rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator(spDoseIterator); auto myDoseStatsSimple = myDoseStatsCalculator.calculateDoseStatistics(); auto myDoseStatsComplex = myDoseStatsCalculator.calculateDoseStatistics(true); auto doseStatisticsXMLWriter = io::other::DoseStatisticsXMLWriter(); //1) test writing statistics to xml file CHECK_THROW_EXPLICIT(doseStatisticsXMLWriter.writeDoseStatistics(nullptr, "aFilename.txt"), core::NullPointerException); FileNameString filenameSimple = "testStatisticsSimple.xml"; CHECK_NO_THROW(doseStatisticsXMLWriter.writeDoseStatistics(myDoseStatsSimple, filenameSimple)); CHECK(boost::filesystem::exists(filenameSimple)); FileNameString filenameComplex = "testStatisticsComplex.xml"; CHECK_NO_THROW(doseStatisticsXMLWriter.writeDoseStatistics(myDoseStatsComplex, filenameComplex)); CHECK(boost::filesystem::exists(filenameComplex)); //2) test reading statistics from XML file and compare DoseStatistics io::other::DoseStatisticsXMLReader readerSimple= io::other::DoseStatisticsXMLReader(filenameSimple); boost::shared_ptr rereadSimplyDose; CHECK_NO_THROW(rereadSimplyDose = readerSimple.generateDoseStatistic()); CHECK(checkEqualDoseStatistic(myDoseStatsSimple, rereadSimplyDose)); io::other::DoseStatisticsXMLReader readerComplex = io::other::DoseStatisticsXMLReader(filenameComplex); boost::shared_ptr rereadComplexDose; CHECK_NO_THROW(rereadComplexDose = readerComplex.generateDoseStatistic()); CHECK(checkEqualDoseStatistic(myDoseStatsComplex, rereadComplexDose)); io::other::DoseStatisticsXMLReader readerInvalidFilename = io::other::DoseStatisticsXMLReader("invalidFilename.xml"); CHECK_THROW_EXPLICIT(readerInvalidFilename.generateDoseStatistic(), core::InvalidParameterException); //delete files again CHECK_EQUAL(std::remove(filenameSimple.c_str()), 0); CHECK_EQUAL(std::remove(filenameComplex.c_str()),0); //3) test writing statistics to string boost::property_tree::ptree ptSimple = doseStatisticsXMLWriter.writeDoseStatistics(myDoseStatsSimple); XMLString strSimple = doseStatisticsXMLWriter.writerDoseStatisticsToString(myDoseStatsSimple); CHECK_THROW_EXPLICIT(doseStatisticsXMLWriter.writerDoseStatisticsToString(nullptr), core::NullPointerException); boost::property_tree::ptree ptComplex = doseStatisticsXMLWriter.writeDoseStatistics(myDoseStatsComplex); XMLString strComplex = doseStatisticsXMLWriter.writerDoseStatisticsToString(myDoseStatsComplex); std::stringstream sstrSimple; boost::property_tree::xml_parser::write_xml(sstrSimple, ptSimple, boost::property_tree::xml_writer_make_settings('\t', 1)); CHECK_EQUAL(strSimple, sstrSimple.str()); std::stringstream sstrComplex; boost::property_tree::xml_parser::write_xml(sstrComplex, ptComplex, boost::property_tree::xml_writer_make_settings('\t', 1)); CHECK_EQUAL(strComplex, sstrComplex.str()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/other/files.cmake b/testing/io/other/files.cmake index 687ddb7..c4e9e8b 100644 --- a/testing/io/other/files.cmake +++ b/testing/io/other/files.cmake @@ -1,16 +1,12 @@ SET(CPP_FILES - ../../core/DummyDoseAccessor.cpp - ../../core/DummyDVHGenerator.cpp CompareDVH.cpp CompareDoseStatistic.cpp DoseStatisticsIOTest.cpp DVHXMLIOTest.cpp rttbIOTests.cpp ) SET(H_FILES - ../../core/DummyDoseAccessor.h - ../../core/DummyDVHGenerator.h CompareDVH.h CompareDoseStatistic.h ) diff --git a/testing/masks/BoostMaskTest.cpp b/testing/masks/BoostMaskTest.cpp index a88f2f4..985863e 100644 --- a/testing/masks/BoostMaskTest.cpp +++ b/testing/masks/BoostMaskTest.cpp @@ -1,247 +1,247 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include #include #include "litCheckMacros.h" #include "rttbBaseType.h" -#include "../core/DummyStructure.h" -#include "../core/DummyDoseAccessor.h" +#include "DummyStructure.h" +#include "DummyDoseAccessor.h" #include "rttbDicomDoseAccessor.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomFileStructureSetGenerator.h" #include "rttbDicomFileStructureSetGenerator.h" #include "rttbGenericDoseIterator.h" #include "rttbDVHCalculator.h" #include "rttbGenericMaskedDoseIterator.h" #include "rttbBoostMask.h" #include "rttbBoostMaskAccessor.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace testing { /*! @brief BoostMaskRedesignTest. 1) test constructors 2) test getRelevantVoxelVector 3) test getMaskAt */ int BoostMaskTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; typedef core::Structure::Pointer StructTypePointer; // generate test dose. geometric info: patient position (-25, -2, 35), center of the 1st.voxel boost::shared_ptr spTestDoseAccessor = boost::make_shared(); boost::shared_ptr geometricPtr = boost::make_shared (spTestDoseAccessor->getGeometricInfo()); DummyStructure myStructGenerator(spTestDoseAccessor->getGeometricInfo()); //generate test structure. contours are (-20,0.5,38.75); (-12.5,0.5,38.75); (-12.5,10.5,38.75); (-20,10.5,38.75); //(-20, 0.5, 41.25); (-12.5, 0.5, 41.25); (-12.5, 10.5, 41.25); (-20, 10.5, 41.25); core::Structure myTestStruct = myStructGenerator.CreateRectangularStructureCentered(2,3); StructTypePointer spMyStruct = boost::make_shared(myTestStruct); //generate test structure 2. contours are (-20,0.5,38.75); (-12.5,0.5,38.75); (-12.5,10.5,38.75); (-20,10.5,38.75); //(-20, 0.5, 40); (-12.5, 0.5, 40); (-12.5, 10.5, 40); (-20, 10.5, 40); core::Structure myTestStruct2 = myStructGenerator.CreateRectangularStructureCenteredContourPlaneThicknessNotEqualDosePlaneThickness(2); StructTypePointer spMyStruct2 = boost::make_shared(myTestStruct2); //generate test structure. contours are //(-20,0.5,38.75); (-12.5,0.5,38.75); (-12.5,10.5,38.75); (-20,10.5,38.75); //(-20, 0.5, 41.25); (-12.5, 0.5, 41.25); (-12.5, 10.5, 41.25); (-20, 10.5, 41.25); //(-20, 0.5, 48.75); (-12.5, 0.5, 48.75); (-12.5, 10.5, 48.75); (-20, 10.5, 48.75); //(-20, 0.5, 51.25); (-12.5, 0.5, 51.25); (-12.5, 10.5, 51.25); (-20, 10.5, 51.25); //to test calcVoxelizationThickness bug core::Structure myTestStruct3 = myStructGenerator.CreateRectangularStructureCentered(2, 3, 6, 7); StructTypePointer spMyStruct3 = boost::make_shared(myTestStruct3); //1) test BoostMask & BoostMaskAccessor constructor CHECK_NO_THROW(rttb::masks::boost::BoostMask(geometricPtr, spMyStruct)); rttb::masks::boost::BoostMask boostMask = rttb::masks::boost::BoostMask( geometricPtr, spMyStruct); CHECK_NO_THROW(rttb::masks::boost::BoostMaskAccessor(spMyStruct, spTestDoseAccessor->getGeometricInfo(), true)); rttb::masks::boost::BoostMaskAccessor boostMaskAccessor(spMyStruct, spTestDoseAccessor->getGeometricInfo(), true); //2) test getRelevantVoxelVector CHECK_NO_THROW(boostMask.getRelevantVoxelVector()); CHECK_NO_THROW(boostMaskAccessor.getRelevantVoxelVector()); //3) test getMaskAt const VoxelGridIndex3D inMask1(2, 1, 2); //corner between two contours slice -> volumeFraction = 0.25 const VoxelGridIndex3D inMask2(3, 4, 2); //inside between two contours slice ->volumeFraction = 1 const VoxelGridIndex3D inMask3(4, 5, 2); //side between two contours slice -> volumeFraction = 0.5 const VoxelGridIndex3D inMask4(2, 1, 1); //corner on the first contour slice -> volumeFraction = 0.25/2 = 0.125 const VoxelGridIndex3D inMask5(2, 1, 3); //corner on the last contour slice -> volumeFraction = 0.25/2 = 0.125 const VoxelGridIndex3D inMask6(3, 4, 1); //inside on the first contour slice ->volumeFraction = 1 /2 = 0.5 const VoxelGridIndex3D outMask1(7, 5, 4); const VoxelGridIndex3D outMask2(2, 1, 0); const VoxelGridIndex3D outMask3(2, 1, 4); VoxelGridID testId; double errorConstantBoostMask = 1e-7; core::MaskVoxel tmpMV1(0), tmpMV2(0); CHECK(boostMaskAccessor.getMaskAt(inMask1, tmpMV1)); geometricPtr->convert(inMask1, testId); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_CLOSE(0.25, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor.getMaskAt(inMask2, tmpMV1)); CHECK(geometricPtr->convert(inMask2, testId)); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(1, tmpMV1.getRelevantVolumeFraction()); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor.getMaskAt(inMask3, tmpMV1)); CHECK(geometricPtr->convert(inMask3, testId)); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_CLOSE(0.5, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor.getMaskAt(inMask4, tmpMV1)); CHECK(geometricPtr->convert(inMask4, testId)); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_CLOSE(0.125, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor.getMaskAt(inMask5, tmpMV1)); CHECK(geometricPtr->convert(inMask5, testId)); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_CLOSE(0.125, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor.getMaskAt(inMask6, tmpMV1)); CHECK(geometricPtr->convert(inMask6, testId)); CHECK(boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_CLOSE(0.5, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(!boostMaskAccessor.getMaskAt(outMask1, tmpMV1)); CHECK(geometricPtr->convert(outMask1, testId)); CHECK(!boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); CHECK(!boostMaskAccessor.getMaskAt(outMask2, tmpMV1)); CHECK(geometricPtr->convert(outMask2, testId)); CHECK(!boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); CHECK(!boostMaskAccessor.getMaskAt(outMask3, tmpMV1)); CHECK(geometricPtr->convert(outMask3, testId)); CHECK(!boostMaskAccessor.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); rttb::masks::boost::BoostMask boostMask2 = rttb::masks::boost::BoostMask( geometricPtr, spMyStruct2); CHECK_NO_THROW(boostMask2.getRelevantVoxelVector()); rttb::masks::boost::BoostMaskAccessor boostMaskAccessor2(spMyStruct2, spTestDoseAccessor->getGeometricInfo(), true); CHECK_NO_THROW(boostMaskAccessor2.getRelevantVoxelVector()); CHECK(boostMaskAccessor2.getMaskAt(inMask1, tmpMV1)); geometricPtr->convert(inMask1, testId); CHECK(boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); //corner, the first contour weight 0.25, the second contour weights 0.5 -> volumeFraction = 0.25*0.25 + 1.25*0.5 = 0.1875 CHECK_CLOSE(0.1875, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor2.getMaskAt(inMask2, tmpMV1)); CHECK(geometricPtr->convert(inMask2, testId)); CHECK(boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); //inside, the first contour weight 0.25, the second contour weights 0.5 -> ->volumeFraction = 1*0.25 + 1*0.5 = 0.75 CHECK_EQUAL(0.75, tmpMV1.getRelevantVolumeFraction()); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor2.getMaskAt(inMask3, tmpMV1)); CHECK(geometricPtr->convert(inMask3, testId)); CHECK(boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); //side the first contour weight 0.25, the second contour weights 0.5 -> ->volumeFraction = 0.5*0.25 + 0.5*0.5 = 0.75 CHECK_CLOSE(0.375, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor2.getMaskAt(inMask4, tmpMV1)); CHECK(geometricPtr->convert(inMask4, testId)); CHECK(boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); //corner on the first contour slice, weight 0.25 -> volumeFraction = 0.25*0.25 = 0.0625 CHECK_CLOSE(0.0625, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(boostMaskAccessor2.getMaskAt(inMask6, tmpMV1)); CHECK(geometricPtr->convert(inMask6, testId)); CHECK(boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); //inside on the first contour slice, weight 0.25 ->volumeFraction = 1 * 0.25 = 0.25 CHECK_CLOSE(0.25, tmpMV1.getRelevantVolumeFraction(), errorConstantBoostMask); CHECK_EQUAL(testId, tmpMV1.getVoxelGridID()); CHECK(!boostMaskAccessor2.getMaskAt(outMask1, tmpMV1)); CHECK(geometricPtr->convert(outMask1, testId)); CHECK(!boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); //CHECK_EQUAL(testId,tmpMV1.getVoxelGridID()); -> return value will not be valid outside the mask CHECK(!boostMaskAccessor2.getMaskAt(outMask2, tmpMV1)); CHECK(geometricPtr->convert(outMask2, testId)); CHECK(!boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); //CHECK_EQUAL(testId,tmpMV1.getVoxelGridID()); -> return value will not be valid outside the mask CHECK(!boostMaskAccessor2.getMaskAt(outMask3, tmpMV1)); CHECK(geometricPtr->convert(outMask3, testId)); CHECK(!boostMaskAccessor2.getMaskAt(testId, tmpMV2)); CHECK_EQUAL(tmpMV1, tmpMV2); CHECK_EQUAL(0, tmpMV1.getRelevantVolumeFraction()); //CHECK_EQUAL(testId,tmpMV1.getVoxelGridID()); -> return value will not be valid outside the mask //3) test calcVoxelizationThickness bug rttb::masks::boost::BoostMask boostMask3 = rttb::masks::boost::BoostMask( geometricPtr, spMyStruct3); CHECK_NO_THROW(boostMask3.getRelevantVoxelVector()); rttb::masks::boost::BoostMaskAccessor boostMaskAccessor3(spMyStruct3, spTestDoseAccessor->getGeometricInfo(), true); CHECK_NO_THROW(boostMaskAccessor3.getRelevantVoxelVector()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/masks/CMakeLists.txt b/testing/masks/CMakeLists.txt index c92918b..da6027f 100644 --- a/testing/masks/CMakeLists.txt +++ b/testing/masks/CMakeLists.txt @@ -1,20 +1,20 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(Boost_Mask_TESTS ${EXECUTABLE_OUTPUT_PATH}/${RTToolbox_PREFIX}MaskTests) SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) #----------------------------------------------------------------------------- ADD_TEST(BoostMaskTest ${Boost_Mask_TESTS} BoostMaskTest) -RTTB_CREATE_TEST_MODULE(Mask DEPENDS RTTBDicomIO RTTBMask PACKAGE_DEPENDS PRIVATE Boost|filesystem Litmus DCMTK) +RTTB_CREATE_TEST_MODULE(Mask DEPENDS RTTBDicomIO RTTBMask RTTBTestHelper PACKAGE_DEPENDS PRIVATE Boost|filesystem Litmus DCMTK) IF (CMAKE_COMPILER_IS_GNUCC) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fext-numeric-literals") ENDIF() \ No newline at end of file diff --git a/testing/masks/files.cmake b/testing/masks/files.cmake index faa8a36..755fb7d 100644 --- a/testing/masks/files.cmake +++ b/testing/masks/files.cmake @@ -1,13 +1,7 @@ SET(CPP_FILES - ../core/DummyStructure.cpp - ../core/DummyDoseAccessor.cpp - ../core/CreateTestStructure.cpp BoostMaskTest.cpp rttbBoostMaskTests.cpp ) SET(H_FILES - ../core/DummyStructure.h - ../core/CreateTestStructure.h - ../core/DummyDoseAccessor.h ) diff --git a/testing/models/BioModelScatterPlotTest.cpp b/testing/models/BioModelScatterPlotTest.cpp index 2b4c4fd..5acf3c7 100644 --- a/testing/models/BioModelScatterPlotTest.cpp +++ b/testing/models/BioModelScatterPlotTest.cpp @@ -1,233 +1,233 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #include #include #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbBaseTypeModels.h" #include "rttbBioModel.h" #include "rttbBioModelScatterPlots.h" -#include "../core/DummyDVHGenerator.h" +#include "DummyDVHGenerator.h" #include "DummyModel.h" #include "rttbIntegration.h" #include #include #include namespace rttb { namespace testing { typedef models::ScatterPlotType ScatterPlotType; /*! @brief BioModelScatterPlotTest. Test the scatterplot methods. 1) test if parameters are set correctly 2) test if scatterData contain each model value exactly once */ int BioModelScatterPlotTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //generate artificial DVH and corresponding statistical values DummyDVHGenerator dummyDVH; const IDType structureID = "myStructure"; const IDType doseID = "myDose"; core::DVH::Pointer dvhPtr = boost::make_shared(dummyDVH.generateDVH(structureID, doseID, 0, 2000)); //test Dummy Model models::BioModelParamType param1 = 0.35; models::BioModelParamType param2 = 0.023333333333333; models::BioModelParamType param3 = 10000000; //model values will be dose/normalisationDose DoseTypeGy normalisationDose = 10; rttb::models::DummyModel model(dvhPtr); model.resetCounters(); //default number of points is 100 CHECK_NO_THROW(models::getScatterPlotVary1Parameter(model, 0, param1, 0.5, normalisationDose)); model.resetCounters(); ScatterPlotType scatter = models::getScatterPlotVary1Parameter(model, 0, param1, 0.5, normalisationDose); //only 1st parameter should gave been changed CHECK_EQUAL(100, model.getSetParam1Count()); CHECK_EQUAL(0, model.getSetParam2Count()); CHECK_EQUAL(0, model.getSetParam3Count()); CHECK_EQUAL(100, model.getCalcCount()); // all model values should match the corresponding dose/normalizationDose ScatterPlotType::iterator iter; for (iter = scatter.begin(); iter != scatter.end(); ++iter) { double currentKey = iter->first; if ((currentKey / normalisationDose) != iter->second.first) { CHECK_EQUAL((currentKey / normalisationDose), iter->second.first); } } model.resetCounters(); //number of points is 50 CHECK_NO_THROW(models::getScatterPlotVary1Parameter(model, 1, param2, 0.25, normalisationDose, 50)); model.resetCounters(); scatter = models::getScatterPlotVary1Parameter(model, 1, param2, 0.25, normalisationDose, 50); //only 1st parameter should gave been changed CHECK_EQUAL(0, model.getSetParam1Count()); CHECK_EQUAL(50, model.getSetParam2Count()); CHECK_EQUAL(0, model.getSetParam3Count()); CHECK_EQUAL(50, model.getCalcCount()); // all model values should match the corresponding dose/normalizationDose for (iter = scatter.begin(); iter != scatter.end(); ++iter) { double currentKey = iter->first; if ((currentKey / normalisationDose) != iter->second.first) { CHECK_EQUAL((currentKey / normalisationDose), iter->second.first); } } model.resetCounters(); //number of points is 150 CHECK_NO_THROW(models::getScatterPlotVary1Parameter(model, 2, param3, 0.75, normalisationDose, 150)); model.resetCounters(); scatter = models::getScatterPlotVary1Parameter(model, 2, param3, 0.75, normalisationDose, 150); //only 1st parameter should gave been changed CHECK_EQUAL(0, model.getSetParam1Count()); CHECK_EQUAL(0, model.getSetParam2Count()); CHECK_EQUAL(150, model.getSetParam3Count()); CHECK_EQUAL(150, model.getCalcCount()); // all model values should match the corresponding dose/normalizationDose for (iter = scatter.begin(); iter != scatter.end(); ++iter) { double currentKey = iter->first; if ((currentKey / normalisationDose) != iter->second.first) { CHECK_EQUAL((currentKey / normalisationDose), iter->second.first); } } model.resetCounters(); std::vector paramIDVec; models::BioModel::ParamVectorType meanVec; models::BioModel::ParamVectorType varianceVec; paramIDVec.push_back(0); meanVec.push_back(1); varianceVec.push_back(0.6); paramIDVec.push_back(1); meanVec.push_back(10); varianceVec.push_back(0.5); paramIDVec.push_back(2); meanVec.push_back(100); varianceVec.push_back(0.4); //number of points is 50 CHECK_NO_THROW(models::getScatterPlotVaryParameters(model, paramIDVec, meanVec, varianceVec, normalisationDose, 50)); model.resetCounters(); scatter = models::getScatterPlotVaryParameters(model, paramIDVec, meanVec, varianceVec, normalisationDose, 50); //only 1st parameter should gave been changed CHECK_EQUAL(50, model.getSetParam1Count()); CHECK_EQUAL(50, model.getSetParam2Count()); CHECK_EQUAL(50, model.getSetParam3Count()); CHECK_EQUAL(50, model.getCalcCount()); // all model values should match the corresponding dose/normalizationDose for (iter = scatter.begin(); iter != scatter.end(); ++iter) { double currentKey = iter->first; if ((currentKey / normalisationDose) != iter->second.first) { CHECK_EQUAL((currentKey / normalisationDose), iter->second.first); } } model.resetCounters(); //test 2000 points CHECK_NO_THROW(models::getScatterPlotVaryParameters(model, paramIDVec, meanVec, varianceVec, normalisationDose, 10000)); //test iterativeIntegration /*std::string bedFileName="d:/Temp/bed.txt"; std::ifstream dvh_ifstr(bedFileName,std::ios::in); std::vector volumeV2; std::vector bedV2; //std::cout << "iterative integration"<< std::endl; if ( !dvh_ifstr.is_open() ) { std::cerr<< "DVH file name invalid: could not open the dvh file!"<> volume; volumeV2.push_back(volume); //std::cout << "("<< volume << ","; std::string lineSub2 = line.substr(found2+1,found3-found2-1); //std::cout << lineSub2 << std::endl; std::stringstream ss2(lineSub2); double bed; ss2 >> bed; bedV2.push_back(bed); //std::cout << bed << ");"; } } } struct rttb::models::TcpParams params={0.302101,0.08,10000000,volumeV2,bedV2}; double result = rttb::models::integrateTCP(0, params);*/ RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/models/CMakeLists.txt b/testing/models/CMakeLists.txt index 8aff449..bd0b5d3 100644 --- a/testing/models/CMakeLists.txt +++ b/testing/models/CMakeLists.txt @@ -1,19 +1,19 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(MODELS_TESTS ${EXECUTABLE_OUTPUT_PATH}/${RTToolbox_PREFIX}ModelTests) SET(MODELS_HEADER_TEST ${EXECUTABLE_OUTPUT_PATH}/${RTToolbox_PREFIX}ModelsHeaderTest) SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) #----------------------------------------------------------------------------- ADD_TEST(BioModelTest ${MODELS_TESTS} BioModelTest) ADD_TEST(BioModelScatterPlotTest ${MODELS_TESTS} BioModelScatterPlotTest) ADD_TEST(DvhBasedModelsTest ${MODELS_TESTS} DvhBasedModelsTest) ADD_TEST(LQModelAccessorTest ${MODELS_TESTS} LQModelAccessorTest "${TEST_DATA_ROOT}/Dose/DICOM/ConstantTwo.dcm" "${TEST_DATA_ROOT}/Dose/DICOM/LinearIncreaseX.dcm") -RTTB_CREATE_TEST_MODULE(Model DEPENDS RTTBModels RTTBDicomIO PACKAGE_DEPENDS Boost Litmus DCMTK RTTBData) +RTTB_CREATE_TEST_MODULE(Model DEPENDS RTTBModels RTTBDicomIO RTTBTestHelper PACKAGE_DEPENDS Boost Litmus DCMTK RTTBData) diff --git a/testing/models/files.cmake b/testing/models/files.cmake index ca92f5f..24dca6c 100644 --- a/testing/models/files.cmake +++ b/testing/models/files.cmake @@ -1,16 +1,14 @@ SET(CPP_FILES rttbModelsTest.cpp BioModelTest.cpp rttbScatterTester.cpp BioModelScatterPlotTest.cpp DummyModel.cpp - ../core/DummyDVHGenerator.cpp DvhBasedModelsTest.cpp LQModelAccessorTest.cpp ) SET(H_FILES rttbScatterTester.h DummyModel.h - ../core/DummyDVHGenerator.h )