diff --git a/code/algorithms/files.cmake b/code/algorithms/files.cmake index 981351b..458f698 100644 --- a/code/algorithms/files.cmake +++ b/code/algorithms/files.cmake @@ -1,17 +1,12 @@ SET(CPP_FILES rttbDoseStatistics.cpp - rttbDoseStatisticsCalculator.cpp rttbArithmetic.cpp ) SET(H_FILES rttbDoseStatistics.h - rttbDoseStatisticsCalculator.h rttbArithmetic.h + rttbArithmetic.tpp rttbBinaryFunctorDoseAccessor.h -) - -SET(TXX_FILES - rttbArithmetic.tpp - rttbBinaryFunctorDoseAccessor.tpp + rttbBinaryFunctorDoseAccessor.tpp ) diff --git a/code/algorithms/rttbDoseStatistics.cpp b/code/algorithms/rttbDoseStatistics.cpp index 14fe157..ac63f89 100644 --- a/code/algorithms/rttbDoseStatistics.cpp +++ b/code/algorithms/rttbDoseStatistics.cpp @@ -1,314 +1,453 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ +#include +#include +#include +#include +#include +#include +#include +#include + #include "rttbDoseStatistics.h" -#include "rttbDataNotAvailableException.h" +#include "rttbNullPointerException.h" +#include "rttbInvalidDoseException.h" namespace rttb { namespace algorithms { - DoseStatistics::DoseStatistics(DoseStatisticType minimum, DoseStatisticType maximum, DoseStatisticType mean, - DoseStatisticType stdDeviation, unsigned int numVoxels, VolumeType volume, - ResultListPointer maximumVoxelPositions /*= ResultListPointer()*/, - ResultListPointer minimumVoxelPositions /*= ResultListPointer()*/, - DoseToVolumeFunctionType Dx /*= std::map()*/, - VolumeToDoseFunctionType Vx /*= std::map()*/, - VolumeToDoseFunctionType MOHx /*= std::map()*/, - VolumeToDoseFunctionType MOCx /*= std::map()*/, - VolumeToDoseFunctionType MaxOHx /*= std::map()*/, - VolumeToDoseFunctionType MinOCx /*= std::map()*/) : _minimum(minimum), - _maximum(maximum), _mean(mean), _stdDeviation(stdDeviation), _numVoxels(numVoxels), _volume(volume), - _maximumVoxelPositions(maximumVoxelPositions), _minimumVoxelPositions(minimumVoxelPositions), _Dx(Dx), _Vx(Vx), - _MOHx(MOHx), - _MOCx(MOCx), _MaxOHx(MaxOHx), _MinOCx(MinOCx) + DoseStatistics::DoseStatistics() { - + initSuccess = false; } - - DoseStatistics::~DoseStatistics() + DoseStatistics::DoseStatistics(DoseIteratorPointer aDoseIterator) { - + _doseIterator = aDoseIterator; + initSuccess = false; + this->init(); } - - void DoseStatistics::setMinimumVoxelPositions(ResultListPointer minimumVoxelPositions) + void DoseStatistics::setDoseIterator(DoseIteratorPointer aDoseIterator) { - _minimumVoxelPositions = minimumVoxelPositions; + _doseIterator = aDoseIterator; + initSuccess = false; + this->init(); } - void DoseStatistics::setMaximumVoxelPositions(ResultListPointer maximumVoxelPositions) + DoseStatistics::DoseIteratorPointer DoseStatistics::getDoseIterator() const { - _maximumVoxelPositions = maximumVoxelPositions; + return _doseIterator; } - void DoseStatistics::setDx(const DoseToVolumeFunctionType& DxValues) - { - _Dx = DxValues; - } - void DoseStatistics::setVx(const VolumeToDoseFunctionType& VxValues) + bool DoseStatistics::init() { - _Vx = VxValues; - } - void DoseStatistics::setMOHx(const VolumeToDoseFunctionType& MOHxValues) - { - _MOHx = MOHxValues; - } + if (!_doseIterator) + { + throw core::NullPointerException("_doseIterator must not be NULL!"); + } - void DoseStatistics::setMOCx(const VolumeToDoseFunctionType& MOCxValues) - { - _MOCx = MOCxValues; - } + doseVector.clear(); + voxelProportionVector.clear(); - void DoseStatistics::setMaxOHx(const VolumeToDoseFunctionType& MaxOHValues) - { - _MaxOHx = MaxOHValues; - } + std::multimap doseValueVSIndexMap; + std::vector voxelProportionVectorTemp; - void DoseStatistics::setMinOCx(const VolumeToDoseFunctionType& MinOCValues) - { - _MinOCx = MinOCValues; + + this->_maximum = 0; + this->_mean = 0; + this->_stdDeviation = 0; + this->_variance = 0; + + float sum = 0; + _numVoxels = 0; + float squareSum = 0; + + _doseIterator->reset(); + int i = 0; + DoseTypeGy doseValue = 0; + + while (_doseIterator->isPositionValid()) + { + doseValue = _doseIterator->getCurrentDoseValue(); + + if (i == 0) + { + _minimum = doseValue; + } + + rttb::FractionType voxelProportion = _doseIterator->getCurrentRelevantVolumeFraction(); + sum += doseValue * voxelProportion; + _numVoxels += voxelProportion; + squareSum += doseValue * doseValue * voxelProportion; + + if (doseValue > this->_maximum) + { + _maximum = doseValue; + } + else if (doseValue < this->_minimum) + { + _minimum = doseValue; + } + + voxelProportionVectorTemp.push_back(voxelProportion); + doseValueVSIndexMap.insert(std::pair(doseValue, i)); + + i++; + _doseIterator->next(); + } + + if (_numVoxels != 0) + { + _mean = sum / _numVoxels; + _variance = (squareSum / _numVoxels - _mean * _mean); + + if (_variance < errorConstant) + { + _stdDeviation = 0; + } + else + { + _stdDeviation = pow(_variance, 0.5); + } + } + + //sort dose values and corresponding volume fractions in member variables + std::multimap::iterator it; + + for (it = doseValueVSIndexMap.begin(); it != doseValueVSIndexMap.end(); ++it) + { + doseVector.push_back((float)(*it).first); + voxelProportionVector.push_back(voxelProportionVectorTemp.at((*it).second)); + } + + initSuccess = true; + + return true; } - unsigned int DoseStatistics::getNumberOfVoxels() const + double DoseStatistics::getNumberOfVoxels() { + if (!initSuccess) + { + throw core::InvalidDoseException("DoseStatistics is not initialized: set dose using setDoseIterator()! "); + } + return _numVoxels; } - - VolumeType DoseStatistics::getVolume() const + DoseStatisticType DoseStatistics::getMaximum(ResultListPointer maxVoxelVector) const { - return _volume; - } + if (!initSuccess) + { + throw core::InvalidDoseException("DoseStatistics is not initialized: set dose using setDoseIterator()! "); + } + + if (maxVoxelVector == NULL) + { + throw core::NullPointerException("resultsVector must not be NULL! "); + } + + if (maxVoxelVector->size() == 0) + { + this->_doseIterator->reset(); + DoseTypeGy doseValue = 0; + + while (_doseIterator->isPositionValid()) + { + doseValue = _doseIterator->getCurrentDoseValue(); + + if (doseValue == _maximum) + { + VoxelGridID currentID = _doseIterator->getCurrentVoxelGridID(); + std::pair voxel(doseValue, currentID); + maxVoxelVector->push_back(voxel); + } + + _doseIterator->next(); + } + } - DoseStatisticType DoseStatistics::getMaximum() const - { return _maximum; } - DoseStatisticType DoseStatistics::getMinimum() const + DoseStatisticType DoseStatistics::getMinimum(ResultListPointer minVoxelVector, int number) const { + if (!initSuccess) + { + throw core::InvalidDoseException("DoseStatistics is not initialized: set dose using setDoseIterator()! "); + + } + + if (minVoxelVector == NULL) + { + throw core::NullPointerException("resultsVector must not be NULL! "); + } + + /*! @todo: Architecture Annotation: + Finding the positions for the minimum only once reduces computation time, + but will require sensible use by the programmers. To be save the output vector + minVoxelVector will be always cleared here to garantee that no false values are + presented. This change may be revoced to increase computation speed later on + (only compute if(minVoxelVector->size()==0)). + */ + minVoxelVector->clear(); + int count = 0; + this->_doseIterator->reset(); + DoseTypeGy doseValue = 0; + + while (_doseIterator->isPositionValid() && count < number) + { + doseValue = _doseIterator->getCurrentDoseValue(); + + if (doseValue == _minimum) + { + VoxelGridID currentID = _doseIterator->getCurrentVoxelGridID(); + std::pair voxel(doseValue, currentID); + minVoxelVector->push_back(voxel); + count++; + } + + _doseIterator->next(); + } + return _minimum; } DoseStatisticType DoseStatistics::getMean() const { + if (!initSuccess) + { + throw core::InvalidDoseException("DoseStatistics is not initialized: set dose using setDoseIterator()! "); + } + return _mean; } DoseStatisticType DoseStatistics::getStdDeviation() const { + if (!initSuccess) + { + throw core::InvalidDoseException("DoseStatistics is not initialized: set dose using setDoseIterator()! "); + } + 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); + if (!initSuccess) + { + throw core::InvalidDoseException("DoseStatistics is not initialized: set dose using setDoseIterator()! "); + } + return _variance; } VolumeType DoseStatistics::getVx(DoseTypeGy xDoseAbsolute) const { - DoseTypeGy dummy; - return getValue(_Vx, xDoseAbsolute, false, dummy); - } + rttb::FractionType count = 0; + _doseIterator->reset(); - DoseTypeGy DoseStatistics::getDx(VolumeType xVolumeAbsolute, bool findNearestValue, - VolumeType& nearestXVolume) const - { - return getValue(_Dx, xVolumeAbsolute, findNearestValue, nearestXVolume); - } + DoseTypeGy currentDose = 0; - DoseTypeGy DoseStatistics::getDx(VolumeType xVolumeAbsolute) const - { - VolumeType dummy; - return getValue(_Dx, xVolumeAbsolute, false, dummy); - } + while (_doseIterator->isPositionValid()) + { + currentDose = _doseIterator->getCurrentDoseValue(); - DoseTypeGy DoseStatistics::getMOHx(VolumeType xVolumeAbsolute, bool findNearestValue, - VolumeType& nearestXVolume) const - { - return getValue(_MOHx, xVolumeAbsolute, findNearestValue, nearestXVolume); - } + if (currentDose >= xDoseAbsolute) + { + count += _doseIterator->getCurrentRelevantVolumeFraction(); + } - DoseTypeGy DoseStatistics::getMOHx(VolumeType xVolumeAbsolute) const - { - VolumeType dummy; - return getValue(_MOHx, xVolumeAbsolute, false, dummy); - } + _doseIterator->next(); + } - DoseTypeGy DoseStatistics::getMOCx(VolumeType xVolumeAbsolute, bool findNearestValue, - VolumeType& maximumDistanceFromOriginalVolume) const - { - return getValue(_MOCx, xVolumeAbsolute, findNearestValue, maximumDistanceFromOriginalVolume); + return count * this->_doseIterator->getCurrentVoxelVolume(); } - DoseTypeGy DoseStatistics::getMOCx(VolumeType xVolumeAbsolute) const + DoseTypeGy DoseStatistics::getDx(DoseTypeGy xVolumeAbsolute) const { - VolumeType dummy; - return getValue(_MOCx, xVolumeAbsolute, false, dummy); - } + double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); + DoseTypeGy resultDose = 0; - DoseTypeGy DoseStatistics::getMaxOHx(VolumeType xVolumeAbsolute, bool findNearestValue, - VolumeType& maximumDistanceFromOriginalVolume) const - { - return getValue(_MaxOHx, xVolumeAbsolute, findNearestValue, maximumDistanceFromOriginalVolume); - } + double countVoxels = 0; + int i = doseVector.size() - 1; - DoseTypeGy DoseStatistics::getMaxOHx(VolumeType xVolumeAbsolute) const - { - VolumeType dummy; - return getValue(_MaxOHx, xVolumeAbsolute, false, dummy); - } + for (; i >= 0; i--) + { + countVoxels += voxelProportionVector.at(i); - DoseTypeGy DoseStatistics::getMinOCx(VolumeType xVolumeAbsolute, bool findNearestValue, - VolumeType& maximumDistanceFromOriginalVolume) const - { - return getValue(_MinOCx, xVolumeAbsolute, findNearestValue, maximumDistanceFromOriginalVolume); - } + if (countVoxels >= noOfVoxel) + { + break; + } + } - DoseTypeGy DoseStatistics::getMinOCx(VolumeType xVolumeAbsolute) const - { - VolumeType dummy; - return getValue(_MinOCx, xVolumeAbsolute, false, dummy); + if (i >= 0) + { + resultDose = doseVector.at(i); + } + else + { + resultDose = _minimum; + } + + return resultDose; } - double DoseStatistics::getValue(std::map aMap, double key, - bool findNearestValueInstead, double& storedKey) const + DoseTypeGy DoseStatistics::getMOHx(DoseTypeGy xVolumeAbsolute) const { - if (aMap.find(key) != aMap.end()) + double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); + + + if (noOfVoxel == 0) { - return aMap.find(key)->second; + return 0; } else { - //value not in map. We have to find the nearest value - if (aMap.empty()) - { - throw core::DataNotAvailableException("No Vx values are defined"); - } - else + double countVoxels = 0; + double sum = 0; + + for (int i = doseVector.size() - 1; i >= 0; i--) { - if (findNearestValueInstead) - { - auto iterator = findNearestKeyInMap(aMap, key); - storedKey = iterator->first; - return iterator->second; - } - else + double voxelProportion = voxelProportionVector.at(i); + countVoxels += voxelProportion; + sum += doseVector.at(i) * voxelProportion; + + if (countVoxels >= noOfVoxel) { - throw core::DataNotAvailableException("No Vx value with required dose is defined"); + break; } } + + return (DoseTypeGy)(sum / noOfVoxel); } } - std::map::const_iterator DoseStatistics::findNearestKeyInMap(std::map aMap, - double key) const + DoseTypeGy DoseStatistics::getMOCx(DoseTypeGy xVolumeAbsolute) const { - double minDistance = 1e19; - double minDistanceLast = 1e20; + double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); - auto iterator = std::begin(aMap); - while (iterator != std::end(aMap)) + if (noOfVoxel == 0) + { + return 0; + } + else { - minDistanceLast = minDistance; - minDistance = fabs(iterator->first - key); + double countVoxels = 0; + double sum = 0; + std::vector::const_iterator it = doseVector.begin(); + std::vector::const_iterator itD = voxelProportionVector.begin(); - if (minDistanceLast > minDistance) - { - ++iterator; - } - else + for (; it != doseVector.end(); ++it, ++itD) { - if (iterator != std::begin(aMap)) - { - --iterator; - return iterator; - } - else + double voxelProportion = *itD; + countVoxels += voxelProportion; + sum += (*it) * voxelProportion; + + if (countVoxels >= noOfVoxel) { - return std::begin(aMap); + break; } } - } - --iterator; - return iterator; + return (DoseTypeGy)(sum / noOfVoxel); + } } - DoseStatistics::ResultListPointer DoseStatistics::getMaximumPositions() const + DoseTypeGy DoseStatistics::getMaxOHx(DoseTypeGy xVolumeAbsolute) const { - return _maximumVoxelPositions; - } + double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); + DoseTypeGy resultDose = 0; - DoseStatistics::ResultListPointer DoseStatistics::getMinimumPositions() const - { - return _minimumVoxelPositions; - } + double countVoxels = 0; + int i = doseVector.size() - 1; - DoseStatistics::DoseToVolumeFunctionType DoseStatistics::getAllVx() const - { - return _Vx; - } + for (; i >= 0; i--) + { + countVoxels += voxelProportionVector.at(i); - DoseStatistics::VolumeToDoseFunctionType DoseStatistics::getAllDx() const - { - return _Dx; - } + if (countVoxels >= noOfVoxel) + { + break; + } + } - DoseStatistics::VolumeToDoseFunctionType DoseStatistics::getAllMOHx() const - { - return _MOHx; - } + if (i - 1 >= 0) + { + resultDose = doseVector.at(i - 1); + } - DoseStatistics::VolumeToDoseFunctionType DoseStatistics::getAllMOCx() const - { - return _MOCx; + return resultDose; } - DoseStatistics::VolumeToDoseFunctionType DoseStatistics::getAllMaxOHx() const + DoseTypeGy DoseStatistics::getMinOCx(DoseTypeGy xVolumeAbsolute) const { - return _MaxOHx; - } + double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); + DoseTypeGy resultDose = 0; - DoseStatistics::VolumeToDoseFunctionType DoseStatistics::getAllMinOCx() const - { - return _MinOCx; - } + double countVoxels = 0; + std::vector::const_iterator it = doseVector.begin(); + std::vector::const_iterator itD = voxelProportionVector.begin(); + + for (; itD != voxelProportionVector.end(); ++itD, ++it) + { + countVoxels += *itD; + + if (countVoxels >= noOfVoxel) + { + break; + } + } + if (it != doseVector.end()) + { + ++it; + if (it != doseVector.end()) + { + resultDose = *it; + } + else + { + resultDose = (DoseTypeGy)_maximum; + } + } + else + { + resultDose = (DoseTypeGy)_maximum; + } + + return resultDose; + } }//end namespace algorithms }//end namespace rttb diff --git a/code/algorithms/rttbDoseStatistics.h b/code/algorithms/rttbDoseStatistics.h index 5a497cc..cc7de52 100644 --- a/code/algorithms/rttbDoseStatistics.h +++ b/code/algorithms/rttbDoseStatistics.h @@ -1,205 +1,164 @@ // ----------------------------------------------------------------------- // 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 #include "rttbBaseType.h" #include "rttbDoseIteratorInterface.h" -namespace rttb -{ +namespace rttb{ - namespace algorithms - { + namespace algorithms{ /*! @class DoseStatistics - @brief This is a data class storing different statistical values from a rt dose distribution - @sa DoseStatisticsCalculator + @brief This is a class calculating different statistical values from a rt dose distribution + These values range fram standard statistical values such as minimum, maximum and mean to more + dose specific properties such as Vx (volume iradiated with a dose >=x), Dx (minimal dose delivered + to x% of the VOI, and MOHx (mean in the hottest volume). */ class 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(std::map aMap, double key, bool findNearestValueInstead, - double& storedKey) const; - - std::map::const_iterator findNearestKeyInMap(std::map aMap, double key) const; - - DoseStatisticType _maximum; - DoseStatisticType _minimum; - ResultListPointer _maximumVoxelPositions; - ResultListPointer _minimumVoxelPositions; - DoseStatisticType _mean; - DoseStatisticType _stdDeviation; - unsigned int _numVoxels; - VolumeType _volume; - DoseToVolumeFunctionType _Dx; - VolumeToDoseFunctionType _Vx; - VolumeToDoseFunctionType _MOHx; - VolumeToDoseFunctionType _MOCx; - VolumeToDoseFunctionType _MaxOHx; - VolumeToDoseFunctionType _MinOCx; - - public: - /*! @brief Standard Constructor - */ - //DoseStatistics(); - - /*! @brief Constructor - @detail 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, unsigned int numVoxels, VolumeType volume, - ResultListPointer minimumVoxelPositions = boost::make_shared > > - (std::vector >()), - ResultListPointer maximumVoxelPositions = boost::make_shared > > - (std::vector >()), - DoseToVolumeFunctionType Dx = DoseToVolumeFunctionType(), - VolumeToDoseFunctionType Vx = VolumeToDoseFunctionType(), - VolumeToDoseFunctionType MOHx = VolumeToDoseFunctionType(), - VolumeToDoseFunctionType MOCx = VolumeToDoseFunctionType(), - VolumeToDoseFunctionType MaxOHx = VolumeToDoseFunctionType(), - VolumeToDoseFunctionType MinOCx = VolumeToDoseFunctionType()); - - ~DoseStatistics(); - - void setMinimumVoxelPositions(ResultListPointer minimumVoxelPositions); - void setMaximumVoxelPositions(ResultListPointer maximumVoxelPositions); - void setDx(const DoseToVolumeFunctionType& DxValues); - void setVx(const VolumeToDoseFunctionType& VxValues); - void setMOHx(const VolumeToDoseFunctionType& MOHxValues); - void setMOCx(const VolumeToDoseFunctionType& MOCxValues); - void setMaxOHx(const VolumeToDoseFunctionType& MaxOHxValues); - void setMinOCx(const VolumeToDoseFunctionType& MinOCxValues); - - /*! @brief Get number of voxels in doseIterator, with sub-voxel accuracy. - */ - unsigned int getNumberOfVoxels() const; - - VolumeType getVolume() 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 getMaximumPositions() 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 getMinimumPositions() 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; - DoseToVolumeFunctionType getAllVx() const; - - /*! @brief Get Dx: the minimal dose delivered to part x of the current volume. - @return Return dose value in Gy. - @exception InvalidDoseException if the Dx values have not been set (i.e. the vector is empty) - */ - DoseTypeGy getDx(VolumeType xVolumeAbsolute, bool findNearestValue, - VolumeType& nearestXVolume) const; - DoseTypeGy getDx(VolumeType xVolumeAbsolute) const; - VolumeToDoseFunctionType getAllDx() const; - - /*! @brief Get MOHx: mean dose of the hottest x voxels. - @return Return dose value in Gy. - @exception InvalidDoseException if the values have not been set (i.e. the vector is empty) - */ - DoseTypeGy getMOHx(VolumeType xVolumeAbsolute, bool findNearestValue, - VolumeType& nearestXVolume) const; - DoseTypeGy getMOHx(VolumeType xVolumeAbsolute) const; - VolumeToDoseFunctionType getAllMOHx() const; - - /*! @brief Get MOCx: mean dose of the coldest x voxels. - @return Return dose value in Gy. - @exception InvalidDoseException if the values have not been set (i.e. the vector is empty) - */ - DoseTypeGy getMOCx(VolumeType xVolumeAbsolute, bool findNearestValue, - VolumeType& nearestXVolume) const; - DoseTypeGy getMOCx(VolumeType xVolumeAbsolute) const; - VolumeToDoseFunctionType getAllMOCx() const; - - /*! @brief Get MaxOHx: Maximum outside of the hottest x voxels. - @return Return dose value in Gy. - @exception InvalidDoseException if the values have not been set (i.e. the vector is empty) - */ - DoseTypeGy getMaxOHx(VolumeType xVolumeAbsolute, bool findNearestValue, - VolumeType& nearestXVolume) const; - DoseTypeGy getMaxOHx(VolumeType xVolumeAbsolute) const; - VolumeToDoseFunctionType getAllMaxOHx() const; - - /*! @brief Get MinOCx: Minimum outside of the coldest x voxels. - @return Return dose value in Gy. - @exception InvalidDoseException if the values have not been set (i.e. the vector is empty) - */ - DoseTypeGy getMinOCx(VolumeType xVolumeAbsolute, bool findNearestValue, - VolumeType& nearestXVolume) const; - DoseTypeGy getMinOCx(VolumeType xVolumeAbsolute) const; - VolumeToDoseFunctionType getAllMinOCx() const; - }; - + { + public: + typedef core::DoseIteratorInterface::DoseIteratorPointer DoseIteratorPointer; + typedef boost::shared_ptr > > ResultListPointer; + + private: + DoseIteratorPointer _doseIterator; + DoseStatisticType _maximum; + DoseStatisticType _minimum; + DoseStatisticType _mean; + DoseStatisticType _stdDeviation; + DoseStatisticType _variance; + DoseStatisticType _numVoxels; + + /* Contains relevant dose values sorted in descending order. + */ + std::vector doseVector; + + /*! Contains the corresponding voxel proprtions to the values in doseVector. + */ + std::vector voxelProportionVector; + + bool initSuccess; + + /*! @brief Calculation of basic dose statistics. It will be called in Constructor. + @exception NullPointerException Thrown if _doseIterator is NULL. + */ + bool init(); + + + + public: + /*! @brief Standard Constructor + */ + DoseStatistics(); + + /*! @brief Constructor + */ + DoseStatistics(DoseIteratorPointer aDoseIterator); + + /*! @brief Set new dose data for statistics. Statistics will be re-initialized. + */ + void setDoseIterator(DoseIteratorPointer aDoseIterator); + + /*! @brief Get dose iterator. + */ + DoseIteratorPointer getDoseIterator() const; + + + /*! @brief Get number of voxels in doseIterator, with sub-voxel accuracy. + @exception InvalidDoseException Thrown if statistic was not initialized. + */ + DoseStatisticType getNumberOfVoxels(); + + /*! @brief Get the maximum of the current dose distribution. + @param maxVoxelVector: vector of all voxel with the dose=maximum. + @return Return the maximum dose in Gy, or -1 if an error occured. + @exception InvalidDoseException Thrown if statistic was not initialized. + */ + DoseStatisticType getMaximum( ResultListPointer maxVoxelVector) const; + + /*! @brief Get the minimum of the current dose distribution. + @param minVoxelVector: vector of all voxel with the dose=minimum. + @param number: the number of dose voxels with dose=minimum that are stored in minVoxelVector. + Only the first occurences are stored. The default value is 100. + @return Return the minimum dose in Gy, or -1 if an error occured. + @exception InvalidDoseException Thrown if statistic was not initialized. + */ + DoseStatisticType getMinimum( ResultListPointer minVoxelVector, int number=100) const; + + /*! @brief Get the mean of the current dose distribution. + @return Return the mean dose in Gy, or -1 if an error occured. + @exception InvalidDoseException Thrown if statistic was not initialized. + */ + DoseStatisticType getMean() const; + + /*! @brief Get the standard deviation of the current dose distribution. + @return Return the standard deviation in Gy, or -1 if an error occured. + @exception InvalidDoseException Thrown if statistic was not initialized. + */ + DoseStatisticType getStdDeviation() const; + + /*! @brief Get the variance of of the current dose distribution. + @return Return the variance in Gy, or -1 if an error occured. + @exception InvalidDoseException Thrown if statistic was not initialized. + */ + DoseStatisticType getVariance() const; + + /*! @brief Get Vx: the volume irradiated with a dose >= x. + @return Return absolute volume in absolute cm3. + */ + VolumeType getVx(DoseTypeGy xDoseAbsolute) const; + + /*! @brief Get Dx: the minimal dose delivered to part x of the current volume. + @return Return dose value in Gy. + */ + DoseTypeGy getDx(VolumeType xVolumeAbsolute) const; + + /*! @brief Get MOHx: mean dose of the hottest x voxels. + @return Return dose value in Gy. + */ + DoseTypeGy getMOHx(VolumeType xVolumeAbsolute) const; + + /*! @brief Get MOCx: mean dose of the coldest x voxels. + @return Return dose value in Gy. + */ + DoseTypeGy getMOCx(VolumeType xVolumeAbsolute) const; + + /*! @brief Get MaxOHx: Maximum outside of the hottest x voxels. + @return Return dose value in Gy. + */ + DoseTypeGy getMaxOHx(VolumeType xVolumeAbsolute) const; + + /*! @brief Get MinOCx: Minimum outside of the coldest x voxels. + @return Return ose value in Gy. + */ + DoseTypeGy getMinOCx(VolumeType xVolumeAbsolute) const; + }; + + } } -} #endif diff --git a/code/algorithms/rttbDoseStatisticsCalculator.cpp b/code/algorithms/rttbDoseStatisticsCalculator.cpp deleted file mode 100644 index 2039fcf..0000000 --- a/code/algorithms/rttbDoseStatisticsCalculator.cpp +++ /dev/null @@ -1,554 +0,0 @@ -// ----------------------------------------------------------------------- -// 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: 877 $ (last changed revision) -// @date $Date: 2015-01-09 10:51:10 +0100 (Fr, 09 Jan 2015) $ (last change date) -// @author $Author: hentsch $ (last changed by) -*/ - -#include "rttbDoseStatisticsCalculator.h" - -#include -#include -#include - -#include "rttbNullPointerException.h" -#include "rttbInvalidDoseException.h" -#include "rttbInvalidParameterException.h" - -namespace rttb -{ - - namespace algorithms - { - DoseStatisticsCalculator::DoseStatisticsCalculator() - { - simpleDoseStatisticsCalculated = false; - _doseIterator = NULL; - } - - DoseStatisticsCalculator::DoseStatisticsCalculator(DoseIteratorPointer aDoseIterator) - { - setDoseIterator(aDoseIterator); - simpleDoseStatisticsCalculated = false; - } - - - DoseStatisticsCalculator::~DoseStatisticsCalculator() - { - - } - - - void DoseStatisticsCalculator::setDoseIterator(DoseIteratorPointer aDoseIterator) - { - if (aDoseIterator == NULL) - { - throw core::NullPointerException("DoseIterator must not be NULL"); - } - else - { - _doseIterator = aDoseIterator; - } - } - - DoseStatisticsCalculator::DoseIteratorPointer DoseStatisticsCalculator::getDoseIterator() const - { - return _doseIterator; - } - - - DoseStatisticsCalculator::DoseStatisticsPointer DoseStatisticsCalculator::calculateDoseStatistics( - bool computeComplexMeasures, const std::vector& precomputeDoseValues, - const std::vector& precomputeVolumeValues) - { - - if (!_doseIterator) - { - throw core::NullPointerException("_doseIterator must not be NULL!"); - } - - //"simple" dose statistics are obligatory - calculateSimpleDoseStatistics(); - - if (computeComplexMeasures) - { - //more complex dose statistics are optional - calculateComplexDoseStatistics(precomputeDoseValues, precomputeVolumeValues); - } - - return _statistics; - - } - - - void DoseStatisticsCalculator::calculateSimpleDoseStatistics() - { - _doseVector.clear(); - _voxelProportionVector.clear(); - - std::multimap doseValueVSIndexMap; - std::vector voxelProportionVectorTemp; - - - DoseStatisticType maximumDose = 0; - DoseStatisticType minimumDose = 0; - DoseStatisticType meanDose = 0; - DoseStatisticType stdDeviationDose = 0; - - - float sum = 0; - unsigned int numVoxels = 0; - float squareSum = 0; - VolumeType volume; - - _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; - DoseStatisticType varianceDose = (squareSum / numVoxels - meanDose * meanDose); - - //standard deviation is defined only for n>=2 - if (varianceDose < errorConstant || numVoxels <= 2) - { - stdDeviationDose = 0; - } - else - { - stdDeviationDose = pow(varianceDose, 0.5); - } - - } - - //sort dose values and corresponding volume fractions in member variables - std::multimap::iterator it; - - for (it = doseValueVSIndexMap.begin(); it != doseValueVSIndexMap.end(); ++it) - { - _doseVector.push_back((float)(*it).first); - _voxelProportionVector.push_back(voxelProportionVectorTemp.at((*it).second)); - } - - volume *= numVoxels; - - _statistics = boost::make_shared(minimumDose, maximumDose, meanDose, stdDeviationDose, numVoxels, - volume); - - simpleDoseStatisticsCalculated = true; - - ResultListPointer minimumVoxelPositions = computeMinimumPositions(100); - ResultListPointer maximumVoxelPositions = computeMaximumPositions(100); - - _statistics->setMinimumVoxelPositions(minimumVoxelPositions); - _statistics->setMaximumVoxelPositions(maximumVoxelPositions); - - - } - - - void DoseStatisticsCalculator::calculateComplexDoseStatistics(const std::vector& precomputeDoseValues, - const std::vector& precomputeVolumeValues) - { - std::vector precomputeDoseValuesNonConst = precomputeDoseValues; - std::vector precomputeVolumeValuesNonConst = precomputeVolumeValues; - - //set default values - if (precomputeDoseValues.empty()) - { - std::vector defaultPrecomputeDoseValues = boost::assign::list_of(0.02 * _statistics->getMaximum())( - 0.05 * _statistics->getMaximum())(0.1 * _statistics->getMaximum())(0.9 * _statistics->getMaximum())( - 0.95 * _statistics->getMaximum())(0.98 * _statistics->getMaximum()); - precomputeDoseValuesNonConst = defaultPrecomputeDoseValues; - } - - if (precomputeVolumeValues.empty()) - { - std::vector defaultPrecomputeVolumeValues = boost::assign::list_of(0.02 * _statistics->getNumberOfVoxels())( - 0.05 * _statistics->getNumberOfVoxels())(0.1 * _statistics->getNumberOfVoxels())(0.9 * _statistics->getNumberOfVoxels()) - (0.95 * _statistics->getNumberOfVoxels())(0.98 * _statistics->getNumberOfVoxels()); - precomputeVolumeValuesNonConst = defaultPrecomputeVolumeValues; - } - - DoseToVolumeFunctionType Vx = computeDoseToVolumeMulti(precomputeDoseValuesNonConst, DoseStatistics::Vx); - VolumeToDoseFunctionType Dx = computeVolumeToDoseFunctionMulti(precomputeVolumeValuesNonConst, DoseStatistics::Dx); - VolumeToDoseFunctionType MOHx = computeVolumeToDoseFunctionMulti(precomputeVolumeValuesNonConst, DoseStatistics::MOHx); - VolumeToDoseFunctionType MOCx = computeVolumeToDoseFunctionMulti(precomputeVolumeValuesNonConst, DoseStatistics::MOCx); - VolumeToDoseFunctionType MaxOHx = computeVolumeToDoseFunctionMulti(precomputeVolumeValuesNonConst, - DoseStatistics::MaxOHx); - VolumeToDoseFunctionType MinOCx = computeVolumeToDoseFunctionMulti(precomputeVolumeValuesNonConst, - DoseStatistics::MinOCx); - - _statistics->setVx(Vx); - _statistics->setDx(Dx); - _statistics->setMOHx(MOHx); - _statistics->setMOCx(MOCx); - _statistics->setMaxOHx(MaxOHx); - _statistics->setMinOCx(MinOCx); - } - - - - DoseStatisticsCalculator::ResultListPointer DoseStatisticsCalculator::computeMaximumPositions( - unsigned int maxNumberMaxima) - { - if (!simpleDoseStatisticsCalculated) - { - throw core::InvalidDoseException("simple DoseStatistics have to be computed in order to call computeMaximumAndPosition()"); - - } - - 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) - { - if (!simpleDoseStatisticsCalculated) - { - throw core::InvalidDoseException("simple DoseStatistics have to be computed in order to call computeMinimumAndPosition()"); - - } - - 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(); - } - - DoseTypeGy DoseStatisticsCalculator::computeDx(VolumeType xVolumeAbsolute) const - { - double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); - DoseTypeGy resultDose = 0; - - double countVoxels = 0; - int i = _doseVector.size() - 1; - - for (; i >= 0; i--) - { - countVoxels += _voxelProportionVector.at(i); - - if (countVoxels >= noOfVoxel) - { - break; - } - } - - if (i >= 0) - { - resultDose = _doseVector.at(i); - } - else - { - resultDose = _statistics->getMinimum(); - } - - return resultDose; - } - - DoseTypeGy DoseStatisticsCalculator::computeMOHx(VolumeType xVolumeAbsolute) const - { - double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); - - - if (noOfVoxel == 0) - { - return 0; - } - else - { - double countVoxels = 0; - double sum = 0; - - for (int i = _doseVector.size() - 1; i >= 0; i--) - { - double voxelProportion = _voxelProportionVector.at(i); - countVoxels += voxelProportion; - sum += _doseVector.at(i) * voxelProportion; - - if (countVoxels >= noOfVoxel) - { - break; - } - } - - return (DoseTypeGy)(sum / noOfVoxel); - } - } - - DoseTypeGy DoseStatisticsCalculator::computeMOCx(DoseTypeGy xVolumeAbsolute) const - { - double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); - - - if (noOfVoxel == 0) - { - return 0; - } - else - { - double countVoxels = 0; - double sum = 0; - std::vector::const_iterator it = _doseVector.begin(); - std::vector::const_iterator itD = _voxelProportionVector.begin(); - - for (; it != _doseVector.end(); ++it, ++itD) - { - double voxelProportion = *itD; - countVoxels += voxelProportion; - sum += (*it) * voxelProportion; - - if (countVoxels >= noOfVoxel) - { - break; - } - } - - return (DoseTypeGy)(sum / noOfVoxel); - } - } - - DoseTypeGy DoseStatisticsCalculator::computeMaxOHx(DoseTypeGy xVolumeAbsolute) const - { - double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); - DoseTypeGy resultDose = 0; - - double countVoxels = 0; - int i = _doseVector.size() - 1; - - for (; i >= 0; i--) - { - countVoxels += _voxelProportionVector.at(i); - - if (countVoxels >= noOfVoxel) - { - break; - } - } - - if (i - 1 >= 0) - { - resultDose = _doseVector.at(i - 1); - } - - return resultDose; - } - - DoseTypeGy DoseStatisticsCalculator::computeMinOCx(DoseTypeGy xVolumeAbsolute) const - { - double noOfVoxel = xVolumeAbsolute / _doseIterator->getCurrentVoxelVolume(); - DoseTypeGy resultDose = 0; - - double countVoxels = 0; - std::vector::const_iterator it = _doseVector.begin(); - std::vector::const_iterator itD = _voxelProportionVector.begin(); - - for (; itD != _voxelProportionVector.end(); ++itD, ++it) - { - countVoxels += *itD; - - if (countVoxels >= noOfVoxel) - { - break; - } - } - - if (it != _doseVector.end()) - { - ++it; - - if (it != _doseVector.end()) - { - resultDose = *it; - } - else - { - resultDose = (DoseTypeGy)_statistics->getMaximum(); - } - } - else - { - resultDose = (DoseTypeGy)_statistics->getMinimum(); - } - - return resultDose; - } - - DoseStatisticsCalculator::DoseToVolumeFunctionType DoseStatisticsCalculator::computeDoseToVolumeMulti( - const std::vector& precomputeDoseValues, DoseStatistics::complexStatistics name) const - { - DoseToVolumeFunctionType VxMulti; - DoseTypeGy maxDose = _statistics->getMaximum(); - - for (int i = 0; i < precomputeDoseValues.size(); ++i) - { - if (name == DoseStatistics::Vx) - { - VxMulti.insert(std::pair(precomputeDoseValues.at(i), - computeVx(maxDose * (precomputeDoseValues.at(i) / 100.0)))); - } - } - - return VxMulti; - } - - DoseStatisticsCalculator::VolumeToDoseFunctionType DoseStatisticsCalculator::computeVolumeToDoseFunctionMulti( - const std::vector& precomputeVolumeValues, DoseStatistics::complexStatistics name) const - { - VolumeToDoseFunctionType multiValues; - VolumeType maxVolume = _statistics->getNumberOfVoxels(); - - for (int i = 0; i < precomputeVolumeValues.size(); ++i) - { - switch (name) - { - case DoseStatistics::Dx: - multiValues.insert(std::pair(precomputeVolumeValues.at(i), - computeDx(maxVolume * (precomputeVolumeValues.at(i) / 100.0)))); - break; - - case DoseStatistics::MOHx: - multiValues.insert(std::pair(precomputeVolumeValues.at(i), - computeMOHx(maxVolume * (precomputeVolumeValues.at(i) / 100.0)))); - break; - - case DoseStatistics::MOCx: - multiValues.insert(std::pair(precomputeVolumeValues.at(i), - computeMOCx(maxVolume * (precomputeVolumeValues.at(i) / 100.0)))); - break; - - case DoseStatistics::MaxOHx: - multiValues.insert(std::pair(precomputeVolumeValues.at(i), - computeMaxOHx(maxVolume * (precomputeVolumeValues.at(i) / 100.0)))); - break; - - case DoseStatistics::MinOCx: - multiValues.insert(std::pair(precomputeVolumeValues.at(i), - computeMinOCx(maxVolume * (precomputeVolumeValues.at(i) / 100.0)))); - break; - - default: - throw core::InvalidParameterException("unknown DoseStatistics name!"); - } - } - - return multiValues; - } - - }//end namespace algorithms -}//end namespace rttb - diff --git a/code/algorithms/rttbDoseStatisticsCalculator.h b/code/algorithms/rttbDoseStatisticsCalculator.h deleted file mode 100644 index 8d01d25..0000000 --- a/code/algorithms/rttbDoseStatisticsCalculator.h +++ /dev/null @@ -1,120 +0,0 @@ -// ----------------------------------------------------------------------- -// 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: 707 $ (last changed revision) -// @date $Date: 2014-09-04 16:37:24 +0200 (Do, 04 Sep 2014) $ (last change date) -// @author $Author: floca $ (last changed by) -*/ - -#ifndef __DOSE_STATISTICS_CALCULATOR_H -#define __DOSE_STATISTICS_CALCULATOR_H - -#include - -#include "rttbBaseType.h" -#include "rttbDoseIteratorInterface.h" -#include "rttbDoseStatistics.h" - -namespace rttb -{ - - namespace algorithms - { - - /*! @class DoseStatisticsCalculator - @brief This is a class calculating different statistical values from a rt dose distribution - These values range from standard statistical values such as minimum, maximum and mean to more - dose specific properties such as Vx (volume irradiated with a dose >=x), Dx (minimal dose delivered - to x% of the VOI, and MOHx (mean in the hottest volume). - */ - class DoseStatisticsCalculator - { - public: - typedef core::DoseIteratorInterface::DoseIteratorPointer DoseIteratorPointer; - typedef DoseStatistics::ResultListPointer ResultListPointer; - typedef DoseStatistics::DoseStatisticsPointer DoseStatisticsPointer; - typedef DoseStatistics::DoseToVolumeFunctionType DoseToVolumeFunctionType; - typedef DoseStatistics::VolumeToDoseFunctionType VolumeToDoseFunctionType; - - private: - DoseIteratorPointer _doseIterator; - - /* Contains relevant dose values sorted in descending order. - */ - std::vector _doseVector; - - /*! Contains the corresponding voxel proportions to the values in doseVector. - */ - std::vector _voxelProportionVector; - - - DoseStatisticsPointer _statistics; - - bool simpleDoseStatisticsCalculated; - - /*! @brief Calculation of basic dose statistics. It will be called in Constructor. - @exception NullPointerException Thrown if _doseIterator is NULL. - */ - - - ResultListPointer computeMaximumPositions(unsigned int maxNumberMaxima); - - ResultListPointer computeMinimumPositions(unsigned int maxNumberMinima); - VolumeType computeVx(DoseTypeGy xDoseAbsolute) const; - DoseTypeGy computeDx(VolumeType xVolumeAbsolute) const; - DoseTypeGy computeMOHx(VolumeType xVolumeAbsolute) const; - DoseTypeGy computeMOCx(DoseTypeGy xVolumeAbsolute) const; - DoseTypeGy computeMaxOHx(DoseTypeGy xVolumeAbsolute) const; - DoseTypeGy computeMinOCx(DoseTypeGy xVolumeAbsolute) const; - - DoseToVolumeFunctionType computeDoseToVolumeMulti(const std::vector& precomputeDoseValues, - DoseStatistics::complexStatistics name) const; - VolumeToDoseFunctionType computeVolumeToDoseFunctionMulti(const std::vector& precomputeVolumeValues, - DoseStatistics::complexStatistics name) const; - - void calculateSimpleDoseStatistics(); - void calculateComplexDoseStatistics(const std::vector& precomputeDoseValues, - const std::vector& precomputeVolumeValues); - - - public: - /*! @brief Standard Constructor - */ - DoseStatisticsCalculator(); - - ~DoseStatisticsCalculator(); - - /*! @brief Constructor - */ - DoseStatisticsCalculator(DoseIteratorPointer aDoseIterator); - - /*! @brief Set new dose data for statistics. Statistics will be re-initialized. - */ - void setDoseIterator(DoseIteratorPointer aDoseIterator); - - DoseIteratorPointer getDoseIterator() const; - - DoseStatisticsPointer calculateDoseStatistics(bool computeComplexMeasures = false, - const std::vector& precomputeDoseValues = std::vector(), - const std::vector& precomputeVolumeValues = std::vector()); - - }; - - } -} - - -#endif diff --git a/code/core/files.cmake b/code/core/files.cmake index 56c703a..069db8c 100644 --- a/code/core/files.cmake +++ b/code/core/files.cmake @@ -1,60 +1,58 @@ SET(CPP_FILES rttbDoseIteratorInterface.cpp rttbDVH.cpp rttbDVHCalculator.cpp rttbDVHSet.cpp - rttbDataNotAvailableException.cpp rttbException.cpp rttbGenericDoseIterator.cpp rttbGenericMaskedDoseIterator.cpp rttbGeometricInfo.cpp rttbIndexOutOfBoundsException.cpp rttbInvalidDoseException.cpp rttbInvalidParameterException.cpp rttbMappingOutsideOfImageException.cpp rttbMaskedDoseIteratorInterface.cpp rttbMaskVoxel.cpp rttbNullPointerException.cpp rttbPaddingException.cpp rttbPhysicalInfo.cpp rttbStructure.cpp rttbStructureSet.cpp rttbStrVectorStructureSetGenerator.cpp ) SET(H_FILES rttbBaseType.h - rttbDataNotAvailableException.h rttbDoseAccessorGeneratorBase.h rttbDoseAccessorGeneratorInterface.h rttbDoseAccessorInterface.h rttbDoseIteratorInterface.h rttbDVH.h rttbDVHCalculator.h rttbDVHGeneratorInterface.h rttbDVHSet.h rttbException.h rttbExceptionMacros.h rttbGenericDoseIterator.h rttbGenericMaskedDoseIterator.h rttbGeometricInfo.h rttbIndexConversionInterface.h rttbIndexOutOfBoundsException.h rttbInvalidDoseException.h rttbInvalidParameterException.h rttbMappingOutsideOfImageException.h rttbMaskAccessorGeneratorBase.h rttbMaskAccessorGeneratorInterface.h rttbMaskAccessorInterface.h rttbMaskedDoseIteratorInterface.h rttbMaskVoxel.h rttbMutableDoseAccessorInterface.h rttbMutableMaskAccessorInterface.h rttbNullPointerException.h rttbPaddingException.h rttbPhysicalInfo.h rttbStructure.h rttbStructureSet.h rttbStructureSetGeneratorInterface.h rttbStrVectorStructureSetGenerator.h ) diff --git a/code/core/rttbDataNotAvailableException.cpp b/code/core/rttbDataNotAvailableException.cpp deleted file mode 100644 index 357c781..0000000 --- a/code/core/rttbDataNotAvailableException.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// ----------------------------------------------------------------------- -// 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: 741 $ (last changed revision) -// @date $Date: 2014-09-16 16:34:22 +0200 (Di, 16 Sep 2014) $ (last change date) -// @author $Author: hentsch $ (last changed by) -*/ - -#include -#include - -#include "rttbDataNotAvailableException.h" - -namespace rttb -{ - namespace core - { - - const char* DataNotAvailableException::what() const throw() - { - return rttb_what.c_str(); - } - - const char* DataNotAvailableException::GetNameOfClass() const - { - return "DataNotAvailableException"; - } - - }//end namespace core -}//end namespace rttb diff --git a/code/core/rttbDataNotAvailableException.h b/code/core/rttbDataNotAvailableException.h deleted file mode 100644 index bfa78c1..0000000 --- a/code/core/rttbDataNotAvailableException.h +++ /dev/null @@ -1,58 +0,0 @@ -// ----------------------------------------------------------------------- -// 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: 741 $ (last changed revision) -// @date $Date: 2014-09-16 16:34:22 +0200 (Di, 16 Sep 2014) $ (last change date) -// @author $Author: hentsch $ (last changed by) -*/ - -#ifndef __DATA_NOT_AVAILABLE_EXCEPTION_H -#define __DATA_NOT_AVAILABLE_EXCEPTION_H - -#include -#include - -#include "rttbException.h" - - -namespace rttb -{ - namespace core - { - - /*! @class DataNotAvailableException - @brief This exception will be thrown if the requested data is not available. - */ - class DataNotAvailableException : public Exception - { - public: - DataNotAvailableException(const std::string& aWhat) : Exception(aWhat) {} - - virtual ~DataNotAvailableException() throw() {} - - /*! @brief Get the exception description - */ - virtual const char* what() const throw(); - - /*! @brief Get the name of the exception class - */ - virtual const char* GetNameOfClass() const; - }; - - } -} - -#endif diff --git a/code/io/other/rttbDoseStatisticsXMLWriter.cpp b/code/io/other/rttbDoseStatisticsXMLWriter.cpp index 39bf48e..88beb4e 100644 --- a/code/io/other/rttbDoseStatisticsXMLWriter.cpp +++ b/code/io/other/rttbDoseStatisticsXMLWriter.cpp @@ -1,464 +1,380 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include #include #include "rttbDoseStatisticsXMLWriter.h" #include "rttbNullPointerException.h" #include "rttbInvalidParameterException.h" -#include "rttbDataNotAvailableException.h" #include "rttbException.h" #include "boost/lexical_cast.hpp" namespace rttb { namespace io { namespace other { static const std::string xmlattrTag = ".x"; static const std::string statisticsTag = "statistics"; static const std::string columnSeparator = "@"; boost::property_tree::ptree writeDoseStatistics(DoseStatisticsPtr aDoseStatistics, DoseTypeGy aReferenceDose) { using boost::property_tree::ptree; ptree pt; - /*rttb::core::DoseIteratorInterface::DoseIteratorPointer spDoseIterator = - aDoseStatistics->getDoseIterator(); - rttb::core::DoseIteratorInterface::DoseAccessorPointer spDoseAccessor = - spDoseIterator->getDoseAccessor(); + rttb::core::DoseIteratorInterface::DoseIteratorPointer spDoseIterator = + aDoseStatistics->getDoseIterator(); + rttb::core::DoseIteratorInterface::DoseAccessorPointer spDoseAccessor = + spDoseIterator->getDoseAccessor(); - boost::shared_ptr< std::vector > > myResultPairs = - boost::make_shared< std::vector > >(); - ResultListPointer spMyResultPairs(myResultPairs); - boost::shared_ptr< std::vector > > myResultPairs2 = - boost::make_shared< std::vector > >(); - ResultListPointer spMyResultPairs2(myResultPairs2);*/ + boost::shared_ptr< std::vector > > myResultPairs = + boost::make_shared< std::vector > >(); + ResultListPointer spMyResultPairs(myResultPairs); + boost::shared_ptr< std::vector > > myResultPairs2 = + boost::make_shared< std::vector > >(); + ResultListPointer spMyResultPairs2(myResultPairs2); pt.put(statisticsTag + ".numberOfVoxels", aDoseStatistics->getNumberOfVoxels()); - pt.put(statisticsTag + ".volume", aDoseStatistics->getVolume()); - pt.put(statisticsTag + ".minimum", aDoseStatistics->getMinimum()); - - auto minimumPositions = aDoseStatistics->getMinimumPositions(); - std::vector >::iterator pairItMin = minimumPositions->begin(); + pt.put(statisticsTag + ".volume", aDoseStatistics->getVx(0)); + pt.put(statisticsTag + ".minimum", aDoseStatistics->getMinimum(spMyResultPairs)); + std::vector >::iterator pairIt = spMyResultPairs->begin(); int count = 0; - for (; pairItMin != minimumPositions->end() && count < 100; ++pairItMin) //output max. 100 minimum + for (; pairIt != spMyResultPairs->end() && count < 100 ; ++pairIt) //output max. 100 minimum { - VoxelGridID voxelID = pairItMin->second; + VoxelGridID voxelID = pairIt->second; pt.add(statisticsTag + ".minimum.voxelGridID", voxelID); - //VoxelGridIndex3D voxelIndex3D; - //spDoseAccessor->getGeometricInfo().convert(voxelID, voxelIndex3D); - //std::string voxelIndex3DStr; - //voxelIndex3DStr = boost::lexical_cast(voxelIndex3D.x()) + "," - // + boost::lexical_cast(voxelIndex3D.y()) + "," - // + boost::lexical_cast(voxelIndex3D.z()); - //pt.add(statisticsTag + ".minimum.voxelIndex3D", voxelIndex3DStr); - - //WorldCoordinate3D worldCoor; - //spDoseAccessor->getGeometricInfo().indexToWorldCoordinate(voxelIndex3D, worldCoor); - //std::string worldCoorStr; - //worldCoorStr = boost::lexical_cast(worldCoor.x()) + "," - // + boost::lexical_cast(worldCoor.y()) + "," - // + boost::lexical_cast(worldCoor.z()); - //pt.add(statisticsTag + ".minimum.worldCoordinate", worldCoorStr); + VoxelGridIndex3D voxelIndex3D; + spDoseAccessor->getGeometricInfo().convert(voxelID, voxelIndex3D); + std::string voxelIndex3DStr; + voxelIndex3DStr = boost::lexical_cast(voxelIndex3D.x()) + "," + + boost::lexical_cast(voxelIndex3D.y()) + "," + + boost::lexical_cast(voxelIndex3D.z()); + pt.add(statisticsTag + ".minimum.voxelIndex3D", voxelIndex3DStr); + + WorldCoordinate3D worldCoor; + spDoseAccessor->getGeometricInfo().indexToWorldCoordinate(voxelIndex3D, worldCoor); + std::string worldCoorStr; + worldCoorStr = boost::lexical_cast(worldCoor.x()) + "," + + boost::lexical_cast(worldCoor.y()) + "," + + boost::lexical_cast(worldCoor.z()); + pt.add(statisticsTag + ".minimum.worldCoordinate", worldCoorStr); count++; } - pt.put(statisticsTag + ".maximum", aDoseStatistics->getMaximum()); - - auto maximumPositions = aDoseStatistics->getMaximumPositions(); - std::vector >::iterator pairItMax = maximumPositions->begin(); + pt.put(statisticsTag + ".maximum", aDoseStatistics->getMaximum(spMyResultPairs2)); + std::vector >::iterator pairIt2 = spMyResultPairs2->begin(); count = 0; - for (; pairItMax != maximumPositions->end() && count < 100; ++pairItMax) //output max. 100 maximum + for (; pairIt2 != spMyResultPairs2->end() && count < 100; ++pairIt2) //output max. 100 maximum { - VoxelGridID voxelID = pairItMax->second; + VoxelGridID voxelID = pairIt2->second; pt.add(statisticsTag + ".maximum.voxelGridID", voxelID); - //VoxelGridIndex3D voxelIndex3D; - //spDoseAccessor->getGeometricInfo().convert(voxelID, voxelIndex3D); - //std::string voxelIndex3DStr; - //voxelIndex3DStr = boost::lexical_cast(voxelIndex3D.x()) + "," - // + boost::lexical_cast(voxelIndex3D.y()) + "," - // + boost::lexical_cast(voxelIndex3D.z()); - //pt.add(statisticsTag + ".maximum.voxelIndex3D", voxelIndex3DStr); + VoxelGridIndex3D voxelIndex3D; + spDoseAccessor->getGeometricInfo().convert(voxelID, voxelIndex3D); + std::string voxelIndex3DStr; + voxelIndex3DStr = boost::lexical_cast(voxelIndex3D.x()) + "," + + boost::lexical_cast(voxelIndex3D.y()) + "," + + boost::lexical_cast(voxelIndex3D.z()); + pt.add(statisticsTag + ".maximum.voxelIndex3D", voxelIndex3DStr); - //WorldCoordinate3D worldCoor; - //spDoseAccessor->getGeometricInfo().indexToWorldCoordinate(voxelIndex3D, worldCoor); - //std::string worldCoorStr; - //worldCoorStr = boost::lexical_cast(worldCoor.x()) + "," - // + boost::lexical_cast(worldCoor.y()) + "," - // + boost::lexical_cast(worldCoor.z()); - //pt.add(statisticsTag + ".maximum.worldCoordinate", worldCoorStr); + WorldCoordinate3D worldCoor; + spDoseAccessor->getGeometricInfo().indexToWorldCoordinate(voxelIndex3D, worldCoor); + std::string worldCoorStr; + worldCoorStr = boost::lexical_cast(worldCoor.x()) + "," + + boost::lexical_cast(worldCoor.y()) + "," + + boost::lexical_cast(worldCoor.z()); + pt.add(statisticsTag + ".maximum.worldCoordinate", worldCoorStr); count ++; } pt.put(statisticsTag + ".mean", aDoseStatistics->getMean()); pt.put(statisticsTag + ".standardDeviation", aDoseStatistics->getStdDeviation()); pt.put(statisticsTag + ".variance", aDoseStatistics->getVariance()); - double absoluteVolume = aDoseStatistics->getVolume(); - - try - { - //Dx - boost::property_tree::ptree dxNode1; - boost::property_tree::ptree dxNode2; - boost::property_tree::ptree dxNode3; - boost::property_tree::ptree dxNode4; - boost::property_tree::ptree dxNode5; - boost::property_tree::ptree dxNode6; - - dxNode1.put("", aDoseStatistics->getDx(absoluteVolume * 0.02)); - dxNode2.put("", aDoseStatistics->getDx(absoluteVolume * 0.05)); - dxNode3.put("", aDoseStatistics->getDx(absoluteVolume * 0.10)); - dxNode4.put("", aDoseStatistics->getDx(absoluteVolume * 0.90)); - dxNode5.put("", aDoseStatistics->getDx(absoluteVolume * 0.95)); - dxNode6.put("", aDoseStatistics->getDx(absoluteVolume * 0.98)); - - dxNode1.put(xmlattrTag, 2); - dxNode2.put(xmlattrTag, 5); - dxNode3.put(xmlattrTag, 10); - dxNode4.put(xmlattrTag, 90); - dxNode5.put(xmlattrTag, 95); - dxNode6.put(xmlattrTag, 98); - - pt.add_child(statisticsTag + ".Dx", dxNode1); - pt.add_child(statisticsTag + ".Dx", dxNode2); - pt.add_child(statisticsTag + ".Dx", dxNode3); - pt.add_child(statisticsTag + ".Dx", dxNode4); - pt.add_child(statisticsTag + ".Dx", dxNode5); - pt.add_child(statisticsTag + ".Dx", dxNode6); - } - catch (core::DataNotAvailableException) - { - //as data is not available (was not computed by doseStatistics), it cannot be written - } + /*to do: x should be defined based on the user's feedback*/ + //Dx + boost::property_tree::ptree dxNode1; + boost::property_tree::ptree dxNode2; + boost::property_tree::ptree dxNode3; + boost::property_tree::ptree dxNode4; + boost::property_tree::ptree dxNode5; + boost::property_tree::ptree dxNode6; + + double absoluteVolume = aDoseStatistics->getVx(0); + + dxNode1.put("", aDoseStatistics->getDx(absoluteVolume * 0.02)); + dxNode2.put("", aDoseStatistics->getDx(absoluteVolume * 0.05)); + dxNode3.put("", aDoseStatistics->getDx(absoluteVolume * 0.10)); + dxNode4.put("", aDoseStatistics->getDx(absoluteVolume * 0.90)); + dxNode5.put("", aDoseStatistics->getDx(absoluteVolume * 0.95)); + dxNode6.put("", aDoseStatistics->getDx(absoluteVolume * 0.98)); + + dxNode1.put(xmlattrTag, 2); + dxNode2.put(xmlattrTag, 5); + dxNode3.put(xmlattrTag, 10); + dxNode4.put(xmlattrTag, 90); + dxNode5.put(xmlattrTag, 95); + dxNode6.put(xmlattrTag, 98); + + pt.add_child(statisticsTag + ".Dx", dxNode1); + pt.add_child(statisticsTag + ".Dx", dxNode2); + pt.add_child(statisticsTag + ".Dx", dxNode3); + pt.add_child(statisticsTag + ".Dx", dxNode4); + pt.add_child(statisticsTag + ".Dx", dxNode5); + pt.add_child(statisticsTag + ".Dx", dxNode6); if (aReferenceDose <= 0) { throw core::InvalidParameterException("aReferenceDose should be >0!"); } - try - { - //Vx - boost::property_tree::ptree vxNode1; - boost::property_tree::ptree vxNode2; - boost::property_tree::ptree vxNode3; - boost::property_tree::ptree vxNode4; - boost::property_tree::ptree vxNode5; - boost::property_tree::ptree vxNode6; - - vxNode1.put("", aDoseStatistics->getVx(aReferenceDose * 0.02)); - vxNode2.put("", aDoseStatistics->getVx(aReferenceDose * 0.05)); - vxNode3.put("", aDoseStatistics->getVx(aReferenceDose * 0.10)); - vxNode4.put("", aDoseStatistics->getVx(aReferenceDose * 0.90)); - vxNode5.put("", aDoseStatistics->getVx(aReferenceDose * 0.95)); - vxNode6.put("", aDoseStatistics->getVx(aReferenceDose * 0.98)); - - vxNode1.put(xmlattrTag, 2); - vxNode2.put(xmlattrTag, 5); - vxNode3.put(xmlattrTag, 10); - vxNode4.put(xmlattrTag, 90); - vxNode5.put(xmlattrTag, 95); - vxNode6.put(xmlattrTag, 98); - - pt.add_child(statisticsTag + ".Vx", vxNode1); - pt.add_child(statisticsTag + ".Vx", vxNode2); - pt.add_child(statisticsTag + ".Vx", vxNode3); - pt.add_child(statisticsTag + ".Vx", vxNode4); - pt.add_child(statisticsTag + ".Vx", vxNode5); - pt.add_child(statisticsTag + ".Vx", vxNode6); - } - catch (core::DataNotAvailableException) - { - //as data is not available (was not computed by doseStatistics), it cannot be written - } - - try - { - //MOHx - boost::property_tree::ptree mohxNode1; - boost::property_tree::ptree mohxNode2; - boost::property_tree::ptree mohxNode3; - - mohxNode1.put("", aDoseStatistics->getMOHx(absoluteVolume * 0.02)); - mohxNode2.put("", aDoseStatistics->getMOHx(absoluteVolume * 0.05)); - mohxNode3.put("", aDoseStatistics->getMOHx(absoluteVolume * 0.10)); - - mohxNode1.put(xmlattrTag, 2); - mohxNode2.put(xmlattrTag, 5); - mohxNode3.put(xmlattrTag, 10); - - pt.add_child(statisticsTag + ".MOHx", mohxNode1); - pt.add_child(statisticsTag + ".MOHx", mohxNode2); - pt.add_child(statisticsTag + ".MOHx", mohxNode3); - } - catch (core::DataNotAvailableException) - { - //as data is not available (was not computed by doseStatistics), it cannot be written - } - - try - { - //MOCx - boost::property_tree::ptree mocxNode1; - boost::property_tree::ptree mocxNode2; - boost::property_tree::ptree mocxNode3; - - mocxNode1.put("", aDoseStatistics->getMOCx(absoluteVolume * 0.02)); - mocxNode2.put("", aDoseStatistics->getMOCx(absoluteVolume * 0.05)); - mocxNode3.put("", aDoseStatistics->getMOCx(absoluteVolume * 0.10)); - - mocxNode1.put(xmlattrTag, 2); - mocxNode2.put(xmlattrTag, 5); - mocxNode3.put(xmlattrTag, 10); - - pt.add_child(statisticsTag + ".MOCx", mocxNode1); - pt.add_child(statisticsTag + ".MOCx", mocxNode2); - pt.add_child(statisticsTag + ".MOCx", mocxNode3); - } - catch (core::DataNotAvailableException) - { - //as data is not available (was not computed by doseStatistics), it cannot be written - } - - try - { - //MaxOHx - boost::property_tree::ptree maxohxNode1; - boost::property_tree::ptree maxohxNode2; - boost::property_tree::ptree maxohxNode3; - - maxohxNode1.put("", aDoseStatistics->getMaxOHx(absoluteVolume * 0.02)); - maxohxNode2.put("", aDoseStatistics->getMaxOHx(absoluteVolume * 0.05)); - maxohxNode3.put("", aDoseStatistics->getMaxOHx(absoluteVolume * 0.10)); - - maxohxNode1.put(xmlattrTag, 2); - maxohxNode2.put(xmlattrTag, 5); - maxohxNode3.put(xmlattrTag, 10); - - pt.add_child(statisticsTag + ".MaxOHx", maxohxNode1); - pt.add_child(statisticsTag + ".MaxOHx", maxohxNode2); - pt.add_child(statisticsTag + ".MaxOHx", maxohxNode3); - } - catch (core::DataNotAvailableException) - { - //as data is not available (was not computed by doseStatistics), it cannot be written - } - - try - { - //MinOCx - boost::property_tree::ptree minocxNode1; - boost::property_tree::ptree minocxNode2; - boost::property_tree::ptree minocxNode3; - - minocxNode1.put("", aDoseStatistics->getMinOCx(absoluteVolume * 0.02)); - minocxNode2.put("", aDoseStatistics->getMinOCx(absoluteVolume * 0.05)); - minocxNode3.put("", aDoseStatistics->getMinOCx(absoluteVolume * 0.10)); - - minocxNode1.put(xmlattrTag, 2); - minocxNode2.put(xmlattrTag, 5); - minocxNode3.put(xmlattrTag, 10); - - pt.add_child(statisticsTag + ".MinOCx", minocxNode1); - pt.add_child(statisticsTag + ".MinOCx", minocxNode2); - pt.add_child(statisticsTag + ".MinOCx", minocxNode3); - } - catch (core::DataNotAvailableException) - { - //as data is not available (was not computed by doseStatistics), it cannot be written - } + //Vx + boost::property_tree::ptree vxNode1; + boost::property_tree::ptree vxNode2; + boost::property_tree::ptree vxNode3; + boost::property_tree::ptree vxNode4; + boost::property_tree::ptree vxNode5; + boost::property_tree::ptree vxNode6; + + vxNode1.put("", aDoseStatistics->getVx(aReferenceDose * 0.02)); + vxNode2.put("", aDoseStatistics->getVx(aReferenceDose * 0.05)); + vxNode3.put("", aDoseStatistics->getVx(aReferenceDose * 0.10)); + vxNode4.put("", aDoseStatistics->getVx(aReferenceDose * 0.90)); + vxNode5.put("", aDoseStatistics->getVx(aReferenceDose * 0.95)); + vxNode6.put("", aDoseStatistics->getVx(aReferenceDose * 0.98)); + + vxNode1.put(xmlattrTag, 2); + vxNode2.put(xmlattrTag, 5); + vxNode3.put(xmlattrTag, 10); + vxNode4.put(xmlattrTag, 90); + vxNode5.put(xmlattrTag, 95); + vxNode6.put(xmlattrTag, 98); + + pt.add_child(statisticsTag + ".Vx", vxNode1); + pt.add_child(statisticsTag + ".Vx", vxNode2); + pt.add_child(statisticsTag + ".Vx", vxNode3); + pt.add_child(statisticsTag + ".Vx", vxNode4); + pt.add_child(statisticsTag + ".Vx", vxNode5); + pt.add_child(statisticsTag + ".Vx", vxNode6); + + //MOHx + boost::property_tree::ptree mohxNode1; + boost::property_tree::ptree mohxNode2; + boost::property_tree::ptree mohxNode3; + + mohxNode1.put("", aDoseStatistics->getMOHx(absoluteVolume * 0.02)); + mohxNode2.put("", aDoseStatistics->getMOHx(absoluteVolume * 0.05)); + mohxNode3.put("", aDoseStatistics->getMOHx(absoluteVolume * 0.10)); + + mohxNode1.put(xmlattrTag, 2); + mohxNode2.put(xmlattrTag, 5); + mohxNode3.put(xmlattrTag, 10); + + pt.add_child(statisticsTag + ".MOHx", mohxNode1); + pt.add_child(statisticsTag + ".MOHx", mohxNode2); + pt.add_child(statisticsTag + ".MOHx", mohxNode3); + + //MOCx + boost::property_tree::ptree mocxNode1; + boost::property_tree::ptree mocxNode2; + boost::property_tree::ptree mocxNode3; + + mocxNode1.put("", aDoseStatistics->getMOCx(absoluteVolume * 0.02)); + mocxNode2.put("", aDoseStatistics->getMOCx(absoluteVolume * 0.05)); + mocxNode3.put("", aDoseStatistics->getMOCx(absoluteVolume * 0.10)); + + mocxNode1.put(xmlattrTag, 2); + mocxNode2.put(xmlattrTag, 5); + mocxNode3.put(xmlattrTag, 10); + + pt.add_child(statisticsTag + ".MOCx", mocxNode1); + pt.add_child(statisticsTag + ".MOCx", mocxNode2); + pt.add_child(statisticsTag + ".MOCx", mocxNode3); + + + //MaxOHx + boost::property_tree::ptree maxohxNode1; + boost::property_tree::ptree maxohxNode2; + boost::property_tree::ptree maxohxNode3; + + maxohxNode1.put("", aDoseStatistics->getMaxOHx(absoluteVolume * 0.02)); + maxohxNode2.put("", aDoseStatistics->getMaxOHx(absoluteVolume * 0.05)); + maxohxNode3.put("", aDoseStatistics->getMaxOHx(absoluteVolume * 0.10)); + + maxohxNode1.put(xmlattrTag, 2); + maxohxNode2.put(xmlattrTag, 5); + maxohxNode3.put(xmlattrTag, 10); + + pt.add_child(statisticsTag + ".MaxOHx", maxohxNode1); + pt.add_child(statisticsTag + ".MaxOHx", maxohxNode2); + pt.add_child(statisticsTag + ".MaxOHx", maxohxNode3); + + //MinOCx + boost::property_tree::ptree minocxNode1; + boost::property_tree::ptree minocxNode2; + boost::property_tree::ptree minocxNode3; + + minocxNode1.put("", aDoseStatistics->getMinOCx(absoluteVolume * 0.02)); + minocxNode2.put("", aDoseStatistics->getMinOCx(absoluteVolume * 0.05)); + minocxNode3.put("", aDoseStatistics->getMinOCx(absoluteVolume * 0.10)); + + minocxNode1.put(xmlattrTag, 2); + minocxNode2.put(xmlattrTag, 5); + minocxNode3.put(xmlattrTag, 10); + + pt.add_child(statisticsTag + ".MinOCx", minocxNode1); + pt.add_child(statisticsTag + ".MinOCx", minocxNode2); + pt.add_child(statisticsTag + ".MinOCx", minocxNode3); return pt; } void writeDoseStatistics(DoseStatisticsPtr aDoseStatistics, FileNameString aFileName, DoseTypeGy aReferenceDose) { boost::property_tree::ptree pt = writeDoseStatistics(aDoseStatistics, aReferenceDose); try { boost::property_tree::xml_parser::write_xml(aFileName, pt); } catch (boost::property_tree::xml_parser_error& /*e*/) { throw core::InvalidParameterException("Write xml failed: xml_parser_error!"); } } XMLString writerDoseStatisticsToString(DoseStatisticsPtr aDoseStatistics, DoseTypeGy aReferenceDose) { boost::property_tree::ptree pt = writeDoseStatistics(aDoseStatistics, aReferenceDose); std::stringstream sstr; try { boost::property_tree::xml_parser::write_xml(sstr, pt); } catch (boost::property_tree::xml_parser_error& /*e*/) { throw core::InvalidParameterException("Write xml to string failed: xml_parser_error!"); } return sstr.str(); } StatisticsString writerDoseStatisticsToTableString(DoseStatisticsPtr aDoseStatistics, DoseTypeGy aReferenceDose) { std::stringstream sstr; - //rttb::core::DoseIteratorInterface::DoseIteratorPointer spDoseIterator = - // aDoseStatistics->getDoseIterator(); - //rttb::core::DoseIteratorInterface::DoseAccessorPointer spDoseAccessor = - // spDoseIterator->getDoseAccessor(); + rttb::core::DoseIteratorInterface::DoseIteratorPointer spDoseIterator = + aDoseStatistics->getDoseIterator(); + rttb::core::DoseIteratorInterface::DoseAccessorPointer spDoseAccessor = + spDoseIterator->getDoseAccessor(); - //boost::shared_ptr< std::vector > > myResultPairs = - // boost::make_shared< std::vector > >(); - //ResultListPointer spMyResultPairs(myResultPairs); - //boost::shared_ptr< std::vector > > myResultPairs2 = - // boost::make_shared< std::vector > >(); - //ResultListPointer spMyResultPairs2(myResultPairs2); + boost::shared_ptr< std::vector > > myResultPairs = + boost::make_shared< std::vector > >(); + ResultListPointer spMyResultPairs(myResultPairs); + boost::shared_ptr< std::vector > > myResultPairs2 = + boost::make_shared< std::vector > >(); + ResultListPointer spMyResultPairs2(myResultPairs2); - sstr << aDoseStatistics->getVolume() * 1000 << columnSeparator; // cm3 to mm3 - sstr << aDoseStatistics->getMaximum() << columnSeparator; - sstr << aDoseStatistics->getMinimum() << columnSeparator; + sstr << aDoseStatistics->getVx(0) * 1000 << columnSeparator; // cm3 to mm3 + sstr << aDoseStatistics->getMaximum(spMyResultPairs2) << columnSeparator; + sstr << aDoseStatistics->getMinimum(spMyResultPairs) << columnSeparator; sstr << aDoseStatistics->getMean() << columnSeparator; sstr << aDoseStatistics->getStdDeviation() << columnSeparator; sstr << aDoseStatistics->getVariance() << columnSeparator; /*to do: x should be defined based on the user's feedback*/ if (aReferenceDose <= 0) { throw core::InvalidParameterException("aReferenceDose should be >0!"); } //Vx - try - { - sstr << aDoseStatistics->getVx(aReferenceDose * 0.02) * 1000 << columnSeparator; // cm3 to mm3 - sstr << aDoseStatistics->getVx(aReferenceDose * 0.05) * 1000 << columnSeparator; // cm3 to mm3 - sstr << aDoseStatistics->getVx(aReferenceDose * 0.10) * 1000 << columnSeparator; // cm3 to mm3 - sstr << aDoseStatistics->getVx(aReferenceDose * 0.90) * 1000 << columnSeparator; // cm3 to mm3 - sstr << aDoseStatistics->getVx(aReferenceDose * 0.95) * 1000 << columnSeparator; // cm3 to mm3 - sstr << aDoseStatistics->getVx(aReferenceDose * 0.98) * 1000 << columnSeparator; // cm3 to mm3 - } - catch (core::DataNotAvailableException) - { - //as data is not available (was not computed by doseStatistics), it cannot be written - } + sstr << aDoseStatistics->getVx(aReferenceDose * 0.02) * 1000 << columnSeparator; // cm3 to mm3 + sstr << aDoseStatistics->getVx(aReferenceDose * 0.05) * 1000 << columnSeparator; // cm3 to mm3 + sstr << aDoseStatistics->getVx(aReferenceDose * 0.10) * 1000 << columnSeparator; // cm3 to mm3 + sstr << aDoseStatistics->getVx(aReferenceDose * 0.90) * 1000 << columnSeparator; // cm3 to mm3 + sstr << aDoseStatistics->getVx(aReferenceDose * 0.95) * 1000 << columnSeparator; // cm3 to mm3 + sstr << aDoseStatistics->getVx(aReferenceDose * 0.98) * 1000 << columnSeparator; // cm3 to mm3 //Dx - double absoluteVolume = aDoseStatistics->getVolume(); + double absoluteVolume = aDoseStatistics->getVx(0); - try - { - sstr << aDoseStatistics->getDx(absoluteVolume * 0.02) << columnSeparator; - sstr << aDoseStatistics->getDx(absoluteVolume * 0.05) << columnSeparator; - sstr << aDoseStatistics->getDx(absoluteVolume * 0.10) << columnSeparator; - sstr << aDoseStatistics->getDx(absoluteVolume * 0.90) << columnSeparator; - sstr << aDoseStatistics->getDx(absoluteVolume * 0.95) << columnSeparator; - sstr << aDoseStatistics->getDx(absoluteVolume * 0.98) << columnSeparator; - } - catch (core::DataNotAvailableException) - { - //as data is not available (was not computed by doseStatistics), it cannot be written - } + sstr << aDoseStatistics->getDx(absoluteVolume * 0.02) << columnSeparator; + sstr << aDoseStatistics->getDx(absoluteVolume * 0.05) << columnSeparator; + sstr << aDoseStatistics->getDx(absoluteVolume * 0.10) << columnSeparator; + sstr << aDoseStatistics->getDx(absoluteVolume * 0.90) << columnSeparator; + sstr << aDoseStatistics->getDx(absoluteVolume * 0.95) << columnSeparator; + sstr << aDoseStatistics->getDx(absoluteVolume * 0.98) << columnSeparator; - try - { - //MOHx - sstr << aDoseStatistics->getMOHx(absoluteVolume * 0.02) << columnSeparator; - sstr << aDoseStatistics->getMOHx(absoluteVolume * 0.05) << columnSeparator; - sstr << aDoseStatistics->getMOHx(absoluteVolume * 0.10) << columnSeparator; - } - catch (core::DataNotAvailableException) - { - //as data is not available (was not computed by doseStatistics), it cannot be written - } - try - { - //MOCx - sstr << aDoseStatistics->getMOCx(absoluteVolume * 0.02) << columnSeparator; - sstr << aDoseStatistics->getMOCx(absoluteVolume * 0.05) << columnSeparator; - sstr << aDoseStatistics->getMOCx(absoluteVolume * 0.10) << columnSeparator; - } - catch (core::DataNotAvailableException) - { - //as data is not available (was not computed by doseStatistics), it cannot be written - } + //MOHx + sstr << aDoseStatistics->getMOHx(absoluteVolume * 0.02) << columnSeparator; + sstr << aDoseStatistics->getMOHx(absoluteVolume * 0.05) << columnSeparator; + sstr << aDoseStatistics->getMOHx(absoluteVolume * 0.10) << columnSeparator; - try - { - //MaxOHx - sstr << aDoseStatistics->getMaxOHx(absoluteVolume * 0.02) << columnSeparator; - sstr << aDoseStatistics->getMaxOHx(absoluteVolume * 0.05) << columnSeparator; - sstr << aDoseStatistics->getMaxOHx(absoluteVolume * 0.10) << columnSeparator; - } - catch (core::DataNotAvailableException) - { - //as data is not available (was not computed by doseStatistics), it cannot be written - } - try - { - //MinOCx - sstr << aDoseStatistics->getMinOCx(absoluteVolume * 0.02) << columnSeparator; - sstr << aDoseStatistics->getMinOCx(absoluteVolume * 0.05) << columnSeparator; - sstr << aDoseStatistics->getMinOCx(absoluteVolume * 0.10) << columnSeparator; - } - catch (core::DataNotAvailableException) - { - //as data is not available (was not computed by doseStatistics), it cannot be written - } + //MOCx + sstr << aDoseStatistics->getMOCx(absoluteVolume * 0.02) << columnSeparator; + sstr << aDoseStatistics->getMOCx(absoluteVolume * 0.05) << columnSeparator; + sstr << aDoseStatistics->getMOCx(absoluteVolume * 0.10) << columnSeparator; + + + //MaxOHx + sstr << aDoseStatistics->getMaxOHx(absoluteVolume * 0.02) << columnSeparator; + sstr << aDoseStatistics->getMaxOHx(absoluteVolume * 0.05) << columnSeparator; + sstr << aDoseStatistics->getMaxOHx(absoluteVolume * 0.10) << columnSeparator; + + //MinOCx + sstr << aDoseStatistics->getMinOCx(absoluteVolume * 0.02) << columnSeparator; + sstr << aDoseStatistics->getMinOCx(absoluteVolume * 0.05) << columnSeparator; + sstr << aDoseStatistics->getMinOCx(absoluteVolume * 0.10) << columnSeparator; return sstr.str(); } } } } \ No newline at end of file diff --git a/testing/algorithms/CMakeLists.txt b/testing/algorithms/CMakeLists.txt index 6d4bc45..4a106e5 100644 --- a/testing/algorithms/CMakeLists.txt +++ b/testing/algorithms/CMakeLists.txt @@ -1,22 +1,21 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(ALGORITHMS_TESTS ${EXECUTABLE_OUTPUT_PATH}/rttbAlgorithmsTests) SET(ALGORITHMS_HEADER_TEST ${EXECUTABLE_OUTPUT_PATH}/rttbAlgorithmsHeaderTest) SET(TEST_DATA_ROOT ${RTTBTesting_SOURCE_DIR}/data) SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) #----------------------------------------------------------------------------- ADD_TEST(DoseStatisticsTest ${ALGORITHMS_TESTS} DoseStatisticsTest) -ADD_TEST(DoseStatisticsCalculatorTest ${ALGORITHMS_TESTS} DoseStatisticsCalculatorTest) ADD_TEST(ArithmeticTest ${ALGORITHMS_TESTS} ArithmeticTest) ADD_TEST(BinaryFunctorDoseAccessorTest ${ALGORITHMS_TESTS} BinaryFunctorDoseAccessorTest "${TEST_DATA_ROOT}/DICOM/TestDose/ConstantTwo.dcm" "${TEST_DATA_ROOT}/DICOM/TestDose/dicompylerTestDose.dcm") RTTB_CREATE_TEST_MODULE(rttbAlgorithms DEPENDS RTTBAlgorithms RTTBMasks RTTBDicomIO PACKAGE_DEPENDS Boost Litmus DCMTK) diff --git a/testing/algorithms/DoseStatisticsCalculatorTest.cpp b/testing/algorithms/DoseStatisticsCalculatorTest.cpp deleted file mode 100644 index 507ce7c..0000000 --- a/testing/algorithms/DoseStatisticsCalculatorTest.cpp +++ /dev/null @@ -1,314 +0,0 @@ -// ----------------------------------------------------------------------- -// 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: 707 $ (last changed revision) -// @date $Date: 2014-09-04 16:37:24 +0200 (Do, 04 Sep 2014) $ (last change date) -// @author $Author: floca $ (last changed by) -*/ - -#include -#include - -#include "litCheckMacros.h" - -#include "rttbBaseType.h" -#include "rttbGenericDoseIterator.h" -#include "rttbDoseIteratorInterface.h" -#include "rttbNullPointerException.h" -#include "rttbDoseStatisticsCalculator.h" -#include "rttbInvalidDoseException.h" -#include "rttbInvalidParameterException.h" -#include "rttbDataNotAvailableException.h" - -#include "../core/DummyDoseAccessor.h" - -namespace rttb -{ - namespace testing - { - - typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; - typedef core::DoseIteratorInterface::DoseIteratorPointer DoseIteratorPointer; - typedef rttb::algorithms::DoseStatistics::ResultListPointer ResultListPointer; - typedef rttb::algorithms::DoseStatistics::DoseStatisticsPointer DoseStatisticsPointer; - - /*! @brief DoseStatisticsCalculatorTest - test the API of DoseStatisticsCalculator - 1) test constructors - 2) test setDoseIterator - 3) test calculateDoseSatistics - 4) get statistical values - */ - - int DoseStatisticsCalculatorTest(int argc, char* argv[]) - { - PREPARE_DEFAULT_TEST_REPORTING; - - boost::shared_ptr spTestDoseAccessor = boost::make_shared(); - DoseAccessorPointer spDoseAccessor(spTestDoseAccessor); - const std::vector* doseVals = spTestDoseAccessor->getDoseVector(); - - boost::shared_ptr spTestDoseIterator = - boost::make_shared(spDoseAccessor); - DoseIteratorPointer spDoseIterator(spTestDoseIterator); - - DoseIteratorPointer spDoseIteratorNull; - - //1) test constructors - // the values cannot be accessed from outside, therefore correct default values are not tested - CHECK_NO_THROW(rttb::algorithms::DoseStatisticsCalculator myEmptyDoseStatCalculatur); - rttb::algorithms::DoseStatisticsCalculator myEmptyDoseStatCalculatur; - rttb::algorithms::DoseStatisticsCalculator myDoseStatCalculaturToBeFilled; - - CHECK_THROW_EXPLICIT(rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator(spDoseIteratorNull), - core::NullPointerException); - - CHECK_NO_THROW(rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator(spDoseIterator)); - rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator(spDoseIterator); - - //2) test setDoseIterator - CHECK_THROW_EXPLICIT(myDoseStatCalculaturToBeFilled.setDoseIterator(spDoseIteratorNull), core::NullPointerException); - CHECK_NO_THROW(myDoseStatCalculaturToBeFilled.setDoseIterator(spDoseIterator)); - - //3) test calculateDoseStatistics - DoseStatisticsPointer theStatistics, theStatistics2; - CHECK_THROW_EXPLICIT(myEmptyDoseStatCalculatur.calculateDoseStatistics(), core::NullPointerException); - CHECK_NO_THROW(theStatistics = myDoseStatsCalculator.calculateDoseStatistics()); - CHECK_NO_THROW(theStatistics2 = myDoseStatCalculaturToBeFilled.calculateDoseStatistics()); - CHECK_EQUAL(theStatistics->getMinimumPositions()->empty(), true); - CHECK_EQUAL(theStatistics->getMaximumPositions()->empty(), true); - CHECK_EQUAL(theStatistics->getAllVx().empty(), true); - CHECK_EQUAL(theStatistics->getAllDx().empty(), true); - CHECK_EQUAL(theStatistics->getAllVx().empty(), true); - CHECK_EQUAL(theStatistics->getAllMaxOHx().empty(), true); - CHECK_EQUAL(theStatistics->getAllMOHx().empty(), true); - CHECK_EQUAL(theStatistics->getAllMOCx().empty(), true); - CHECK_EQUAL(theStatistics->getAllMinOCx().empty(), true); - - //check default values for computeComplexMeasures=true - DoseStatisticsPointer theStatisticsDefault; - CHECK_NO_THROW(theStatisticsDefault = myDoseStatsCalculator.calculateDoseStatistics(true)); - CHECK_NO_THROW(theStatisticsDefault->getVx(0.02 * theStatisticsDefault->getMaximum())); - CHECK_NO_THROW(theStatisticsDefault->getVx(0.05 * theStatisticsDefault->getMaximum())); - CHECK_NO_THROW(theStatisticsDefault->getVx(0.1 * theStatisticsDefault->getMaximum())); - CHECK_NO_THROW(theStatisticsDefault->getVx(0.2 * theStatisticsDefault->getMaximum())); - CHECK_NO_THROW(theStatisticsDefault->getVx(0.8 * theStatisticsDefault->getMaximum())); - CHECK_NO_THROW(theStatisticsDefault->getVx(0.9 * theStatisticsDefault->getMaximum())); - CHECK_NO_THROW(theStatisticsDefault->getVx(0.95 * theStatisticsDefault->getMaximum())); - CHECK_NO_THROW(theStatisticsDefault->getVx(0.98 * theStatisticsDefault->getMaximum())); - CHECK_NO_THROW(theStatisticsDefault->getDx(0.02 * theStatisticsDefault->getNumberOfVoxels())); - CHECK_NO_THROW(theStatisticsDefault->getDx(0.05 * theStatisticsDefault->getNumberOfVoxels())); - CHECK_NO_THROW(theStatisticsDefault->getDx(0.1 * theStatisticsDefault->getNumberOfVoxels())); - CHECK_NO_THROW(theStatisticsDefault->getDx(0.2 * theStatisticsDefault->getNumberOfVoxels())); - CHECK_NO_THROW(theStatisticsDefault->getDx(0.8 * theStatisticsDefault->getNumberOfVoxels())); - CHECK_NO_THROW(theStatisticsDefault->getDx(0.9 * theStatisticsDefault->getNumberOfVoxels())); - CHECK_NO_THROW(theStatisticsDefault->getDx(0.95 * theStatisticsDefault->getNumberOfVoxels())); - CHECK_NO_THROW(theStatisticsDefault->getDx(0.98 * theStatisticsDefault->getNumberOfVoxels())); - - //check manually set values for omputeComplexMeasures=true - std::vector precomputeDoseValues, precomputeVolumeValues; - precomputeDoseValues.push_back(0.01 * theStatistics->getMaximum()); - precomputeDoseValues.push_back(0.02 * theStatistics->getMaximum()); - precomputeDoseValues.push_back(0.05 * theStatistics->getMaximum()); - - precomputeVolumeValues.push_back(0.9 * theStatistics->getNumberOfVoxels()); - precomputeVolumeValues.push_back(0.95 * theStatistics->getNumberOfVoxels()); - precomputeVolumeValues.push_back(0.99 * theStatistics->getNumberOfVoxels()); - - CHECK_NO_THROW(theStatistics = myDoseStatsCalculator.calculateDoseStatistics(true, precomputeDoseValues, - precomputeVolumeValues)); - CHECK_NO_THROW(theStatistics->getVx(0.01 * theStatistics->getMaximum())); - CHECK_NO_THROW(theStatistics->getVx(0.02 * theStatistics->getMaximum())); - CHECK_NO_THROW(theStatistics->getVx(0.05 * theStatistics->getMaximum())); - CHECK_THROW_EXPLICIT(theStatistics->getVx(0.03 * theStatistics->getMaximum()), core::DataNotAvailableException); - CHECK_NO_THROW(theStatistics->getDx(0.9 * theStatistics->getNumberOfVoxels())); - CHECK_NO_THROW(theStatistics->getDx(0.95 * theStatistics->getNumberOfVoxels())); - CHECK_NO_THROW(theStatistics->getDx(0.99 * theStatistics->getNumberOfVoxels())); - CHECK_THROW_EXPLICIT(theStatistics->getDx(0.03 * theStatistics->getNumberOfVoxels()), core::DataNotAvailableException); - CHECK_EQUAL(theStatistics->getVx(0.02 * theStatistics->getMaximum()), - theStatisticsDefault->getVx(0.02 * theStatistics->getMaximum())); - CHECK_EQUAL(theStatistics->getVx(0.05 * theStatistics->getMaximum()), - theStatisticsDefault->getVx(0.05 * theStatistics->getMaximum())); - CHECK_EQUAL(theStatistics->getDx(0.9 * theStatistics->getNumberOfVoxels()), - theStatisticsDefault->getDx(0.9 * theStatistics->getNumberOfVoxels())); - CHECK_EQUAL(theStatistics->getDx(0.95 * theStatistics->getNumberOfVoxels()), - theStatisticsDefault->getDx(0.95 * theStatistics->getNumberOfVoxels())); - - //MOHx, MOCx, MaxOHx and MinOCx are computed analogous to Dx, they will not be checked. - - //4) get statistical values - CHECK_EQUAL(theStatistics->getNumberOfVoxels(), doseVals->size()); - CHECK_EQUAL(theStatistics2->getNumberOfVoxels(), doseVals->size()); - - //compute simple statistical values (min, mean, max, stddev) for comparison - DoseStatisticType maximum = 0; - DoseStatisticType minimum = 1000000; - DoseStatisticType mean = 0; - DoseStatisticType variance = 0; - std::vector::const_iterator doseIt = doseVals->begin(); - - while (doseIt != doseVals->end()) - { - if (maximum < *doseIt) - { - maximum = *doseIt; - } - - if (minimum > *doseIt) - { - minimum = *doseIt; - } - - mean += *doseIt; - ++doseIt; - } - - mean /= doseVals->size(); - float compMean = (int(mean * 100)) / 100; - - doseIt = doseVals->begin(); - - while (doseIt != doseVals->end()) - { - variance += pow(*doseIt - mean, 2); - ++doseIt; - } - - variance /= doseVals->size() - 1; - DoseStatisticType stdDev = pow(variance, 0.5); - - CHECK_EQUAL(theStatistics->getMaximum(), maximum); - CHECK_EQUAL(theStatistics2->getMaximum(), maximum); - - CHECK_EQUAL(theStatistics->getMinimum(), minimum); - CHECK_EQUAL(theStatistics2->getMinimum(), minimum); - - CHECK_EQUAL(theStatistics->getMean(), mean); - CHECK_EQUAL(theStatistics2->getMean(), mean); - - CHECK_EQUAL(theStatistics->getStdDeviation(), stdDev); - CHECK_EQUAL(theStatistics2->getStdDeviation(), stdDev); - - CHECK_EQUAL(theStatistics->getVariance(), variance); - CHECK_EQUAL(theStatistics2->getVariance(), variance); - - //check for complex doseStatistics (maximumPositions, minimumPositions, Vx, Dx, MOHx, MOCx, MAXOHx, MinOCx) - - unsigned int nMax = 0, nMin = 0; - - doseIt = doseVals->begin(); - - while (doseIt != doseVals->end()) - { - if (*doseIt == theStatistics->getMaximum()) - { - nMax++; - } - - if (*doseIt == theStatistics->getMinimum()) - { - nMin++; - } - - ++doseIt; - } - - //only 100 positions are stored - if (nMax > 100) - { - nMax = 100; - } - - if (nMin > 100) - { - nMin = 100; - } - - auto maximaPositions = theStatistics->getMaximumPositions(); - auto minimaPositions = theStatistics->getMinimumPositions(); - - CHECK_EQUAL(maximaPositions->size(), nMax); - CHECK_EQUAL(minimaPositions->size(), nMin); - - for (auto maximaPositionsIterator = std::begin(*maximaPositions); maximaPositionsIterator != std::end(*maximaPositions); - ++maximaPositionsIterator) - { - CHECK_EQUAL(maximaPositionsIterator->first, theStatistics->getMaximum()); - } - - for (auto minimaPositionsIterator = std::begin(*minimaPositions); minimaPositionsIterator != std::end(*minimaPositions); - ++minimaPositionsIterator) - { - CHECK_EQUAL(minimaPositionsIterator->first, theStatistics->getMinimum()); - } - - - //generate specific example dose - maximum = 9.5; - minimum = 2.5; - mean = 6; - int sizeTemplate = 500; - std::vector aDoseVector; - - for (int i = 0; i < sizeTemplate; i++) - { - aDoseVector.push_back(maximum); - aDoseVector.push_back(minimum); - } - - core::GeometricInfo geoInfo = spTestDoseAccessor->getGeometricInfo(); - geoInfo.setNumRows(20); - geoInfo.setNumColumns(10); - geoInfo.setNumSlices(5); - - boost::shared_ptr spTestDoseAccessor2 = - boost::make_shared(aDoseVector, geoInfo); - DoseAccessorPointer spDoseAccessor2(spTestDoseAccessor2); - - boost::shared_ptr spTestDoseIterator2 = - boost::make_shared(spDoseAccessor2); - DoseIteratorPointer spDoseIterator2(spTestDoseIterator2); - - rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator2(spDoseIterator2); - DoseStatisticsPointer theStatistics3 = myDoseStatsCalculator2.calculateDoseStatistics(); - - CHECK_EQUAL(theStatistics3->getMaximum(), maximum); - CHECK_EQUAL(theStatistics3->getMinimum(), minimum); - CHECK_EQUAL(theStatistics3->getMean(), mean); - - - maximaPositions = theStatistics3->getMaximumPositions(); - minimaPositions = theStatistics3->getMinimumPositions(); - - CHECK_EQUAL(maximaPositions->empty(), false); - CHECK_EQUAL(minimaPositions->empty(), false); - - for (auto maximaPositionsIterator = std::begin(*maximaPositions); maximaPositionsIterator != std::end(*maximaPositions); - ++maximaPositionsIterator) - { - CHECK_EQUAL(maximaPositionsIterator->first, theStatistics3->getMaximum()); - } - - for (auto minimaPositionsIterator = std::begin(*minimaPositions); minimaPositionsIterator != std::end(*minimaPositions); - ++minimaPositionsIterator) - { - CHECK_EQUAL(minimaPositionsIterator->first, theStatistics3->getMinimum()); - } - - RETURN_AND_REPORT_TEST_SUCCESS; - } - - }//end namespace testing -}//end namespace rttb diff --git a/testing/algorithms/DoseStatisticsTest.cpp b/testing/algorithms/DoseStatisticsTest.cpp index 10bc265..5c6a803 100644 --- a/testing/algorithms/DoseStatisticsTest.cpp +++ b/testing/algorithms/DoseStatisticsTest.cpp @@ -1,218 +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 #include #include "litCheckMacros.h" #include "rttbBaseType.h" +#include "rttbGenericDoseIterator.h" +#include "rttbDoseIteratorInterface.h" +#include "rttbNullPointerException.h" #include "rttbDoseStatistics.h" -#include "rttbDataNotAvailableException.h" +#include "rttbInvalidDoseException.h" -namespace rttb -{ - namespace testing - { +#include "../core/DummyDoseAccessor.h" +namespace rttb{ + namespace testing{ + + typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; + typedef core::DoseIteratorInterface::DoseIteratorPointer DoseIteratorPointer; 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) + 1) test constructors + 2) test setDoseIterator + 3) test getNumberOfVoxels + 4) get statistical values + floating point accuracy requires this otherwise the test 4 fails! */ - int DoseStatisticsTest(int argc, char* argv[]) - { + 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)); - - VolumeToDoseFunctionType Dx; - Dx.insert(std::make_pair(1000, 1.1)); - Dx.insert(std::make_pair(99000, 106.9)); - - VolumeToDoseFunctionType MOHx; - MOHx.insert(std::make_pair(1000, 5)); - MOHx.insert(std::make_pair(99000, 105.5)); - - VolumeToDoseFunctionType MOCx; - MOCx.insert(std::make_pair(1000, 10)); - MOCx.insert(std::make_pair(99000, 99)); - - VolumeToDoseFunctionType MaxOHx; - MaxOHx.insert(std::make_pair(1000, 40)); - MaxOHx.insert(std::make_pair(99000, 98.3)); - - VolumeToDoseFunctionType MinOCx; - MinOCx.insert(std::make_pair(1000, 25.5)); - MinOCx.insert(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.getMaximumPositions()->empty(), true); - CHECK_EQUAL(aDoseStatistic.getMinimumPositions()->empty(), true); - CHECK_EQUAL(aDoseStatistic.getAllDx().empty(), true); - CHECK_EQUAL(aDoseStatistic.getAllVx().empty(), true); - CHECK_EQUAL(aDoseStatistic.getAllMOHx().empty(), true); - CHECK_EQUAL(aDoseStatistic.getAllMOCx().empty(), true); - CHECK_EQUAL(aDoseStatistic.getAllMaxOHx().empty(), true); - CHECK_EQUAL(aDoseStatistic.getAllMinOCx().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.getMaximumPositions(), resultsMaxVoxels); - CHECK_EQUAL(aDoseStatisticComplex.getMinimumPositions(), resultsMinVoxels); - CHECK_EQUAL(aDoseStatisticComplex.getAllDx() == Dx, true); - CHECK_EQUAL(aDoseStatisticComplex.getAllVx() == Vx, true); - CHECK_EQUAL(aDoseStatisticComplex.getAllMOHx() == MOHx, true); - CHECK_EQUAL(aDoseStatisticComplex.getAllMOCx() == MOCx, true); - CHECK_EQUAL(aDoseStatisticComplex.getAllMaxOHx() == MaxOHx, true); - CHECK_EQUAL(aDoseStatisticComplex.getAllMinOCx() == 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.getMaximumPositions(), resultsMaxVoxels); - CHECK_EQUAL(aDoseStatistic.getMinimumPositions(), resultsMinVoxels); - CHECK_EQUAL(aDoseStatistic.getAllDx() == Dx, true); - CHECK_EQUAL(aDoseStatistic.getAllVx() == Vx, true); - CHECK_EQUAL(aDoseStatistic.getAllMOHx() == MOHx, true); - CHECK_EQUAL(aDoseStatistic.getAllMOCx() == MOCx, true); - CHECK_EQUAL(aDoseStatistic.getAllMaxOHx() == MaxOHx, true); - CHECK_EQUAL(aDoseStatistic.getAllMinOCx() == 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.clear(); - Dx.insert(std::make_pair(1000, 1.1)); - Dx.insert(std::make_pair(2000, 2.0)); - Dx.insert(std::make_pair(5000, 10.8)); - Dx.insert(std::make_pair(90000, 89.5)); - Dx.insert(std::make_pair(98000, 104.4)); - Dx.insert(std::make_pair(99000, 106.9)); - - 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(1000)); - CHECK_NO_THROW(aDoseStatisticNewValues.getDx(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(1000), Dx.find(1000)->second); - CHECK_EQUAL(aDoseStatisticNewValues.getDx(98000), Dx.find(98000)->second); - - //test if key-value combination NOT in map - CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getDx(1001), core::DataNotAvailableException); - CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getVx(10), core::DataNotAvailableException); - - double closestDxKey, closestVxKey; - CHECK_NO_THROW(aDoseStatisticNewValues.getDx(900, true, closestDxKey)); - CHECK_NO_THROW(aDoseStatisticNewValues.getDx(99001, true, closestDxKey)); - CHECK_NO_THROW(aDoseStatisticNewValues.getVx(10, true, closestVxKey)); - CHECK_EQUAL(aDoseStatisticNewValues.getDx(900, true, closestDxKey), Dx.find(1000)->second); - CHECK_EQUAL(aDoseStatisticNewValues.getDx(99001, true, closestDxKey), Dx.find(99000)->second); - CHECK_EQUAL(aDoseStatisticNewValues.getVx(10, true, closestVxKey), Vx.find(5.0)->second); - CHECK_EQUAL(closestDxKey, 99000); - CHECK_EQUAL(closestVxKey, 5); - - //equal distance to two values. First value is returned. - CHECK_NO_THROW(aDoseStatisticNewValues.getDx(1500, true, closestDxKey)); - CHECK_NO_THROW(aDoseStatisticNewValues.getVx(98.5, true, closestVxKey)); - CHECK_EQUAL(aDoseStatisticNewValues.getDx(1500, true, closestDxKey), Dx.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(25), core::DataNotAvailableException); - CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMOHx(9999), core::DataNotAvailableException); - CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMinOCx(25, true, dummy), core::DataNotAvailableException); - CHECK_THROW_EXPLICIT(aDoseStatisticNewValues.getMOHx(9999, true, dummy), core::DataNotAvailableException); + boost::shared_ptr spTestDoseAccessor = boost::make_shared(); + DoseAccessorPointer spDoseAccessor(spTestDoseAccessor); + const std::vector* doseVals = spTestDoseAccessor->getDoseVector(); + + boost::shared_ptr spTestDoseIterator = + boost::make_shared(spDoseAccessor); + DoseIteratorPointer spDoseIterator (spTestDoseIterator); + + DoseIteratorPointer spDoseIteratorNull; + + //1) test constructors + // the values cannot be accessed from outside, therefore correct default values are not tested + CHECK_NO_THROW(rttb::algorithms::DoseStatistics myEmptyDoseStat); + rttb::algorithms::DoseStatistics myEmptyDoseStat; + rttb::algorithms::DoseStatistics myDoseStatToBeFilled; + + CHECK_THROW_EXPLICIT(rttb::algorithms::DoseStatistics myDoseStats(spDoseIteratorNull),core::NullPointerException); + + CHECK_NO_THROW(rttb::algorithms::DoseStatistics myDoseStats(spDoseIterator)); + rttb::algorithms::DoseStatistics myDoseStats(spDoseIterator); + + //2) test setDoseIterator + CHECK_THROW_EXPLICIT(myDoseStatToBeFilled.setDoseIterator(spDoseIteratorNull),core::NullPointerException); + CHECK_NO_THROW(myDoseStatToBeFilled.setDoseIterator(spDoseIterator)); + + //3) test getNumberOfVoxels + CHECK_THROW_EXPLICIT(myEmptyDoseStat.getNumberOfVoxels(),core::InvalidDoseException); + CHECK_EQUAL(myDoseStats.getNumberOfVoxels(),doseVals->size()); + CHECK_EQUAL(myDoseStatToBeFilled.getNumberOfVoxels(),doseVals->size()); + + //4) get statistical values + CHECK_THROW_EXPLICIT(myEmptyDoseStat.getNumberOfVoxels(),core::InvalidDoseException); + CHECK_EQUAL(myDoseStats.getNumberOfVoxels(),doseVals->size()); + CHECK_EQUAL(myDoseStatToBeFilled.getNumberOfVoxels(),doseVals->size()); + + //compute values for comparison + DoseStatisticType maximum = 0; + DoseStatisticType minimum = 1000000; + DoseStatisticType mean = 0; + std::vector::const_iterator doseIt = doseVals->begin(); + while(doseIt != doseVals->end()) + { + if (maximum < *doseIt) + { + maximum = *doseIt; + } + if (minimum > *doseIt) + { + minimum = *doseIt; + } + mean += *doseIt; + doseIt++; + } + mean /=doseVals->size(); + float compMean = (int(mean*100))/100; + + boost::shared_ptr< std::vector > > myResultPairs = + boost::make_shared< std::vector > >(); + ResultListPointer spMyResultPairs(myResultPairs); + boost::shared_ptr< std::vector > > myResultPairs2 = + boost::make_shared< std::vector > >(); + ResultListPointer spMyResultPairs2(myResultPairs2); + + CHECK_THROW_EXPLICIT(myEmptyDoseStat.getMaximum(spMyResultPairs),core::InvalidDoseException); + CHECK_EQUAL(myDoseStats.getMaximum(spMyResultPairs),maximum); + CHECK_EQUAL(myDoseStatToBeFilled.getMaximum(spMyResultPairs2),maximum); + CHECK(spMyResultPairs->size()>0); + + CHECK_EQUAL(spMyResultPairs->size(),spMyResultPairs2->size()); + std::vector >::iterator pairIt = spMyResultPairs->begin(); + std::vector >::iterator pairIt2 = spMyResultPairs2->begin(); + + for (;pairIt != spMyResultPairs->end();++pairIt) + { + CHECK_EQUAL(pairIt->first,pairIt2->first); + CHECK_EQUAL(pairIt->second,pairIt2->second); + ++pairIt2; + } + + spMyResultPairs = boost::make_shared< std::vector > >(); + spMyResultPairs2 = boost::make_shared< std::vector > >(); + CHECK_THROW_EXPLICIT(myEmptyDoseStat.getMinimum(spMyResultPairs),core::InvalidDoseException); + CHECK_EQUAL(myDoseStats.getMinimum(spMyResultPairs),minimum); + CHECK_EQUAL(myDoseStatToBeFilled.getMinimum(spMyResultPairs2),minimum); + CHECK(spMyResultPairs->size()>0); + + CHECK_EQUAL(spMyResultPairs->size(),spMyResultPairs2->size()); + pairIt = spMyResultPairs->begin(); + pairIt2 = spMyResultPairs2->begin(); + + for (;pairIt != spMyResultPairs->end();++pairIt) + { + CHECK_EQUAL(pairIt->first,pairIt2->first); + CHECK_EQUAL(pairIt->second,pairIt2->second); + ++pairIt2; + } + + CHECK_THROW_EXPLICIT(myEmptyDoseStat.getMean(),core::InvalidDoseException); + float tmpMean = myDoseStats.getMean(); + tmpMean = (int(tmpMean*100))/100; + CHECK_EQUAL(tmpMean,compMean); + tmpMean = myDoseStatToBeFilled.getMean(); + tmpMean = (int(tmpMean*100))/100; + CHECK_EQUAL(tmpMean,compMean); + + //generate specific example dose + maximum = 9.5; + minimum = 2.5; + mean = 6; + int sizeTemplate = 500; + std::vector aDoseVector; + for (int i = 0; i < sizeTemplate; i++){ + aDoseVector.push_back(maximum); + aDoseVector.push_back(minimum); + } + + core::GeometricInfo geoInfo = spTestDoseAccessor->getGeometricInfo(); + geoInfo.setNumRows(20); + geoInfo.setNumColumns(10); + geoInfo.setNumSlices(5); + + boost::shared_ptr spTestDoseAccessor2 = + boost::make_shared(aDoseVector,geoInfo); + DoseAccessorPointer spDoseAccessor2(spTestDoseAccessor2); + + boost::shared_ptr spTestDoseIterator2 = + boost::make_shared(spDoseAccessor2); + DoseIteratorPointer spDoseIterator2 (spTestDoseIterator2); + + rttb::algorithms::DoseStatistics myDoseStats2(spDoseIterator2); + + spMyResultPairs = boost::make_shared< std::vector > >(); + CHECK_EQUAL(myDoseStats2.getMaximum(spMyResultPairs),maximum); + CHECK(spMyResultPairs->size()>0); + + CHECK_EQUAL(spMyResultPairs->size(),sizeTemplate); + pairIt = spMyResultPairs->begin(); + + for (;pairIt != spMyResultPairs->end();++pairIt) + { + CHECK_EQUAL(pairIt->first,maximum); + } + + spMyResultPairs = boost::make_shared< std::vector > >(); + int maxmialFound = 200; + CHECK_EQUAL(myDoseStats2.getMinimum(spMyResultPairs, maxmialFound),minimum); + CHECK(spMyResultPairs->size()>0); + + CHECK_EQUAL(spMyResultPairs->size(),maxmialFound); + pairIt = spMyResultPairs->begin(); + + for (;pairIt != spMyResultPairs->end();++pairIt) + { + CHECK_EQUAL(pairIt->first,minimum); + } + + CHECK_EQUAL(myDoseStats2.getMean(),mean); RETURN_AND_REPORT_TEST_SUCCESS; - } + } - }//end namespace testing -}//end namespace rttb + }//end namespace testing + }//end namespace rttb diff --git a/testing/algorithms/files.cmake b/testing/algorithms/files.cmake index e056ae8..31ddd28 100644 --- a/testing/algorithms/files.cmake +++ b/testing/algorithms/files.cmake @@ -1,20 +1,19 @@ SET(CPP_FILES DoseStatisticsTest.cpp - DoseStatisticsCalculatorTest.cpp ArithmeticTest.cpp BinaryFunctorDoseAccessorTest.cpp rttbAlgorithmsTests.cpp #include dummy accessor files ../core/DummyDoseAccessor.cpp ../core/DummyMaskAccessor.cpp ../core/DummyMutableDoseAccessor.cpp ) SET(H_FILES #include dummy accessor files ../core/DummyDoseAccessor.h ../core/DummyMaskAccessor.h ../core/DummyMutableDoseAccessor.h ) diff --git a/testing/algorithms/rttbAlgorithmsTests.cpp b/testing/algorithms/rttbAlgorithmsTests.cpp index 69263f6..e03c3e9 100644 --- a/testing/algorithms/rttbAlgorithmsTests.cpp +++ b/testing/algorithms/rttbAlgorithmsTests.cpp @@ -1,66 +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) */ // this file defines the rttbAlgorithmsTests 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(DoseStatisticsTest); - LIT_REGISTER_TEST(DoseStatisticsCalculatorTest); LIT_REGISTER_TEST(ArithmeticTest); LIT_REGISTER_TEST(BinaryFunctorDoseAccessorTest); } } } int main(int argc, char* argv[]) { int result = 0; rttb::testing::registerTests(); try { result = lit::multiTestsMain(argc, argv); } catch (const std::exception& /*e*/) { result = -1; } catch (...) { result = -1; } return result; } diff --git a/testing/io/other/DoseStatisticsIOTest.cpp b/testing/io/other/DoseStatisticsIOTest.cpp index c76beb0..4fe32e1 100644 --- a/testing/io/other/DoseStatisticsIOTest.cpp +++ b/testing/io/other/DoseStatisticsIOTest.cpp @@ -1,106 +1,98 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html [^] // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ // this file defines the rttbCoreTests for the test driver // and all it expects is that you have a function called RegisterTests #include #include #include #include "litCheckMacros.h" #include "rttbBaseType.h" -#include "rttbDoseStatisticsCalculator.h" +#include "rttbDoseStatistics.h" #include "rttbDoseStatisticsXMLWriter.h" #include "rttbGenericDoseIterator.h" #include "rttbDoseIteratorInterface.h" #include "rttbInvalidParameterException.h" #include "rttbNullPointerException.h" #include "../../core/DummyDoseAccessor.h" namespace rttb { namespace testing { /*! @brief OtherIOTest - test the IO for dose statistics 1) test exception - 2) test writing statistics to xml file + 2) test writing statistcs to xml file */ int DoseStatisticsIOTest(int argc, char* argv[]) { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef core::DoseIteratorInterface::DoseIteratorPointer DoseIteratorPointer; - typedef boost::shared_ptr DoseStatisticsCalculatorPtr; + typedef boost::shared_ptr DoseStatisticsPtr; PREPARE_DEFAULT_TEST_REPORTING; /* generate dummy dose */ boost::shared_ptr spTestDoseAccessor = boost::make_shared(); DoseAccessorPointer spDoseAccessor(spTestDoseAccessor); boost::shared_ptr spTestDoseIterator = boost::make_shared(spDoseAccessor); DoseIteratorPointer spDoseIterator(spTestDoseIterator); - rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator(spDoseIterator); - auto myDoseStatsSimple = myDoseStatsCalculator.calculateDoseStatistics(); - auto myDoseStatsComplex = myDoseStatsCalculator.calculateDoseStatistics(true); + rttb::algorithms::DoseStatistics myDoseStats(spDoseIterator); + DoseStatisticsPtr myDoseStatsPtr = boost::make_shared + (myDoseStats); /* test exception */ - CHECK_THROW_EXPLICIT(io::other::writeDoseStatistics(myDoseStatsSimple, "test.test", 0), + CHECK_THROW_EXPLICIT(io::other::writeDoseStatistics(myDoseStatsPtr, "test.test", 0), core::InvalidParameterException); - /* test writing statistics to xml file */ - FileNameString filenameSimple = "testStatisticsSimple.xml"; - CHECK_NO_THROW(io::other::writeDoseStatistics(myDoseStatsSimple, filenameSimple)); + /* test writing statistcs to xml file */ + FileNameString fN = "testStatistics.xml"; + CHECK_NO_THROW(io::other::writeDoseStatistics(myDoseStatsPtr, fN)); - FileNameString filenameComplex = "testStatisticsComplex.xml"; - CHECK_NO_THROW(io::other::writeDoseStatistics(myDoseStatsComplex, filenameComplex)); + /* test writing statistcs to string */ + boost::property_tree::ptree pt = io::other::writeDoseStatistics(myDoseStatsPtr); + XMLString str = io::other::writerDoseStatisticsToString(myDoseStatsPtr); - /* test writing statistics to string */ - boost::property_tree::ptree ptSimple = io::other::writeDoseStatistics(myDoseStatsSimple); - XMLString strSimple = io::other::writerDoseStatisticsToString(myDoseStatsSimple); + std::stringstream sstr; + boost::property_tree::xml_parser::write_xml(sstr, pt); + CHECK_EQUAL(str, sstr.str()); - boost::property_tree::ptree ptComplex = io::other::writeDoseStatistics(myDoseStatsComplex); - XMLString strComplex = io::other::writerDoseStatisticsToString(myDoseStatsComplex); - std::stringstream sstrSimple; - boost::property_tree::xml_parser::write_xml(sstrSimple, ptSimple); - CHECK_EQUAL(strSimple, sstrSimple.str()); - - std::stringstream sstrComplex; - boost::property_tree::xml_parser::write_xml(sstrComplex, ptComplex); - CHECK_EQUAL(strComplex, sstrComplex.str()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb