diff --git a/code/core/rttbDVH.cpp b/code/core/rttbDVH.cpp index cde17be..2209293 100644 --- a/code/core/rttbDVH.cpp +++ b/code/core/rttbDVH.cpp @@ -1,426 +1,387 @@ // ----------------------------------------------------------------------- // 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(bool relativeVolume) const + std::deque DVH::getDataDifferential() const { - if (!relativeVolume) - { - return _dataDifferential; - } - else - { - return _dataDifferentialRelative; - } + return _dataDifferential; } - std::deque DVH::getDataCumulative(bool relativeVolume) const - { - if (!relativeVolume) - { - return _dataCumulative; - } - else - { - return _dataCumulativeRelative; - } - } + 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(); - _dataCumulativeRelative.clear(); - _dataDifferentialRelative.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; - for (it = _dataDifferential.begin(); it != _dataDifferential.end(); ++it) - { - DoseCalcType datai = ((*it) * 1.0 / _numberOfVoxels); - _dataDifferentialRelative.push_back(datai); - } - _variance = (squareSum / _numberOfVoxels - _mean * _mean); _stdDeviation = pow(_variance, 0.5); this->calcCumulativeDVH(); } void DVH::calcCumulativeDVH() { _dataCumulative.clear(); - _dataCumulativeRelative.clear(); DoseCalcType cumulativeDVHi = 0; - for (auto valueItr = _dataDifferential.rbegin(); valueItr != _dataDifferential.rend(); ++valueItr) { - cumulativeDVHi += *valueItr; + for (auto valueItr = _dataDifferential.rbegin(); valueItr != _dataDifferential.rend(); ++valueItr) { + cumulativeDVHi += *valueItr; _dataCumulative.push_front(cumulativeDVHi); - _dataCumulativeRelative.push_front(cumulativeDVHi / this->getNumberOfVoxels()); } } 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 if (i < _dataCumulativeRelative.size()) - { - VolumeType vx = (_dataCumulativeRelative.at(i)); - vx = (vx * this->_deltaV); - return vx; - } else { return 0; } } DoseTypeGy DVH::getDx(VolumeType xVolumeAbsolute) const { - GridIndexType i = 0; - if (!_dataCumulative.empty()) + for (; i < _dataCumulative.size(); i++) { - for (; i < _dataCumulative.size(); i++) - { - double volumeAbsoluteI = _dataCumulative[i] * this->_deltaV; + double volumeAbsoluteI = _dataCumulative[i] * this->_deltaV; - if (xVolumeAbsolute > volumeAbsoluteI) - { - break; - } - } - } - else - { - for (; i < _dataCumulativeRelative.size(); i++) + if (xVolumeAbsolute > volumeAbsoluteI) { - double volumeAbsoluteI = _dataCumulativeRelative[i] * this->_deltaV; - - if (xVolumeAbsolute / this->getNumberOfVoxels() > volumeAbsoluteI) - { - break; - } + break; } } if (i <= _dataCumulative.size() && i > 0) { DoseTypeGy dx = (i - 1) * this->_deltaD; return dx; } - else if (i < _dataCumulativeRelative.size() && i > 0) - { - DoseTypeGy dx = (i - 1) * this->_deltaD; - return dx; - } else { return 0; } } VolumeType DVH::getAbsoluteVolume(int relativePercent) const { return (relativePercent * getNumberOfVoxels() * getDeltaV() / 100.0); } + std::deque DVH::getRelativeFromAbsolut(DataDifferentialType absoluteData) const + { + + DataDifferentialType relativeData; + 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(); - } + else { + data = getDataDifferential(); + } - if (data.empty()) { - throw InvalidParameterException("DVH data is empty. Can't retrieve normalized DVH"); - } + 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 f6359b1..cd00d41 100644 --- a/code/core/rttbDVH.h +++ b/code/core/rttbDVH.h @@ -1,212 +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 "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; using DVHPointer = boost::shared_ptr; 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 Differential dvh data relative to the total number of voxels - */ - DataDifferentialType _dataDifferentialRelative; + /*! @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; - DataDifferentialType _dataCumulativeRelative; /*! @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(bool relativeVolume = false) const; + 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(bool relativeVolume = false) const; + 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 getRelativeFromAbsolut(DataDifferentialType absoluteData) 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; }; } } #endif diff --git a/testing/core/DVHTest.cpp b/testing/core/DVHTest.cpp index 5e8b605..cf21fb5 100644 --- a/testing/core/DVHTest.cpp +++ b/testing/core/DVHTest.cpp @@ -1,242 +1,242 @@ // ----------------------------------------------------------------------- // 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(false) == aDataDifferential); - CHECK(myDVH.getDataDifferential(true) == aDataDifferentialRelative); + CHECK(myDVH.getDataDifferential() == aDataDifferential); + CHECK(myDVH.getRelativeFromAbsolut(myDVH.getDataDifferential()) == 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(true)); + CHECK_NO_THROW(myDVH.getDataCumulative()); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/examples/RTDVHTest.cpp b/testing/examples/RTDVHTest.cpp index 3ef2e8f..86e0c25 100644 --- a/testing/examples/RTDVHTest.cpp +++ b/testing/examples/RTDVHTest.cpp @@ -1,110 +1,110 @@ // ----------------------------------------------------------------------- // 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 "litCheckMacros.h" #include "rttbDVH.h" #include "rttbBaseType.h" #include "rttbDvhBasedModels.h" #include "rttbDVHXMLFileReader.h" namespace rttb { namespace testing { /*! @brief RTDVHTest. Max, min, mean, modal, median, Vx, Dx, EUD, BED, LQED2 are tested. Test if calculation in new architecture returns similar results to the original implementation. Comparison of actual DVH values is performed in DVHCalculatorComparisonTest.cpp. WARNING: The values for comparison need to be adjusted if the input files are changed! */ int RTDVHTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //ARGUMENTS: 1: dvh file name std::string RTDVH_FILENAME_PTV; if (argc > 1) { RTDVH_FILENAME_PTV = argv[1]; } typedef core::DVH::DVHPointer DVHPointer; /*test RT dvh*/ rttb::io::other::DVHXMLFileReader dvhReader = rttb::io::other::DVHXMLFileReader(RTDVH_FILENAME_PTV); const DoseCalcType expectedValue = 0.01305; //dvhReader DVHPointer dvh = dvhReader.generateDVH(); CHECK_CLOSE(expectedValue, models::getEUD(dvh, 10), errorConstant); std::cout << models::getEUD(dvh, 10) << std::endl; CHECK_NO_THROW(models::calcBEDDVH(dvh, 15, 15)); CHECK_NO_THROW(models::calcLQED2DVH(dvh, 15, 10)); - CHECK_NO_THROW(dvh->getDataDifferential(true)); - CHECK_EQUAL(1, dvh->getDataCumulative(true).at(0)); + CHECK_NO_THROW(dvh->getDataDifferential()); + CHECK_EQUAL(1, dvh->getRelativeFromAbsolut(dvh->getDataCumulative()).at(0)); CHECK_NO_THROW(models::calcBEDDVH(dvh, 15, 15, true)); CHECK_NO_THROW(models::calcLQED2DVH(dvh, 15, 10, true)); //test statistics (relative cumulative data) CHECK_CLOSE(expectedValue, dvh->getMaximum(), errorConstant); CHECK_CLOSE(expectedValue, dvh->getMinimum(), errorConstant); CHECK_CLOSE(expectedValue, dvh->getMean(), errorConstant); CHECK_CLOSE(expectedValue, dvh->getMedian(), errorConstant); CHECK_CLOSE(expectedValue, dvh->getModal(), errorConstant); CHECK_EQUAL(0, dvh->getVx(0.014)); CHECK_EQUAL(250, dvh->getVx(0.01)); CHECK_CLOSE(0.0131, dvh->getDx(100), errorConstant + errorConstant * 10); CHECK_CLOSE(0.013, dvh->getDx(249), errorConstant); CHECK_EQUAL(0, dvh->getDx(251)); //test statistics (absolute cumulative data) - CHECK_EQUAL(2000, dvh->getDataCumulative(false).at(0)); + CHECK_EQUAL(2000, dvh->getDataCumulative().at(0)); CHECK_EQUAL(0, dvh->getVx(0.014)); CHECK_EQUAL(250, dvh->getVx(0.01)); CHECK_CLOSE(0.0131, dvh->getDx(100), errorConstant + errorConstant * 10); CHECK_CLOSE(0.013, dvh->getDx(249), errorConstant); CHECK_EQUAL(0, dvh->getDx(251)); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb