diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkStreamlineTractographyParameters.h b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkStreamlineTractographyParameters.h index 9a0a818f77..d85cd78644 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkStreamlineTractographyParameters.h +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkStreamlineTractographyParameters.h @@ -1,163 +1,163 @@ #pragma once /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include namespace mitk { /** * \brief Datastructure to manage streamline tractography parameters. * */ class MITKFIBERTRACKING_EXPORT StreamlineTractographyParameters { public: enum EndpointConstraints { NONE, ///< No constraints on endpoint locations EPS_IN_TARGET, ///< Both EPs are required to be located in the target image EPS_IN_TARGET_LABELDIFF, ///< Both EPs are required to be located in the target image and the image values at the respective position needs to be distinct EPS_IN_SEED_AND_TARGET, ///< One EP is required to be located in the seed image and one in the target image MIN_ONE_EP_IN_TARGET, ///< At least one EP is required to be located in the target image ONE_EP_IN_TARGET, ///< Exactly one EP is required to be located in the target image NO_EP_IN_TARGET ///< No EP is allowed to be located in the target image }; enum MODE { DETERMINISTIC, PROBABILISTIC }; typedef itk::Image ItkFloatImgType; typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkUcharImgType; StreamlineTractographyParameters(); StreamlineTractographyParameters(const StreamlineTractographyParameters ¶ms) = default; ~StreamlineTractographyParameters(); void SaveParameters(std::string filename); ///< Save image generation parameters to .stp file. void LoadParameters(std::string filename); ///< Load image generation parameters from .stp file. template< class ParameterType > ParameterType ReadVal(boost::property_tree::ptree::value_type const& v, std::string tag, ParameterType defaultValue, bool essential=false); // seeding unsigned int m_SeedsPerVoxel = 1; unsigned int m_TrialsPerSeed = 10; int m_MaxNumFibers = -1; // - seed image // interactive float m_InteractiveRadiusMm = 2; unsigned int m_NumInteractiveSeeds = 50; bool m_EnableInteractive = false; // ROI constraints EndpointConstraints m_EpConstraints; // - mask image // - stop image // - exclusion image // - target image // tractography - MODE m_Mode; + MODE m_Mode= MODE::DETERMINISTIC; bool m_SharpenOdfs = false; float m_Cutoff = 0.1; // - fa/gfa image float m_OdfCutoff = 0.00025; float m_MinTractLengthMm = 20; float m_MaxTractLengthMm = 400; float m_F = 1; float m_G = 0; bool m_FixRandomSeed = false; unsigned int m_NumPreviousDirections = 1; float m_PeakJitter = 0.01; // actual jitter is drawn from a normal distribution with m_PeakJitter*fabs(direction_value) as standard deviation // prior // - peak image float m_Weight = 0.5; bool m_RestrictToPrior = true; bool m_NewDirectionsFromPrior = true; bool m_PriorFlipX = false; bool m_PriorFlipY = false; bool m_PriorFlipZ = false; // neighborhood sampling unsigned int m_NumSamples = 0; bool m_OnlyForwardSamples = false; bool m_StopVotes = false; bool m_AvoidStop = true; bool m_RandomSampling = false; float m_DeflectionMod = 1.0; // data handling bool m_FlipX = false; bool m_FlipY = false; bool m_FlipZ = false; bool m_InterpolateTractographyData = true; bool m_InterpolateRoiImages; bool m_ApplyDirectionMatrix = false; // output and postprocessing bool m_CompressFibers = true; float m_Compression = 0.1; bool m_OutputProbMap = false; float GetAngularThresholdDot() const; float GetAngularThresholdDeg() const; void SetAngularThresholdDeg(float angular_threshold_deg); float GetLoopCheckDeg() const; void SetLoopCheckDeg(float loop_check_deg); float GetStepSizeMm() const; float GetStepSizeVox() const; void SetStepSizeVox(float step_size_vox); float GetSamplingDistanceMm() const; float GetSamplingDistanceVox() const; void SetSamplingDistanceVox(float sampling_distance_vox); void SetMinVoxelSizeMm(float min_voxel_size_mm); float GetMinVoxelSizeMm() const; private: void AutoAdjust(); float m_SamplingDistanceVox = -1; float m_SamplingDistanceMm; float m_AngularThresholdDeg = -1; float m_AngularThresholdDot; float m_LoopCheckDeg = -1; float m_StepSizeVox = -1; float m_StepSizeMm; float m_MinVoxelSizeMm = 1.0; }; } diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberFitTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberFitTest.cpp index 50ae680d15..d383efac16 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberFitTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberFitTest.cpp @@ -1,266 +1,277 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTestingMacros.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include class mitkFiberFitTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkFiberFitTestSuite); MITK_TEST(Fit1); MITK_TEST(Fit2); MITK_TEST(Fit3); MITK_TEST(Fit4); MITK_TEST(Fit5); MITK_TEST(Fit6); CPPUNIT_TEST_SUITE_END(); typedef itk::Image ItkFloatImgType; private: /** Members used inside the different (sub-)tests. All members are initialized via setUp().*/ typedef itk::FitFibersToImageFilter FitterType; FitterType::Pointer fitter; public: mitk::FiberBundle::Pointer LoadFib(std::string fib_name) { std::vector fibInfile = mitk::IOUtil::Load(GetTestDataFilePath("DiffusionImaging/FiberFit/" + fib_name)); mitk::BaseData::Pointer baseData = fibInfile.at(0); mitk::FiberBundle::Pointer fib = dynamic_cast(baseData.GetPointer()); return fib; } void setUp() override { std::vector tracts; tracts.push_back(LoadFib("Cluster_0.fib")); tracts.push_back(LoadFib("Cluster_1.fib")); tracts.push_back(LoadFib("Cluster_2.fib")); tracts.push_back(LoadFib("Cluster_3.fib")); tracts.push_back(LoadFib("Cluster_4.fib")); mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Peak Image"}, {}); mitk::PeakImage::Pointer peaks = mitk::IOUtil::Load(GetTestDataFilePath("DiffusionImaging/FiberFit/csd_peak_image.nii.gz"), &functor); typedef mitk::ImageToItk< mitk::PeakImage::ItkPeakImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(peaks); caster->Update(); mitk::PeakImage::ItkPeakImageType::Pointer peak_image = caster->GetOutput(); fitter = FitterType::New(); fitter->SetPeakImage(peak_image); fitter->SetTractograms(tracts); } void tearDown() override { } void CompareFibs(mitk::FiberBundle::Pointer test, mitk::FiberBundle::Pointer ref, std::string out_name) { vtkSmartPointer weights = test->GetFiberWeights(); vtkSmartPointer ref_weights = ref->GetFiberWeights(); CPPUNIT_ASSERT_MESSAGE("Number of weights should be equal", weights->GetSize()==ref_weights->GetSize()); for (int i=0; iGetSize(); ++i) { if (ref_weights->GetValue(i)>0) { if (fabs( weights->GetValue(i)/ref_weights->GetValue(i)-1 )>0.01) { mitk::IOUtil::Save(test, mitk::IOUtil::GetTempPath()+out_name); CPPUNIT_ASSERT_MESSAGE("Weights should be equal", false); } } else if (weights->GetValue(i)>0) { mitk::IOUtil::Save(test, mitk::IOUtil::GetTempPath()+out_name); CPPUNIT_ASSERT_MESSAGE("Weights should be equal", false); } } } void CompareImages(mitk::PeakImage::ItkPeakImageType::Pointer testImage, std::string name) { mitk::LocaleSwitch localeSwitch("C"); typedef mitk::ImageToItk< mitk::PeakImage::ItkPeakImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(mitk::IOUtil::Load(GetTestDataFilePath("DiffusionImaging/FiberFit/out/" + name))); caster->Update(); mitk::PeakImage::ItkPeakImageType::Pointer refImage = caster->GetOutput(); itk::ImageRegionConstIterator< mitk::PeakImage::ItkPeakImageType > it1(testImage, testImage->GetLargestPossibleRegion()); itk::ImageRegionConstIterator< mitk::PeakImage::ItkPeakImageType > it2(refImage, refImage->GetLargestPossibleRegion()); while(!it1.IsAtEnd()) { if (it2.Get()>0.0001) { if (fabs( it1.Get()/it2.Get()-1 )>0.01) { itk::ImageFileWriter< mitk::PeakImage::ItkPeakImageType >::Pointer writer = itk::ImageFileWriter< mitk::PeakImage::ItkPeakImageType >::New(); writer->SetInput(testImage); writer->SetFileName(mitk::IOUtil::GetTempPath()+name); writer->Update(); MITK_INFO << it1.Get() << " - " << it2.Get(); CPPUNIT_ASSERT_MESSAGE("Peak images should be equal 1", false); } } else if (it1.Get()>0.0001) { itk::ImageFileWriter< mitk::PeakImage::ItkPeakImageType >::Pointer writer = itk::ImageFileWriter< mitk::PeakImage::ItkPeakImageType >::New(); writer->SetInput(testImage); writer->SetFileName(mitk::IOUtil::GetTempPath()+name); writer->Update(); CPPUNIT_ASSERT_MESSAGE("Peak images should be equal 2", false); } ++it1; ++it2; } } void Fit1() { omp_set_num_threads(1); - fitter->SetLambda(0.1); +// fitter->SetLambda(0.1); fitter->SetFilterOutliers(false); fitter->SetRegularization(VnlCostFunction::NONE); fitter->Update(); std::vector< mitk::FiberBundle::Pointer > output_tracts = fitter->GetTractograms(); mitk::FiberBundle::Pointer test = mitk::FiberBundle::New(); test = test->AddBundles(output_tracts); mitk::FiberBundle::Pointer ref = LoadFib("out/NONE_fitted.fib"); CompareFibs(test, ref, "NONE_fitted.fib"); CompareImages(fitter->GetFittedImage(), "NONE_fitted_image.nrrd"); CompareImages(fitter->GetResidualImage(), "NONE_residual_image.nrrd"); + CompareImages(fitter->GetOverexplainedImage(), "NONE_underexplained_image.nrrd"); + CompareImages(fitter->GetUnderexplainedImage(), "NONE_overexplained_image.nrrd"); } void Fit2() { omp_set_num_threads(1); - fitter->SetLambda(0.1); +// fitter->SetLambda(0.1); fitter->SetFilterOutliers(false); fitter->SetRegularization(VnlCostFunction::MSM); fitter->Update(); std::vector< mitk::FiberBundle::Pointer > output_tracts = fitter->GetTractograms(); mitk::FiberBundle::Pointer test = mitk::FiberBundle::New(); test = test->AddBundles(output_tracts); mitk::FiberBundle::Pointer ref = LoadFib("out/MSM_fitted.fib"); CompareFibs(test, ref, "MSM_fitted.fib"); CompareImages(fitter->GetFittedImage(), "MSM_fitted_image.nrrd"); CompareImages(fitter->GetResidualImage(), "MSM_residual_image.nrrd"); + CompareImages(fitter->GetOverexplainedImage(), "MSM_underexplained_image.nrrd"); + CompareImages(fitter->GetUnderexplainedImage(), "MSM_overexplained_image.nrrd"); } void Fit3() { omp_set_num_threads(1); - fitter->SetLambda(0.1); +// fitter->SetLambda(0.1); fitter->SetFilterOutliers(false); fitter->SetRegularization(VnlCostFunction::VARIANCE); fitter->Update(); std::vector< mitk::FiberBundle::Pointer > output_tracts = fitter->GetTractograms(); mitk::FiberBundle::Pointer test = mitk::FiberBundle::New(); test = test->AddBundles(output_tracts); mitk::FiberBundle::Pointer ref = LoadFib("out/MSE_fitted.fib"); CompareFibs(test, ref, "MSE_fitted.fib"); CompareImages(fitter->GetFittedImage(), "MSE_fitted_image.nrrd"); CompareImages(fitter->GetResidualImage(), "MSE_residual_image.nrrd"); + CompareImages(fitter->GetOverexplainedImage(), "MSE_underexplained_image.nrrd"); + CompareImages(fitter->GetUnderexplainedImage(), "MSE_overexplained_image.nrrd"); } void Fit4() { omp_set_num_threads(1); - fitter->SetLambda(0.1); + fitter->SetLambda(100); fitter->SetFilterOutliers(false); fitter->SetRegularization(VnlCostFunction::VOXEL_VARIANCE); fitter->Update(); std::vector< mitk::FiberBundle::Pointer > output_tracts = fitter->GetTractograms(); mitk::FiberBundle::Pointer test = mitk::FiberBundle::New(); test = test->AddBundles(output_tracts); mitk::FiberBundle::Pointer ref = LoadFib("out/LocalMSE_fitted.fib"); CompareFibs(test, ref, "LocalMSE_fitted.fib"); CompareImages(fitter->GetFittedImage(), "LocalMSE_fitted_image.nrrd"); CompareImages(fitter->GetResidualImage(), "LocalMSE_residual_image.nrrd"); + CompareImages(fitter->GetOverexplainedImage(), "LocalMSE_underexplained_image.nrrd"); + CompareImages(fitter->GetUnderexplainedImage(), "LocalMSE_overexplained_image.nrrd"); } void Fit5() { omp_set_num_threads(1); - fitter->SetLambda(0.1); fitter->SetFilterOutliers(false); fitter->SetRegularization(VnlCostFunction::GROUP_VARIANCE); fitter->Update(); std::vector< mitk::FiberBundle::Pointer > output_tracts = fitter->GetTractograms(); mitk::FiberBundle::Pointer test = mitk::FiberBundle::New(); test = test->AddBundles(output_tracts); mitk::FiberBundle::Pointer ref = LoadFib("out/GroupMSE_fitted.fib"); CompareFibs(test, ref, "GroupMSE_fitted.fib"); CompareImages(fitter->GetFittedImage(), "GroupMSE_fitted_image.nrrd"); CompareImages(fitter->GetResidualImage(), "GroupMSE_residual_image.nrrd"); + CompareImages(fitter->GetOverexplainedImage(), "GroupMSE_underexplained_image.nrrd"); + CompareImages(fitter->GetUnderexplainedImage(), "GroupMSE_overexplained_image.nrrd"); } void Fit6() { omp_set_num_threads(1); - fitter->SetLambda(10); + fitter->SetLambda(1000); fitter->SetFilterOutliers(false); fitter->SetRegularization(VnlCostFunction::GROUP_LASSO); fitter->Update(); std::vector< mitk::FiberBundle::Pointer > output_tracts = fitter->GetTractograms(); mitk::FiberBundle::Pointer test = mitk::FiberBundle::New(); test = test->AddBundles(output_tracts); mitk::FiberBundle::Pointer ref = LoadFib("out/GroupLasso_fitted.fib"); CompareFibs(test, ref, "GroupLasso_fitted.fib"); CompareImages(fitter->GetFittedImage(), "GroupLasso_fitted_image.nrrd"); CompareImages(fitter->GetResidualImage(), "GroupLasso_residual_image.nrrd"); + CompareImages(fitter->GetOverexplainedImage(), "GroupLasso_underexplained_image.nrrd"); + CompareImages(fitter->GetUnderexplainedImage(), "GroupLasso_overexplained_image.nrrd"); } }; MITK_TEST_SUITE_REGISTRATION(mitkFiberFit)