diff --git a/Modules/ImageStatistics/Testing/mitkImageStatisticsCalculatorTest.cpp b/Modules/ImageStatistics/Testing/mitkImageStatisticsCalculatorTest.cpp index cfbb184611..ca883e8895 100644 --- a/Modules/ImageStatistics/Testing/mitkImageStatisticsCalculatorTest.cpp +++ b/Modules/ImageStatistics/Testing/mitkImageStatisticsCalculatorTest.cpp @@ -1,1141 +1,1133 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkImageStatisticsCalculator.h" #include #include #include #include #include #include #include /** * \brief Test class for mitkImageStatisticsCalculator * * This test covers: * - instantiation of an ImageStatisticsCalculator class * - correctness of statistics when using PlanarFigures for masking */ class mitkImageStatisticsCalculatorTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkImageStatisticsCalculatorTestSuite); MITK_TEST(TestUninitializedImage); MITK_TEST(TestCase1); MITK_TEST(TestCase2); MITK_TEST(TestCase3); MITK_TEST(TestCase4); MITK_TEST(TestCase5); MITK_TEST(TestCase6); MITK_TEST(TestCase7); MITK_TEST(TestCase8); MITK_TEST(TestCase9); MITK_TEST(TestCase10); MITK_TEST(TestCase11); MITK_TEST(TestCase12); MITK_TEST(TestPic3DCroppedNoMask); MITK_TEST(TestPic3DCroppedBinMask); MITK_TEST(TestPic3DCroppedMultilabelMask); MITK_TEST(TestPic3DCroppedPlanarFigure); MITK_TEST(TestUS4DCroppedNoMaskTimeStep1); MITK_TEST(TestUS4DCroppedBinMaskTimeStep1); MITK_TEST(TestUS4DCroppedMultilabelMaskTimeStep1); MITK_TEST(TestUS4DCroppedPlanarFigureTimeStep1); MITK_TEST(TestUS4DCroppedAllTimesteps); MITK_TEST(TestUS4DCropped3DMask); CPPUNIT_TEST_SUITE_END(); public: void TestUninitializedImage(); void TestCase1(); void TestCase2(); void TestCase3(); void TestCase4(); void TestCase5(); void TestCase6(); void TestCase7(); void TestCase8(); void TestCase9(); void TestCase10(); void TestCase11(); void TestCase12(); void TestPic3DCroppedNoMask(); void TestPic3DCroppedBinMask(); void TestPic3DCroppedMultilabelMask(); void TestPic3DCroppedPlanarFigure(); void TestUS4DCroppedNoMaskTimeStep1(); void TestUS4DCroppedBinMaskTimeStep1(); void TestUS4DCroppedMultilabelMaskTimeStep1(); void TestUS4DCroppedPlanarFigureTimeStep1(); void TestUS4DCroppedAllTimesteps(); void TestUS4DCropped3DMask(); private: mitk::Image::ConstPointer m_TestImage; mitk::Image::ConstPointer m_Pic3DCroppedImage; mitk::Image::Pointer m_Pic3DCroppedBinMask; mitk::Image::Pointer m_Pic3DCroppedMultilabelMask; mitk::PlanarFigure::Pointer m_Pic3DCroppedPlanarFigure; mitk::Image::ConstPointer m_US4DCroppedImage; mitk::Image::Pointer m_US4DCroppedBinMask; mitk::Image::Pointer m_US4DCroppedMultilabelMask; mitk::Image::Pointer m_US4DCropped3DBinMask; mitk::PlanarFigure::Pointer m_US4DCroppedPlanarFigure; mitk::PlaneGeometry::Pointer m_Geometry; // creates a polygon given a geometry and a vector of 2d points mitk::PlanarPolygon::Pointer GeneratePlanarPolygon(mitk::PlaneGeometry::Pointer geometry, std::vector points); // universal function to calculate statistics - const mitk::ImageStatisticsContainer::Pointer ComputeStatistics(mitk::Image::ConstPointer image, - mitk::MaskGenerator::Pointer maskGen = nullptr, - mitk::MaskGenerator::Pointer secondardMaskGen = nullptr, - unsigned short label = 1); + const mitk::ImageStatisticsContainer::Pointer + mitkImageStatisticsCalculatorTestSuite::ComputeStatistics(mitk::Image::ConstPointer image, + mitk::MaskGenerator::Pointer maskGen = nullptr, + mitk::MaskGenerator::Pointer secondardMaskGen = nullptr) + { + mitk::ImageStatisticsCalculator::Pointer imgStatCalc = mitk::ImageStatisticsCalculator::New(); + imgStatCalc->SetInputImage(image); + + if (maskGen.IsNotNull()) + { + imgStatCalc->SetMask(maskGen.GetPointer()); + if (secondardMaskGen.IsNotNull()) + { + imgStatCalc->SetSecondaryMask(secondardMaskGen.GetPointer()); + } + } + + return imgStatCalc->GetStatistics(); + } void VerifyStatistics(mitk::ImageStatisticsContainer::ImageStatisticsObject stats, mitk::ImageStatisticsContainer::RealType testMean, mitk::ImageStatisticsContainer::RealType testSD, mitk::ImageStatisticsContainer::RealType testMedian = 0); // T26098 histogram statistics need to be tested (median, uniformity, UPP, entropy) void VerifyStatistics(mitk::ImageStatisticsContainer::ImageStatisticsObject stats, mitk::ImageStatisticsContainer::VoxelCountType N, mitk::ImageStatisticsContainer::RealType mean, mitk::ImageStatisticsContainer::RealType MPP, mitk::ImageStatisticsContainer::RealType skewness, mitk::ImageStatisticsContainer::RealType kurtosis, mitk::ImageStatisticsContainer::RealType variance, mitk::ImageStatisticsContainer::RealType stdev, mitk::ImageStatisticsContainer::RealType min, mitk::ImageStatisticsContainer::RealType max, mitk::ImageStatisticsContainer::RealType RMS, mitk::ImageStatisticsContainer::IndexType minIndex, mitk::ImageStatisticsContainer::IndexType maxIndex); }; void mitkImageStatisticsCalculatorTestSuite::TestUninitializedImage() { /***************************** * loading uninitialized image to datastorage ******************************/ MITK_INFO << std::endl << "Test uninitialized image: -----------------------------------------------------------------------------------"; mitk::Image::Pointer image = mitk::Image::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(image); mitk::ImageStatisticsCalculator::Pointer is = mitk::ImageStatisticsCalculator::New(); CPPUNIT_ASSERT_THROW(is->GetStatistics(), mitk::Exception); } void mitkImageStatisticsCalculatorTestSuite::TestCase1() { /***************************** * one whole white pixel * -> mean of 255 expected ******************************/ MITK_INFO << std::endl << "Test case 1:-----------------------------------------------------------------------------------"; std::string filename = this->GetTestDataFilePath("ImageStatisticsTestData/testimage.nrrd"); m_TestImage = mitk::IOUtil::Load(filename); CPPUNIT_ASSERT_MESSAGE("Failed loading an mitk::Image", m_TestImage.IsNotNull()); m_Geometry = m_TestImage->GetSlicedGeometry()->GetPlaneGeometry(0); CPPUNIT_ASSERT_MESSAGE("Failed getting image geometry", m_Geometry.IsNotNull()); mitk::Point2D pnt1; pnt1[0] = 10.5; pnt1[1] = 3.5; mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5; mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5; mitk::Point2D pnt4; pnt4[0] = 10.5; pnt4[1] = 4.5; std::vector points{ pnt1,pnt2,pnt3,pnt4 }; auto figure = GeneratePlanarPolygon(m_Geometry, points); mitk::ImageStatisticsContainer::Pointer statisticsContainer; mitk::PlanarFigureMaskGenerator::Pointer planFigMaskGen = mitk::PlanarFigureMaskGenerator::New(); planFigMaskGen->SetInputImage(m_TestImage); planFigMaskGen->SetPlanarFigure(figure.GetPointer()); CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_TestImage, planFigMaskGen.GetPointer())); - auto statisticsObjectTimestep0 = statisticsContainer->GetStatisticsForTimeStep(0); + auto statisticsObjectTimestep0 = statisticsContainer->GetStatistics(1, 0); this->VerifyStatistics(statisticsObjectTimestep0, 255.0, 0.0, 255.0); } void mitkImageStatisticsCalculatorTestSuite::TestCase2() { /***************************** * half pixel in x-direction (white) * -> mean of 255 expected ******************************/ MITK_INFO << std::endl << "Test case 2:-----------------------------------------------------------------------------------"; std::string filename = this->GetTestDataFilePath("ImageStatisticsTestData/testimage.nrrd"); m_TestImage = mitk::IOUtil::Load(filename); m_Geometry = m_TestImage->GetSlicedGeometry()->GetPlaneGeometry(0); mitk::Point2D pnt1; pnt1[0] = 10.0; pnt1[1] = 3.5; mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5; mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5; mitk::Point2D pnt4; pnt4[0] = 10.0; pnt4[1] = 4.5; std::vector points{ pnt1,pnt2,pnt3,pnt4 }; auto figure = GeneratePlanarPolygon(m_Geometry, points); mitk::PlanarFigureMaskGenerator::Pointer planFigMaskGen = mitk::PlanarFigureMaskGenerator::New(); planFigMaskGen->SetInputImage(m_TestImage); planFigMaskGen->SetPlanarFigure(figure.GetPointer()); mitk::ImageStatisticsContainer::Pointer statisticsContainer; CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_TestImage, planFigMaskGen.GetPointer())); - auto statisticsObjectTimestep0 = statisticsContainer->GetStatisticsForTimeStep(0); + auto statisticsObjectTimestep0 = statisticsContainer->GetStatistics(1,0); this->VerifyStatistics(statisticsObjectTimestep0, 255.0, 0.0, 255.0); } void mitkImageStatisticsCalculatorTestSuite::TestCase3() { /***************************** * half pixel in diagonal-direction (white) * -> mean of 255 expected ******************************/ MITK_INFO << std::endl << "Test case 3:-----------------------------------------------------------------------------------"; std::string filename = this->GetTestDataFilePath("ImageStatisticsTestData/testimage.nrrd"); m_TestImage = mitk::IOUtil::Load(filename); m_Geometry = m_TestImage->GetSlicedGeometry()->GetPlaneGeometry(0); mitk::Point2D pnt1; pnt1[0] = 10.5; pnt1[1] = 3.5; mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5; mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5; std::vector points{ pnt1,pnt2,pnt3 }; auto figure = GeneratePlanarPolygon(m_Geometry, points); mitk::PlanarFigureMaskGenerator::Pointer planFigMaskGen = mitk::PlanarFigureMaskGenerator::New(); planFigMaskGen->SetInputImage(m_TestImage); planFigMaskGen->SetPlanarFigure(figure.GetPointer()); mitk::ImageStatisticsContainer::Pointer statisticsContainer; CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_TestImage, planFigMaskGen.GetPointer())); - auto statisticsObjectTimestep0 = statisticsContainer->GetStatisticsForTimeStep(0); + auto statisticsObjectTimestep0 = statisticsContainer->GetStatistics(1, 0); this->VerifyStatistics(statisticsObjectTimestep0, 255.0, 0.0, 255.0); } void mitkImageStatisticsCalculatorTestSuite::TestCase4() { /***************************** * one pixel (white) + 2 half pixels (white) + 1 half pixel (black) * -> mean of 191.25 expected ******************************/ MITK_INFO << std::endl << "Test case 4:-----------------------------------------------------------------------------------"; std::string filename = this->GetTestDataFilePath("ImageStatisticsTestData/testimage.nrrd"); m_TestImage = mitk::IOUtil::Load(filename); m_Geometry = m_TestImage->GetSlicedGeometry()->GetPlaneGeometry(0); mitk::Point2D pnt1; pnt1[0] = 1.1; pnt1[1] = 1.1; mitk::Point2D pnt2; pnt2[0] = 2.0; pnt2[1] = 2.0; mitk::Point2D pnt3; pnt3[0] = 3.0; pnt3[1] = 1.0; mitk::Point2D pnt4; pnt4[0] = 2.0; pnt4[1] = 0.0; std::vector points{ pnt1,pnt2,pnt3,pnt4 }; auto figure = GeneratePlanarPolygon(m_Geometry, points); mitk::PlanarFigureMaskGenerator::Pointer planFigMaskGen = mitk::PlanarFigureMaskGenerator::New(); planFigMaskGen->SetInputImage(m_TestImage); planFigMaskGen->SetPlanarFigure(figure.GetPointer()); mitk::ImageStatisticsContainer::Pointer statisticsContainer; CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_TestImage, planFigMaskGen.GetPointer())); - auto statisticsObjectTimestep0 = statisticsContainer->GetStatisticsForTimeStep(0); + auto statisticsObjectTimestep0 = statisticsContainer->GetStatistics(1, 0); this->VerifyStatistics(statisticsObjectTimestep0, 191.25, 127.5, 253.72499847412109); } void mitkImageStatisticsCalculatorTestSuite::TestCase5() { /***************************** * whole pixel (white) + half pixel (gray) in x-direction * -> mean of 191.5 expected ******************************/ MITK_INFO << std::endl << "Test case 5:-----------------------------------------------------------------------------------"; std::string filename = this->GetTestDataFilePath("ImageStatisticsTestData/testimage.nrrd"); m_TestImage = mitk::IOUtil::Load(filename); m_Geometry = m_TestImage->GetSlicedGeometry()->GetPlaneGeometry(0); mitk::Point2D pnt1; pnt1[0] = 11.0; pnt1[1] = 3.5; mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5; mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5; mitk::Point2D pnt4; pnt4[0] = 11.0; pnt4[1] = 4.5; std::vector points{ pnt1,pnt2,pnt3,pnt4 }; auto figure = GeneratePlanarPolygon(m_Geometry, points); mitk::PlanarFigureMaskGenerator::Pointer planFigMaskGen = mitk::PlanarFigureMaskGenerator::New(); planFigMaskGen->SetInputImage(m_TestImage); planFigMaskGen->SetPlanarFigure(figure.GetPointer()); mitk::ImageStatisticsContainer::Pointer statisticsContainer; CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_TestImage, planFigMaskGen.GetPointer())); - auto statisticsObjectTimestep0 = statisticsContainer->GetStatisticsForTimeStep(0); + auto statisticsObjectTimestep0 = statisticsContainer->GetStatistics(1, 0); this->VerifyStatistics(statisticsObjectTimestep0, 191.50, 89.802561210691536, 128.63499999046327); } void mitkImageStatisticsCalculatorTestSuite::TestCase6() { /***************************** * quarter pixel (black) + whole pixel (white) + half pixel (gray) in x-direction * -> mean of 191.5 expected ******************************/ MITK_INFO << std::endl << "Test case 6:-----------------------------------------------------------------------------------"; std::string filename = this->GetTestDataFilePath("ImageStatisticsTestData/testimage.nrrd"); m_TestImage = mitk::IOUtil::Load(filename); m_Geometry = m_TestImage->GetSlicedGeometry()->GetPlaneGeometry(0); mitk::Point2D pnt1; pnt1[0] = 11.0; pnt1[1] = 3.5; mitk::Point2D pnt2; pnt2[0] = 9.25; pnt2[1] = 3.5; mitk::Point2D pnt3; pnt3[0] = 9.25; pnt3[1] = 4.5; mitk::Point2D pnt4; pnt4[0] = 11.0; pnt4[1] = 4.5; std::vector points{ pnt1,pnt2,pnt3,pnt4 }; auto figure = GeneratePlanarPolygon(m_Geometry, points); mitk::PlanarFigureMaskGenerator::Pointer planFigMaskGen = mitk::PlanarFigureMaskGenerator::New(); planFigMaskGen->SetInputImage(m_TestImage); planFigMaskGen->SetPlanarFigure(figure.GetPointer()); mitk::ImageStatisticsContainer::Pointer statisticsContainer; CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_TestImage, planFigMaskGen.GetPointer())); - auto statisticsObjectTimestep0 = statisticsContainer->GetStatisticsForTimeStep(0); + auto statisticsObjectTimestep0 = statisticsContainer->GetStatistics(1, 0); this->VerifyStatistics(statisticsObjectTimestep0, 191.5, 89.802561210691536, 128.63499999046327); } void mitkImageStatisticsCalculatorTestSuite::TestCase7() { /***************************** * half pixel (black) + whole pixel (white) + half pixel (gray) in x-direction * -> mean of 127.66 expected ******************************/ MITK_INFO << std::endl << "Test case 7:-----------------------------------------------------------------------------------"; std::string filename = this->GetTestDataFilePath("ImageStatisticsTestData/testimage.nrrd"); m_TestImage = mitk::IOUtil::Load(filename); m_Geometry = m_TestImage->GetSlicedGeometry()->GetPlaneGeometry(0); mitk::Point2D pnt1; pnt1[0] = 11.0; pnt1[1] = 3.5; mitk::Point2D pnt2; pnt2[0] = 9.0; pnt2[1] = 3.5; mitk::Point2D pnt3; pnt3[0] = 9.0; pnt3[1] = 4.0; mitk::Point2D pnt4; pnt4[0] = 11.0; pnt4[1] = 4.0; std::vector points{ pnt1,pnt2,pnt3,pnt4 }; auto figure = GeneratePlanarPolygon(m_Geometry, points); mitk::PlanarFigureMaskGenerator::Pointer planFigMaskGen = mitk::PlanarFigureMaskGenerator::New(); planFigMaskGen->SetInputImage(m_TestImage); planFigMaskGen->SetPlanarFigure(figure.GetPointer()); mitk::ImageStatisticsContainer::Pointer statisticsContainer; CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_TestImage, planFigMaskGen.GetPointer())); - auto statisticsObjectTimestep0 = statisticsContainer->GetStatisticsForTimeStep(0); + auto statisticsObjectTimestep0 = statisticsContainer->GetStatistics(1, 0); this->VerifyStatistics(statisticsObjectTimestep0, 127.666666666666667, 127.50032679696680, 128.7750015258789); } void mitkImageStatisticsCalculatorTestSuite::TestCase8() { /***************************** * whole pixel (gray) * -> mean of 128 expected ******************************/ MITK_INFO << std::endl << "Test case 8:-----------------------------------------------------------------------------------"; std::string filename = this->GetTestDataFilePath("ImageStatisticsTestData/testimage.nrrd"); m_TestImage = mitk::IOUtil::Load(filename); m_Geometry = m_TestImage->GetSlicedGeometry()->GetPlaneGeometry(0); mitk::Point2D pnt1; pnt1[0] = 11.5; pnt1[1] = 10.5; mitk::Point2D pnt2; pnt2[0] = 11.5; pnt2[1] = 11.5; mitk::Point2D pnt3; pnt3[0] = 12.5; pnt3[1] = 11.5; mitk::Point2D pnt4; pnt4[0] = 12.5; pnt4[1] = 10.5; std::vector points{ pnt1,pnt2,pnt3,pnt4 }; auto figure = GeneratePlanarPolygon(m_Geometry, points); mitk::PlanarFigureMaskGenerator::Pointer planFigMaskGen = mitk::PlanarFigureMaskGenerator::New(); planFigMaskGen->SetInputImage(m_TestImage); planFigMaskGen->SetPlanarFigure(figure.GetPointer()); mitk::ImageStatisticsContainer::Pointer statisticsContainer; CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_TestImage, planFigMaskGen.GetPointer())); - auto statisticsObjectTimestep0 = statisticsContainer->GetStatisticsForTimeStep(0); + auto statisticsObjectTimestep0 = statisticsContainer->GetStatistics(1, 0); this->VerifyStatistics(statisticsObjectTimestep0, 128.0, 0.0, 128.0); } void mitkImageStatisticsCalculatorTestSuite::TestCase9() { /***************************** * whole pixel (gray) + half pixel (white) in y-direction * -> mean of 191.5 expected ******************************/ MITK_INFO << std::endl << "Test case 9:-----------------------------------------------------------------------------------"; std::string filename = this->GetTestDataFilePath("ImageStatisticsTestData/testimage.nrrd"); m_TestImage = mitk::IOUtil::Load(filename); m_Geometry = m_TestImage->GetSlicedGeometry()->GetPlaneGeometry(0); mitk::Point2D pnt1; pnt1[0] = 11.5; pnt1[1] = 10.5; mitk::Point2D pnt2; pnt2[0] = 11.5; pnt2[1] = 12.0; mitk::Point2D pnt3; pnt3[0] = 12.5; pnt3[1] = 12.0; mitk::Point2D pnt4; pnt4[0] = 12.5; pnt4[1] = 10.5; std::vector points{ pnt1,pnt2,pnt3,pnt4 }; auto figure = GeneratePlanarPolygon(m_Geometry, points); mitk::PlanarFigureMaskGenerator::Pointer planFigMaskGen = mitk::PlanarFigureMaskGenerator::New(); planFigMaskGen->SetInputImage(m_TestImage); planFigMaskGen->SetPlanarFigure(figure.GetPointer()); mitk::ImageStatisticsContainer::Pointer statisticsContainer; CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_TestImage, planFigMaskGen.GetPointer())); - auto statisticsObjectTimestep0 = statisticsContainer->GetStatisticsForTimeStep(0); + auto statisticsObjectTimestep0 = statisticsContainer->GetStatistics(1, 0); this->VerifyStatistics(statisticsObjectTimestep0, 191.5, 89.802561210691536, 128.63499999046327); } void mitkImageStatisticsCalculatorTestSuite::TestCase10() { /***************************** * 2 whole pixel (white) + 2 whole pixel (black) in y-direction * -> mean of 127.66 expected ******************************/ MITK_INFO << std::endl << "Test case 10:-----------------------------------------------------------------------------------"; std::string filename = this->GetTestDataFilePath("ImageStatisticsTestData/testimage.nrrd"); m_TestImage = mitk::IOUtil::Load(filename); m_Geometry = m_TestImage->GetSlicedGeometry()->GetPlaneGeometry(0); mitk::Point2D pnt1; pnt1[0] = 11.5; pnt1[1] = 10.5; mitk::Point2D pnt2; pnt2[0] = 11.5; pnt2[1] = 13.5; mitk::Point2D pnt3; pnt3[0] = 12.5; pnt3[1] = 13.5; mitk::Point2D pnt4; pnt4[0] = 12.5; pnt4[1] = 10.5; std::vector points{ pnt1,pnt2,pnt3,pnt4 }; auto figure = GeneratePlanarPolygon(m_Geometry, points); mitk::PlanarFigureMaskGenerator::Pointer planFigMaskGen = mitk::PlanarFigureMaskGenerator::New(); planFigMaskGen->SetInputImage(m_TestImage); planFigMaskGen->SetPlanarFigure(figure.GetPointer()); mitk::ImageStatisticsContainer::Pointer statisticsContainer; CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_TestImage, planFigMaskGen.GetPointer())); - auto statisticsObjectTimestep0 = statisticsContainer->GetStatisticsForTimeStep(0); + auto statisticsObjectTimestep0 = statisticsContainer->GetStatistics(1, 0); this->VerifyStatistics(statisticsObjectTimestep0, 127.666666666666667, 127.50032679696680, 128.7750015258789); } void mitkImageStatisticsCalculatorTestSuite::TestCase11() { /***************************** * 9 whole pixels (white) + 3 half pixels (white) * + 3 whole pixel (black) [ + 3 slightly less than half pixels (black)] * -> mean of 204.0 expected ******************************/ MITK_INFO << std::endl << "Test case 11:-----------------------------------------------------------------------------------"; std::string filename = this->GetTestDataFilePath("ImageStatisticsTestData/testimage.nrrd"); m_TestImage = mitk::IOUtil::Load(filename); m_Geometry = m_TestImage->GetSlicedGeometry()->GetPlaneGeometry(0); mitk::Point2D pnt1; pnt1[0] = 0.5; pnt1[1] = 0.5; mitk::Point2D pnt2; pnt2[0] = 3.5; pnt2[1] = 3.5; mitk::Point2D pnt3; pnt3[0] = 8.4999; pnt3[1] = 3.5; mitk::Point2D pnt4; pnt4[0] = 5.4999; pnt4[1] = 0.5; std::vector points{ pnt1,pnt2,pnt3,pnt4 }; auto figure = GeneratePlanarPolygon(m_Geometry, points); mitk::PlanarFigureMaskGenerator::Pointer planFigMaskGen = mitk::PlanarFigureMaskGenerator::New(); planFigMaskGen->SetInputImage(m_TestImage); planFigMaskGen->SetPlanarFigure(figure.GetPointer()); mitk::ImageStatisticsContainer::Pointer statisticsContainer; CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_TestImage, planFigMaskGen.GetPointer())); - auto statisticsObjectTimestep0 = statisticsContainer->GetStatisticsForTimeStep(0); + auto statisticsObjectTimestep0 = statisticsContainer->GetStatistics(1, 0); this->VerifyStatistics(statisticsObjectTimestep0, 204.0, 105.58003057938019, 253.724998474121083); } void mitkImageStatisticsCalculatorTestSuite::TestCase12() { /***************************** * half pixel (white) + whole pixel (white) + half pixel (black) * -> mean of 212.66 expected ******************************/ MITK_INFO << std::endl << "Test case 12:-----------------------------------------------------------------------------------"; std::string filename = this->GetTestDataFilePath("ImageStatisticsTestData/testimage.nrrd"); m_TestImage = mitk::IOUtil::Load(filename); m_Geometry = m_TestImage->GetSlicedGeometry()->GetPlaneGeometry(0); mitk::Point2D pnt1; pnt1[0] = 9.5; pnt1[1] = 0.5; mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 2.5; mitk::Point2D pnt3; pnt3[0] = 11.5; pnt3[1] = 2.5; std::vector points{ pnt1,pnt2,pnt3 }; auto figure = GeneratePlanarPolygon(m_Geometry, points); mitk::PlanarFigureMaskGenerator::Pointer planFigMaskGen = mitk::PlanarFigureMaskGenerator::New(); planFigMaskGen->SetInputImage(m_TestImage); planFigMaskGen->SetPlanarFigure(figure.GetPointer()); mitk::ImageStatisticsContainer::Pointer statisticsContainer; CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_TestImage, planFigMaskGen.GetPointer())); - auto statisticsObjectTimestep0 = statisticsContainer->GetStatisticsForTimeStep(0); + auto statisticsObjectTimestep0 = statisticsContainer->GetStatistics(1, 0); this->VerifyStatistics(statisticsObjectTimestep0, 212.666666666666667, 73.323484187082443, 254.36499786376954); } // T26098 histogram statistics need to be tested (median, uniformity, UPP, entropy) void mitkImageStatisticsCalculatorTestSuite::TestPic3DCroppedNoMask() { MITK_INFO << std::endl << "Test Pic3D cropped without mask:-----------------------------------------------------------------------------------"; std::string Pic3DCroppedFile = this->GetTestDataFilePath("ImageStatisticsTestData/Pic3D_cropped.nrrd"); m_Pic3DCroppedImage = mitk::IOUtil::Load(Pic3DCroppedFile); CPPUNIT_ASSERT_MESSAGE("Failed loading Pic3D_cropped", m_Pic3DCroppedImage.IsNotNull()); //calculated ground truth via script mitk::ImageStatisticsContainer::VoxelCountType expected_N = 27; mitk::ImageStatisticsContainer::RealType expected_mean = -564.1481481481481481; mitk::ImageStatisticsContainer::RealType expected_MPP = 113.66666666666667; //mitk::ImageStatisticsContainer::RealType expected_median = -825; mitk::ImageStatisticsContainer::RealType expected_skewness = 0.7120461106763573; mitk::ImageStatisticsContainer::RealType expected_kurtosis = 1.8794464383714844; mitk::ImageStatisticsContainer::RealType expected_variance = 145946.82336182334; mitk::ImageStatisticsContainer::RealType expected_standarddev = 382.02987234223366; mitk::ImageStatisticsContainer::RealType expected_min = -927; mitk::ImageStatisticsContainer::RealType expected_max = 147; mitk::ImageStatisticsContainer::RealType expected_RMS = 681.32955052662169; mitk::ImageStatisticsContainer::IndexType expected_minIndex; expected_minIndex.set_size(3); expected_minIndex[0] = 2; expected_minIndex[1] = 1; expected_minIndex[2] = 1; mitk::ImageStatisticsContainer::IndexType expected_maxIndex; expected_maxIndex.set_size(3); expected_maxIndex[0] = 0; expected_maxIndex[1] = 1; expected_maxIndex[2] = 2; mitk::ImageStatisticsContainer::Pointer statisticsContainer; CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_Pic3DCroppedImage)); - auto statisticsObject = statisticsContainer->GetStatisticsForTimeStep(0); + auto statisticsObject = statisticsContainer->GetStatistics(mitk::ImageStatisticsContainer::NO_MASK_LABEL_VALUE, 0); VerifyStatistics(statisticsObject, expected_N, expected_mean, expected_MPP, expected_skewness, expected_kurtosis, expected_variance, expected_standarddev, expected_min, expected_max, expected_RMS, expected_minIndex, expected_maxIndex); } // T26098 histogram statistics need to be tested (median, uniformity, UPP, entropy) void mitkImageStatisticsCalculatorTestSuite::TestPic3DCroppedBinMask() { MITK_INFO << std::endl << "Test Pic3D cropped binary mask:-----------------------------------------------------------------------------------"; std::string Pic3DCroppedFile = this->GetTestDataFilePath("ImageStatisticsTestData/Pic3D_cropped.nrrd"); m_Pic3DCroppedImage = mitk::IOUtil::Load(Pic3DCroppedFile); CPPUNIT_ASSERT_MESSAGE("Failed loading Pic3D_cropped", m_Pic3DCroppedImage.IsNotNull()); std::string Pic3DCroppedBinMaskFile = this->GetTestDataFilePath("ImageStatisticsTestData/Pic3D_croppedBinMask.nrrd"); m_Pic3DCroppedBinMask = mitk::IOUtil::Load(Pic3DCroppedBinMaskFile); CPPUNIT_ASSERT_MESSAGE("Failed loading Pic3D binary mask", m_Pic3DCroppedBinMask.IsNotNull()); //calculated ground truth via script mitk::ImageStatisticsContainer::RealType expected_kurtosis = 1.0765697398089618; mitk::ImageStatisticsContainer::RealType expected_MPP = -nan(""); mitk::ImageStatisticsContainer::RealType expected_max = -22; mitk::ImageStatisticsContainer::RealType expected_mean = -464; mitk::ImageStatisticsContainer::RealType expected_min = -846; mitk::ImageStatisticsContainer::VoxelCountType expected_N = 4; mitk::ImageStatisticsContainer::RealType expected_RMS = 633.20191618998331; mitk::ImageStatisticsContainer::RealType expected_skewness = 0.0544059290851858; mitk::ImageStatisticsContainer::RealType expected_standarddev = 430.86966320067910; mitk::ImageStatisticsContainer::RealType expected_variance = 185648.66666666663; mitk::ImageStatisticsContainer::IndexType expected_minIndex; expected_minIndex.set_size(3); expected_minIndex[0] = 1; expected_minIndex[1] = 0; expected_minIndex[2] = 0; mitk::ImageStatisticsContainer::IndexType expected_maxIndex; expected_maxIndex.set_size(3); expected_maxIndex[0] = 0; expected_maxIndex[1] = 0; expected_maxIndex[2] = 1; mitk::ImageMaskGenerator::Pointer imgMaskGen = mitk::ImageMaskGenerator::New(); imgMaskGen->SetImageMask(m_Pic3DCroppedBinMask); imgMaskGen->SetInputImage(m_Pic3DCroppedImage); imgMaskGen->SetTimeStep(0); mitk::ImageStatisticsContainer::Pointer statisticsContainer; - CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_Pic3DCroppedImage, imgMaskGen.GetPointer(), nullptr, 1)); - auto statisticsObjectTimestep0 = statisticsContainer->GetStatisticsForTimeStep(0); + CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_Pic3DCroppedImage, imgMaskGen.GetPointer(), nullptr)); + auto statisticsObjectTimestep0 = statisticsContainer->GetStatistics(1, 0); VerifyStatistics(statisticsObjectTimestep0, expected_N, expected_mean, expected_MPP, expected_skewness, expected_kurtosis, expected_variance, expected_standarddev, expected_min, expected_max, expected_RMS, expected_minIndex, expected_maxIndex); } // T26098 histogram statistics need to be tested (median, uniformity, UPP, entropy) void mitkImageStatisticsCalculatorTestSuite::TestPic3DCroppedMultilabelMask() { - MITK_INFO << std::endl << "Test Pic3D cropped multilabel mask:-----------------------------------------------------------------------------------"; + MITK_INFO << std::endl << "Test Pic3D cropped multi-label mask:-----------------------------------------------------------------------------------"; std::string Pic3DCroppedFile = this->GetTestDataFilePath("ImageStatisticsTestData/Pic3D_cropped.nrrd"); m_Pic3DCroppedImage = mitk::IOUtil::Load(Pic3DCroppedFile); CPPUNIT_ASSERT_MESSAGE("Failed loading Pic3D_cropped", m_Pic3DCroppedImage.IsNotNull()); std::string Pic3DCroppedMultilabelMaskFile = this->GetTestDataFilePath("ImageStatisticsTestData/Pic3D_croppedMultilabelMask.nrrd"); m_Pic3DCroppedMultilabelMask = mitk::IOUtil::Load(Pic3DCroppedMultilabelMaskFile); - CPPUNIT_ASSERT_MESSAGE("Failed loading Pic3D multilabel mask", m_Pic3DCroppedMultilabelMask.IsNotNull()); + CPPUNIT_ASSERT_MESSAGE("Failed loading Pic3D multi-label mask", m_Pic3DCroppedMultilabelMask.IsNotNull()); //calculated ground truth via script mitk::ImageStatisticsContainer::RealType expected_kurtosis = 1.5; mitk::ImageStatisticsContainer::RealType expected_MPP = -nan(""); mitk::ImageStatisticsContainer::RealType expected_max = -22; mitk::ImageStatisticsContainer::RealType expected_mean = -586.33333333333333; mitk::ImageStatisticsContainer::RealType expected_min = -916; mitk::ImageStatisticsContainer::VoxelCountType expected_N = 3; mitk::ImageStatisticsContainer::RealType expected_RMS = 764.78566351044469; mitk::ImageStatisticsContainer::RealType expected_skewness = 0.6774469597523700; mitk::ImageStatisticsContainer::RealType expected_standarddev = 491.02987010296363; mitk::ImageStatisticsContainer::RealType expected_variance = 241110.33333333334; mitk::ImageStatisticsContainer::IndexType expected_minIndex; expected_minIndex.set_size(3); expected_minIndex[0] = 2; expected_minIndex[1] = 0; expected_minIndex[2] = 1; mitk::ImageStatisticsContainer::IndexType expected_maxIndex; expected_maxIndex.set_size(3); expected_maxIndex[0] = 0; expected_maxIndex[1] = 0; expected_maxIndex[2] = 1; mitk::ImageMaskGenerator::Pointer imgMaskGen = mitk::ImageMaskGenerator::New(); imgMaskGen->SetImageMask(m_Pic3DCroppedMultilabelMask); imgMaskGen->SetInputImage(m_Pic3DCroppedImage); imgMaskGen->SetTimeStep(0); mitk::ImageStatisticsContainer::Pointer statisticsContainer; - CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_Pic3DCroppedImage, imgMaskGen.GetPointer(), nullptr, 2)); - auto statisticsObjectTimestep0 = statisticsContainer->GetStatisticsForTimeStep(0); + CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_Pic3DCroppedImage, imgMaskGen.GetPointer(), nullptr)); + auto statisticsObjectTimestep0 = statisticsContainer->GetStatistics(2, 0); VerifyStatistics(statisticsObjectTimestep0, expected_N, expected_mean, expected_MPP, expected_skewness, expected_kurtosis, expected_variance, expected_standarddev, expected_min, expected_max, expected_RMS, expected_minIndex, expected_maxIndex); } // T26098 histogram statistics need to be tested (median, uniformity, UPP, entropy) void mitkImageStatisticsCalculatorTestSuite::TestPic3DCroppedPlanarFigure() { MITK_INFO << std::endl << "Test Pic3D cropped planar figure:-----------------------------------------------------------------------------------"; std::string Pic3DCroppedFile = this->GetTestDataFilePath("ImageStatisticsTestData/Pic3D_cropped.nrrd"); m_Pic3DCroppedImage = mitk::IOUtil::Load(Pic3DCroppedFile); CPPUNIT_ASSERT_MESSAGE("Failed loading Pic3D_cropped", m_Pic3DCroppedImage.IsNotNull()); std::string Pic3DCroppedPlanarFigureFile = this->GetTestDataFilePath("ImageStatisticsTestData/Pic3D_croppedPF.pf"); m_Pic3DCroppedPlanarFigure = mitk::IOUtil::Load(Pic3DCroppedPlanarFigureFile); CPPUNIT_ASSERT_MESSAGE("Failed loading Pic3D planar figure", m_Pic3DCroppedPlanarFigure.IsNotNull()); //calculated ground truth via script mitk::ImageStatisticsContainer::RealType expected_kurtosis = 1; mitk::ImageStatisticsContainer::RealType expected_MPP = -nan(""); mitk::ImageStatisticsContainer::RealType expected_max = -67; mitk::ImageStatisticsContainer::RealType expected_mean = -446; mitk::ImageStatisticsContainer::RealType expected_min = -825; mitk::ImageStatisticsContainer::VoxelCountType expected_N = 2; mitk::ImageStatisticsContainer::RealType expected_RMS = 697.27899724572228; mitk::ImageStatisticsContainer::RealType expected_skewness = 0; mitk::ImageStatisticsContainer::RealType expected_standarddev = 535.98694013940303; mitk::ImageStatisticsContainer::RealType expected_variance = 287282.0; mitk::ImageStatisticsContainer::IndexType expected_minIndex; expected_minIndex.set_size(3); expected_minIndex[0] = 1; expected_minIndex[1] = 1; expected_minIndex[2] = 1; mitk::ImageStatisticsContainer::IndexType expected_maxIndex; expected_maxIndex.set_size(3); expected_maxIndex[0] = 0; expected_maxIndex[1] = 1; expected_maxIndex[2] = 1; mitk::PlanarFigureMaskGenerator::Pointer pfMaskGen = mitk::PlanarFigureMaskGenerator::New(); pfMaskGen->SetInputImage(m_Pic3DCroppedImage); pfMaskGen->SetPlanarFigure(m_Pic3DCroppedPlanarFigure); mitk::ImageStatisticsContainer::Pointer statisticsContainer; CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_Pic3DCroppedImage, pfMaskGen.GetPointer())); - auto statisticsObjectTimestep0 = statisticsContainer->GetStatisticsForTimeStep(0); + auto statisticsObjectTimestep0 = statisticsContainer->GetStatistics(1, 0); VerifyStatistics(statisticsObjectTimestep0, expected_N, expected_mean, expected_MPP, expected_skewness, expected_kurtosis, expected_variance, expected_standarddev, expected_min, expected_max, expected_RMS, expected_minIndex, expected_maxIndex); } // T26098 histogram statistics need to be tested (median, uniformity, UPP, entropy) void mitkImageStatisticsCalculatorTestSuite::TestUS4DCroppedNoMaskTimeStep1() { - MITK_INFO << std::endl << "Test US4D cropped without mask timestep 1:-----------------------------------------------------------------------------------"; + MITK_INFO << std::endl << "Test US4D cropped without mask time step 1:-----------------------------------------------------------------------------------"; std::string US4DCroppedFile = this->GetTestDataFilePath("ImageStatisticsTestData/US4D_cropped.nrrd"); m_US4DCroppedImage = mitk::IOUtil::Load(US4DCroppedFile); CPPUNIT_ASSERT_MESSAGE("Failed loading US4D_cropped", m_US4DCroppedImage.IsNotNull()); //calculated ground truth via script mitk::ImageStatisticsContainer::RealType expected_kurtosis = 1.5398359155908228; mitk::ImageStatisticsContainer::RealType expected_MPP = 157.74074074074073; mitk::ImageStatisticsContainer::RealType expected_max = 199; mitk::ImageStatisticsContainer::RealType expected_mean = 157.74074074074073; mitk::ImageStatisticsContainer::RealType expected_min = 101; mitk::ImageStatisticsContainer::VoxelCountType expected_N = 27; mitk::ImageStatisticsContainer::RealType expected_RMS = 161.11544579426010; mitk::ImageStatisticsContainer::RealType expected_skewness = 0.0347280313508018; mitk::ImageStatisticsContainer::RealType expected_standarddev = 32.803133753432512; mitk::ImageStatisticsContainer::RealType expected_variance = 1076.0455840455834; mitk::ImageStatisticsContainer::IndexType expected_minIndex; expected_minIndex.set_size(3); expected_minIndex[0] = 0; expected_minIndex[1] = 2; expected_minIndex[2] = 0; mitk::ImageStatisticsContainer::IndexType expected_maxIndex; expected_maxIndex.set_size(3); expected_maxIndex[0] = 0; expected_maxIndex[1] = 0; expected_maxIndex[2] = 1; mitk::ImageStatisticsContainer::Pointer statisticsContainer=mitk::ImageStatisticsContainer::New(); CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_US4DCroppedImage)); - auto statisticsObjectTimestep1 = statisticsContainer->GetStatisticsForTimeStep(1); + auto statisticsObjectTimestep1 = statisticsContainer->GetStatistics(mitk::ImageStatisticsContainer::NO_MASK_LABEL_VALUE, 1); VerifyStatistics(statisticsObjectTimestep1, expected_N, expected_mean, expected_MPP, expected_skewness, expected_kurtosis, expected_variance, expected_standarddev, expected_min, expected_max, expected_RMS, expected_minIndex, expected_maxIndex); } // T26098 histogram statistics need to be tested (median, uniformity, UPP, entropy) void mitkImageStatisticsCalculatorTestSuite::TestUS4DCroppedBinMaskTimeStep1() { - MITK_INFO << std::endl << "Test US4D cropped with binary mask timestep 1:-----------------------------------------------------------------------------------"; + MITK_INFO << std::endl << "Test US4D cropped with binary mask time step 1:-----------------------------------------------------------------------------------"; std::string US4DCroppedFile = this->GetTestDataFilePath("ImageStatisticsTestData/US4D_cropped.nrrd"); m_US4DCroppedImage = mitk::IOUtil::Load(US4DCroppedFile); CPPUNIT_ASSERT_MESSAGE("Failed loading US4D_cropped", m_US4DCroppedImage.IsNotNull()); std::string US4DCroppedBinMaskFile = this->GetTestDataFilePath("ImageStatisticsTestData/US4D_croppedBinMask.nrrd"); m_US4DCroppedBinMask = mitk::IOUtil::Load(US4DCroppedBinMaskFile); CPPUNIT_ASSERT_MESSAGE("Failed loading US4D binary mask", m_US4DCroppedBinMask.IsNotNull()); //calculated ground truth via script mitk::ImageStatisticsContainer::RealType expected_kurtosis = 1.5863739712889191; mitk::ImageStatisticsContainer::RealType expected_MPP = 166.75; mitk::ImageStatisticsContainer::RealType expected_max = 199; mitk::ImageStatisticsContainer::RealType expected_mean = 166.75; mitk::ImageStatisticsContainer::RealType expected_min = 120; mitk::ImageStatisticsContainer::VoxelCountType expected_N = 4; mitk::ImageStatisticsContainer::RealType expected_RMS = 170.68043971117487; mitk::ImageStatisticsContainer::RealType expected_skewness = -0.4285540263894276; mitk::ImageStatisticsContainer::RealType expected_standarddev = 36.417715469260287; mitk::ImageStatisticsContainer::RealType expected_variance = 1326.25; mitk::ImageStatisticsContainer::IndexType expected_minIndex; expected_minIndex.set_size(3); expected_minIndex[0] = 0; expected_minIndex[1] = 0; expected_minIndex[2] = 2; mitk::ImageStatisticsContainer::IndexType expected_maxIndex; expected_maxIndex.set_size(3); expected_maxIndex[0] = 1; expected_maxIndex[1] = 1; expected_maxIndex[2] = 1; mitk::ImageMaskGenerator::Pointer imgMask1 = mitk::ImageMaskGenerator::New(); imgMask1->SetInputImage(m_US4DCroppedImage); imgMask1->SetImageMask(m_US4DCroppedBinMask); mitk::ImageStatisticsContainer::Pointer statisticsContainer=mitk::ImageStatisticsContainer::New(); - CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_US4DCroppedImage, imgMask1.GetPointer(), nullptr, 1)); - auto statisticsObjectTimestep1 = statisticsContainer->GetStatisticsForTimeStep(1); + CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_US4DCroppedImage, imgMask1.GetPointer(), nullptr)); + auto statisticsObjectTimestep1 = statisticsContainer->GetStatistics(1, 1); VerifyStatistics(statisticsObjectTimestep1, expected_N, expected_mean, expected_MPP, expected_skewness, expected_kurtosis, expected_variance, expected_standarddev, expected_min, expected_max, expected_RMS, expected_minIndex, expected_maxIndex); } // T26098 histogram statistics need to be tested (median, uniformity, UPP, entropy) void mitkImageStatisticsCalculatorTestSuite::TestUS4DCroppedMultilabelMaskTimeStep1() { - MITK_INFO << std::endl << "Test US4D cropped with mulitlabel mask timestep 1:-----------------------------------------------------------------------------------"; + MITK_INFO << std::endl << "Test US4D cropped with multi-label mask time step 1:-----------------------------------------------------------------------------------"; std::string US4DCroppedFile = this->GetTestDataFilePath("ImageStatisticsTestData/US4D_cropped.nrrd"); m_US4DCroppedImage = mitk::IOUtil::Load(US4DCroppedFile); CPPUNIT_ASSERT_MESSAGE("Failed loading US4D_cropped", m_US4DCroppedImage.IsNotNull()); std::string US4DCroppedMultilabelMaskFile = this->GetTestDataFilePath("ImageStatisticsTestData/US4D_croppedMultilabelMask.nrrd"); m_US4DCroppedMultilabelMask = mitk::IOUtil::Load(US4DCroppedMultilabelMaskFile); - CPPUNIT_ASSERT_MESSAGE("Failed loading US4D multilabel mask", m_US4DCroppedMultilabelMask.IsNotNull()); + CPPUNIT_ASSERT_MESSAGE("Failed loading US4D multi-label mask", m_US4DCroppedMultilabelMask.IsNotNull()); //calculated ground truth via script mitk::ImageStatisticsContainer::RealType expected_kurtosis = 1.0432484564918287; mitk::ImageStatisticsContainer::RealType expected_MPP = 159.75; mitk::ImageStatisticsContainer::RealType expected_max = 199; mitk::ImageStatisticsContainer::RealType expected_mean = 159.75; mitk::ImageStatisticsContainer::RealType expected_min = 120; mitk::ImageStatisticsContainer::VoxelCountType expected_N = 4; mitk::ImageStatisticsContainer::RealType expected_RMS = 165.05447333128134; mitk::ImageStatisticsContainer::RealType expected_skewness = -0.004329226115093; mitk::ImageStatisticsContainer::RealType expected_standarddev = 41.508031351374242; mitk::ImageStatisticsContainer::RealType expected_variance = 1722.9166666666670; mitk::ImageStatisticsContainer::IndexType expected_minIndex; expected_minIndex.set_size(3); expected_minIndex[0] = 0; expected_minIndex[1] = 0; expected_minIndex[2] = 2; mitk::ImageStatisticsContainer::IndexType expected_maxIndex; expected_maxIndex.set_size(3); expected_maxIndex[0] = 0; expected_maxIndex[1] = 0; expected_maxIndex[2] = 1; mitk::ImageMaskGenerator::Pointer imgMask1 = mitk::ImageMaskGenerator::New(); imgMask1->SetInputImage(m_US4DCroppedImage); imgMask1->SetImageMask(m_US4DCroppedMultilabelMask); mitk::ImageStatisticsContainer::Pointer statisticsContainer; - CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_US4DCroppedImage, imgMask1.GetPointer(), nullptr, 1)); - auto statisticsObjectTimestep1 = statisticsContainer->GetStatisticsForTimeStep(1); + CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_US4DCroppedImage, imgMask1.GetPointer(), nullptr)); + auto statisticsObjectTimestep1 = statisticsContainer->GetStatistics(1, 1); VerifyStatistics(statisticsObjectTimestep1, expected_N, expected_mean, expected_MPP, expected_skewness, expected_kurtosis, expected_variance, expected_standarddev, expected_min, expected_max, expected_RMS, expected_minIndex, expected_maxIndex); } // T26098 histogram statistics need to be tested (median, uniformity, UPP, entropy) void mitkImageStatisticsCalculatorTestSuite::TestUS4DCroppedPlanarFigureTimeStep1() { - MITK_INFO << std::endl << "Test US4D cropped planar figure timestep 1:-----------------------------------------------------------------------------------"; + MITK_INFO << std::endl << "Test US4D cropped planar figure time step 1:-----------------------------------------------------------------------------------"; std::string US4DCroppedFile = this->GetTestDataFilePath("ImageStatisticsTestData/US4D_cropped.nrrd"); m_US4DCroppedImage = mitk::IOUtil::Load(US4DCroppedFile); CPPUNIT_ASSERT_MESSAGE("Failed loading US4D_cropped", m_US4DCroppedImage.IsNotNull()); std::string US4DCroppedPlanarFigureFile = this->GetTestDataFilePath("ImageStatisticsTestData/US4D_croppedPF.pf"); m_US4DCroppedPlanarFigure = mitk::IOUtil::Load(US4DCroppedPlanarFigureFile); CPPUNIT_ASSERT_MESSAGE("Failed loading US4D planar figure", m_US4DCroppedPlanarFigure.IsNotNull()); //calculated ground truth via script mitk::ImageStatisticsContainer::RealType expected_kurtosis = 1; mitk::ImageStatisticsContainer::RealType expected_MPP = 172.5; mitk::ImageStatisticsContainer::RealType expected_max = 197; mitk::ImageStatisticsContainer::RealType expected_mean = 172.5; mitk::ImageStatisticsContainer::RealType expected_min = 148; mitk::ImageStatisticsContainer::VoxelCountType expected_N = 2; mitk::ImageStatisticsContainer::RealType expected_RMS = 175.94530400098776; mitk::ImageStatisticsContainer::RealType expected_skewness = 0; mitk::ImageStatisticsContainer::RealType expected_standarddev = 34.648232278140831; mitk::ImageStatisticsContainer::RealType expected_variance = 1200.5000000000002; mitk::ImageStatisticsContainer::IndexType expected_minIndex; expected_minIndex.set_size(3); expected_minIndex[0] = 2; expected_minIndex[1] = 2; expected_minIndex[2] = 2; mitk::ImageStatisticsContainer::IndexType expected_maxIndex; expected_maxIndex.set_size(3); expected_maxIndex[0] = 2; expected_maxIndex[1] = 2; expected_maxIndex[2] = 1; mitk::PlanarFigureMaskGenerator::Pointer pfMaskGen = mitk::PlanarFigureMaskGenerator::New(); pfMaskGen->SetInputImage(m_US4DCroppedImage); pfMaskGen->SetPlanarFigure(m_US4DCroppedPlanarFigure); mitk::ImageStatisticsContainer::Pointer statisticsContainer; CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_US4DCroppedImage, pfMaskGen.GetPointer())); - auto statisticsObjectTimestep1 = statisticsContainer->GetStatisticsForTimeStep(1); + auto statisticsObjectTimestep1 = statisticsContainer->GetStatistics(1, 1); VerifyStatistics(statisticsObjectTimestep1, expected_N, expected_mean, expected_MPP, expected_skewness, expected_kurtosis, expected_variance, expected_standarddev, expected_min, expected_max, expected_RMS, expected_minIndex, expected_maxIndex); } void mitkImageStatisticsCalculatorTestSuite::TestUS4DCroppedAllTimesteps() { - MITK_INFO << std::endl << "Test US4D cropped all timesteps:-----------------------------------------------------------------------------------"; + MITK_INFO << std::endl << "Test US4D cropped all time steps:-----------------------------------------------------------------------------------"; std::string US4DCroppedFile = this->GetTestDataFilePath("ImageStatisticsTestData/US4D_cropped.nrrd"); m_US4DCroppedImage = mitk::IOUtil::Load(US4DCroppedFile); CPPUNIT_ASSERT_MESSAGE("Failed loading US4D_cropped", m_US4DCroppedImage.IsNotNull()); mitk::ImageStatisticsContainer::Pointer statisticsContainer=mitk::ImageStatisticsContainer::New(); CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_US4DCroppedImage)); for (int i = 0; i < 4; i++) { - CPPUNIT_ASSERT_MESSAGE("Error computing statistics for multiple timestep", statisticsContainer->TimeStepExists(i)); + CPPUNIT_ASSERT_MESSAGE("Error computing statistics for multiple time steps", statisticsContainer->StatisticsExist(mitk::ImageStatisticsContainer::NO_MASK_LABEL_VALUE, i)); } } void mitkImageStatisticsCalculatorTestSuite::TestUS4DCropped3DMask() { MITK_INFO << std::endl << "Test US4D cropped with 3D binary Mask:-----------------------------------------------------------------------------------"; std::string US4DCroppedFile = this->GetTestDataFilePath("ImageStatisticsTestData/US4D_cropped.nrrd"); m_US4DCroppedImage = mitk::IOUtil::Load(US4DCroppedFile); CPPUNIT_ASSERT_MESSAGE("Failed loading US4D_cropped", m_US4DCroppedImage.IsNotNull()); std::string US4DCropped3DBinMaskFile = this->GetTestDataFilePath("ImageStatisticsTestData/US4D_cropped3DBinMask.nrrd"); m_US4DCropped3DBinMask = mitk::IOUtil::Load(US4DCropped3DBinMaskFile); CPPUNIT_ASSERT_MESSAGE("Failed loading Pic3D binary mask", m_US4DCropped3DBinMask.IsNotNull()); //calculated ground truth via script mitk::ImageStatisticsContainer::RealType expected_kurtosis = 1; mitk::ImageStatisticsContainer::RealType expected_MPP = 198; mitk::ImageStatisticsContainer::RealType expected_max = 199; mitk::ImageStatisticsContainer::RealType expected_mean = 198; mitk::ImageStatisticsContainer::RealType expected_min = 197; mitk::ImageStatisticsContainer::VoxelCountType expected_N = 2; mitk::ImageStatisticsContainer::RealType expected_RMS = 198.00505044063902; mitk::ImageStatisticsContainer::RealType expected_skewness = 0; mitk::ImageStatisticsContainer::RealType expected_standarddev = 1.4142135623730951; mitk::ImageStatisticsContainer::RealType expected_variance = 2; mitk::ImageStatisticsContainer::IndexType expected_minIndex; expected_minIndex.set_size(3); expected_minIndex[0] = 1; expected_minIndex[1] = 2; expected_minIndex[2] = 1; mitk::ImageStatisticsContainer::IndexType expected_maxIndex; expected_maxIndex.set_size(3); expected_maxIndex[0] = 1; expected_maxIndex[1] = 1; expected_maxIndex[2] = 1; mitk::ImageMaskGenerator::Pointer imgMask1 = mitk::ImageMaskGenerator::New(); imgMask1->SetInputImage(m_US4DCroppedImage); imgMask1->SetImageMask(m_US4DCropped3DBinMask); mitk::ImageStatisticsContainer::Pointer statisticsContainer = mitk::ImageStatisticsContainer::New(); - CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_US4DCroppedImage, imgMask1.GetPointer(), nullptr, 1)); - auto statisticsObjectTimestep1 = statisticsContainer->GetStatisticsForTimeStep(1); + CPPUNIT_ASSERT_NO_THROW(statisticsContainer = ComputeStatistics(m_US4DCroppedImage, imgMask1.GetPointer(), nullptr)); + auto statisticsObjectTimestep1 = statisticsContainer->GetStatistics(1, 1); VerifyStatistics(statisticsObjectTimestep1, expected_N, expected_mean, expected_MPP, expected_skewness, expected_kurtosis, expected_variance, expected_standarddev, expected_min, expected_max, expected_RMS, expected_minIndex, expected_maxIndex); } mitk::PlanarPolygon::Pointer mitkImageStatisticsCalculatorTestSuite::GeneratePlanarPolygon(mitk::PlaneGeometry::Pointer geometry, std::vector points) { mitk::PlanarPolygon::Pointer figure = mitk::PlanarPolygon::New(); figure->SetPlaneGeometry(geometry); figure->PlaceFigure(points[0]); for (unsigned int i = 1; i < points.size(); i++) { figure->SetControlPoint(i, points[i], true); } return figure; } -const mitk::ImageStatisticsContainer::Pointer -mitkImageStatisticsCalculatorTestSuite::ComputeStatistics(mitk::Image::ConstPointer image, - mitk::MaskGenerator::Pointer maskGen, - mitk::MaskGenerator::Pointer secondardMaskGen, - unsigned short label) -{ - mitk::ImageStatisticsCalculator::Pointer imgStatCalc = mitk::ImageStatisticsCalculator::New(); - imgStatCalc->SetInputImage(image); - - if (maskGen.IsNotNull()) - { - imgStatCalc->SetMask(maskGen.GetPointer()); - if (secondardMaskGen.IsNotNull()) - { - imgStatCalc->SetSecondaryMask(secondardMaskGen.GetPointer()); - } - } - - return imgStatCalc->GetStatistics(label); -} - void mitkImageStatisticsCalculatorTestSuite::VerifyStatistics(mitk::ImageStatisticsContainer::ImageStatisticsObject stats, mitk::ImageStatisticsContainer::RealType testMean, mitk::ImageStatisticsContainer::RealType testSD, mitk::ImageStatisticsContainer::RealType testMedian) { mitk::ImageStatisticsContainer::RealType meanObject = 0; mitk::ImageStatisticsContainer::RealType standardDeviationObject = 0; mitk::ImageStatisticsContainer::RealType medianObject = 0; CPPUNIT_ASSERT_NO_THROW(meanObject = stats.GetValueConverted(mitk::ImageStatisticsConstants::MEAN())); CPPUNIT_ASSERT_NO_THROW(standardDeviationObject = stats.GetValueConverted(mitk::ImageStatisticsConstants::STANDARDDEVIATION())); CPPUNIT_ASSERT_NO_THROW(medianObject = stats.GetValueConverted(mitk::ImageStatisticsConstants::MEDIAN())); - CPPUNIT_ASSERT_MESSAGE("Calculated mean grayvalue is not equal to the desired value.", std::abs(meanObject - testMean) < mitk::eps); - CPPUNIT_ASSERT_MESSAGE("Calculated grayvalue sd is not equal to the desired value.", std::abs(standardDeviationObject - testSD) < mitk::eps); - CPPUNIT_ASSERT_MESSAGE("Calculated median grayvalue is not equal to the desired value.", std::abs(medianObject - testMedian) < mitk::eps); + CPPUNIT_ASSERT_MESSAGE("Calculated mean gray value is not equal to the desired value.", std::abs(meanObject - testMean) < mitk::eps); + CPPUNIT_ASSERT_MESSAGE("Calculated gray value sd is not equal to the desired value.", std::abs(standardDeviationObject - testSD) < mitk::eps); + CPPUNIT_ASSERT_MESSAGE("Calculated median gray value is not equal to the desired value.", std::abs(medianObject - testMedian) < mitk::eps); } // T26098 histogram statistics need to be tested (median, uniformity, UPP, entropy) void mitkImageStatisticsCalculatorTestSuite::VerifyStatistics(mitk::ImageStatisticsContainer::ImageStatisticsObject stats, mitk::ImageStatisticsContainer::VoxelCountType N, mitk::ImageStatisticsContainer::RealType mean, mitk::ImageStatisticsContainer::RealType MPP, mitk::ImageStatisticsContainer::RealType skewness, mitk::ImageStatisticsContainer::RealType kurtosis, mitk::ImageStatisticsContainer::RealType variance, mitk::ImageStatisticsContainer::RealType stdev, mitk::ImageStatisticsContainer::RealType min, mitk::ImageStatisticsContainer::RealType max, mitk::ImageStatisticsContainer::RealType RMS, mitk::ImageStatisticsContainer::IndexType minIndex, mitk::ImageStatisticsContainer::IndexType maxIndex) { mitk::ImageStatisticsContainer::VoxelCountType numberOfVoxelsObject; mitk::ImageStatisticsContainer::RealType meanObject = 0; mitk::ImageStatisticsContainer::RealType mppObject = 0; mitk::ImageStatisticsContainer::RealType skewnessObject = 0; mitk::ImageStatisticsContainer::RealType kurtosisObject = 0; mitk::ImageStatisticsContainer::RealType varianceObject = 0; mitk::ImageStatisticsContainer::RealType standardDeviationObject = 0; mitk::ImageStatisticsContainer::RealType minObject = 0; mitk::ImageStatisticsContainer::RealType maxObject = 0; mitk::ImageStatisticsContainer::RealType rmsObject = 0; mitk::ImageStatisticsContainer::IndexType minIndexObject(3,0); mitk::ImageStatisticsContainer::IndexType maxIndexObject(3,0); CPPUNIT_ASSERT_NO_THROW(numberOfVoxelsObject = stats.GetValueConverted(mitk::ImageStatisticsConstants::NUMBEROFVOXELS())); CPPUNIT_ASSERT_NO_THROW(meanObject = stats.GetValueConverted(mitk::ImageStatisticsConstants::MEAN())); CPPUNIT_ASSERT_NO_THROW(mppObject = stats.GetValueConverted(mitk::ImageStatisticsConstants::MPP())); CPPUNIT_ASSERT_NO_THROW(skewnessObject = stats.GetValueConverted(mitk::ImageStatisticsConstants::SKEWNESS())); CPPUNIT_ASSERT_NO_THROW(kurtosisObject = stats.GetValueConverted(mitk::ImageStatisticsConstants::KURTOSIS())); CPPUNIT_ASSERT_NO_THROW(varianceObject = stats.GetValueConverted(mitk::ImageStatisticsConstants::VARIANCE())); - if (std::abs(varianceObject - variance) >= mitk::eps) - MITK_INFO << "xxx"; CPPUNIT_ASSERT_NO_THROW(standardDeviationObject = stats.GetValueConverted(mitk::ImageStatisticsConstants::STANDARDDEVIATION())); CPPUNIT_ASSERT_NO_THROW(minObject = stats.GetValueConverted(mitk::ImageStatisticsConstants::MINIMUM())); CPPUNIT_ASSERT_NO_THROW(maxObject = stats.GetValueConverted(mitk::ImageStatisticsConstants::MAXIMUM())); CPPUNIT_ASSERT_NO_THROW(rmsObject = stats.GetValueConverted(mitk::ImageStatisticsConstants::RMS())); CPPUNIT_ASSERT_NO_THROW(minIndexObject = stats.GetValueConverted(mitk::ImageStatisticsConstants::MINIMUMPOSITION())); CPPUNIT_ASSERT_NO_THROW(maxIndexObject = stats.GetValueConverted(mitk::ImageStatisticsConstants::MAXIMUMPOSITION())); CPPUNIT_ASSERT_MESSAGE("Calculated value does not fit expected value", numberOfVoxelsObject - N == 0); CPPUNIT_ASSERT_MESSAGE("Calculated value does not fit expected value", std::abs(meanObject - mean) < mitk::eps); - // in three test cases MPP is None because the roi has no positive pixels + // in three test cases MPP is None because the ROI has no positive pixels if (!std::isnan(mppObject)) { CPPUNIT_ASSERT_MESSAGE("Calculated value does not fit expected value", std::abs(mppObject - MPP) < mitk::eps); } CPPUNIT_ASSERT_MESSAGE("Calculated value does not fit expected value", std::abs(skewnessObject - skewness) < mitk::eps); CPPUNIT_ASSERT_MESSAGE("Calculated value does not fit expected value", std::abs(kurtosisObject - kurtosis) < mitk::eps); CPPUNIT_ASSERT_MESSAGE("Calculated value does not fit expected value", std::abs(varianceObject - variance) < mitk::eps); CPPUNIT_ASSERT_MESSAGE("Calculated value does not fit expected value", std::abs(standardDeviationObject - stdev) < mitk::eps); CPPUNIT_ASSERT_MESSAGE("Calculated value does not fit expected value", std::abs(minObject - min) < mitk::eps); CPPUNIT_ASSERT_MESSAGE("Calculated value does not fit expected value", std::abs(maxObject - max) < mitk::eps); CPPUNIT_ASSERT_MESSAGE("Calculated value does not fit expected value", std::abs(rmsObject - RMS) < mitk::eps); for (unsigned int i = 0; i < minIndex.size(); ++i) { CPPUNIT_ASSERT_MESSAGE("Calculated value does not fit expected value", std::abs(minIndexObject[i] - minIndex[i]) < mitk::eps); } for (unsigned int i = 0; i < maxIndex.size(); ++i) { CPPUNIT_ASSERT_MESSAGE("Calculated value does not fit expected value", std::abs(maxIndexObject[i] - maxIndex[i]) < mitk::eps); } } MITK_TEST_SUITE_REGISTRATION(mitkImageStatisticsCalculator) diff --git a/Modules/ImageStatistics/Testing/mitkImageStatisticsContainerTest.cpp b/Modules/ImageStatistics/Testing/mitkImageStatisticsContainerTest.cpp index c81d04373a..886f09458e 100644 --- a/Modules/ImageStatistics/Testing/mitkImageStatisticsContainerTest.cpp +++ b/Modules/ImageStatistics/Testing/mitkImageStatisticsContainerTest.cpp @@ -1,378 +1,365 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // Testing #include "mitkTestingMacros.h" #include "mitkTestFixture.h" //MITK includes #include "mitkArbitraryTimeGeometry.h" #include "mitkImageStatisticsContainerNodeHelper.h" #include "mitkImageStatisticsContainerManager.h" #include "mitkImageStatisticsContainer.h" class mitkImageStatisticsContainerTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkImageStatisticsContainerTestSuite); MITK_TEST(StatisticNamesIO); MITK_TEST(InvalidKey); MITK_TEST(TimeSteps); MITK_TEST(PrintSelf); MITK_TEST(InternalClone); MITK_TEST(StatisticNames); MITK_TEST(OverwriteStatistic); MITK_TEST(AllStatisticNamesForContainer); MITK_TEST(Reset); CPPUNIT_TEST_SUITE_END(); private: mitk::ImageStatisticsContainer::Pointer m_StatisticsContainer; mitk::ImageStatisticsContainer::Pointer m_StatisticsContainer2; mitk::ImageStatisticsContainer::Pointer m_StatisticsContainer3; mitk::ImageStatisticsContainer::ImageStatisticsObject m_StatisticsObject; mitk::ImageStatisticsContainer::ImageStatisticsObject m_StatisticsObject2; mitk::ImageStatisticsContainer::ImageStatisticsObject m_StatisticsObject3; mitk::ArbitraryTimeGeometry::Pointer m_TimeGeometry; mitk::Geometry3D::Pointer m_Geometry1; mitk::Geometry3D::Pointer m_Geometry2; mitk::Geometry3D::Pointer m_Geometry3; mitk::Geometry3D::Pointer m_Geometry3_5; mitk::Geometry3D::Pointer m_Geometry4; mitk::Geometry3D::Pointer m_Geometry5; mitk::TimePointType m_Geometry1MinTP; mitk::TimePointType m_Geometry2MinTP; mitk::TimePointType m_Geometry3MinTP; mitk::TimePointType m_Geometry3_5MinTP; mitk::TimePointType m_Geometry4MinTP; mitk::TimePointType m_Geometry5MinTP; mitk::TimePointType m_Geometry1MaxTP; mitk::TimePointType m_Geometry2MaxTP; mitk::TimePointType m_Geometry3MaxTP; mitk::TimePointType m_Geometry3_5MaxTP; mitk::TimePointType m_Geometry4MaxTP; mitk::TimePointType m_Geometry5MaxTP; std::vector estimatedDefaultStatisticNames { "Mean", "Median", "StandardDeviation", "RMS", "Max", "MaxPosition", "Min", "MinPosition", "#Voxel", "Volume [mm^3]", "Skewness", "Kurtosis", "Uniformity", "Entropy", "MPP", "UPP" }; public: void setUp() override { m_StatisticsContainer = mitk::ImageStatisticsContainer::New(); m_StatisticsContainer2 = mitk::ImageStatisticsContainer::New(); m_StatisticsContainer3 = mitk::ImageStatisticsContainer::New(); m_Geometry1 = mitk::Geometry3D::New(); m_Geometry2 = mitk::Geometry3D::New(); m_Geometry3 = mitk::Geometry3D::New(); m_Geometry3_5 = mitk::Geometry3D::New(); m_Geometry4 = mitk::Geometry3D::New(); m_Geometry5 = mitk::Geometry3D::New(); m_Geometry1MinTP = 1; m_Geometry2MinTP = 2; m_Geometry3MinTP = 3; m_Geometry3_5MinTP = 3.5; m_Geometry4MinTP = 4; m_Geometry5MinTP = 5; m_Geometry1MaxTP = 1.9; m_Geometry2MaxTP = 2.9; m_Geometry3MaxTP = 3.9; m_Geometry3_5MaxTP = 3.9; m_Geometry4MaxTP = 4.9; m_Geometry5MaxTP = 5.9; m_TimeGeometry = mitk::ArbitraryTimeGeometry::New(); m_TimeGeometry->ClearAllGeometries(); m_TimeGeometry->AppendNewTimeStep(m_Geometry1, m_Geometry1MinTP, m_Geometry1MaxTP); m_TimeGeometry->AppendNewTimeStep(m_Geometry2, m_Geometry2MinTP, m_Geometry2MaxTP); m_TimeGeometry->AppendNewTimeStep(m_Geometry3, m_Geometry3MinTP, m_Geometry3MaxTP); m_TimeGeometry->AppendNewTimeStep(m_Geometry4, m_Geometry4MinTP, m_Geometry4MaxTP); m_TimeGeometry->AppendNewTimeStep(m_Geometry5, m_Geometry5MinTP, m_Geometry5MaxTP); } void tearDown() override { m_StatisticsContainer->Reset(); m_StatisticsContainer2->Reset(); m_StatisticsContainer3->Reset(); m_StatisticsObject.Reset(); m_StatisticsObject2.Reset(); m_StatisticsObject3.Reset(); m_TimeGeometry->ClearAllGeometries(); } void StatisticNamesIO() { auto defaultStatisticNames = mitk::ImageStatisticsContainer::ImageStatisticsObject::GetDefaultStatisticNames(); for (size_t i = 0; i < estimatedDefaultStatisticNames.size(); i++) { CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated default statistics names are not correct.", defaultStatisticNames.at(i), estimatedDefaultStatisticNames.at(i)); } std::string testName = "testName"; double realTypeTest = 3.14; m_StatisticsObject.AddStatistic(testName, realTypeTest); auto customStatisticNames = m_StatisticsObject.GetCustomStatisticNames(); size_t one = 1; CPPUNIT_ASSERT_EQUAL_MESSAGE("Amount of estimated custom statistics names is not correct.", customStatisticNames.size(), one); CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated custom statistics names are not correct.", customStatisticNames.front(), testName); auto allStatisticNames = m_StatisticsObject.GetAllStatisticNames(); estimatedDefaultStatisticNames.push_back(testName); for (size_t i = 0; i < estimatedDefaultStatisticNames.size(); i++) { CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated statistics names are not correct.", allStatisticNames.at(i), estimatedDefaultStatisticNames.at(i)); } auto existingStatisticNames = m_StatisticsObject.GetExistingStatisticNames(); CPPUNIT_ASSERT_EQUAL_MESSAGE("Amount of estimated existing statistics names is not correct.", existingStatisticNames.size(), one); CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated existing statistics names are not correct.", existingStatisticNames.front(), testName); m_StatisticsObject.Reset(); CPPUNIT_ASSERT_MESSAGE("Custom statistics names were not removed correctly.", m_StatisticsObject.GetCustomStatisticNames().empty()); } void InvalidKey() { CPPUNIT_ASSERT_THROW_MESSAGE("Exception should have been thrown because key does not exists.", m_StatisticsObject.GetValueNonConverted("Test"), mitk::Exception); } void TimeSteps() { m_StatisticsContainer->SetTimeGeometry(m_TimeGeometry); - m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->TimeStepExists(0), true); - m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->TimeStepExists(1), true); - m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->TimeStepExists(2), true); - m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->TimeStepExists(3), true); - m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->TimeStepExists(4), true); - - CPPUNIT_ASSERT_THROW_MESSAGE("Out of timeStep geometry bounds timeStep was added but no exception was thrown.", m_StatisticsContainer->SetStatisticsForTimeStep(42, m_StatisticsObject), mitk::Exception); - - CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistics container does not contain the right amount of timeSteps.", static_cast (m_StatisticsContainer->GetNumberOfTimeSteps()), 5); - - CPPUNIT_ASSERT_THROW_MESSAGE("A statistic for a non existing time steps was found.", m_StatisticsContainer->GetStatisticsForTimeStep(42), mitk::Exception); + m_StatisticsContainer->SetStatistics(1,0, m_StatisticsObject); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->StatisticsExist(1, 0), true); + m_StatisticsContainer->SetStatistics(1,1, m_StatisticsObject); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->StatisticsExist(1, 1), true); + m_StatisticsContainer->SetStatistics(1,2, m_StatisticsObject); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->StatisticsExist(1, 2), true); + m_StatisticsContainer->SetStatistics(1,3, m_StatisticsObject); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->StatisticsExist(1, 3), true); + m_StatisticsContainer->SetStatistics(1,4, m_StatisticsObject); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->StatisticsExist(1, 4), true); + + CPPUNIT_ASSERT_THROW_MESSAGE("Out of timeStep geometry bounds timeStep was added but no exception was thrown.", m_StatisticsContainer->SetStatistics(1,42, m_StatisticsObject), mitk::Exception); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistics container does not contain the right amount of timeSteps.", static_cast (m_StatisticsContainer->GetExistingTimeSteps(1).size()), 5); + + CPPUNIT_ASSERT_THROW_MESSAGE("A statistic for a non existing time steps was found.", m_StatisticsContainer->GetStatistics(1, 42), mitk::Exception); } void PrintSelf() { std::stringstream print; // Check print function for empty container CPPUNIT_ASSERT_NO_THROW_MESSAGE("Print function throws an exception.", m_StatisticsContainer->Print(print)); m_StatisticsContainer->SetTimeGeometry(m_TimeGeometry); m_StatisticsObject.AddStatistic("Test", 4.2); - m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,0, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,1, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,2, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,3, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,4, m_StatisticsObject); // Check print function for filled container CPPUNIT_ASSERT_NO_THROW_MESSAGE("Print function throws an exception.", m_StatisticsContainer->Print(print)); } void InternalClone() { m_StatisticsContainer->SetTimeGeometry(m_TimeGeometry); m_StatisticsObject.AddStatistic("Test", 4.2); - m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,0, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,1, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,2, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,3, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,4, m_StatisticsObject); auto clone = m_StatisticsContainer->Clone(); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", m_StatisticsContainer->GetNumberOfTimeSteps(), clone->GetNumberOfTimeSteps()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", m_StatisticsContainer->GetExistingTimeSteps(1).size(), clone->GetExistingTimeSteps(1).size()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->TimeStepExists(0), true); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->TimeStepExists(1), true); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->TimeStepExists(2), true); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->TimeStepExists(3), true); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->TimeStepExists(4), true); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->StatisticsExist(1, 0), true); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->StatisticsExist(1, 1), true); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->StatisticsExist(1, 2), true); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->StatisticsExist(1, 3), true); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->StatisticsExist(1, 4), true); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->GetStatisticsForTimeStep(0).HasStatistic("Test"), true); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->GetStatisticsForTimeStep(1).HasStatistic("Test"), true); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->GetStatisticsForTimeStep(2).HasStatistic("Test"), true); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->GetStatisticsForTimeStep(3).HasStatistic("Test"), true); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->GetStatisticsForTimeStep(4).HasStatistic("Test"), true); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->GetStatistics(1,0).HasStatistic("Test"), true); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->GetStatistics(1,1).HasStatistic("Test"), true); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->GetStatistics(1,2).HasStatistic("Test"), true); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->GetStatistics(1,3).HasStatistic("Test"), true); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", clone->GetStatistics(1,4).HasStatistic("Test"), true); } void StatisticNames() { m_StatisticsContainer->SetTimeGeometry(m_TimeGeometry); m_StatisticsContainer2->SetTimeGeometry(m_TimeGeometry); m_StatisticsContainer3->SetTimeGeometry(m_TimeGeometry); m_StatisticsObject.AddStatistic("Test", 4.2); m_StatisticsObject2.AddStatistic("Test2", 4.2); m_StatisticsObject3.AddStatistic("Test3", 4.2); // Setting the same statistics for different time steps will only add the statistics name once. - m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,0, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,1, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,2, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,3, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,4, m_StatisticsObject); // Setting the same statistics for different time steps will only add the statistics name once. - m_StatisticsContainer2->SetStatisticsForTimeStep(0, m_StatisticsObject2); - m_StatisticsContainer2->SetStatisticsForTimeStep(1, m_StatisticsObject2); - m_StatisticsContainer2->SetStatisticsForTimeStep(2, m_StatisticsObject2); - m_StatisticsContainer2->SetStatisticsForTimeStep(3, m_StatisticsObject2); - m_StatisticsContainer2->SetStatisticsForTimeStep(4, m_StatisticsObject2); + m_StatisticsContainer2->SetStatistics(1,0, m_StatisticsObject2); + m_StatisticsContainer2->SetStatistics(1,1, m_StatisticsObject2); + m_StatisticsContainer2->SetStatistics(1,2, m_StatisticsObject2); + m_StatisticsContainer2->SetStatistics(1,3, m_StatisticsObject2); + m_StatisticsContainer2->SetStatistics(1,4, m_StatisticsObject2); // Setting the same statistics for different time steps will only add the statistics name once. - m_StatisticsContainer3->SetStatisticsForTimeStep(0, m_StatisticsObject3); - m_StatisticsContainer3->SetStatisticsForTimeStep(1, m_StatisticsObject3); - m_StatisticsContainer3->SetStatisticsForTimeStep(2, m_StatisticsObject3); - m_StatisticsContainer3->SetStatisticsForTimeStep(3, m_StatisticsObject3); - m_StatisticsContainer3->SetStatisticsForTimeStep(4, m_StatisticsObject3); + m_StatisticsContainer3->SetStatistics(1,0, m_StatisticsObject3); + m_StatisticsContainer3->SetStatistics(1,1, m_StatisticsObject3); + m_StatisticsContainer3->SetStatistics(1,2, m_StatisticsObject3); + m_StatisticsContainer3->SetStatistics(1,3, m_StatisticsObject3); + m_StatisticsContainer3->SetStatistics(1,4, m_StatisticsObject3); CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated statistics names are not correct.", mitk::GetAllStatisticNames(m_StatisticsContainer).size(), estimatedDefaultStatisticNames.size() + 1); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Custom statistic name was not saved correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(0).HasStatistic("Test"), true); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Custom statistic name was not saved correctly.", m_StatisticsContainer->GetStatistics(1,0).HasStatistic("Test"), true); std::vector containers; containers.push_back(m_StatisticsContainer2.GetPointer()); containers.push_back(m_StatisticsContainer3.GetPointer()); CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated statistics names are not correct.", mitk::GetAllStatisticNames(containers).size(), estimatedDefaultStatisticNames.size() + 2); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Custom statistic name was not saved correctly.", m_StatisticsContainer2->GetStatisticsForTimeStep(0).HasStatistic("Test2"), true); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Custom statistic name was not saved correctly.", m_StatisticsContainer3->GetStatisticsForTimeStep(0).HasStatistic("Test3"), true); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Custom statistic name was not saved correctly.", m_StatisticsContainer2->GetStatistics(1,0).HasStatistic("Test2"), true); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Custom statistic name was not saved correctly.", m_StatisticsContainer3->GetStatistics(1,0).HasStatistic("Test3"), true); } void OverwriteStatistic() { m_StatisticsContainer->SetTimeGeometry(m_TimeGeometry); m_StatisticsObject.AddStatistic("Test", 4.2); - m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,0, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,1, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,2, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,3, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,4, m_StatisticsObject); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic was not correctly added to StatisticsObject.", boost::get (m_StatisticsContainer->GetStatisticsForTimeStep(0).GetValueNonConverted("Test")), 4.2); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic was not correctly added to StatisticsObject.", boost::get (m_StatisticsContainer->GetStatistics(1,0).GetValueNonConverted("Test")), 4.2); // An existing statistic won't be updated by adding another statistic with same name to that object. m_StatisticsObject.AddStatistic("Test", 42.0); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic was overwritten.", boost::get(m_StatisticsContainer->GetStatisticsForTimeStep(0).GetValueNonConverted("Test")), 4.2); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic was overwritten.", boost::get(m_StatisticsContainer->GetStatistics(1,0).GetValueNonConverted("Test")), 4.2); } void AllStatisticNamesForContainer() { m_StatisticsContainer->SetTimeGeometry(m_TimeGeometry); m_StatisticsObject.AddStatistic("Test", 4.2); m_StatisticsObject2.AddStatistic("Test2", 4.2); // Setting the same statistics for different time steps will only add the statistics name once. - m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject2); - m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject2); - m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,0, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,1, m_StatisticsObject2); + m_StatisticsContainer->SetStatistics(1,2, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,3, m_StatisticsObject2); + m_StatisticsContainer->SetStatistics(1,4, m_StatisticsObject); std::vector containers; // Check if empty vector triggers exception. CPPUNIT_ASSERT_NO_THROW_MESSAGE("Empty vector triggered an exception.", mitk::GetAllStatisticNames(containers)); containers.push_back(m_StatisticsContainer2.GetPointer()); containers.push_back(m_StatisticsContainer3.GetPointer()); // Check if vector with empty container triggers exception. CPPUNIT_ASSERT_NO_THROW_MESSAGE("Empty container triggered an exception.", mitk::GetAllStatisticNames(containers)); // Adding filled container to check if data was saved correctly. containers.push_back(m_StatisticsContainer.GetPointer()); CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated statistics names are not correct.", mitk::GetAllStatisticNames(containers).size(), estimatedDefaultStatisticNames.size() + 2); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Custom statistic name was not saved correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(0).HasStatistic("Test"), true); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Custom statistic name was not saved correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(1).HasStatistic("Test2"), true); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Custom statistic name was not saved correctly.", m_StatisticsContainer->GetStatistics(1,0).HasStatistic("Test"), true); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Custom statistic name was not saved correctly.", m_StatisticsContainer->GetStatistics(1,1).HasStatistic("Test2"), true); } void Reset() { m_StatisticsContainer->SetTimeGeometry(m_TimeGeometry); m_StatisticsObject.AddStatistic("Test", 4.2); - m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject); - m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,0, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,1, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,2, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,3, m_StatisticsObject); + m_StatisticsContainer->SetStatistics(1,4, m_StatisticsObject); m_StatisticsContainer->Reset(); m_StatisticsObject.Reset(); - m_TimeGeometry->ClearAllGeometries(); - - CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(0).GetExistingStatisticNames().size(), size_t()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(0).GetCustomStatisticNames().size(), size_t()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(1).GetExistingStatisticNames().size(), size_t()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(1).GetCustomStatisticNames().size(), size_t()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(2).GetExistingStatisticNames().size(), size_t()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(2).GetCustomStatisticNames().size(), size_t()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(3).GetExistingStatisticNames().size(), size_t()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(3).GetCustomStatisticNames().size(), size_t()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(4).GetExistingStatisticNames().size(), size_t()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(4).GetCustomStatisticNames().size(), size_t()); + CPPUNIT_ASSERT_MESSAGE("Statistics container was reseted correctly.", m_StatisticsContainer->GetExistingLabelValues(false).empty()); CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic was not deleted correctly.", m_StatisticsObject.HasStatistic("Test"), false); - - CPPUNIT_ASSERT_EQUAL_MESSAGE("Time geometry was not cleared correctly.", m_TimeGeometry->IsValid(), false); } }; MITK_TEST_SUITE_REGISTRATION(mitkImageStatisticsContainer) diff --git a/Modules/ImageStatistics/mitkImageStatisticsCalculator.cpp b/Modules/ImageStatistics/mitkImageStatisticsCalculator.cpp index 6c3f8d916b..25031da9b4 100644 --- a/Modules/ImageStatistics/mitkImageStatisticsCalculator.cpp +++ b/Modules/ImageStatistics/mitkImageStatisticsCalculator.cpp @@ -1,550 +1,510 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkImageStatisticsCalculator.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace mitk { void ImageStatisticsCalculator::SetInputImage(const mitk::Image *image) { if (image != m_Image) { m_Image = image; this->Modified(); } } void ImageStatisticsCalculator::SetMask(mitk::MaskGenerator *mask) { if (mask != m_MaskGenerator) { m_MaskGenerator = mask; this->Modified(); } } void ImageStatisticsCalculator::SetSecondaryMask(mitk::MaskGenerator *mask) { if (mask != m_SecondaryMaskGenerator) { m_SecondaryMaskGenerator = mask; this->Modified(); } } void ImageStatisticsCalculator::SetNBinsForHistogramStatistics(unsigned int nBins) { if (nBins != m_nBinsForHistogramStatistics) { m_nBinsForHistogramStatistics = nBins; this->Modified(); this->m_UseBinSizeOverNBins = false; } if (m_UseBinSizeOverNBins) { this->Modified(); this->m_UseBinSizeOverNBins = false; } } unsigned int ImageStatisticsCalculator::GetNBinsForHistogramStatistics() const { return m_nBinsForHistogramStatistics; } void ImageStatisticsCalculator::SetBinSizeForHistogramStatistics(double binSize) { if (binSize != m_binSizeForHistogramStatistics) { m_binSizeForHistogramStatistics = binSize; this->Modified(); this->m_UseBinSizeOverNBins = true; } if (!m_UseBinSizeOverNBins) { this->Modified(); this->m_UseBinSizeOverNBins = true; } } double ImageStatisticsCalculator::GetBinSizeForHistogramStatistics() const { return m_binSizeForHistogramStatistics; } - mitk::ImageStatisticsContainer* ImageStatisticsCalculator::GetStatistics(LabelIndex label) + mitk::ImageStatisticsContainer* ImageStatisticsCalculator::GetStatistics() { if (m_Image.IsNull()) { mitkThrow() << "no image"; } if (!m_Image->IsInitialized()) { mitkThrow() << "Image not initialized!"; } - if (IsUpdateRequired(label)) + if (IsUpdateRequired()) { auto timeGeometry = m_Image->GetTimeGeometry(); + m_StatisticContainer = ImageStatisticsContainer::New(); + m_StatisticContainer->SetTimeGeometry(timeGeometry->Clone()); + // always compute statistics on all timesteps for (unsigned int timeStep = 0; timeStep < m_Image->GetTimeSteps(); timeStep++) { if (m_MaskGenerator.IsNotNull()) { m_MaskGenerator->SetTimeStep(timeStep); - //See T25625: otherwise, the mask is not computed again after setting a different time step - m_MaskGenerator->Modified(); m_InternalMask = m_MaskGenerator->GetMask(); if (m_MaskGenerator->GetReferenceImage().IsNotNull()) { m_InternalImageForStatistics = m_MaskGenerator->GetReferenceImage(); } else { m_InternalImageForStatistics = m_Image; } } else { m_InternalImageForStatistics = m_Image; } if (m_SecondaryMaskGenerator.IsNotNull()) { m_SecondaryMaskGenerator->SetTimeStep(timeStep); m_SecondaryMask = m_SecondaryMaskGenerator->GetMask(); } ImageTimeSelector::Pointer imgTimeSel = ImageTimeSelector::New(); imgTimeSel->SetInput(m_InternalImageForStatistics); imgTimeSel->SetTimeNr(timeStep); imgTimeSel->UpdateLargestPossibleRegion(); imgTimeSel->Update(); m_ImageTimeSlice = imgTimeSel->GetOutput(); // Calculate statistics with/without mask if (m_MaskGenerator.IsNull() && m_SecondaryMaskGenerator.IsNull()) { // 1) calculate statistics unmasked: AccessByItk_2(m_ImageTimeSlice, InternalCalculateStatisticsUnmasked, timeGeometry, timeStep) } else { // 2) calculate statistics masked AccessByItk_2(m_ImageTimeSlice, InternalCalculateStatisticsMasked, timeGeometry, timeStep) } } } - auto it = m_StatisticContainers.find(label); - if (it != m_StatisticContainers.end()) - { - return (it->second).GetPointer(); - } - else - { - mitkThrow() << "unknown label"; - return nullptr; - } + return m_StatisticContainer; } template void ImageStatisticsCalculator::InternalCalculateStatisticsUnmasked( typename itk::Image *image, const TimeGeometry *timeGeometry, TimeStepType timeStep) { typedef typename itk::Image ImageType; typedef typename mitk::StatisticsImageFilter ImageStatisticsFilterType; typedef typename itk::MinMaxImageFilterWithIndex MinMaxFilterType; - // reset statistics container if exists - ImageStatisticsContainer::Pointer statisticContainerForImage; - LabelIndex labelNoMask = 1; - auto it = m_StatisticContainers.find(labelNoMask); - if (it != m_StatisticContainers.end()) - { - statisticContainerForImage = it->second; - } - else - { - statisticContainerForImage = ImageStatisticsContainer::New(); - statisticContainerForImage->SetTimeGeometry(const_cast(timeGeometry)); - m_StatisticContainers.emplace(labelNoMask, statisticContainerForImage); - } - auto statObj = ImageStatisticsContainer::ImageStatisticsObject(); typename ImageStatisticsFilterType::Pointer statisticsFilter = ImageStatisticsFilterType::New(); statisticsFilter->SetInput(image); statisticsFilter->SetCoordinateTolerance(0.001); statisticsFilter->SetDirectionTolerance(0.001); // TODO: this is single threaded. Implement our own image filter that does this multi threaded // typename itk::MinimumMaximumImageCalculator::Pointer imgMinMaxFilter = // itk::MinimumMaximumImageCalculator::New(); imgMinMaxFilter->SetImage(image); // imgMinMaxFilter->Compute(); vnl_vector minIndex, maxIndex; typename MinMaxFilterType::Pointer minMaxFilter = MinMaxFilterType::New(); minMaxFilter->SetInput(image); minMaxFilter->UpdateLargestPossibleRegion(); typename ImageType::PixelType minval = minMaxFilter->GetMin(); typename ImageType::PixelType maxval = minMaxFilter->GetMax(); typename ImageType::IndexType tmpMinIndex = minMaxFilter->GetMinIndex(); typename ImageType::IndexType tmpMaxIndex = minMaxFilter->GetMaxIndex(); // typename ImageType::IndexType tmpMinIndex = imgMinMaxFilter->GetIndexOfMinimum(); // typename ImageType::IndexType tmpMaxIndex = imgMinMaxFilter->GetIndexOfMaximum(); minIndex.set_size(tmpMaxIndex.GetIndexDimension()); maxIndex.set_size(tmpMaxIndex.GetIndexDimension()); for (unsigned int i = 0; i < tmpMaxIndex.GetIndexDimension(); i++) { minIndex[i] = tmpMinIndex[i]; maxIndex[i] = tmpMaxIndex[i]; } statObj.AddStatistic(mitk::ImageStatisticsConstants::MINIMUMPOSITION(), minIndex); statObj.AddStatistic(mitk::ImageStatisticsConstants::MAXIMUMPOSITION(), maxIndex); // convert m_binSize in m_nBins if necessary unsigned int nBinsForHistogram; if (m_UseBinSizeOverNBins) { nBinsForHistogram = std::max(static_cast(std::ceil(maxval - minval)) / m_binSizeForHistogramStatistics, 10.); // do not allow less than 10 bins } else { nBinsForHistogram = m_nBinsForHistogramStatistics; } statisticsFilter->SetHistogramParameters(nBinsForHistogram, minval, maxval); try { statisticsFilter->Update(); } catch (const itk::ExceptionObject &e) { mitkThrow() << "Image statistics calculation failed due to following ITK Exception: \n " << e.what(); } auto voxelVolume = GetVoxelVolume(image); auto numberOfPixels = image->GetLargestPossibleRegion().GetNumberOfPixels(); auto volume = static_cast(numberOfPixels) * voxelVolume; auto variance = statisticsFilter->GetSigma() * statisticsFilter->GetSigma(); auto rms = std::sqrt(std::pow(statisticsFilter->GetMean(), 2.) + statisticsFilter->GetVariance()); // variance = sigma^2 - statObj.AddStatistic(mitk::ImageStatisticsConstants::NUMBEROFVOXELS(), + statObj.AddStatistic(ImageStatisticsConstants::NUMBEROFVOXELS(), static_cast(numberOfPixels)); - statObj.AddStatistic(mitk::ImageStatisticsConstants::VOLUME(), volume); - statObj.AddStatistic(mitk::ImageStatisticsConstants::MEAN(), statisticsFilter->GetMean()); - statObj.AddStatistic(mitk::ImageStatisticsConstants::MINIMUM(), + statObj.AddStatistic(ImageStatisticsConstants::VOLUME(), volume); + statObj.AddStatistic(ImageStatisticsConstants::MEAN(), statisticsFilter->GetMean()); + statObj.AddStatistic(ImageStatisticsConstants::MINIMUM(), static_cast(statisticsFilter->GetMinimum())); - statObj.AddStatistic(mitk::ImageStatisticsConstants::MAXIMUM(), + statObj.AddStatistic(ImageStatisticsConstants::MAXIMUM(), static_cast(statisticsFilter->GetMaximum())); - statObj.AddStatistic(mitk::ImageStatisticsConstants::STANDARDDEVIATION(), statisticsFilter->GetSigma()); - statObj.AddStatistic(mitk::ImageStatisticsConstants::VARIANCE(), variance); - statObj.AddStatistic(mitk::ImageStatisticsConstants::SKEWNESS(), statisticsFilter->GetSkewness()); - statObj.AddStatistic(mitk::ImageStatisticsConstants::KURTOSIS(), statisticsFilter->GetKurtosis()); - statObj.AddStatistic(mitk::ImageStatisticsConstants::RMS(), rms); - statObj.AddStatistic(mitk::ImageStatisticsConstants::MPP(), statisticsFilter->GetMPP()); - statObj.AddStatistic(mitk::ImageStatisticsConstants::ENTROPY(), statisticsFilter->GetEntropy()); - statObj.AddStatistic(mitk::ImageStatisticsConstants::MEDIAN(), statisticsFilter->GetMedian()); - statObj.AddStatistic(mitk::ImageStatisticsConstants::UNIFORMITY(), statisticsFilter->GetUniformity()); - statObj.AddStatistic(mitk::ImageStatisticsConstants::UPP(), statisticsFilter->GetUPP()); + statObj.AddStatistic(ImageStatisticsConstants::STANDARDDEVIATION(), statisticsFilter->GetSigma()); + statObj.AddStatistic(ImageStatisticsConstants::VARIANCE(), variance); + statObj.AddStatistic(ImageStatisticsConstants::SKEWNESS(), statisticsFilter->GetSkewness()); + statObj.AddStatistic(ImageStatisticsConstants::KURTOSIS(), statisticsFilter->GetKurtosis()); + statObj.AddStatistic(ImageStatisticsConstants::RMS(), rms); + statObj.AddStatistic(ImageStatisticsConstants::MPP(), statisticsFilter->GetMPP()); + statObj.AddStatistic(ImageStatisticsConstants::ENTROPY(), statisticsFilter->GetEntropy()); + statObj.AddStatistic(ImageStatisticsConstants::MEDIAN(), statisticsFilter->GetMedian()); + statObj.AddStatistic(ImageStatisticsConstants::UNIFORMITY(), statisticsFilter->GetUniformity()); + statObj.AddStatistic(ImageStatisticsConstants::UPP(), statisticsFilter->GetUPP()); statObj.m_Histogram = statisticsFilter->GetHistogram(); - statisticContainerForImage->SetStatisticsForTimeStep(timeStep, statObj); + + m_StatisticContainer->SetStatistics(ImageStatisticsContainer::NO_MASK_LABEL_VALUE, timeStep, statObj); } template double ImageStatisticsCalculator::GetVoxelVolume(typename itk::Image *image) const { auto spacing = image->GetSpacing(); double voxelVolume = 1.; for (unsigned int i = 0; i < image->GetImageDimension(); i++) { voxelVolume *= spacing[i]; } return voxelVolume; } template void ImageStatisticsCalculator::InternalCalculateStatisticsMasked(typename itk::Image *image, const TimeGeometry *timeGeometry, unsigned int timeStep) { typedef itk::Image ImageType; typedef itk::Image MaskType; typedef typename MaskType::PixelType LabelPixelType; typedef LabelStatisticsImageFilter ImageStatisticsFilterType; typedef MaskUtilities MaskUtilType; typedef typename itk::MinMaxLabelImageFilterWithIndex MinMaxLabelFilterType; // workaround: if m_SecondaryMaskGenerator ist not null but m_MaskGenerator is! (this is the case if we request a // 'ignore zuero valued pixels' mask in the gui but do not define a primary mask) bool swapMasks = false; if (m_SecondaryMask.IsNotNull() && m_InternalMask.IsNull()) { m_InternalMask = m_SecondaryMask; m_SecondaryMask = nullptr; swapMasks = true; } // maskImage has to have the same dimension as image typename MaskType::ConstPointer maskImage = MaskType::New(); try { // try to access the pixel values directly (no copying or casting). Only works if mask pixels are of pixelType // unsigned short maskImage = ImageToItkImage(m_InternalMask); } catch (const itk::ExceptionObject &) { typename MaskType::Pointer noneConstMaskImage; //needed to work arround the fact that CastToItkImage currently does not support const itk images. // if the pixel type of the mask is not short, then we have to make a copy of m_InternalMask (and cast the values) CastToItkImage(m_InternalMask, noneConstMaskImage); maskImage = noneConstMaskImage; } // if we have a secondary mask (say a ignoreZeroPixelMask) we need to combine the masks (corresponds to AND) if (m_SecondaryMask.IsNotNull()) { // dirty workaround for a bug when pf mask + any other mask is used in conjunction. We need a proper fix for this // (Fabian Isensee is responsible and probably working on it!) if (m_InternalMask->GetDimension() == 2 && (m_SecondaryMask->GetDimension() == 3 || m_SecondaryMask->GetDimension() == 4)) { - mitk::Image::ConstPointer old_img = m_SecondaryMaskGenerator->GetReferenceImage(); + Image::ConstPointer old_img = m_SecondaryMaskGenerator->GetReferenceImage(); m_SecondaryMaskGenerator->SetInputImage(m_MaskGenerator->GetReferenceImage()); m_SecondaryMask = m_SecondaryMaskGenerator->GetMask(); m_SecondaryMaskGenerator->SetInputImage(old_img); } typename MaskType::ConstPointer secondaryMaskImage = MaskType::New(); secondaryMaskImage = ImageToItkImage(m_SecondaryMask); // secondary mask should be a ignore zero value pixel mask derived from image. it has to be cropped to the mask // region (which may be planar or simply smaller) typename MaskUtilities::Pointer secondaryMaskMaskUtil = MaskUtilities::New(); secondaryMaskMaskUtil->SetImage(secondaryMaskImage.GetPointer()); secondaryMaskMaskUtil->SetMask(maskImage.GetPointer()); typename MaskType::ConstPointer adaptedSecondaryMaskImage = secondaryMaskMaskUtil->ExtractMaskImageRegion(); typename itk::MaskImageFilter2::Pointer maskFilter = itk::MaskImageFilter2::New(); maskFilter->SetInput1(maskImage); maskFilter->SetInput2(adaptedSecondaryMaskImage); maskFilter->SetMaskingValue( 1); // all pixels of maskImage where secondaryMaskImage==1 will be kept, all the others are set to 0 maskFilter->UpdateLargestPossibleRegion(); maskImage = maskFilter->GetOutput(); } typename MaskUtilType::Pointer maskUtil = MaskUtilType::New(); maskUtil->SetImage(image); maskUtil->SetMask(maskImage.GetPointer()); // if mask is smaller than image, extract the image region where the mask is typename ImageType::ConstPointer adaptedImage = ImageType::New(); adaptedImage = maskUtil->ExtractMaskImageRegion(); // this also checks mask sanity // find min, max, minindex and maxindex typename MinMaxLabelFilterType::Pointer minMaxFilter = MinMaxLabelFilterType::New(); minMaxFilter->SetInput(adaptedImage); minMaxFilter->SetLabelInput(maskImage); minMaxFilter->UpdateLargestPossibleRegion(); // set histogram parameters for each label individually (min/max may be different for each label) typedef typename std::unordered_map MapType; std::vector relevantLabels = minMaxFilter->GetRelevantLabels(); MapType minVals; MapType maxVals; std::unordered_map nBins; for (LabelPixelType label : relevantLabels) { minVals[label] = static_cast(minMaxFilter->GetMin(label)); maxVals[label] = static_cast(minMaxFilter->GetMax(label)); unsigned int nBinsForHistogram; if (m_UseBinSizeOverNBins) { nBinsForHistogram = std::max(static_cast(std::ceil(minMaxFilter->GetMax(label) - minMaxFilter->GetMin(label))) / m_binSizeForHistogramStatistics, 10.); // do not allow less than 10 bins } else { nBinsForHistogram = m_nBinsForHistogramStatistics; } nBins[label] = nBinsForHistogram; } typename ImageStatisticsFilterType::Pointer imageStatisticsFilter = ImageStatisticsFilterType::New(); imageStatisticsFilter->SetDirectionTolerance(0.001); imageStatisticsFilter->SetCoordinateTolerance(0.001); imageStatisticsFilter->SetInput(adaptedImage); imageStatisticsFilter->SetLabelInput(maskImage); imageStatisticsFilter->SetHistogramParameters(nBins, minVals, maxVals); imageStatisticsFilter->Update(); - auto labels = imageStatisticsFilter->GetValidLabelValues(); - auto it = labels.begin(); + const auto labels = imageStatisticsFilter->GetValidLabelValues(); - while (it != labels.end()) + for (auto labelValue : labels) { - ImageStatisticsContainer::Pointer statisticContainerForLabelImage; - auto labelIt = m_StatisticContainers.find(*it); - // reset if statisticContainer already exist - if (labelIt != m_StatisticContainers.end()) - { - statisticContainerForLabelImage = labelIt->second; - } - // create new statisticContainer - else - { - statisticContainerForLabelImage = ImageStatisticsContainer::New(); - statisticContainerForLabelImage->SetTimeGeometry(const_cast(timeGeometry)); - // link label (*it) to statisticContainer - m_StatisticContainers.emplace(*it, statisticContainerForLabelImage); - } - ImageStatisticsContainer::ImageStatisticsObject statObj; // find min, max, minindex and maxindex // make sure to only look in the masked region, use a masker for this vnl_vector minIndex, maxIndex; - mitk::Point3D worldCoordinateMin; - mitk::Point3D worldCoordinateMax; - mitk::Point3D indexCoordinateMin; - mitk::Point3D indexCoordinateMax; - m_InternalImageForStatistics->GetGeometry()->IndexToWorld(minMaxFilter->GetMinIndex(*it), worldCoordinateMin); - m_InternalImageForStatistics->GetGeometry()->IndexToWorld(minMaxFilter->GetMaxIndex(*it), worldCoordinateMax); + Point3D worldCoordinateMin; + Point3D worldCoordinateMax; + Point3D indexCoordinateMin; + Point3D indexCoordinateMax; + m_InternalImageForStatistics->GetGeometry()->IndexToWorld(minMaxFilter->GetMinIndex(labelValue), worldCoordinateMin); + m_InternalImageForStatistics->GetGeometry()->IndexToWorld(minMaxFilter->GetMaxIndex(labelValue), worldCoordinateMax); m_Image->GetGeometry()->WorldToIndex(worldCoordinateMin, indexCoordinateMin); m_Image->GetGeometry()->WorldToIndex(worldCoordinateMax, indexCoordinateMax); minIndex.set_size(3); maxIndex.set_size(3); // for (unsigned int i=0; i < tmpMaxIndex.GetIndexDimension(); i++) for (unsigned int i = 0; i < 3; i++) { minIndex[i] = indexCoordinateMin[i]; maxIndex[i] = indexCoordinateMax[i]; } - statObj.AddStatistic(mitk::ImageStatisticsConstants::MINIMUMPOSITION(), minIndex); - statObj.AddStatistic(mitk::ImageStatisticsConstants::MAXIMUMPOSITION(), maxIndex); + statObj.AddStatistic(ImageStatisticsConstants::MINIMUMPOSITION(), minIndex); + statObj.AddStatistic(ImageStatisticsConstants::MAXIMUMPOSITION(), maxIndex); auto voxelVolume = GetVoxelVolume(image); auto numberOfVoxels = - static_cast(imageStatisticsFilter->GetCount(*it)); + static_cast(imageStatisticsFilter->GetCount(labelValue)); auto volume = static_cast(numberOfVoxels) * voxelVolume; - auto rms = std::sqrt(std::pow(imageStatisticsFilter->GetMean(*it), 2.) + - imageStatisticsFilter->GetVariance(*it)); // variance = sigma^2 - auto variance = imageStatisticsFilter->GetSigma(*it) * imageStatisticsFilter->GetSigma(*it); - - statObj.AddStatistic(mitk::ImageStatisticsConstants::NUMBEROFVOXELS(), numberOfVoxels); - statObj.AddStatistic(mitk::ImageStatisticsConstants::VOLUME(), volume); - statObj.AddStatistic(mitk::ImageStatisticsConstants::MEAN(), imageStatisticsFilter->GetMean(*it)); - statObj.AddStatistic(mitk::ImageStatisticsConstants::MINIMUM(), - static_cast(imageStatisticsFilter->GetMinimum(*it))); - statObj.AddStatistic(mitk::ImageStatisticsConstants::MAXIMUM(), - static_cast(imageStatisticsFilter->GetMaximum(*it))); - statObj.AddStatistic(mitk::ImageStatisticsConstants::STANDARDDEVIATION(), imageStatisticsFilter->GetSigma(*it)); - statObj.AddStatistic(mitk::ImageStatisticsConstants::VARIANCE(), variance); - statObj.AddStatistic(mitk::ImageStatisticsConstants::SKEWNESS(), imageStatisticsFilter->GetSkewness(*it)); - statObj.AddStatistic(mitk::ImageStatisticsConstants::KURTOSIS(), imageStatisticsFilter->GetKurtosis(*it)); - statObj.AddStatistic(mitk::ImageStatisticsConstants::RMS(), rms); - statObj.AddStatistic(mitk::ImageStatisticsConstants::MPP(), imageStatisticsFilter->GetMPP(*it)); - statObj.AddStatistic(mitk::ImageStatisticsConstants::ENTROPY(), imageStatisticsFilter->GetEntropy(*it)); - statObj.AddStatistic(mitk::ImageStatisticsConstants::MEDIAN(), imageStatisticsFilter->GetMedian(*it)); - statObj.AddStatistic(mitk::ImageStatisticsConstants::UNIFORMITY(), imageStatisticsFilter->GetUniformity(*it)); - statObj.AddStatistic(mitk::ImageStatisticsConstants::UPP(), imageStatisticsFilter->GetUPP(*it)); - statObj.m_Histogram = imageStatisticsFilter->GetHistogram(*it); - statisticContainerForLabelImage->SetStatisticsForTimeStep(timeStep, statObj); - ++it; + auto rms = std::sqrt(std::pow(imageStatisticsFilter->GetMean(labelValue), 2.) + + imageStatisticsFilter->GetVariance(labelValue)); // variance = sigma^2 + auto variance = imageStatisticsFilter->GetSigma(labelValue) * imageStatisticsFilter->GetSigma(labelValue); + + statObj.AddStatistic(ImageStatisticsConstants::NUMBEROFVOXELS(), numberOfVoxels); + statObj.AddStatistic(ImageStatisticsConstants::VOLUME(), volume); + statObj.AddStatistic(ImageStatisticsConstants::MEAN(), imageStatisticsFilter->GetMean(labelValue)); + statObj.AddStatistic(ImageStatisticsConstants::MINIMUM(), + static_cast(imageStatisticsFilter->GetMinimum(labelValue))); + statObj.AddStatistic(ImageStatisticsConstants::MAXIMUM(), + static_cast(imageStatisticsFilter->GetMaximum(labelValue))); + statObj.AddStatistic(ImageStatisticsConstants::STANDARDDEVIATION(), imageStatisticsFilter->GetSigma(labelValue)); + statObj.AddStatistic(ImageStatisticsConstants::VARIANCE(), variance); + statObj.AddStatistic(ImageStatisticsConstants::SKEWNESS(), imageStatisticsFilter->GetSkewness(labelValue)); + statObj.AddStatistic(ImageStatisticsConstants::KURTOSIS(), imageStatisticsFilter->GetKurtosis(labelValue)); + statObj.AddStatistic(ImageStatisticsConstants::RMS(), rms); + statObj.AddStatistic(ImageStatisticsConstants::MPP(), imageStatisticsFilter->GetMPP(labelValue)); + statObj.AddStatistic(ImageStatisticsConstants::ENTROPY(), imageStatisticsFilter->GetEntropy(labelValue)); + statObj.AddStatistic(ImageStatisticsConstants::MEDIAN(), imageStatisticsFilter->GetMedian(labelValue)); + statObj.AddStatistic(ImageStatisticsConstants::UNIFORMITY(), imageStatisticsFilter->GetUniformity(labelValue)); + statObj.AddStatistic(ImageStatisticsConstants::UPP(), imageStatisticsFilter->GetUPP(labelValue)); + statObj.m_Histogram = imageStatisticsFilter->GetHistogram(labelValue); + + m_StatisticContainer->SetStatistics(labelValue, timeStep, statObj); } // swap maskGenerators back if (swapMasks) { m_SecondaryMask = m_InternalMask; m_InternalMask = nullptr; } } - bool ImageStatisticsCalculator::IsUpdateRequired(LabelIndex label) const + bool ImageStatisticsCalculator::IsUpdateRequired() const { - unsigned long thisClassTimeStamp = this->GetMTime(); - unsigned long inputImageTimeStamp = m_Image->GetMTime(); + const auto thisClassTimeStamp = this->GetMTime(); + const auto inputImageTimeStamp = m_Image->GetMTime(); - auto it = m_StatisticContainers.find(label); - if (it == m_StatisticContainers.end()) + if (m_StatisticContainer.IsNull()) { return true; } - unsigned long statisticsTimeStamp = it->second->GetMTime(); + const auto statisticsTimeStamp = m_StatisticContainer->GetMTime(); if (thisClassTimeStamp > statisticsTimeStamp) // inputs have changed { return true; } if (inputImageTimeStamp > statisticsTimeStamp) // image has changed { return true; } if (m_MaskGenerator.IsNotNull()) { - unsigned long maskGeneratorTimeStamp = m_MaskGenerator->GetMTime(); + const auto maskGeneratorTimeStamp = m_MaskGenerator->GetMTime(); if (maskGeneratorTimeStamp > statisticsTimeStamp) // there is a mask generator and it has changed { return true; } } if (m_SecondaryMaskGenerator.IsNotNull()) { - unsigned long maskGeneratorTimeStamp = m_SecondaryMaskGenerator->GetMTime(); + const auto maskGeneratorTimeStamp = m_SecondaryMaskGenerator->GetMTime(); if (maskGeneratorTimeStamp > statisticsTimeStamp) // there is a secondary mask generator and it has changed { return true; } } return false; } } // namespace mitk diff --git a/Modules/ImageStatistics/mitkImageStatisticsCalculator.h b/Modules/ImageStatistics/mitkImageStatisticsCalculator.h index 170c6d4b95..d8f9c5c7d4 100644 --- a/Modules/ImageStatistics/mitkImageStatisticsCalculator.h +++ b/Modules/ImageStatistics/mitkImageStatisticsCalculator.h @@ -1,119 +1,118 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkImageStatisticsCalculator_h #define mitkImageStatisticsCalculator_h #include #include #include #include namespace mitk { class MITKIMAGESTATISTICS_EXPORT ImageStatisticsCalculator: public itk::Object { public: /** Standard Self typedef */ typedef ImageStatisticsCalculator Self; typedef itk::Object Superclass; typedef itk::SmartPointer< Self > Pointer; typedef itk::SmartPointer< const Self > ConstPointer; /** Method for creation through the object factory. */ itkNewMacro(Self); /** Runtime information support. */ itkTypeMacro(ImageStatisticsCalculator_v2, itk::Object); typedef double statisticsValueType; typedef std::map statisticsMapType; typedef itk::Statistics::Histogram HistogramType; typedef unsigned short MaskPixelType; - using LabelIndex = ImageStatisticsContainer::LabelIndex; + using LabelIndex = ImageStatisticsContainer::LabelValueType; /**Documentation @brief Set the image for which the statistics are to be computed.*/ void SetInputImage(const mitk::Image* image); /**Documentation @brief Set the mask generator that creates the mask which is to be used to calculate statistics. If no more mask is desired simply set @param mask to nullptr*/ void SetMask(mitk::MaskGenerator* mask); /**Documentation @brief Set this if more than one mask should be applied (for instance if a IgnorePixelValueMask were to be used alongside with a segmentation). Both masks are combined using pixel wise AND operation. The secondary mask does not have to be the same size than the primary but they need to have some overlap*/ void SetSecondaryMask(mitk::MaskGenerator* mask); /**Documentation @brief Set number of bins to be used for histogram statistics. If Bin size is set after number of bins, bin size will be used instead!*/ void SetNBinsForHistogramStatistics(unsigned int nBins); /**Documentation @brief Retrieve the number of bins used for histogram statistics. Careful: The return value does not indicate whether NBins or BinSize is used. That solely depends on which parameter has been set last.*/ unsigned int GetNBinsForHistogramStatistics() const; /**Documentation @brief Set bin size to be used for histogram statistics. If nbins is set after bin size, nbins will be used instead!*/ void SetBinSizeForHistogramStatistics(double binSize); /**Documentation @brief Retrieve the bin size for histogram statistics. Careful: The return value does not indicate whether NBins or BinSize is used. That solely depends on which parameter has been set last.*/ double GetBinSizeForHistogramStatistics() const; /**Documentation - @brief Returns the statistics for label @a label. If these requested statistics are not computed yet the computation is done as well. - For performance reasons, statistics for all labels in the image are computed at once. + @brief Returns the statistics. If these requested statistics are not computed yet the computation is done as well. */ - ImageStatisticsContainer* GetStatistics(LabelIndex label=1); + ImageStatisticsContainer* GetStatistics(); protected: ImageStatisticsCalculator(){ m_nBinsForHistogramStatistics = 100; m_binSizeForHistogramStatistics = 10; m_UseBinSizeOverNBins = false; }; private: //Calculates statistics for each timestep for image template < typename TPixel, unsigned int VImageDimension > void InternalCalculateStatisticsUnmasked( typename itk::Image< TPixel, VImageDimension >* image, const TimeGeometry* timeGeometry, TimeStepType timeStep); template < typename TPixel, unsigned int VImageDimension > void InternalCalculateStatisticsMasked( typename itk::Image< TPixel, VImageDimension >* image, const TimeGeometry* timeGeometry, unsigned int timeStep); template < typename TPixel, unsigned int VImageDimension > double GetVoxelVolume(typename itk::Image* image) const; - bool IsUpdateRequired(LabelIndex label) const; + bool IsUpdateRequired() const; mitk::Image::ConstPointer m_Image; mitk::Image::Pointer m_ImageTimeSlice; mitk::Image::ConstPointer m_InternalImageForStatistics; mitk::MaskGenerator::Pointer m_MaskGenerator; mitk::Image::ConstPointer m_InternalMask; mitk::MaskGenerator::Pointer m_SecondaryMaskGenerator; mitk::Image::ConstPointer m_SecondaryMask; unsigned int m_nBinsForHistogramStatistics; double m_binSizeForHistogramStatistics; bool m_UseBinSizeOverNBins; - std::map m_StatisticContainers; + ImageStatisticsContainer::Pointer m_StatisticContainer; }; } #endif diff --git a/Modules/ImageStatistics/mitkImageStatisticsContainer.cpp b/Modules/ImageStatistics/mitkImageStatisticsContainer.cpp index 0f63304ab9..03bd820022 100644 --- a/Modules/ImageStatistics/mitkImageStatisticsContainer.cpp +++ b/Modules/ImageStatistics/mitkImageStatisticsContainer.cpp @@ -1,248 +1,285 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include #include namespace mitk { ImageStatisticsContainer::ImageStatisticsContainer() { this->Reset(); } // The order is derived from the old (<2018) image statistics plugin. const ImageStatisticsContainer::ImageStatisticsObject::StatisticNameVector ImageStatisticsContainer::ImageStatisticsObject::m_DefaultNames = {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()}; ImageStatisticsContainer::ImageStatisticsObject::ImageStatisticsObject() { Reset(); } - void ImageStatisticsContainer::ImageStatisticsObject::AddStatistic(const std::string &key, StatisticsVariantType value) + void ImageStatisticsContainer::ImageStatisticsObject::AddStatistic(const std::string_view key, StatisticsVariantType value) { m_Statistics.emplace(key, value); if (std::find(m_DefaultNames.cbegin(), m_DefaultNames.cend(), key) == m_DefaultNames.cend()) { if (std::find(m_CustomNames.cbegin(), m_CustomNames.cend(), key) == m_CustomNames.cend()) { m_CustomNames.emplace_back(key); } } } const ImageStatisticsContainer::ImageStatisticsObject::StatisticNameVector & ImageStatisticsContainer::ImageStatisticsObject::GetDefaultStatisticNames() { return m_DefaultNames; } const ImageStatisticsContainer::ImageStatisticsObject::StatisticNameVector & ImageStatisticsContainer::ImageStatisticsObject::GetCustomStatisticNames() const { return m_CustomNames; } ImageStatisticsContainer::ImageStatisticsObject::StatisticNameVector ImageStatisticsContainer::ImageStatisticsObject::GetAllStatisticNames() const { StatisticNameVector names = GetDefaultStatisticNames(); names.insert(names.cend(), m_CustomNames.cbegin(), m_CustomNames.cend()); return names; } ImageStatisticsContainer::ImageStatisticsObject::StatisticNameVector ImageStatisticsContainer::ImageStatisticsObject::GetExistingStatisticNames() const { StatisticNameVector names; std::transform(m_Statistics.begin(), m_Statistics.end(), std::back_inserter(names), [](const auto &pair) { return pair.first; }); return names; } - bool ImageStatisticsContainer::ImageStatisticsObject::HasStatistic(const std::string &name) const + bool ImageStatisticsContainer::ImageStatisticsObject::HasStatistic(const std::string_view name) const { return m_Statistics.find(name) != m_Statistics.cend(); } ImageStatisticsContainer::StatisticsVariantType ImageStatisticsContainer::ImageStatisticsObject::GetValueNonConverted( - const std::string &name) const + const std::string_view name) const { if (HasStatistic(name)) { return m_Statistics.find(name)->second; } else { mitkThrow() << "invalid statistic key, could not find"; } } void ImageStatisticsContainer::ImageStatisticsObject::Reset() { m_Statistics.clear(); m_CustomNames.clear(); } - bool ImageStatisticsContainer::TimeStepExists(TimeStepType timeStep) const + const static ImageStatisticsContainer::LabelValueType NO_MASK_LABEL_VALUE = 1; + + bool ImageStatisticsContainer::StatisticsExist(LabelValueType labelValue, TimeStepType timeStep) const { - return m_TimeStepMap.find(timeStep) != m_TimeStepMap.end(); + auto labelFinding = m_LabelTimeStep2StatisticsMap.find(labelValue); + if (labelFinding == m_LabelTimeStep2StatisticsMap.end()) return false; + + auto timeFinding = labelFinding->second.find(timeStep); + + return timeFinding != labelFinding->second.end(); } const ImageStatisticsContainer::HistogramType* - ImageStatisticsContainer::GetHistogramForTimeStep(TimeStepType timeStep) const + ImageStatisticsContainer::GetHistogram(LabelValueType labelValue, TimeStepType timeStep) const { - return this->GetStatisticsForTimeStep(timeStep).m_Histogram; + return this->GetStatistics(labelValue, timeStep).m_Histogram; } - const ImageStatisticsContainer::ImageStatisticsObject &ImageStatisticsContainer::GetStatisticsForTimeStep( + const ImageStatisticsContainer::ImageStatisticsObject &ImageStatisticsContainer::GetStatistics(LabelValueType labelValue, TimeStepType timeStep) const { - auto it = m_TimeStepMap.find(timeStep); - if (it != m_TimeStepMap.end()) - { - return it->second; - } - mitkThrow() << "StatisticsObject for timeStep " << timeStep << " not found!"; + auto labelFinding = m_LabelTimeStep2StatisticsMap.find(labelValue); + if (labelFinding == m_LabelTimeStep2StatisticsMap.end()) mitkThrow() << "Cannot get statistics. Requested label value does not exist. Invalid label:" <second.find(timeStep); + if (timeFinding == labelFinding->second.end()) mitkThrow() << "Cannot get statistics. Requested time step does not exist. Invalid time step:" << timeStep; + + return timeFinding->second; } - void ImageStatisticsContainer::SetStatisticsForTimeStep(TimeStepType timeStep, ImageStatisticsObject statistics) + void ImageStatisticsContainer::SetStatistics(LabelValueType labelValue, TimeStepType timeStep, const ImageStatisticsObject& statistics) { - if (timeStep < this->GetTimeSteps()) - { - m_TimeStepMap.emplace(timeStep, statistics); - this->Modified(); - } - else - { - mitkThrow() << "Given timeStep " << timeStep - << " out of timeStep geometry bounds. TimeSteps in geometry: " << this->GetTimeSteps(); - } + + if (!this->GetTimeGeometry()->IsValidTimeStep(timeStep)) mitkThrow() << "Given timeStep " << timeStep + << " out of TimeGeometry bounds of the object. TimeSteps in geometry: " << this->GetTimeSteps(); + + m_LabelTimeStep2StatisticsMap[labelValue][timeStep] = statistics; + this->Modified(); } void ImageStatisticsContainer::PrintSelf(std::ostream &os, itk::Indent indent) const { Superclass::PrintSelf(os, indent); - for (unsigned int i = 0; i < this->GetTimeSteps(); i++) + for (const auto& [labelValue, timeMap] : m_LabelTimeStep2StatisticsMap) { - os << std::endl << indent << "Statistics instance for timeStep " << i << ":"; - if (this->TimeStepExists(i)) + for (const auto& [timeStep, container] : timeMap) { - auto statisticsValues = GetStatisticsForTimeStep(i); + os << std::endl << indent << "Statistics instance (Label "<< labelValue << ", TimeStep "<< timeStep << "):"; + auto statisticsValues = GetStatistics(labelValue,timeStep); auto statisticKeys = statisticsValues.GetExistingStatisticNames(); os << std::endl << indent << "Number of entries: " << statisticKeys.size(); for (const auto& aKey : statisticKeys) { os << std::endl << indent.GetNextIndent() << aKey << ": " << statisticsValues.GetValueNonConverted(aKey); } } - else + } + } + + + ImageStatisticsContainer::LabelValueVectorType ImageStatisticsContainer::GetExistingLabelValues(bool ignoreUnlabeled) const + { + LabelValueVectorType result; + for (const auto& [labelValue, timeMap] : m_LabelTimeStep2StatisticsMap) + { + if (!ignoreUnlabeled || labelValue != NO_MASK_LABEL_VALUE) { - os << std::endl << indent << "N/A"; + result.push_back(labelValue); } } + return result; } - unsigned int ImageStatisticsContainer::GetNumberOfTimeSteps() const { return this->GetTimeSteps(); } - - void ImageStatisticsContainer::Reset() + ImageStatisticsContainer::TimeStepVectorType ImageStatisticsContainer::GetExistingTimeSteps(LabelValueType labelValue) const { - for (auto iter = m_TimeStepMap.begin(); iter != m_TimeStepMap.end(); iter++) + TimeStepVectorType result; + + auto labelFinding = m_LabelTimeStep2StatisticsMap.find(labelValue); + if (labelFinding == m_LabelTimeStep2StatisticsMap.end()) mitkThrow() << "Cannot get existing time steps. Requested label value does not exist. Invalid label:" << labelValue; + + for (const auto& [timestep, stats] : labelFinding->second) { - iter->second.Reset(); + result.push_back(timestep); } + return result; + } + + void ImageStatisticsContainer::Reset() + { + m_LabelTimeStep2StatisticsMap.clear(); + this->Modified(); } itk::LightObject::Pointer ImageStatisticsContainer::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->m_LabelTimeStep2StatisticsMap = m_LabelTimeStep2StatisticsMap; rval->SetTimeGeometry(this->GetTimeGeometry()->Clone()); return ioPtr; } - void ImageStatisticsContainer::SetTimeStepMap(TimeStepMapType map) { m_TimeStepMap = map; } - ImageStatisticsContainer::ImageStatisticsObject::StatisticNameVector GetAllStatisticNames( const ImageStatisticsContainer *container) { ImageStatisticsContainer::ImageStatisticsObject::StatisticNameVector names = ImageStatisticsContainer::ImageStatisticsObject::GetDefaultStatisticNames(); if (container) { std::set customKeys; - for (unsigned int i = 0; i < container->GetTimeSteps(); i++) + auto labelValues = container->GetExistingLabelValues(false); + + for (const auto labelValue : labelValues) { - auto statisticKeys = container->GetStatisticsForTimeStep(i).GetCustomStatisticNames(); - customKeys.insert(statisticKeys.cbegin(), statisticKeys.cend()); + auto timeSteps = container->GetExistingTimeSteps(labelValue); + + for (const auto timeStep : timeSteps) + { + auto statisticKeys = container->GetStatistics(labelValue, timeStep).GetCustomStatisticNames(); + customKeys.insert(statisticKeys.cbegin(), statisticKeys.cend()); + } } names.insert(names.cend(), customKeys.cbegin(), customKeys.cend()); } return names; } ImageStatisticsContainer::ImageStatisticsObject::StatisticNameVector GetAllStatisticNames( std::vector containers) { ImageStatisticsContainer::ImageStatisticsObject::StatisticNameVector names = ImageStatisticsContainer::ImageStatisticsObject::GetDefaultStatisticNames(); std::set customKeys; for (const auto &container : containers) { - for (unsigned int i = 0; i < container->GetTimeSteps(); i++) + std::set customKeys; + + auto labelValues = container->GetExistingLabelValues(false); + + for (const auto labelValue : labelValues) { - if(container->TimeStepExists(i)) + auto timeSteps = container->GetExistingTimeSteps(labelValue); + + for (const auto timeStep : timeSteps) { - auto statisticKeys = container->GetStatisticsForTimeStep(i).GetCustomStatisticNames(); + auto statisticKeys = container->GetStatistics(labelValue, timeStep).GetCustomStatisticNames(); customKeys.insert(statisticKeys.cbegin(), statisticKeys.cend()); } } + + names.insert(names.cend(), customKeys.cbegin(), customKeys.cend()); } names.insert(names.end(), customKeys.begin(), customKeys.end()); return names; }; } // namespace mitk diff --git a/Modules/ImageStatistics/mitkImageStatisticsContainer.h b/Modules/ImageStatistics/mitkImageStatisticsContainer.h index b68eb6e611..d0a18bee7a 100644 --- a/Modules/ImageStatistics/mitkImageStatisticsContainer.h +++ b/Modules/ImageStatistics/mitkImageStatisticsContainer.h @@ -1,167 +1,178 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkImageStatisticsContainer_h #define mitkImageStatisticsContainer_h #include #include #include +#include #include #include namespace mitk { /** - @brief Container class for storing a StatisticsObject for each timestep. + @brief Container class for storing a StatisticsObject for each time step. Stored statistics are: - for the defined statistics, see GetAllStatisticNames - Histogram of Pixel Values */ class MITKIMAGESTATISTICS_EXPORT ImageStatisticsContainer : public mitk::BaseData { public: mitkClassMacro(ImageStatisticsContainer, mitk::BaseData); itkFactorylessNewMacro(Self); itkCloneMacro(Self); using HistogramType = itk::Statistics::Histogram; - using RealType = double; - 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; + using LabelValueType = LabelSetImage::LabelValueType; void SetRequestedRegionToLargestPossibleRegion() override {} bool RequestedRegionIsOutsideOfTheBufferedRegion() override { return false; } bool VerifyRequestedRegion() override { return true; } void SetRequestedRegion(const itk::DataObject*) override {} /** @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. + The type used to create the boost::variant is important as only this type can be recovered later on. */ class MITKIMAGESTATISTICS_EXPORT ImageStatisticsObject { public: ImageStatisticsObject(); + + using RealType = double; + using IndexType = vnl_vector; + using VoxelCountType = unsigned long; + + using StatisticsVariantType = boost::variant; + /** @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); + void AddStatistic(const std::string_view key, StatisticsVariantType value); using StatisticNameVector = std::vector; /** @brief Returns the names of the default statistics @details The order is derived from the image statistics plugin. */ static const StatisticNameVector& GetDefaultStatisticNames(); /** @brief Returns the names of all custom statistics (defined at runtime and no default names). */ const StatisticNameVector& GetCustomStatisticNames() const; /** @brief Returns the names of all statistics (default and custom defined) Additional custom keys are added at the end in a sorted order. */ StatisticNameVector GetAllStatisticNames() const; StatisticNameVector GetExistingStatisticNames() const; - bool HasStatistic(const std::string& name) const; + bool HasStatistic(const std::string_view name) const; /** @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 + TType GetValueConverted(const std::string_view name) const { auto value = GetValueNonConverted(name); return boost::get(value); } /** @brief Returns the requested value @exception if no statistics with key name was found. */ - StatisticsVariantType GetValueNonConverted(const std::string& name) const; + StatisticsVariantType GetValueNonConverted(const std::string_view name) const; void Reset(); HistogramType::ConstPointer m_Histogram=nullptr; private: + + using StatisticsMapType = std::map < std::string, StatisticsVariantType, std::less<>>; + StatisticsMapType m_Statistics; StatisticNameVector m_CustomNames; static const StatisticNameVector m_DefaultNames; }; - using TimeStepMapType = std::map; + using StatisticsVariantType = ImageStatisticsObject::StatisticsVariantType; + using RealType = ImageStatisticsObject::RealType; + using IndexType = ImageStatisticsObject::IndexType; + using VoxelCountType = ImageStatisticsObject::VoxelCountType; - unsigned int GetNumberOfTimeSteps() const; + using TimeStepVectorType = std::vector; + TimeStepVectorType GetExistingTimeSteps(LabelValueType labelValue) const; + + /** Value that can be used to query for the statistic if no mask was provided.*/ + const static LabelValueType NO_MASK_LABEL_VALUE = Label::UNLABELED_VALUE; + using LabelValueVectorType = LabelSetImage::LabelValueVectorType; + LabelValueVectorType GetExistingLabelValues(bool ignoreUnlabeled) const; /** @brief Deletes all stored values*/ void Reset(); - /** - @brief Returns the statisticObject for the given Timestep - @pre timeStep must be valid - */ - const ImageStatisticsObject& GetStatisticsForTimeStep(TimeStepType timeStep) const; + const ImageStatisticsObject& GetStatistics(LabelValueType labelValue, TimeStepType timeStep) const; /** @brief Sets the statisticObject for the given Timestep @pre timeStep must be valid */ - void SetStatisticsForTimeStep(TimeStepType timeStep, ImageStatisticsObject statistics); + void SetStatistics(LabelValueType labelValue, TimeStepType timeStep, const ImageStatisticsObject& statistics); /** @brief Checks if the Time step exists @pre timeStep must be valid */ - bool TimeStepExists(TimeStepType timeStep) const; + bool StatisticsExist(LabelValueType labelValue, TimeStepType timeStep) const; /** /brief Returns the histogram of the passed time step. @pre timeStep must be valid*/ - const HistogramType* GetHistogramForTimeStep(TimeStepType timeStep) const; + const HistogramType* GetHistogram(LabelValueType labelValue, TimeStepType timeStep) const; protected: ImageStatisticsContainer(); void PrintSelf(std::ostream &os, itk::Indent indent) const override; private: itk::LightObject::Pointer InternalClone() const override; - void SetTimeStepMap(TimeStepMapType map); + using TimeStepMapType = std::map; + using LabelMapType = std::map; - TimeStepMapType m_TimeStepMap; + LabelMapType m_LabelTimeStep2StatisticsMap; }; MITKIMAGESTATISTICS_EXPORT ImageStatisticsContainer::ImageStatisticsObject::StatisticNameVector GetAllStatisticNames(const ImageStatisticsContainer* container); MITKIMAGESTATISTICS_EXPORT ImageStatisticsContainer::ImageStatisticsObject::StatisticNameVector GetAllStatisticNames(std::vector containers); } #endif