diff --git a/code/algorithms/rttbDoseStatistics.cpp b/code/algorithms/rttbDoseStatistics.cpp index 540bbad..b3140e1 100644 --- a/code/algorithms/rttbDoseStatistics.cpp +++ b/code/algorithms/rttbDoseStatistics.cpp @@ -1,328 +1,327 @@ // ----------------------------------------------------------------------- // 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 "rttbDoseStatistics.h" #include "boost/make_shared.hpp" #include "rttbDataNotAvailableException.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace algorithms { - DoseStatistics::DoseStatistics(DoseStatisticType minimum, DoseStatisticType maximum, - DoseStatisticType mean, - DoseStatisticType stdDeviation, VoxelNumberType numVoxels, VolumeType volume, - ResultListPointer maximumVoxelPositions /*= ResultListPointer()*/, - ResultListPointer minimumVoxelPositions /*= ResultListPointer()*/, - VolumeToDoseMeasure Dx /*= VolumeToDoseMeasure(VolumeToDoseMeasure::complexStatistics::Dx)*/, - DoseToVolumeFunctionType Vx /*= std::map()*/, - VolumeToDoseMeasure MOHx /*= std::map()*/, - VolumeToDoseMeasure MOCx /*= std::map()*/, - VolumeToDoseMeasure MaxOHx /*= std::map()*/, - VolumeToDoseMeasure MinOCx /*= std::map()*/, - DoseTypeGy referenceDose /*=-1*/): + DoseStatistics::DoseStatistics(DoseStatisticType minimum, DoseStatisticType maximum, DoseStatisticType mean, + DoseStatisticType stdDeviation, VoxelNumberType numVoxels, VolumeType volume, + ResultListPointer maximumVoxelPositions /*= ResultListPointer()*/, + ResultListPointer minimumVoxelPositions /*= ResultListPointer()*/, + VolumeToDoseMeasure Dx, + DoseToVolumeFunctionType Vx, + VolumeToDoseMeasure MOHx, + VolumeToDoseMeasure MOCx, + VolumeToDoseMeasure MaxOHx, + VolumeToDoseMeasure MinOCx, + DoseTypeGy referenceDose /*=-1*/): _minimum(minimum), _maximum(maximum), _mean(mean), _stdDeviation(stdDeviation), _numVoxels(numVoxels), _volume(volume), _Dx(Dx), _Vx(Vx), _MOHx(MOHx), _MOCx(MOCx), _MaxOHx(MaxOHx), _MinOCx(MinOCx) { if (maximumVoxelPositions == NULL) { _maximumVoxelPositions = boost::make_shared > > (std::vector >()); } else { _maximumVoxelPositions = maximumVoxelPositions; } if (minimumVoxelPositions == NULL) { _minimumVoxelPositions = boost::make_shared > > (std::vector >()); } else { _minimumVoxelPositions = minimumVoxelPositions; } if (referenceDose <= 0) { _referenceDose = _maximum; } else { _referenceDose = referenceDose; } } DoseStatistics::~DoseStatistics() { } void DoseStatistics::setMinimumVoxelPositions(ResultListPointer minimumVoxelPositions) { _minimumVoxelPositions = minimumVoxelPositions; } void DoseStatistics::setMaximumVoxelPositions(ResultListPointer maximumVoxelPositions) { _maximumVoxelPositions = maximumVoxelPositions; } void DoseStatistics::setDx(const VolumeToDoseMeasure& DxValues) { _Dx = DxValues; } void DoseStatistics::setVx(const VolumeToDoseFunctionType& VxValues) { _Vx = VxValues; } void DoseStatistics::setMOHx(const VolumeToDoseMeasure& MOHxValues) { _MOHx = MOHxValues; } void DoseStatistics::setMOCx(const VolumeToDoseMeasure& MOCxValues) { _MOCx = MOCxValues; } void DoseStatistics::setMaxOHx(const VolumeToDoseMeasure& MaxOHValues) { _MaxOHx = MaxOHValues; } void DoseStatistics::setMinOCx(const VolumeToDoseMeasure& MinOCValues) { _MinOCx = MinOCValues; } void DoseStatistics::setReferenceDose(DoseTypeGy referenceDose) { if (referenceDose <= 0) { _referenceDose = _maximum; } else { _referenceDose = referenceDose; } } VoxelNumberType DoseStatistics::getNumberOfVoxels() const { return _numVoxels; } VolumeType DoseStatistics::getVolume() const { return _volume; } DoseTypeGy DoseStatistics::getReferenceDose() const { return _referenceDose; } DoseStatisticType DoseStatistics::getMaximum() const { return _maximum; } DoseStatisticType DoseStatistics::getMinimum() const { return _minimum; } DoseStatisticType DoseStatistics::getMean() const { return _mean; } DoseStatisticType DoseStatistics::getStdDeviation() const { return _stdDeviation; } DoseStatisticType DoseStatistics::getVariance() const { return _stdDeviation * _stdDeviation; } VolumeType DoseStatistics::getVx(DoseTypeGy xDoseAbsolute, bool findNearestValue, DoseTypeGy& nearestXDose) const { return getValue(_Vx, xDoseAbsolute, findNearestValue, nearestXDose); } VolumeType DoseStatistics::getVx(DoseTypeGy xDoseAbsolute) const { DoseTypeGy dummy; return getValue(_Vx, xDoseAbsolute, false, dummy); } VolumeType DoseStatistics::getVxRelative(DoseTypeGy xDoseRelative) const { if (_referenceDose != -1 && xDoseRelative >=0 && xDoseRelative <=1){ DoseTypeGy xDoseAbsolute = xDoseRelative * _referenceDose; DoseTypeGy dummy; return getValue(_Vx, xDoseAbsolute, false, dummy); } else { throw rttb::core::InvalidParameterException("Reference dose must be > 0 and 0 <= relative Dose <= 1"); } } VolumeType DoseStatistics::getVxRelative(DoseTypeGy xDoseRelative, bool findNearestValue, DoseTypeGy& nearestXDose) const { if (_referenceDose != -1 && xDoseRelative >= 0 && xDoseRelative <= 1){ DoseTypeGy xDoseAbsolute = xDoseRelative * _referenceDose; return getValue(_Vx, xDoseAbsolute, findNearestValue, nearestXDose); } else { throw rttb::core::InvalidParameterException("Reference dose must be > 0 and 0 <= relative Dose <= 1"); } } double DoseStatistics::getValue(const std::map& aMap, double key, bool findNearestValueInstead, double& storedKey) const { if (aMap.find(key) != std::end(aMap)) { return aMap.find(key)->second; } else { //value not in map. We have to find the nearest value if (aMap.empty()) { throw core::DataNotAvailableException("No Vx values are defined"); } else { if (findNearestValueInstead) { auto iterator = findNearestKeyInMap(aMap, key); storedKey = iterator->first; return iterator->second; } else { throw core::DataNotAvailableException("No Vx value with required dose is defined"); } } } } std::map::const_iterator DoseStatistics::findNearestKeyInMap( const std::map& aMap, double key) const { double minDistance = 1e19; double minDistanceLast = 1e20; auto iterator = std::begin(aMap); while (iterator != std::end(aMap)) { minDistanceLast = minDistance; minDistance = fabs(iterator->first - key); if (minDistanceLast > minDistance) { ++iterator; } else { if (iterator != std::begin(aMap)) { --iterator; return iterator; } else { return std::begin(aMap); } } } --iterator; return iterator; } DoseStatistics::ResultListPointer DoseStatistics::getMaximumVoxelPositions() const { return _maximumVoxelPositions; } DoseStatistics::ResultListPointer DoseStatistics::getMinimumVoxelPositions() const { return _minimumVoxelPositions; } DoseStatistics::DoseToVolumeFunctionType DoseStatistics::getAllVx() const { return _Vx; } VolumeToDoseMeasure DoseStatistics::getDx() const { return _Dx; } VolumeToDoseMeasure DoseStatistics::getMOHx() const { return _MOHx; } VolumeToDoseMeasure DoseStatistics::getMOCx() const { return _MOCx; } VolumeToDoseMeasure DoseStatistics::getMaxOHx() const { return _MaxOHx; } VolumeToDoseMeasure DoseStatistics::getMinOCx() const { return _MinOCx; } }//end namespace algorithms }//end namespace rttb diff --git a/code/algorithms/rttbDoseStatistics.h b/code/algorithms/rttbDoseStatistics.h index 647a438..84d6a8f 100644 --- a/code/algorithms/rttbDoseStatistics.h +++ b/code/algorithms/rttbDoseStatistics.h @@ -1,185 +1,183 @@ // ----------------------------------------------------------------------- // 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_STATISTICS_H #define __DOSE_STATISTICS_H #include #include #include "boost/shared_ptr.hpp" #include "rttbBaseType.h" #include "RTTBAlgorithmsExports.h" #include "rttbVolumeToDoseMeasure.h" namespace rttb { namespace algorithms { /*! @class DoseStatistics @brief This is a data class storing different statistical values from a rt dose distribution @sa DoseStatisticsCalculator */ class RTTBAlgorithms_EXPORT DoseStatistics { public: enum complexStatistics { Dx, Vx, MOHx, MOCx, MaxOHx, MinOCx }; typedef boost::shared_ptr > > ResultListPointer; typedef boost::shared_ptr DoseStatisticsPointer; typedef std::map DoseToVolumeFunctionType; typedef std::map VolumeToDoseFunctionType; private: double getValue(const std::map& aMap, double key, bool findNearestValueInstead, double& storedKey) const; std::map::const_iterator findNearestKeyInMap(const std::map& aMap, double key) const; DoseStatisticType _maximum; DoseStatisticType _minimum; ResultListPointer _maximumVoxelPositions; ResultListPointer _minimumVoxelPositions; DoseStatisticType _mean; DoseStatisticType _stdDeviation; VoxelNumberType _numVoxels; VolumeType _volume; DoseTypeGy _referenceDose; //for Vx computation VolumeToDoseMeasure _Dx; DoseToVolumeFunctionType _Vx; VolumeToDoseMeasure _MOHx; VolumeToDoseMeasure _MOCx; VolumeToDoseMeasure _MaxOHx; VolumeToDoseMeasure _MinOCx; public: /*! @brief Standard Constructor */ //DoseStatistics(); /*! @brief Constructor @details the dose statistic values are set. Complex values maximumVoxelLocation, maximumVoxelLocation, Dx, Vx, MOHx, MOCx, MaxOHx and MinOCx are optional */ DoseStatistics(DoseStatisticType minimum, DoseStatisticType maximum, DoseStatisticType mean, DoseStatisticType stdDeviation, VoxelNumberType numVoxels, VolumeType volume, - ResultListPointer minimumVoxelPositions = - NULL, - ResultListPointer maximumVoxelPositions = - NULL, - VolumeToDoseMeasure Dx = VolumeToDoseMeasure(VolumeToDoseMeasure::complexStatistics::Dx), - DoseToVolumeFunctionType Vx = DoseToVolumeFunctionType(), - VolumeToDoseMeasure MOHx = VolumeToDoseMeasure(VolumeToDoseMeasure::complexStatistics::MOHx), - VolumeToDoseMeasure MOCx = VolumeToDoseMeasure(VolumeToDoseMeasure::complexStatistics::MOCx), - VolumeToDoseMeasure MaxOHx = VolumeToDoseMeasure(VolumeToDoseMeasure::complexStatistics::MaxOHx), - VolumeToDoseMeasure MinOCx = VolumeToDoseMeasure(VolumeToDoseMeasure::complexStatistics::MinOCx), - DoseTypeGy referenceDose = -1); + ResultListPointer minimumVoxelPositions = NULL, + ResultListPointer maximumVoxelPositions = NULL, + VolumeToDoseMeasure Dx = VolumeToDoseMeasure(VolumeToDoseMeasure::Dx), + DoseToVolumeFunctionType Vx = DoseToVolumeFunctionType(), + VolumeToDoseMeasure MOHx = VolumeToDoseMeasure(VolumeToDoseMeasure::MOHx), + VolumeToDoseMeasure MOCx = VolumeToDoseMeasure(VolumeToDoseMeasure::MOCx), + VolumeToDoseMeasure MaxOHx = VolumeToDoseMeasure(VolumeToDoseMeasure::MaxOHx), + VolumeToDoseMeasure MinOCx = VolumeToDoseMeasure(VolumeToDoseMeasure::MinOCx), + DoseTypeGy referenceDose = -1); ~DoseStatistics(); void setMinimumVoxelPositions(ResultListPointer minimumVoxelPositions); void setMaximumVoxelPositions(ResultListPointer maximumVoxelPositions); void setDx(const VolumeToDoseMeasure& DxValues); void setVx(const VolumeToDoseFunctionType& VxValues); void setMOHx(const VolumeToDoseMeasure& MOHxValues); void setMOCx(const VolumeToDoseMeasure& MOCxValues); void setMaxOHx(const VolumeToDoseMeasure& MaxOHxValues); void setMinOCx(const VolumeToDoseMeasure& MinOCxValues); void setReferenceDose(DoseTypeGy referenceDose); /*! @brief Get number of voxels in doseIterator, with sub-voxel accuracy. */ VoxelNumberType getNumberOfVoxels() const; /*! @brief Get the volume of the voxels in doseIterator (in cm3), with sub-voxel accuracy */ VolumeType getVolume() const; /*! @brief Get the reference dose for Vx computation */ DoseTypeGy getReferenceDose() const; /*! @brief Get the maximum of the current dose distribution. @return Return the maximum dose in Gy */ DoseStatisticType getMaximum() const; /*! @brief Get a vector of the the maximum dose VoxelGridIDs together with their dose value in Gy @exception InvalidDoseException if the vector has not been set (i.e. is empty) */ ResultListPointer getMaximumVoxelPositions() const; /*! @brief Get the minimum of the current dose distribution. @return Return the minimum dose in Gy */ DoseStatisticType getMinimum() const; /*! @brief Get a vector of the the minimum dose VoxelGridIDs together with their dose value in Gy @exception InvalidDoseException if the vector has not been set (i.e. is empty) */ ResultListPointer getMinimumVoxelPositions() const; /*! @brief Get the mean of the current dose distribution. @return Return the mean dose in Gy */ DoseStatisticType getMean() const; /*! @brief Get the standard deviation of the current dose distribution. @return Return the standard deviation in Gy */ DoseStatisticType getStdDeviation() const; /*! @brief Get the variance of of the current dose distribution. @return Return the variance in Gy */ DoseStatisticType getVariance() const; /*! @brief Get Vx: the volume irradiated with a dose >= x. @return Return absolute volume in absolute cm^3. @exception NoDataException if the Vx values have not been set (i.e. the vector is empty) @exception NoDataException if the requested Dose is not in the vector */ VolumeType getVx(DoseTypeGy xDoseAbsolute) const; VolumeType getVx(DoseTypeGy xDoseAbsolute, bool findNearestValue, DoseTypeGy& nearestXDose) const; VolumeType getVxRelative(DoseTypeGy xDoseRelative) const; VolumeType getVxRelative(DoseTypeGy xDoseRelative, bool findNearestValue, DoseTypeGy& nearestXDose) const; DoseToVolumeFunctionType getAllVx() const; VolumeToDoseMeasure getDx() const; VolumeToDoseMeasure getMOHx() const; VolumeToDoseMeasure getMOCx() const; VolumeToDoseMeasure getMaxOHx() const; VolumeToDoseMeasure getMinOCx() const; }; } } #endif diff --git a/code/algorithms/rttbDoseStatisticsCalculator.cpp b/code/algorithms/rttbDoseStatisticsCalculator.cpp index c1d51fb..4aed7b3 100644 --- a/code/algorithms/rttbDoseStatisticsCalculator.cpp +++ b/code/algorithms/rttbDoseStatisticsCalculator.cpp @@ -1,473 +1,473 @@ // ----------------------------------------------------------------------- // 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 "rttbDoseStatisticsCalculator.h" #include #include #include #include #include "rttbNullPointerException.h" #include "rttbInvalidDoseException.h" #include "rttbInvalidParameterException.h" #include "rttbDxVolumeToDoseMeasureCalculator.h" #include "rttbMOHxVolumeToDoseMeasureCalculator.h" #include "rttbMOCxVolumeToDoseMeasureCalculator.h" #include "rttbMaxOHxVolumeToDoseMeasureCalculator.h" #include "rttbMinOCxVolumeToDoseMeasureCalculator.h" #include namespace rttb { namespace algorithms { DoseStatisticsCalculator::DoseStatisticsCalculator(DoseIteratorPointer aDoseIterator) { if (aDoseIterator == NULL) { throw core::NullPointerException("DoseIterator must not be NULL"); } else { _doseIterator = aDoseIterator; } _simpleDoseStatisticsCalculated = false; _multiThreading = false; _mutex = ::boost::make_shared<::boost::shared_mutex>(); } DoseStatisticsCalculator::~DoseStatisticsCalculator() { } DoseStatisticsCalculator::DoseIteratorPointer DoseStatisticsCalculator::getDoseIterator() const { return _doseIterator; } DoseStatisticsCalculator::DoseStatisticsPointer DoseStatisticsCalculator::calculateDoseStatistics( bool computeComplexMeasures, unsigned int maxNumberMinimaPositions, unsigned int maxNumberMaximaPositions) { if (!_doseIterator) { throw core::NullPointerException("_doseIterator must not be NULL!"); } //"simple" dose statistics are mandatory calculateSimpleDoseStatistics(maxNumberMinimaPositions, maxNumberMaximaPositions); if (computeComplexMeasures) { //more complex dose statistics are optional with default maximum dose and default relative x values calculateComplexDoseStatistics(_statistics->getMaximum(), std::vector(), std::vector()); } return _statistics; } DoseStatisticsCalculator::DoseStatisticsPointer DoseStatisticsCalculator::calculateDoseStatistics( DoseTypeGy referenceDose, unsigned int maxNumberMinimaPositions, unsigned int maxNumberMaximaPositions) { if (!_doseIterator) { throw core::NullPointerException("_doseIterator must not be NULL!"); } if (referenceDose <= 0) { throw rttb::core::InvalidParameterException("Reference dose must be > 0 !"); } //simple dose statistics calculateSimpleDoseStatistics(maxNumberMinimaPositions, maxNumberMaximaPositions); //more complex dose statistics with given reference dose and default x values calculateComplexDoseStatistics(referenceDose, std::vector(), std::vector()); return _statistics; } DoseStatisticsCalculator::DoseStatisticsPointer DoseStatisticsCalculator::calculateDoseStatistics( const std::vector& precomputeDoseValues, const std::vector& precomputeVolumeValues, DoseTypeGy referenceDose, unsigned int maxNumberMinimaPositions, unsigned int maxNumberMaximaPositions) { if (!_doseIterator) { throw core::NullPointerException("_doseIterator must not be NULL!"); } //"simple" dose statistics calculateSimpleDoseStatistics(maxNumberMinimaPositions, maxNumberMaximaPositions); if (referenceDose <= 0) { //more complex dose statistics with default maximum dose and relative x values calculateComplexDoseStatistics(_statistics->getMaximum(), precomputeDoseValues, precomputeVolumeValues); } else { //more complex dose statistics with given reference dose and relative x values calculateComplexDoseStatistics(referenceDose, precomputeDoseValues, precomputeVolumeValues); } return _statistics; } void DoseStatisticsCalculator::calculateSimpleDoseStatistics(unsigned int maxNumberMinimaPositions, unsigned int maxNumberMaximaPositions) { _doseVector.clear(); _voxelProportionVector.clear(); std::multimap doseValueVSIndexMap; std::vector voxelProportionVectorTemp; DoseStatisticType maximumDose = 0; DoseStatisticType minimumDose = std::numeric_limits::max(); DoseStatisticType meanDose; DoseStatisticType stdDeviationDose; DoseTypeGy sum = 0; VolumeType numVoxels = 0.0; DoseTypeGy squareSum = 0; VolumeType volume = 0; _doseIterator->reset(); int i = 0; DoseTypeGy doseValue = 0; while (_doseIterator->isPositionValid()) { doseValue = _doseIterator->getCurrentDoseValue(); if (i == 0) { minimumDose = doseValue; volume = _doseIterator->getCurrentVoxelVolume(); } rttb::FractionType voxelProportion = _doseIterator->getCurrentRelevantVolumeFraction(); sum += doseValue * voxelProportion; numVoxels += voxelProportion; squareSum += doseValue * doseValue * voxelProportion; if (doseValue > maximumDose) { maximumDose = doseValue; } else if (doseValue < minimumDose) { minimumDose = doseValue; } voxelProportionVectorTemp.push_back(voxelProportion); doseValueVSIndexMap.insert(std::pair(doseValue, i)); i++; _doseIterator->next(); } if (numVoxels != 0) { meanDose = sum / numVoxels; //standard deviation is defined only for n>=2 if (numVoxels >= 2) { //uncorrected variance is calculated DoseStatisticType varianceDose = (squareSum / numVoxels - meanDose * meanDose); if (varianceDose < errorConstant) { stdDeviationDose = 0; } else { stdDeviationDose = pow(varianceDose, 0.5); } } else { stdDeviationDose = 0; } } //sort dose values and corresponding volume fractions in member variables for (auto it = doseValueVSIndexMap.begin(); it != doseValueVSIndexMap.end(); ++it) { _doseVector.push_back((float)(*it).first); _voxelProportionVector.push_back(voxelProportionVectorTemp.at((*it).second)); } volume *= numVoxels; _statistics = boost::make_shared(minimumDose, maximumDose, meanDose, stdDeviationDose, numVoxels, volume); _simpleDoseStatisticsCalculated = true; ResultListPointer minimumVoxelPositions = computeMinimumPositions(maxNumberMinimaPositions); ResultListPointer maximumVoxelPositions = computeMaximumPositions(maxNumberMaximaPositions); _statistics->setMinimumVoxelPositions(minimumVoxelPositions); _statistics->setMaximumVoxelPositions(maximumVoxelPositions); } void DoseStatisticsCalculator::calculateComplexDoseStatistics(DoseTypeGy referenceDose, const std::vector& precomputeDoseValues, const std::vector& precomputeVolumeValues) { if (!_simpleDoseStatisticsCalculated) { throw core::InvalidDoseException("simple DoseStatistics have to be computed in order to call calculateComplexDoseStatistics()"); } std::vector precomputeDoseValuesNonConst = precomputeDoseValues; std::vector precomputeVolumeValuesNonConst = precomputeVolumeValues; //set default values if (precomputeDoseValues.empty()) { std::vector defaultPrecomputeDoseValues = boost::assign::list_of(0.02)(0.05)(0.1)(0.9)( 0.95)(0.98); precomputeDoseValuesNonConst = defaultPrecomputeDoseValues; } if (precomputeVolumeValues.empty()) { std::vector defaultPrecomputeVolumeValues = boost::assign::list_of(0.02)(0.05)(0.1)(0.9)( 0.95)(0.98); precomputeVolumeValuesNonConst = defaultPrecomputeVolumeValues; } DxVolumeToDoseMeasureCalculator Dx = DxVolumeToDoseMeasureCalculator(precomputeVolumeValuesNonConst, _statistics->getVolume(), - this->_doseVector, this->_voxelProportionVector, this->_doseIterator->getCurrentVoxelVolume(), _statistics->getMinimum(), VolumeToDoseMeasure::complexStatistics::Dx); + this->_doseVector, this->_voxelProportionVector, this->_doseIterator->getCurrentVoxelVolume(), _statistics->getMinimum(), VolumeToDoseMeasure::Dx); Dx.compute(); DoseToVolumeFunctionType Vx = computeDoseToVolumeFunctionMulti(referenceDose, precomputeDoseValuesNonConst, DoseStatistics::Vx); MOHxVolumeToDoseMeasureCalculator MOHx = MOHxVolumeToDoseMeasureCalculator(precomputeVolumeValuesNonConst, _statistics->getVolume(), - this->_doseVector, this->_voxelProportionVector, this->_doseIterator->getCurrentVoxelVolume(), VolumeToDoseMeasure::complexStatistics::MOHx); + this->_doseVector, this->_voxelProportionVector, this->_doseIterator->getCurrentVoxelVolume(), VolumeToDoseMeasure::MOHx); MOHx.compute(); MOCxVolumeToDoseMeasureCalculator MOCx = MOCxVolumeToDoseMeasureCalculator(precomputeVolumeValuesNonConst, _statistics->getVolume(), - this->_doseVector, this->_voxelProportionVector, this->_doseIterator->getCurrentVoxelVolume(), VolumeToDoseMeasure::complexStatistics::MOCx); + this->_doseVector, this->_voxelProportionVector, this->_doseIterator->getCurrentVoxelVolume(), VolumeToDoseMeasure::MOCx); MOCx.compute(); MaxOHxVolumeToDoseMeasureCalculator MaxOHx = MaxOHxVolumeToDoseMeasureCalculator(precomputeVolumeValuesNonConst, _statistics->getVolume(), - this->_doseVector, this->_voxelProportionVector, this->_doseIterator->getCurrentVoxelVolume(), VolumeToDoseMeasure::complexStatistics::MaxOHx); + this->_doseVector, this->_voxelProportionVector, this->_doseIterator->getCurrentVoxelVolume(), VolumeToDoseMeasure::MaxOHx); MaxOHx.compute(); MinOCxVolumeToDoseMeasureCalculator MinOCx = MinOCxVolumeToDoseMeasureCalculator(precomputeVolumeValuesNonConst, _statistics->getVolume(), - this->_doseVector, this->_voxelProportionVector, this->_doseIterator->getCurrentVoxelVolume(), _statistics->getMinimum(), _statistics->getMaximum(), VolumeToDoseMeasure::complexStatistics::MinOCx); + this->_doseVector, this->_voxelProportionVector, this->_doseIterator->getCurrentVoxelVolume(), _statistics->getMinimum(), _statistics->getMaximum(), VolumeToDoseMeasure::MinOCx); MinOCx.compute(); _statistics->setVx(Vx); _statistics->setDx(Dx.getMeasure()); _statistics->setMOHx(MOHx.getMeasure()); _statistics->setMOCx(MOCx.getMeasure()); _statistics->setMaxOHx(MaxOHx.getMeasure()); _statistics->setMinOCx(MinOCx.getMeasure()); _statistics->setReferenceDose(referenceDose); } DoseStatisticsCalculator::ResultListPointer DoseStatisticsCalculator::computeMaximumPositions( unsigned int maxNumberMaxima) const { if (!_simpleDoseStatisticsCalculated) { throw core::InvalidDoseException("simple DoseStatistics have to be computed in order to call computeMaximumPositions()"); } ResultListPointer maxVoxelVector = boost::make_shared > >(); unsigned int count = 0; this->_doseIterator->reset(); DoseTypeGy doseValue = 0; while (_doseIterator->isPositionValid() && count < maxNumberMaxima) { doseValue = _doseIterator->getCurrentDoseValue(); if (doseValue == _statistics->getMaximum()) { VoxelGridID currentID = _doseIterator->getCurrentVoxelGridID(); std::pair voxel(doseValue, currentID); maxVoxelVector->push_back(voxel); count++; } _doseIterator->next(); } return maxVoxelVector; } DoseStatisticsCalculator::ResultListPointer DoseStatisticsCalculator::computeMinimumPositions( unsigned int maxNumberMinima) const { if (!_simpleDoseStatisticsCalculated) { throw core::InvalidDoseException("simple DoseStatistics have to be computed in order to call computeMinimumPositions()"); } ResultListPointer minVoxelVector = boost::make_shared > >(); /*! @todo: Architecture Annotation: Finding the positions for the minimum only once reduces computation time, but will require sensible use by the programmers. To be save the output vector minVoxelVector will be always cleared here to garantee that no false values are presented. This change may be revoced to increase computation speed later on (only compute if(minVoxelVector->size()==0)). */ unsigned int count = 0; this->_doseIterator->reset(); DoseTypeGy doseValue = 0; while (_doseIterator->isPositionValid() && count < maxNumberMinima) { doseValue = _doseIterator->getCurrentDoseValue(); if (doseValue == _statistics->getMinimum()) { VoxelGridID currentID = _doseIterator->getCurrentVoxelGridID(); std::pair voxel(doseValue, currentID); minVoxelVector->push_back(voxel); count++; } _doseIterator->next(); } return minVoxelVector; } VolumeType DoseStatisticsCalculator::computeVx(DoseTypeGy xDoseAbsolute) const { rttb::FractionType count = 0; _doseIterator->reset(); DoseTypeGy currentDose = 0; while (_doseIterator->isPositionValid()) { currentDose = _doseIterator->getCurrentDoseValue(); if (currentDose >= xDoseAbsolute) { count += _doseIterator->getCurrentRelevantVolumeFraction(); } _doseIterator->next(); } return count * this->_doseIterator->getCurrentVoxelVolume(); } DoseStatisticsCalculator::DoseToVolumeFunctionType DoseStatisticsCalculator::computeDoseToVolumeFunctionMulti(DoseTypeGy referenceDose, const std::vector& precomputeDoseValues, DoseStatistics::complexStatistics name) const { std::vector threads; DoseToVolumeFunctionType VxMulti; for (size_t i = 0; i < precomputeDoseValues.size(); ++i) { if (_multiThreading) { threads.push_back(boost::thread(&DoseStatisticsCalculator::computeDoseToVolumeSingle, this, referenceDose, precomputeDoseValues.at(i), name, std::ref(VxMulti))); } else { DoseStatisticsCalculator::computeDoseToVolumeSingle(referenceDose, precomputeDoseValues.at(i), name, std::ref(VxMulti)); } } for (unsigned int i=0; i lock(*_mutex); VxMulti.insert(std::pair(xAbsolue, computeVx(xAbsolue))); } else { VxMulti.insert(std::pair(xAbsolue, computeVx(xAbsolue))); } } else { throw core::InvalidParameterException("unknown DoseStatistics name!"); } } void DoseStatisticsCalculator::setMultiThreading(const bool choice) { _multiThreading = choice; } }//end namespace algorithms }//end namespace rttb diff --git a/code/algorithms/rttbDxVolumeToDoseMeasureCalculator.h b/code/algorithms/rttbDxVolumeToDoseMeasureCalculator.h index 99f8356..422c5db 100644 --- a/code/algorithms/rttbDxVolumeToDoseMeasureCalculator.h +++ b/code/algorithms/rttbDxVolumeToDoseMeasureCalculator.h @@ -1,57 +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: 1674 $ (last changed revision) // @date $Date: 2017-01-27 10:34:46 +0100 (Fr, 27 Jan 2017) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #ifndef __DX_VOLUME_TO_DOSE_MEASURE_CALCULATOR_H #define __DX_VOLUME_TO_DOSE_MEASURE_CALCULATOR_H #include #include #include "rttbBaseType.h" #include "RTTBAlgorithmsExports.h" -#include "rttbvolumetodosemeasureCalculator.h" -#include "rttbvolumetodosemeasure.h" +#include "rttbVolumeToDoseMeasureCalculator.h" +#include "rttbVolumetoDoseMeasure.h" namespace rttb { namespace algorithms { class RTTBAlgorithms_EXPORT DxVolumeToDoseMeasureCalculator: public VolumeToDoseMeasureCalculator { private: DoseStatisticType _minimum; public: DxVolumeToDoseMeasureCalculator(const std::vector& precomputeVolumeValues, const VolumeType& volume, const std::vector& doseVector, const std::vector& voxelProportionVector, const DoseVoxelVolumeType& currentVoxelVolume, const DoseStatisticType& minimum, VolumeToDoseMeasure::complexStatistics name); private: void computeSpecificValue(double xAbsolute); }; } } #endif diff --git a/code/algorithms/rttbMOCxVolumeToDoseMeasureCalculator.h b/code/algorithms/rttbMOCxVolumeToDoseMeasureCalculator.h index 09ce36b..2a4beb1 100644 --- a/code/algorithms/rttbMOCxVolumeToDoseMeasureCalculator.h +++ b/code/algorithms/rttbMOCxVolumeToDoseMeasureCalculator.h @@ -1,54 +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: 1674 $ (last changed revision) // @date $Date: 2017-01-27 10:34:46 +0100 (Fr, 27 Jan 2017) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #ifndef __MOCX_VOLUME_TO_DOSE_MEASURE_CALCULATOR_H #define __MOCX_VOLUME_TO_DOSE_MEASURE_CALCULATOR_H #include #include #include "rttbBaseType.h" #include "RTTBAlgorithmsExports.h" -#include "rttbvolumetodosemeasureCalculator.h" -#include "rttbvolumetodosemeasure.h" +#include "rttbVolumeToDoseMeasureCalculator.h" +#include "rttbVolumetoDoseMeasure.h" namespace rttb { namespace algorithms { class RTTBAlgorithms_EXPORT MOCxVolumeToDoseMeasureCalculator : public VolumeToDoseMeasureCalculator { public: MOCxVolumeToDoseMeasureCalculator(const std::vector& precomputeVolumeValues, const VolumeType& volume, const std::vector& doseVector, const std::vector& voxelProportionVector, const DoseVoxelVolumeType& currentVoxelVolume, VolumeToDoseMeasure::complexStatistics name); private: void computeSpecificValue(double xAbsolute); }; } } #endif diff --git a/code/algorithms/rttbMOHxVolumeToDoseMeasureCalculator.h b/code/algorithms/rttbMOHxVolumeToDoseMeasureCalculator.h index 801310b..e5b7b57 100644 --- a/code/algorithms/rttbMOHxVolumeToDoseMeasureCalculator.h +++ b/code/algorithms/rttbMOHxVolumeToDoseMeasureCalculator.h @@ -1,57 +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: 1674 $ (last changed revision) // @date $Date: 2017-01-27 10:34:46 +0100 (Fr, 27 Jan 2017) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #ifndef __MOHX_VOLUME_TO_DOSE_MEASURE_CALCULATOR_H #define __MOHX_VOLUME_TO_DOSE_MEASURE_CALCULATOR_H #include #include #include "rttbBaseType.h" #include "RTTBAlgorithmsExports.h" -#include "rttbvolumetodosemeasureCalculator.h" -#include "rttbvolumetodosemeasure.h" +#include "rttbVolumeToDoseMeasureCalculator.h" +#include "rttbVolumetoDoseMeasure.h" namespace rttb { namespace algorithms { class RTTBAlgorithms_EXPORT MOHxVolumeToDoseMeasureCalculator : public VolumeToDoseMeasureCalculator { private: DoseStatisticType _minimum; public: MOHxVolumeToDoseMeasureCalculator(const std::vector& precomputeVolumeValues, const VolumeType& volume, const std::vector& doseVector, const std::vector& voxelProportionVector, const DoseVoxelVolumeType& currentVoxelVolume, VolumeToDoseMeasure::complexStatistics name); private: void computeSpecificValue(double xAbsolute); }; } } #endif diff --git a/code/algorithms/rttbMinOCxVolumeToDoseMeasureCalculator.h b/code/algorithms/rttbMinOCxVolumeToDoseMeasureCalculator.h index 77683c8..97b21cf 100644 --- a/code/algorithms/rttbMinOCxVolumeToDoseMeasureCalculator.h +++ b/code/algorithms/rttbMinOCxVolumeToDoseMeasureCalculator.h @@ -1,58 +1,58 @@ // ----------------------------------------------------------------------- // 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: 1674 $ (last changed revision) // @date $Date: 2017-01-27 10:34:46 +0100 (Fr, 27 Jan 2017) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #ifndef __MINOCX_VOLUME_TO_DOSE_MEASURE_CALCULATOR_H #define __MINOCX_VOLUME_TO_DOSE_MEASURE_CALCULATOR_H #include #include #include "rttbBaseType.h" #include "RTTBAlgorithmsExports.h" -#include "rttbvolumetodosemeasureCalculator.h" -#include "rttbvolumetodosemeasure.h" +#include "rttbVolumeToDoseMeasureCalculator.h" +#include "rttbVolumetoDoseMeasure.h" namespace rttb { namespace algorithms { class RTTBAlgorithms_EXPORT MinOCxVolumeToDoseMeasureCalculator : public VolumeToDoseMeasureCalculator { private: DoseStatisticType _minimum; DoseStatisticType _maximum; public: MinOCxVolumeToDoseMeasureCalculator(const std::vector& precomputeVolumeValues, const VolumeType& volume, const std::vector& doseVector, const std::vector& voxelProportionVector, const DoseVoxelVolumeType& currentVoxelVolume, const DoseStatisticType& minimum, const DoseStatisticType& maximum, VolumeToDoseMeasure::complexStatistics name); private: void computeSpecificValue(double xAbsolute); }; } } #endif diff --git a/code/io/other/rttbDoseStatisticsXMLReader.cpp b/code/io/other/rttbDoseStatisticsXMLReader.cpp index cd13c4d..1688303 100644 --- a/code/io/other/rttbDoseStatisticsXMLReader.cpp +++ b/code/io/other/rttbDoseStatisticsXMLReader.cpp @@ -1,218 +1,218 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1328 $ (last changed revision) // @date $Date: 2016-04-22 09:50:01 +0200 (Fr, 22 Apr 2016) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include #include #include #include #include #include #include "rttbDoseStatisticsXMLReader.h" #include "rttbInvalidParameterException.h" #include "rttbVolumeToDoseMeasure.h" namespace rttb { namespace io { namespace other { typedef boost::shared_ptr DoseStatisticsPtr; DoseStatisticsXMLReader::DoseStatisticsXMLReader(const std::string& filename) : _filename(filename), _newFile(true) { } DoseStatisticsXMLReader::~DoseStatisticsXMLReader() { } void DoseStatisticsXMLReader::setFilename(const std::string& filename) { _filename = filename; _newFile = true; } DoseStatisticsPtr DoseStatisticsXMLReader::generateDoseStatistic() { if (_newFile) { this->createDoseStatistic(); } return _doseStatistic; } void DoseStatisticsXMLReader::createDoseStatistic() { boost::property_tree::ptree pt; // Load the XML file into the property tree. If reading fails // (cannot open file, parse error), an exception is thrown. try { read_xml(_filename, pt); } catch (boost::property_tree::xml_parser_error& /*e*/) { throw rttb::core::InvalidParameterException("DoseStatistics file name invalid: could not open the xml file!"); } // data to fill the parameter for the DoseStatistics std::string name; std::string datum; unsigned int x; std::pair voxelid; std::vector < std::pair> vec; //initialize all parameters for the DoseStatistics double minimum=-1; double maximum=-1; double numVoxels=-1; double volume=-1; double referenceDose = -1; double mean=-1; double stdDeviation=-1; boost::shared_ptr > > minimumVoxelPositions = nullptr; boost::shared_ptr > > maximumVoxelPositions = nullptr; - rttb::algorithms::VolumeToDoseMeasure Dx = rttb::algorithms::VolumeToDoseMeasure(rttb::algorithms::VolumeToDoseMeasure::complexStatistics::Dx); - rttb::algorithms::VolumeToDoseMeasure MOHx = rttb::algorithms::VolumeToDoseMeasure(rttb::algorithms::VolumeToDoseMeasure::complexStatistics::MOHx); - rttb::algorithms::VolumeToDoseMeasure MOCx = rttb::algorithms::VolumeToDoseMeasure(rttb::algorithms::VolumeToDoseMeasure::complexStatistics::MOCx); - rttb::algorithms::VolumeToDoseMeasure MaxOHx = rttb::algorithms::VolumeToDoseMeasure(rttb::algorithms::VolumeToDoseMeasure::complexStatistics::MaxOHx); - rttb::algorithms::VolumeToDoseMeasure MinOCx = rttb::algorithms::VolumeToDoseMeasure(rttb::algorithms::VolumeToDoseMeasure::complexStatistics::MinOCx); + rttb::algorithms::VolumeToDoseMeasure Dx = rttb::algorithms::VolumeToDoseMeasure(rttb::algorithms::VolumeToDoseMeasure::Dx); + rttb::algorithms::VolumeToDoseMeasure MOHx = rttb::algorithms::VolumeToDoseMeasure(rttb::algorithms::VolumeToDoseMeasure::MOHx); + rttb::algorithms::VolumeToDoseMeasure MOCx = rttb::algorithms::VolumeToDoseMeasure(rttb::algorithms::VolumeToDoseMeasure::MOCx); + rttb::algorithms::VolumeToDoseMeasure MaxOHx = rttb::algorithms::VolumeToDoseMeasure(rttb::algorithms::VolumeToDoseMeasure::MaxOHx); + rttb::algorithms::VolumeToDoseMeasure MinOCx = rttb::algorithms::VolumeToDoseMeasure(rttb::algorithms::VolumeToDoseMeasure::MinOCx); std::map Vx; BOOST_FOREACH(boost::property_tree::ptree::value_type & data, pt.get_child("statistics.results")) { datum = data.second.data(); BOOST_FOREACH(boost::property_tree::ptree::value_type & middle, data.second) { BOOST_FOREACH(boost::property_tree::ptree::value_type & innernode, middle.second) { std::string mia = innernode.first; if (innernode.first == "name") { name = innernode.second.data(); } else if (innernode.first == "voxelGridID") { boost::replace_all(datum, "\r\n", ""); boost::replace_all(datum, "\n", ""); boost::trim(datum); voxelid.first = boost::lexical_cast(datum); voxelid.second = boost::lexical_cast(innernode.second.data()); vec.push_back(voxelid); } else if (innernode.first == "x") { x = boost::lexical_cast(innernode.second.data()); } } } // fill with the extracted data if (name == "numberOfVoxels") { numVoxels = boost::lexical_cast(datum); } else if (name == "volume") { volume = boost::lexical_cast(datum); Dx.setVolume(volume); } else if (name == "referenceDose") { referenceDose = boost::lexical_cast(datum); } else if (name == "mean") { mean = boost::lexical_cast(datum); } else if (name == "standardDeviation") { stdDeviation = boost::lexical_cast(datum); } else if (name == "minimum") { minimum = boost::lexical_cast(datum); if (!vec.empty()) { minimumVoxelPositions = boost::make_shared>>(vec); vec.clear(); } } else if (name == "maximum") { maximum = boost::lexical_cast(datum); if (!vec.empty()) { maximumVoxelPositions = boost::make_shared>>(vec); vec.clear(); } } else if (name == "Dx") { Dx.insertValue(std::pair(boost::lexical_cast(x)*volume / 100, boost::lexical_cast(datum))); } else if (name == "Vx") { Vx[boost::lexical_cast(x)*referenceDose / 100] = boost::lexical_cast(datum); } else if (name == "MOHx") { MOHx.insertValue(std::pair(boost::lexical_cast(x)*volume / 100, boost::lexical_cast(datum))); } else if (name == "MOCx") { MOCx.insertValue(std::pair(boost::lexical_cast(x)*volume / 100, boost::lexical_cast(datum))); } else if (name == "MaxOHx") { MaxOHx.insertValue(std::pair(boost::lexical_cast(x)*volume / 100, boost::lexical_cast(datum))); } else if (name == "MinOCx") { MinOCx.insertValue(std::pair(boost::lexical_cast(x)*volume / 100, boost::lexical_cast(datum))); } } // make DoseStatistcs _doseStatistic = boost::make_shared( minimum, maximum, mean, stdDeviation, numVoxels, volume, minimumVoxelPositions, maximumVoxelPositions , Dx, Vx, MOHx, MOCx, MaxOHx, MinOCx, referenceDose); } }//end namespace other }//end namespace io }//end namespace rttb diff --git a/testing/algorithms/DoseStatisticsTest.cpp b/testing/algorithms/DoseStatisticsTest.cpp index 2bfc12c..46ead60 100644 --- a/testing/algorithms/DoseStatisticsTest.cpp +++ b/testing/algorithms/DoseStatisticsTest.cpp @@ -1,249 +1,249 @@ // ----------------------------------------------------------------------- // 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 "rttbDoseStatistics.h" #include "rttbDataNotAvailableException.h" #include "rttbVolumeToDoseMeasure.h" namespace rttb { namespace testing { typedef rttb::algorithms::DoseStatistics::ResultListPointer ResultListPointer; typedef rttb::algorithms::DoseStatistics::DoseToVolumeFunctionType DoseToVolumeFunctionType; typedef rttb::algorithms::DoseStatistics::VolumeToDoseFunctionType VolumeToDoseFunctionType; /*! @brief DoseStatisticsTest - test the API of DoseStatistics 1) test constructors 2) test setters 3) test getters of complex statistics (with stored key and without stored key) */ int DoseStatisticsTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; DoseStatisticType minimum = 1.0; DoseStatisticType mean = 5.5; DoseStatisticType maximum = 108.2; DoseStatisticType stdDeviation = 10.1; unsigned int numVoxels = 100000; VolumeType volume = numVoxels * (0.5 * 0.5 * 0.5); std::vector > minVoxels; std::vector > maxVoxels; minVoxels.push_back(std::make_pair(1.0, 11)); minVoxels.push_back(std::make_pair(1.0, 22)); minVoxels.push_back(std::make_pair(1.0, 33)); minVoxels.push_back(std::make_pair(1.0, 44)); maxVoxels.push_back(std::make_pair(108.2, 5)); maxVoxels.push_back(std::make_pair(108.2, 6)); maxVoxels.push_back(std::make_pair(108.2, 7)); maxVoxels.push_back(std::make_pair(108.2, 8)); ResultListPointer resultsMinVoxels = boost::make_shared > >(minVoxels); ResultListPointer resultsMaxVoxels = boost::make_shared > >(maxVoxels); DoseToVolumeFunctionType Vx; Vx.insert(std::make_pair(1.1, 1000)); Vx.insert(std::make_pair(106.9, 99000)); - algorithms::VolumeToDoseMeasure Dx = algorithms::VolumeToDoseMeasure(algorithms::VolumeToDoseMeasure::complexStatistics::Dx, std::map(), volume); + algorithms::VolumeToDoseMeasure Dx = algorithms::VolumeToDoseMeasure(algorithms::VolumeToDoseMeasure::Dx, std::map(), volume); Dx.insertValue(std::make_pair(1000, 1.1)); Dx.insertValue(std::make_pair(99000, 106.9)); - algorithms::VolumeToDoseMeasure MOHx = algorithms::VolumeToDoseMeasure(algorithms::VolumeToDoseMeasure::complexStatistics::MOHx, std::map(), volume); + algorithms::VolumeToDoseMeasure MOHx = algorithms::VolumeToDoseMeasure(algorithms::VolumeToDoseMeasure::MOHx, std::map(), volume); MOHx.insertValue(std::make_pair(1000, 5)); MOHx.insertValue(std::make_pair(99000, 105.5)); - algorithms::VolumeToDoseMeasure MOCx = algorithms::VolumeToDoseMeasure(algorithms::VolumeToDoseMeasure::complexStatistics::MOCx, std::map(), volume); + algorithms::VolumeToDoseMeasure MOCx = algorithms::VolumeToDoseMeasure(algorithms::VolumeToDoseMeasure::MOCx, std::map(), volume); MOCx.insertValue(std::make_pair(1000, 10)); MOCx.insertValue(std::make_pair(99000, 99)); - algorithms::VolumeToDoseMeasure MaxOHx = algorithms::VolumeToDoseMeasure(algorithms::VolumeToDoseMeasure::complexStatistics::MaxOHx, std::map(), volume); + algorithms::VolumeToDoseMeasure MaxOHx = algorithms::VolumeToDoseMeasure(algorithms::VolumeToDoseMeasure::MaxOHx, std::map(), volume); MaxOHx.insertValue(std::make_pair(1000, 40)); MaxOHx.insertValue(std::make_pair(99000, 98.3)); - algorithms::VolumeToDoseMeasure MinOCx = algorithms::VolumeToDoseMeasure(algorithms::VolumeToDoseMeasure::complexStatistics::MinOCx, std::map(), volume); + algorithms::VolumeToDoseMeasure MinOCx = algorithms::VolumeToDoseMeasure(algorithms::VolumeToDoseMeasure::MinOCx, std::map(), volume); MinOCx.insertValue(std::make_pair(1000, 25.5)); MinOCx.insertValue(std::make_pair(99000, 102.7)); //1) test constructors CHECK_NO_THROW(rttb::algorithms::DoseStatistics aDoseStatistic(minimum, maximum, mean, stdDeviation, numVoxels, volume)); rttb::algorithms::DoseStatistics aDoseStatistic(minimum, maximum, mean, stdDeviation, numVoxels, volume); CHECK_EQUAL(aDoseStatistic.getMinimum(), minimum); CHECK_EQUAL(aDoseStatistic.getMaximum(), maximum); CHECK_EQUAL(aDoseStatistic.getMean(), mean); CHECK_EQUAL(aDoseStatistic.getStdDeviation(), stdDeviation); CHECK_EQUAL(aDoseStatistic.getVariance(), stdDeviation * stdDeviation); CHECK_EQUAL(aDoseStatistic.getNumberOfVoxels(), numVoxels); CHECK_EQUAL(aDoseStatistic.getVolume(), volume); //check default values for unset complex values CHECK_EQUAL(aDoseStatistic.getMaximumVoxelPositions()->empty(), true); CHECK_EQUAL(aDoseStatistic.getMinimumVoxelPositions()->empty(), true); CHECK_EQUAL(aDoseStatistic.getDx().getAllValues().empty(), true); CHECK_EQUAL(aDoseStatistic.getAllVx().empty(), true); CHECK_EQUAL(aDoseStatistic.getMOHx().getAllValues().empty(), true); CHECK_EQUAL(aDoseStatistic.getMOCx().getAllValues().empty(), true); CHECK_EQUAL(aDoseStatistic.getMaxOHx().getAllValues().empty(), true); CHECK_EQUAL(aDoseStatistic.getMinOCx().getAllValues().empty(), true); CHECK_NO_THROW(rttb::algorithms::DoseStatistics aDoseStatisticComplex(minimum, maximum, mean, stdDeviation, numVoxels, volume, resultsMaxVoxels, resultsMinVoxels, Dx, Vx, MOHx, MOCx, MaxOHx, MinOCx)); rttb::algorithms::DoseStatistics aDoseStatisticComplex(minimum, maximum, mean, stdDeviation, numVoxels, volume, resultsMaxVoxels, resultsMinVoxels, Dx, Vx, MOHx, MOCx, MaxOHx, MinOCx); CHECK_EQUAL(aDoseStatisticComplex.getMaximumVoxelPositions(), resultsMaxVoxels); CHECK_EQUAL(aDoseStatisticComplex.getMinimumVoxelPositions(), resultsMinVoxels); CHECK_EQUAL(aDoseStatisticComplex.getDx() == Dx, true); CHECK_EQUAL(aDoseStatisticComplex.getAllVx() == Vx, true); CHECK_EQUAL(aDoseStatisticComplex.getMOHx() == MOHx, true); CHECK_EQUAL(aDoseStatisticComplex.getMOCx() == MOCx, true); CHECK_EQUAL(aDoseStatisticComplex.getMaxOHx() == MaxOHx, true); CHECK_EQUAL(aDoseStatisticComplex.getMinOCx() == MinOCx, true); //2) test setters (only complex statistics have setters) CHECK_NO_THROW(aDoseStatistic.setMaximumVoxelPositions(resultsMaxVoxels)); CHECK_NO_THROW(aDoseStatistic.setMinimumVoxelPositions(resultsMinVoxels)); CHECK_NO_THROW(aDoseStatistic.setDx(Dx)); CHECK_NO_THROW(aDoseStatistic.setVx(Vx)); CHECK_NO_THROW(aDoseStatistic.setMOHx(MOHx)); CHECK_NO_THROW(aDoseStatistic.setMOCx(MOCx)); CHECK_NO_THROW(aDoseStatistic.setMaxOHx(MaxOHx)); CHECK_NO_THROW(aDoseStatistic.setMinOCx(MinOCx)); CHECK_EQUAL(aDoseStatistic.getMaximumVoxelPositions(), resultsMaxVoxels); CHECK_EQUAL(aDoseStatistic.getMinimumVoxelPositions(), resultsMinVoxels); CHECK_EQUAL(aDoseStatistic.getDx() == Dx, true); CHECK_EQUAL(aDoseStatistic.getAllVx() == Vx, true); CHECK_EQUAL(aDoseStatistic.getMOHx() == MOHx, true); CHECK_EQUAL(aDoseStatistic.getMOCx() == MOCx, true); CHECK_EQUAL(aDoseStatistic.getMaxOHx() == MaxOHx, true); CHECK_EQUAL(aDoseStatistic.getMinOCx() == MinOCx, true); //3) test getters of complex statistics(with stored key and without stored key) //getAll*() already tested in (2) Vx.clear(); Vx.insert(std::make_pair(1.1, 1000)); Vx.insert(std::make_pair(5.0, 2300)); Vx.insert(std::make_pair(90, 90500)); Vx.insert(std::make_pair(107, 99000)); Dx.insertValue(std::make_pair(2000, 2.0)); Dx.insertValue(std::make_pair(5000, 10.8)); Dx.insertValue(std::make_pair(90000, 89.5)); Dx.insertValue(std::make_pair(98000, 104.4)); rttb::algorithms::DoseStatistics aDoseStatisticNewValues(minimum, maximum, mean, stdDeviation, numVoxels, volume); aDoseStatisticNewValues.setDx(Dx); aDoseStatisticNewValues.setVx(Vx); CHECK_NO_THROW(aDoseStatisticNewValues.getVx(1.1)); CHECK_NO_THROW(aDoseStatisticNewValues.getVx(90)); CHECK_NO_THROW(aDoseStatisticNewValues.getDx().getValue(1000)); CHECK_NO_THROW(aDoseStatisticNewValues.getDx().getValue(98000)); CHECK_EQUAL(aDoseStatisticNewValues.getVx(1.1), Vx.find(1.1)->second); CHECK_EQUAL(aDoseStatisticNewValues.getVx(90), Vx.find(90)->second); CHECK_EQUAL(aDoseStatisticNewValues.getDx().getValue(1000), Dx.getAllValues().find(1000)->second); CHECK_EQUAL(aDoseStatisticNewValues.getDx().getValue(98000), Dx.getAllValues().find(98000)->second); //test if key-value combination NOT in map CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getDx().getValue(1001), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getVx(10), core::DataNotAvailableException); double closestDxKey, closestVxKey; CHECK_NO_THROW(aDoseStatisticNewValues.getDx().getValue(900, true, closestDxKey)); CHECK_NO_THROW(aDoseStatisticNewValues.getDx().getValue(99001, true, closestDxKey)); CHECK_NO_THROW(aDoseStatisticNewValues.getVx(10, true, closestVxKey)); CHECK_EQUAL(aDoseStatisticNewValues.getDx().getValue(900, true, closestDxKey), Dx.getAllValues().find(1000)->second); CHECK_EQUAL(aDoseStatisticNewValues.getDx().getValue(99001, true, closestDxKey), Dx.getAllValues().find(99000)->second); CHECK_EQUAL(aDoseStatisticNewValues.getVx(10, true, closestVxKey), Vx.find(5.0)->second); CHECK_EQUAL(closestDxKey, 99000); CHECK_EQUAL(closestVxKey, 5); // relatives only between 0 and 1 CHECK_NO_THROW(aDoseStatisticNewValues.getVxRelative(1.1 / aDoseStatistic.getReferenceDose())); CHECK_NO_THROW(aDoseStatisticNewValues.getDx().getValueRelative(1000 / aDoseStatistic.getVolume())); CHECK_THROW(aDoseStatisticNewValues.getVxRelative(-0.3)); CHECK_THROW(aDoseStatisticNewValues.getVxRelative(1.1)); CHECK_THROW(aDoseStatisticNewValues.getDx().getValueRelative(0.5)); CHECK_NO_THROW(aDoseStatisticNewValues.getDx().getValueRelative(900 / aDoseStatistic.getVolume(), true, closestDxKey)); CHECK_NO_THROW(aDoseStatisticNewValues.getDx().getValueRelative(0.5, true, closestDxKey)); CHECK_NO_THROW(aDoseStatisticNewValues.getVxRelative(10 / aDoseStatistic.getReferenceDose(), true, closestVxKey)); CHECK_EQUAL(aDoseStatisticNewValues.getDx().getValueRelative(900 / aDoseStatistic.getVolume(), true, closestDxKey), Dx.getAllValues().find(1000)->second); CHECK_EQUAL(aDoseStatisticNewValues.getVxRelative(10 / aDoseStatistic.getReferenceDose(), true, closestVxKey), Vx.find(5.0)->second); CHECK_EQUAL(closestVxKey, 5); //equal distance to two values. First value is returned. CHECK_NO_THROW(aDoseStatisticNewValues.getDx().getValue(1500, true, closestDxKey)); CHECK_NO_THROW(aDoseStatisticNewValues.getVx(98.5, true, closestVxKey)); CHECK_EQUAL(aDoseStatisticNewValues.getDx().getValue(1500, true, closestDxKey), Dx.getAllValues().find(1000)->second); CHECK_EQUAL(aDoseStatisticNewValues.getVx(98.5, true, closestVxKey), Vx.find(90.0)->second); CHECK_EQUAL(closestDxKey, 1000); CHECK_EQUAL(closestVxKey, 90.0); double dummy; CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMinOCx().getValue(25), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMOHx().getValue(9999), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMinOCx().getValue(25, true, dummy), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMOHx().getValue(9999, true, dummy), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMinOCx().getValueRelative(25 / aDoseStatistic.getVolume()), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMOHx().getValueRelative(9999 / aDoseStatistic.getVolume()), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMinOCx().getValueRelative(25 / aDoseStatistic.getVolume(), true, dummy), core::DataNotAvailableException); CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMOHx().getValueRelative(9999 / aDoseStatistic.getVolume(), true, dummy), core::DataNotAvailableException); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb