diff --git a/Applications/Diffusion/CMakeLists.txt b/Applications/Diffusion/CMakeLists.txt index 7df47d093b..c78b58eea6 100644 --- a/Applications/Diffusion/CMakeLists.txt +++ b/Applications/Diffusion/CMakeLists.txt @@ -1,76 +1,93 @@ project(MitkDiffusion) set(DIFFUSIONAPP_NAME MitkDiffusion) set(_app_options) if(MITK_SHOW_CONSOLE_WINDOW) list(APPEND _app_options SHOW_CONSOLE) endif() # Create a cache entry for the provisioning file which is used to export # the file name in the MITKConfig.cmake file. This will keep external projects # which rely on this file happy. set(DIFFUSIONIMAGINGAPP_PROVISIONING_FILE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${DIFFUSIONAPP_NAME}.provisioning" CACHE INTERNAL "${DIFFUSIONAPP_NAME} provisioning file" FORCE) # should be identical to the list in /CMake/mitkBuildConfigurationmitkDiffusion.cmake # remember to set plugins which should be automatically toggled in target_libraries.cmake set(_plugins + org.commontk.configadmin + org.commontk.eventadmin + org.blueberry.core.runtime + org.blueberry.core.expressions + org.blueberry.core.commands + org.blueberry.ui.qt + org.blueberry.ui.qt.log + org.blueberry.ui.qt.help + org.mitk.core.services + org.mitk.gui.common org.mitk.planarfigure + org.mitk.core.ext + org.mitk.gui.qt.application + org.mitk.gui.qt.ext org.mitk.gui.qt.diffusionimagingapp + org.mitk.gui.qt.common + org.mitk.gui.qt.stdmultiwidgeteditor + org.mitk.gui.qt.common.legacy + org.mitk.gui.qt.datamanager org.mitk.gui.qt.measurementtoolbox org.mitk.gui.qt.segmentation org.mitk.gui.qt.volumevisualization org.mitk.gui.qt.diffusionimaging + org.mitk.gui.qt.diffusionimaging.connectomics org.mitk.gui.qt.diffusionimaging.fiberfox org.mitk.gui.qt.diffusionimaging.fiberprocessing org.mitk.gui.qt.diffusionimaging.ivim org.mitk.gui.qt.diffusionimaging.odfpeaks org.mitk.gui.qt.diffusionimaging.preprocessing org.mitk.gui.qt.diffusionimaging.reconstruction org.mitk.gui.qt.diffusionimaging.tractography - org.mitk.gui.qt.diffusionimaging.connectomics org.mitk.gui.qt.imagenavigator org.mitk.gui.qt.moviemaker org.mitk.gui.qt.basicimageprocessing org.mitk.gui.qt.properties org.mitk.gui.qt.viewnavigator ) # Plug-ins listed below will not be # - added as a build-time dependency to the executable # - listed in the provisioning file for the executable # - installed if they are external plug-ins set(_exclude_plugins org.blueberry.test org.blueberry.uitest org.mitk.gui.qt.coreapplication org.mitk.gui.qt.extapplication ) set(_src_files MitkDiffusion.cpp ) qt5_add_resources(_src_files splashscreen.qrc) mitkFunctionCreateBlueBerryApplication( NAME ${DIFFUSIONAPP_NAME} DESCRIPTION "MITK Diffusion" PLUGINS ${_plugins} EXCLUDE_PLUGINS ${_exclude_plugins} SOURCES ${_src_files} ${_app_options} ) mitk_use_modules(TARGET ${DIFFUSIONAPP_NAME} MODULES MitkAppUtil) # Add meta dependencies (e.g. on auto-load modules from depending modules) if(TARGET ${CMAKE_PROJECT_NAME}-autoload) add_dependencies(${DIFFUSIONAPP_NAME} ${CMAKE_PROJECT_NAME}-autoload) endif() # Add a build time dependency to legacy BlueBerry bundles. if(MITK_MODULES_ENABLED_PLUGINS) add_dependencies(${DIFFUSIONAPP_NAME} ${MITK_MODULES_ENABLED_PLUGINS}) endif() diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerRandomForest.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerRandomForest.cpp index 863145bc38..22a7218bdf 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerRandomForest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerRandomForest.cpp @@ -1,948 +1,948 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _TrackingForestHandler_cpp #define _TrackingForestHandler_cpp #include "mitkTrackingHandlerRandomForest.h" #include #include namespace mitk { template< int ShOrder, int NumberOfSignalFeatures > TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::TrackingHandlerRandomForest() : m_WmSampleDistance(-1) , m_NumTrees(30) , m_MaxTreeDepth(25) , m_SampleFraction(1.0) , m_NumberOfSamples(0) , m_GmSamplesPerVoxel(-1) , m_NumPreviousDirections(1) , m_BidirectionalFiberSampling(false) , m_ZeroDirWmFeatures(true) , m_MaxNumWmSamples(-1) { vnl_vector_fixed ref; ref.fill(0); ref[0]=1; itk::OrientationDistributionFunction< float, 200 > odf; m_DirectionContainer.clear(); for (unsigned int i = 0; i odf_dir; odf_dir[0] = odf.GetDirection(i)[0]; odf_dir[1] = odf.GetDirection(i)[1]; odf_dir[2] = odf.GetDirection(i)[2]; if (dot_product(ref, odf_dir)>0) // only used directions on one hemisphere m_DirectionContainer.push_back(odf_dir); // store indices for later mapping the classifier output to the actual direction } m_OdfFloatDirs.set_size(m_DirectionContainer.size(), 3); for (unsigned int i=0; i TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::~TrackingHandlerRandomForest() { } template< int ShOrder, int NumberOfSignalFeatures > typename TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::DwiFeatureImageType::PixelType TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::GetDwiFeaturesAtPosition(itk::Point itkP, typename DwiFeatureImageType::Pointer image, bool interpolate) { // transform physical point to index coordinates itk::Index<3> idx; itk::ContinuousIndex< float, 3> cIdx; image->TransformPhysicalPointToIndex(itkP, idx); image->TransformPhysicalPointToContinuousIndex(itkP, cIdx); typename DwiFeatureImageType::PixelType pix; pix.Fill(0.0); if ( image->GetLargestPossibleRegion().IsInside(idx) ) { pix = image->GetPixel(idx); if (!interpolate) return pix; } else return pix; float frac_x = cIdx[0] - idx[0]; float frac_y = cIdx[1] - idx[1]; float frac_z = cIdx[2] - idx[2]; if (frac_x<0) { idx[0] -= 1; frac_x += 1; } if (frac_y<0) { idx[1] -= 1; frac_y += 1; } if (frac_z<0) { idx[2] -= 1; frac_z += 1; } frac_x = 1-frac_x; frac_y = 1-frac_y; frac_z = 1-frac_z; // int coordinates inside image? if (idx[0] >= 0 && idx[0] < static_cast(image->GetLargestPossibleRegion().GetSize(0) - 1) && idx[1] >= 0 && idx[1] < static_cast(image->GetLargestPossibleRegion().GetSize(1) - 1) && idx[2] >= 0 && idx[2] < static_cast(image->GetLargestPossibleRegion().GetSize(2) - 1)) { // trilinear interpolation vnl_vector_fixed interpWeights; interpWeights[0] = ( frac_x)*( frac_y)*( frac_z); interpWeights[1] = (1-frac_x)*( frac_y)*( frac_z); interpWeights[2] = ( frac_x)*(1-frac_y)*( frac_z); interpWeights[3] = ( frac_x)*( frac_y)*(1-frac_z); interpWeights[4] = (1-frac_x)*(1-frac_y)*( frac_z); interpWeights[5] = ( frac_x)*(1-frac_y)*(1-frac_z); interpWeights[6] = (1-frac_x)*( frac_y)*(1-frac_z); interpWeights[7] = (1-frac_x)*(1-frac_y)*(1-frac_z); pix = image->GetPixel(idx) * interpWeights[0]; typename DwiFeatureImageType::IndexType tmpIdx = idx; tmpIdx[0]++; pix += image->GetPixel(tmpIdx) * interpWeights[1]; tmpIdx = idx; tmpIdx[1]++; pix += image->GetPixel(tmpIdx) * interpWeights[2]; tmpIdx = idx; tmpIdx[2]++; pix += image->GetPixel(tmpIdx) * interpWeights[3]; tmpIdx = idx; tmpIdx[0]++; tmpIdx[1]++; pix += image->GetPixel(tmpIdx) * interpWeights[4]; tmpIdx = idx; tmpIdx[1]++; tmpIdx[2]++; pix += image->GetPixel(tmpIdx) * interpWeights[5]; tmpIdx = idx; tmpIdx[2]++; tmpIdx[0]++; pix += image->GetPixel(tmpIdx) * interpWeights[6]; tmpIdx = idx; tmpIdx[0]++; tmpIdx[1]++; tmpIdx[2]++; pix += image->GetPixel(tmpIdx) * interpWeights[7]; } return pix; } template< int ShOrder, int NumberOfSignalFeatures > void TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::InputDataValidForTracking() { if (m_InputDwis.empty()) mitkThrow() << "No diffusion-weighted images set!"; if (!IsForestValid()) mitkThrow() << "No or invalid random forest detected!"; } template< int ShOrder, int NumberOfSignalFeatures> template typename std::enable_if< NumberOfSignalFeatures <=99, T >::type TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::InitDwiImageFeatures(mitk::Image::Pointer mitk_dwi) { MITK_INFO << "Calculating spherical harmonics features"; typedef itk::AnalyticalDiffusionQballReconstructionImageFilter InterpolationFilterType; typename InterpolationFilterType::Pointer filter = InterpolationFilterType::New(); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(mitk_dwi)); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(mitk_dwi), mitk::DiffusionPropertyHelper::GetItkVectorImage(mitk_dwi) ); filter->SetLambda(0.006); filter->SetNormalizationMethod(InterpolationFilterType::QBAR_RAW_SIGNAL); filter->Update(); m_DwiFeatureImages.push_back(filter->GetCoefficientImage()); return true; } template< int ShOrder, int NumberOfSignalFeatures> template typename std::enable_if< NumberOfSignalFeatures >=100, T >::type TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::InitDwiImageFeatures(mitk::Image::Pointer mitk_dwi) { MITK_INFO << "Interpolating raw dwi signal features"; typedef itk::AnalyticalDiffusionQballReconstructionImageFilter InterpolationFilterType; typename InterpolationFilterType::Pointer filter = InterpolationFilterType::New(); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(mitk_dwi)); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(mitk_dwi), mitk::DiffusionPropertyHelper::GetItkVectorImage(mitk_dwi) ); filter->SetLambda(0.006); filter->SetNormalizationMethod(InterpolationFilterType::QBAR_RAW_SIGNAL); filter->Update(); typename DwiFeatureImageType::Pointer dwiFeatureImage = DwiFeatureImageType::New(); dwiFeatureImage->SetSpacing(filter->GetOutput()->GetSpacing()); dwiFeatureImage->SetOrigin(filter->GetOutput()->GetOrigin()); dwiFeatureImage->SetDirection(filter->GetOutput()->GetDirection()); dwiFeatureImage->SetLargestPossibleRegion(filter->GetOutput()->GetLargestPossibleRegion()); dwiFeatureImage->SetBufferedRegion(filter->GetOutput()->GetLargestPossibleRegion()); dwiFeatureImage->SetRequestedRegion(filter->GetOutput()->GetLargestPossibleRegion()); dwiFeatureImage->Allocate(); // get signal values and store them in the feature image vnl_vector_fixed ref; ref.fill(0); ref[0]=1; itk::OrientationDistributionFunction< float, 2*NumberOfSignalFeatures > odf; itk::ImageRegionIterator< typename InterpolationFilterType::OutputImageType > it(filter->GetOutput(), filter->GetOutput()->GetLargestPossibleRegion()); while(!it.IsAtEnd()) { typename DwiFeatureImageType::PixelType pix; int f = 0; for (unsigned int i = 0; i0) // only used directions on one hemisphere { pix[f] = it.Get()[i]; f++; } } dwiFeatureImage->SetPixel(it.GetIndex(), pix); ++it; } m_DwiFeatureImages.push_back(dwiFeatureImage); return true; } template< int ShOrder, int NumberOfSignalFeatures > void TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::InitForTracking() { MITK_INFO << "Initializing random forest tracker."; if (m_NeedsDataInit) { InputDataValidForTracking(); m_DwiFeatureImages.clear(); InitDwiImageFeatures<>(m_InputDwis.at(0)); m_NeedsDataInit = false; } } template< int ShOrder, int NumberOfSignalFeatures > vnl_vector_fixed TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::ProposeDirection(const itk::Point& pos, std::deque >& olddirs, itk::Index<3>& oldIndex) { vnl_vector_fixed output_direction; output_direction.fill(0); itk::Index<3> idx; m_DwiFeatureImages.at(0)->TransformPhysicalPointToIndex(pos, idx); bool check_last_dir = false; vnl_vector_fixed last_dir; if (!olddirs.empty()) { last_dir = olddirs.back(); if (last_dir.magnitude()>0.5) check_last_dir = true; } if (!m_Interpolate && oldIndex==idx) return last_dir; // store feature pixel values in a vigra data type vigra::MultiArray<2, float> featureData = vigra::MultiArray<2, float>( vigra::Shape2(1,m_Forest->feature_count()) ); typename DwiFeatureImageType::PixelType dwiFeaturePixel = GetDwiFeaturesAtPosition(pos, m_DwiFeatureImages.at(0), m_Interpolate); for (unsigned int f=0; f direction_matrix = m_DwiFeatureImages.at(0)->GetDirection().GetVnlMatrix(); vnl_matrix_fixed inverse_direction_matrix = m_DwiFeatureImages.at(0)->GetInverseDirection().GetVnlMatrix(); // append normalized previous direction(s) to feature vector int i = 0; vnl_vector_fixed ref; ref.fill(0); ref[0]=1; for (auto d : olddirs) { vnl_vector_fixed tempD; tempD[0] = d[0]; tempD[1] = d[1]; tempD[2] = d[2]; if (m_FlipX) tempD[0] *= -1; if (m_FlipY) tempD[1] *= -1; if (m_FlipZ) tempD[2] *= -1; tempD = inverse_direction_matrix * tempD; last_dir[0] = tempD[0]; last_dir[1] = tempD[1]; last_dir[2] = tempD[2]; int c = 0; for (int f=NumberOfSignalFeatures+3*i; f0) { int c = 0; for (auto img : m_AdditionalFeatureImages.at(0)) { float v = GetImageValue(pos, img, false); featureData(0,NumberOfSignalFeatures+m_NumPreviousDirections*3+c) = v; c++; } } // perform classification vigra::MultiArray<2, float> probs(vigra::Shape2(1, m_Forest->class_count())); m_Forest->predictProbabilities(featureData, probs); vnl_vector< float > angles = m_OdfFloatDirs*last_dir; vnl_vector< float > probs2; probs2.set_size(m_DirectionContainer.size()); probs2.fill(0.0); // used for probabilistic direction sampling float probs_sum = 0; float pNonFib = 0; // probability that we left the white matter float w = 0; // weight of the predicted direction for (int i=0; iclass_count(); i++) // for each class (number of possible directions + out-of-wm class) { if (probs(0,i)>0) // if probability of respective class is 0, do nothing { // get label of class (does not correspond to the loop variable i) unsigned int classLabel = 0; m_Forest->ext_param_.to_classlabel(i, classLabel); if (classLabel=m_AngularThreshold) probs2[classLabel] = probs(0,i); probs_sum += probs2[classLabel]; } else if (m_Mode==MODE::DETERMINISTIC) { vnl_vector_fixed d = m_DirectionContainer.at(classLabel); // get direction vector assiciated with the respective direction index if (check_last_dir) // do we have a previous streamline direction or did we just start? { // TODO: check if hard curvature threshold is necessary. // alternatively try square of dot product as weight. // TODO: check if additional weighting with dot product as directional prior is necessary. are there alternatives on the classification level? float dot = angles[classLabel]; // claculate angle between the candidate direction vector and the previous streamline direction if (fabs(dot)>=m_AngularThreshold) // is angle between the directions smaller than our hard threshold? { if (dot<0) // make sure we don't walk backwards d *= -1; float w_i = probs(0,i)*fabs(dot); output_direction += w_i*d; // weight contribution to output direction with its probability and the angular deviation from the previous direction w += w_i; // increase output weight of the final direction } } else { output_direction += probs(0,i)*d; w += probs(0,i); } } } else pNonFib += probs(0,i); // probability that we are not in the white matter anymore } } if (m_Mode==MODE::PROBABILISTIC && pNonFib<0.5) { probs2 /= probs_sum; boost::random::discrete_distribution dist(probs2.begin(), probs2.end()); int sampled_idx = 0; #pragma omp critical { boost::random::variate_generator> sampler(m_Rng, dist); sampled_idx = sampler(); } output_direction = m_DirectionContainer.at(sampled_idx); w = probs2[sampled_idx]; if (check_last_dir && angles[sampled_idx]<0) // make sure we don't walk backwards output_direction *= -1; } // if we did not find a suitable direction, make sure that we return (0,0,0) if (pNonFib>w && w>0) output_direction.fill(0.0); else { vnl_vector_fixed tempD; tempD[0] = output_direction[0]; tempD[1] = output_direction[1]; tempD[2] = output_direction[2]; tempD = direction_matrix * tempD; output_direction[0] = tempD[0]; output_direction[1] = tempD[1]; output_direction[2] = tempD[2]; if (m_FlipX) output_direction[0] *= -1; if (m_FlipY) output_direction[1] *= -1; if (m_FlipZ) output_direction[2] *= -1; } return output_direction * w; } template< int ShOrder, int NumberOfSignalFeatures > void TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::StartTraining() { m_StartTime = std::chrono::system_clock::now(); InputDataValidForTraining(); InitForTraining(); CalculateTrainingSamples(); MITK_INFO << "Maximum tree depths: " << m_MaxTreeDepth; MITK_INFO << "Sample fraction per tree: " << m_SampleFraction; MITK_INFO << "Number of trees: " << m_NumTrees; DefaultSplitType splitter; splitter.UsePointBasedWeights(true); splitter.SetWeights(m_Weights); splitter.UseRandomSplit(false); splitter.SetPrecision(mitk::eps); splitter.SetMaximumTreeDepth(m_MaxTreeDepth); std::vector< std::shared_ptr< vigra::RandomForest > > trees; int count = 0; #pragma omp parallel for for (int i = 0; i < m_NumTrees; ++i) { std::shared_ptr< vigra::RandomForest > lrf = std::make_shared< vigra::RandomForest >(); lrf->set_options().use_stratification(vigra::RF_NONE); // How the data should be made equal lrf->set_options().sample_with_replacement(true); // if sampled with replacement or not lrf->set_options().samples_per_tree(m_SampleFraction); // Fraction of samples that are used to train a tree lrf->set_options().tree_count(1); // Number of trees that are calculated; lrf->set_options().min_split_node_size(5); // Minimum number of datapoints that must be in a node lrf->ext_param_.max_tree_depth = m_MaxTreeDepth; lrf->learn(m_FeatureData, m_LabelData,vigra::rf::visitors::VisitorBase(),splitter); #pragma omp critical { count++; MITK_INFO << "Tree " << count << " finished training."; trees.push_back(lrf); } } for (int i = 1; i < m_NumTrees; ++i) trees.at(0)->trees_.push_back(trees.at(i)->trees_[0]); m_Forest = trees.at(0); m_Forest->options_.tree_count_ = m_NumTrees; MITK_INFO << "Training finsihed"; m_EndTime = std::chrono::system_clock::now(); std::chrono::hours hh = std::chrono::duration_cast(m_EndTime - m_StartTime); std::chrono::minutes mm = std::chrono::duration_cast(m_EndTime - m_StartTime); mm %= 60; MITK_INFO << "Training took " << hh.count() << "h and " << mm.count() << "m"; } template< int ShOrder, int NumberOfSignalFeatures > void TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::InputDataValidForTraining() { if (m_InputDwis.empty()) mitkThrow() << "No diffusion-weighted images set!"; if (m_Tractograms.empty()) mitkThrow() << "No tractograms set!"; if (m_InputDwis.size()!=m_Tractograms.size()) mitkThrow() << "Unequal number of diffusion-weighted images and tractograms detected!"; } template< int ShOrder, int NumberOfSignalFeatures > bool TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::IsForestValid() { int additional_features = 0; if (m_AdditionalFeatureImages.size()>0) additional_features = m_AdditionalFeatureImages.at(0).size(); if (!m_Forest) - MITK_ERROR << "Forest could not be read!"; + MITK_INFO << "No forest available!"; else { if (m_Forest->tree_count() <= 0) MITK_ERROR << "Forest contains no trees!"; if ( m_Forest->feature_count() != static_cast(NumberOfSignalFeatures+3*m_NumPreviousDirections+additional_features) ) MITK_ERROR << "Wrong number of features in forest: got " << m_Forest->feature_count() << ", expected " << (NumberOfSignalFeatures+3*m_NumPreviousDirections+additional_features); } if(m_Forest && m_Forest->tree_count()>0 && m_Forest->feature_count() == static_cast(NumberOfSignalFeatures+3*m_NumPreviousDirections+additional_features)) return true; return false; } template< int ShOrder, int NumberOfSignalFeatures > void TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::InitForTraining() { MITK_INFO << "Spherical signal interpolation and sampling ..."; for (unsigned int i=0; i(m_InputDwis.at(i)); if (i>=m_AdditionalFeatureImages.size()) { m_AdditionalFeatureImages.push_back(std::vector< ItkFloatImgType::Pointer >()); } if (i>=m_FiberVolumeModImages.size()) { ItkFloatImgType::Pointer img = ItkFloatImgType::New(); img->SetSpacing( m_DwiFeatureImages.at(i)->GetSpacing() ); img->SetOrigin( m_DwiFeatureImages.at(i)->GetOrigin() ); img->SetDirection( m_DwiFeatureImages.at(i)->GetDirection() ); img->SetLargestPossibleRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() ); img->SetBufferedRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() ); img->SetRequestedRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() ); img->Allocate(); img->FillBuffer(1); m_FiberVolumeModImages.push_back(img); } if (m_FiberVolumeModImages.at(i)==nullptr) { m_FiberVolumeModImages.at(i) = ItkFloatImgType::New(); m_FiberVolumeModImages.at(i)->SetSpacing( m_DwiFeatureImages.at(i)->GetSpacing() ); m_FiberVolumeModImages.at(i)->SetOrigin( m_DwiFeatureImages.at(i)->GetOrigin() ); m_FiberVolumeModImages.at(i)->SetDirection( m_DwiFeatureImages.at(i)->GetDirection() ); m_FiberVolumeModImages.at(i)->SetLargestPossibleRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() ); m_FiberVolumeModImages.at(i)->SetBufferedRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() ); m_FiberVolumeModImages.at(i)->SetRequestedRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() ); m_FiberVolumeModImages.at(i)->Allocate(); m_FiberVolumeModImages.at(i)->FillBuffer(1); } if (i>=m_MaskImages.size()) { ItkUcharImgType::Pointer newMask = ItkUcharImgType::New(); newMask->SetSpacing( m_DwiFeatureImages.at(i)->GetSpacing() ); newMask->SetOrigin( m_DwiFeatureImages.at(i)->GetOrigin() ); newMask->SetDirection( m_DwiFeatureImages.at(i)->GetDirection() ); newMask->SetLargestPossibleRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() ); newMask->SetBufferedRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() ); newMask->SetRequestedRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() ); newMask->Allocate(); newMask->FillBuffer(1); m_MaskImages.push_back(newMask); } if (m_MaskImages.at(i)==nullptr) { m_MaskImages.at(i) = ItkUcharImgType::New(); m_MaskImages.at(i)->SetSpacing( m_DwiFeatureImages.at(i)->GetSpacing() ); m_MaskImages.at(i)->SetOrigin( m_DwiFeatureImages.at(i)->GetOrigin() ); m_MaskImages.at(i)->SetDirection( m_DwiFeatureImages.at(i)->GetDirection() ); m_MaskImages.at(i)->SetLargestPossibleRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() ); m_MaskImages.at(i)->SetBufferedRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() ); m_MaskImages.at(i)->SetRequestedRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() ); m_MaskImages.at(i)->Allocate(); m_MaskImages.at(i)->FillBuffer(1); } } MITK_INFO << "Resampling fibers and calculating number of samples ..."; m_NumberOfSamples = 0; m_SampleUsage.clear(); for (unsigned int t=0; t::Pointer env = itk::TractDensityImageFilter< ItkUcharImgType >::New(); env->SetFiberBundle(m_Tractograms.at(t)); env->SetInputImage(mask); env->SetBinaryOutput(true); env->SetUseImageGeometry(true); env->Update(); wmmask = env->GetOutput(); if (t>=m_WhiteMatterImages.size()) m_WhiteMatterImages.push_back(wmmask); else m_WhiteMatterImages.at(t) = wmmask; } // Calculate white-matter samples if (m_WmSampleDistance<0) { typename DwiFeatureImageType::Pointer image = m_DwiFeatureImages.at(t); float minSpacing = 1; if(image->GetSpacing()[0]GetSpacing()[1] && image->GetSpacing()[0]GetSpacing()[2]) minSpacing = image->GetSpacing()[0]; else if (image->GetSpacing()[1] < image->GetSpacing()[2]) minSpacing = image->GetSpacing()[1]; else minSpacing = image->GetSpacing()[2]; m_WmSampleDistance = minSpacing*0.5; } m_Tractograms.at(t)->ResampleLinear(m_WmSampleDistance); int wmSamples = m_Tractograms.at(t)->GetNumberOfPoints()-2*m_Tractograms.at(t)->GetNumFibers(); if (m_BidirectionalFiberSampling) wmSamples *= 2; if (m_ZeroDirWmFeatures) wmSamples *= (m_NumPreviousDirections+1); MITK_INFO << "White matter samples available: " << wmSamples; // upper limit for samples if (m_MaxNumWmSamples>0 && wmSamples>m_MaxNumWmSamples) { if ((float)m_MaxNumWmSamples/wmSamples > 0.8) { m_SampleUsage.push_back(std::vector(wmSamples, true)); m_NumberOfSamples += wmSamples; } else { m_SampleUsage.push_back(std::vector(wmSamples, false)); m_NumberOfSamples += m_MaxNumWmSamples; wmSamples = m_MaxNumWmSamples; MITK_INFO << "Limiting white matter samples to: " << m_MaxNumWmSamples; itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer randgen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New(); randgen->SetSeed(); int c = 0; while (cGetIntegerVariate(m_MaxNumWmSamples-1); if (m_SampleUsage[t][idx]==false) { m_SampleUsage[t][idx]=true; ++c; } } } } else { m_SampleUsage.push_back(std::vector(wmSamples, true)); m_NumberOfSamples += wmSamples; } // calculate gray-matter samples itk::ImageRegionConstIterator it(wmmask, wmmask->GetLargestPossibleRegion()); int OUTOFWM = 0; while(!it.IsAtEnd()) { if (it.Get()==0 && mask->GetPixel(it.GetIndex())>0) OUTOFWM++; ++it; } MITK_INFO << "Non-white matter voxels: " << OUTOFWM; if (m_GmSamplesPerVoxel>0) { m_GmSamples.push_back(m_GmSamplesPerVoxel); m_NumberOfSamples += m_GmSamplesPerVoxel*OUTOFWM; } else if (OUTOFWM>0) { int gm_per_voxel = 0.5+(float)wmSamples/(float)OUTOFWM; if (gm_per_voxel<=0) gm_per_voxel = 1; m_GmSamples.push_back(gm_per_voxel); m_NumberOfSamples += m_GmSamples.back()*OUTOFWM; MITK_INFO << "Non-white matter samples per voxel: " << m_GmSamples.back(); } else { m_GmSamples.push_back(0); } MITK_INFO << "Non-white matter samples: " << m_GmSamples.back()*OUTOFWM; } MITK_INFO << "Number of samples: " << m_NumberOfSamples; } template< int ShOrder, int NumberOfSignalFeatures > void TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::CalculateTrainingSamples() { vnl_vector_fixed ref; ref.fill(0); ref[0]=1; m_FeatureData.reshape( vigra::Shape2(m_NumberOfSamples, NumberOfSignalFeatures+m_NumPreviousDirections*3+m_AdditionalFeatureImages.at(0).size()) ); m_LabelData.reshape( vigra::Shape2(m_NumberOfSamples,1) ); m_Weights.reshape( vigra::Shape2(m_NumberOfSamples,1) ); MITK_INFO << "Number of features: " << m_FeatureData.shape(1); itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandGen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New(); m_RandGen->SetSeed(); MITK_INFO << "Creating training data ..."; unsigned int sampleCounter = 0; for (unsigned int t=0; t it(wmMask, wmMask->GetLargestPossibleRegion()); while(!it.IsAtEnd()) { if (it.Get()==0 && (mask.IsNull() || (mask.IsNotNull() && mask->GetPixel(it.GetIndex())>0))) { typename DwiFeatureImageType::PixelType pix = image->GetPixel(it.GetIndex()); // random directions for (unsigned int i=0; iGetIntegerVariate(m_NumPreviousDirections); // how many directions should be zero? for (unsigned int i=0; i probe; if (static_cast(i)GetVariate()*2-1; probe[1] = m_RandGen->GetVariate()*2-1; probe[2] = m_RandGen->GetVariate()*2-1; probe.normalize(); if (dot_product(ref, probe)<0) probe *= -1; } for (unsigned int f=NumberOfSignalFeatures+3*i; f itkP; image->TransformIndexToPhysicalPoint(it.GetIndex(), itkP); float v = GetImageValue(itkP, img, false); m_FeatureData(sampleCounter,NumberOfSignalFeatures+m_NumPreviousDirections*3+add_feat_c) = v; add_feat_c++; } // label and sample weight m_LabelData(sampleCounter,0) = m_DirectionContainer.size(); m_Weights(sampleCounter,0) = 1.0; sampleCounter++; } } ++it; } unsigned int num_gm_samples = sampleCounter; // white matter samples mitk::FiberBundle::Pointer fib = m_Tractograms.at(t); vtkSmartPointer< vtkPolyData > polyData = fib->GetFiberPolyData(); vnl_vector_fixed zero_dir; zero_dir.fill(0.0); for (int i=0; iGetNumFibers(); i++) { vtkCell* cell = polyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); float fiber_weight = fib->GetFiberWeight(i); for (int n = 0; n <= static_cast(m_NumPreviousDirections); ++n) { if (!m_ZeroDirWmFeatures) n = m_NumPreviousDirections; for (bool reverse : {false, true}) { for (int j=1; j itkP1, itkP2; int num_nonzero_dirs = m_NumPreviousDirections; if (!reverse) num_nonzero_dirs = std::min(n, j); else num_nonzero_dirs = std::min(n, numPoints-j-1); vnl_vector_fixed dir; // zero directions for (unsigned int k=0; kGetPoint(j-n_idx); itkP1[0] = p[0]; itkP1[1] = p[1]; itkP1[2] = p[2]; p = points->GetPoint(j-n_idx+1); itkP2[0] = p[0]; itkP2[1] = p[1]; itkP2[2] = p[2]; } else { p = points->GetPoint(j+n_idx); itkP1[0] = p[0]; itkP1[1] = p[1]; itkP1[2] = p[2]; p = points->GetPoint(j+n_idx-1); itkP2[0] = p[0]; itkP2[1] = p[1]; itkP2[2] = p[2]; } dir[0]=itkP1[0]-itkP2[0]; dir[1]=itkP1[1]-itkP2[1]; dir[2]=itkP1[2]-itkP2[2]; if (dir.magnitude()<0.0001) mitkThrow() << "streamline error!"; dir.normalize(); if (dir[0]!=dir[0] || dir[1]!=dir[1] || dir[2]!=dir[2]) mitkThrow() << "ERROR: NaN direction!"; if (dot_product(ref, dir)<0) dir *= -1; int c = 0; for (unsigned int f=NumberOfSignalFeatures+3*(k+m_NumPreviousDirections-num_nonzero_dirs); fGetPoint(j); itkP1[0] = p[0]; itkP1[1] = p[1]; itkP1[2] = p[2]; if (reverse) { p = points->GetPoint(j-1); itkP2[0] = p[0]; itkP2[1] = p[1]; itkP2[2] = p[2]; } else { p = points->GetPoint(j+1); itkP2[0] = p[0]; itkP2[1] = p[1]; itkP2[2] = p[2]; } dir[0]=itkP2[0]-itkP1[0]; dir[1]=itkP2[1]-itkP1[1]; dir[2]=itkP2[2]-itkP1[2]; if (dir.magnitude()<0.0001) mitkThrow() << "streamline error!"; dir.normalize(); if (dir[0]!=dir[0] || dir[1]!=dir[1] || dir[2]!=dir[2]) mitkThrow() << "ERROR: NaN direction!"; if (dot_product(ref, dir)<0) dir *= -1; // image features float volume_mod = GetImageValue(itkP1, fiber_folume, false); // diffusion signal features typename DwiFeatureImageType::PixelType pix = GetDwiFeaturesAtPosition(itkP1, image, m_Interpolate); for (unsigned int f=0; f(itkP1, img, false); add_feat_c++; m_FeatureData(sampleCounter,NumberOfSignalFeatures+2+add_feat_c) = v; } // set label values float angle = 0; float m = dir.magnitude(); if (m>0.0001) { int l = 0; for (auto d : m_DirectionContainer) { float a = fabs(dot_product(dir, d)); if (a>angle) { m_LabelData(sampleCounter,0) = l; m_Weights(sampleCounter,0) = fiber_weight*volume_mod; angle = a; } l++; } } sampleCounter++; } if (!m_BidirectionalFiberSampling) // don't sample fibers backward break; } } } } m_Tractograms.clear(); MITK_INFO << "done"; } template< int ShOrder, int NumberOfSignalFeatures > void TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::SaveForest(std::string forestFile) { MITK_INFO << "Saving forest to " << forestFile; if (IsForestValid()) { vigra::rf_export_HDF5( *m_Forest, forestFile, "" ); MITK_INFO << "Forest saved successfully."; } else MITK_INFO << "Forest invalid! Could not be saved."; } template< int ShOrder, int NumberOfSignalFeatures > void TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::LoadForest(std::string forestFile) { MITK_INFO << "Loading forest from " << forestFile; m_Forest = std::make_shared< vigra::RandomForest >(); vigra::rf_import_HDF5( *m_Forest, forestFile); } } #endif diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.cpp index 4f02ad6cbf..a9a7a8cfd9 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.cpp @@ -1,1011 +1,1018 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkIVIMView.h" // qt #include "qmessagebox.h" #include "qclipboard.h" // mitk #include "mitkImage.h" #include "mitkImageCast.h" #include "mitkLookupTable.h" #include "mitkLookupTableProperty.h" #include #include // itk #include "itkScalarImageToHistogramGenerator.h" #include "itkRegionOfInterestImageFilter.h" #include "itkImageRegionConstIteratorWithIndex.h" // itk/mitk #include "itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h" #include "itkRegularizedIVIMReconstructionFilter.h" #include "mitkImageCast.h" #include const std::string QmitkIVIMView::VIEW_ID = "org.mitk.views.ivim"; QmitkIVIMView::QmitkIVIMView() - : QmitkAbstractView() - , m_Controls( 0 ) - , m_SliceObserverTag1(0), m_SliceObserverTag2(0), m_SliceObserverTag3(0) - , m_DiffusionImageNode(nullptr) - , m_MaskImageNode(nullptr) - , m_Active(false) - , m_Visible(false) - , m_HoldUpdate(false) + : QmitkAbstractView() + , m_Controls( 0 ) + , m_SliceObserverTag1(0), m_SliceObserverTag2(0), m_SliceObserverTag3(0) + , m_DiffusionImageNode(nullptr) + , m_MaskImageNode(nullptr) + , m_Active(false) + , m_Visible(false) + , m_HoldUpdate(false) { } QmitkIVIMView::~QmitkIVIMView() { } void QmitkIVIMView::CreateQtPartControl( QWidget *parent ) { // hold update untill all elements are set this->m_HoldUpdate = true; - // build up qt view, unless already done - if ( !m_Controls ) - { - // create GUI widgets from the Qt Designer's .ui file - m_Controls = new Ui::QmitkIVIMViewControls; - m_Controls->setupUi( parent ); - - connect( m_Controls->m_ButtonStart, SIGNAL(clicked()), this, SLOT(FittIVIMStart()) ); - connect( m_Controls->m_ButtonAutoThres, SIGNAL(clicked()), this, SLOT(AutoThreshold()) ); - - connect( m_Controls->m_MethodCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(MethodCombo(int)) ); - - connect( m_Controls->m_DStarSlider, SIGNAL(valueChanged(int)), this, SLOT(DStarSlider(int)) ); - connect( m_Controls->m_BThreshSlider, SIGNAL(valueChanged(int)), this, SLOT(BThreshSlider(int)) ); - connect( m_Controls->m_S0ThreshSlider, SIGNAL(valueChanged(int)), this, SLOT(S0ThreshSlider(int)) ); - connect( m_Controls->m_NumItSlider, SIGNAL(valueChanged(int)), this, SLOT(NumItsSlider(int)) ); - connect( m_Controls->m_LambdaSlider, SIGNAL(valueChanged(int)), this, SLOT(LambdaSlider(int)) ); - - connect( m_Controls->m_CheckDStar, SIGNAL(clicked()), this, SLOT(Checkbox()) ); - connect( m_Controls->m_CheckD, SIGNAL(clicked()), this, SLOT(Checkbox()) ); - connect( m_Controls->m_Checkf, SIGNAL(clicked()), this, SLOT(Checkbox()) ); - - connect( m_Controls->m_ChooseMethod, SIGNAL(clicked()), this, SLOT(ChooseMethod()) ); - connect( m_Controls->m_CurveClipboard, SIGNAL(clicked()), this, SLOT(ClipboardCurveButtonClicked()) ); - connect( m_Controls->m_ValuesClipboard, SIGNAL(clicked()), this, SLOT(ClipboardStatisticsButtonClicked()) ); - - // connect all kurtosis actions to a recompute - connect( m_Controls->m_KurtosisRangeWidget, SIGNAL( rangeChanged(double, double)), this, SLOT(OnKurtosisParamsChanged() ) ); - //connect( m_Controls->m_MaximalBValueWidget, SIGNAL( valueChanged(double)), this, SLOT( OnKurtosisParamsChanged() ) ); - connect( m_Controls->m_OmitBZeroCB, SIGNAL( stateChanged(int) ), this, SLOT( OnKurtosisParamsChanged() ) ); - connect( m_Controls->m_KurtosisFitScale, SIGNAL( currentIndexChanged(int)), this, SLOT( OnKurtosisParamsChanged() ) ); - connect( m_Controls->m_UseKurtosisBoundsCB, SIGNAL(clicked() ), this, SLOT( OnKurtosisParamsChanged() ) ); - } + // build up qt view, unless already done + if ( !m_Controls ) + { + // create GUI widgets from the Qt Designer's .ui file + m_Controls = new Ui::QmitkIVIMViewControls; + m_Controls->setupUi( parent ); + + connect( m_Controls->m_ButtonStart, SIGNAL(clicked()), this, SLOT(FittIVIMStart()) ); + connect( m_Controls->m_ButtonAutoThres, SIGNAL(clicked()), this, SLOT(AutoThreshold()) ); + + connect( m_Controls->m_MethodCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(MethodCombo(int)) ); + + connect( m_Controls->m_DStarSlider, SIGNAL(valueChanged(int)), this, SLOT(DStarSlider(int)) ); + connect( m_Controls->m_BThreshSlider, SIGNAL(valueChanged(int)), this, SLOT(BThreshSlider(int)) ); + connect( m_Controls->m_S0ThreshSlider, SIGNAL(valueChanged(int)), this, SLOT(S0ThreshSlider(int)) ); + connect( m_Controls->m_NumItSlider, SIGNAL(valueChanged(int)), this, SLOT(NumItsSlider(int)) ); + connect( m_Controls->m_LambdaSlider, SIGNAL(valueChanged(int)), this, SLOT(LambdaSlider(int)) ); + + connect( m_Controls->m_CheckDStar, SIGNAL(clicked()), this, SLOT(Checkbox()) ); + connect( m_Controls->m_CheckD, SIGNAL(clicked()), this, SLOT(Checkbox()) ); + connect( m_Controls->m_Checkf, SIGNAL(clicked()), this, SLOT(Checkbox()) ); + + connect( m_Controls->m_ChooseMethod, SIGNAL(clicked()), this, SLOT(ChooseMethod()) ); + connect( m_Controls->m_CurveClipboard, SIGNAL(clicked()), this, SLOT(ClipboardCurveButtonClicked()) ); + connect( m_Controls->m_ValuesClipboard, SIGNAL(clicked()), this, SLOT(ClipboardStatisticsButtonClicked()) ); + + // connect all kurtosis actions to a recompute + connect( m_Controls->m_KurtosisRangeWidget, SIGNAL( rangeChanged(double, double)), this, SLOT(OnKurtosisParamsChanged() ) ); + //connect( m_Controls->m_MaximalBValueWidget, SIGNAL( valueChanged(double)), this, SLOT( OnKurtosisParamsChanged() ) ); + connect( m_Controls->m_OmitBZeroCB, SIGNAL( stateChanged(int) ), this, SLOT( OnKurtosisParamsChanged() ) ); + connect( m_Controls->m_KurtosisFitScale, SIGNAL( currentIndexChanged(int)), this, SLOT( OnKurtosisParamsChanged() ) ); + connect( m_Controls->m_UseKurtosisBoundsCB, SIGNAL(clicked() ), this, SLOT( OnKurtosisParamsChanged() ) ); + } - QString dstar = QString::number(m_Controls->m_DStarSlider->value()/1000.0); - m_Controls->m_DStarLabel->setText(dstar); + QString dstar = QString::number(m_Controls->m_DStarSlider->value()/1000.0); + m_Controls->m_DStarLabel->setText(dstar); - QString bthresh = QString::number(m_Controls->m_BThreshSlider->value()*5.0); - m_Controls->m_BThreshLabel->setText(bthresh); + QString bthresh = QString::number(m_Controls->m_BThreshSlider->value()*5.0); + m_Controls->m_BThreshLabel->setText(bthresh); - QString s0thresh = QString::number(m_Controls->m_S0ThreshSlider->value()*0.5); - m_Controls->m_S0ThreshLabel->setText(s0thresh); + QString s0thresh = QString::number(m_Controls->m_S0ThreshSlider->value()*0.5); + m_Controls->m_S0ThreshLabel->setText(s0thresh); - QString numits = QString::number(m_Controls->m_NumItSlider->value()); - m_Controls->m_NumItsLabel->setText(numits); + QString numits = QString::number(m_Controls->m_NumItSlider->value()); + m_Controls->m_NumItsLabel->setText(numits); - QString lambda = QString::number(m_Controls->m_LambdaSlider->value()*.00001); - m_Controls->m_LambdaLabel->setText(lambda); + QString lambda = QString::number(m_Controls->m_LambdaSlider->value()*.00001); + m_Controls->m_LambdaLabel->setText(lambda); - m_Controls->m_MethodCombo->setVisible(m_Controls->m_ChooseMethod->isChecked()); - m_Controls->m_Warning->setVisible(false); + m_Controls->m_MethodCombo->setVisible(m_Controls->m_ChooseMethod->isChecked()); + m_Controls->m_Warning->setVisible(false); - MethodCombo(m_Controls->m_MethodCombo->currentIndex()); + MethodCombo(m_Controls->m_MethodCombo->currentIndex()); - m_Controls->m_KurtosisRangeWidget->setSingleStep(0.1); - m_Controls->m_KurtosisRangeWidget->setRange( 0.0, 10.0 ); - m_Controls->m_KurtosisRangeWidget->setMaximumValue( 5.0 ); + m_Controls->m_KurtosisRangeWidget->setSingleStep(0.1); + m_Controls->m_KurtosisRangeWidget->setRange( 0.0, 10.0 ); + m_Controls->m_KurtosisRangeWidget->setMaximumValue( 5.0 ); - // LogScale not working yet, have to fix that first - // m_Controls->m_KurtosisFitScale->setEnabled(false); + // LogScale not working yet, have to fix that first + // m_Controls->m_KurtosisFitScale->setEnabled(false); - //m_Controls->m_MaximalBValueWidget->setVisible( false ); + //m_Controls->m_MaximalBValueWidget->setVisible( false ); - // release update block after the UI-elements were all set - this->m_HoldUpdate = false; + // release update block after the UI-elements were all set + this->m_HoldUpdate = false; } void QmitkIVIMView::SetFocus() { m_Controls->m_ButtonAutoThres->setFocus(); } void QmitkIVIMView::Checkbox() { - itk::StartEvent dummy; - OnSliceChanged(dummy); + itk::StartEvent dummy; + OnSliceChanged(dummy); } void QmitkIVIMView::MethodCombo(int val) { - switch(val) - { - case 0: - m_Controls->m_DstarFrame->setVisible(false); - m_Controls->m_NeglSiFrame->setVisible(true); - m_Controls->m_NeglBframe->setVisible(false); - m_Controls->m_IterationsFrame->setVisible(false); - m_Controls->m_LambdaFrame->setVisible(false); - break; - case 1: - m_Controls->m_DstarFrame->setVisible(true); - m_Controls->m_NeglSiFrame->setVisible(true); - m_Controls->m_NeglBframe->setVisible(false); - m_Controls->m_IterationsFrame->setVisible(false); - m_Controls->m_LambdaFrame->setVisible(false); - break; - case 2: - m_Controls->m_DstarFrame->setVisible(false); - m_Controls->m_NeglSiFrame->setVisible(true); - m_Controls->m_NeglBframe->setVisible(true); - m_Controls->m_IterationsFrame->setVisible(false); - m_Controls->m_LambdaFrame->setVisible(false); - break; - case 3: - m_Controls->m_DstarFrame->setVisible(false); - m_Controls->m_NeglSiFrame->setVisible(true); - m_Controls->m_NeglBframe->setVisible(true); - m_Controls->m_IterationsFrame->setVisible(false); - m_Controls->m_LambdaFrame->setVisible(false); - break; - case 4: - m_Controls->m_DstarFrame->setVisible(false); - m_Controls->m_NeglSiFrame->setVisible(false); - m_Controls->m_NeglBframe->setVisible(false); - m_Controls->m_IterationsFrame->setVisible(false); - m_Controls->m_LambdaFrame->setVisible(false); - break; - } + switch(val) + { + case 0: + m_Controls->m_DstarFrame->setVisible(false); + m_Controls->m_NeglSiFrame->setVisible(true); + m_Controls->m_NeglBframe->setVisible(false); + m_Controls->m_IterationsFrame->setVisible(false); + m_Controls->m_LambdaFrame->setVisible(false); + break; + case 1: + m_Controls->m_DstarFrame->setVisible(true); + m_Controls->m_NeglSiFrame->setVisible(true); + m_Controls->m_NeglBframe->setVisible(false); + m_Controls->m_IterationsFrame->setVisible(false); + m_Controls->m_LambdaFrame->setVisible(false); + break; + case 2: + m_Controls->m_DstarFrame->setVisible(false); + m_Controls->m_NeglSiFrame->setVisible(true); + m_Controls->m_NeglBframe->setVisible(true); + m_Controls->m_IterationsFrame->setVisible(false); + m_Controls->m_LambdaFrame->setVisible(false); + break; + case 3: + m_Controls->m_DstarFrame->setVisible(false); + m_Controls->m_NeglSiFrame->setVisible(true); + m_Controls->m_NeglBframe->setVisible(true); + m_Controls->m_IterationsFrame->setVisible(false); + m_Controls->m_LambdaFrame->setVisible(false); + break; + case 4: + m_Controls->m_DstarFrame->setVisible(false); + m_Controls->m_NeglSiFrame->setVisible(false); + m_Controls->m_NeglBframe->setVisible(false); + m_Controls->m_IterationsFrame->setVisible(false); + m_Controls->m_LambdaFrame->setVisible(false); + break; + } - itk::StartEvent dummy; - OnSliceChanged(dummy); + itk::StartEvent dummy; + OnSliceChanged(dummy); } void QmitkIVIMView::DStarSlider (int val) { - QString sval = QString::number(val/1000.0); - m_Controls->m_DStarLabel->setText(sval); + QString sval = QString::number(val/1000.0); + m_Controls->m_DStarLabel->setText(sval); - itk::StartEvent dummy; - OnSliceChanged(dummy); + itk::StartEvent dummy; + OnSliceChanged(dummy); } void QmitkIVIMView::BThreshSlider (int val) { - QString sval = QString::number(val*5.0); - m_Controls->m_BThreshLabel->setText(sval); + QString sval = QString::number(val*5.0); + m_Controls->m_BThreshLabel->setText(sval); - itk::StartEvent dummy; - OnSliceChanged(dummy); + itk::StartEvent dummy; + OnSliceChanged(dummy); } void QmitkIVIMView::S0ThreshSlider (int val) { - QString sval = QString::number(val*0.5); - m_Controls->m_S0ThreshLabel->setText(sval); + QString sval = QString::number(val*0.5); + m_Controls->m_S0ThreshLabel->setText(sval); - itk::StartEvent dummy; - OnSliceChanged(dummy); + itk::StartEvent dummy; + OnSliceChanged(dummy); } void QmitkIVIMView::NumItsSlider (int val) { - QString sval = QString::number(val); - m_Controls->m_NumItsLabel->setText(sval); + QString sval = QString::number(val); + m_Controls->m_NumItsLabel->setText(sval); - itk::StartEvent dummy; - OnSliceChanged(dummy); + itk::StartEvent dummy; + OnSliceChanged(dummy); } void QmitkIVIMView::LambdaSlider (int val) { - QString sval = QString::number(val*.00001); - m_Controls->m_LambdaLabel->setText(sval); + QString sval = QString::number(val*.00001); + m_Controls->m_LambdaLabel->setText(sval); - itk::StartEvent dummy; - OnSliceChanged(dummy); + itk::StartEvent dummy; + OnSliceChanged(dummy); } void QmitkIVIMView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& nodes) { - bool foundOneDiffusionImage = false; - m_Controls->m_InputData->setTitle("Please Select Input Data"); - m_Controls->m_DiffusionImageLabel->setText("mandatory"); - m_Controls->m_MaskImageLabel->setText("optional"); - m_MaskImageNode = nullptr; - m_DiffusionImageNode = nullptr; - - // iterate all selected objects, adjust warning visibility - for (auto node: nodes) + bool foundOneDiffusionImage = false; + m_Controls->m_InputData->setTitle("Please Select Input Data"); + m_Controls->m_DiffusionImageLabel->setText("mandatory"); + m_Controls->m_MaskImageLabel->setText("optional"); + m_MaskImageNode = nullptr; + m_DiffusionImageNode = nullptr; + + // iterate all selected objects, adjust warning visibility + for (auto node: nodes) + { + if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { - if( node.IsNotNull() && dynamic_cast(node->GetData()) ) + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(node->GetData())) ); + + if( isDiffusionImage ) + { + m_DiffusionImageNode = node; + foundOneDiffusionImage = true; + m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str()); + } + else + { + bool isBinary = false; + node->GetPropertyValue("binary", isBinary); + if (isBinary) { - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(node->GetData())) ); - - if( isDiffusionImage ) - { - m_DiffusionImageNode = node; - foundOneDiffusionImage = true; - m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str()); - } - else - { - bool isBinary = false; - node->GetPropertyValue("binary", isBinary); - if (isBinary) - { - m_MaskImageNode = node; - m_Controls->m_MaskImageLabel->setText(node->GetName().c_str()); - } - } + m_MaskImageNode = node; + m_Controls->m_MaskImageLabel->setText(node->GetName().c_str()); } + } } + } - if (m_DiffusionImageNode.IsNotNull()) - { - m_Controls->m_VisualizeResultsWidget->setVisible(true); - m_Controls->m_KurtosisVisualizationWidget->setVisible(true); - m_Controls->m_InputData->setTitle("Input Data"); + if (m_DiffusionImageNode.IsNotNull()) + { + m_Controls->m_VisualizeResultsWidget->setVisible(true); + m_Controls->m_KurtosisVisualizationWidget->setVisible(true); + m_Controls->m_InputData->setTitle("Input Data"); - m_HoldUpdate = false; - } - else - { - m_Controls->m_VisualizeResultsWidget->setVisible(false); - m_Controls->m_KurtosisVisualizationWidget->setVisible(false); - m_Controls->m_DiffusionImageLabel->setText("mandatory"); - } + m_HoldUpdate = false; + } + else + { + m_Controls->m_VisualizeResultsWidget->setVisible(false); + m_Controls->m_KurtosisVisualizationWidget->setVisible(false); + m_Controls->m_DiffusionImageLabel->setText("mandatory"); + } - m_Controls->m_ButtonStart->setEnabled( foundOneDiffusionImage ); - m_Controls->m_ButtonAutoThres->setEnabled( foundOneDiffusionImage ); + m_Controls->m_ButtonStart->setEnabled( foundOneDiffusionImage ); + m_Controls->m_ButtonAutoThres->setEnabled( foundOneDiffusionImage ); - m_Controls->m_ControlsFrame->setEnabled( foundOneDiffusionImage ); - m_Controls->m_BottomControlsFrame->setEnabled( foundOneDiffusionImage ); + m_Controls->m_ControlsFrame->setEnabled( foundOneDiffusionImage ); + m_Controls->m_BottomControlsFrame->setEnabled( foundOneDiffusionImage ); - itk::StartEvent dummy; - OnSliceChanged(dummy); + itk::StartEvent dummy; + OnSliceChanged(dummy); } void QmitkIVIMView::AutoThreshold() { - QList nodes = this->GetDataManagerSelection(); - if (nodes.empty()) return; + QList nodes = this->GetDataManagerSelection(); + if (nodes.empty()) return; - if (!nodes.front()) - { - // Nothing selected. Inform the user and return - QMessageBox::information( nullptr, "Template", "Please load and select a diffusion image before starting image processing."); - return; - } + if (!nodes.front()) + { + // Nothing selected. Inform the user and return + QMessageBox::information( nullptr, "Template", "Please load and select a diffusion image before starting image processing."); + return; + } - mitk::Image* dimg = dynamic_cast(nodes.front()->GetData()); + mitk::Image* dimg = dynamic_cast(nodes.front()->GetData()); - if (!dimg) - { - // Nothing selected. Inform the user and return - QMessageBox::information( nullptr, "Template", "No valid diffusion image was found."); - return; - } + if (!dimg) + { + // Nothing selected. Inform the user and return + QMessageBox::information( nullptr, "Template", "No valid diffusion image was found."); + return; + } - // find bzero index - int index = -1; - DirContainerType::Pointer directions = static_cast( dimg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); - for(DirContainerType::ConstIterator it = directions->Begin(); - it != directions->End(); ++it) - { - index++; - GradientDirectionType g = it.Value(); - if(g[0] == 0 && g[1] == 0 && g[2] == 0 ) - break; - } + // find bzero index + int index = -1; + DirContainerType::Pointer directions = static_cast( dimg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); + for(DirContainerType::ConstIterator it = directions->Begin(); + it != directions->End(); ++it) + { + index++; + GradientDirectionType g = it.Value(); + if(g[0] == 0 && g[1] == 0 && g[2] == 0 ) + break; + } - VecImgType::Pointer vecimg = VecImgType::New(); - mitk::CastToItkImage(dimg, vecimg); + VecImgType::Pointer vecimg = VecImgType::New(); + mitk::CastToItkImage(dimg, vecimg); - int vecLength = vecimg->GetVectorLength(); - index = index > vecLength-1 ? vecLength-1 : index; + int vecLength = vecimg->GetVectorLength(); + index = index > vecLength-1 ? vecLength-1 : index; - MITK_INFO << "Performing Histogram Analysis on Channel" << index; + MITK_INFO << "Performing Histogram Analysis on Channel" << index; - typedef itk::Image ImgType; - ImgType::Pointer img = ImgType::New(); - mitk::CastToItkImage(dimg, img); + typedef itk::Image ImgType; + ImgType::Pointer img = ImgType::New(); + mitk::CastToItkImage(dimg, img); - itk::ImageRegionIterator itw (img, img->GetLargestPossibleRegion() ); - itw.GoToBegin(); + itk::ImageRegionIterator itw (img, img->GetLargestPossibleRegion() ); + itw.GoToBegin(); - itk::ImageRegionConstIterator itr (vecimg, vecimg->GetLargestPossibleRegion() ); - itr.GoToBegin(); + itk::ImageRegionConstIterator itr (vecimg, vecimg->GetLargestPossibleRegion() ); + itr.GoToBegin(); - while(!itr.IsAtEnd()) - { - itw.Set(itr.Get().GetElement(index)); - ++itr; - ++itw; - } + while(!itr.IsAtEnd()) + { + itw.Set(itr.Get().GetElement(index)); + ++itr; + ++itw; + } - typedef itk::Statistics::ScalarImageToHistogramGenerator< ImgType > - HistogramGeneratorType; - typedef HistogramGeneratorType::HistogramType HistogramType; - - HistogramGeneratorType::Pointer histogramGenerator = HistogramGeneratorType::New(); - histogramGenerator->SetInput( img ); - histogramGenerator->SetMarginalScale( 10 ); // Defines y-margin width of histogram - histogramGenerator->SetNumberOfBins( 100 ); // CT range [-1024, +2048] --> bin size 4 values - histogramGenerator->SetHistogramMin( dimg->GetStatistics()->GetScalarValueMin() ); - histogramGenerator->SetHistogramMax( dimg->GetStatistics()->GetScalarValueMax() * .5 ); - histogramGenerator->Compute(); - - HistogramType::ConstIterator iter = histogramGenerator->GetOutput()->Begin(); - float maxFreq = 0; - float maxValue = 0; - while ( iter != histogramGenerator->GetOutput()->End() ) + typedef itk::Statistics::ScalarImageToHistogramGenerator< ImgType > + HistogramGeneratorType; + typedef HistogramGeneratorType::HistogramType HistogramType; + + HistogramGeneratorType::Pointer histogramGenerator = HistogramGeneratorType::New(); + histogramGenerator->SetInput( img ); + histogramGenerator->SetMarginalScale( 10 ); // Defines y-margin width of histogram + histogramGenerator->SetNumberOfBins( 100 ); // CT range [-1024, +2048] --> bin size 4 values + histogramGenerator->SetHistogramMin( dimg->GetStatistics()->GetScalarValueMin() ); + histogramGenerator->SetHistogramMax( dimg->GetStatistics()->GetScalarValueMax() * .5 ); + histogramGenerator->Compute(); + + HistogramType::ConstIterator iter = histogramGenerator->GetOutput()->Begin(); + float maxFreq = 0; + float maxValue = 0; + while ( iter != histogramGenerator->GetOutput()->End() ) + { + if(iter.GetFrequency() > maxFreq) { - if(iter.GetFrequency() > maxFreq) - { - maxFreq = iter.GetFrequency(); - maxValue = iter.GetMeasurementVector()[0]; - } - ++iter; + maxFreq = iter.GetFrequency(); + maxValue = iter.GetMeasurementVector()[0]; } + ++iter; + } - maxValue *= 2; + maxValue *= 2; - int sliderPos = maxValue * 2; - m_Controls->m_S0ThreshSlider->setValue(sliderPos); - S0ThreshSlider(sliderPos); + int sliderPos = maxValue * 2; + m_Controls->m_S0ThreshSlider->setValue(sliderPos); + S0ThreshSlider(sliderPos); } void QmitkIVIMView::FittIVIMStart() { - QList nodes = this->GetDataManagerSelection(); + QList nodes = this->GetDataManagerSelection(); - mitk::Image* img = 0; - for ( int i=0; i(nodes.at(i)->GetData()); + mitk::Image* img = 0; + for ( int i=0; i(nodes.at(i)->GetData()); - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(nodes.at(i)->GetData())) ); + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(nodes.at(i)->GetData())) ); - if (img && isDiffusionImage) - break; - } + if (img && isDiffusionImage) + break; + } - if (!img) - { - QMessageBox::information( nullptr, "Template", "No valid diffusion-weighted image selected."); - return; - } + if (!img) + { + QMessageBox::information( nullptr, "Template", "No valid diffusion-weighted image selected."); + return; + } - VecImgType::Pointer vecimg = VecImgType::New(); - mitk::CastToItkImage(img, vecimg); + VecImgType::Pointer vecimg = VecImgType::New(); + mitk::CastToItkImage(img, vecimg); - OutImgType::IndexType dummy; + OutImgType::IndexType dummy; - if( m_Controls->m_ModelTabSelectionWidget->currentIndex() ) - { - // KURTOSIS - KurtosisFilterType::Pointer filter = KurtosisFilterType::New(); - filter->SetInput(vecimg); - filter->SetReferenceBValue( static_cast(img->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); - filter->SetGradientDirections( static_cast( img->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); - filter->SetSmoothingSigma( this->m_Controls->m_SigmaSpinBox->value() ); + if( m_Controls->m_ModelTabSelectionWidget->currentIndex() ) + { + // KURTOSIS + KurtosisFilterType::Pointer filter = KurtosisFilterType::New(); + filter->SetInput(vecimg); + filter->SetReferenceBValue( static_cast(img->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); + filter->SetGradientDirections( static_cast( img->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); + filter->SetSmoothingSigma( this->m_Controls->m_SigmaSpinBox->value() ); - if( this->m_Controls->m_UseKurtosisBoundsCB->isChecked() ) - filter->SetBoundariesForKurtosis( this->m_Controls->m_KurtosisRangeWidget->minimumValue(), this->m_Controls->m_KurtosisRangeWidget->maximumValue() ); + if( this->m_Controls->m_UseKurtosisBoundsCB->isChecked() ) + filter->SetBoundariesForKurtosis( this->m_Controls->m_KurtosisRangeWidget->minimumValue(), this->m_Controls->m_KurtosisRangeWidget->maximumValue() ); - filter->SetFittingScale( static_cast(this->m_Controls->m_KurtosisFitScale->currentIndex() ) ); + filter->SetFittingScale( static_cast(this->m_Controls->m_KurtosisFitScale->currentIndex() ) ); - if( m_MaskImageNode.IsNotNull() ) - { - mitk::Image::Pointer maskImg = dynamic_cast(m_MaskImageNode->GetData()); - typedef itk::Image MaskImgType; + if( m_MaskImageNode.IsNotNull() ) + { + mitk::Image::Pointer maskImg = dynamic_cast(m_MaskImageNode->GetData()); + typedef itk::Image MaskImgType; - MaskImgType::Pointer maskItk; - CastToItkImage( maskImg, maskItk ); + MaskImgType::Pointer maskItk; + CastToItkImage( maskImg, maskItk ); - filter->SetImageMask( maskItk ); - } + filter->SetImageMask( maskItk ); + } - filter->Update(); + filter->Update(); - mitk::LookupTable::Pointer kurt_map_lut = mitk::LookupTable::New(); - kurt_map_lut->SetType( mitk::LookupTable::JET_TRANSPARENT ); - mitk::LookupTableProperty::Pointer kurt_lut_prop = - mitk::LookupTableProperty::New(); - kurt_lut_prop->SetLookupTable( kurt_map_lut ); + mitk::LookupTable::Pointer kurt_map_lut = mitk::LookupTable::New(); + kurt_map_lut->SetType( mitk::LookupTable::JET_TRANSPARENT ); + mitk::LookupTableProperty::Pointer kurt_lut_prop = + mitk::LookupTableProperty::New(); + kurt_lut_prop->SetLookupTable( kurt_map_lut ); - mitk::Image::Pointer dimage = mitk::Image::New(); - dimage->InitializeByItk( filter->GetOutput(0) ); - dimage->SetVolume( filter->GetOutput(0)->GetBufferPointer()); + mitk::Image::Pointer dimage = mitk::Image::New(); + dimage->InitializeByItk( filter->GetOutput(0) ); + dimage->SetVolume( filter->GetOutput(0)->GetBufferPointer()); - mitk::Image::Pointer kimage = mitk::Image::New(); - kimage->InitializeByItk( filter->GetOutput(1) ); - kimage->SetVolume( filter->GetOutput(1)->GetBufferPointer()); + mitk::Image::Pointer kimage = mitk::Image::New(); + kimage->InitializeByItk( filter->GetOutput(1) ); + kimage->SetVolume( filter->GetOutput(1)->GetBufferPointer()); - QString new_dname = "Kurtosis_DMap"; - new_dname.append("_Method-"+m_Controls->m_KurtosisFitScale->currentText()); - QString new_kname = "Kurtosis_KMap"; - new_kname.append("_Method-"+m_Controls->m_KurtosisFitScale->currentText()); - - if( this->m_Controls->m_CheckKurtD->isChecked() ) - { - mitk::DataNode::Pointer dnode = mitk::DataNode::New(); - dnode->SetData( dimage ); - dnode->SetName(new_dname.toLatin1()); - dnode->SetProperty("LookupTable", kurt_lut_prop ); - GetDataStorage()->Add(dnode, nodes.front()); - } - - if( this->m_Controls->m_CheckKurtK->isChecked() ) - { - mitk::DataNode::Pointer knode = mitk::DataNode::New(); - knode->SetData( kimage ); - knode->SetName(new_kname.toLatin1()); - knode->SetProperty("LookupTable", kurt_lut_prop ); - GetDataStorage()->Add(knode, nodes.front()); - } + QString new_dname = "Kurtosis_DMap"; + new_dname.append("_Method-"+m_Controls->m_KurtosisFitScale->currentText()); + QString new_kname = "Kurtosis_KMap"; + new_kname.append("_Method-"+m_Controls->m_KurtosisFitScale->currentText()); + if( this->m_Controls->m_CheckKurtD->isChecked() ) + { + mitk::DataNode::Pointer dnode = mitk::DataNode::New(); + dnode->SetData( dimage ); + dnode->SetName(new_dname.toLatin1()); + dnode->SetProperty("LookupTable", kurt_lut_prop ); + GetDataStorage()->Add(dnode, nodes.front()); } - else + + if( this->m_Controls->m_CheckKurtK->isChecked() ) { - FittIVIM(vecimg, + mitk::DataNode::Pointer knode = mitk::DataNode::New(); + knode->SetData( kimage ); + knode->SetName(new_kname.toLatin1()); + knode->SetProperty("LookupTable", kurt_lut_prop ); + GetDataStorage()->Add(knode, nodes.front()); + } + + } + else + { + FittIVIM(vecimg, static_cast( img->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), static_cast(img->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(), true, dummy); - OutputToDatastorage(nodes); - } + OutputToDatastorage(nodes); + } } void QmitkIVIMView::OnKurtosisParamsChanged() { itk::StartEvent dummy; OnSliceChanged(dummy); } void QmitkIVIMView::OnSliceChanged(const itk::EventObject& /*e*/) { - if(!m_Visible) - return; + if(!m_Visible) + return; - if(m_HoldUpdate) - return; + if(m_HoldUpdate) + return; - m_Controls->m_Warning->setVisible(false); - if(!m_Controls || m_DiffusionImageNode.IsNull()) - return; + m_Controls->m_Warning->setVisible(false); + if(!m_Controls || m_DiffusionImageNode.IsNull()) + return; - m_Controls->m_VisualizeResultsWidget->setVisible(false); - m_Controls->m_KurtosisVisualizationWidget->setVisible(false); + m_Controls->m_VisualizeResultsWidget->setVisible(false); + m_Controls->m_KurtosisVisualizationWidget->setVisible(false); - mitk::Image::Pointer diffusionImg = dynamic_cast(m_DiffusionImageNode->GetData()); - mitk::Image::Pointer maskImg = nullptr; - if (m_MaskImageNode.IsNotNull()) - maskImg = dynamic_cast(m_MaskImageNode->GetData()); + mitk::Image::Pointer diffusionImg = dynamic_cast(m_DiffusionImageNode->GetData()); + mitk::Image::Pointer maskImg = nullptr; + if (m_MaskImageNode.IsNotNull()) + maskImg = dynamic_cast(m_MaskImageNode->GetData()); - if (!this->GetRenderWindowPart()) return; + if (!this->GetRenderWindowPart()) return; - VecImgType::Pointer vecimg = VecImgType::New(); - mitk::CastToItkImage(diffusionImg, vecimg); + VecImgType::Pointer vecimg = VecImgType::New(); + mitk::CastToItkImage(diffusionImg, vecimg); - VecImgType::Pointer roiImage = VecImgType::New(); + VecImgType::Pointer roiImage = VecImgType::New(); + + bool success = false; + if(maskImg.IsNull()) + { + int roisize = 0; + if(m_Controls->m_MethodCombo->currentIndex() == 4) + roisize = 5; - bool success = false; - if(maskImg.IsNull()) + mitk::Point3D pos = this->GetRenderWindowPart()->GetSelectedPosition(); + + VecImgType::IndexType crosspos; + diffusionImg->GetGeometry()->WorldToIndex(pos, crosspos); + if (!vecimg->GetLargestPossibleRegion().IsInside(crosspos)) { - int roisize = 0; - if(m_Controls->m_MethodCombo->currentIndex() == 4) - roisize = 5; + m_Controls->m_Warning->setText(QString("Crosshair position not inside of selected diffusion weighted image. Reinit needed!")); + m_Controls->m_Warning->setVisible(true); + return; + } + else + m_Controls->m_Warning->setVisible(false); - mitk::Point3D pos = this->GetRenderWindowPart()->GetSelectedPosition(); + VecImgType::IndexType index; + index[0] = crosspos[0] - roisize; index[0] = index[0] < 0 ? 0 : index[0]; + index[1] = crosspos[1] - roisize; index[1] = index[1] < 0 ? 0 : index[1]; + index[2] = crosspos[2] - roisize; index[2] = index[2] < 0 ? 0 : index[2]; - VecImgType::IndexType crosspos; - diffusionImg->GetGeometry()->WorldToIndex(pos, crosspos); - if (!vecimg->GetLargestPossibleRegion().IsInside(crosspos)) - { - m_Controls->m_Warning->setText(QString("Crosshair position not inside of selected diffusion weighted image. Reinit needed!")); - m_Controls->m_Warning->setVisible(true); - return; - } - else - m_Controls->m_Warning->setVisible(false); - - VecImgType::IndexType index; - index[0] = crosspos[0] - roisize; index[0] = index[0] < 0 ? 0 : index[0]; - index[1] = crosspos[1] - roisize; index[1] = index[1] < 0 ? 0 : index[1]; - index[2] = crosspos[2] - roisize; index[2] = index[2] < 0 ? 0 : index[2]; - - VecImgType::SizeType size; - size[0] = roisize*2+1; - size[1] = roisize*2+1; - size[2] = roisize*2+1; - - VecImgType::SizeType maxSize = vecimg->GetLargestPossibleRegion().GetSize(); - size[0] = index[0]+size[0] > maxSize[0] ? maxSize[0]-index[0] : size[0]; - size[1] = index[1]+size[1] > maxSize[1] ? maxSize[1]-index[1] : size[1]; - size[2] = index[2]+size[2] > maxSize[2] ? maxSize[2]-index[2] : size[2]; - - VecImgType::RegionType region; - region.SetSize( size ); - region.SetIndex( index ); - vecimg->SetRequestedRegion( region ); - - VecImgType::IndexType newstart; - newstart.Fill(0); - - VecImgType::RegionType newregion; - newregion.SetSize( size ); - newregion.SetIndex( newstart ); - - roiImage->CopyInformation( vecimg ); - roiImage->SetRegions( newregion ); - roiImage->SetOrigin( pos ); - roiImage->Allocate(); - roiImage->SetPixel(newstart, vecimg->GetPixel(index)); - - if( m_Controls->m_ModelTabSelectionWidget->currentIndex() ) - { - success = FitKurtosis(roiImage, - static_cast( diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), - static_cast(diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(), - newstart); - } - else - { - success = FittIVIM(roiImage, - static_cast( diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), - static_cast(diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(), - false, - crosspos); - } + VecImgType::SizeType size; + size[0] = roisize*2+1; + size[1] = roisize*2+1; + size[2] = roisize*2+1; + + VecImgType::SizeType maxSize = vecimg->GetLargestPossibleRegion().GetSize(); + size[0] = index[0]+size[0] > maxSize[0] ? maxSize[0]-index[0] : size[0]; + size[1] = index[1]+size[1] > maxSize[1] ? maxSize[1]-index[1] : size[1]; + size[2] = index[2]+size[2] > maxSize[2] ? maxSize[2]-index[2] : size[2]; + + VecImgType::RegionType region; + region.SetSize( size ); + region.SetIndex( index ); + vecimg->SetRequestedRegion( region ); + + VecImgType::IndexType newstart; + newstart.Fill(0); + + VecImgType::RegionType newregion; + newregion.SetSize( size ); + newregion.SetIndex( newstart ); + + roiImage->CopyInformation( vecimg ); + roiImage->SetRegions( newregion ); + roiImage->SetOrigin( pos ); + roiImage->Allocate(); + roiImage->SetPixel(newstart, vecimg->GetPixel(index)); + + if( m_Controls->m_ModelTabSelectionWidget->currentIndex() ) + { + success = FitKurtosis(roiImage, + static_cast( diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), + static_cast(diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(), + newstart); } else { - typedef itk::Image MaskImgType; + success = FittIVIM(roiImage, + static_cast( diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), + static_cast(diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(), + false, + crosspos); + } + } + else + { + typedef itk::Image MaskImgType; - MaskImgType::Pointer maskItk; - CastToItkImage( maskImg, maskItk ); + MaskImgType::Pointer maskItk; + CastToItkImage( maskImg, maskItk ); - mitk::Point3D pos; - pos[0] = 0; - pos[1] = 0; - pos[2] = 0; + mitk::Point3D pos; + pos[0] = 0; + pos[1] = 0; + pos[2] = 0; - VecImgType::IndexType index; - index[0] = 0; - index[1] = 0; - index[2] = 0; + VecImgType::IndexType index; + index[0] = 0; + index[1] = 0; + index[2] = 0; - VecImgType::SizeType size; - size[0] = 1; - size[1] = 1; - size[2] = 1; + VecImgType::SizeType size; + size[0] = 1; + size[1] = 1; + size[2] = 1; - VecImgType::RegionType region; - region.SetSize( size ); - region.SetIndex( index ); - vecimg->SetRequestedRegion( region ); + VecImgType::RegionType region; + region.SetSize( size ); + region.SetIndex( index ); + vecimg->SetRequestedRegion( region ); - // iterators over output and input - itk::ImageRegionConstIteratorWithIndex - vecit(vecimg, vecimg->GetLargestPossibleRegion()); + // iterators over output and input + itk::ImageRegionConstIteratorWithIndex + vecit(vecimg, vecimg->GetLargestPossibleRegion()); - itk::VariableLengthVector avg(vecimg->GetVectorLength()); - avg.Fill(0); + itk::VariableLengthVector avg(vecimg->GetVectorLength()); + avg.Fill(0); - float numPixels = 0; - while ( ! vecit.IsAtEnd() ) - { - VecImgType::PointType point; - vecimg->TransformIndexToPhysicalPoint(vecit.GetIndex(), point); + float numPixels = 0; + while ( ! vecit.IsAtEnd() ) + { + VecImgType::PointType point; + vecimg->TransformIndexToPhysicalPoint(vecit.GetIndex(), point); - MaskImgType::IndexType index; - maskItk->TransformPhysicalPointToIndex(point, index); + MaskImgType::IndexType index; + maskItk->TransformPhysicalPointToIndex(point, index); - if(maskItk->GetPixel(index) != 0) - { - avg += vecit.Get(); - numPixels += 1.0; - } + if(maskItk->GetPixel(index) != 0) + { + avg += vecit.Get(); + numPixels += 1.0; + } - // update iterators - ++vecit; + // update iterators + ++vecit; - } + } - avg /= numPixels; + avg /= numPixels; - m_Controls->m_Warning->setText(QString("Averaging ")+QString::number((int)numPixels)+QString(" voxels!")); - m_Controls->m_Warning->setVisible(true); + m_Controls->m_Warning->setText(QString("Averaging ")+QString::number((int)numPixels)+QString(" voxels!")); + m_Controls->m_Warning->setVisible(true); - roiImage->CopyInformation( vecimg ); - roiImage->SetRegions( region ); - roiImage->SetOrigin( pos ); - roiImage->Allocate(); - roiImage->SetPixel(index, avg); + roiImage->CopyInformation( vecimg ); + roiImage->SetRegions( region ); + roiImage->SetOrigin( pos ); + roiImage->Allocate(); + roiImage->SetPixel(index, avg); - if( m_Controls->m_ModelTabSelectionWidget->currentIndex() ) - { - success = FitKurtosis(roiImage, - static_cast( diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), - static_cast(diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(), - index); - } - else - { - success = FittIVIM(roiImage, - static_cast( diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), - static_cast(diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(), - false, - index); - } + if( m_Controls->m_ModelTabSelectionWidget->currentIndex() ) + { + success = FitKurtosis(roiImage, + static_cast( diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), + static_cast(diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(), + index); + } + else + { + success = FittIVIM(roiImage, + static_cast( diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), + static_cast(diffusionImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(), + false, + index); + } - // do not update until selection changed, the values will remain the same as long as the mask is selected! - m_HoldUpdate = true; + // do not update until selection changed, the values will remain the same as long as the mask is selected! + m_HoldUpdate = true; - } + } - vecimg->SetRegions( vecimg->GetLargestPossibleRegion() ); + vecimg->SetRegions( vecimg->GetLargestPossibleRegion() ); - if (success) + if (success) + { + // 0 - IVIM, 1 - Kurtosis + if( m_Controls->m_ModelTabSelectionWidget->currentIndex() ) { - // 0 - IVIM, 1 - Kurtosis - if( m_Controls->m_ModelTabSelectionWidget->currentIndex() ) - { - m_Controls->m_KurtosisVisualizationWidget->setVisible(true); - m_Controls->m_KurtosisVisualizationWidget->SetData(m_KurtosisSnap); - } - else - { - m_Controls->m_VisualizeResultsWidget->setVisible(true); - m_Controls->m_VisualizeResultsWidget->SetParameters(m_Snap); - } + m_Controls->m_KurtosisVisualizationWidget->setVisible(true); + m_Controls->m_KurtosisVisualizationWidget->SetData(m_KurtosisSnap); + } + else + { + m_Controls->m_VisualizeResultsWidget->setVisible(true); + m_Controls->m_VisualizeResultsWidget->SetParameters(m_Snap); } + } } bool QmitkIVIMView::FitKurtosis( itk::VectorImage *vecimg, DirContainerType *dirs, float bval, OutImgType::IndexType &crosspos ) { KurtosisFilterType::Pointer filter = KurtosisFilterType::New(); itk::KurtosisFitConfiguration fit_config; fit_config.omit_bzero = this->m_Controls->m_OmitBZeroCB->isChecked(); if( this->m_Controls->m_UseKurtosisBoundsCB->isChecked() ) { fit_config.use_K_limits = true; vnl_vector_fixed k_limits; k_limits[0] = this->m_Controls->m_KurtosisRangeWidget->minimumValue(); k_limits[1] = this->m_Controls->m_KurtosisRangeWidget->maximumValue(); fit_config.K_limits = k_limits; } fit_config.fit_scale = static_cast(this->m_Controls->m_KurtosisFitScale->currentIndex() ); m_KurtosisSnap = filter->GetSnapshot( vecimg->GetPixel( crosspos ), dirs, bval, fit_config ); return true; } bool QmitkIVIMView::FittIVIM(itk::VectorImage* vecimg, DirContainerType* dirs, float bval, bool multivoxel, OutImgType::IndexType &crosspos) { - IVIMFilterType::Pointer filter = IVIMFilterType::New(); - filter->SetInput(vecimg); - filter->SetGradientDirections(dirs); - filter->SetBValue(bval); + IVIMFilterType::Pointer filter = IVIMFilterType::New(); + filter->SetInput(vecimg); + filter->SetGradientDirections(dirs); + filter->SetBValue(bval); - switch(m_Controls->m_MethodCombo->currentIndex()) - { + switch(m_Controls->m_MethodCombo->currentIndex()) + { - case 0: - filter->SetMethod(IVIMFilterType::IVIM_FIT_ALL); - filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble()); - break; - - case 1: - filter->SetMethod(IVIMFilterType::IVIM_DSTAR_FIX); - filter->SetDStar(m_Controls->m_DStarLabel->text().toDouble()); - filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble()); - break; - - case 2: - filter->SetMethod(IVIMFilterType::IVIM_D_THEN_DSTAR); - filter->SetBThres(m_Controls->m_BThreshLabel->text().toDouble()); - filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble()); - filter->SetFitDStar(m_Controls->m_CheckDStar->isChecked()); - break; - - case 3: - filter->SetMethod(IVIMFilterType::IVIM_LINEAR_D_THEN_F); - filter->SetBThres(m_Controls->m_BThreshLabel->text().toDouble()); - filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble()); - filter->SetFitDStar(m_Controls->m_CheckDStar->isChecked()); - break; - - case 4: - filter->SetMethod(IVIMFilterType::IVIM_REGULARIZED); - filter->SetBThres(m_Controls->m_BThreshLabel->text().toDouble()); - filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble()); - filter->SetNumberIterations(m_Controls->m_NumItsLabel->text().toInt()); - filter->SetLambda(m_Controls->m_LambdaLabel->text().toDouble()); - filter->SetFitDStar(m_Controls->m_CheckDStar->isChecked()); - break; - } + case 0: + filter->SetMethod(IVIMFilterType::IVIM_FIT_ALL); + filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble()); + break; + + case 1: + filter->SetMethod(IVIMFilterType::IVIM_DSTAR_FIX); + filter->SetDStar(m_Controls->m_DStarLabel->text().toDouble()); + filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble()); + break; + + case 2: + filter->SetMethod(IVIMFilterType::IVIM_D_THEN_DSTAR); + filter->SetBThres(m_Controls->m_BThreshLabel->text().toDouble()); + filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble()); + filter->SetFitDStar(m_Controls->m_CheckDStar->isChecked()); + break; + + case 3: + filter->SetMethod(IVIMFilterType::IVIM_LINEAR_D_THEN_F); + filter->SetBThres(m_Controls->m_BThreshLabel->text().toDouble()); + filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble()); + filter->SetFitDStar(m_Controls->m_CheckDStar->isChecked()); + break; + + case 4: + filter->SetMethod(IVIMFilterType::IVIM_REGULARIZED); + filter->SetBThres(m_Controls->m_BThreshLabel->text().toDouble()); + filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble()); + filter->SetNumberIterations(m_Controls->m_NumItsLabel->text().toInt()); + filter->SetLambda(m_Controls->m_LambdaLabel->text().toDouble()); + filter->SetFitDStar(m_Controls->m_CheckDStar->isChecked()); + break; + } - if(!multivoxel) - { - filter->SetFitDStar(true); - } + if(!multivoxel) + { + filter->SetFitDStar(true); + } - filter->SetNumberOfThreads(1); - filter->SetVerbose(false); - filter->SetCrossPosition(crosspos); + filter->SetNumberOfThreads(1); + filter->SetVerbose(false); + filter->SetCrossPosition(crosspos); - try{ - filter->Update(); - m_Snap = filter->GetSnapshot(); - m_DStarMap = filter->GetOutput(2); - m_DMap = filter->GetOutput(1); - m_fMap = filter->GetOutput(); - } - catch (itk::ExceptionObject &ex) - { - MITK_INFO << ex ; - m_Controls->m_Warning->setText(QString("IVIM fit not possible: ")+ex.GetDescription()); - m_Controls->m_Warning->setVisible(true); - return false; - } - return true; + try{ + filter->Update(); + m_Snap = filter->GetSnapshot(); + m_DStarMap = filter->GetOutput(2); + m_DMap = filter->GetOutput(1); + m_fMap = filter->GetOutput(); + } + catch (itk::ExceptionObject &ex) + { + MITK_INFO << ex ; + m_Controls->m_Warning->setText(QString("IVIM fit not possible: ")+ex.GetDescription()); + m_Controls->m_Warning->setVisible(true); + return false; + } + return true; } void QmitkIVIMView::OutputToDatastorage(const QList& nodes) { - // Outputs to Datastorage - QString basename(nodes.front()->GetName().c_str()); + // Outputs to Datastorage + QString basename(nodes.front()->GetName().c_str()); - if(m_Controls->m_CheckDStar->isChecked()) - { - mitk::Image::Pointer dstarimage = mitk::Image::New(); - dstarimage->InitializeByItk(m_DStarMap.GetPointer()); - dstarimage->SetVolume(m_DStarMap->GetBufferPointer()); - QString newname2 = ""; newname2 = newname2.append("IVIM_DStarMap_Method-%1").arg(m_Controls->m_MethodCombo->currentText()); - mitk::DataNode::Pointer node2=mitk::DataNode::New(); - node2->SetData( dstarimage ); - node2->SetName(newname2.toLatin1()); - GetDataStorage()->Add(node2, nodes.front()); - } + if(m_Controls->m_CheckDStar->isChecked()) + { + mitk::Image::Pointer dstarimage = mitk::Image::New(); + dstarimage->InitializeByItk(m_DStarMap.GetPointer()); + dstarimage->SetVolume(m_DStarMap->GetBufferPointer()); + QString newname2 = ""; newname2 = newname2.append("IVIM_DStarMap_Method-%1").arg(m_Controls->m_MethodCombo->currentText()); + mitk::DataNode::Pointer node2=mitk::DataNode::New(); + node2->SetData( dstarimage ); + node2->SetName(newname2.toLatin1()); + GetDataStorage()->Add(node2, nodes.front()); + } - if(m_Controls->m_CheckD->isChecked()) - { - mitk::Image::Pointer dimage = mitk::Image::New(); - dimage->InitializeByItk(m_DMap.GetPointer()); - dimage->SetVolume(m_DMap->GetBufferPointer()); - QString newname1 = ""; newname1 = newname1.append("IVIM_DMap_Method-%1").arg(m_Controls->m_MethodCombo->currentText()); - mitk::DataNode::Pointer node1=mitk::DataNode::New(); - node1->SetData( dimage ); - node1->SetName(newname1.toLatin1()); - GetDataStorage()->Add(node1, nodes.front()); - } + if(m_Controls->m_CheckD->isChecked()) + { + mitk::Image::Pointer dimage = mitk::Image::New(); + dimage->InitializeByItk(m_DMap.GetPointer()); + dimage->SetVolume(m_DMap->GetBufferPointer()); + QString newname1 = ""; newname1 = newname1.append("IVIM_DMap_Method-%1").arg(m_Controls->m_MethodCombo->currentText()); + mitk::DataNode::Pointer node1=mitk::DataNode::New(); + node1->SetData( dimage ); + node1->SetName(newname1.toLatin1()); + GetDataStorage()->Add(node1, nodes.front()); + } - if(m_Controls->m_Checkf->isChecked()) - { - mitk::Image::Pointer image = mitk::Image::New(); - image->InitializeByItk(m_fMap.GetPointer()); - image->SetVolume(m_fMap->GetBufferPointer()); - QString newname0 = ""; newname0 = newname0.append("IVIM_fMap_Method-%1").arg(m_Controls->m_MethodCombo->currentText()); - mitk::DataNode::Pointer node=mitk::DataNode::New(); - node->SetData( image ); - node->SetName(newname0.toLatin1()); - GetDataStorage()->Add(node, nodes.front()); - } + if(m_Controls->m_Checkf->isChecked()) + { + mitk::Image::Pointer image = mitk::Image::New(); + image->InitializeByItk(m_fMap.GetPointer()); + image->SetVolume(m_fMap->GetBufferPointer()); + QString newname0 = ""; newname0 = newname0.append("IVIM_fMap_Method-%1").arg(m_Controls->m_MethodCombo->currentText()); + mitk::DataNode::Pointer node=mitk::DataNode::New(); + node->SetData( image ); + node->SetName(newname0.toLatin1()); + GetDataStorage()->Add(node, nodes.front()); + } - this->GetRenderWindowPart()->RequestUpdate(); + this->GetRenderWindowPart()->RequestUpdate(); - // reset the data node labels, the selection in DataManager is lost after adding - // a new node -> we cannot directly proceed twice, the DWI ( and MASK) image have to be selected again - m_Controls->m_InputData->setTitle("Please Select Input Data"); - m_Controls->m_DiffusionImageLabel->setText("mandatory"); - m_Controls->m_MaskImageLabel->setText("optional"); - m_MaskImageNode = nullptr; - m_DiffusionImageNode = nullptr; + // reset the data node labels, the selection in DataManager is lost after adding + // a new node -> we cannot directly proceed twice, the DWI ( and MASK) image have to be selected again + m_Controls->m_InputData->setTitle("Please Select Input Data"); + m_Controls->m_DiffusionImageLabel->setText("mandatory"); + m_Controls->m_MaskImageLabel->setText("optional"); + m_MaskImageNode = nullptr; + m_DiffusionImageNode = nullptr; } void QmitkIVIMView::ChooseMethod() { - m_Controls->m_MethodCombo->setVisible(m_Controls->m_ChooseMethod->isChecked()); + m_Controls->m_MethodCombo->setVisible(m_Controls->m_ChooseMethod->isChecked()); } void QmitkIVIMView::ClipboardCurveButtonClicked() { // Kurtosis - if ( m_Controls->m_ModelTabSelectionWidget->currentIndex() ) - { - std::stringstream ss; - QString clipboard("Measurement Points\n"); + if ( m_Controls->m_ModelTabSelectionWidget->currentIndex() ) + { + std::stringstream ss; + QString clipboard("Measurement Points\n"); - ss << m_KurtosisSnap.bvalues << "\n" << m_KurtosisSnap.measurements << "\n\n"; - ss << "Fitted Values ( D K [b_0] ) \n" << m_KurtosisSnap.m_D << " " << m_KurtosisSnap.m_K; - if( m_KurtosisSnap.m_fittedBZero ) - ss << " " << m_KurtosisSnap.m_BzeroFit; + ss << m_KurtosisSnap.bvalues << "\n" << m_KurtosisSnap.measurements << "\n\n"; + ss << "Fitted Values ( D K [b_0] ) \n" << m_KurtosisSnap.m_D << " " << m_KurtosisSnap.m_K; + if( m_KurtosisSnap.m_fittedBZero ) + ss << " " << m_KurtosisSnap.m_BzeroFit; - ss << "\n\n"; - clipboard.append( QString( ss.str().c_str() )); + ss << "\n\n"; + clipboard.append( QString( ss.str().c_str() )); - ss.str( std::string() ); - ss.clear(); + ss.str( std::string() ); + ss.clear(); - QApplication::clipboard()->setText( - clipboard, QClipboard::Clipboard ); - } - else - { + QApplication::clipboard()->setText( + clipboard, QClipboard::Clipboard ); + } + else + { - QString clipboard("Measurement Points\n"); - for ( unsigned int i=0; isetText( - clipboard, QClipboard::Clipboard ); + for(int i=0; isetText( + clipboard, QClipboard::Clipboard ); + } } void QmitkIVIMView::ClipboardStatisticsButtonClicked() { - // Kurtosis - if ( m_Controls->m_ModelTabSelectionWidget->currentIndex() ) - { + // Kurtosis + if ( m_Controls->m_ModelTabSelectionWidget->currentIndex() ) + { - QString clipboard( "D \t K \n" ); - clipboard = clipboard.append( "%L1 \t %L2" ) + QString clipboard( "D \t K \n" ); + clipboard = clipboard.append( "%L1 \t %L2" ) .arg( m_KurtosisSnap.m_D, 0, 'f', 10 ) .arg( m_KurtosisSnap.m_K, 0, 'f', 10 ) ; - QApplication::clipboard()->setText( - clipboard, QClipboard::Clipboard ); - } - else - { - QString clipboard( "f \t D \t D* \n" ); - clipboard = clipboard.append( "%L1 \t %L2 \t %L3" ) - .arg( m_Snap.currentF, 0, 'f', 10 ) - .arg( m_Snap.currentD, 0, 'f', 10 ) - .arg( m_Snap.currentDStar, 0, 'f', 10 ) ; - - QApplication::clipboard()->setText( - clipboard, QClipboard::Clipboard ); - } + QApplication::clipboard()->setText( + clipboard, QClipboard::Clipboard ); + } + else + { + QString clipboard( "f \t D \t D* \n" ); + clipboard = clipboard.append( "%L1 \t %L2 \t %L3" ) + .arg( m_Snap.currentF, 0, 'f', 10 ) + .arg( m_Snap.currentD, 0, 'f', 10 ) + .arg( m_Snap.currentDStar, 0, 'f', 10 ) ; + + QApplication::clipboard()->setText( + clipboard, QClipboard::Clipboard ); + } } void QmitkIVIMView::Activated() { - m_Active = true; + m_Active = true; } void QmitkIVIMView::Deactivated() { - m_Active = false; + m_Active = false; } void QmitkIVIMView::Visible() { - m_Visible = true; - auto renderWindowPart = dynamic_cast(this->GetRenderWindowPart()); + m_Visible = true; + auto renderWindowPart = dynamic_cast(this->GetRenderWindowPart()); + if (renderWindowPart!=nullptr) + { { - mitk::SliceNavigationController* slicer = renderWindowPart->GetQmitkRenderWindow("axial")->GetSliceNavigationController(); - itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); - command->SetCallbackFunction( this, &QmitkIVIMView::OnSliceChanged ); - m_SliceObserverTag1 = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), command ); + mitk::SliceNavigationController* slicer = renderWindowPart->GetQmitkRenderWindow("axial")->GetSliceNavigationController(); + itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); + command->SetCallbackFunction( this, &QmitkIVIMView::OnSliceChanged ); + m_SliceObserverTag1 = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), command ); } { - mitk::SliceNavigationController* slicer = renderWindowPart->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController(); - itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); - command->SetCallbackFunction( this, &QmitkIVIMView::OnSliceChanged ); - m_SliceObserverTag2 = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), command ); + mitk::SliceNavigationController* slicer = renderWindowPart->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController(); + itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); + command->SetCallbackFunction( this, &QmitkIVIMView::OnSliceChanged ); + m_SliceObserverTag2 = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), command ); } { - mitk::SliceNavigationController* slicer = renderWindowPart->GetQmitkRenderWindow("coronal")->GetSliceNavigationController(); - itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); - command->SetCallbackFunction( this, &QmitkIVIMView::OnSliceChanged ); - m_SliceObserverTag3 = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), command ); + mitk::SliceNavigationController* slicer = renderWindowPart->GetQmitkRenderWindow("coronal")->GetSliceNavigationController(); + itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); + command->SetCallbackFunction( this, &QmitkIVIMView::OnSliceChanged ); + m_SliceObserverTag3 = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), command ); } + } } void QmitkIVIMView::Hidden() { - m_Visible = false; - auto renderWindowPart = dynamic_cast(this->GetRenderWindowPart()); + m_Visible = false; + auto renderWindowPart = dynamic_cast(this->GetRenderWindowPart()); + + if (renderWindowPart!=nullptr) + { { - mitk::SliceNavigationController* slicer = renderWindowPart->GetQmitkRenderWindow("axial")->GetSliceNavigationController(); - slicer->RemoveObserver( m_SliceObserverTag1 ); + mitk::SliceNavigationController* slicer = renderWindowPart->GetQmitkRenderWindow("axial")->GetSliceNavigationController(); + slicer->RemoveObserver( m_SliceObserverTag1 ); } { - mitk::SliceNavigationController* slicer = renderWindowPart->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController(); - slicer->RemoveObserver( m_SliceObserverTag2 ); + mitk::SliceNavigationController* slicer = renderWindowPart->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController(); + slicer->RemoveObserver( m_SliceObserverTag2 ); } { - mitk::SliceNavigationController* slicer = renderWindowPart->GetQmitkRenderWindow("coronal")->GetSliceNavigationController(); - slicer->RemoveObserver( m_SliceObserverTag3 ); + mitk::SliceNavigationController* slicer = renderWindowPart->GetQmitkRenderWindow("coronal")->GetSliceNavigationController(); + slicer->RemoveObserver( m_SliceObserverTag3 ); } + } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMViewControls.ui index 887789baeb..19a73a338d 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMViewControls.ui @@ -1,1172 +1,1158 @@ QmitkIVIMViewControls 0 0 423 1563 0 0 QmitkTemplate 9 9 9 9 Intra Voxel Incoherent Motion Estimation 0 9 0 0 Please Select Input Data Optional ROI image ROI: DWI to analyze <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> Optional ROI image <html><head/><body><p><span style=" color:#969696;">optional</span></p></body></html> DWI to analyze Raw DWI: QFrame::NoFrame QFrame::Raised 0 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 warning display Qt::RichText true QFrame::StyledPanel QFrame::Raised 0 0 0 0 0 0 0 0 IVIM Parameters 9 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 80 16777215 D* 100 60 Qt::Horizontal 51 16777215 200 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter QFrame::NoFrame QFrame::Raised 0 0 0 0 0 80 16777215 neglect b< 250 34 Qt::Horizontal 51 16777215 46.5 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter QFrame::NoFrame QFrame::Raised 0 0 0 0 0 80 16777215 #iterations 100 10 Qt::Horizontal 30 16777215 TextLabel Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter QFrame::NoFrame QFrame::Raised 0 0 0 0 0 80 16777215 lambda 1000 10 Qt::Horizontal 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 0 0 30 16777215 TextLabel Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 15 16777215 Calculate threshold from histogram * QFrame::NoFrame QFrame::Plain 0 0 0 0 0 80 16777215 neglect Si< 100 0 Qt::Horizontal 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 0 0 30 16777215 TextLabel Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 15 16777215 Calculate threshold from histogram * QFrame::NoFrame QFrame::Raised 0 0 0 0 80 0 Output Images f true D false D* false true 0 0 0 400 - - - 0 - - - 0 - - - 0 - - - 0 - - Choose Method 2 3 Param. Fit Fit D & f with fixed D* value Fit D & f (high b), then fit D* Linearly fit D & f (high b), then fit D* Regularized Kurtosis QFrame::StyledPanel QFrame::Raised 2 2 2 2 2 Smoothing sigma Select Fit Type Omit b=0 Measurement 80 0 Output Images Force the fitting of K to remain within the given boundaries Boundaries for K Select if the data is fitted directly (straight) or the logarithmic equation is used Straight Fit Logarithmic Fit 2 QLayout::SetMaximumSize D false K true Signa for gaussian smoothing applied prior to map computation 0.000000000000000 5.000000000000000 0.100000000000000 On 0 0 0 400 Generate Output Images QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 Datapoints to Clipboard Parameters to Clipboard QmitkIVIMWidget QWidget
QmitkIVIMWidget.h
1
QmitkKurtosisWidget QWidget
QmitkKurtosisWidget.h
1
ctkRangeWidget QWidget
ctkRangeWidget.h
1
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkGibbsTrackingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkGibbsTrackingView.cpp index e9f4111ecb..0a560d188a 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkGibbsTrackingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkGibbsTrackingView.cpp @@ -1,636 +1,635 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkGibbsTrackingView.h" // Qt #include #include #include #include // MITK #include #include #include #include #include // ITK #include #include #include // MISC #include QmitkTrackingWorker::QmitkTrackingWorker(QmitkGibbsTrackingView* view) : m_View(view) { } void QmitkTrackingWorker::run() { m_View->m_GlobalTracker = QmitkGibbsTrackingView::GibbsTrackingFilterType::New(); m_View->m_GlobalTracker->SetQBallImage(m_View->m_ItkQBallImage); m_View->m_GlobalTracker->SetTensorImage(m_View->m_ItkTensorImage); m_View->m_GlobalTracker->SetMaskImage(m_View->m_MaskImage); m_View->m_GlobalTracker->SetStartTemperature((float)m_View->m_Controls->m_StartTempSlider->value()/100); m_View->m_GlobalTracker->SetEndTemperature((float)m_View->m_Controls->m_EndTempSlider->value()/10000); m_View->m_GlobalTracker->SetIterations(m_View->m_Controls->m_IterationsBox->text().toDouble()); m_View->m_GlobalTracker->SetParticleWeight((float)m_View->m_Controls->m_ParticleWeightSlider->value()/10000); m_View->m_GlobalTracker->SetParticleWidth((float)(m_View->m_Controls->m_ParticleWidthSlider->value())/10); m_View->m_GlobalTracker->SetParticleLength((float)(m_View->m_Controls->m_ParticleLengthSlider->value())/10); m_View->m_GlobalTracker->SetInexBalance((float)m_View->m_Controls->m_InExBalanceSlider->value()/10); m_View->m_GlobalTracker->SetMinFiberLength(m_View->m_Controls->m_FiberLengthSlider->value()); m_View->m_GlobalTracker->SetCurvatureThreshold(cos((float)m_View->m_Controls->m_CurvatureThresholdSlider->value()*M_PI/180)); m_View->m_GlobalTracker->SetRandomSeed(m_View->m_Controls->m_RandomSeedSlider->value()); try{ m_View->m_GlobalTracker->Update(); } catch( mitk::Exception e ) { MITK_ERROR << "Internal error occured: " << e.what() << "\nAborting"; } m_View->m_TrackingThread.quit(); } const std::string QmitkGibbsTrackingView::VIEW_ID = "org.mitk.views.gibbstracking"; QmitkGibbsTrackingView::QmitkGibbsTrackingView() : QmitkAbstractView() , m_Controls( 0 ) , m_FiberBundle(nullptr) , m_MaskImage(nullptr) , m_TensorImage(nullptr) , m_QBallImage(nullptr) , m_ItkQBallImage(nullptr) , m_ItkTensorImage(nullptr) , m_ImageNode(nullptr) , m_MaskImageNode(nullptr) , m_FiberBundleNode(nullptr) , m_ThreadIsRunning(false) , m_ElapsedTime(0) , m_GlobalTracker(nullptr) , m_TrackingWorker(this) , m_TrackingNode(nullptr) { m_TrackingWorker.moveToThread(&m_TrackingThread); connect(&m_TrackingThread, SIGNAL(started()), this, SLOT(BeforeThread())); connect(&m_TrackingThread, SIGNAL(started()), &m_TrackingWorker, SLOT(run())); connect(&m_TrackingThread, SIGNAL(finished()), this, SLOT(AfterThread())); - connect(&m_TrackingThread, SIGNAL(terminated()), this, SLOT(AfterThread())); m_TrackingTimer = new QTimer(this); } QmitkGibbsTrackingView::~QmitkGibbsTrackingView() { if (m_GlobalTracker.IsNull()) return; m_GlobalTracker->SetAbortTracking(true); m_TrackingThread.wait(); } // update tracking status and generate fiber bundle void QmitkGibbsTrackingView::TimerUpdate() { UpdateTrackingStatus(); GenerateFiberBundle(); } // tell global tractography filter to stop after current step void QmitkGibbsTrackingView::StopGibbsTracking() { if (m_GlobalTracker.IsNull()) return; m_GlobalTracker->SetAbortTracking(true); m_Controls->m_TrackingStop->setEnabled(false); m_Controls->m_TrackingStop->setText("Stopping Tractography ..."); m_TrackingNode = nullptr; } // update gui elements and generate fiber bundle after tracking is finished void QmitkGibbsTrackingView::AfterThread() { m_ThreadIsRunning = false; m_TrackingTimer->stop(); UpdateGUI(); if( !m_GlobalTracker->GetIsInValidState() ) { QMessageBox::critical( nullptr, "Gibbs Tracking", "An internal error occured. Tracking aborted.\n Please check the log for details." ); m_FiberBundleNode = nullptr; return; } UpdateTrackingStatus(); if(m_Controls->m_ParticleWeightSlider->value()==0) { m_Controls->m_ParticleWeightLabel->setText(QString::number(m_GlobalTracker->GetParticleWeight())); m_Controls->m_ParticleWeightSlider->setValue(m_GlobalTracker->GetParticleWeight()*10000); } if(m_Controls->m_ParticleWidthSlider->value()==0) { m_Controls->m_ParticleWidthLabel->setText(QString::number(m_GlobalTracker->GetParticleWidth())); m_Controls->m_ParticleWidthSlider->setValue(m_GlobalTracker->GetParticleWidth()*10); } if(m_Controls->m_ParticleLengthSlider->value()==0) { m_Controls->m_ParticleLengthLabel->setText(QString::number(m_GlobalTracker->GetParticleLength())); m_Controls->m_ParticleLengthSlider->setValue(m_GlobalTracker->GetParticleLength()*10); } GenerateFiberBundle(); m_FiberBundleNode = 0; m_GlobalTracker = 0; // images not needed anymore ( relevant only for computation ) // we need to release them to remove the memory access block created through CastToItk<> calls this->m_ItkQBallImage = 0; this->m_ItkTensorImage = 0; } // start tracking timer and update gui elements before tracking is started void QmitkGibbsTrackingView::BeforeThread() { m_ThreadIsRunning = true; m_TrackingTime = QTime::currentTime(); m_ElapsedTime = 0; m_TrackingTimer->start(1000); UpdateGUI(); } // setup gui elements and signal/slot connections void QmitkGibbsTrackingView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkGibbsTrackingViewControls; m_Controls->setupUi( parent ); AdvancedSettings(); connect( m_TrackingTimer, SIGNAL(timeout()), this, SLOT(TimerUpdate()) ); connect( m_Controls->m_TrackingStop, SIGNAL(clicked()), this, SLOT(StopGibbsTracking()) ); connect( m_Controls->m_TrackingStart, SIGNAL(clicked()), this, SLOT(StartGibbsTracking()) ); connect( m_Controls->m_AdvancedSettingsCheckbox, SIGNAL(clicked()), this, SLOT(AdvancedSettings()) ); connect( m_Controls->m_SaveTrackingParameters, SIGNAL(clicked()), this, SLOT(SaveTrackingParameters()) ); connect( m_Controls->m_LoadTrackingParameters, SIGNAL(clicked()), this, SLOT(LoadTrackingParameters()) ); connect( m_Controls->m_ParticleWidthSlider, SIGNAL(valueChanged(int)), this, SLOT(SetParticleWidth(int)) ); connect( m_Controls->m_ParticleLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(SetParticleLength(int)) ); connect( m_Controls->m_InExBalanceSlider, SIGNAL(valueChanged(int)), this, SLOT(SetInExBalance(int)) ); connect( m_Controls->m_FiberLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(SetFiberLength(int)) ); connect( m_Controls->m_ParticleWeightSlider, SIGNAL(valueChanged(int)), this, SLOT(SetParticleWeight(int)) ); connect( m_Controls->m_StartTempSlider, SIGNAL(valueChanged(int)), this, SLOT(SetStartTemp(int)) ); connect( m_Controls->m_EndTempSlider, SIGNAL(valueChanged(int)), this, SLOT(SetEndTemp(int)) ); connect( m_Controls->m_CurvatureThresholdSlider, SIGNAL(valueChanged(int)), this, SLOT(SetCurvatureThreshold(int)) ); connect( m_Controls->m_RandomSeedSlider, SIGNAL(valueChanged(int)), this, SLOT(SetRandomSeed(int)) ); connect( m_Controls->m_OutputFileButton, SIGNAL(clicked()), this, SLOT(SetOutputFile()) ); } } void QmitkGibbsTrackingView::SetFocus() { m_Controls->m_TrackingStart->setFocus(); } void QmitkGibbsTrackingView::SetInExBalance(int value) { m_Controls->m_InExBalanceLabel->setText(QString::number((float)value/10)); } void QmitkGibbsTrackingView::SetFiberLength(int value) { m_Controls->m_FiberLengthLabel->setText(QString::number(value)+"mm"); } void QmitkGibbsTrackingView::SetRandomSeed(int value) { if (value>=0) m_Controls->m_RandomSeedLabel->setText(QString::number(value)); else m_Controls->m_RandomSeedLabel->setText("auto"); } void QmitkGibbsTrackingView::SetParticleWeight(int value) { if (value>0) m_Controls->m_ParticleWeightLabel->setText(QString::number((float)value/10000)); else m_Controls->m_ParticleWeightLabel->setText("auto"); } void QmitkGibbsTrackingView::SetStartTemp(int value) { m_Controls->m_StartTempLabel->setText(QString::number((float)value/100)); } void QmitkGibbsTrackingView::SetEndTemp(int value) { m_Controls->m_EndTempLabel->setText(QString::number((float)value/10000)); } void QmitkGibbsTrackingView::SetParticleWidth(int value) { if (value>0) m_Controls->m_ParticleWidthLabel->setText(QString::number((float)value/10)+" mm"); else m_Controls->m_ParticleWidthLabel->setText("auto"); } void QmitkGibbsTrackingView::SetParticleLength(int value) { if (value>0) m_Controls->m_ParticleLengthLabel->setText(QString::number((float)value/10)+" mm"); else m_Controls->m_ParticleLengthLabel->setText("auto"); } void QmitkGibbsTrackingView::SetCurvatureThreshold(int value) { m_Controls->m_CurvatureThresholdLabel->setText(QString::number(value)+"°"); } // called if datamanager selection changes void QmitkGibbsTrackingView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& nodes) { if (m_ThreadIsRunning) return; m_ImageNode = nullptr; m_MaskImageNode = nullptr; // iterate all selected objects for (mitk::DataNode::Pointer node: nodes) { if( node.IsNotNull() && dynamic_cast(node->GetData()) ) m_ImageNode = node; else if( node.IsNotNull() && dynamic_cast(node->GetData()) ) m_ImageNode = node; else if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { mitk::Image::Pointer img = dynamic_cast(node->GetData()); if (img->GetPixelType().GetPixelType()==itk::ImageIOBase::SCALAR) m_MaskImageNode = node; } } UpdateGUI(); } void QmitkGibbsTrackingView::NodeRemoved(const mitk::DataNode * node) { if (m_ThreadIsRunning) { if (node==m_TrackingNode.GetPointer()) { StopGibbsTracking(); } } } // update gui elements displaying trackings status void QmitkGibbsTrackingView::UpdateTrackingStatus() { if (m_GlobalTracker.IsNull()) return; m_ElapsedTime += m_TrackingTime.elapsed()/1000; m_TrackingTime.restart(); unsigned long hours = m_ElapsedTime/3600; unsigned long minutes = (m_ElapsedTime%3600)/60; unsigned long seconds = m_ElapsedTime%60; m_Controls->m_ProposalAcceptance->setText(QString::number(m_GlobalTracker->GetProposalAcceptance()*100)+"%"); m_Controls->m_TrackingTimeLabel->setText( QString::number(hours)+QString("h ")+QString::number(minutes)+QString("m ")+QString::number(seconds)+QString("s") ); m_Controls->m_NumConnectionsLabel->setText( QString::number(m_GlobalTracker->GetNumConnections()) ); m_Controls->m_NumParticlesLabel->setText( QString::number(m_GlobalTracker->GetNumParticles()) ); m_Controls->m_CurrentStepLabel->setText( QString::number(100*m_GlobalTracker->GetCurrentIteration()/m_GlobalTracker->GetIterations())+"%" ); m_Controls->m_AcceptedFibersLabel->setText( QString::number(m_GlobalTracker->GetNumAcceptedFibers()) ); } // update gui elements (enable/disable elements and set tooltips) void QmitkGibbsTrackingView::UpdateGUI() { if (m_ImageNode.IsNotNull()) { m_Controls->m_QballImageLabel->setText(m_ImageNode->GetName().c_str()); m_Controls->m_DataFrame->setTitle("Input Data"); } else { m_Controls->m_QballImageLabel->setText("mandatory"); m_Controls->m_DataFrame->setTitle("Please Select Input Data"); } if (m_MaskImageNode.IsNotNull()) m_Controls->m_MaskImageLabel->setText(m_MaskImageNode->GetName().c_str()); else m_Controls->m_MaskImageLabel->setText("optional"); if (!m_ThreadIsRunning && m_ImageNode.IsNotNull()) { m_Controls->m_TrackingStop->setEnabled(false); m_Controls->m_TrackingStart->setEnabled(true); m_Controls->m_LoadTrackingParameters->setEnabled(true); m_Controls->m_IterationsBox->setEnabled(true); m_Controls->m_AdvancedFrame->setEnabled(true); m_Controls->m_TrackingStop->setText("Stop Tractography"); m_Controls->m_TrackingStart->setToolTip("Start tractography. No further change of parameters possible."); m_Controls->m_TrackingStop->setToolTip(""); } else if (!m_ThreadIsRunning) { m_Controls->m_TrackingStop->setEnabled(false); m_Controls->m_TrackingStart->setEnabled(false); m_Controls->m_LoadTrackingParameters->setEnabled(true); m_Controls->m_IterationsBox->setEnabled(true); m_Controls->m_AdvancedFrame->setEnabled(true); m_Controls->m_TrackingStop->setText("Stop Tractography"); m_Controls->m_TrackingStart->setToolTip("No Q-Ball image selected."); m_Controls->m_TrackingStop->setToolTip(""); } else { m_Controls->m_TrackingStop->setEnabled(true); m_Controls->m_TrackingStart->setEnabled(false); m_Controls->m_LoadTrackingParameters->setEnabled(false); m_Controls->m_IterationsBox->setEnabled(false); m_Controls->m_AdvancedFrame->setEnabled(false); m_Controls->m_AdvancedFrame->setVisible(false); m_Controls->m_AdvancedSettingsCheckbox->setChecked(false); m_Controls->m_TrackingStart->setToolTip("Tracking in progress."); m_Controls->m_TrackingStop->setToolTip("Stop tracking and display results."); } } // show/hide advanced settings frame void QmitkGibbsTrackingView::AdvancedSettings() { m_Controls->m_AdvancedFrame->setVisible(m_Controls->m_AdvancedSettingsCheckbox->isChecked()); } // set mask image data node void QmitkGibbsTrackingView::SetMask() { QList nodes = GetDataManagerSelection(); if (nodes.empty()) { m_MaskImageNode = nullptr; m_Controls->m_MaskImageLabel->setText("-"); return; } for (auto node: nodes) { if (node.IsNotNull() && dynamic_cast(node->GetData())) { m_MaskImageNode = node; m_Controls->m_MaskImageLabel->setText(node->GetName().c_str()); return; } } } // check for mask and qbi and start tracking thread void QmitkGibbsTrackingView::StartGibbsTracking() { if(m_ThreadIsRunning) { MITK_WARN("QmitkGibbsTrackingView")<<"Thread already running!"; return; } m_GlobalTracker = nullptr; if (m_ImageNode.IsNull()) { QMessageBox::information( nullptr, "Warning", "Please load and select a qball image before starting image processing."); return; } if (dynamic_cast(m_ImageNode->GetData())) m_QBallImage = dynamic_cast(m_ImageNode->GetData()); else if (dynamic_cast(m_ImageNode->GetData())) m_TensorImage = dynamic_cast(m_ImageNode->GetData()); if (m_QBallImage.IsNull() && m_TensorImage.IsNull()) return; // cast qbi to itk m_TrackingNode = m_ImageNode; m_ItkTensorImage = nullptr; m_ItkQBallImage = nullptr; m_MaskImage = nullptr; if (m_QBallImage.IsNotNull()) { m_ItkQBallImage = ItkQBallImgType::New(); mitk::CastToItkImage(m_QBallImage, m_ItkQBallImage); } else { m_ItkTensorImage = ItkTensorImage::New(); mitk::CastToItkImage(m_TensorImage, m_ItkTensorImage); } // mask image found? // catch exceptions thrown by the itkAccess macros try{ if(m_MaskImageNode.IsNotNull()) { if (dynamic_cast(m_MaskImageNode->GetData())) mitk::CastToItkImage(dynamic_cast(m_MaskImageNode->GetData()), m_MaskImage); } } catch(...){}; // start worker thread m_TrackingThread.start(QThread::LowestPriority); } // generate mitkFiberBundle from tracking filter output void QmitkGibbsTrackingView::GenerateFiberBundle() { if (m_GlobalTracker.IsNull() || (!(m_Controls->m_VisualizationCheckbox->isChecked() || m_Controls->m_VisualizeOnceButton->isChecked()) && m_ThreadIsRunning)) return; if (m_Controls->m_VisualizeOnceButton->isChecked()) m_Controls->m_VisualizeOnceButton->setChecked(false); vtkSmartPointer fiberBundle = m_GlobalTracker->GetFiberBundle(); if ( m_GlobalTracker->GetNumAcceptedFibers()==0 ) return; m_FiberBundle = mitk::FiberBundle::New(fiberBundle); m_FiberBundle->SetReferenceGeometry(dynamic_cast(m_ImageNode->GetData())->GetGeometry()); if (m_FiberBundleNode.IsNotNull()){ GetDataStorage()->Remove(m_FiberBundleNode); m_FiberBundleNode = 0; } m_FiberBundleNode = mitk::DataNode::New(); m_FiberBundleNode->SetData(m_FiberBundle); QString name("FiberBundle_"); name += m_ImageNode->GetName().c_str(); name += "_Gibbs"; m_FiberBundleNode->SetName(name.toStdString()); m_FiberBundleNode->SetVisibility(true); if (!m_OutputFileName.isEmpty() && !m_ThreadIsRunning) { try { mitk::IOUtil::Save(m_FiberBundle.GetPointer(),m_OutputFileName.toStdString()); QMessageBox::information(nullptr, "Fiber bundle saved to", m_OutputFileName); } catch (itk::ExceptionObject &ex) { QMessageBox::information(nullptr, "Fiber bundle could not be saved", QString("%1\n%2\n%3\n%4\n%5\n%6").arg(ex.GetNameOfClass()).arg(ex.GetFile()).arg(ex.GetLine()).arg(ex.GetLocation()).arg(ex.what()).arg(ex.GetDescription())); } } if(m_ImageNode.IsNull()) GetDataStorage()->Add(m_FiberBundleNode); else GetDataStorage()->Add(m_FiberBundleNode, m_ImageNode); } void QmitkGibbsTrackingView::SetOutputFile() { // SELECT FOLDER DIALOG m_OutputFileName = QFileDialog::getSaveFileName(0, tr("Set file name"), QDir::currentPath()+"/FiberBundle.fib", tr("Fiber Bundle (*.fib)") ); if (m_OutputFileName.isEmpty()) m_Controls->m_OutputFileLabel->setText("N/A"); else m_Controls->m_OutputFileLabel->setText(m_OutputFileName); } // save current tracking paramters as xml file (.gtp) void QmitkGibbsTrackingView::SaveTrackingParameters() { TiXmlDocument documentXML; TiXmlDeclaration* declXML = new TiXmlDeclaration( "1.0", "", "" ); documentXML.LinkEndChild( declXML ); TiXmlElement* mainXML = new TiXmlElement("global_tracking_parameter_file"); mainXML->SetAttribute("file_version", "0.1"); documentXML.LinkEndChild(mainXML); TiXmlElement* paramXML = new TiXmlElement("parameter_set"); paramXML->SetAttribute("iterations", m_Controls->m_IterationsBox->text().toStdString()); paramXML->SetAttribute("particle_length", QString::number((float)m_Controls->m_ParticleLengthSlider->value()/10).toStdString()); paramXML->SetAttribute("particle_width", QString::number((float)m_Controls->m_ParticleWidthSlider->value()/10).toStdString()); paramXML->SetAttribute("particle_weight", QString::number((float)m_Controls->m_ParticleWeightSlider->value()/10000).toStdString()); paramXML->SetAttribute("temp_start", QString::number((float)m_Controls->m_StartTempSlider->value()/100).toStdString()); paramXML->SetAttribute("temp_end", QString::number((float)m_Controls->m_EndTempSlider->value()/10000).toStdString()); paramXML->SetAttribute("inexbalance", QString::number((float)m_Controls->m_InExBalanceSlider->value()/10).toStdString()); paramXML->SetAttribute("fiber_length", QString::number(m_Controls->m_FiberLengthSlider->value()).toStdString()); paramXML->SetAttribute("curvature_threshold", QString::number(m_Controls->m_CurvatureThresholdSlider->value()).toStdString()); mainXML->LinkEndChild(paramXML); QString filename = QFileDialog::getSaveFileName( 0, tr("Save Parameters"), QDir::currentPath()+"/param.gtp", tr("Global Tracking Parameters (*.gtp)") ); if(filename.isEmpty() || filename.isNull()) return; if(!filename.endsWith(".gtp")) filename += ".gtp"; documentXML.SaveFile( filename.toStdString() ); } // load current tracking paramters from xml file (.gtp) void QmitkGibbsTrackingView::LoadTrackingParameters() { QString filename = QFileDialog::getOpenFileName(0, tr("Load Parameters"), QDir::currentPath(), tr("Global Tracking Parameters (*.gtp)") ); if(filename.isEmpty() || filename.isNull()) return; TiXmlDocument doc( filename.toStdString() ); doc.LoadFile(); TiXmlHandle hDoc(&doc); TiXmlElement* pElem; TiXmlHandle hRoot(0); pElem = hDoc.FirstChildElement().Element(); hRoot = TiXmlHandle(pElem); pElem = hRoot.FirstChildElement("parameter_set").Element(); QString iterations(pElem->Attribute("iterations")); m_Controls->m_IterationsBox->setText(iterations); QString particleLength(pElem->Attribute("particle_length")); float pLength = particleLength.toFloat(); QString particleWidth(pElem->Attribute("particle_width")); float pWidth = particleWidth.toFloat(); if (pLength==0) m_Controls->m_ParticleLengthLabel->setText("auto"); else m_Controls->m_ParticleLengthLabel->setText(particleLength+" mm"); if (pWidth==0) m_Controls->m_ParticleWidthLabel->setText("auto"); else m_Controls->m_ParticleWidthLabel->setText(particleWidth+" mm"); m_Controls->m_ParticleWidthSlider->setValue(pWidth*10); m_Controls->m_ParticleLengthSlider->setValue(pLength*10); QString partWeight(pElem->Attribute("particle_weight")); m_Controls->m_ParticleWeightSlider->setValue(partWeight.toFloat()*10000); m_Controls->m_ParticleWeightLabel->setText(partWeight); QString startTemp(pElem->Attribute("temp_start")); m_Controls->m_StartTempSlider->setValue(startTemp.toFloat()*100); m_Controls->m_StartTempLabel->setText(startTemp); QString endTemp(pElem->Attribute("temp_end")); m_Controls->m_EndTempSlider->setValue(endTemp.toFloat()*10000); m_Controls->m_EndTempLabel->setText(endTemp); QString inExBalance(pElem->Attribute("inexbalance")); m_Controls->m_InExBalanceSlider->setValue(inExBalance.toFloat()*10); m_Controls->m_InExBalanceLabel->setText(inExBalance); QString fiberLength(pElem->Attribute("fiber_length")); m_Controls->m_FiberLengthSlider->setValue(fiberLength.toInt()); m_Controls->m_FiberLengthLabel->setText(fiberLength+"mm"); QString curvThres(pElem->Attribute("curvature_threshold")); m_Controls->m_CurvatureThresholdSlider->setValue(curvThres.toInt()); m_Controls->m_CurvatureThresholdLabel->setText(curvThres+"°"); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkMLBTView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkMLBTView.cpp index 266c9c254c..ddc5815005 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkMLBTView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkMLBTView.cpp @@ -1,452 +1,452 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkMLBTView.h" // Qt #include #include #include #include #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include const std::string QmitkMLBTView::VIEW_ID = "org.mitk.views.mlbtview"; using namespace berry; QmitkMLBTView::QmitkMLBTView() : QmitkAbstractView() , m_Controls( 0 ) { m_TrackingTimer = std::make_shared(this); m_LastLoadedForestName = "(none)"; m_ForestHandler = new mitk::TrackingHandlerRandomForest<6,100>(); } // Destructor QmitkMLBTView::~QmitkMLBTView() { delete m_ForestHandler; } void QmitkMLBTView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkMLBTViewControls; m_Controls->setupUi( parent ); connect( m_Controls->m_StartTrainingButton, SIGNAL ( clicked() ), this, SLOT( StartTrainingThread() ) ); connect( &m_TrainingWatcher, SIGNAL ( finished() ), this, SLOT( OnTrainingThreadStop() ) ); connect( m_Controls->m_StartTrackingButton, SIGNAL ( clicked() ), this, SLOT( StartTrackingThread() ) ); connect( &m_TrackingWatcher, SIGNAL ( finished() ), this, SLOT( OnTrackingThreadStop() ) ); connect( m_Controls->m_SaveForestButton, SIGNAL ( clicked() ), this, SLOT( SaveForest() ) ); connect( m_Controls->m_LoadForestButton, SIGNAL ( clicked() ), this, SLOT( LoadForest() ) ); connect( m_TrackingTimer.get(), SIGNAL(timeout()), this, SLOT(BuildFibers()) ); connect( m_Controls->m_TimerIntervalBox, SIGNAL(valueChanged(int)), this, SLOT( ChangeTimerInterval(int) )); connect( m_Controls->m_DemoModeBox, SIGNAL(stateChanged(int)), this, SLOT( ToggleDemoMode(int) )); connect( m_Controls->m_PauseTrackingButton, SIGNAL ( clicked() ), this, SLOT( PauseTracking() ) ); connect( m_Controls->m_AbortTrackingButton, SIGNAL ( clicked() ), this, SLOT( AbortTracking() ) ); connect( m_Controls->m_AddTwButton, SIGNAL ( clicked() ), this, SLOT( AddTrainingWidget() ) ); connect( m_Controls->m_RemoveTwButton, SIGNAL ( clicked() ), this, SLOT( RemoveTrainingWidget() ) ); m_Controls->m_TrackingMaskImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_TrackingSeedImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_TrackingStopImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_TrackingRawImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_TissueImageBox->SetDataStorage(this->GetDataStorage()); mitk::NodePredicateIsDWI::Pointer isDiffusionImage = mitk::NodePredicateIsDWI::New(); mitk::TNodePredicateDataType::Pointer isMitkImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateNot::Pointer noDiffusionImage = mitk::NodePredicateNot::New(isDiffusionImage); mitk::NodePredicateAnd::Pointer finalPredicate = mitk::NodePredicateAnd::New(isMitkImage, noDiffusionImage); m_Controls->m_TissueImageBox->SetPredicate(finalPredicate); mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); finalPredicate = mitk::NodePredicateAnd::New(finalPredicate, isBinaryPredicate); m_Controls->m_TrackingMaskImageBox->SetPredicate(finalPredicate); m_Controls->m_TrackingSeedImageBox->SetPredicate(finalPredicate); m_Controls->m_TrackingStopImageBox->SetPredicate(finalPredicate); m_Controls->m_TrackingRawImageBox->SetPredicate(isDiffusionImage); m_Controls->m_TrackingMaskImageBox->SetZeroEntryText("--"); m_Controls->m_TrackingSeedImageBox->SetZeroEntryText("--"); m_Controls->m_TrackingStopImageBox->SetZeroEntryText("--"); m_Controls->m_TissueImageBox->SetZeroEntryText("--"); AddTrainingWidget(); UpdateGui(); } } void QmitkMLBTView::AddTrainingWidget() { std::shared_ptr tw = std::make_shared(); tw->SetDataStorage(this->GetDataStorage()); m_Controls->m_TwFrame->layout()->addWidget(tw.get()); m_TrainingWidgets.push_back(tw); } void QmitkMLBTView::RemoveTrainingWidget() { if(m_TrainingWidgets.size()>1) { m_TrainingWidgets.back().reset(); m_TrainingWidgets.pop_back(); } } void QmitkMLBTView::UpdateGui() { if (m_ForestHandler->IsForestValid()) { std::string label_text="Random forest available: "+m_LastLoadedForestName; m_Controls->statusLabel->setText( QString(label_text.c_str()) ); m_Controls->m_SaveForestButton->setEnabled(true); m_Controls->m_StartTrackingButton->setEnabled(true); } else { m_Controls->statusLabel->setText("Please load or train random forest!"); m_Controls->m_SaveForestButton->setEnabled(false); m_Controls->m_StartTrackingButton->setEnabled(false); } } void QmitkMLBTView::SetFocus() { m_Controls->toolBox->setFocus(); } void QmitkMLBTView::AbortTracking() { if (tracker.IsNotNull()) { tracker->m_AbortTracking = true; } } void QmitkMLBTView::PauseTracking() { if (tracker.IsNotNull()) { tracker->m_PauseTracking = !tracker->m_PauseTracking; } } void QmitkMLBTView::ChangeTimerInterval(int value) { m_TrackingTimer->setInterval(value); } -void QmitkMLBTView::ToggleDemoMode(int state) +void QmitkMLBTView::ToggleDemoMode(int ) { if (tracker.IsNotNull()) { tracker->SetDemoMode(m_Controls->m_DemoModeBox->isChecked()); tracker->m_Stop = false; } } void QmitkMLBTView::BuildFibers() { if (m_Controls->m_DemoModeBox->isChecked() && tracker.IsNotNull() && tracker->m_BuildFibersFinished) { vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData(); mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly); outFib->SetFiberColors(255,255,255); m_TractogramNode->SetData(outFib); m_SamplingPointsNode->SetData(tracker->m_SamplingPointset); m_AlternativePointsNode->SetData(tracker->m_AlternativePointset); m_StopVotePointsNode->SetData(tracker->m_StopVotePointset); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); tracker->m_BuildFibersFinished = false; tracker->m_BuildFibersReady = 0; tracker->m_Stop = false; } } void QmitkMLBTView::LoadForest() { QString filename = QFileDialog::getOpenFileName(0, tr("Load Forest"), QDir::currentPath(), tr("HDF5 random forest file (*.rf)") ); if(filename.isEmpty() || filename.isNull()) return; m_ForestHandler->LoadForest( filename.toStdString() ); QFileInfo fi( filename ); m_LastLoadedForestName = QString( fi.baseName() + "." + fi.completeSuffix() ).toStdString(); UpdateGui(); } void QmitkMLBTView::StartTrackingThread() { m_TractogramNode = mitk::DataNode::New(); m_TractogramNode->SetName("MLBT Result"); //m_TractogramNode->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(20)); m_TractogramNode->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(true)); m_TractogramNode->SetProperty("LineWidth", mitk::IntProperty::New(1)); //m_TractogramNode->SetProperty("color",mitk::ColorProperty::New(0, 1, 1)); this->GetDataStorage()->Add(m_TractogramNode); m_SamplingPointsNode = mitk::DataNode::New(); m_SamplingPointsNode->SetName("SamplingPoints"); m_SamplingPointsNode->SetProperty("pointsize", mitk::FloatProperty::New(0.2)); m_SamplingPointsNode->SetProperty("color", mitk::ColorProperty::New(1,1,1)); mitk::PointSetShapeProperty::Pointer bla = mitk::PointSetShapeProperty::New(); bla->SetValue(8); m_SamplingPointsNode->SetProperty("Pointset.2D.shape", bla); m_SamplingPointsNode->SetProperty("Pointset.2D.distance to plane", mitk::FloatProperty::New(1.5)); m_SamplingPointsNode->SetProperty("point 2D size", mitk::FloatProperty::New(0.1)); m_SamplingPointsNode->SetProperty("Pointset.2D.fill shape", mitk::BoolProperty::New(true)); this->GetDataStorage()->Add(m_SamplingPointsNode); m_AlternativePointsNode = mitk::DataNode::New(); m_AlternativePointsNode->SetName("AlternativePoints"); m_AlternativePointsNode->SetProperty("pointsize", mitk::FloatProperty::New(0.2)); m_AlternativePointsNode->SetProperty("color", mitk::ColorProperty::New(0,1,0)); m_AlternativePointsNode->SetProperty("Pointset.2D.shape", bla); m_AlternativePointsNode->SetProperty("Pointset.2D.distance to plane", mitk::FloatProperty::New(1.5)); m_AlternativePointsNode->SetProperty("point 2D size", mitk::FloatProperty::New(0.1)); m_AlternativePointsNode->SetProperty("Pointset.2D.fill shape", mitk::BoolProperty::New(true)); this->GetDataStorage()->Add(m_AlternativePointsNode); m_StopVotePointsNode = mitk::DataNode::New(); m_StopVotePointsNode->SetName("StopVotes"); m_StopVotePointsNode->SetProperty("pointsize", mitk::FloatProperty::New(0.2)); m_StopVotePointsNode->SetProperty("color", mitk::ColorProperty::New(1,0,0)); m_StopVotePointsNode->SetProperty("Pointset.2D.shape", bla); m_StopVotePointsNode->SetProperty("Pointset.2D.distance to plane", mitk::FloatProperty::New(1.5)); m_StopVotePointsNode->SetProperty("point 2D size", mitk::FloatProperty::New(0.1)); m_StopVotePointsNode->SetProperty("Pointset.2D.fill shape", mitk::BoolProperty::New(true)); this->GetDataStorage()->Add(m_StopVotePointsNode); QFuture future = QtConcurrent::run( this, &QmitkMLBTView::StartTracking ); m_TrackingWatcher.setFuture(future); m_TrackingThreadIsRunning = true; m_Controls->m_StartTrackingButton->setEnabled(false); m_TrackingTimer->start(m_Controls->m_TimerIntervalBox->value()); } void QmitkMLBTView::OnTrackingThreadStop() { m_TrackingThreadIsRunning = false; m_Controls->m_StartTrackingButton->setEnabled(true); vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData(); mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly); m_TractogramNode->SetData(outFib); m_TractogramNode->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(1)); if (m_Controls->m_DemoModeBox->isChecked()) { m_SamplingPointsNode->SetData(tracker->m_SamplingPointset); m_AlternativePointsNode->SetData(tracker->m_AlternativePointset); } tracker = nullptr; m_TrackingTimer->stop(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkMLBTView::StartTracking() { if ( m_Controls->m_TrackingRawImageBox->GetSelectedNode().IsNull() || !m_ForestHandler->IsForestValid()) return; mitk::Image::Pointer dwi = dynamic_cast(m_Controls->m_TrackingRawImageBox->GetSelectedNode()->GetData()); m_ForestHandler->AddDwi(dwi); m_ForestHandler->SetMode(mitk::TrackingDataHandler::MODE::DETERMINISTIC); // int numThread = itk::MultiThreader::GetGlobalDefaultNumberOfThreads(); tracker = TrackerType::New(); tracker->SetDemoMode(m_Controls->m_DemoModeBox->isChecked()); if (m_Controls->m_DemoModeBox->isChecked()) tracker->SetNumberOfThreads(1); if (m_Controls->m_TrackingMaskImageBox->GetSelectedNode().IsNotNull()) { mitk::Image::Pointer mask = dynamic_cast(m_Controls->m_TrackingMaskImageBox->GetSelectedNode()->GetData()); ItkUcharImgType::Pointer itkMask = ItkUcharImgType::New(); mitk::CastToItkImage(mask, itkMask); tracker->SetMaskImage(itkMask); } if (m_Controls->m_TrackingSeedImageBox->GetSelectedNode().IsNotNull()) { mitk::Image::Pointer img = dynamic_cast(m_Controls->m_TrackingSeedImageBox->GetSelectedNode()->GetData()); ItkUcharImgType::Pointer itkImg = ItkUcharImgType::New(); mitk::CastToItkImage(img, itkImg); tracker->SetSeedImage(itkImg); } if (m_Controls->m_TrackingStopImageBox->GetSelectedNode().IsNotNull()) { mitk::Image::Pointer img = dynamic_cast(m_Controls->m_TrackingStopImageBox->GetSelectedNode()->GetData()); ItkUcharImgType::Pointer itkImg = ItkUcharImgType::New(); mitk::CastToItkImage(img, itkImg); tracker->SetStoppingRegions(itkImg); } if (m_Controls->m_TissueImageBox->GetSelectedNode().IsNotNull()) { mitk::Image::Pointer img = dynamic_cast(m_Controls->m_TissueImageBox->GetSelectedNode()->GetData()); ItkUcharImgType::Pointer itkImg = ItkUcharImgType::New(); mitk::CastToItkImage(img, itkImg); tracker->SetTissueImage(itkImg); } tracker->SetSeedsPerVoxel(m_Controls->m_NumberOfSeedsBox->value()); tracker->SetStepSize(m_Controls->m_TrackingStepSizeBox->value()); tracker->SetMinTractLength(m_Controls->m_MinLengthBox->value()); tracker->SetMaxTractLength(m_Controls->m_MaxLengthBox->value()); tracker->SetAposterioriCurvCheck(false); tracker->SetNumberOfSamples(m_Controls->m_NumSamplesBox->value()); tracker->SetTrackingHandler(m_ForestHandler); tracker->SetSamplingDistance(m_Controls->m_SamplingDistanceBox->value()); tracker->SetUseStopVotes(m_Controls->m_OnlyForwardSamples->isChecked()); tracker->SetOnlyForwardSamples(m_Controls->m_OnlyForwardSamples->isChecked()); tracker->SetNumPreviousDirections(m_Controls->m_NumPrevDirs->value()); tracker->SetSeedOnlyGm(m_Controls->m_SeedGm->isChecked()); tracker->Update(); } void QmitkMLBTView::SaveForest() { if (!m_ForestHandler->IsForestValid()) { UpdateGui(); return; } QString filename = QFileDialog::getSaveFileName(0, tr("Save Forest"), QDir::currentPath()+"/forest.rf", tr("HDF5 random forest file (*.rf)") ); if(filename.isEmpty() || filename.isNull()) return; if(!filename.endsWith(".rf")) filename += ".rf"; m_ForestHandler->SaveForest( filename.toStdString() ); } void QmitkMLBTView::StartTrainingThread() { if (!this->IsTrainingInputValid()) { QMessageBox::warning(nullptr, "Training aborted", "Training could not be started. Not all necessary datasets were selected."); return; } QFuture future = QtConcurrent::run( this, &QmitkMLBTView::StartTraining ); m_TrainingWatcher.setFuture(future); m_Controls->m_StartTrainingButton->setEnabled(false); m_Controls->m_StartTrainingButton->setText("Training in progress ..."); m_Controls->m_StartTrainingButton->setToolTip("Training in progress. This can take up to a couple of hours."); m_Controls->m_StartTrainingButton->setCursor(Qt::WaitCursor); QApplication::processEvents(); m_Controls->m_SaveForestButton->setEnabled(false); m_Controls->m_LoadForestButton->setEnabled(false); } void QmitkMLBTView::OnTrainingThreadStop() { m_Controls->m_StartTrainingButton->setEnabled(true); m_Controls->m_SaveForestButton->setEnabled(true); m_Controls->m_LoadForestButton->setEnabled(true); m_Controls->m_StartTrainingButton->setCursor(Qt::ArrowCursor); m_Controls->m_StartTrainingButton->setText("Start Training"); m_Controls->m_StartTrainingButton->setToolTip("Start Training. This can take up to a couple of hours."); m_LastLoadedForestName = "new_forest"; UpdateGui(); QApplication::processEvents(); } void QmitkMLBTView::StartTraining() { std::vector< mitk::Image::Pointer > m_SelectedDiffImages; std::vector< mitk::FiberBundle::Pointer > m_SelectedFB; std::vector< ItkUcharImgType::Pointer > m_MaskImages; std::vector< ItkUcharImgType::Pointer > m_WhiteMatterImages; for (auto w : m_TrainingWidgets) { m_SelectedDiffImages.push_back(dynamic_cast(w->GetImage()->GetData())); m_SelectedFB.push_back(dynamic_cast(w->GetFibers()->GetData())); if (w->GetMask().IsNotNull()) { mitk::Image::Pointer img = dynamic_cast(w->GetMask()->GetData()); ItkUcharImgType::Pointer itkMask = ItkUcharImgType::New(); mitk::CastToItkImage(img, itkMask); m_MaskImages.push_back(itkMask); } else m_MaskImages.push_back(nullptr); if (w->GetWhiteMatter().IsNotNull()) { mitk::Image::Pointer img = dynamic_cast(w->GetWhiteMatter()->GetData()); ItkUcharImgType::Pointer itkMask = ItkUcharImgType::New(); mitk::CastToItkImage(img, itkMask); m_WhiteMatterImages.push_back(itkMask); } else m_WhiteMatterImages.push_back(nullptr); } m_ForestHandler->SetDwis(m_SelectedDiffImages); m_ForestHandler->SetTractograms(m_SelectedFB); m_ForestHandler->SetMaskImages(m_MaskImages); m_ForestHandler->SetWhiteMatterImages(m_WhiteMatterImages); m_ForestHandler->SetNumTrees(m_Controls->m_NumTreesBox->value()); m_ForestHandler->SetMaxTreeDepth(m_Controls->m_MaxDepthBox->value()); m_ForestHandler->SetGrayMatterSamplesPerVoxel(m_Controls->m_GmSamplingBox->value()); m_ForestHandler->SetSampleFraction(m_Controls->m_SampleFractionBox->value()); m_ForestHandler->SetStepSize(m_Controls->m_TrainingStepSizeBox->value()); m_ForestHandler->SetNumPreviousDirections(m_Controls->m_NumPrevDirs->value()); m_ForestHandler->StartTraining(); } bool QmitkMLBTView::IsTrainingInputValid(void) const { for (auto widget : m_TrainingWidgets) { if (widget->GetImage().IsNull() || widget->GetFibers().IsNull()) { return false; } } return true; } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.cpp index 2a2df6ef69..428b3e5bc4 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.cpp @@ -1,592 +1,595 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include #include // Qmitk #include "QmitkStreamlineTrackingView.h" #include "QmitkStdMultiWidget.h" // Qt #include // MITK #include #include #include #include #include #include #include #include #include #include #include #include // VTK #include #include #include #include #include #include #include #include #include const std::string QmitkStreamlineTrackingView::VIEW_ID = "org.mitk.views.streamlinetracking"; const std::string id_DataManager = "org.mitk.views.datamanager"; using namespace berry; QmitkStreamlineTrackingView::QmitkStreamlineTrackingView() : m_Controls(nullptr) , m_TrackingHandler(nullptr) { } // Destructor QmitkStreamlineTrackingView::~QmitkStreamlineTrackingView() { } void QmitkStreamlineTrackingView::CreateQtPartControl( QWidget *parent ) { if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkStreamlineTrackingViewControls; m_Controls->setupUi( parent ); m_Controls->m_FaImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_SeedImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_MaskImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_StopImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_TissueImageBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isImagePredicate = mitk::TNodePredicateDataType::New(); mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateNot::Pointer isNotBinaryPredicate = mitk::NodePredicateNot::New( isBinaryPredicate ); mitk::NodePredicateAnd::Pointer isNotABinaryImagePredicate = mitk::NodePredicateAnd::New( isImagePredicate, isNotBinaryPredicate ); mitk::NodePredicateDimension::Pointer dimensionPredicate = mitk::NodePredicateDimension::New(3); m_Controls->m_FaImageBox->SetPredicate( mitk::NodePredicateAnd::New(isNotABinaryImagePredicate, dimensionPredicate) ); m_Controls->m_FaImageBox->SetZeroEntryText("--"); m_Controls->m_SeedImageBox->SetPredicate( mitk::NodePredicateAnd::New(isBinaryPredicate, dimensionPredicate) ); m_Controls->m_SeedImageBox->SetZeroEntryText("--"); m_Controls->m_MaskImageBox->SetPredicate( mitk::NodePredicateAnd::New(isBinaryPredicate, dimensionPredicate) ); m_Controls->m_MaskImageBox->SetZeroEntryText("--"); m_Controls->m_StopImageBox->SetPredicate( mitk::NodePredicateAnd::New(isBinaryPredicate, dimensionPredicate) ); m_Controls->m_StopImageBox->SetZeroEntryText("--"); m_Controls->m_TissueImageBox->SetPredicate( mitk::NodePredicateAnd::New(isNotABinaryImagePredicate, dimensionPredicate) ); m_Controls->m_TissueImageBox->SetZeroEntryText("--"); connect( m_Controls->commandLinkButton, SIGNAL(clicked()), this, SLOT(DoFiberTracking()) ); connect( m_Controls->m_InteractiveBox, SIGNAL(stateChanged(int)), this, SLOT(ToggleInteractive()) ); connect( m_Controls->m_TissueImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()) ); connect( m_Controls->m_ModeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()) ); connect( m_Controls->m_FaImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(DeleteTrackingHandler()) ); connect( m_Controls->m_ModeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(DeleteTrackingHandler()) ); m_FirstTensorProbRun = true; } UpdateGui(); } void QmitkStreamlineTrackingView::ToggleInteractive() { UpdateGui(); mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart(); if ( m_Controls->m_InteractiveBox->isChecked() ) { QApplication::setOverrideCursor(Qt::PointingHandCursor); QApplication::processEvents(); m_InteractiveNode = mitk::DataNode::New(); QString name("InteractiveFib"); m_InteractiveNode->SetName(name.toStdString()); GetDataStorage()->Add(m_InteractiveNode); m_InteractivePointSetNode = mitk::DataNode::New(); m_InteractivePointSetNode->SetProperty("color", mitk::ColorProperty::New(1,1,1)); m_InteractivePointSetNode->SetName("InteractiveSeedRegion"); mitk::PointSetShapeProperty::Pointer shape_prop = mitk::PointSetShapeProperty::New(); shape_prop->SetValue(mitk::PointSetShapeProperty::PointSetShape::CIRCLE); m_InteractivePointSetNode->SetProperty("Pointset.2D.shape", shape_prop); GetDataStorage()->Add(m_InteractivePointSetNode); if (renderWindow) { { mitk::SliceNavigationController* slicer = renderWindow->GetQmitkRenderWindow(QString("axial"))->GetSliceNavigationController(); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkStreamlineTrackingView::OnSliceChanged ); m_SliceObserverTag1 = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), command ); } { mitk::SliceNavigationController* slicer = renderWindow->GetQmitkRenderWindow(QString("sagittal"))->GetSliceNavigationController(); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkStreamlineTrackingView::OnSliceChanged ); m_SliceObserverTag2 = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), command ); } { mitk::SliceNavigationController* slicer = renderWindow->GetQmitkRenderWindow(QString("coronal"))->GetSliceNavigationController(); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkStreamlineTrackingView::OnSliceChanged ); m_SliceObserverTag3 = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), command ); } } } else { QApplication::restoreOverrideCursor(); QApplication::processEvents(); m_InteractiveNode = nullptr; m_InteractivePointSetNode = nullptr; - mitk::SliceNavigationController* slicer = renderWindow->GetQmitkRenderWindow(QString("axial"))->GetSliceNavigationController(); - slicer->RemoveObserver(m_SliceObserverTag1); - slicer = renderWindow->GetQmitkRenderWindow(QString("sagittal"))->GetSliceNavigationController(); - slicer->RemoveObserver(m_SliceObserverTag2); - slicer = renderWindow->GetQmitkRenderWindow(QString("coronal"))->GetSliceNavigationController(); - slicer->RemoveObserver(m_SliceObserverTag3); + if (renderWindow) + { + mitk::SliceNavigationController* slicer = renderWindow->GetQmitkRenderWindow(QString("axial"))->GetSliceNavigationController(); + slicer->RemoveObserver(m_SliceObserverTag1); + slicer = renderWindow->GetQmitkRenderWindow(QString("sagittal"))->GetSliceNavigationController(); + slicer->RemoveObserver(m_SliceObserverTag2); + slicer = renderWindow->GetQmitkRenderWindow(QString("coronal"))->GetSliceNavigationController(); + slicer->RemoveObserver(m_SliceObserverTag3); + } } } void QmitkStreamlineTrackingView::OnSliceChanged(const itk::EventObject& /*e*/) { std::srand(std::time(0)); m_SeedPoints.clear(); itk::Point world_pos = this->GetRenderWindowPart()->GetSelectedPosition(); m_SeedPoints.push_back(world_pos); float radius = m_Controls->m_SeedRadiusBox->value(); int num = m_Controls->m_NumSeedsBox->value(); mitk::PointSet::Pointer pointset = mitk::PointSet::New(); pointset->InsertPoint(0, world_pos); m_InteractivePointSetNode->SetProperty("pointsize", mitk::FloatProperty::New(radius*2)); m_InteractivePointSetNode->SetProperty("point 2D size", mitk::FloatProperty::New(radius*2)); m_InteractivePointSetNode->SetData(pointset); for (int i=1; i p; p[0] = rand()%1000-500; p[1] = rand()%1000-500; p[2] = rand()%1000-500; p.Normalize(); p *= radius; m_SeedPoints.push_back(world_pos+p); } DoFiberTracking(); } void QmitkStreamlineTrackingView::SetFocus() { } void QmitkStreamlineTrackingView::DeleteTrackingHandler() { if (m_TrackingHandler != nullptr) { delete m_TrackingHandler; m_TrackingHandler = nullptr; } } void QmitkStreamlineTrackingView::OnSelectionChanged( berry::IWorkbenchPart::Pointer part, const QList& nodes ) { m_InputImageNodes.clear(); m_InputImages.clear(); DeleteTrackingHandler(); for( auto node : nodes ) { if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { if( dynamic_cast(node->GetData()) ) { m_InputImageNodes.push_back(node); m_InputImages.push_back(dynamic_cast(node->GetData())); } else if ( dynamic_cast(node->GetData()) ) { m_InputImageNodes.push_back(node); m_InputImages.push_back(dynamic_cast(node->GetData())); } else { mitk::Image* img = dynamic_cast(node->GetData()); if (img!=nullptr) { int dim = img->GetDimension(); unsigned int* dimensions = img->GetDimensions(); if (dim==4 && dimensions[3]%3==0) { m_InputImageNodes.push_back(node); m_InputImages.push_back(dynamic_cast(node->GetData())); } } } } } UpdateGui(); } void QmitkStreamlineTrackingView::UpdateGui() { m_Controls->m_TensorImageLabel->setText("mandatory"); m_Controls->m_fBox->setVisible(false); m_Controls->m_fLabel->setVisible(false); m_Controls->m_gBox->setVisible(false); m_Controls->m_gLabel->setVisible(false); m_Controls->m_FaImageBox->setVisible(false); m_Controls->mFaImageLabel->setVisible(false); m_Controls->m_OdfCutoffBox->setVisible(false); m_Controls->m_OdfCutoffLabel->setVisible(false); m_Controls->m_SharpenOdfsBox->setVisible(false); if (m_Controls->m_TissueImageBox->GetSelectedNode().IsNotNull()) m_Controls->m_SeedGmBox->setVisible(true); else m_Controls->m_SeedGmBox->setVisible(false); if(!m_InputImageNodes.empty()) { if (m_InputImageNodes.size()>1) m_Controls->m_TensorImageLabel->setText(m_InputImageNodes.size()+" images selected"); else m_Controls->m_TensorImageLabel->setText(m_InputImageNodes.at(0)->GetName().c_str()); m_Controls->m_InputData->setTitle("Input Data"); m_Controls->commandLinkButton->setEnabled(!m_Controls->m_InteractiveBox->isChecked()); m_Controls->m_InteractiveBox->setEnabled(true); if ( dynamic_cast(m_InputImageNodes.at(0)->GetData()) ) { m_Controls->m_fBox->setVisible(true); m_Controls->m_fLabel->setVisible(true); m_Controls->m_gBox->setVisible(true); m_Controls->m_gLabel->setVisible(true); m_Controls->mFaImageLabel->setVisible(true); m_Controls->m_FaImageBox->setVisible(true); -// if (m_Controls->m_ModeBox->currentIndex()==1) -// { -// m_Controls->m_OdfCutoffBox->setVisible(true); -// m_Controls->m_OdfCutoffLabel->setVisible(true); -// m_Controls->m_SharpenOdfsBox->setVisible(true); -// } + // if (m_Controls->m_ModeBox->currentIndex()==1) + // { + // m_Controls->m_OdfCutoffBox->setVisible(true); + // m_Controls->m_OdfCutoffLabel->setVisible(true); + // m_Controls->m_SharpenOdfsBox->setVisible(true); + // } } else if ( dynamic_cast(m_InputImageNodes.at(0)->GetData()) ) { m_Controls->mFaImageLabel->setVisible(true); m_Controls->m_FaImageBox->setVisible(true); m_Controls->m_OdfCutoffBox->setVisible(true); m_Controls->m_OdfCutoffLabel->setVisible(true); m_Controls->m_SharpenOdfsBox->setVisible(true); } } else { m_Controls->m_InputData->setTitle("Please Select Input Data"); m_Controls->commandLinkButton->setEnabled(!m_Controls->m_InteractiveBox->isChecked()); m_Controls->m_InteractiveBox->setEnabled(false); } } void QmitkStreamlineTrackingView::DoFiberTracking() { if (m_InputImages.empty()) return; if( dynamic_cast(m_InputImageNodes.at(0)->GetData()) ) { typedef itk::Image< itk::DiffusionTensor3D, 3> TensorImageType; typedef mitk::ImageToItk CasterType; if (m_Controls->m_ModeBox->currentIndex()==1) { if (m_InputImages.size()>1) { QMessageBox::information(nullptr, "Information", "Probabilistic tensor tractography is only implemented for single-tensor mode!"); return; } if (m_FirstTensorProbRun) { QMessageBox::information(nullptr, "Information", "Internally calculating ODF from tensor image and performing probabilistic ODF tractography. ODFs are sharpened (min-max normalized and raised to the power of 4). TEND parameters are ignored."); m_FirstTensorProbRun = false; } if (m_TrackingHandler==nullptr) { typedef mitk::ImageToItk< mitk::TrackingHandlerOdf::ItkOdfImageType > CasterType; m_TrackingHandler = new mitk::TrackingHandlerOdf(); TensorImageType::Pointer itkImg = TensorImageType::New(); mitk::CastToItkImage(m_InputImages.at(0), itkImg); typedef itk::TensorImageToQBallImageFilter< float, float > FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkImg ); filter->Update(); dynamic_cast(m_TrackingHandler)->SetOdfImage(filter->GetOutput()); if (m_Controls->m_FaImageBox->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer itkImg = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast(m_Controls->m_FaImageBox->GetSelectedNode()->GetData()), itkImg); dynamic_cast(m_TrackingHandler)->SetGfaImage(itkImg); } } dynamic_cast(m_TrackingHandler)->SetGfaThreshold(m_Controls->m_ScalarThresholdBox->value()); dynamic_cast(m_TrackingHandler)->SetOdfThreshold(0); dynamic_cast(m_TrackingHandler)->SetSharpenOdfs(true); } else { if (m_TrackingHandler==nullptr) { m_TrackingHandler = new mitk::TrackingHandlerTensor(); for (int i=0; i<(int)m_InputImages.size(); i++) { TensorImageType::Pointer itkImg = TensorImageType::New(); mitk::CastToItkImage(m_InputImages.at(i), itkImg); dynamic_cast(m_TrackingHandler)->AddTensorImage(itkImg); } if (m_Controls->m_FaImageBox->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer itkImg = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast(m_Controls->m_FaImageBox->GetSelectedNode()->GetData()), itkImg); dynamic_cast(m_TrackingHandler)->SetFaImage(itkImg); } } dynamic_cast(m_TrackingHandler)->SetFaThreshold(m_Controls->m_ScalarThresholdBox->value()); dynamic_cast(m_TrackingHandler)->SetF((float)m_Controls->m_fBox->value()); dynamic_cast(m_TrackingHandler)->SetG((float)m_Controls->m_gBox->value()); } } else if ( dynamic_cast(m_InputImageNodes.at(0)->GetData()) ) { if (m_TrackingHandler==nullptr) { typedef mitk::ImageToItk< mitk::TrackingHandlerOdf::ItkOdfImageType > CasterType; m_TrackingHandler = new mitk::TrackingHandlerOdf(); mitk::TrackingHandlerOdf::ItkOdfImageType::Pointer itkImg = mitk::TrackingHandlerOdf::ItkOdfImageType::New(); mitk::CastToItkImage(m_InputImages.at(0), itkImg); dynamic_cast(m_TrackingHandler)->SetOdfImage(itkImg); if (m_Controls->m_FaImageBox->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer itkImg = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast(m_Controls->m_FaImageBox->GetSelectedNode()->GetData()), itkImg); dynamic_cast(m_TrackingHandler)->SetGfaImage(itkImg); } } dynamic_cast(m_TrackingHandler)->SetGfaThreshold(m_Controls->m_ScalarThresholdBox->value()); dynamic_cast(m_TrackingHandler)->SetOdfThreshold(m_Controls->m_OdfCutoffBox->value()); dynamic_cast(m_TrackingHandler)->SetSharpenOdfs(m_Controls->m_SharpenOdfsBox->isChecked()); } else { if (m_Controls->m_ModeBox->currentIndex()==1) { QMessageBox::information(nullptr, "Information", "Probabilstic tractography is not implemented for peak images."); return; } try { if (m_TrackingHandler==nullptr) { typedef mitk::ImageToItk< mitk::TrackingHandlerPeaks::PeakImgType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(m_InputImages.at(0)); caster->Update(); mitk::TrackingHandlerPeaks::PeakImgType::Pointer itkImg = caster->GetOutput(); m_TrackingHandler = new mitk::TrackingHandlerPeaks(); dynamic_cast(m_TrackingHandler)->SetPeakImage(itkImg); } dynamic_cast(m_TrackingHandler)->SetPeakThreshold(m_Controls->m_ScalarThresholdBox->value()); } catch(...) { return; } } m_TrackingHandler->SetFlipX(m_Controls->m_FlipXBox->isChecked()); m_TrackingHandler->SetFlipY(m_Controls->m_FlipYBox->isChecked()); m_TrackingHandler->SetFlipZ(m_Controls->m_FlipZBox->isChecked()); m_TrackingHandler->SetInterpolate(m_Controls->m_InterpolationBox->isChecked()); switch (m_Controls->m_ModeBox->currentIndex()) { case 0: m_TrackingHandler->SetMode(mitk::TrackingDataHandler::MODE::DETERMINISTIC); break; case 1: m_TrackingHandler->SetMode(mitk::TrackingDataHandler::MODE::PROBABILISTIC); break; default: m_TrackingHandler->SetMode(mitk::TrackingDataHandler::MODE::DETERMINISTIC); } typedef itk::StreamlineTrackingFilter TrackerType; TrackerType::Pointer tracker = TrackerType::New(); if (m_Controls->m_InteractiveBox->isChecked()) { tracker->SetSeedPoints(m_SeedPoints); } else if (m_Controls->m_SeedImageBox->GetSelectedNode().IsNotNull()) { ItkUCharImageType::Pointer mask = ItkUCharImageType::New(); mitk::CastToItkImage(dynamic_cast(m_Controls->m_SeedImageBox->GetSelectedNode()->GetData()), mask); tracker->SetSeedImage(mask); } if (m_Controls->m_MaskImageBox->GetSelectedNode().IsNotNull()) { ItkUCharImageType::Pointer mask = ItkUCharImageType::New(); mitk::CastToItkImage(dynamic_cast(m_Controls->m_MaskImageBox->GetSelectedNode()->GetData()), mask); tracker->SetMaskImage(mask); } if (m_Controls->m_StopImageBox->GetSelectedNode().IsNotNull()) { ItkUCharImageType::Pointer mask = ItkUCharImageType::New(); mitk::CastToItkImage(dynamic_cast(m_Controls->m_StopImageBox->GetSelectedNode()->GetData()), mask); tracker->SetStoppingRegions(mask); } if (m_Controls->m_TissueImageBox->GetSelectedNode().IsNotNull()) { ItkUCharImageType::Pointer mask = ItkUCharImageType::New(); mitk::CastToItkImage(dynamic_cast(m_Controls->m_TissueImageBox->GetSelectedNode()->GetData()), mask); tracker->SetTissueImage(mask); tracker->SetSeedOnlyGm(m_Controls->m_SeedGmBox->isChecked()); } tracker->SetSeedsPerVoxel(m_Controls->m_SeedsPerVoxelBox->value()); tracker->SetStepSize(m_Controls->m_StepSizeBox->value()); //tracker->SetSamplingDistance(0.7); tracker->SetUseStopVotes(false); tracker->SetOnlyForwardSamples(false); tracker->SetAposterioriCurvCheck(false); tracker->SetMaxNumTracts(m_Controls->m_NumFibersBox->value()); tracker->SetNumberOfSamples(m_Controls->m_NumSamplesBox->value()); tracker->SetTrackingHandler(m_TrackingHandler); tracker->SetAngularThreshold(m_Controls->m_AngularThresholdBox->value()); tracker->SetMinTractLength(m_Controls->m_MinTractLengthBox->value()); tracker->SetUseOutputProbabilityMap(m_Controls->m_OutputProbMap->isChecked() && !m_Controls->m_InteractiveBox->isChecked()); tracker->Update(); if (m_Controls->m_InteractiveBox->isChecked()) { vtkSmartPointer fiberBundle = tracker->GetFiberPolyData(); if (m_InteractiveNode.IsNull()) { m_InteractiveNode = mitk::DataNode::New(); QString name("InteractiveFib"); m_InteractiveNode->SetName(name.toStdString()); GetDataStorage()->Add(m_InteractiveNode); } mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(fiberBundle); fib->SetReferenceGeometry(dynamic_cast(m_InputImageNodes.at(0)->GetData())->GetGeometry()); if (m_Controls->m_ResampleFibersBox->isChecked()) fib->Compress(m_Controls->m_FiberErrorBox->value()); m_InteractiveNode->SetData(fib); } else if (!tracker->GetUseOutputProbabilityMap()) { vtkSmartPointer fiberBundle = tracker->GetFiberPolyData(); if (fiberBundle->GetNumberOfLines() == 0) { QMessageBox warnBox; warnBox.setWindowTitle("Warning"); warnBox.setText("No fiberbundle was generated!"); warnBox.setDetailedText("No fibers were generated using the chosen parameters. Typical reasons are:\n\n- Cutoff too high. Some images feature very low FA/GFA/peak size. Try to lower this parameter.\n- Angular threshold too strict. Try to increase this parameter.\n- A small step sizes also means many steps to go wrong. Especially in the case of probabilistic tractography. Try to adjust the angular threshold."); warnBox.setIcon(QMessageBox::Warning); warnBox.exec(); return; } mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(fiberBundle); fib->SetReferenceGeometry(dynamic_cast(m_InputImageNodes.at(0)->GetData())->GetGeometry()); if (m_Controls->m_ResampleFibersBox->isChecked()) fib->Compress(m_Controls->m_FiberErrorBox->value()); fib->ColorFibersByOrientation(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(fib); QString name("FiberBundle_"); name += m_InputImageNodes.at(0)->GetName().c_str(); name += "_Streamline"; node->SetName(name.toStdString()); GetDataStorage()->Add(node, m_InputImageNodes.at(0)); } else { TrackerType::ItkDoubleImgType::Pointer outImg = tracker->GetOutputProbabilityMap(); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk(outImg.GetPointer()); img->SetVolume(outImg->GetBufferPointer()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(img); QString name("ProbabilityMap_"); name += m_InputImageNodes.at(0)->GetName().c_str(); node->SetName(name.toStdString()); mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); lut->SetType(mitk::LookupTable::JET_TRANSPARENT); mitk::LookupTableProperty::Pointer lut_prop = mitk::LookupTableProperty::New(); lut_prop->SetLookupTable(lut); node->SetProperty("LookupTable", lut_prop); node->SetProperty("opacity", mitk::FloatProperty::New(0.5)); GetDataStorage()->Add(node, m_InputImageNodes.at(0)); } }