diff --git a/code/core/rttbAccessorInterface.h b/code/core/rttbAccessorInterface.h index f09a5f7..08979c5 100644 --- a/code/core/rttbAccessorInterface.h +++ b/code/core/rttbAccessorInterface.h @@ -1,105 +1,100 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __ACCESSOR_INTERFACE_H #define __ACCESSOR_INTERFACE_H #include #include "rttbBaseType.h" #include "rttbGeometricInfo.h" #include "rttbIndexConversionInterface.h" #include "rttbCommon.h" #include #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class AccessorInterface @brief Interface for any sort of Accessor */ class RTTBCore_EXPORT AccessorInterface : public IndexConversionInterface { public: rttbClassMacro(AccessorInterface, IndexConversionInterface); private: AccessorInterface(const AccessorInterface&) = delete; //not implemented on purpose -> non-copyable AccessorInterface& operator=(const AccessorInterface&) = delete;//not implemented on purpose -> non-copyable public: AccessorInterface() = default; ~AccessorInterface() override = default; /*! @brief test if given ID is inside current dose grid */ bool validID(const VoxelGridID aID) const { return this->getGeometricInfo().validID(aID); }; /*! @brief test if given index is inside current dose grid */ bool validIndex(const VoxelGridIndex3D& aIndex) const { return this->getGeometricInfo().validIndex(aIndex); }; virtual const core::GeometricInfo& getGeometricInfo() const = 0; virtual GridSizeType getGridSize() const { return this->getGeometricInfo().getNumberOfVoxels(); }; virtual GenericValueType getValueAt(const VoxelGridID aID) const = 0; virtual GenericValueType getValueAt(const VoxelGridIndex3D& aIndex) const = 0; /*! @brief is true if dose is on a homogeneous grid @remarks Inhomogeneous grids are not supported at the moment, but if they will be supported in the future the interface does not need to change. */ virtual bool isGridHomogeneous() const { return true; } virtual const IDType getUID() const = 0; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbAccessorWithGeoInfoBase.cpp b/code/core/rttbAccessorWithGeoInfoBase.cpp index 8f5b140..1a13661 100644 --- a/code/core/rttbAccessorWithGeoInfoBase.cpp +++ b/code/core/rttbAccessorWithGeoInfoBase.cpp @@ -1,45 +1,38 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ - #include "rttbAccessorWithGeoInfoBase.h" namespace rttb { namespace core { const core::GeometricInfo& AccessorWithGeoInfoBase:: getGeometricInfo() const { return _geoInfo; } AccessorWithGeoInfoBase::~AccessorWithGeoInfoBase() = default; AccessorWithGeoInfoBase::AccessorWithGeoInfoBase() = default; } } diff --git a/code/core/rttbAccessorWithGeoInfoBase.h b/code/core/rttbAccessorWithGeoInfoBase.h index 044908b..d4d8fb0 100644 --- a/code/core/rttbAccessorWithGeoInfoBase.h +++ b/code/core/rttbAccessorWithGeoInfoBase.h @@ -1,62 +1,57 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __ACCESSOR_WITH_GEO_INFO_BASE_H #define __ACCESSOR_WITH_GEO_INFO_BASE_H #include "rttbAccessorInterface.h" #include "RTTBCoreExports.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class AccessorWithGeoInfoBase @brief Base class for all accessor implementations that have there own geometric info. */ class RTTBCore_EXPORT AccessorWithGeoInfoBase : public core::AccessorInterface { protected: virtual void assembleGeometricInfo()=0; core::GeometricInfo _geoInfo; public: ~AccessorWithGeoInfoBase() override; AccessorWithGeoInfoBase(); const core::GeometricInfo& getGeometricInfo() const override; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbBaseType.h b/code/core/rttbBaseType.h index e726eb5..d6d53d8 100644 --- a/code/core/rttbBaseType.h +++ b/code/core/rttbBaseType.h @@ -1,619 +1,613 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #ifndef __BASE_TYPE_NEW_H #define __BASE_TYPE_NEW_H #include #include #include #include #include #include #include #include #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { const double errorConstant = 1e-5; const double reducedErrorConstant = 0.0001; using UnsignedIndex1D = unsigned short; /*! @class UnsignedIndex3D @brief 3D index. */ class UnsignedIndex3D: public boost::numeric::ublas::vector { public: UnsignedIndex3D() : boost::numeric::ublas::vector(3,0) {} UnsignedIndex3D(const UnsignedIndex1D value) : boost::numeric::ublas::vector(3, value) {} UnsignedIndex3D(const UnsignedIndex1D xValue, const UnsignedIndex1D yValue, const UnsignedIndex1D zValue) : boost::numeric::ublas::vector(3, xValue) { (*this)(1) = yValue; (*this)(2) = zValue; } const UnsignedIndex1D x() const { return (*this)(0); } const UnsignedIndex1D y() const { return (*this)(1); } const UnsignedIndex1D z() const { return (*this)(2); } friend bool operator==(const UnsignedIndex3D& gi1, const UnsignedIndex3D& gi2) { if (gi1.size() != gi2.size()) { return false; } for (size_t i = 0; i < gi1.size(); i++) { if (gi1(i) != gi2(i)) { return false; } } return true; } friend std::ostream& operator<<(std::ostream& s, const UnsignedIndex3D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; return s; } }; using UnsignedIndexList = 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) {} WorldCoordinate3D(const WorldCoordinate value) : boost::numeric::ublas::vector(3, value) {} WorldCoordinate3D(const WorldCoordinate xValue, const WorldCoordinate yValue, const WorldCoordinate zValue) : boost::numeric::ublas::vector(3, xValue) { (*this)(1) = yValue; (*this)(2) = zValue; } WorldCoordinate3D(const WorldCoordinate3D& w): boost::numeric::ublas::vector(3) { (*this)(0) = w.x(); (*this)(1) = w.y(); (*this)(2) = w.z(); } const WorldCoordinate x() const { return (*this)(0); } const WorldCoordinate y() const { return (*this)(1); } const WorldCoordinate z() const { return (*this)(2); } //vector cross product (not included in boost.ublas) WorldCoordinate3D cross(WorldCoordinate3D aVector) const { WorldCoordinate3D result; WorldCoordinate x = (*this)(0); WorldCoordinate y = (*this)(1); WorldCoordinate z = (*this)(2); result(0) = y * aVector(2) - z * aVector(1); result(1) = z * aVector(0) - x * aVector(2); result(2) = x * aVector(1) - y * aVector(0); return result; } 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) { (*this)(0) = wc(0); (*this)(1) = wc(1); (*this)(2) = wc(2); return (*this); } WorldCoordinate3D operator-(const boost::numeric::ublas::vector wc) { return WorldCoordinate3D((*this)(0) - wc(0), (*this)(1) - wc(1), (*this)(2) - wc(2)); } WorldCoordinate3D operator+(const boost::numeric::ublas::vector wc) { return WorldCoordinate3D((*this)(0) + wc(0), (*this)(1) + wc(1), (*this)(2) + wc(2)); } friend bool operator==(const WorldCoordinate3D& wc1, const WorldCoordinate3D& wc2) { if (wc1.size() != wc2.size()) { return false; } for (size_t i = 0; i < wc1.size(); i++) { if (wc1(i) != wc2(i)) { return false; } } return true; } bool equalsAlmost(const WorldCoordinate3D& another, double 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 DoubleVoxelGridIndex3D = rttb::WorldCoordinate3D; using ImageSize = rttb::UnsignedIndex3D; 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) {} 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; } } 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) {} 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 UnsignedIndex3D& ui) { (*this)(0) = ui(0); (*this)(1) = ui(1); (*this)(2) = ui(2); return (*this); } friend bool operator==(const VoxelGridIndex3D& gi1, const VoxelGridIndex3D& gi2) { if (gi1.size() != gi2.size()) { return false; } for (size_t i = 0; i < gi1.size(); i++) { if (gi1(i) != gi2(i)) { return false; } } return true; } friend std::ostream& operator<<(std::ostream& s, const VoxelGridIndex3D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; return s; } }; /*! @class VoxelGridIndex3D @brief 2D voxel grid index. */ class VoxelGridIndex2D: public boost::numeric::ublas::vector { public: VoxelGridIndex2D() : boost::numeric::ublas::vector(2,0) {} 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/rttbDVH.cpp b/code/core/rttbDVH.cpp index 9ef8eb9..880fe12 100644 --- a/code/core/rttbDVH.cpp +++ b/code/core/rttbDVH.cpp @@ -1,394 +1,388 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include #include #include "rttbDVH.h" #include "rttbException.h" #include "rttbInvalidParameterException.h" #include "rttbUtils.h" namespace rttb { namespace core { DVH::~DVH() = default; DVH::DVH(const DataDifferentialType& aDataDifferential, const DoseTypeGy& aDeltaD, const DoseVoxelVolumeType& aDeltaV, const IDType& aStructureID, const IDType& aDoseID): DVH(aDataDifferential, aDeltaD, aDeltaV, aStructureID, aDoseID, "") { } DVH::DVH(const DataDifferentialType& aDataDifferential, DoseTypeGy aDeltaD, DoseVoxelVolumeType aDeltaV, const IDType& aStructureID, const IDType& aDoseID, const IDType& aVoxelizationID): _deltaD(aDeltaD), _deltaV(aDeltaV), _structureID(aStructureID), _doseID(aDoseID), _voxelizationID(aVoxelizationID) { _dataDifferential.clear(); _dataDifferential = aDataDifferential; this->init(); } DVH::DVH(const DVH& copy) : DVH(copy._dataDifferential, copy._deltaD, copy._deltaV, copy._structureID, copy._doseID, copy._voxelizationID) { _label = copy._label; } DVH& DVH::operator=(const DVH& copy) { if (this != ©) { _deltaD = copy._deltaD; _deltaV = copy._deltaV; _structureID = copy._structureID; _doseID = copy._doseID; _voxelizationID = copy._voxelizationID; _label = copy._label; _dataDifferential.clear(); _dataDifferential = copy._dataDifferential; } this->init(); return *this; } bool operator==(const DVH& aDVH, const DVH& otherDVH) { bool result; //larger error constant because especially numberOfVoxels differ quite a bit after serialization const double errorConstantDVH = 1e-4; result = valueIsClose(aDVH.getDeltaD(), otherDVH.getDeltaD(), errorConstantDVH); result = result && valueIsClose(aDVH.getDeltaV(), otherDVH.getDeltaV(), errorConstantDVH); result = result && (aDVH.getDoseID() == otherDVH.getDoseID()); result = result && (aDVH.getStructureID() == otherDVH.getStructureID()); result = result && (aDVH.getVoxelizationID() == otherDVH.getVoxelizationID()); result = result && valueIsClose(aDVH.getNumberOfVoxels(),otherDVH.getNumberOfVoxels(), errorConstantDVH); result = result && valueIsClose(aDVH.getMaximum(), otherDVH.getMaximum(), errorConstantDVH); result = result && valueIsClose(aDVH.getMinimum(), otherDVH.getMinimum(), errorConstantDVH); result = result && valueIsClose(aDVH.getMean(), otherDVH.getMean(), errorConstantDVH); result = result && (aDVH.getDataDifferential().size() == otherDVH.getDataDifferential().size()); if (!result) { return result; } for (size_t i = 0; i < aDVH.getDataDifferential().size(); i++) { result = result && valueIsClose(aDVH.getDataDifferential().at(i), otherDVH.getDataDifferential().at(i), errorConstantDVH); } return result; } std::ostream& operator<<(std::ostream& s, const DVH& aDVH) { s << "[ " << aDVH.getStructureID() << ", " << aDVH.getDoseID() << ", " << aDVH.getVoxelizationID() << "\n " << "Number of Voxels: " << aDVH.getNumberOfVoxels() << " " << "Minimum/Maximum/Mean/Standard deviation: " << aDVH.getMinimum() << ", " << aDVH.getMaximum() << ", " << aDVH.getMean() << ", " << aDVH.getStdDeviation() << " ]"; return s; } std::deque DVH::getDataDifferential() const { return _dataDifferential; } std::deque DVH::getDataCumulative() const { return _dataCumulative; } DoseVoxelVolumeType DVH::getDeltaV() const { return _deltaV; } DoseTypeGy DVH::getDeltaD() const { return _deltaD; } IDType DVH::getDoseID() const { return this->_doseID; } IDType DVH::getStructureID() const { return this->_structureID; } IDType DVH::getVoxelizationID() const { return this->_voxelizationID; } void DVH::setDoseID(IDType aDoseID) { _doseID = aDoseID; } void DVH::setStructureID(IDType aStrID) { _structureID = aStrID; } DoseStatisticType DVH::getMaximum() const { return _maximum; } DoseStatisticType DVH::getMinimum() const { return _minimum; } DoseStatisticType DVH::getMean() const { return _mean; } DVHVoxelNumber DVH::getNumberOfVoxels() const { return _numberOfVoxels; } DoseStatisticType DVH::getStdDeviation() const { return _stdDeviation; } DoseStatisticType DVH::getVariance() const { return _variance; } void DVH::init() { if (_deltaD == 0 || _deltaV == 0) { throw InvalidParameterException("DVH init error: neither _deltaD nor _deltaV must be zero!"); } if (this->_dataDifferential.empty()) { throw InvalidParameterException("DVH init error: data differential is empty!"); } double sum = 0; double squareSum = 0; _numberOfVoxels = 0; _maximum = 0; _minimum = 0; _dataCumulative.clear(); DataDifferentialType::iterator it; int i = 0; for (it = _dataDifferential.begin(); it != _dataDifferential.end(); ++it) { _numberOfVoxels += (*it); if ((*it) > 0) { _maximum = (i + 0.5) * this->_deltaD; } if ((_minimum == 0.0f) && ((*it) > 0)) { _minimum = (i + 0.5) * this->_deltaD; } sum += (*it) * (i + 0.5) * this->_deltaD; squareSum += (*it) * pow((i + 0.5) * this->_deltaD, 2); i++; } _mean = sum / _numberOfVoxels; _variance = (squareSum / _numberOfVoxels - _mean * _mean); _stdDeviation = pow(_variance, 0.5); this->calcCumulativeDVH(); } void DVH::calcCumulativeDVH() { _dataCumulative.clear(); DoseCalcType cumulativeDVHi = 0; for (auto valueItr = _dataDifferential.rbegin(); valueItr != _dataDifferential.rend(); ++valueItr) { cumulativeDVHi += *valueItr; _dataCumulative.push_front(cumulativeDVHi); } } DoseStatisticType DVH::getMedian() const { double median_voxel = 0; int median_i = 0; for (GridIndexType i = 0; i < this->_dataDifferential.size(); i++) { if (median_voxel < (_numberOfVoxels - median_voxel)) { median_voxel += _dataDifferential[i]; median_i = i; } } double median = (median_i + 0.5) * this->_deltaD; return median; } DoseStatisticType DVH::getModal() const { double modal_voxel = 0; int modal_i = 0; for (GridIndexType i = 0; i < this->_dataDifferential.size(); i++) { if (modal_voxel < _dataDifferential[i]) { modal_voxel = _dataDifferential[i]; modal_i = i; } } double modal = (modal_i + 0.5) * this->_deltaD; return modal; } VolumeType DVH::getVx(DoseTypeGy xDoseAbsolute) const { auto i = static_cast(xDoseAbsolute / _deltaD); if (i < _dataCumulative.size()) { VolumeType vx = (_dataCumulative.at(i)); vx = (vx * this->_deltaV); return vx; } else { return 0; } } DoseTypeGy DVH::getDx(VolumeType xVolumeAbsolute) const { GridIndexType i = 0; for (; i < _dataCumulative.size(); i++) { double volumeAbsoluteI = _dataCumulative[i] * this->_deltaV; if (xVolumeAbsolute > volumeAbsoluteI) { break; } } if (i <= _dataCumulative.size() && i > 0) { DoseTypeGy dx = (i - 1) * this->_deltaD; return dx; } else { return 0; } } VolumeType DVH::getAbsoluteVolume(int relativePercent) const { return (relativePercent * getNumberOfVoxels() * getDeltaV() / 100.0); } std::deque DVH::convertAbsoluteToRelative(bool isCumulative) const { DataDifferentialType relativeData, absoluteData; if (isCumulative) { absoluteData = getDataCumulative(); } else { absoluteData = getDataDifferential(); } for (std::deque::iterator it = absoluteData.begin(); it != absoluteData.end(); ++it) { relativeData.push_back((*it) / getNumberOfVoxels()); } return relativeData; } void DVH::setLabel(StructureLabel aLabel) { _label = aLabel; } StructureLabel DVH::getLabel() const { return _label; } std::map DVH::getNormalizedDVH(DVHType dvhType) const { std::map normalizedDVH; DataDifferentialType data; if (dvhType.Type == DVHType::Cumulative) { data = getDataCumulative(); } else { data = getDataDifferential(); } if (data.empty()) { throw InvalidParameterException("DVH data is empty. Can't retrieve normalized DVH"); } for (size_t i = 0; i < data.size(); i++) { normalizedDVH.insert(std::pair(i * getDeltaD(), data[i] * getDeltaV())); } return normalizedDVH; } }//end namespace core }//end namespace rttb diff --git a/code/core/rttbDVH.h b/code/core/rttbDVH.h index a86c416..59e75f3 100644 --- a/code/core/rttbDVH.h +++ b/code/core/rttbDVH.h @@ -1,218 +1,213 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __DVH_H #define __DVH_H #include #include #include #include "boost/shared_ptr.hpp" #include "rttbBaseType.h" #include "rttbCommon.h" #include "RTTBCoreExports.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class DVH @brief This is a class representing a dose volume histogram (DVH) */ class RTTBCore_EXPORT DVH { public: using DataDifferentialType = std::deque; rttbClassMacroNoParent(DVH); private: /*! @brief Differential dvh data index is the dose bin, value is the voxel number (sub voxel accuracy) of the dose bin */ DataDifferentialType _dataDifferential; /*! @brief Absolute dose value of a dose-bin in Gy */ DoseTypeGy _deltaD; /*! @brief Volume of a voxel in cm3 */ DoseVoxelVolumeType _deltaV; IDType _structureID; IDType _doseID; IDType _voxelizationID; StructureLabel _label; DoseStatisticType _maximum; DoseStatisticType _minimum; DoseStatisticType _mean; DoseStatisticType _modal; DVHVoxelNumber _numberOfVoxels; DoseStatisticType _median; DoseStatisticType _stdDeviation; DoseStatisticType _variance; DataDifferentialType _dataCumulative; /*! @brief DVH initialization The DVH is initialized and all statistical values are calculated. @throw if _deltaV or _deltaD are zero @throw is _data differential is empty */ void init(); /*! @brief Calculate the cumulative data of dvh */ void calcCumulativeDVH(); public: ~DVH(); /*! @throw if _deltaV or _deltaD are zero @throw is _data differential is empty */ DVH(const DataDifferentialType& aDataDifferential, const DoseTypeGy& aDeltaD, const DoseVoxelVolumeType& aDeltaV, const IDType& aStructureID, const IDType& aDoseID); /*! @throw if _deltaV or _deltaD are zero @throw is _data differential is empty */ DVH(const DataDifferentialType& aDataDifferential, DoseTypeGy aDeltaD, DoseVoxelVolumeType aDeltaV, const IDType& aStructureID, const IDType& aDoseID, const IDType& aVoxelizationID); DVH(const DVH& copy); /*! @throw if _deltaV or _deltaD are zero @throw is _data differential is empty */ DVH& operator=(const DVH& copy); /*! equality operator DVHs are considered equal if the following are equal (let alone double inconsistencies): - structureID - doseID - voxelizationID - number of voxels - Histogram entries. */ bool friend operator==(const DVH& aDVH, const DVH& otherDVH); friend std::ostream& operator<<(std::ostream& s, const DVH& aDVH); void setLabel(StructureLabel aLabel); StructureLabel getLabel() const; /*! @param relativeVolume default false-> Value is the voxel number of the dose bin; if true-> value is the relative volume % between 0 and 1, (the voxel number of this dose bin)/(number of voxels) @return Return differential data of the dvh (relative or absolute depending on the input parameter). */ DataDifferentialType getDataDifferential() const; /*! @param relativeVolume default false-> Value is the voxel number of the dose bin; if true-> value is the relative volume % between 0 and 1, (the voxel number of this dose bin)/(number of voxels) @return Return cumulative data of the dvh */ DataDifferentialType getDataCumulative() const; DoseVoxelVolumeType getDeltaV() const; DoseTypeGy getDeltaD() const; IDType getStructureID() const; IDType getDoseID() const; IDType getVoxelizationID() const; void setDoseID(IDType aDoseID); void setStructureID(IDType aStrID); /*! @brief Calculate number of the voxels (with sub voxel accuracy) @return Return -1 if not initialized */ DVHVoxelNumber getNumberOfVoxels() const; /*! @brief Get the maximum dose in Gy from dvh @return Return the maximum dose in Gy (i+0.5)*deltaD, i-the maximal dose-bin with volume>0 Return -1 if not initialized */ DoseStatisticType getMaximum() const; /*! @brief Get the minimum dose in Gy from dvh @return Return the minimum dose (i+0.5)*deltaD, i-the minimal dose-bin with volume>0 Return -1 if not initialized */ DoseStatisticType getMinimum() const; DoseStatisticType getMean() const; DoseStatisticType getMedian() const; DoseStatisticType getModal() const; DoseStatisticType getStdDeviation() const; DoseStatisticType getVariance() const; /*! @brief Get Vx the volume irradiated to >= x @return Return absolute Volume in absolute cm3 Return -1 if not initialized */ VolumeType getVx(DoseTypeGy xDoseAbsolute) const; /*! @brief Get Dx the minimal dose delivered to x @return Return absolute dose value in Gy Return -1 if not initialized */ DoseTypeGy getDx(VolumeType xVolumeAbsolute) const; /*! @brief Calculate the absolute volume in cm3 @param relativePercent 0~100, the percent of the whole volume */ VolumeType getAbsoluteVolume(int relativePercent) const; /*! @brief Convert absolute values relative to the total number of voxels */ DataDifferentialType convertAbsoluteToRelative(bool isCumulative = true) const; /* @brief Multiplies each values with its Delta value. Values depend on DVHType. @param The DVHType that is being used DVHType::Cumulative or DVHType::Differential */ std::map getNormalizedDVH(DVHType dvhType = { DVHType::Cumulative }) const; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbDVHCalculator.cpp b/code/core/rttbDVHCalculator.cpp index cbf9049..8c5e2ba 100644 --- a/code/core/rttbDVHCalculator.cpp +++ b/code/core/rttbDVHCalculator.cpp @@ -1,131 +1,124 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include #include "rttbDVHCalculator.h" #include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" - namespace rttb { namespace core { DVHCalculator::DVHCalculator(DoseIteratorPointer aDoseIterator, const IDType& aStructureID, const IDType& aDoseID, DoseTypeGy aDeltaD, const int aNumberOfBins) { if (aDoseIterator == nullptr) { throw NullPointerException("aDoseIterator must not be nullptr! "); } _doseIteratorPtr = aDoseIterator; _structureID = aStructureID; _doseID = aDoseID; if (aNumberOfBins <= 0 || aDeltaD < 0) { throw InvalidParameterException("aNumberOfBins/aDeltaD must be >0! "); } _numberOfBins = aNumberOfBins; _deltaD = aDeltaD; if (_deltaD == 0) { aDoseIterator->reset(); DoseTypeGy max = 0; while (aDoseIterator->isPositionValid()) { DoseTypeGy currentVal = 0; currentVal = aDoseIterator->getCurrentDoseValue(); if (currentVal > max) { max = currentVal; } aDoseIterator->next(); } _deltaD = (max * 1.5 / _numberOfBins); if (_deltaD == 0) { _deltaD = 0.1; } } } DVHCalculator::~DVHCalculator() = default; DVH::Pointer DVHCalculator::generateDVH() { std::deque dataDifferential(_numberOfBins, 0); // calculate DVH _doseIteratorPtr->reset(); while (_doseIteratorPtr->isPositionValid()) { DoseTypeGy currentVal = 0; FractionType voxelProportion = _doseIteratorPtr->getCurrentRelevantVolumeFraction(); currentVal = _doseIteratorPtr->getCurrentDoseValue(); auto dose_bin = static_cast(currentVal / _deltaD); if (dose_bin < _numberOfBins) { dataDifferential[dose_bin] += voxelProportion; } else { throw InvalidParameterException("_numberOfBins is too small: dose bin out of bounds! "); } _doseIteratorPtr->next(); } if (boost::dynamic_pointer_cast(_doseIteratorPtr)) { _dvh = boost::make_shared(dataDifferential, _deltaD, _doseIteratorPtr->getCurrentVoxelVolume(), _structureID, _doseID, _doseIteratorPtr->getVoxelizationID()); } else { _dvh = boost::make_shared(dataDifferential, _deltaD, _doseIteratorPtr->getCurrentVoxelVolume(), _structureID, _doseID); } return _dvh; } }//end namespace core }//end namespace rttb diff --git a/code/core/rttbDVHCalculator.h b/code/core/rttbDVHCalculator.h index 0139735..55973b1 100644 --- a/code/core/rttbDVHCalculator.h +++ b/code/core/rttbDVHCalculator.h @@ -1,82 +1,77 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __DVH_CALCULATOR_H #define __DVH_CALCULATOR_H #include "rttbBaseType.h" #include "rttbDoseIteratorInterface.h" #include "rttbMaskedDoseIteratorInterface.h" #include "rttbDVHGeneratorInterface.h" #include "RTTBCoreExports.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class DVHCalculator @brief Calculates a DVH for a given DoseIterator. */ class RTTBCore_EXPORT DVHCalculator : public DVHGeneratorInterface { public: using DoseIteratorPointer = core::DoseIteratorInterface::Pointer; using MaskedDoseIteratorPointer = core::MaskedDoseIteratorInterface::Pointer; DoseIteratorPointer _doseIteratorPtr; IDType _structureID; IDType _doseID; DoseTypeGy _deltaD; int _numberOfBins; /*! @brief Constructor. @param aDeltaD the absolute dose value in Gy for dose_bin [i,i+1). Optional, if aDeltaD==0, it will be calculated using aDeltaD=max(aDoseIterator)*1.5/aNumberOfBins @exception InvalidParameterException throw if _numberOfBins<=0 or _deltaD<0 */ DVHCalculator(DoseIteratorPointer aDoseIterator, const IDType& aStructureID, const IDType& aDoseID, const DoseTypeGy aDeltaD = 0, const int aNumberOfBins = 201); ~DVHCalculator(); /*! @brief Generate DVH @return Return new shared pointer of DVH. @exception InvalidParameterException throw if _numberOfBins invalid: _numberOfBins must be > max(aDoseIterator)/aDeltaD! */ DVH::Pointer generateDVH() override; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbDVHGeneratorInterface.h b/code/core/rttbDVHGeneratorInterface.h index 99a79a7..3c01907 100644 --- a/code/core/rttbDVHGeneratorInterface.h +++ b/code/core/rttbDVHGeneratorInterface.h @@ -1,57 +1,52 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __DVH_GENERATOR_INTERFACE_H #define __DVH_GENERATOR_INTERFACE_H #include #include "rttbDVH.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class DVHGeneratorInterface @brief Interface for all DVH generating classes */ class DVHGeneratorInterface { protected: core::DVH::Pointer _dvh; public: /*! @brief Generate DVH @return Return new shared pointer of DVH. */ virtual core::DVH::Pointer generateDVH() = 0; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbDVHSet.cpp b/code/core/rttbDVHSet.cpp index 9d7fc57..6dc83bd 100644 --- a/code/core/rttbDVHSet.cpp +++ b/code/core/rttbDVHSet.cpp @@ -1,223 +1,217 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include "rttbDVHSet.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace core { DVHSet::DVHSet(IDType aStructureSetID, IDType aDoseID) : _structureSetID(aStructureSetID), _doseID(aDoseID) {} DVHSet::DVHSet(DVHSetType aDVHTVSet, DVHSetType aDVHHTSet, IDType aStructureSetID, IDType aDoseID) { _dvhHTSet = aDVHHTSet; _dvhTVSet = aDVHTVSet; this->_structureSetID = aStructureSetID; this->_doseID = aDoseID; } DVHSet::DVHSet(DVHSetType aDVHTVSet, DVHSetType aDVHHTSet, DVHSetType aDVHWVSet, IDType aStructureSetID, IDType aDoseID) { _dvhHTSet = aDVHHTSet; _dvhTVSet = aDVHTVSet; _dvhWVSet = aDVHWVSet; this->_structureSetID = aStructureSetID; this->_doseID = aDoseID; } std::size_t DVHSet::size() const { return _dvhHTSet.size() + _dvhTVSet.size() + _dvhWVSet.size(); } void DVHSet::setStrSetID(IDType aStrSetID) { _structureSetID = aStrSetID; } void DVHSet::setDoseID(IDType aDoseID) { _doseID = aDoseID; } IDType DVHSet::getStrSetID() const { return _structureSetID; } IDType DVHSet::getDoseID() const { return _doseID; } DVH* DVHSet::getDVH(IDType structureID) { auto itTV = _dvhTVSet.begin(); for (; itTV != _dvhTVSet.end(); ++itTV) { if ((*(itTV)).getStructureID() == structureID) { return &(*itTV); } } auto itHT = _dvhHTSet.begin(); for (; itHT != _dvhHTSet.end(); ++itHT) { if ((*(itHT)).getStructureID() == structureID) { return &(*itHT); } } auto itWV = _dvhWVSet.begin(); for (; itWV != _dvhWVSet.end(); ++itWV) { if ((*(itWV)).getStructureID() == structureID) { return &(*itWV); } } std::cout << "No DVH with the structure id: " << structureID << " was found!" << std::endl; return nullptr; } void DVHSet::insert(DVH& aDvh, DVHRole aDVHRole) { if (aDVHRole.Type == DVHRole::TargetVolume) { _dvhTVSet.push_back(aDvh); } else if (aDVHRole.Type == DVHRole::HealthyTissue) { _dvhHTSet.push_back(aDvh); } else if (aDVHRole.Type == DVHRole::WholeVolume) { _dvhWVSet.push_back(aDvh); } else { throw core::InvalidParameterException("aDVHType must be TV or HT or WV!"); } } VolumeType DVHSet::getWholeVolume(DoseTypeGy aDoseAbsolute) const { VolumeType volume = this->getHealthyTissueVolume(aDoseAbsolute) + this->getTargetVolume( aDoseAbsolute); return volume; } VolumeType DVHSet::getHealthyTissueVolume(DoseTypeGy aDoseAbsolute) const { auto itHT = _dvhHTSet.begin(); VolumeType volume = 0; while (itHT != _dvhHTSet.end()) { VolumeType testVol = 0; DVH dvh = *(itHT); testVol = dvh.getVx(aDoseAbsolute); if (testVol >= 0) { volume += testVol; } ++itHT; } return volume; } VolumeType DVHSet::getTargetVolume(DoseTypeGy aDoseAbsolute) const { auto itTV = _dvhTVSet.begin(); VolumeType volume = 0; while (itTV != _dvhTVSet.end()) { VolumeType testVol = 0; DVH dvh = *(itTV); testVol = dvh.getVx(aDoseAbsolute); if (testVol >= 0) { volume += testVol; } ++itTV; } return volume; } bool operator==(const DVHSet& aDVHSet, const DVHSet& otherDVHSet) { if (aDVHSet.getStrSetID() != otherDVHSet.getStrSetID()) { return false; } if (aDVHSet.getDoseID() != otherDVHSet.getDoseID()) { return false; } if (aDVHSet.size() != otherDVHSet.size()) { return false; } return true; } std::ostream& operator<<(std::ostream& s, const DVHSet& aDVHSet) { s << "[ " << aDVHSet.getStrSetID() << ", " << aDVHSet.getDoseID() << " ]"; return s; } std::ostream& operator<<(std::ostream& s, const DVHSet::DVHSetType& aDVHSet) { s << "[ "; for (const auto & i : aDVHSet) { s << i; } s << " ]"; return s; } } } diff --git a/code/core/rttbDVHSet.h b/code/core/rttbDVHSet.h index 2c8f10a..62b4e1f 100644 --- a/code/core/rttbDVHSet.h +++ b/code/core/rttbDVHSet.h @@ -1,152 +1,146 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #ifndef __DVH_SET_H #define __DVH_SET_H #include #include #include #include "rttbCommon.h" #include "rttbBaseType.h" #include "rttbDVH.h" #include "RTTBCoreExports.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class DVHSet @brief This is a class representing a RT DVHSet including Target Volume and Organ at Risk. @details A DVHSet consists of three subsets: one for the target volume (_dvhTVSet), one for healthy tissue (_dvhHTSet), and one for the whole volume (_dvhWVSet). */ class RTTBCore_EXPORT DVHSet { public: rttbClassMacroNoParent(DVHSet) using DVHSetType = std::vector; using IndexType = DVHSetType::size_type; private: IDType _structureSetID; IDType _doseID; DVHSetType _dvhTVSet; DVHSetType _dvhHTSet; DVHSetType _dvhWVSet; public: DVHSet(IDType aStructureSetID = "", IDType aDoseID = ""); DVHSet(DVHSetType aDVHTVSet, DVHSetType aDVHHTSet, IDType aStructureSetID = "", IDType aDoseID = ""); DVHSet(DVHSetType aDVHTVSet, DVHSetType aDVHHTSet, DVHSetType aDVHWVSet, IDType aStructureSetID = "", IDType aDoseID = ""); /*! @brief Get the size of the DVHSet, that is the sum of the numbers of DVHs in all sub-sets. */ std::size_t size() const; void setStrSetID(IDType aStrSetID); void setDoseID(IDType aDoseID); IDType getStrSetID() const; IDType getDoseID() const; /*! @brief Get the DVH according to the structure ID @return Return nullptr if not found */ DVH* getDVH(IDType aStructureID); /*! @brief Insert a DVH object. @brief param aDVHType "TV" for target volume or "HT" for healthy tissue or "WV" for whole volume @exception InvalidParameterException Thrown if no valid DVHRole was given. */ void insert(DVH& aDvh, DVHRole aDVHRole); /*! @brief Get DVH subset for target volume */ const DVHSetType& getTargetVolumeSet() const { return _dvhTVSet; }; /*! @brief Get DVH subset for healthy tissue */ const DVHSetType& getHealthyTissueSet() const { return _dvhHTSet; }; /*! @brief Get DVH subset for whole volume */ const DVHSetType& getWholeVolumeSet() const { return _dvhWVSet; }; /*! @brief Get the whole volume irradiated to >= aDoseAbsolute */ VolumeType getWholeVolume(DoseTypeGy aDoseAbsolute) const; /*! @brief Get the healthy tissue volume irradiated to >= aDoseAbsolute @return Return -1 if DVH of _dvhHTSet init() failed */ VolumeType getHealthyTissueVolume(DoseTypeGy aDoseAbsolute) const; /*! @brief Get the target volume irradiated to >= aDoseAbsolute @return Return -1 if DVH of _dvhTVSet init() failed */ VolumeType getTargetVolume(DoseTypeGy aDoseAbsolute) const; /*! DVHSets are considered equal if they have the same structureSet, dose and voxelization ID and the number of DVHs are equal. */ bool friend operator==(const DVHSet& aDVHSet, const DVHSet& otherDVHSet); friend std::ostream& operator<<(std::ostream& s, const DVHSet& aDVHSet); friend std::ostream& operator<<(std::ostream& s, const DVHSetType& aDVHSet); }; bool operator==(const DVHSet& aDVHSet, const DVHSet& otherDVHSet); std::ostream& operator<<(std::ostream& s, const DVHSet& aDVHSet); std::ostream& operator<<(std::ostream& s, const DVHSet::DVHSetType& aDVHSet); } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbDataNotAvailableException.h b/code/core/rttbDataNotAvailableException.h index 2de51df..ebe6bf4 100644 --- a/code/core/rttbDataNotAvailableException.h +++ b/code/core/rttbDataNotAvailableException.h @@ -1,49 +1,42 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #ifndef __DATA_NOT_AVAILABLE_EXCEPTION_H #define __DATA_NOT_AVAILABLE_EXCEPTION_H #include #include "rttbException.h" #include "RTTBCoreExports.h" - namespace rttb { namespace core { /*! @class DataNotAvailableException @brief This exception will be thrown if the requested data is not available. */ class RTTBCore_EXPORT DataNotAvailableException : public Exception { public: DataNotAvailableException(const std::string& aWhat) : Exception(aWhat) {} }; } } #endif diff --git a/code/core/rttbDoseAccessorGeneratorBase.h b/code/core/rttbDoseAccessorGeneratorBase.h index 5808cc2..ece92d7 100644 --- a/code/core/rttbDoseAccessorGeneratorBase.h +++ b/code/core/rttbDoseAccessorGeneratorBase.h @@ -1,53 +1,48 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __DOSE_ACCESSOR_GENERATOR_BASE_H #define __DOSE_ACCESSOR_GENERATOR_BASE_H #include #include "rttbDoseAccessorGeneratorInterface.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class DoseAccessorGeneratorBase @brief Abstract class for all Dose Accessor generating classes */ class DoseAccessorGeneratorBase: public DoseAccessorGeneratorInterface { protected: /*! @brief Dose accessor which should be generated */ DoseAccessorPointer _doseAccessor; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbDoseAccessorGeneratorInterface.h b/code/core/rttbDoseAccessorGeneratorInterface.h index f58740b..b9c50f4 100644 --- a/code/core/rttbDoseAccessorGeneratorInterface.h +++ b/code/core/rttbDoseAccessorGeneratorInterface.h @@ -1,70 +1,65 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __DOSE_ACCESSOR_GENERATOR_INTERFACE_H #define __DOSE_ACCESSOR_GENERATOR_INTERFACE_H #include "rttbDoseAccessorInterface.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class DoseAccessorGeneratorInterface @brief Interface for all Dose Accessor generating classes */ class DoseAccessorGeneratorInterface { public: using DoseAccessorPointer = core::AccessorInterface::Pointer; private: DoseAccessorGeneratorInterface(const DoseAccessorGeneratorInterface&) = delete; //not implemented on purpose -> non-copyable DoseAccessorGeneratorInterface& operator=(const DoseAccessorGeneratorInterface&) = delete;//not implemented on purpose -> non-copyable protected: DoseAccessorGeneratorInterface() = default; virtual ~DoseAccessorGeneratorInterface() = default; public: /*! @brief Generate DoseAccessor @return Return shared pointer of DoseAccessor. */ virtual DoseAccessorPointer generateDoseAccessor() = 0; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbDoseAccessorInterface.h b/code/core/rttbDoseAccessorInterface.h index 311f693..12669df 100644 --- a/code/core/rttbDoseAccessorInterface.h +++ b/code/core/rttbDoseAccessorInterface.h @@ -1,43 +1,38 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __DOSE_ACCESSOR_INTERFACE_NEW_H #define __DOSE_ACCESSOR_INTERFACE_NEW_H #include "rttbAccessorInterface.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { using DoseAccessorInterface = rttb::core::AccessorInterface; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbDoseIteratorInterface.cpp b/code/core/rttbDoseIteratorInterface.cpp index 9ebe9f9..b0c3cf9 100644 --- a/code/core/rttbDoseIteratorInterface.cpp +++ b/code/core/rttbDoseIteratorInterface.cpp @@ -1,41 +1,35 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include "rttbDoseIteratorInterface.h" #include "rttbNullPointerException.h" namespace rttb { namespace core { DoseIteratorInterface::DoseIteratorInterface(DoseAccessorPointer aDoseAccessor) { if (aDoseAccessor == nullptr) { throw NullPointerException(" dose accessor pointer must not be nullptr!"); } _spDoseAccessor = aDoseAccessor; } }//end: namespace core }//end: namespace rttb diff --git a/code/core/rttbDoseIteratorInterface.h b/code/core/rttbDoseIteratorInterface.h index f4d5bae..4fe6915 100644 --- a/code/core/rttbDoseIteratorInterface.h +++ b/code/core/rttbDoseIteratorInterface.h @@ -1,105 +1,100 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __DOSE_ITERATOR_INTERFACE_NEW_H #define __DOSE_ITERATOR_INTERFACE_NEW_H #include "rttbBaseType.h" #include "rttbCommon.h" #include "rttbDoseAccessorInterface.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { class GeometricInfo; /*! @class DoseIteratorInterface @brief This class represents the dose iterator interface. */ class DoseIteratorInterface { public: rttbClassMacroNoParent(DoseIteratorInterface); using DoseAccessorPointer = DoseAccessorInterface::Pointer; private: DoseIteratorInterface(const DoseIteratorInterface&) = delete; //not implemented on purpose -> non-copyable DoseIteratorInterface& operator=(const DoseIteratorInterface&) = delete;//not implemented on purpose -> non-copyable DoseIteratorInterface() = default; protected: /*! @brief DoseAccessor to get access to actual dose data */ DoseAccessorPointer _spDoseAccessor; public: /*! @brief Constructor with a DoseIterator this should be the default for all implementations. */ DoseIteratorInterface(DoseAccessorPointer aDoseAccessor); virtual ~DoseIteratorInterface() = default; /*! @brief Set the iterator to the start of the dose. */ virtual bool reset() = 0; /*! @brief Move to next position. If this position is valid is not necessarily tested. */ virtual void next() = 0; virtual bool isPositionValid() const = 0; /*! @brief Return volume of one voxel (in cm3)*/ //previously getDeltaV() virtual DoseVoxelVolumeType getCurrentVoxelVolume() const = 0; virtual DoseTypeGy getCurrentDoseValue() const = 0; /*! @return If this is a masked dose iterator, return the voxel proportion inside a given structure, value 0~1; Otherwise, 1 */ virtual FractionType getCurrentRelevantVolumeFraction() const = 0; virtual VoxelGridID getCurrentVoxelGridID() const = 0; virtual IDType getVoxelizationID() const { return ""; }; IDType getDoseUID() const { return _spDoseAccessor->getUID(); }; }; //end class }//end: namespace core }//end: namespace rttb #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbException.h b/code/core/rttbException.h index e9728b2..bf6b25b 100644 --- a/code/core/rttbException.h +++ b/code/core/rttbException.h @@ -1,50 +1,44 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #ifndef __RTTBEXCEPTION_H #define __RTTBEXCEPTION_H #include #include #include "RTTBCoreExports.h" namespace rttb { namespace core { /*! @class Exception @brief Exception interface used by all RTToolbox exceptions. */ class RTTBCore_EXPORT Exception : public std::runtime_error { public: Exception(const std::string& aWhat) : runtime_error(aWhat) {}; }; } } #endif diff --git a/code/core/rttbExceptionMacros.h b/code/core/rttbExceptionMacros.h index cc28faf..a45ae35 100644 --- a/code/core/rttbExceptionMacros.h +++ b/code/core/rttbExceptionMacros.h @@ -1,101 +1,95 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include #include "rttbException.h" /*!@def rttbDefaultExceptionMacro * This macro is used to throw a basic ExceptionObject within an object method. * It will generate the exception message and throw the exception.\n * Use rttbDefaultExceptionStaticMacro() for other objects that do not compli with the api or for * static functions.\n * Use rttbExceptionMacro() if you want to specifiy a arbitrary exception class that should be thrown. * Example usage looks like: * rttbDefaultExceptionMacro(<< "this is an exception" << this->SomeVariable); * @ingroup Exception */ #define rttbDefaultExceptionMacro(x) \ { \ std::ostringstream message; \ message << "Exception: " \ << "(" << this << "): " x; \ ::rttb::core::Exception e_(message.str().c_str()); \ throw e_; /* Explicit naming to work around Intel compiler bug. */ \ } /*!@def rttbExceptionMacro * This macro is used to throw the passed exception class within an object method. * The macro presumes that the object owns a method this->GetNameOfClass().\n * The macro will set file name, line number and function signiture to the exception * and log the exception as error in the logbook before throwing it.\n * Use rttbExceptionStaticMacro() for other objects that do not compli with the api or for * static functions.\n * @sa mapGenericExceptionMacro * * Example usage looks like: * rttbExceptionMacro(AnExceptionClass, << "this is an exception" << this->SomeVariable); * @ingroup Exception */ #define rttbExceptionMacro( EType, x) \ { \ std::ostringstream message; \ message << "Exception: "\ << "(" << this << "): " x; \ EType e_(message.str().c_str()); \ throw e_; /* Explicit naming to work around Intel compiler bug. */ \ } /*!@def rttbDefaultExceptionStaticMacro * This macro is used to throw a basic ExceptionObject within a static method. * It will generate the exception message and throw the exception.\n * Use rttbExceptionStaticMacro() if you want to specifiy a arbitrary exception class that should be thrown. * Example usage looks like: * rttbDefaultExceptionMacro(<< "this is an exception" << SomeVariable); * @ingroup Exception */ #define rttbDefaultExceptionStaticMacro(x) \ { \ std::ostringstream message; \ message << "Exception: " x; \ ::rttb::core::Exception e_(message.str().c_str()); \ throw e_; /* Explicit naming to work around Intel compiler bug. */ \ } /*!@def rttbExceptionStaticMacro * This macro is used to throw the passed exception class within a static method. * The macro will set file name, line number and function signiture to the exception * and log the exception as error in the logbook before throwing it.\n * Use mapGenericExceptionMacro() for other objects that do not compli with the api or for * static functions.\n * @sa mapGenericExceptionMacro * * Example usage looks like: * rttbExceptionMacro(AnExceptionClass, << "this is an exception" << this->SomeVariable); * @ingroup Exception */ #define rttbExceptionStaticMacro( EType, x) \ { \ std::ostringstream message; \ message << "Exception: " x; \ EType e_(message.str().c_str()); \ throw e_; /* Explicit naming to work around Intel compiler bug. */ \ } diff --git a/code/core/rttbGenericDoseIterator.cpp b/code/core/rttbGenericDoseIterator.cpp index f883d48..8e318f6 100644 --- a/code/core/rttbGenericDoseIterator.cpp +++ b/code/core/rttbGenericDoseIterator.cpp @@ -1,93 +1,87 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include "rttbGenericDoseIterator.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace core { GenericDoseIterator::GenericDoseIterator(DoseAccessorPointer aDoseAccessor) : DoseIteratorInterface( aDoseAccessor) { _currentDoseVoxelGridID = 0; _currentVoxelVolume = 0; } bool GenericDoseIterator::reset() { _currentDoseVoxelGridID = 0; if (_spDoseAccessor->isGridHomogeneous()) { SpacingVectorType3D voxelSizeVec = (_spDoseAccessor->getGeometricInfo()).getSpacing(); _currentVoxelVolume = voxelSizeVec(0) * voxelSizeVec(1) * voxelSizeVec(2) / 1000; } else { _currentVoxelVolume = 0; throw InvalidParameterException("Inhomogeneous grids are currently not supported!"); } return true; } void GenericDoseIterator::next() { if (_spDoseAccessor->getGeometricInfo().getNumberOfVoxels() > _currentDoseVoxelGridID) { ++_currentDoseVoxelGridID; } } bool GenericDoseIterator::isPositionValid() const { return _spDoseAccessor->getGeometricInfo().validID(_currentDoseVoxelGridID); } DoseVoxelVolumeType GenericDoseIterator::getCurrentVoxelVolume() const { if (_spDoseAccessor->isGridHomogeneous()) { return _currentVoxelVolume; } else { throw InvalidParameterException("Inhomogeneous grids are currently not supported!"); } } DoseTypeGy GenericDoseIterator::getCurrentDoseValue() const { if (isPositionValid()) { return _spDoseAccessor->getValueAt(_currentDoseVoxelGridID); } else { return 0; } } }//end: namespace core }//end: namespace rttb \ No newline at end of file diff --git a/code/core/rttbGenericDoseIterator.h b/code/core/rttbGenericDoseIterator.h index 799b351..4c5a53d 100644 --- a/code/core/rttbGenericDoseIterator.h +++ b/code/core/rttbGenericDoseIterator.h @@ -1,111 +1,106 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __GENERIC_DOSE_ITERATOR_INTERFACE_NEW_H #define __GENERIC_DOSE_ITERATOR_INTERFACE_NEW_H #include #include #include #include "rttbBaseType.h" #include "rttbDoseIteratorInterface.h" #include "RTTBCoreExports.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class GenericDoseIterator @brief Standard implementation of the dose iterator interface. */ class RTTBCore_EXPORT GenericDoseIterator : public DoseIteratorInterface { public: using DoseAccessorPointer = DoseAccessorInterface::Pointer; using DoseIteratorPointer = DoseIteratorInterface::Pointer; private: VoxelGridID _currentDoseVoxelGridID; DoseVoxelVolumeType _currentVoxelVolume; GenericDoseIterator(const GenericDoseIterator&) = delete; //not implemented on purpose -> non-copyable GenericDoseIterator& operator=(const GenericDoseIterator&) = delete;//not implemented on purpose -> non-copyable public: /*! @brief Constructor @param aDoseAccessor contains the corresponding dose data */ GenericDoseIterator(DoseAccessorPointer aDoseAccessor); /*! @brief Set the itterator to the start of the Dose. @exception InvalidParameterException if a inhomogeneous grid is defined in the dose accessors, because these grids are currently not supported. */ bool reset() override; /*! @brief Test if next voxel position is still on the data grid, if so move to next position. */ void next() override; /*! @brief Determine if the current voxel position is valid. */ bool isPositionValid() const override; /*! @brief Return volume of one voxel (in cm3) @exception InvalidParameterException if a inhomogeneous grid is defined in the dose accessors, because these grids are currently not supported. */ DoseVoxelVolumeType getCurrentVoxelVolume() const override; DoseTypeGy getCurrentDoseValue() const override; /*! @brief For DoseIterators this function returns 1, always, because no mask is applied. */ inline FractionType getCurrentRelevantVolumeFraction() const override { return 1; }; inline VoxelGridID getCurrentVoxelGridID() const override { return _currentDoseVoxelGridID; }; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbGenericMaskedDoseIterator.cpp b/code/core/rttbGenericMaskedDoseIterator.cpp index cc7c34e..2424d06 100644 --- a/code/core/rttbGenericMaskedDoseIterator.cpp +++ b/code/core/rttbGenericMaskedDoseIterator.cpp @@ -1,100 +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. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include "rttbGenericMaskedDoseIterator.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace core { bool GenericMaskedDoseIterator::reset() { _maskVoxelVec = _spMask->getRelevantVoxelVector(); _currentMaskPos = _maskVoxelVec->begin(); core::GeometricInfo geoInfo = _spDoseAccessor->getGeometricInfo(); _currentVoxelVolume = geoInfo.getSpacing()(0) * geoInfo.getSpacing()(1) * geoInfo.getSpacing()( 2) / 1000; return true; } void GenericMaskedDoseIterator::next() { ++_currentMaskPos; } DoseVoxelVolumeType GenericMaskedDoseIterator::getCurrentVoxelVolume() const { if (_spDoseAccessor->isGridHomogeneous()) { return _currentVoxelVolume; } else { throw InvalidParameterException("Inhomogeneous grids are currently not supported! "); } } FractionType GenericMaskedDoseIterator::getCurrentRelevantVolumeFraction() const { if (!(_currentMaskPos == _maskVoxelVec->end())) { assert(_spMask->getGeometricInfo().validID(_currentMaskPos->getVoxelGridID())); return _currentMaskPos->getRelevantVolumeFraction(); } return 0; } bool GenericMaskedDoseIterator::isPositionValid() const { if (_currentMaskPos == _maskVoxelVec->end()) { return false; } return _spDoseAccessor->getGeometricInfo().validID(_currentMaskPos->getVoxelGridID()) && _spMask->getGeometricInfo().validID(_currentMaskPos->getVoxelGridID()); } VoxelGridID GenericMaskedDoseIterator::getCurrentVoxelGridID() const { return _currentMaskPos->getVoxelGridID(); } DoseTypeGy GenericMaskedDoseIterator::getCurrentMaskedDoseValue() const { assert(isPositionValid()); return getCurrentDoseValue() * getCurrentRelevantVolumeFraction(); } DoseTypeGy GenericMaskedDoseIterator::getCurrentDoseValue() const { assert(_spDoseAccessor->getGeometricInfo().validID(_currentMaskPos->getVoxelGridID())); return _spDoseAccessor->getValueAt(_currentMaskPos->getVoxelGridID()); } }//end namespace core }//end namespace rttb \ No newline at end of file diff --git a/code/core/rttbGenericMaskedDoseIterator.h b/code/core/rttbGenericMaskedDoseIterator.h index 9c97528..2af24e0 100644 --- a/code/core/rttbGenericMaskedDoseIterator.h +++ b/code/core/rttbGenericMaskedDoseIterator.h @@ -1,114 +1,109 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __GENERIC_MASKED_DOSE_ITERATOR_NEW_H #define __GENERIC_MASKED_DOSE_ITERATOR_NEW_H #include #include "rttbBaseType.h" #include "rttbMaskedDoseIteratorInterface.h" #include "rttbMaskAccessorInterface.h" #include "RTTBCoreExports.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class GenericMaskedDoseIterator @brief This is a templated class representing a generic masked dose iterator for a VoxelizationPolicy. @see testing/GenericMaskedDoseIteratorTest.cpp for more information. */ class RTTBCore_EXPORT GenericMaskedDoseIterator : public MaskedDoseIteratorInterface { public: using MaskVoxelListPointer = MaskAccessorInterface::MaskVoxelListPointer; using MaskVoxelList = MaskAccessorInterface::MaskVoxelList; using MaskAccessorPointer = MaskedDoseIteratorInterface::MaskAccessorPointer; using DoseAccessorPointer = MaskedDoseIteratorInterface::DoseAccessorPointer; private: using MaskVoxelListIterator = MaskVoxelList::const_iterator; /*! The current index position of the vector _maskVoxelVec*/ MaskVoxelListIterator _currentMaskPos; /*! vector of MaskVoxel, as defined in the voxelization*/ MaskVoxelListPointer _maskVoxelVec; /*! the volume in cm^3 of the current dose voxel*/ DoseVoxelVolumeType _currentVoxelVolume; public: GenericMaskedDoseIterator(MaskAccessorPointer aSpMask, DoseAccessorPointer aDoseAccessor) : MaskedDoseIteratorInterface(aSpMask, aDoseAccessor) {}; /*! @brief Set the position on the first index. Use also as initialization. */ bool reset() override; /*! move to next mask position. The validity of the position is not checked here. */ void next() override; /*! @brief Volume of one voxel (in cm3) @exception InvalidParameterException if a inhomogeneous grid is defined in the dose accessors, because these grids are currently not supported. */ DoseVoxelVolumeType getCurrentVoxelVolume() const override; FractionType getCurrentRelevantVolumeFraction() const override; inline MaskVoxelListPointer getMaskVoxelVec() const { return _maskVoxelVec; }; /*! Check first if the position inside the maskedVoxelVector is valid. If so, check if the gridID at the current position in the MaskedVoxelVector is valid in the dose and mask grid. */ bool isPositionValid() const override; /*! @brief get current VoxelGridID (on dose voxel grid)*/ VoxelGridID getCurrentVoxelGridID() const override; /*! @return current dose value multiplied by current volume fraction*/ DoseTypeGy getCurrentMaskedDoseValue() const override; /*! @return current dose value without masking*/ DoseTypeGy getCurrentDoseValue() const override; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbGeometricInfo.cpp b/code/core/rttbGeometricInfo.cpp index e402699..5d78d25 100644 --- a/code/core/rttbGeometricInfo.cpp +++ b/code/core/rttbGeometricInfo.cpp @@ -1,310 +1,304 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include "rttbGeometricInfo.h" #include #include #include namespace rttb { namespace core { void GeometricInfo::setSpacing(const SpacingVectorType3D& aSpacingVector) { _spacing = aSpacingVector; } const SpacingVectorType3D& GeometricInfo::getSpacing() const { return _spacing; } void GeometricInfo::setImagePositionPatient(const WorldCoordinate3D& aImagePositionPatient) { _imagePositionPatient = aImagePositionPatient; } const WorldCoordinate3D& GeometricInfo::getImagePositionPatient() const { return _imagePositionPatient; } void GeometricInfo::setOrientationMatrix(const OrientationMatrix& anOrientationMatrix) { _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::worldCoordinateToGeometryCoordinate(const WorldCoordinate3D& aWorldCoordinate, DoubleVoxelGridIndex3D& 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 = DoubleVoxelGridIndex3D(resultS(0), resultS(1), resultS(2)); //if we convert DoubleVoxelGridIndex3D (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 { DoubleVoxelGridIndex3D doubleIndex; bool inside = worldCoordinateToGeometryCoordinate(aWorldCoordinate, doubleIndex); aIndex = VoxelGridIndex3D(GridIndexType(doubleIndex(0)+0.5), GridIndexType(doubleIndex(1)+0.5), GridIndexType(doubleIndex(2)+0.5)); return inside; } bool GeometricInfo::geometryCoordinateToWorldCoordinate(const DoubleVoxelGridIndex3D& 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 DoubleVoxelGridIndex3D (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 { DoubleVoxelGridIndex3D indexDouble = DoubleVoxelGridIndex3D(aIndex(0), aIndex(1), aIndex(2)); return geometryCoordinateToWorldCoordinate(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 983c8e9..d4ea7e0 100644 --- a/code/core/rttbGeometricInfo.h +++ b/code/core/rttbGeometricInfo.h @@ -1,193 +1,187 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #ifndef __GEOMETRIC_INFO_NEW_H #define __GEOMETRIC_INFO_NEW_H #include #include #include "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; 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, DoubleVoxelGridIndex3D @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 worldCoordinateToGeometryCoordinate(const WorldCoordinate3D& aWorldCoordinate, DoubleVoxelGridIndex3D& 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 DoubleVoxelGridIndex3D, 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 geometryCoordinateToWorldCoordinate(const DoubleVoxelGridIndex3D& 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. */ friend std::ostream& operator << (std::ostream& s, const GeometricInfo& anGeometricInfo); }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbIndexConversionInterface.h b/code/core/rttbIndexConversionInterface.h index 5982e5f..36c7bc6 100644 --- a/code/core/rttbIndexConversionInterface.h +++ b/code/core/rttbIndexConversionInterface.h @@ -1,60 +1,55 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __INDEX_CONVERSION_INTERFACE_NEW_H #define __INDEX_CONVERSION_INTERFACE_NEW_H #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif #include namespace rttb { namespace core { /*! @class IndexConversionInterface @brief This class represents the conversion of 3D grid indices to 1D grid IDs. */ class IndexConversionInterface { public: rttbClassMacroNoParent(IndexConversionInterface); private: IndexConversionInterface(const IndexConversionInterface&) = delete; //not implemented on purpose -> non-copyable IndexConversionInterface& operator=(const IndexConversionInterface&) = delete;//not implemented on purpose -> non-copyable public: IndexConversionInterface() = default; virtual ~IndexConversionInterface() = default; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbIndexOutOfBoundsException.h b/code/core/rttbIndexOutOfBoundsException.h index 33dcdf3..c645f2f 100644 --- a/code/core/rttbIndexOutOfBoundsException.h +++ b/code/core/rttbIndexOutOfBoundsException.h @@ -1,47 +1,41 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #ifndef __INDEX_OUT_OF_BOUNDS_EXCEPTION_H #define __INDEX_OUT_OF_BOUNDS_EXCEPTION_H #include #include "rttbException.h" #include "RTTBCoreExports.h" namespace rttb { namespace core { /*! @class IndexOutOfBoundsException @brief This exception will be thrown if any index out of bound. */ class RTTBCore_EXPORT IndexOutOfBoundsException : public Exception { public: IndexOutOfBoundsException(const std::string& aWhat): Exception(aWhat) {} }; } } #endif diff --git a/code/core/rttbInvalidDoseException.h b/code/core/rttbInvalidDoseException.h index 84a9e4a..c815749 100644 --- a/code/core/rttbInvalidDoseException.h +++ b/code/core/rttbInvalidDoseException.h @@ -1,48 +1,42 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #ifndef __INVALID_DOSE_EXCEPTION_H #define __INVALID_DOSE_EXCEPTION_H #include #include "rttbException.h" #include "RTTBCoreExports.h" namespace rttb { namespace core { /*! @class InvalidDoseException @brief This exception will be thrown if dose is invalid. */ class RTTBCore_EXPORT InvalidDoseException : public Exception { public: InvalidDoseException(const std::string& aWhat): Exception(aWhat) {} }; } } #endif diff --git a/code/core/rttbInvalidParameterException.h b/code/core/rttbInvalidParameterException.h index e3b2aad..1d4d903 100644 --- a/code/core/rttbInvalidParameterException.h +++ b/code/core/rttbInvalidParameterException.h @@ -1,47 +1,41 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #ifndef __INVALID_PARAMETER_EXCEPTION_H #define __INVALID_PARAMETER_EXCEPTION_H #include #include "rttbException.h" #include "RTTBCoreExports.h" namespace rttb { namespace core { /*! @class InvalidParameterException @brief This exception will be thrown if any parameter is invalid. */ class RTTBCore_EXPORT InvalidParameterException : public Exception { public: InvalidParameterException(const std::string& aWhat): Exception(aWhat) {} }; } } #endif diff --git a/code/core/rttbMappingOutsideOfImageException.h b/code/core/rttbMappingOutsideOfImageException.h index e5d0b8a..7f97af1 100644 --- a/code/core/rttbMappingOutsideOfImageException.h +++ b/code/core/rttbMappingOutsideOfImageException.h @@ -1,49 +1,42 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #ifndef __MAPPING_OUTSIDE_OF_IMAGE_EXCEPTION_H #define __MAPPING_OUTSIDE_OF_IMAGE_EXCEPTION_H #include #include "rttbException.h" #include "RTTBCoreExports.h" - namespace rttb { namespace core { /*! @class MappingOutsideOfImageException @brief This exception will be thrown if a transformation leads to an invalid position outside of the image. */ class RTTBCore_EXPORT MappingOutsideOfImageException : public Exception { public: MappingOutsideOfImageException(const std::string& aWhat): Exception(aWhat) {} }; } } #endif diff --git a/code/core/rttbMaskAccessorGeneratorBase.h b/code/core/rttbMaskAccessorGeneratorBase.h index 87dbadd..250618d 100644 --- a/code/core/rttbMaskAccessorGeneratorBase.h +++ b/code/core/rttbMaskAccessorGeneratorBase.h @@ -1,62 +1,57 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __MASK_ACCESSOR_GENERATOR_BASE_H #define __MASK_ACCESSOR_GENERATOR_BASE_H #include "rttbMaskAccessorGeneratorInterface.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class MaskAccessorGeneratorBase @brief Abstract class for all DoseAccessor generating classes */ class MaskAccessorGeneratorBase: public MaskAccessorGeneratorInterface { public: using MaskAccessorPointer = core::MaskAccessorInterface::Pointer; private: protected: /*! @brief Mask accessor which should be generated */ MaskAccessorPointer _maskAccessor; public: }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbMaskAccessorGeneratorInterface.h b/code/core/rttbMaskAccessorGeneratorInterface.h index f750cce..7612996 100644 --- a/code/core/rttbMaskAccessorGeneratorInterface.h +++ b/code/core/rttbMaskAccessorGeneratorInterface.h @@ -1,70 +1,65 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __MASK_ACCESSOR_GENERATOR_INTERFACE_H #define __MASK_ACCESSOR_GENERATOR_INTERFACE_H #include "rttbMaskAccessorInterface.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class MaskAccessorGeneratorInterface @brief Interface for all MaskAccessor generating classes */ class MaskAccessorGeneratorInterface { public: using MaskAccessorPointer = core::MaskAccessorInterface::Pointer; private: MaskAccessorGeneratorInterface(const MaskAccessorGeneratorInterface&) = delete; //not implemented on purpose -> non-copyable MaskAccessorGeneratorInterface& operator=(const MaskAccessorGeneratorInterface&) = delete;//not implemented on purpose -> non-copyable protected: MaskAccessorGeneratorInterface() = default; virtual ~MaskAccessorGeneratorInterface() = default; public: /*! @brief Generate MaskAccessor @return Return shared pointer of MaskAccessor. */ virtual MaskAccessorPointer generateMaskAccessor() = 0; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbMaskAccessorInterface.h b/code/core/rttbMaskAccessorInterface.h index 44072d0..0b532d6 100644 --- a/code/core/rttbMaskAccessorInterface.h +++ b/code/core/rttbMaskAccessorInterface.h @@ -1,111 +1,106 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __MASK_ACCESSOR_INTERFACE_NEW_H #define __MASK_ACCESSOR_INTERFACE_NEW_H #include "rttbCommon.h" #include "rttbBaseType.h" #include "rttbMaskVoxel.h" #include "rttbIndexConversionInterface.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { class GeometricInfo; /*! @class MaskAccessorInterface @brief This class triggers the voxelization and gives acess to the masked voxels. */ class MaskAccessorInterface: public IndexConversionInterface { public: rttbClassMacro(MaskAccessorInterface, IndexConversionInterface); using MaskVoxelList = std::vector; using MaskVoxelListPointer = boost::shared_ptr; private: MaskAccessorInterface(const MaskAccessorInterface&) = delete; //not implemented on purpose -> non-copyable MaskAccessorInterface& operator=(const MaskAccessorInterface&) = delete;//not implemented on purpose -> non-copyable public: MaskAccessorInterface() = default; ~MaskAccessorInterface() override = default; /*! @brief Start generation of mask @post mask is valid and acessible */ virtual void updateMask() = 0; virtual const GeometricInfo& getGeometricInfo() const = 0; /*! @brief Get vector containing all relevant voxels that are inside the given structure. */ virtual MaskVoxelListPointer getRelevantVoxelVector() = 0; /*! @brief get vector containing all relevant voxels that have a relevant volume above the given threshold and are inside the given structure @pre updateMask should have been called (at least once, to ensure a valid mask). */ virtual MaskVoxelListPointer getRelevantVoxelVector(float lowerThreshold) = 0; /*! @brief Get masked voxel value corresponding to a given VoxelGridID. @post after a valid call voxel contains the mask information corresponding to aID. If aID is not valid, voxel values are undefined. @return Indicates if a MaskVoxel for the given ID exists and therefore if parameter voxel containes valid values. @pre updateMask should have been called (at least once, to ensure a valid mask). */ virtual bool getMaskAt(const VoxelGridID aID, MaskVoxel& voxel) const = 0; /*! @brief Get masked voxel value corresponding to a given VoxelGridIndex. @post after a valid call voxel contains the mask information corresponding to gridIndex. If gridIndex is not valid, voxel values are undefined. @return Indicates if a MaskVoxel for the given index exists and therefore if parameter voxel containes valid values. @pre updateMask should have been called (at least once, to ensure a valid mask). */ virtual bool getMaskAt(const VoxelGridIndex3D& gridIndex, MaskVoxel& voxel) const = 0; /* @brief Is true if dose is on a homogeneous grid. @note Inhomogeneous grids are not supported at the moment, but if they will be supported in the future the interface does not need to change. */ virtual bool isGridHomogeneous() const { return true; } virtual IDType getMaskUID() const = 0; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbMaskAccessorProcessorBase.h b/code/core/rttbMaskAccessorProcessorBase.h index 05d9010..2b2044f 100644 --- a/code/core/rttbMaskAccessorProcessorBase.h +++ b/code/core/rttbMaskAccessorProcessorBase.h @@ -1,68 +1,63 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __MASK_ACCESSOR_PROCESSOR_BASE_H #define __MASK_ACCESSOR_PROCESSOR_BASE_H #include "rttbMaskAccessorProcessorInterface.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class MaskAccessorProcessorBase @brief Abstract class for all MaskAccessor converter classes */ class MaskAccessorProcessorBase: public MaskAccessorProcessorInterface { public: using MaskAccessorPointer = core::MaskAccessorInterface::Pointer; void setMaskAccessor(MaskAccessorPointer accessor) override { _maskAccessor = accessor; }; private: MaskAccessorProcessorBase(const MaskAccessorProcessorBase&) = delete; //not implemented on purpose -> non-copyable MaskAccessorProcessorBase& operator=(const MaskAccessorProcessorBase&) = delete;//not implemented on purpose -> non-copyable protected: MaskAccessorProcessorBase() = default; ~MaskAccessorProcessorBase() override = default; /*! @brief Mask accessor which should be generated */ MaskAccessorPointer _maskAccessor; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbMaskAccessorProcessorInterface.h b/code/core/rttbMaskAccessorProcessorInterface.h index c3064e1..3ea5fec 100644 --- a/code/core/rttbMaskAccessorProcessorInterface.h +++ b/code/core/rttbMaskAccessorProcessorInterface.h @@ -1,74 +1,69 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __MASK_ACCESSOR_PROCESSOR_INTERFACE_H #define __MASK_ACCESSOR_PROCESSOR_INTERFACE_H #include "rttbMaskAccessorInterface.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class MaskAccessorProcessorInterface @brief Interface for all MaskAccessor converter classes */ class MaskAccessorProcessorInterface { public: using MaskAccessorPointer = core::MaskAccessorInterface::Pointer; private: MaskAccessorProcessorInterface(const MaskAccessorProcessorInterface&) = delete; //not implemented on purpose -> non-copyable MaskAccessorProcessorInterface& operator=(const MaskAccessorProcessorInterface&) = delete;//not implemented on purpose -> non-copyable protected: MaskAccessorProcessorInterface() = default; virtual ~MaskAccessorProcessorInterface() = default; public: /*! @brief Sets the MaskAccessor that should be processed @pre passed accessor must point to a valid instance. */ virtual void setMaskAccessor(MaskAccessorPointer accessor) = 0; /*! @brief Process the passed MaskAccessor @return if the processing was successful. */ virtual bool process() = 0; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbMaskVoxel.cpp b/code/core/rttbMaskVoxel.cpp index f230eb1..6e7f1dd 100644 --- a/code/core/rttbMaskVoxel.cpp +++ b/code/core/rttbMaskVoxel.cpp @@ -1,96 +1,90 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include "rttbMaskVoxel.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace core { MaskVoxel::MaskVoxel(const rttb::VoxelGridID& aVoxelGridID) { if (aVoxelGridID < 0) { std::cout << aVoxelGridID << std::endl; throw InvalidParameterException("VoxelGridID is not valid!"); } else { _voxelGridID = aVoxelGridID; _volumeFraction = 1; } } MaskVoxel::MaskVoxel(const rttb::VoxelGridID& aVoxelGridID, FractionType aVolumeFraction) { if (aVoxelGridID < 0) { std::cout << aVoxelGridID << std::endl; throw InvalidParameterException("VoxelGridID is not valid!"); } else if (aVolumeFraction < 0 || aVolumeFraction > 1) { std::cout << aVolumeFraction << std::endl; throw InvalidParameterException("Volume fraction needs to be between 0 and 1!"); } else { _voxelGridID = aVoxelGridID; _volumeFraction = aVolumeFraction; } } bool MaskVoxel::operator==(const MaskVoxel& voxel) const { return ((_voxelGridID == voxel.getVoxelGridID()) && (_volumeFraction == voxel.getRelevantVolumeFraction())); } bool MaskVoxel::operator<(const MaskVoxel& maskVoxel) const { return (_voxelGridID < maskVoxel.getVoxelGridID()); } const VoxelGridID& MaskVoxel::getVoxelGridID() const { return _voxelGridID; } void MaskVoxel::setRelevantVolumeFraction(FractionType aVolumeFraction) { if (aVolumeFraction < 0 || aVolumeFraction > 1) { std::cout << aVolumeFraction << std::endl; throw InvalidParameterException("Volume fraction needs to be between 0 and 1!"); } _volumeFraction = aVolumeFraction; } FractionType MaskVoxel::getRelevantVolumeFraction() const { return _volumeFraction; } }//end namespace core }//end namespace rttb diff --git a/code/core/rttbMaskVoxel.h b/code/core/rttbMaskVoxel.h index 8f07e9d..1f7891d 100644 --- a/code/core/rttbMaskVoxel.h +++ b/code/core/rttbMaskVoxel.h @@ -1,92 +1,86 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #ifndef __MASK_VOXEL_NEW_H #define __MASK_VOXEL_NEW_H #include "rttbBaseType.h" #include "RTTBCoreExports.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class MaskVoxel * @brief AMaskVoxel stores the VoxelGridID of the corresponding dose voxel and the corresponding volume fraction as defined by the given mask. */ class RTTBCore_EXPORT MaskVoxel { private: /*! @brief A 1D voxel grid index on dose grid */ VoxelGridID _voxelGridID; /*! @brief The relevant volume fraction that is masked by the given structure: 0~1 */ FractionType _volumeFraction; public: /*! @brief Constructor @pre aVoxelGridID needs to point to a valid grid position. */ MaskVoxel(const VoxelGridID& aVoxelGridID); /*! @brief Constructor @pre aVoxelGridID needs to point to a valid grid position. */ MaskVoxel(const VoxelGridID& aVoxelGridID, FractionType aVolumeFraction); /*! @brief Operator == @return Return true if the id and volumeFraction are equal to these of the maskVoxel */ bool operator==(const MaskVoxel& maskVoxel) const; /*! @brief Operator < @return Return true if the id < the id of the maskVoxel */ bool operator<(const MaskVoxel& maskVoxel) const; const VoxelGridID& getVoxelGridID() const; void setRelevantVolumeFraction(const FractionType aVolumeFraction); FractionType getRelevantVolumeFraction() const; friend std::ostream& operator<<(std::ostream& s, const MaskVoxel& maskVoxel) { s << "( " << maskVoxel.getVoxelGridID() << ": " << maskVoxel.getRelevantVolumeFraction() << " )"; return s; }; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbMaskedDoseIteratorInterface.cpp b/code/core/rttbMaskedDoseIteratorInterface.cpp index f7659e2..cc89049 100644 --- a/code/core/rttbMaskedDoseIteratorInterface.cpp +++ b/code/core/rttbMaskedDoseIteratorInterface.cpp @@ -1,49 +1,43 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include "rttbMaskedDoseIteratorInterface.h" #include "rttbMaskAccessorInterface.h" #include "rttbNullPointerException.h" #include "rttbException.h" namespace rttb { namespace core { MaskedDoseIteratorInterface::MaskedDoseIteratorInterface(MaskAccessorPointer aMaskAccessor, DoseAccessorPointer aDoseAccessor): DoseIteratorInterface(aDoseAccessor) { if (aMaskAccessor == nullptr) { throw NullPointerException(" mask pointer must not be nullptr!"); } else { _spMask = aMaskAccessor; } if (!(_spMask->getGeometricInfo() == _spDoseAccessor->getGeometricInfo())) { throw Exception("Mask and Dose need to be defined on the same grid"); } } } } \ No newline at end of file diff --git a/code/core/rttbMaskedDoseIteratorInterface.h b/code/core/rttbMaskedDoseIteratorInterface.h index be8c87e..aeccc3a 100644 --- a/code/core/rttbMaskedDoseIteratorInterface.h +++ b/code/core/rttbMaskedDoseIteratorInterface.h @@ -1,86 +1,80 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #ifndef __MASKED_DOSE_ITERATOR_INTERFACE_NEW_H #define __MASKED_DOSE_ITERATOR_INTERFACE_NEW_H #include #include "rttbDoseIteratorInterface.h" #include "rttbMaskAccessorInterface.h" #include "RTTBCoreExports.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { class MaskAccessorInterface; /*! @class MaskedDoseIteratorInterface @brief Give access to masked dose data. */ class RTTBCore_EXPORT MaskedDoseIteratorInterface : public DoseIteratorInterface { public: rttbClassMacro(MaskedDoseIteratorInterface, DoseIteratorInterface); using MaskAccessorPointer = MaskAccessorInterface::Pointer; using DoseAccessorPointer = DoseAccessorInterface::Pointer; using DoseIteratorPointer = DoseIteratorInterface::Pointer; private: MaskedDoseIteratorInterface(const MaskedDoseIteratorInterface&) = delete; MaskedDoseIteratorInterface& operator=(const MaskedDoseIteratorInterface&) = delete; protected: /*! @brief Mask that is to be applied to currently loaded dose*/ MaskAccessorPointer _spMask; public: /* Constructor @pre core::GeometricInfo represents the same geometric space for both mask and dose, i.e. both live on the same data grid. Both accessors need to be valid. */ MaskedDoseIteratorInterface(MaskAccessorPointer aMaskAccessor, DoseAccessorPointer aDoseAccessor); ~MaskedDoseIteratorInterface() override = default; inline MaskAccessorPointer getMaskAccessor() const { return _spMask; }; /* Return doseValue*voxelFraction for the current position */ virtual DoseTypeGy getCurrentMaskedDoseValue() const = 0; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbMutableDoseAccessorInterface.h b/code/core/rttbMutableDoseAccessorInterface.h index 91bd539..c491e90 100644 --- a/code/core/rttbMutableDoseAccessorInterface.h +++ b/code/core/rttbMutableDoseAccessorInterface.h @@ -1,59 +1,54 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __MUTABLE_DOSE_ACCESSOR_INTERFACE_NEW_H #define __MUTABLE_DOSE_ACCESSOR_INTERFACE_NEW_H #include "rttbDoseAccessorInterface.h" #include "rttbBaseType.h" #include "rttbCommon.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class MutableDoseAccessorInterface @brief Extends the DoseAccessorInterface to provide writing access to the data. */ class MutableDoseAccessorInterface: public DoseAccessorInterface { public: rttbClassMacro(MutableDoseAccessorInterface, DoseAccessorInterface) virtual void setDoseAt(const VoxelGridID aID, DoseTypeGy value) = 0; virtual void setDoseAt(const VoxelGridIndex3D& aIndex, DoseTypeGy value) = 0; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbMutableMaskAccessorInterface.h b/code/core/rttbMutableMaskAccessorInterface.h index 1054e6d..6601102 100644 --- a/code/core/rttbMutableMaskAccessorInterface.h +++ b/code/core/rttbMutableMaskAccessorInterface.h @@ -1,65 +1,60 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __MUTABLE_MASK_ACCESSOR_INTERFACE_H #define __MUTABLE_MASK_ACCESSOR_INTERFACE_H #include "rttbCommon.h" #include "rttbMaskAccessorInterface.h" #include "rttbBaseType.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { class MaskVoxel; /*! @class MutableMaskAccessorInterface @brief Extends the MaskAccessorInterface to provide writing access to the data. @details This interface is created for external manipulation of generated masks. For example to store the results of arithmetic operations on other masks. */ class MutableMaskAccessorInterface: public MaskAccessorInterface { public: rttbClassMacro(MutableMaskAccessorInterface, MaskAccessorInterface) using MaskVoxelList = core::MaskAccessorInterface::MaskVoxelList; using MaskVoxelListPointer = core::MaskAccessorInterface::MaskVoxelListPointer; virtual void setRelevantVoxelVector(MaskVoxelListPointer aVoxelListPointer) = 0; virtual void setMaskAt(VoxelGridID aID, const MaskVoxel& voxel) = 0; virtual void setMaskAt(const VoxelGridIndex3D& gridIndex, const MaskVoxel& voxel) = 0; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbNullPointerException.h b/code/core/rttbNullPointerException.h index 3de5e2f..dc2d2dd 100644 --- a/code/core/rttbNullPointerException.h +++ b/code/core/rttbNullPointerException.h @@ -1,47 +1,40 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #ifndef __NULL_POINTER_EXCEPTION_H #define __NULL_POINTER_EXCEPTION_H #include #include "rttbException.h" #include "RTTBCoreExports.h" - namespace rttb { namespace core { /*! @class NullPointerException @brief This exception will be thrown if any pointer is nullptr. */ class RTTBCore_EXPORT NullPointerException : public Exception { public: NullPointerException(const std::string& aWhat): Exception(aWhat) {} }; } } #endif diff --git a/code/core/rttbPaddingException.h b/code/core/rttbPaddingException.h index 0d76de0..c7618d8 100644 --- a/code/core/rttbPaddingException.h +++ b/code/core/rttbPaddingException.h @@ -1,47 +1,40 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #ifndef __PADDING_EXCEPTION_H #define __PADDING_EXCEPTION_H #include #include "rttbException.h" - namespace rttb { namespace core { /*! @class PaddingException @brief This exception will be thrown if it can't be guaranteed that a transformation covers only a part of the target space. */ class PaddingException: public Exception { public: PaddingException(const std::string& aWhat): Exception(aWhat) {} }; } } #endif diff --git a/code/core/rttbStrVectorStructureSetGenerator.cpp b/code/core/rttbStrVectorStructureSetGenerator.cpp index 5a2b7f4..e0651f7 100644 --- a/code/core/rttbStrVectorStructureSetGenerator.cpp +++ b/code/core/rttbStrVectorStructureSetGenerator.cpp @@ -1,67 +1,61 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include "rttbStrVectorStructureSetGenerator.h" #include #include "boost/make_shared.hpp" namespace rttb { namespace core { StrVectorStructureSetGenerator::StrVectorStructureSetGenerator(std::vector& aStructureVector, IDType aPatientUID) { _patientUID = aPatientUID; _strVector = aStructureVector; } StrVectorStructureSetGenerator::StructureSetPointer StrVectorStructureSetGenerator::generateStructureSet() { std::vector _filteredStructs = _strVector; if (this->getStructureLabelFilterActive()) { _filteredStructs.clear(); std::regex e(this->getFilterRegEx()); std::vector::iterator it; for(it= _strVector.begin();it!=_strVector.end();++it) { if (std::regex_match((*it)->getLabel(), e)) { _filteredStructs.push_back((*it)); } } } return boost::make_shared(_filteredStructs, _patientUID); } } }//end namespace rttb diff --git a/code/core/rttbStrVectorStructureSetGenerator.h b/code/core/rttbStrVectorStructureSetGenerator.h index ae52196..a3e6097 100644 --- a/code/core/rttbStrVectorStructureSetGenerator.h +++ b/code/core/rttbStrVectorStructureSetGenerator.h @@ -1,83 +1,76 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ - #ifndef __STR_VECTOR_STRUCTURE_SET_GENERATOR_H #define __STR_VECTOR_STRUCTURE_SET_GENERATOR_H #include #include #include "rttbStructureSetGeneratorInterface.h" #include "rttbStructureSet.h" #include "RTTBCoreExports.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class StrVectorStructureSetGenerator @brief Generate a structure set with a vector of Structures. */ class RTTBCore_EXPORT StrVectorStructureSetGenerator : public core::StructureSetGeneratorInterface { public: using StructTypePointer = core::Structure::Pointer; using StructureSetPointer = StructureSet::Pointer; protected: IDType _patientUID; std::vector _strVector; StrVectorStructureSetGenerator() = default; public: /*! @brief Constructor @param aStructureVector the vector of structure shared pointer @param aPatientUID the patient UID. */ StrVectorStructureSetGenerator(std::vector& aStructureVector, IDType aPatientUID = ""); /*! @brief Generate StructureSet @return Return shared pointer of StructureSet. */ StructureSetPointer generateStructureSet() override; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbStructure.cpp b/code/core/rttbStructure.cpp index 8872ca2..22dfe89 100644 --- a/code/core/rttbStructure.cpp +++ b/code/core/rttbStructure.cpp @@ -1,145 +1,139 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include #include #include #include #include #include #include "rttbStructure.h" #include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace core { /*! Compares two polygons in the same plane. Helper function for sorting of polygons. */ bool comparePolygon(PolygonType A, PolygonType B) { PolygonType::iterator it; for (it = A.begin(); it != A.end(); ++it) { if ((*it)(2) != A.at(0)(2)) { throw std::range_error("Error: A must in the same _z plane!"); } } PolygonType::iterator it2; for (it2 = B.begin(); it2 != B.end(); ++it2) { if ((*it2)(2) != B.at(0)(2)) { throw std::range_error("Error: B must in the same _z plane!"); } } if (A.size() == 0 || B.size() == 0) { throw std::range_error("Error: A and B must not be empty!"); } return (A.at(0)(2) < B.at(0)(2)); } Structure::Structure() : _structureVector(0), _label("") { if (_strUID.empty()) { boost::uuids::uuid id; boost::uuids::random_generator generator; id = generator(); std::stringstream ss; ss << id; _strUID = ss.str(); } } Structure::Structure(PolygonSequenceType strVector) : Structure() { _structureVector = strVector; sort(_structureVector.begin(), _structureVector.end(), comparePolygon); } Structure::Structure(const Structure& copy) : _structureVector(copy.getStructureVector()), _strUID(copy.getUID()), _label(copy.getLabel()) { } Structure::~Structure() = default; const PolygonSequenceType& Structure::getStructureVector() const { return _structureVector; } int Structure::getNumberOfEndpoints() const { int count = 0; PolygonSequenceType::const_iterator itVV; for (itVV = _structureVector.begin(); itVV != _structureVector.end(); ++itVV) { count += (int)(*itVV).size(); } return count; } IDType Structure::getUID() const { return _strUID; } void Structure::setUID(const IDType& aUID) { _strUID = aUID; } void Structure::setLabel(const StructureLabel& aLabel) { _label = aLabel; } StructureLabel Structure::getLabel() const { return _label; } }//end namespace core }//end namespace rttb diff --git a/code/core/rttbStructure.h b/code/core/rttbStructure.h index 09887cc..4746c98 100644 --- a/code/core/rttbStructure.h +++ b/code/core/rttbStructure.h @@ -1,114 +1,107 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ - #ifndef __STRUCTURE_H #define __STRUCTURE_H #include #include #include "rttbBaseType.h" #include "rttbCommon.h" #include "RTTBCoreExports.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class Structure @brief This is a class representing a RT Structure */ class RTTBCore_EXPORT Structure { public: rttbClassMacroNoParent(Structure); private: /*! @brief WorldCoordinate3D in mm */ PolygonSequenceType _structureVector; /*! @brief Contour Geometric Type using DICOM-RT definition (3006,0042). * POINT: indicates that the contour is a single point, defining a specific location of significance. * OPEN_PLANAR: indicates that the last vertex shall not be connected to the first point, and that all points * in Contour Data (3006,0050) shall be coplanar. * OPEN_NONPLANAR: indicates that the last vertex shall not be connected to the first point, and that the points * in Contour Data(3006,0050) may be non-coplanar. * CLOSED_PLANAR: indicates that the last point shall be connected to the first point, where the first point is * not repeated in the Contour Data. All points in Contour Data (3006,0050) shall be coplanar. */ std::vector _contourGeometricTypeVector; /*! @brief Structure UID*/ IDType _strUID; /*! @brief Structure Label*/ StructureLabel _label; public: /*! @brief Structure Standard Constructor uid will be randomly generated using boost::uuid library at first. To change the uid using setUID(). */ Structure(); /*! @brief Structure Constructor uid will be randomly generated using boost::uuid library at first. To change the uid using setUID(). */ Structure(PolygonSequenceType strVector); Structure(const Structure& copy); ~Structure(); const PolygonSequenceType& getStructureVector() const; /*! @brief Get the number of end points (points that define the polygon) of all contours of the structure. */ int getNumberOfEndpoints() const; IDType getUID() const; void setUID(const IDType& aUID); void setLabel(const StructureLabel& aLabel); StructureLabel getLabel() const; }; }//end namespace core }//end namespace rttb #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbStructureSet.cpp b/code/core/rttbStructureSet.cpp index 81624be..10366cd 100644 --- a/code/core/rttbStructureSet.cpp +++ b/code/core/rttbStructureSet.cpp @@ -1,84 +1,78 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include #include #include #include #include #include "rttbStructureSet.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace core { StructureSet::StructureSet(const std::vector& aStructureVector, IDType aPatientUID, IDType aUID) { _structureSetVector = aStructureVector; _patientUID = aPatientUID; _UID = aUID; if (_UID == "") { boost::uuids::uuid id; boost::uuids::random_generator generator; id = generator(); std::stringstream ss; ss << id; _UID = ss.str(); } } Structure::Pointer StructureSet::getStructure(size_t aStructureNo) const { auto size = this->getNumberOfStructures(); if (aStructureNo >= size) { std::stringstream sstr; sstr << "aStructureNo must be between 0 and " << size; throw InvalidParameterException(sstr.str()); } return _structureSetVector.at(aStructureNo); } StructureSet::NumberOfStructuresType StructureSet::getNumberOfStructures() const { return _structureSetVector.size(); } IDType StructureSet::getUID() const { return _UID; } IDType StructureSet::getPatientUID() const { return _patientUID; } }//end namespace core }//end namespace rttb diff --git a/code/core/rttbStructureSet.h b/code/core/rttbStructureSet.h index d43cae0..ff03a22 100644 --- a/code/core/rttbStructureSet.h +++ b/code/core/rttbStructureSet.h @@ -1,93 +1,87 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #ifndef __STRUCTURE_SET_H #define __STRUCTURE_SET_H #include #include "rttbBaseType.h" #include "rttbCommon.h" #include "rttbStructure.h" #include "RTTBCoreExports.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class StructureSet @brief This is an class representing a structure set, which can be used to generate masks. */ class RTTBCore_EXPORT StructureSet { public: rttbClassMacroNoParent(StructureSet); using NumberOfStructuresType = size_t; protected: std::vector _structureSetVector; IDType _UID; IDType _patientUID; public: virtual ~StructureSet() = default; /*! @brief Constructor @param aPatientUID the patient UID. @param aUID the structure set UID. If it is empty, it will be calculated in the constructor */ StructureSet(const std::vector& aStructureVector, IDType aPatientUID = "", IDType aUID = ""); /*! @brief Get the Structure with the index aStructureNo @return Return Structure pointer. @exception InvalidParameterException Thrown if structureNo not between 0 and number of structures of structureSet. */ Structure::Pointer getStructure(size_t aStructureNo) const; /*! @brief Get the number of structures @return Return the number of structures. */ NumberOfStructuresType getNumberOfStructures() const; virtual IDType getUID() const; virtual IDType getPatientUID() const; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/core/rttbStructureSetGeneratorInterface.h b/code/core/rttbStructureSetGeneratorInterface.h index 0c018a3..57ef737 100644 --- a/code/core/rttbStructureSetGeneratorInterface.h +++ b/code/core/rttbStructureSetGeneratorInterface.h @@ -1,94 +1,89 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __STRUCTURE_SET_GENERATOR_INTERFACE_H #define __STRUCTURE_SET_GENERATOR_INTERFACE_H #include #include "rttbStructureSet.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace core { /*! @class StructureSetGeneratorInterface @brief Interface for all structure set generating classes */ class StructureSetGeneratorInterface { public: rttbClassMacroNoParent(StructureSetGeneratorInterface); private: StructureSetGeneratorInterface(const StructureSetGeneratorInterface&) = delete; //not implemented on purpose -> non-copyable StructureSetGeneratorInterface& operator=(const StructureSetGeneratorInterface&) = delete;//not implemented on purpose -> non-copyable protected: StructureSetGeneratorInterface() = default; virtual ~StructureSetGeneratorInterface() = default; private: bool _activeFilter{false}; std::string _filterRegEx; public: void setStructureLabelFilterActive(bool active) { _activeFilter = active; }; bool getStructureLabelFilterActive() const { return _activeFilter; }; void setFilterRegEx(const std::string& filter) { _filterRegEx = filter; }; std::string getFilterRegEx() const { return _filterRegEx; }; /*! @brief Generate StructureSet @return Return shared pointer of StructureSet. */ virtual StructureSet::Pointer generateStructureSet() = 0; }; } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/testing/core/BaseTypeTest.cpp b/testing/core/BaseTypeTest.cpp index 911b582..d51e2c7 100644 --- a/testing/core/BaseTypeTest.cpp +++ b/testing/core/BaseTypeTest.cpp @@ -1,277 +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. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include "litCheckMacros.h" #include "rttbBaseType.h" namespace rttb { namespace testing { /*! @brief BaseTypeTests - tests the API for the classes in baseType 1) UnsignedIndex3D 2) WorldCoordinate3D 3) SpacingVectorType3D 4) OrientationMatrix 5) VoxelGridIndex3D 6) VoxelGridIndex2D */ int BaseTypeTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //1) UnsignedIndex3D CHECK_NO_THROW(UnsignedIndex3D ui); UnsignedIndex3D emptyUnsignedIndex3D; CHECK_EQUAL(emptyUnsignedIndex3D.x(), 0); CHECK_EQUAL(emptyUnsignedIndex3D.y(), 0); CHECK_EQUAL(emptyUnsignedIndex3D.z(), 0); CHECK_NO_THROW(UnsignedIndex3D ui(5)); UnsignedIndex3D sameValueUnsignedIndex(5); CHECK_EQUAL(sameValueUnsignedIndex.x(), 5); CHECK_EQUAL(sameValueUnsignedIndex.y(), 5); CHECK_EQUAL(sameValueUnsignedIndex.z(), 5); CHECK_NO_THROW(UnsignedIndex3D ui(5, 8, 42)); UnsignedIndex3D differentValueUnsignedIndex(5, 8, 42); CHECK_EQUAL(differentValueUnsignedIndex.x(), 5); CHECK_EQUAL(differentValueUnsignedIndex.y(), 8); CHECK_EQUAL(differentValueUnsignedIndex.z(), 42); UnsignedIndex3D threeDimensionalUnsignedIndexSame(5, 8, 42); UnsignedIndex3D threeDimensionalUnsignedIndexDifferent(1, 2, 3); CHECK(differentValueUnsignedIndex == threeDimensionalUnsignedIndexSame); CHECK_EQUAL(differentValueUnsignedIndex == threeDimensionalUnsignedIndexDifferent, false); CHECK_EQUAL(differentValueUnsignedIndex == sameValueUnsignedIndex, false); CHECK_EQUAL(emptyUnsignedIndex3D == sameValueUnsignedIndex, 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_NO_THROW(VoxelGridIndex3D vgiValue(2)); VoxelGridIndex3D vgiValue(2); CHECK_EQUAL(vgiValue.x(), 2); CHECK_EQUAL(vgiValue.y(), 2); CHECK_EQUAL(vgiValue.z(), 2); 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.toString(), "2 3 5"); CHECK_NO_THROW(vgiValueDifferent = threeDimensionalUnsignedIndexSame); CHECK_EQUAL(vgiValueDifferent.x(), 5); CHECK_EQUAL(vgiValueDifferent.y(), 8); CHECK_EQUAL(vgiValueDifferent.z(), 42); VoxelGridIndex3D vgiValueDifferentSame(5, 8, 42); CHECK_EQUAL(vgi==vgiValue, false); CHECK_EQUAL(vgiValueDifferentSame == vgiValueDifferent, true); //6) VoxelGridIndex2D CHECK_NO_THROW(VoxelGridIndex2D vgi); VoxelGridIndex2D vgi2D; CHECK_EQUAL(vgi2D.x(), 0); CHECK_EQUAL(vgi2D.y(), 0); CHECK_NO_THROW(VoxelGridIndex2D vgi2DValue(2)); VoxelGridIndex2D vgi2DValue(2); CHECK_EQUAL(vgi2DValue.x(), 2); CHECK_EQUAL(vgi2DValue.y(), 2); CHECK_NO_THROW(VoxelGridIndex2D vgi2DValueDifferent(2, 3)); VoxelGridIndex2D vgi2DValueDifferent(2, 3); CHECK_EQUAL(vgi2DValueDifferent.x(), 2); CHECK_EQUAL(vgi2DValueDifferent.y(), 3); 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/DVHCalculatorTest.cpp b/testing/core/DVHCalculatorTest.cpp index eb782e3..53f1d7f 100644 --- a/testing/core/DVHCalculatorTest.cpp +++ b/testing/core/DVHCalculatorTest.cpp @@ -1,154 +1,148 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests #include #include #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbDVHCalculator.h" #include "rttbGenericMaskedDoseIterator.h" #include "rttbGeometricInfo.h" #include "rttbGenericDoseIterator.h" #include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" #include "DummyDoseAccessor.h" #include "DummyMaskAccessor.h" namespace rttb { namespace testing { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef core::GenericMaskedDoseIterator::MaskAccessorPointer MaskAccessorPointer; typedef core::DVHCalculator::DoseIteratorPointer DoseIteratorPointer; typedef core::DVHCalculator::MaskedDoseIteratorPointer MaskedDoseIteratorPointer; /*!@brief DVHTest - test the API of DVH 1) test constructors (values as expected?) */ int DVHCalculatorTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //create null pointer to DoseIterator DoseIteratorPointer spDoseIteratorNull; const IDType structureID = "myStructure"; const IDType doseIDNull = "myDose"; //1) test constructors (values as expected?) CHECK_THROW_EXPLICIT(core::DVHCalculator myDVHCalc(spDoseIteratorNull, structureID, doseIDNull), core::NullPointerException); //create dummy DoseAccessor boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DoseAccessorPointer spDoseAccessor(spTestDoseAccessor); const std::vector* doseVals = spTestDoseAccessor->getDoseVector(); //create corresponding DoseIterator boost::shared_ptr spTestDoseIterator = boost::make_shared(spDoseAccessor); DoseIteratorPointer spDoseIterator(spTestDoseIterator); const IDType doseID = spDoseAccessor->getUID(); CHECK_NO_THROW(core::DVHCalculator myDVHCalc(spDoseIterator, structureID, doseID)); CHECK_THROW_EXPLICIT(core::DVHCalculator myDVHCalc(spDoseIterator, structureID, doseID, -1), core::InvalidParameterException); int numBins = 21; DoseTypeGy binSize = 0; DoseStatisticType maximum = 0; std::vector::const_iterator doseIt = doseVals->begin(); while (doseIt != doseVals->end()) { if (maximum < *doseIt) { maximum = *doseIt; } ++doseIt; } binSize = maximum * 1.5 / numBins; CHECK_NO_THROW(core::DVHCalculator myDVHCalc(spDoseIterator, structureID, doseID, binSize, numBins)); CHECK_THROW_EXPLICIT(core::DVHCalculator myDVHCalc(spDoseIterator, structureID, doseID, 0, 0), core::InvalidParameterException);//aNumberOfBins must be >=0 core::DVHCalculator myDVHCalc(spDoseIterator, structureID, doseID, binSize, 1); CHECK_THROW_EXPLICIT(myDVHCalc.generateDVH(), core::InvalidParameterException);//_numberOfBins must be > max(aDoseIterator)/aDeltaD! //generateDVH (only test basic functionality here and test it in RTTBDicomIOTests and RTTBITKIOTests) //create dummy DoseAccessor with values 0 to check if _deltaD is set to 0.1 std::vector zeros(1000, 0); core::GeometricInfo geoInfo; geoInfo.setNumColumns(10); geoInfo.setNumRows(10); geoInfo.setNumSlices(10); geoInfo.setSpacing({1.0, 1.0, 1.0}); boost::shared_ptr spTestDoseAccessorZeros = boost::make_shared(zeros, geoInfo); DoseAccessorPointer spDoseAccessorZeros(spTestDoseAccessorZeros); boost::shared_ptr spTestDoseIteratorZeros = boost::make_shared(spDoseAccessorZeros); DoseIteratorPointer spDoseIteratorZeros(spTestDoseIteratorZeros); CHECK_NO_THROW(core::DVHCalculator myDVHCalc2(spDoseIteratorZeros, structureID, doseID, 0, numBins)); core::DVHCalculator myDVHCalc2(spDoseIteratorZeros, structureID, doseID, 0, numBins); core::DVH::Pointer dvh; CHECK_NO_THROW(dvh = myDVHCalc2.generateDVH()); CHECK(dvh); CHECK_CLOSE(dvh->getDeltaD(), 0.1, errorConstant); //create dummy MaskAccessor boost::shared_ptr spTestMaskAccessor = boost::make_shared(spDoseAccessor->getGeometricInfo()); MaskAccessorPointer spMaskAccessor(spTestMaskAccessor); //create corresponding MaskedDoseIterator boost::shared_ptr spTestMaskedDoseIterator = boost::make_shared(spMaskAccessor, spDoseAccessor); MaskedDoseIteratorPointer spMaskedDoseIterator(spTestMaskedDoseIterator); CHECK_NO_THROW(core::DVHCalculator myDVHCalc3(spMaskedDoseIterator, structureID, doseID)); core::DVHCalculator myDVHCalc3(spMaskedDoseIterator, structureID, doseID); CHECK_NO_THROW(dvh = myDVHCalc3.generateDVH()); CHECK(dvh); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/core/DVHSetTest.cpp b/testing/core/DVHSetTest.cpp index 1d23a7f..5c25455 100644 --- a/testing/core/DVHSetTest.cpp +++ b/testing/core/DVHSetTest.cpp @@ -1,207 +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. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include #include #include #include #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbDVH.h" #include "rttbDVHSet.h" #include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" #include "DummyDVHGenerator.h" namespace rttb { namespace testing { 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[]) { 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/DVHTest.cpp b/testing/core/DVHTest.cpp index 6c93b4b..fc34f66 100644 --- a/testing/core/DVHTest.cpp +++ b/testing/core/DVHTest.cpp @@ -1,242 +1,236 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include #include #include #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbDVH.h" #include "DummyDoseAccessor.h" #include "DummyMaskAccessor.h" namespace rttb { namespace testing { typedef core::DVH::DataDifferentialType DataDifferentialType; /*! @brief DVHTest - test the API of DVH 1) test constructors (values as expected?) 2) test assignement 3) test set/getLabel 4) test set/get 5) test equality */ int DVHTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //generate artificial DVH and corresponding statistical values DoseTypeGy binSize = DoseTypeGy(0.1); DoseVoxelVolumeType voxelVolume = 8; DataDifferentialType anEmptyDataDifferential; DataDifferentialType aDataDifferential; DataDifferentialType aDataDifferential2; DataDifferentialType aDataDifferentialRelative; DoseStatisticType maximum = 0; DoseStatisticType minimum = 0; double sum = 0; double squareSum = 0; DoseCalcType value = 0; DVHVoxelNumber numberOfVoxels = 0; // creat default values [0,100) for (int i = 0; i < 100; i++) { value = DoseCalcType((double(rand()) / RAND_MAX) * 1000); numberOfVoxels += value; aDataDifferential.push_back(value); aDataDifferential2.push_back(value * 10); if (value > 0) { maximum = (i + 0.5) * binSize; if (minimum == 0) { minimum = (i + 0.5) * binSize; } } sum += value * (i + 0.5) * binSize; squareSum += value * pow((i + 0.5) * binSize, 2); } double medianVoxel = 0; double modalVoxel = 0; unsigned int count = 0; unsigned int medianCount = 0; unsigned int modalCount = 0; for (const auto& aValue : aDataDifferential) { std::cout << aValue << std::endl; if (medianVoxel < numberOfVoxels - medianVoxel) { medianVoxel += aValue; medianCount = count; } if (modalVoxel < aValue) { modalVoxel = aValue; modalCount = count; } count++; } DoseStatisticType median = (medianCount + 0.5)*binSize; DoseStatisticType modal = (modalCount + 0.5)*binSize; DoseStatisticType mean = sum / numberOfVoxels; DoseStatisticType variance = (squareSum / numberOfVoxels - mean * mean); DoseStatisticType stdDeviation = pow(variance, 0.5); std::deque::iterator it; for (it = aDataDifferential.begin(); it != aDataDifferential.end(); ++it) { aDataDifferentialRelative.push_back((*it) / numberOfVoxels); } IDType structureID = "myStructure"; IDType doseID = "myDose"; IDType voxelizationID = "myVoxelization"; //1) test default constructor (values as expected?) CHECK_THROW(core::DVH(anEmptyDataDifferential, binSize, voxelVolume, structureID, doseID, voxelizationID)); CHECK_THROW(core::DVH(anEmptyDataDifferential, binSize, voxelVolume, structureID, doseID)); CHECK_NO_THROW(core::DVH(aDataDifferential, binSize, voxelVolume, structureID, doseID, voxelizationID)); CHECK_NO_THROW(core::DVH(aDataDifferential, binSize, voxelVolume, structureID, doseID)); CHECK_THROW(core::DVH(aDataDifferential, 0, voxelVolume, structureID, doseID, voxelizationID)); CHECK_THROW(core::DVH(aDataDifferential, 0, voxelVolume, structureID, doseID)); CHECK_THROW(core::DVH(aDataDifferential, binSize, 0, structureID, doseID, voxelizationID)); CHECK_THROW(core::DVH(aDataDifferential, binSize, 0, structureID, doseID)); //2) test assignment core::DVH myTestDVH(aDataDifferential, binSize, voxelVolume, structureID, doseID); CHECK_NO_THROW(core::DVH myOtherDVH = myTestDVH); core::DVH myOtherDVH(myTestDVH); CHECK_NO_THROW(myOtherDVH = myTestDVH); //3) test set/getLabel core::DVH myDVH(aDataDifferential, binSize, voxelVolume, structureID, doseID, voxelizationID); StructureLabel label = ""; CHECK_EQUAL(myDVH.getLabel(), label); CHECK_EQUAL(myDVH.getLabel(), label); label = "myLabel"; CHECK_NO_THROW(myDVH.setLabel(label)); CHECK_NO_THROW(myDVH.setLabel(label)); CHECK_EQUAL(myDVH.getLabel(), label); CHECK_EQUAL(myDVH.getLabel(), label); label = "myLabel2"; CHECK_NO_THROW(myDVH.setLabel(label)); CHECK_NO_THROW(myDVH.setLabel(label)); CHECK_EQUAL(myDVH.getLabel(), label); CHECK_EQUAL(myDVH.getLabel(), label); //4) test set/get //IDs CHECK_EQUAL(myDVH.getStructureID(), structureID); CHECK_EQUAL(myDVH.getDoseID(), doseID); CHECK_EQUAL(myDVH.getVoxelizationID(), voxelizationID); /*! is related to #2029*/ myDVH.setDoseID("somethingElse"); CHECK_EQUAL(myDVH.getDoseID(), "somethingElse"); CHECK_EQUAL(myDVH.getVoxelizationID(), voxelizationID); CHECK_EQUAL(myDVH.getStructureID(), structureID); /*! is related to #2029*/ myDVH.setStructureID("somethingOther"); CHECK_EQUAL(myDVH.getDoseID(), "somethingElse"); CHECK_EQUAL(myDVH.getVoxelizationID(), voxelizationID); CHECK_EQUAL(myDVH.getStructureID(), "somethingOther"); //dataDifferential CHECK(myDVH.getDataDifferential() == aDataDifferential); CHECK(myDVH.getDataDifferential() == aDataDifferential); CHECK(myDVH.convertAbsoluteToRelative(false) == aDataDifferentialRelative); CHECK_EQUAL(myDVH.getNumberOfVoxels(), numberOfVoxels); CHECK_EQUAL(myDVH.getDeltaV(), voxelVolume); CHECK_EQUAL(myDVH.getDeltaD(), binSize); CHECK_EQUAL(myDVH.getMaximum(), maximum); CHECK_EQUAL(myDVH.getMinimum(), minimum); CHECK_EQUAL(myDVH.getMean(), mean); CHECK_EQUAL(myDVH.getVariance(), variance); CHECK_EQUAL(myDVH.getStdDeviation(), stdDeviation); CHECK_EQUAL(myDVH.getMedian(), median); CHECK_EQUAL(myDVH.getModal(), modal); //We can't test for absolute values as the implementation of rand() differs depending on compiler and different DVHs are created CHECK_NO_THROW(myDVH.getVx(0)); CHECK_NO_THROW(myDVH.getVx(7)); CHECK_NO_THROW(myDVH.getDx(0)); CHECK_NO_THROW(myDVH.getDx(100000)); int percentage = 20; VolumeType absVol = VolumeType(percentage * numberOfVoxels * voxelVolume / 100.0); CHECK_EQUAL(myDVH.getAbsoluteVolume(percentage), absVol); //5) test equality structureID = myDVH.getStructureID(); doseID = myDVH.getDoseID(); voxelizationID = myDVH.getVoxelizationID(); core::DVH myDVH2(aDataDifferential2, binSize, voxelVolume, structureID, doseID); core::DVH myDVH3(aDataDifferential, binSize, voxelVolume, structureID+"_diff", doseID); core::DVH myDVH4(aDataDifferential, binSize, voxelVolume, structureID, doseID+"_diff"); core::DVH myDVH5(aDataDifferential, binSize, voxelVolume, structureID, doseID, voxelizationID+"_diff"); CHECK(!(myDVH == myDVH2)); CHECK(!(myDVH == myDVH3)); CHECK(!(myDVH == myDVH4)); CHECK(!(myDVH == myDVH5)); CHECK_EQUAL(myDVH, myDVH); core::DVH aDVH(myOtherDVH); CHECK_EQUAL(aDVH, myOtherDVH); std::map normalizedDVHDiff = myDVH.getNormalizedDVH({ DVHType::Differential }); for (auto elem : normalizedDVHDiff) { CHECK_EQUAL(aDataDifferential.at(std::round(elem.first / binSize)), (elem.second / voxelVolume)); } std::map normalizedDVHCum = myDVH.getNormalizedDVH(); for (auto elem : normalizedDVHCum) { CHECK_EQUAL(myDVH.getDataCumulative().at(std::round(elem.first / binSize)), (elem.second / voxelVolume)); } CHECK_NO_THROW(myDVH.getDataCumulative()); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/core/DummyDVHGenerator.cpp b/testing/core/DummyDVHGenerator.cpp index dfe118e..66e1487 100644 --- a/testing/core/DummyDVHGenerator.cpp +++ b/testing/core/DummyDVHGenerator.cpp @@ -1,109 +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. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #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/testing/core/DummyDVHGenerator.h index ebbfaf4..c65c51e 100644 --- a/testing/core/DummyDVHGenerator.h +++ b/testing/core/DummyDVHGenerator.h @@ -1,71 +1,65 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __DUMMY_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 diff --git a/testing/core/DummyDoseAccessor.h b/testing/core/DummyDoseAccessor.h index 5f6a89c..d31a21e 100644 --- a/testing/core/DummyDoseAccessor.h +++ b/testing/core/DummyDoseAccessor.h @@ -1,79 +1,78 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ #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 diff --git a/testing/core/DummyInhomogeneousDoseAccessor.cpp b/testing/core/DummyInhomogeneousDoseAccessor.cpp index 83c28f9..0087e28 100644 --- a/testing/core/DummyInhomogeneousDoseAccessor.cpp +++ b/testing/core/DummyInhomogeneousDoseAccessor.cpp @@ -1,43 +1,37 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include "DummyInhomogeneousDoseAccessor.h" namespace rttb { namespace testing { DummyInhomogeneousDoseAccessor::~DummyInhomogeneousDoseAccessor() {} DummyInhomogeneousDoseAccessor::DummyInhomogeneousDoseAccessor() : DummyDoseAccessor() { } bool DummyInhomogeneousDoseAccessor::isGridHomogeneous() const { return false; } }//end namespace testing }//end namespace rttb \ No newline at end of file diff --git a/testing/core/DummyInhomogeneousDoseAccessor.h b/testing/core/DummyInhomogeneousDoseAccessor.h index 91260e4..05a4938 100644 --- a/testing/core/DummyInhomogeneousDoseAccessor.h +++ b/testing/core/DummyInhomogeneousDoseAccessor.h @@ -1,50 +1,44 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __DUMMY_DOSE_INHOMOGENEOUS_ACCESSOR_H #define __DUMMY_DOSE_INHOMOGENEOUS_ACCESSOR_H #include "DummyDoseAccessor.h" - namespace rttb { namespace testing { /*! @class DummyInhomogeneousDoseAccessor @brief A dummy DoseAccessor for testing with inhomogeneous grid */ class 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.h b/testing/core/DummyMaskAccessor.h index d5d119e..d2c0466 100644 --- a/testing/core/DummyMaskAccessor.h +++ b/testing/core/DummyMaskAccessor.h @@ -1,76 +1,75 @@ // ----------------------------------------------------------------------- // 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 diff --git a/testing/core/DummyMutableDoseAccessor.h b/testing/core/DummyMutableDoseAccessor.h index 14f61a7..f7ceca3 100644 --- a/testing/core/DummyMutableDoseAccessor.h +++ b/testing/core/DummyMutableDoseAccessor.h @@ -1,83 +1,82 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ #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 diff --git a/testing/core/GenericDoseIteratorTest.cpp b/testing/core/GenericDoseIteratorTest.cpp index 93d6657..7894dbc 100644 --- a/testing/core/GenericDoseIteratorTest.cpp +++ b/testing/core/GenericDoseIteratorTest.cpp @@ -1,112 +1,106 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbGenericDoseIterator.h" #include "DummyDoseAccessor.h" #include "DummyInhomogeneousDoseAccessor.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace testing { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; /*! @brief GenericDoseIteratorTest - test the API of GenericDoseIterator 1) test constructor (values as expected?) 2) test reset/next/get current values/isPositionValid 3) test DoseIteratorInterface functions */ int GenericDoseIteratorTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //create dummy DoseAccessor boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DoseAccessorPointer spDoseAccessor(spTestDoseAccessor); boost::shared_ptr spTestDoseAccessorInhomo = boost::make_shared(); DoseAccessorPointer spDoseAccessorInhomo(spTestDoseAccessorInhomo); //1) test constructor (values as expected?) CHECK_NO_THROW(core::GenericDoseIterator genDoseIterator(spDoseAccessor)); core::GenericDoseIterator genDoseIterator(spDoseAccessor); const VoxelGridID defaultDoseVoxelGridID = 0; const DoseVoxelVolumeType defaultVoxelVolume = 0; CHECK_EQUAL(defaultDoseVoxelGridID, genDoseIterator.getCurrentVoxelGridID()); CHECK_EQUAL(defaultVoxelVolume, genDoseIterator.getCurrentVoxelVolume()); core::GenericDoseIterator genDoseIteratorInhomo(spDoseAccessorInhomo); //2) test reset/next genDoseIterator.reset(); const DoseVoxelVolumeType homogeneousVoxelVolume = genDoseIterator.getCurrentVoxelVolume(); CHECK_EQUAL(defaultDoseVoxelGridID, genDoseIterator.getCurrentVoxelGridID()); CHECK(!(defaultVoxelVolume == genDoseIterator.getCurrentVoxelVolume())); core::GeometricInfo geoInfo = spTestDoseAccessor->getGeometricInfo(); SpacingVectorType3D spacing = geoInfo.getSpacing(); CHECK_EQUAL(spacing(0)*spacing(1)*spacing(2) / 1000, genDoseIterator.getCurrentVoxelVolume()); CHECK_THROW_EXPLICIT(genDoseIteratorInhomo.reset(), core::InvalidParameterException); //check if the correct voxels are accessed const std::vector* doseVals = spTestDoseAccessor->getDoseVector(); genDoseIterator.reset(); VoxelGridID position = 0; while (genDoseIterator.isPositionValid()) { CHECK_EQUAL(genDoseIterator.getCurrentDoseValue(), doseVals->at(position)); CHECK_EQUAL(homogeneousVoxelVolume, genDoseIterator.getCurrentVoxelVolume()); CHECK_EQUAL(1, genDoseIterator.getCurrentRelevantVolumeFraction()); CHECK_EQUAL(position, genDoseIterator.getCurrentVoxelGridID()); genDoseIterator.next(); position++; } CHECK_EQUAL(spTestDoseAccessor->getGridSize(), spTestDoseAccessor->getGeometricInfo().getNumberOfVoxels()); //check isPositionValid() in invalid positions CHECK(!(genDoseIterator.isPositionValid())); //after end of dose CHECK_EQUAL(genDoseIterator.getCurrentDoseValue(), 0); genDoseIterator.reset(); CHECK_EQUAL(defaultDoseVoxelGridID, genDoseIterator.getCurrentVoxelGridID()); CHECK(genDoseIterator.isPositionValid());//before start of dose //3) test DoseIteratorInterface functions CHECK_EQUAL(genDoseIterator.getVoxelizationID(), ""); CHECK_EQUAL(genDoseIterator.getDoseUID(), spTestDoseAccessor->getUID()); CHECK_THROW_EXPLICIT(genDoseIteratorInhomo.getCurrentVoxelVolume(), core::InvalidParameterException); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/core/GenericMaskedDoseIteratorTest.cpp b/testing/core/GenericMaskedDoseIteratorTest.cpp index 6547c0b..6ba9097 100644 --- a/testing/core/GenericMaskedDoseIteratorTest.cpp +++ b/testing/core/GenericMaskedDoseIteratorTest.cpp @@ -1,143 +1,137 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include #include #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbGenericMaskedDoseIterator.h" #include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" #include "rttbException.h" #include "DummyDoseAccessor.h" #include "DummyInhomogeneousDoseAccessor.h" #include "DummyMaskAccessor.h" namespace rttb { namespace testing { typedef core::GenericMaskedDoseIterator::MaskAccessorPointer MaskAccessorPointer; typedef core::GenericMaskedDoseIterator::DoseAccessorPointer DoseAccessorPointer; /*! @brief GenericMaskedDoseIteratorTest. 1) test constructor (values as expected?) 2) test reset/next/get current values/isPositionValid */ int GenericMaskedDoseIteratorTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DoseAccessorPointer spDoseAccessor(spTestDoseAccessor); boost::shared_ptr spTestDoseAccessorInhomo = boost::make_shared(); DoseAccessorPointer spDoseAccessorInhomo(spTestDoseAccessorInhomo); const std::vector* doseVals = spTestDoseAccessor->getDoseVector(); core::GeometricInfo geoInfo; boost::shared_ptr spTestMaskAccessor = boost::make_shared (geoInfo); MaskAccessorPointer spMaskAccessor(spTestMaskAccessor); //1) test constructor (values as expected?) //not nullptr MaskAccessorPointer spNullMaskAccessor; DoseAccessorPointer spNullDoseAccessor; CHECK_THROW_EXPLICIT(core::GenericMaskedDoseIterator genMaskedDoseIterator(spNullMaskAccessor, spDoseAccessor), core::NullPointerException); CHECK_THROW_EXPLICIT(core::GenericMaskedDoseIterator genMaskedDoseIterator(spMaskAccessor, spNullDoseAccessor), core::NullPointerException); //not same core::GeometricInfo CHECK_THROW_EXPLICIT(core::GenericMaskedDoseIterator genMaskedDoseIterator(spMaskAccessor, spDoseAccessor), core::Exception); //set correct GeometricInfo geoInfo = spDoseAccessor->getGeometricInfo(); boost::shared_ptr spTestMaskAccessor1 = boost::make_shared (geoInfo); MaskAccessorPointer spMaskAccessorTemp(spTestMaskAccessor1); spMaskAccessor.swap(spMaskAccessorTemp); CHECK_NO_THROW(core::GenericMaskedDoseIterator genMaskedDoseIterator(spMaskAccessor, spDoseAccessor)); CHECK_EQUAL(spMaskAccessor->isGridHomogeneous(), true); core::GenericMaskedDoseIterator genMaskedDoseIterator(spMaskAccessor, spDoseAccessor); core::GenericMaskedDoseIterator genMaskedDoseIteratorInhomo(spMaskAccessor, spDoseAccessorInhomo); //2) test reset/next const DummyMaskAccessor::MaskVoxelListPointer maskedVoxelListPtr = spTestMaskAccessor1->getRelevantVoxelVector(); genMaskedDoseIterator.reset(); const DoseVoxelVolumeType homogeneousVoxelVolume = genMaskedDoseIterator.getCurrentVoxelVolume(); CHECK_EQUAL((maskedVoxelListPtr->begin())->getVoxelGridID(), genMaskedDoseIterator.getCurrentVoxelGridID()); geoInfo = spDoseAccessor->getGeometricInfo(); SpacingVectorType3D spacing = geoInfo.getSpacing(); CHECK_EQUAL(spacing(0)*spacing(1)*spacing(2) / 1000, genMaskedDoseIterator.getCurrentVoxelVolume()); CHECK_THROW_EXPLICIT(genMaskedDoseIteratorInhomo.getCurrentVoxelVolume(), core::InvalidParameterException); genMaskedDoseIterator.reset(); for (unsigned int i = 0; i < maskedVoxelListPtr->size(); i++) { CHECK_NO_THROW(genMaskedDoseIterator.next()); } CHECK_EQUAL(genMaskedDoseIterator.getCurrentRelevantVolumeFraction(), 0); //check if the correct voxels are accessed genMaskedDoseIterator.reset(); VoxelGridID defaultDoseVoxelGridID = genMaskedDoseIterator.getCurrentVoxelGridID(); DoseTypeGy controlValue = 0; VoxelGridID position = 0; while (genMaskedDoseIterator.isPositionValid()) { controlValue = doseVals->at((maskedVoxelListPtr->at(position)).getVoxelGridID()); CHECK_EQUAL(controlValue, genMaskedDoseIterator.getCurrentDoseValue()); controlValue = controlValue * (maskedVoxelListPtr->at(position)).getRelevantVolumeFraction(); CHECK_EQUAL(controlValue, genMaskedDoseIterator.getCurrentMaskedDoseValue()); CHECK_EQUAL(homogeneousVoxelVolume, genMaskedDoseIterator.getCurrentVoxelVolume()); CHECK_EQUAL((maskedVoxelListPtr->at(position)).getRelevantVolumeFraction(), genMaskedDoseIterator.getCurrentRelevantVolumeFraction()); CHECK_EQUAL((maskedVoxelListPtr->at(position)).getVoxelGridID(), genMaskedDoseIterator.getCurrentVoxelGridID()); CHECK(genMaskedDoseIterator.isPositionValid()); genMaskedDoseIterator.next(); position++; } //check isPositionValid() in invalid positions CHECK(!(genMaskedDoseIterator.isPositionValid())); //after end of dose genMaskedDoseIterator.reset(); CHECK_EQUAL(defaultDoseVoxelGridID, genMaskedDoseIterator.getCurrentVoxelGridID()); CHECK(genMaskedDoseIterator.isPositionValid());//at start of dose RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/core/GeometricInfoTest.cpp b/testing/core/GeometricInfoTest.cpp index 52ee032..2e2ec50 100644 --- a/testing/core/GeometricInfoTest.cpp +++ b/testing/core/GeometricInfoTest.cpp @@ -1,561 +1,555 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include "litCheckMacros.h" #include "rttbBaseType.h" #include "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, geometryCoordinateToWorldCoordinate(), worldCoordinateToGeometryCoordinate(), indexToWorldCoordinate() 13) test getNumberOfVoxels 14) Test convert, validID and validIndex */ 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; DoubleVoxelGridIndex3D testDoubleIndex; DoubleVoxelGridIndex3D doubleIndex1 = DoubleVoxelGridIndex3D(0.1, 0, -0.3); const WorldCoordinate3D expectedDoubleIndex1(20.1, 100, -1000.3); DoubleVoxelGridIndex3D doubleIndex2 = DoubleVoxelGridIndex3D(11, 6, 15); //outside const WorldCoordinate3D expectedDoubleIndex2(31, 106, -985); DoubleVoxelGridIndex3D doubleIndex3 = DoubleVoxelGridIndex3D(10.1, 5.0, 3.0); // outside: Grid dimension = [10,5,3] const WorldCoordinate3D expectedDoubleIndex3(30.1, 105, -997); DoubleVoxelGridIndex3D doubleIndex4 = DoubleVoxelGridIndex3D(0.0, 0.0, 0.0); const WorldCoordinate3D expectedDoubleIndex4 = geoInfo.getImagePositionPatient(); //test double index to world coordinate geoInfo.geometryCoordinateToWorldCoordinate(doubleIndex1, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, expectedDoubleIndex1); geoInfo.geometryCoordinateToWorldCoordinate(doubleIndex2, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, expectedDoubleIndex2); geoInfo.geometryCoordinateToWorldCoordinate(doubleIndex3, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, expectedDoubleIndex3); geoInfo.geometryCoordinateToWorldCoordinate(doubleIndex4, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, expectedDoubleIndex4); geoInfo.worldCoordinateToGeometryCoordinate(expectedDoubleIndex4, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndex4); geoInfo.worldCoordinateToGeometryCoordinate(expectedDoubleIndex3, testDoubleIndex); CHECK_CLOSE(testDoubleIndex(0), doubleIndex3(0), errorConstant); CHECK_CLOSE(testDoubleIndex(1), doubleIndex3(1), errorConstant); CHECK_CLOSE(testDoubleIndex(2), doubleIndex3(2), errorConstant); geoInfo.worldCoordinateToGeometryCoordinate(expectedDoubleIndex2, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndex2); geoInfo.worldCoordinateToGeometryCoordinate(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, geometryCoordinateToWorldCoordinate(), worldCoordinateToGeometryCoordinate(), 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 DoubleVoxelGridIndex3D doubleIndexPixelOutside1 = DoubleVoxelGridIndex3D(-0.501, 0.0, 0.0); const DoubleVoxelGridIndex3D doubleIndexPixelOutside2 = DoubleVoxelGridIndex3D(0.0, 9.501, 0.0); const DoubleVoxelGridIndex3D doubleIndexPixelZero1 = DoubleVoxelGridIndex3D(0.0, 0.0, 0.0); const DoubleVoxelGridIndex3D doubleIndexPixelZero2 = DoubleVoxelGridIndex3D(-0.5, -0.5, -0.5); const DoubleVoxelGridIndex3D doubleIndexPixelZero3 = DoubleVoxelGridIndex3D(0.499999, 0.499999, 0.499999); const DoubleVoxelGridIndex3D doubleIndexPixelOne1 = DoubleVoxelGridIndex3D(1.0, 0.0, 0.0); const DoubleVoxelGridIndex3D doubleIndexPixelOne2 = DoubleVoxelGridIndex3D(0.5, 0.499999, 0.499999); const DoubleVoxelGridIndex3D doubleIndexPixelOne3 = DoubleVoxelGridIndex3D(1.49, -0.5, -0.5); const DoubleVoxelGridIndex3D doubleIndexPixelLast1 = DoubleVoxelGridIndex3D(9.0, 9.0, 9.0); const DoubleVoxelGridIndex3D doubleIndexPixelLast2 = DoubleVoxelGridIndex3D(9.4999, 9.4999, 9.4999); const DoubleVoxelGridIndex3D doubleIndexPixelLast3 = DoubleVoxelGridIndex3D(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.geometryCoordinateToWorldCoordinate(doubleIndexPixelOutside1, testWorldCoordinate); CHECK(!isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelOutside2, testWorldCoordinate); CHECK(!isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelZero1, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelZero1); CHECK(isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelZero2, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelZero2); CHECK(isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelZero3, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelZero3); CHECK(isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelOne1, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelOne1); CHECK(isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelOne2, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelOne2); CHECK(isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelOne3, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelOne3); CHECK(isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelLast1, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelLast1); CHECK(isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelLast2, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelLast2); CHECK(isInside); isInside = geoInfoSimple.geometryCoordinateToWorldCoordinate(doubleIndexPixelLast3, testWorldCoordinate); CHECK_EQUAL(testWorldCoordinate, worldCoordinatePixelLast3); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinateOutside1, testDoubleIndex); CHECK(!isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinateOutside2, testDoubleIndex); CHECK(!isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelZero1, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelZero1); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelZero2, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelZero2); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelZero3, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelZero3); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelOne1, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelOne1); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelOne2, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelOne2); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelOne3, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelOne3); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelLast1, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelLast1); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(worldCoordinatePixelLast2, testDoubleIndex); CHECK_EQUAL(testDoubleIndex, doubleIndexPixelLast2); CHECK(isInside); isInside = geoInfoSimple.worldCoordinateToGeometryCoordinate(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; VoxelGridID aId; 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)); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/core/MaskVoxelTest.cpp b/testing/core/MaskVoxelTest.cpp index f573f29..db593bd 100644 --- a/testing/core/MaskVoxelTest.cpp +++ b/testing/core/MaskVoxelTest.cpp @@ -1,101 +1,95 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbMaskVoxel.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace testing { /*! @brief MaskVoxelTest - test the API of MaskVoxel 1) test constructors (values as expected?) 2) test set/getRelevantVolumeFraction 3) test operators "==" 4) test operator "<" */ int MaskVoxelTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //1) test constructors (values as expected?) //MaskVoxel(const VoxelGridID& aVoxelGridID); VoxelGridID anID = 5; const FractionType defaultFraction = 1; CHECK_NO_THROW(core::MaskVoxel MaskVoxel(anID)); CHECK_THROW_EXPLICIT(core::MaskVoxel MaskVoxel(-anID), core::InvalidParameterException); core::MaskVoxel aMaskVoxel2(anID); CHECK_EQUAL(anID, aMaskVoxel2.getVoxelGridID()); CHECK_EQUAL(defaultFraction, aMaskVoxel2.getRelevantVolumeFraction()); //MaskVoxel(const VoxelGridID& aVoxelGridID, FractionType aVolumeFraction) anID = 15; FractionType aFraction = 0.73; CHECK_NO_THROW(core::MaskVoxel MaskVoxel(anID, aFraction)); CHECK_THROW_EXPLICIT(core::MaskVoxel MaskVoxel(-anID, aFraction), core::InvalidParameterException); CHECK_THROW_EXPLICIT(core::MaskVoxel MaskVoxel(anID, -aFraction), core::InvalidParameterException); CHECK_THROW_EXPLICIT(core::MaskVoxel MaskVoxel(-anID, -aFraction), core::InvalidParameterException); CHECK_THROW_EXPLICIT(core::MaskVoxel MaskVoxel(anID, aFraction + 2), core::InvalidParameterException); CHECK_THROW_EXPLICIT(core::MaskVoxel MaskVoxel(-anID, aFraction + 2), core::InvalidParameterException); core::MaskVoxel aMaskVoxel3(anID, aFraction); CHECK_EQUAL(anID, aMaskVoxel3.getVoxelGridID()); CHECK_EQUAL(aFraction, aMaskVoxel3.getRelevantVolumeFraction()); //2) test set/getRelevantVolumeFraction aFraction = 0.42; anID = aMaskVoxel3.getVoxelGridID(); CHECK_NO_THROW(aMaskVoxel3.setRelevantVolumeFraction(aFraction)); CHECK_THROW_EXPLICIT(aMaskVoxel3.setRelevantVolumeFraction(-aFraction), core::InvalidParameterException); CHECK_THROW_EXPLICIT(aMaskVoxel3.setRelevantVolumeFraction(aFraction + 2), core::InvalidParameterException); aMaskVoxel3.setRelevantVolumeFraction(aFraction); CHECK_EQUAL(anID, aMaskVoxel3.getVoxelGridID()); CHECK_EQUAL(aFraction, aMaskVoxel3.getRelevantVolumeFraction()); //3) test operators "==" CHECK(!(aMaskVoxel2 == aMaskVoxel3)); //not equal core::MaskVoxel aMaskVoxel4(aMaskVoxel3.getVoxelGridID()); CHECK(!(aMaskVoxel4 == aMaskVoxel3)); //equal ID, but unequal volume fraction -> not equal aMaskVoxel4.setRelevantVolumeFraction(aMaskVoxel3.getRelevantVolumeFraction()); CHECK_EQUAL(aMaskVoxel4, aMaskVoxel3); //equal aMaskVoxel2.setRelevantVolumeFraction(aMaskVoxel3.getRelevantVolumeFraction()); CHECK(!(aMaskVoxel2 == aMaskVoxel3)); //no equal ID -> not equal //4) test operator "<" core::MaskVoxel aMaskVoxel5(2); CHECK(aMaskVoxel2 < aMaskVoxel3); CHECK(!(aMaskVoxel3 < aMaskVoxel4)); CHECK(!(aMaskVoxel4 < aMaskVoxel5)); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/core/StrVectorStructureSetGeneratorTest.cpp b/testing/core/StrVectorStructureSetGeneratorTest.cpp index 0eb0622..1b9c23b 100644 --- a/testing/core/StrVectorStructureSetGeneratorTest.cpp +++ b/testing/core/StrVectorStructureSetGeneratorTest.cpp @@ -1,95 +1,89 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbStrVectorStructureSetGenerator.h" #include "DummyStructure.h" #include "DummyDoseAccessor.h" #include "rttbInvalidParameterException.h" #include "rttbStructure.h" namespace rttb { namespace testing { /*! @brief StrVectorStructureSetGeneratorTest - tests the API for Structure 1) empty structure vector 2) dummy structure 3) with regex */ int StrVectorStructureSetGeneratorTest(int argc, char* argv[]) { typedef core::Structure::Pointer StructTypePointer; PREPARE_DEFAULT_TEST_REPORTING; //1) empty structure vector std::vector strVector; CHECK_NO_THROW(core::StrVectorStructureSetGenerator generator1(strVector)); CHECK_NO_THROW(core::StrVectorStructureSetGenerator(strVector).generateStructureSet()); CHECK_EQUAL(core::StrVectorStructureSetGenerator( strVector).generateStructureSet()->getNumberOfStructures(), 0); CHECK_THROW_EXPLICIT(core::StrVectorStructureSetGenerator( strVector).generateStructureSet()->getStructure(0), core::InvalidParameterException); //2) dummy structure boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DummyStructure myStructGenerator(spTestDoseAccessor->getGeometricInfo()); GridIndexType zPlane = 4; core::Structure rect = myStructGenerator.CreateRectangularStructureCentered(zPlane); StructTypePointer rectStrPtr = boost::make_shared(rect); rectStrPtr->setLabel("test"); strVector.push_back(rectStrPtr); CHECK_NO_THROW(core::StrVectorStructureSetGenerator generator2(strVector)); CHECK_NO_THROW(core::StrVectorStructureSetGenerator(strVector).generateStructureSet()); CHECK_EQUAL(core::StrVectorStructureSetGenerator( strVector).generateStructureSet()->getNumberOfStructures(), 1); CHECK_NO_THROW(core::StrVectorStructureSetGenerator(strVector).generateStructureSet()->getStructure( 0)); //3) with regex StructTypePointer rectStrPtr2 = boost::make_shared(rect); rectStrPtr2->setLabel("none"); strVector.push_back(rectStrPtr2); core::StrVectorStructureSetGenerator generator(strVector); generator.setStructureLabelFilterActive(true); generator.setFilterRegEx("test"); CHECK_NO_THROW(generator.generateStructureSet()); CHECK_EQUAL(generator.generateStructureSet()->getNumberOfStructures(), 1); CHECK_EQUAL(generator.generateStructureSet()->getStructure(0)->getLabel(), "test"); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb \ No newline at end of file diff --git a/testing/core/StructureSetTest.cpp b/testing/core/StructureSetTest.cpp index add189c..0a3932f 100644 --- a/testing/core/StructureSetTest.cpp +++ b/testing/core/StructureSetTest.cpp @@ -1,82 +1,76 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include #include "litCheckMacros.h" #include "DummyStructure.h" #include "DummyDoseAccessor.h" #include "rttbInvalidParameterException.h" #include "rttbStructure.h" #include "rttbStructureSet.h" namespace rttb { namespace testing { /*! @brief StructureSet - tests the API for StructureSet 1) constructor 2) getters */ int StructureSetTest(int argc, char* argv[]) { typedef core::Structure::Pointer StructTypePointer; PREPARE_DEFAULT_TEST_REPORTING; boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DummyStructure myStructGenerator(spTestDoseAccessor->getGeometricInfo()); GridIndexType zPlane = 4; core::Structure rect = myStructGenerator.CreateRectangularStructureCentered(zPlane); StructTypePointer rectStrPtr = boost::make_shared(rect); rectStrPtr->setLabel("test"); StructTypePointer rectStrPtr2 = boost::make_shared(rect); rectStrPtr2->setLabel("test2"); const IDType patientUID("patientUID"); const IDType UID("UID"); //1) constructor CHECK_NO_THROW(core::StructureSet({ })); core::StructureSet structureSetDefault({ }); CHECK_NO_THROW(core::StructureSet({ rectStrPtr, rectStrPtr2 }, patientUID, UID)); core::StructureSet structureSet({rectStrPtr, rectStrPtr2}, patientUID, UID); //2) getters CHECK_EQUAL(structureSetDefault.getNumberOfStructures(), 0); CHECK_EQUAL(structureSet.getNumberOfStructures(), 2); CHECK_EQUAL(structureSet.getStructure(0)->getLabel(), "test"); CHECK_EQUAL(structureSet.getStructure(1)->getLabel(), "test2"); CHECK_THROW_EXPLICIT(structureSet.getStructure(2), core::InvalidParameterException); CHECK_EQUAL(structureSet.getUID(), UID); CHECK_EQUAL(structureSet.getPatientUID(), patientUID); CHECK_NO_THROW(structureSetDefault.getUID()); CHECK_NO_THROW(structureSetDefault.getPatientUID()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb \ No newline at end of file diff --git a/testing/core/StructureTest.cpp b/testing/core/StructureTest.cpp index c55fb5f..59827e1 100644 --- a/testing/core/StructureTest.cpp +++ b/testing/core/StructureTest.cpp @@ -1,138 +1,132 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #include #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbStructure.h" #include "rttbInvalidParameterException.h" #include "DummyStructure.h" #include "DummyDoseAccessor.h" namespace rttb { namespace testing { /*! @brief StructureTest - tests the API for Structure 1) constructors 2) get/setXX */ int StructureTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DummyStructure myStructGenerator(spTestDoseAccessor->getGeometricInfo()); //1) constructors CHECK_NO_THROW(core::Structure()); core::Structure emptyTestStruct; CHECK_EQUAL("", emptyTestStruct.getLabel()); CHECK_NO_THROW(emptyTestStruct.getUID()); GridIndexType zPlane = 4; core::Structure rect = myStructGenerator.CreateRectangularStructureCentered(zPlane); CHECK_NO_THROW(core::Structure(rect.getStructureVector())); core::Structure rect2 = core::Structure(rect.getStructureVector()); CHECK_EQUAL(rect.getLabel(), rect2.getLabel()); CHECK(rect.getUID() != rect2.getUID()); PolygonSequenceType rectVec = rect.getStructureVector(); PolygonSequenceType rect2Vec = rect2.getStructureVector(); CHECK_EQUAL(rectVec.size(), rect2Vec.size()); PolygonSequenceType::iterator it = rectVec.begin(); PolygonSequenceType::iterator it2 = rect2Vec.begin(); for (; it != rectVec.end(); ++it) { CHECK_EQUAL(it->size(), it2->size()); PolygonType::iterator pit = it->begin(); PolygonType::iterator pit2 = it2->begin(); for (; pit != it->end(); ++pit) { CHECK_EQUAL(*(pit), *(pit2)); ++pit2; } ++it2; } CHECK_NO_THROW(core::Structure rect3 = rect); core::Structure rect3 = rect; CHECK_EQUAL(rect.getLabel(), rect3.getLabel()); CHECK_EQUAL(rect.getUID(), rect3.getUID()); PolygonSequenceType rect3Vec = rect3.getStructureVector(); CHECK_EQUAL(rectVec.size(), rect3Vec.size()); it = rectVec.begin(); PolygonSequenceType::iterator it3 = rect3Vec.begin(); for (; it != rectVec.end(); ++it) { CHECK_EQUAL(it->size(), it3->size()); PolygonType::iterator pit = it->begin(); PolygonType::iterator pit3 = it3->begin(); for (; pit != it->end(); ++pit) { CHECK_EQUAL(*(pit), *(pit3)); ++pit3; } ++it3; } //2) get/setXX CHECK_EQUAL("", emptyTestStruct.getLabel()); CHECK_NO_THROW(emptyTestStruct.setLabel("NEW Label")); CHECK_EQUAL("NEW Label", emptyTestStruct.getLabel()); CHECK_NO_THROW(emptyTestStruct.getUID()); CHECK_NO_THROW(emptyTestStruct.setUID("1.2.345.67.8.9")); CHECK_EQUAL("1.2.345.67.8.9", emptyTestStruct.getUID()); CHECK((emptyTestStruct.getStructureVector()).empty()); CHECK_EQUAL(0, emptyTestStruct.getNumberOfEndpoints()); CHECK_EQUAL(4, rect.getNumberOfEndpoints()); CHECK_EQUAL(rect.getNumberOfEndpoints(), rect2.getNumberOfEndpoints()); core::Structure circ = myStructGenerator.CreateTestStructureCircle(zPlane); CHECK_EQUAL(4004, circ.getNumberOfEndpoints()); core::Structure multiPoly = myStructGenerator.CreateTestStructureIntersectingTwoPolygonsInDifferentSlices(zPlane, zPlane + 1); CHECK_EQUAL(8, multiPoly.getNumberOfEndpoints()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/core/rttbCoreTests.cpp b/testing/core/rttbCoreTests.cpp index fb9dd3b..04df057 100644 --- a/testing/core/rttbCoreTests.cpp +++ b/testing/core/rttbCoreTests.cpp @@ -1,73 +1,67 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests #if defined(_MSC_VER) #pragma warning ( disable : 4786 ) #endif #include "litMultiTestsMain.h" namespace rttb { namespace testing { void registerTests() { LIT_REGISTER_TEST(GeometricInfoTest); LIT_REGISTER_TEST(MaskVoxelTest); LIT_REGISTER_TEST(GenericDoseIteratorTest); LIT_REGISTER_TEST(GenericMaskedDoseIteratorTest); LIT_REGISTER_TEST(DVHCalculatorTest); LIT_REGISTER_TEST(DVHTest); LIT_REGISTER_TEST(DVHSetTest); LIT_REGISTER_TEST(GeometricInfoTest); LIT_REGISTER_TEST(MaskVoxelTest); LIT_REGISTER_TEST(GenericDoseIteratorTest); LIT_REGISTER_TEST(StructureTest); LIT_REGISTER_TEST(StrVectorStructureSetGeneratorTest); LIT_REGISTER_TEST(StructureSetTest); LIT_REGISTER_TEST(BaseTypeTest); } } } int main(int argc, char* argv[]) { int result = 0; rttb::testing::registerTests(); try { result = lit::multiTestsMain(argc, argv); } catch (...) { result = -1; } return result; }