diff --git a/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFFirstOrderNumericStatistics.cpp b/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFFirstOrderNumericStatistics.cpp index 57e8c57113..661da77654 100644 --- a/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFFirstOrderNumericStatistics.cpp +++ b/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFFirstOrderNumericStatistics.cpp @@ -1,358 +1,358 @@ /*=================================================================== 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 // MITK #include #include #include // ITK #include #include #include // STL #include struct FirstOrderNumericParameterStruct { mitk::IntensityQuantifier::Pointer quantifier; double MinimumIntensity; double MaximumIntensity; int Bins; std::string prefix; }; template void CalculateFirstOrderStatistics(itk::Image* itkImage, mitk::Image::Pointer mask, mitk::GIFFirstOrderNumericStatistics::FeatureListType & featureList, FirstOrderNumericParameterStruct params) { typedef itk::Image ImageType; typedef itk::Image MaskType; typename MaskType::Pointer maskImage = MaskType::New(); mitk::CastToItkImage(mask, maskImage); // // Calculate the Volume of Voxel (Maximum to the 3th order) // double voxelVolume = 1; for (unsigned int i = 0; i < std::min(3, VImageDimension); ++i) voxelVolume *= itkImage->GetSpacing()[i]; // // Calculate the Hypervolume of Voxel // double voxelSpace = 1; for (unsigned int i = 0; i < VImageDimension; ++i) voxelSpace *= itkImage->GetSpacing()[i]; unsigned int numberOfBins = params.quantifier->GetBins(); std::vector histogram; histogram.resize(numberOfBins, 0); double minimum = std::numeric_limits::max(); double maximum = std::numeric_limits::lowest(); double absoluteMinimum = std::numeric_limits::max(); double absoluteMaximum = std::numeric_limits::lowest(); double sum = 0; double sumTwo= 0; double sumThree = 0; unsigned int numberOfVoxels = 0; itk::ImageRegionIterator imageIter(itkImage, itkImage->GetLargestPossibleRegion()); itk::ImageRegionIterator maskIter(maskImage, maskImage->GetLargestPossibleRegion()); while (!imageIter.IsAtEnd()) { double value = imageIter.Get(); absoluteMinimum = std::min(minimum, value); absoluteMaximum = std::max(maximum, value); if (maskIter.Get() > 0) { minimum = std::min(minimum, value); maximum = std::max(maximum, value); sum += value; sumTwo += value * value; sumThree += value * value*value; histogram[params.quantifier->IntensityToIndex(value)] += 1; ++numberOfVoxels; } ++maskIter; ++imageIter; } // // Histogram based calculations // unsigned int passedValues = 0; double doubleNoOfVoxes = numberOfVoxels; double median = 0; double lastIntensityWithValues = params.quantifier->IndexToMeanIntensity(0); std::size_t modeIdx = 0; double modeValue = 0; double entropy = 0; double uniformity = 0; std::vector percentiles; percentiles.resize(20, 0); for (std::size_t idx = 0; idx < histogram.size(); ++idx) { unsigned int actualValues = histogram[idx]; for (std::size_t percentileIdx = 0; percentileIdx < percentiles.size(); ++percentileIdx) { double threshold = doubleNoOfVoxes * (percentileIdx + 1) *1.0 / (percentiles.size()); if ((passedValues < threshold) & ((passedValues + actualValues) >= threshold)) { // Lower Bound if (passedValues == std::floor(threshold)) { percentiles[percentileIdx] = 0.5*(lastIntensityWithValues + params.quantifier->IndexToMeanIntensity(idx)); } else { percentiles[percentileIdx] = params.quantifier->IndexToMeanIntensity(idx); } } } if ((passedValues < doubleNoOfVoxes * 0.5) & ((passedValues + actualValues) >= doubleNoOfVoxes * 0.5)) { // Lower Bound if (passedValues == std::floor(doubleNoOfVoxes * 0.5)) { median = 0.5*(lastIntensityWithValues + params.quantifier->IndexToMeanIntensity(idx)); } else { median = params.quantifier->IndexToMeanIntensity(idx); } } if (actualValues > histogram[modeIdx]) { modeIdx = idx; } if (actualValues > 0) { lastIntensityWithValues = params.quantifier->IndexToMeanIntensity(idx); double currentProbability = actualValues / (1.0 *numberOfVoxels); uniformity += currentProbability * currentProbability; entropy += currentProbability * std::log(currentProbability) / std::log(2); } passedValues += actualValues; } double p10 = percentiles[1]; double p25idx = params.quantifier->IntensityToIndex(percentiles[4]); double p75idx = params.quantifier->IntensityToIndex(percentiles[14]); double p90 = percentiles[17]; double mean = sum / (numberOfVoxels); double variance = sumTwo / (numberOfVoxels) - (mean*mean); double energy = sumTwo; double rootMeanSquare = std::sqrt(sumTwo / numberOfVoxels); double sumAbsoluteDistanceToMean = 0; double sumAbsoluteDistanceToMedian = 0; double sumRobust = 0; double sumRobustSquare = 0; double sumRobustAbsolulteDistanceToMean = 0; double sumValueMinusMean = 0; double sumValueMinusMeanThree = 0; double sumValueMinusMeanFour = 0; unsigned int numberOfRobustVoxel = 0; maskIter.GoToBegin(); imageIter.GoToBegin(); while (!imageIter.IsAtEnd()) { if (maskIter.Get() > 0) { double value = imageIter.Get(); double valueMinusMean = value - mean; sumAbsoluteDistanceToMean += std::abs(valueMinusMean); sumAbsoluteDistanceToMedian += std::abs(value - median); sumValueMinusMean += valueMinusMean; sumValueMinusMeanThree += valueMinusMean * valueMinusMean * valueMinusMean; sumValueMinusMeanFour += valueMinusMean * valueMinusMean * valueMinusMean * valueMinusMean; if ((p10 <= value) & (value <= p90)) { sumRobust += value; sumRobustSquare += value * value; ++numberOfRobustVoxel; } } ++maskIter; ++imageIter; } double robustMean = sumRobust / numberOfRobustVoxel; double robustVariance = sumRobustSquare / numberOfRobustVoxel - (robustMean * robustMean); maskIter.GoToBegin(); imageIter.GoToBegin(); while (!imageIter.IsAtEnd()) { if (maskIter.Get() > 0) { double value = imageIter.Get(); if ((p10 <= value) & (value <= p90)) { sumRobustAbsolulteDistanceToMean += std::abs(value - robustMean); } } ++maskIter; ++imageIter; } double meanAbsoluteDeviation = sumAbsoluteDistanceToMean / numberOfVoxels; double medianAbsoluteDeviation = sumAbsoluteDistanceToMedian / numberOfVoxels; double robustMeanAbsoluteDeviation = sumRobustAbsolulteDistanceToMean / numberOfRobustVoxel; double skewness = sumValueMinusMeanThree / numberOfVoxels / variance / std::sqrt(variance); double kurtosis = sumValueMinusMeanFour / numberOfVoxels / variance / variance; double interquantileRange = p75idx - p25idx; double coefficientOfVariation = std::sqrt(variance) / mean; double quantileCoefficientOfDispersion = (p75idx - p25idx) / (p75idx + p25idx + 2); - double coveredImageRange = (absoluteMaximum - absoluteMinimum) / (maximum - minimum); + double coveredImageRange = (maximum - minimum)/ (absoluteMaximum - absoluteMinimum) ; featureList.push_back(std::make_pair(params.prefix + "Mean", mean)); featureList.push_back(std::make_pair(params.prefix + "Variance", variance)); featureList.push_back(std::make_pair(params.prefix + "Skewness", skewness)); featureList.push_back(std::make_pair(params.prefix + "Excess kurtosis", kurtosis-3)); featureList.push_back(std::make_pair(params.prefix + "Median", median)); featureList.push_back(std::make_pair(params.prefix + "Minimum", minimum)); featureList.push_back(std::make_pair(params.prefix + "05th Percentile", percentiles[0])); featureList.push_back(std::make_pair(params.prefix + "10th Percentile", percentiles[1])); featureList.push_back(std::make_pair(params.prefix + "15th Percentile", percentiles[2])); featureList.push_back(std::make_pair(params.prefix + "20th Percentile", percentiles[3])); featureList.push_back(std::make_pair(params.prefix + "25th Percentile", percentiles[4])); featureList.push_back(std::make_pair(params.prefix + "30th Percentile", percentiles[5])); featureList.push_back(std::make_pair(params.prefix + "35th Percentile", percentiles[6])); featureList.push_back(std::make_pair(params.prefix + "40th Percentile", percentiles[7])); featureList.push_back(std::make_pair(params.prefix + "45th Percentile", percentiles[8])); featureList.push_back(std::make_pair(params.prefix + "50th Percentile", percentiles[9])); featureList.push_back(std::make_pair(params.prefix + "55th Percentile", percentiles[10])); featureList.push_back(std::make_pair(params.prefix + "60th Percentile", percentiles[11])); featureList.push_back(std::make_pair(params.prefix + "65th Percentile", percentiles[12])); featureList.push_back(std::make_pair(params.prefix + "70th Percentile", percentiles[13])); featureList.push_back(std::make_pair(params.prefix + "75th Percentile", percentiles[14])); featureList.push_back(std::make_pair(params.prefix + "80th Percentile", percentiles[15])); featureList.push_back(std::make_pair(params.prefix + "85th Percentile", percentiles[16])); featureList.push_back(std::make_pair(params.prefix + "90th Percentile", percentiles[17])); featureList.push_back(std::make_pair(params.prefix + "95th Percentile", percentiles[18])); featureList.push_back(std::make_pair(params.prefix + "Maximum", maximum)); featureList.push_back(std::make_pair(params.prefix + "Interquantile range", interquantileRange)); featureList.push_back(std::make_pair(params.prefix + "Range", maximum-minimum)); featureList.push_back(std::make_pair(params.prefix + "Mean absolute deviation", meanAbsoluteDeviation)); featureList.push_back(std::make_pair(params.prefix + "Robust mean absolute deviation", robustMeanAbsoluteDeviation)); featureList.push_back(std::make_pair(params.prefix + "Median absolute deviation", medianAbsoluteDeviation)); featureList.push_back(std::make_pair(params.prefix + "Coefficient of variation", coefficientOfVariation)); featureList.push_back(std::make_pair(params.prefix + "Quantile coefficient of dispersion", quantileCoefficientOfDispersion)); featureList.push_back(std::make_pair(params.prefix + "Energy", energy)); featureList.push_back(std::make_pair(params.prefix + "Root mean square", rootMeanSquare)); featureList.push_back(std::make_pair(params.prefix + "Standard Deviation", std::sqrt(variance))); featureList.push_back(std::make_pair(params.prefix + "Kurtosis", kurtosis)); featureList.push_back(std::make_pair(params.prefix + "Robust mean", robustMean)); featureList.push_back(std::make_pair(params.prefix + "Robust variance", robustVariance)); featureList.push_back(std::make_pair(params.prefix + "Covered image intensity range", coveredImageRange)); featureList.push_back(std::make_pair(params.prefix + "Mode index", modeIdx)); featureList.push_back(std::make_pair(params.prefix + "Mode value", params.quantifier->IndexToMeanIntensity(modeIdx))); featureList.push_back(std::make_pair(params.prefix + "Mode probability", histogram[modeIdx] / (1.0*numberOfVoxels))); featureList.push_back(std::make_pair(params.prefix + "Entropy", entropy)); featureList.push_back(std::make_pair(params.prefix + "Uniformtiy", uniformity)); featureList.push_back(std::make_pair(params.prefix + "Number of voxels", numberOfVoxels)); featureList.push_back(std::make_pair(params.prefix + "Sum of voxels", sum)); featureList.push_back(std::make_pair(params.prefix + "Voxel space", voxelSpace)); featureList.push_back(std::make_pair(params.prefix + "Voxel volume", voxelVolume)); featureList.push_back(std::make_pair(params.prefix + "Image Dimension", VImageDimension)); return; } mitk::GIFFirstOrderNumericStatistics::GIFFirstOrderNumericStatistics() { SetShortName("fon"); SetLongName("first-order-numeric"); SetFeatureClassName("First Order Numeric"); } mitk::GIFFirstOrderNumericStatistics::FeatureListType mitk::GIFFirstOrderNumericStatistics::CalculateFeatures(const Image::Pointer & image, const Image::Pointer &mask) { InitializeQuantifier(image, mask); FeatureListType featureList; FirstOrderNumericParameterStruct params; params.quantifier = GetQuantifier(); params.MinimumIntensity = GetQuantifier()->GetMinimum(); params.MaximumIntensity = GetQuantifier()->GetMaximum(); params.Bins = GetQuantifier()->GetBins(); params.prefix = FeatureDescriptionPrefix(); AccessByItk_3(image, CalculateFirstOrderStatistics, mask, featureList, params); return featureList; } mitk::GIFFirstOrderNumericStatistics::FeatureNameListType mitk::GIFFirstOrderNumericStatistics::GetFeatureNames() { FeatureNameListType featureList; return featureList; } void mitk::GIFFirstOrderNumericStatistics::AddArguments(mitkCommandLineParser &parser) { std::string name = GetOptionPrefix(); parser.addArgument(GetLongName(), name, mitkCommandLineParser::Bool, "Use First Order Statistic (Numeric)", "calculates First Order Statistic (Numeric)", us::Any()); AddQuantifierArguments(parser); } void mitk::GIFFirstOrderNumericStatistics::CalculateFeaturesUsingParameters(const Image::Pointer & feature, const Image::Pointer &, const Image::Pointer &maskNoNAN, FeatureListType &featureList) { auto parsedArgs = GetParameter(); if (parsedArgs.count(GetLongName())) { InitializeQuantifierFromParameters(feature, maskNoNAN); MITK_INFO << "Start calculating first order features ...."; auto localResults = this->CalculateFeatures(feature, maskNoNAN); featureList.insert(featureList.end(), localResults.begin(), localResults.end()); MITK_INFO << "Finished calculating first order features...."; } } std::string mitk::GIFFirstOrderNumericStatistics::GetCurrentFeatureEncoding() { return QuantifierParameterString(); } \ No newline at end of file diff --git a/Modules/Classification/CLUtilities/test/mitkGIFFirstOrderNumericStatisticsTest.cpp b/Modules/Classification/CLUtilities/test/mitkGIFFirstOrderNumericStatisticsTest.cpp index c392384b01..31bac39039 100644 --- a/Modules/Classification/CLUtilities/test/mitkGIFFirstOrderNumericStatisticsTest.cpp +++ b/Modules/Classification/CLUtilities/test/mitkGIFFirstOrderNumericStatisticsTest.cpp @@ -1,113 +1,113 @@ /*=================================================================== 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 #include #include "mitkIOUtil.h" #include #include class mitkGIFFirstOrderNumericStatisticsTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkGIFFirstOrderNumericStatisticsTestSuite); MITK_TEST(ImageDescription_PhantomTest); CPPUNIT_TEST_SUITE_END(); private: mitk::Image::Pointer m_IBSI_Phantom_Image_Small; mitk::Image::Pointer m_IBSI_Phantom_Image_Large; mitk::Image::Pointer m_IBSI_Phantom_Mask_Small; mitk::Image::Pointer m_IBSI_Phantom_Mask_Large; public: void setUp(void) override { m_IBSI_Phantom_Image_Small = mitk::IOUtil::Load(GetTestDataFilePath("Radiomics/IBSI_Phantom_Image_Small.nrrd")); m_IBSI_Phantom_Image_Large = mitk::IOUtil::Load(GetTestDataFilePath("Radiomics/IBSI_Phantom_Image_Large.nrrd")); m_IBSI_Phantom_Mask_Small = mitk::IOUtil::Load(GetTestDataFilePath("Radiomics/IBSI_Phantom_Mask_Small.nrrd")); m_IBSI_Phantom_Mask_Large = mitk::IOUtil::Load(GetTestDataFilePath("Radiomics/IBSI_Phantom_Mask_Large.nrrd")); } void ImageDescription_PhantomTest() { mitk::GIFFirstOrderNumericStatistics::Pointer featureCalculator = mitk::GIFFirstOrderNumericStatistics::New(); featureCalculator->SetUseBinsize(true); featureCalculator->SetBinsize(1.0); featureCalculator->SetUseMinimumIntensity(true); featureCalculator->SetUseMaximumIntensity(true); featureCalculator->SetMinimumIntensity(0.5); featureCalculator->SetMaximumIntensity(6.5); auto featureList = featureCalculator->CalculateFeatures(m_IBSI_Phantom_Image_Large, m_IBSI_Phantom_Mask_Large); std::map results; for (auto valuePair : featureList) { MITK_INFO << valuePair.first << " : " << valuePair.second; results[valuePair.first] = valuePair.second; } CPPUNIT_ASSERT_EQUAL_MESSAGE("Image Diagnostics should calculate 50 features.", std::size_t(50), featureList.size()); // These values are obtained by a run of the filter. // The might be wrong! CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Mean with Large IBSI Phantom Image", 2.15, results["First Order Numeric::Mean"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Variance with Large IBSI Phantom Image", 3.05, results["First Order Numeric::Variance"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Skewness with Large IBSI Phantom Image", 1.08, results["First Order Numeric::Skewness"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Excess kurtosis with Large IBSI Phantom Image", -0.355, results["First Order Numeric::Excess kurtosis"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Median with Large IBSI Phantom Image", 1, results["First Order Numeric::Median"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Minimum with Large IBSI Phantom Image", 1, results["First Order Numeric::Minimum"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::10th Percentile with Large IBSI Phantom Image", 1, results["First Order Numeric::10th Percentile"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::90th Percentile with Large IBSI Phantom Image", 4, results["First Order Numeric::90th Percentile"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Maximum with Large IBSI Phantom Image", 6, results["First Order Numeric::Maximum"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Interquantile range with Large IBSI Phantom Image", 3, results["First Order Numeric::Interquantile range"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Range with Large IBSI Phantom Image", 5, results["First Order Numeric::Range"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Mean absolute deviation with Large IBSI Phantom Image", 1.55, results["First Order Numeric::Mean absolute deviation"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Robust mean absolute deviation with Large IBSI Phantom Image", 1.11, results["First Order Numeric::Robust mean absolute deviation"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Median absolute deviation with Large IBSI Phantom Image", 1.15, results["First Order Numeric::Median absolute deviation"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Coefficient of variation with Large IBSI Phantom Image", 0.812, results["First Order Numeric::Coefficient of variation"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Quantile coefficient of dispersion with Large IBSI Phantom Image", 0.6, results["First Order Numeric::Quantile coefficient of dispersion"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Energy with Large IBSI Phantom Image", 567, results["First Order Numeric::Energy"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Root mean square with Large IBSI Phantom Image", 2.77, results["First Order Numeric::Root mean square"], 0.01); // These values are taken from the IBSI Initiative to ensure compatibility // The values are given with an accuracy of 0.01 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Standard Deviation with Large IBSI Phantom Image", 1.74513, results["First Order Numeric::Standard Deviation"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Kurtosis with Large IBSI Phantom Image", 2.64538, results["First Order Numeric::Kurtosis"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Robust mean with Large IBSI Phantom Image", 1.74627, results["First Order Numeric::Robust mean"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Robust variance with Large IBSI Phantom Image", 1.65204, results["First Order Numeric::Robust variance"], 0.01); - CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Covered image intensity range with Large IBSI Phantom Image", 1.2, results["First Order Numeric::Covered image intensity range"], 0.01); + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Covered image intensity range with Large IBSI Phantom Image", 0.83333, results["First Order Numeric::Covered image intensity range"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Mode index with Large IBSI Phantom Image",0 , results["First Order Numeric::Mode index"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Mode value with Large IBSI Phantom Image", 1, results["First Order Numeric::Mode value"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Mode probability with Large IBSI Phantom Image", 0.675676, results["First Order Numeric::Mode probability"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Entropy with Large IBSI Phantom Image", -1.26561, results["First Order Numeric::Entropy"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Uniformtiy with Large IBSI Phantom Image", 0.512418, results["First Order Numeric::Uniformtiy"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Number of voxels with Large IBSI Phantom Image", 74 , results["First Order Numeric::Number of voxels"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Sum of voxels with Large IBSI Phantom Image", 159, results["First Order Numeric::Sum of voxels"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Voxel space with Large IBSI Phantom Image", 8, results["First Order Numeric::Voxel space"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Voxel volume with Large IBSI Phantom Image", 8, results["First Order Numeric::Voxel volume"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("First Order Numeric::Image Dimension with Large IBSI Phantom Image", 3, results["First Order Numeric::Image Dimension"], 0.01); } }; MITK_TEST_SUITE_REGISTRATION(mitkGIFFirstOrderNumericStatistics ) \ No newline at end of file