diff --git a/Modules/ImageStatistics/mitkImageStatisticsContainer.cpp b/Modules/ImageStatistics/mitkImageStatisticsContainer.cpp index 60d1b840cf..b4fa7f678f 100644 --- a/Modules/ImageStatistics/mitkImageStatisticsContainer.cpp +++ b/Modules/ImageStatistics/mitkImageStatisticsContainer.cpp @@ -1,158 +1,97 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include + namespace mitk { StatisticsContainer::StatisticsContainer() { this->Reset(); } - StatisticsContainer::StatisticsObject::StatisticsObject() { - this->Reset(); - } - - StatisticsContainer::RealType StatisticsContainer::StatisticsObject::GetVariance() const { - return m_Std * m_Std; - } - - StatisticsContainer::statisticsOrderedVectorType StatisticsContainer::StatisticsObject::GetStatisticsAsOrderedVector() const { - statisticsOrderedVectorType statisticsAsVector; - statisticsAsVector.emplace_back(std::make_pair("Mean", std::to_string(m_Mean))); - statisticsAsVector.emplace_back(std::make_pair("Median", std::to_string(m_Median))); - statisticsAsVector.emplace_back(std::make_pair("StandardDeviation", std::to_string(m_Std))); - statisticsAsVector.emplace_back(std::make_pair("RMS", std::to_string(m_RMS))); - statisticsAsVector.emplace_back(std::make_pair("Max", std::to_string(m_Max))); - statisticsAsVector.emplace_back(std::make_pair("MaxPosition", ConvertToString(m_MaxIndex))); - statisticsAsVector.emplace_back(std::make_pair("Min", std::to_string(m_Min))); - statisticsAsVector.emplace_back(std::make_pair("MinPosition", ConvertToString(m_MinIndex))); - statisticsAsVector.emplace_back(std::make_pair("#Voxel", std::to_string(m_N))); - statisticsAsVector.emplace_back(std::make_pair("Volume [mm^3]", std::to_string(m_Volume))); - statisticsAsVector.emplace_back(std::make_pair("Skewness", std::to_string(m_Skewness))); - statisticsAsVector.emplace_back(std::make_pair("Kurtosis", std::to_string(m_Kurtosis))); - statisticsAsVector.emplace_back(std::make_pair("Uniformity", std::to_string(m_Uniformity))); - statisticsAsVector.emplace_back(std::make_pair("Entropy", std::to_string(m_Entropy))); - statisticsAsVector.emplace_back(std::make_pair("MPP", std::to_string(m_MPP))); - statisticsAsVector.emplace_back(std::make_pair("UPP", std::to_string(m_UPP))); - return statisticsAsVector; - } - - std::string StatisticsContainer::StatisticsObject::ConvertToString(const vnl_vector& index) const { - std::string result; - for (const auto& aValue : index) { - if (!result.empty()) { - result += "/"; - } - result += std::to_string(aValue); - } - return result; - } - - void StatisticsContainer::StatisticsObject::Reset() { - m_N = 0; - m_Volume = nan(""); - m_Mean = nan(""); - m_Min = nan(""); - m_Max = nan(""); - m_Std = nan(""); - m_Skewness = nan(""); - m_Kurtosis = nan(""); - m_RMS = nan(""); - m_MPP = nan(""); - m_Median = nan(""); - m_Uniformity = nan(""); - m_UPP = nan(""); - m_Entropy = nan(""); - - m_MinIndex.set_size(0); - m_MaxIndex.set_size(0); - m_Label = 0; - m_Histogram = HistogramType::New(); + void StatisticsContainer::StatisticsObject::AddStatistic(const std::string& key, StatisticsVariantType value) + { + statistics.emplace(key, value); } bool StatisticsContainer::TimeStepExists(TimeStepType timeStep) const { return m_TimeStepMap.find(timeStep) != m_TimeStepMap.end(); } StatisticsContainer::StatisticsObject StatisticsContainer::GetStatisticsForTimeStep(TimeStepType timeStep) const { auto it = m_TimeStepMap.find(timeStep); if (it != m_TimeStepMap.end()) { return it->second; } mitkThrow() << "StatisticsObject for timeStep " << timeStep << " not found!"; } void StatisticsContainer::SetStatisticsForTimeStep(TimeStepType timeStep, StatisticsObject statistics) { if (timeStep < this->GetTimeSteps()) { - m_TimeStepMap[timeStep] = statistics; + m_TimeStepMap.emplace(timeStep, statistics); } else { mitkThrow() << "Given timeStep " << timeStep << " out of timeStep geometry bounds. TimeSteps in geometry: " << this->GetTimeSteps(); } } void StatisticsContainer::PrintSelf(std::ostream &os, itk::Indent indent) const { Superclass::PrintSelf(os, indent); - + auto statisticKeys = StatisticsContainer::StatisticsObject::GetAllStatisticNames(); for (unsigned int i = 0; i < this->GetTimeSteps(); i++) { - auto statistics = GetStatisticsAsOrderedVector(i); + auto statisticsValues = GetStatisticsForTimeStep(i); os << std::endl << indent << "Statistics instance for timeStep " << i << ":"; - for (const auto& aStatisticValue : statistics) { - os << std::endl << indent.GetNextIndent() << aStatisticValue.first << ": " << aStatisticValue.second; + for (const auto& aKey : statisticKeys) { + os << std::endl << indent.GetNextIndent() << aKey << ": " << statisticsValues.GetValueNonConverted(aKey); } } } - StatisticsContainer::statisticsOrderedVectorType StatisticsContainer::GetStatisticsAsOrderedVector(TimeStepType timeStep) const - { - return GetStatisticsForTimeStep(timeStep).GetStatisticsAsOrderedVector(); - } - unsigned int StatisticsContainer::GetNumberOfTimeSteps()const { return this->GetTimeSteps(); } void StatisticsContainer::Reset() { for (auto iter = m_TimeStepMap.begin(); iter != m_TimeStepMap.end(); iter++) { iter->second.Reset(); } } itk::LightObject::Pointer StatisticsContainer::InternalClone() const { itk::LightObject::Pointer ioPtr = Superclass::InternalClone(); Self::Pointer rval = dynamic_cast(ioPtr.GetPointer()); if (rval.IsNull()) { itkExceptionMacro(<< "downcast to type " << "StatisticsContainer" << " failed."); } rval->SetTimeStepMap(m_TimeStepMap); rval->SetTimeGeometry(this->GetTimeGeometry()->Clone()); return ioPtr; } void StatisticsContainer::SetTimeStepMap(TimeStepMapType map) { m_TimeStepMap = map; } } diff --git a/Modules/ImageStatistics/mitkImageStatisticsContainer.h b/Modules/ImageStatistics/mitkImageStatisticsContainer.h index a282a2147d..ca2886117d 100644 --- a/Modules/ImageStatistics/mitkImageStatisticsContainer.h +++ b/Modules/ImageStatistics/mitkImageStatisticsContainer.h @@ -1,133 +1,183 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKIMAGESTATISTICSCONTAINER #define MITKIMAGESTATISTICSCONTAINER #include #include #include +#include + +#include namespace mitk { /**Documentation - @brief Container class for storing the computed image statistics. + @brief Container class for storing a StatisticsObject for each timestep. Stored statistics are: - - N: number of voxels - - Mean - - MPP (Mean of positive pixels) - - Median - - Skewness - - Kurtosis - - Uniformity - - UPP (Uniformity of positive pixels) - - Std (Standard Deviation) - - Min - - Max - - RMS (Root Mean Square) + - for the defined statistics, see GetAllStatisticNames - Label (if applicable, the label (unsigned short) of the mask the statistics belong to) - - Entropy - - MinIndex (Index of Image where the Minimum is located) - - MaxIndex (Index of Image where the Maximum is located) - Histogram of Pixel Values*/ class MITKIMAGESTATISTICS_EXPORT StatisticsContainer : public mitk::BaseData { public: mitkClassMacro(StatisticsContainer, mitk::BaseData) - itkFactorylessNewMacro(Self) - itkCloneMacro(Self) + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) using HistogramType = itk::Statistics::Histogram; using RealType = double; - using statisticsOrderedVectorType = std::vector < std::pair >; using LabelIndex = unsigned int; + using IndexType = vnl_vector; + using VoxelCountType = unsigned long; + using StatisticsVariantType = boost::variant; + using StatisticsMapType = std::map < std::string, StatisticsVariantType>; + using StatisticsKeyType = std::string; virtual void SetRequestedRegionToLargestPossibleRegion() override {}; virtual bool RequestedRegionIsOutsideOfTheBufferedRegion() override { return false; }; virtual bool VerifyRequestedRegion() override { return true; }; virtual void SetRequestedRegion(const itk::DataObject*) override {}; - struct StatisticsObject { - - StatisticsObject(); - RealType GetVariance() const; - statisticsOrderedVectorType GetStatisticsAsOrderedVector() const; - std::string ConvertToString(const vnl_vector& index) const; - void Reset(); - - long m_N; - RealType m_Volume; - RealType m_Mean, m_Min, m_Max, m_Std; - RealType m_Skewness; - RealType m_Kurtosis; - RealType m_RMS; - RealType m_MPP; - vnl_vector m_MinIndex, m_MaxIndex; - RealType m_Median; - RealType m_Uniformity; - RealType m_UPP; - RealType m_Entropy; + /**Documentation + @brief Container class for storing the computed image statistics. + @details The statistics are stored in a map with value as boost::variant. + The type used to create the boost::variant is important as only this type can be recovered lateron. + */ + class StatisticsObject { + public: + StatisticsObject() { + Reset(); + } + /**Documentation + @brief Adds a statistic to the statistics object + @details if already a statistic with that name is included, it is overwritten + */ + void AddStatistic(const std::string& key, StatisticsVariantType value); + + /**Documentation + @brief Returns the names of all statistics + @details The order is derived from the image statistics plugin + */ + static std::vector GetAllStatisticNames() { + std::vector statisticKeys = { + ImageStatisticsConstants::MEAN(), + ImageStatisticsConstants::MEDIAN(), + ImageStatisticsConstants::STANDARDDEVIATION(), + ImageStatisticsConstants::RMS(), + ImageStatisticsConstants::MAXIMUM(), + ImageStatisticsConstants::MAXIMUMPOSITION(), + ImageStatisticsConstants::MINIMUM(), + ImageStatisticsConstants::MINIMUMPOSITION(), + ImageStatisticsConstants::NUMBEROFVOXELS(), + ImageStatisticsConstants::VOLUME(), + ImageStatisticsConstants::SKEWNESS(), + ImageStatisticsConstants::KURTOSIS(), + ImageStatisticsConstants::UNIFORMITY(), + ImageStatisticsConstants::ENTROPY(), + ImageStatisticsConstants::MPP(), + ImageStatisticsConstants::UPP() }; + return statisticKeys; }; + + bool HasStatistic(const std::string& name) const { + auto valueIterator = statistics.find(name); + if (valueIterator != statistics.end()) { + return true; + } + else { + return false; + } + } + + /**Documentation + @brief Converts the requested value to the defined type + @param name defined string on creation (AddStatistic) + @exception if no statistics with key name was found. + */ + template + TType GetValueConverted(const std::string& name) const + { + auto value = GetValueNonConverted(name); + return boost::get(value); + }; + + /**Documentation + @brief Returns the requested value + @exception if no statistics with key name was found. + */ + StatisticsVariantType GetValueNonConverted(const std::string& name) const { + if (HasStatistic(name)) { + return statistics.find(name)->second; + } + else { + mitkThrow() << "invalid statistic key, could not find"; + } + } + + void Reset() { + statistics.clear(); + }; + LabelIndex m_Label; - HistogramType::Pointer m_Histogram; + HistogramType::ConstPointer m_Histogram=nullptr; + private: + StatisticsMapType statistics; }; typedef std::map TimeStepMapType; - /**Documentation - @brief Returns a std::vector