diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractClusteringFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractClusteringFilter.cpp index d85f434205..c7feec9017 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractClusteringFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractClusteringFilter.cpp @@ -1,504 +1,492 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "itkTractClusteringFilter.h" #define _USE_MATH_DEFINES #include #include #include namespace itk{ TractClusteringFilter::TractClusteringFilter() : m_NumPoints(12) , m_InCentroids(nullptr) , m_MinClusterSize(1) , m_MaxClusters(0) , m_MergeDuplicateThreshold(-1) , m_DoResampling(true) , m_FilterMask(nullptr) , m_OverlapThreshold(0.0) { } TractClusteringFilter::~TractClusteringFilter() { for (auto m : m_Metrics) delete m; } std::vector > TractClusteringFilter::GetOutFiberIndices() const { return m_OutFiberIndices; } void TractClusteringFilter::SetMetrics(const std::vector &Metrics) { m_Metrics = Metrics; } std::vector TractClusteringFilter::GetOutClusters() const { return m_OutClusters; } std::vector TractClusteringFilter::GetOutCentroids() const { return m_OutCentroids; } std::vector TractClusteringFilter::GetOutTractograms() const { return m_OutTractograms; } void TractClusteringFilter::SetDistances(const std::vector &Distances) { m_Distances = Distances; } float TractClusteringFilter::CalcOverlap(vnl_matrix& t) { float overlap = 0; if (m_FilterMask.IsNotNull()) { for (unsigned int i=0; i p = t.get_column(i); itk::Point point; point[0] = p[0]; point[1] = p[1]; point[2] = p[2]; itk::Index<3> idx; m_FilterMask->TransformPhysicalPointToIndex(point, idx); if (m_FilterMask->GetLargestPossibleRegion().IsInside(idx) && m_FilterMask->GetPixel(idx)>0) overlap += 1; } overlap /= m_NumPoints; } else return 1.0; return overlap; } std::vector > TractClusteringFilter::ResampleFibers(mitk::FiberBundle::Pointer tractogram) { mitk::FiberBundle::Pointer temp_fib = tractogram->GetDeepCopy(); if (m_DoResampling) temp_fib->ResampleToNumPoints(m_NumPoints); std::vector< vnl_matrix > out_fib; for (int i=0; iGetFiberPolyData()->GetNumberOfCells(); i++) { vtkCell* cell = temp_fib->GetFiberPolyData()->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vnl_matrix streamline; streamline.set_size(3, m_NumPoints); streamline.fill(0.0); for (int j=0; jGetPoint(j, cand); vnl_vector_fixed< float, 3 > candV; candV[0]=cand[0]; candV[1]=cand[1]; candV[2]=cand[2]; streamline.set_column(j, candV); } out_fib.push_back(streamline); } return out_fib; } std::vector< TractClusteringFilter::Cluster > TractClusteringFilter::ClusterStep(std::vector< long > f_indices, std::vector distances) { float dist_thres = distances.back(); distances.pop_back(); std::vector< Cluster > C; int N = f_indices.size(); Cluster c1; c1.I.push_back(f_indices.at(0)); c1.h = T[f_indices.at(0)]; c1.n = 1; C.push_back(c1); if (f_indices.size()==1) return C; for (int i=1; i t = T.at(f_indices.at(i)); int min_cluster_index = -1; float min_cluster_distance = 99999; bool flip = false; for (unsigned int k=0; k v = C.at(k).h / C.at(k).n; bool f = false; float d = 0; for (auto m : m_Metrics) d += m->CalculateDistance(t, v, f); d /= m_Metrics.size(); if (d=0 && min_cluster_distance outC; -#pragma omp parallel for +//#pragma omp parallel for for (int c=0; c<(int)C.size(); c++) { std::vector< Cluster > tempC = ClusterStep(C.at(c).I, distances); AppendCluster(outC, tempC); } return outC; } else return C; } void TractClusteringFilter::AppendCluster(std::vector< Cluster >& a, std::vector< Cluster >&b) { for (auto c : b) a.push_back(c); } void TractClusteringFilter::MergeDuplicateClusters(std::vector< TractClusteringFilter::Cluster >& clusters) { if (m_MergeDuplicateThreshold<0) m_MergeDuplicateThreshold = m_Distances.at(0)/2; bool found = true; MITK_INFO << "Merging duplicate clusters with distance threshold " << m_MergeDuplicateThreshold; int start = 0; while (found && m_MergeDuplicateThreshold>mitk::eps) { std::cout << " \r"; std::cout << "Number of clusters: " << clusters.size() << '\r'; cout.flush(); found = false; for (int k1=start; k1<(int)clusters.size(); ++k1) { Cluster c1 = clusters.at(k1); vnl_matrix t = c1.h / c1.n; std::vector< int > merge_indices; std::vector< bool > flip_indices; #pragma omp parallel for for (int k2=0; k2<(int)clusters.size(); ++k2) { if (k1!=k2) { Cluster c2 = clusters.at(k2); vnl_matrix v = c2.h / c2.n; bool f = false; -// d = m_Metric->CalculateDistance(t, v, f); // alwayse use MDF? float d = 0; for (auto m : m_Metrics) d += m->CalculateDistance(t, v, f); d /= m_Metrics.size(); #pragma omp critical if (d TractClusteringFilter::AddToKnownClusters(std::vector< long > f_indices, std::vector >& centroids) { float dist_thres = m_Distances.at(0); int N = f_indices.size(); std::vector< Cluster > C; vnl_matrix zero_h; zero_h.set_size(T.at(0).rows(), T.at(0).cols()); zero_h.fill(0.0); Cluster no_fit; no_fit.h = zero_h; for (unsigned int i=0; i t = T.at(f_indices.at(i)); int min_cluster_index = -1; float min_cluster_distance = 99999; bool flip = false; if (CalcOverlap(t)>=m_OverlapThreshold) { int c_idx = 0; for (vnl_matrix centroid : centroids) { bool f = false; float d = 0; for (auto m : m_Metrics) d += m->CalculateDistance(t, centroid, f); d /= m_Metrics.size(); if (d=0 && min_cluster_distance f_indices; for (unsigned int i=0; i clusters; if (m_InCentroids.IsNull()) { MITK_INFO << "Clustering fibers"; clusters = ClusterStep(f_indices, m_Distances); -// while (clusters.size()>5000) -// { -// MITK_INFO << "Number of clusters: " << clusters.size(); -// MITK_INFO << "Increasing cluster size"; -// for (unsigned int i=0; i > centroids = ResampleFibers(m_InCentroids); if (centroids.empty()) { MITK_INFO << "No fibers in centroid tractogram!"; return; } MITK_INFO << "Clustering with input centroids"; clusters = AddToKnownClusters(f_indices, centroids); no_match = clusters.back(); clusters.pop_back(); MITK_INFO << "Number of clusters: " << clusters.size(); MergeDuplicateClusters(clusters); } MITK_INFO << "Clustering finished"; int max = clusters.size()-1; if (m_MaxClusters>0 && clusters.size()-1>m_MaxClusters) max = m_MaxClusters; for (int i=clusters.size()-1; i>=0; --i) { Cluster c = clusters.at(i); if ( c.n>=(int)m_MinClusterSize && !(m_MaxClusters>0 && clusters.size()-i>m_MaxClusters) ) { m_OutClusters.push_back(c); vtkSmartPointer weights = vtkSmartPointer::New(); vtkSmartPointer pTmp = m_Tractogram->GeneratePolyDataByIds(c.I, weights); mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(pTmp); if (max>0) fib->SetFiberWeights((float)i/max); m_OutTractograms.push_back(fib); m_OutFiberIndices.push_back(c.I); // create centroid vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); vtkSmartPointer polyData = vtkSmartPointer::New(); vtkSmartPointer container = vtkSmartPointer::New(); vnl_matrix centroid_points = c.h / c.n; for (unsigned int j=0; jInsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); polyData->SetPoints(vtkNewPoints); polyData->SetLines(vtkNewCells); mitk::FiberBundle::Pointer centroid = mitk::FiberBundle::New(polyData); centroid->SetFiberColors(255, 255, 255); m_OutCentroids.push_back(centroid); } } MITK_INFO << "Final number of clusters: " << m_OutTractograms.size(); int w = 0; for (auto fib : m_OutTractograms) { if (m_OutTractograms.size()>1) { fib->SetFiberWeights((float)w/(m_OutTractograms.size()-1)); m_OutCentroids.at(w)->SetFiberWeights((float)w/(m_OutTractograms.size()-1)); } else { fib->SetFiberWeights(1); m_OutCentroids.at(w)->SetFiberWeights(1); } fib->ColorFibersByFiberWeights(false, false); ++w; } if (no_match.n>0) { vtkSmartPointer weights = vtkSmartPointer::New(); vtkSmartPointer pTmp = m_Tractogram->GeneratePolyDataByIds(no_match.I, weights); mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(pTmp); fib->SetFiberColors(0, 0, 0); m_OutFiberIndices.push_back(no_match.I); m_OutTractograms.push_back(fib); } } } diff --git a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/ExtractSimilarTracts.cpp b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/ExtractSimilarTracts.cpp index fd07b7bac2..a312dd42ac 100644 --- a/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/ExtractSimilarTracts.cpp +++ b/Modules/DiffusionImaging/FiberTracking/cmdapps/TractographyEvaluation/ExtractSimilarTracts.cpp @@ -1,240 +1,238 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include typedef itksys::SystemTools ist; typedef itk::Image ItkFloatImgType; mitk::FiberBundle::Pointer LoadFib(std::string filename) { std::vector fibInfile = mitk::IOUtil::Load(filename); if( fibInfile.empty() ) std::cout << "File " << filename << " could not be read!"; mitk::BaseData::Pointer baseData = fibInfile.at(0); return dynamic_cast(baseData.GetPointer()); } ItkFloatImgType::Pointer LoadItkImage(const std::string& filename) { mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::Load(filename)[0].GetPointer()); ItkFloatImgType::Pointer itkMask = ItkFloatImgType::New(); mitk::CastToItkImage(img, itkMask); return itkMask; } /*! \brief Spatially cluster fibers */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Extract Similar Tracts"); parser.setCategory("Fiber Tracking Evaluation"); parser.setContributor("MIC"); parser.setArgumentPrefix("--", "-"); parser.addArgument("", "i", mitkCommandLineParser::InputFile, "Input:", "input fiber bundle (.fib, .trk, .tck)", us::Any(), false); parser.addArgument("ref_tracts", "", mitkCommandLineParser::StringList, "Ref. Tracts:", "reference tracts (.fib, .trk, .tck)", us::Any(), false); parser.addArgument("ref_masks", "", mitkCommandLineParser::StringList, "Ref. Masks:", "reference bundle masks", us::Any()); parser.addArgument("", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output root", us::Any(), false); parser.addArgument("distance", "", mitkCommandLineParser::Int, "Distance:", "", 10); parser.addArgument("metric", "", mitkCommandLineParser::String, "Metric:", ""); parser.addArgument("subsample", "", mitkCommandLineParser::Float, "Subsampling factor:", "Only use specified fraction of input fibers", 1.0); std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; std::string in_fib = us::any_cast(parsedArgs["i"]); std::string out_root = us::any_cast(parsedArgs["o"]); mitkCommandLineParser::StringContainerType ref_bundle_files = us::any_cast(parsedArgs["ref_tracts"]); mitkCommandLineParser::StringContainerType ref_mask_files; if (parsedArgs.count("ref_masks")) ref_mask_files = us::any_cast(parsedArgs["ref_masks"]); if (ref_mask_files.size()>0 && ref_mask_files.size()!=ref_bundle_files.size()) { MITK_INFO << "If reference masks are used, there has to be one mask per reference tract."; return EXIT_FAILURE; } int distance = 10; if (parsedArgs.count("distance")) distance = us::any_cast(parsedArgs["distance"]); std::string metric = "EU_MEAN"; if (parsedArgs.count("metric")) metric = us::any_cast(parsedArgs["metric"]); float subsample = 1.0; if (parsedArgs.count("subsample")) subsample = us::any_cast(parsedArgs["subsample"]); try { mitk::FiberBundle::Pointer fib = LoadFib(in_fib); std::srand(0); if (subsample<1.0) fib = fib->SubsampleFibers(subsample); mitk::FiberBundle::Pointer resampled_fib = fib->GetDeepCopy(); resampled_fib->ResampleToNumPoints(12); std::vector< mitk::FiberBundle::Pointer > ref_fibs; std::vector< ItkFloatImgType::Pointer > ref_masks; for (std::size_t i=0; i distances; distances.push_back(distance); mitk::FiberBundle::Pointer anchor_tractogram = mitk::FiberBundle::New(nullptr); unsigned int c = 0; for (auto ref_fib : ref_fibs) { MITK_INFO << "Extracting " << ist::GetFilenameName(ref_bundle_files.at(c)); // std::streambuf *old = cout.rdbuf(); // <-- save // std::stringstream ss; // std::cout.rdbuf (ss.rdbuf()); // <-- redirect try { itk::TractClusteringFilter::Pointer segmenter = itk::TractClusteringFilter::New(); // calculate centroids from reference bundle { MITK_INFO << "TEST 1"; itk::TractClusteringFilter::Pointer clusterer = itk::TractClusteringFilter::New(); clusterer->SetDistances({10,20,30}); clusterer->SetTractogram(ref_fib); clusterer->SetMetrics({new mitk::ClusteringMetricEuclideanStd()}); clusterer->SetMergeDuplicateThreshold(0.0); clusterer->Update(); MITK_INFO << "TEST 2"; std::vector tracts = clusterer->GetOutCentroids(); ref_fib = mitk::FiberBundle::New(nullptr); ref_fib = ref_fib->AddBundles(tracts); - MITK_INFO << "TEST 3"; mitk::IOUtil::Save(ref_fib, out_root + "centroids_" + ist::GetFilenameName(ref_bundle_files.at(c))); segmenter->SetInCentroids(ref_fib); - MITK_INFO << "TEST 4"; } // segment tract segmenter->SetFilterMask(ref_masks.at(c)); segmenter->SetOverlapThreshold(0.8); segmenter->SetDistances(distances); segmenter->SetTractogram(resampled_fib); segmenter->SetMergeDuplicateThreshold(0.0); segmenter->SetDoResampling(false); if (metric=="EU_MEAN") segmenter->SetMetrics({new mitk::ClusteringMetricEuclideanMean()}); else if (metric=="EU_STD") segmenter->SetMetrics({new mitk::ClusteringMetricEuclideanStd()}); else if (metric=="EU_MAX") segmenter->SetMetrics({new mitk::ClusteringMetricEuclideanMax()}); segmenter->Update(); std::vector< std::vector< long > > clusters = segmenter->GetOutFiberIndices(); if (clusters.size()>0) { vtkSmartPointer weights = vtkSmartPointer::New(); mitk::FiberBundle::Pointer result = mitk::FiberBundle::New(nullptr); std::vector< mitk::FiberBundle::Pointer > result_fibs; for (unsigned int cluster_index=0; cluster_indexGeneratePolyDataByIds(clusters.at(cluster_index), weights))); result = result->AddBundles(result_fibs); anchor_tractogram = anchor_tractogram->AddBundle(result); mitk::IOUtil::Save(result, out_root + "anchor_" + ist::GetFilenameName(ref_bundle_files.at(c))); fib = mitk::FiberBundle::New(fib->GeneratePolyDataByIds(clusters.back(), weights)); resampled_fib = mitk::FiberBundle::New(resampled_fib->GeneratePolyDataByIds(clusters.back(), weights)); } } catch(itk::ExceptionObject& excpt) { MITK_INFO << "Exception while processing " << ist::GetFilenameName(ref_bundle_files.at(c)); MITK_INFO << excpt.GetDescription(); } catch(std::exception& excpt) { MITK_INFO << "Exception while processing " << ist::GetFilenameName(ref_bundle_files.at(c)); MITK_INFO << excpt.what(); } // std::cout.rdbuf (old); // <-- restore if (fib->GetNumFibers()==0) break; ++c; } MITK_INFO << "Streamlines in anchor tractogram: " << anchor_tractogram->GetNumFibers(); mitk::IOUtil::Save(anchor_tractogram, out_root + "anchor_tractogram.trk"); MITK_INFO << "Streamlines remaining in candidate tractogram: " << fib->GetNumFibers(); mitk::IOUtil::Save(fib, out_root + "candidate_tractogram.trk"); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkDiffusionImagingRegistration.dox b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkHeadMotionCorrection.dox similarity index 76% rename from Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkDiffusionImagingRegistration.dox rename to Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkHeadMotionCorrection.dox index 90e4f6f551..0b98310a5f 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkDiffusionImagingRegistration.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkHeadMotionCorrection.dox @@ -1,5 +1,5 @@ /** -\page org_mitk_views_diffusionregistrationview Head-Motion Correction +\page org_mitk_views_headmotioncorrectionview Head-Motion Correction This view allows head-motion and eddy-current correction by affinely registering all volumes to the first unweighted volume of the complete diffusion-weighted image. The individual gradient directions are roated accordingly. */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkSimpleRegistration.dox b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkSimpleRegistration.dox new file mode 100644 index 0000000000..50f5be7cdd --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkSimpleRegistration.dox @@ -0,0 +1,8 @@ +/** +\page org_mitk_views_simpleregistrationview Registration + +This view enables the simple rigid or affine registration of two images. The registered image will be displayed in transparent blue color overlayed over the fixed image. To regain normal coloring, right-click on the data node and adjust the corresponding settings. + +It is also possible to transform a tractogram with a registration object obtained from a previous registration of two images. + +*/ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkSimpleRigidRegistration.dox b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkSimpleRigidRegistration.dox deleted file mode 100644 index d98878e5a2..0000000000 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/documentation/UserManual/QmitkSimpleRigidRegistration.dox +++ /dev/null @@ -1,5 +0,0 @@ -/** -\page org_mitk_views_simplerigidregistrationview Rigid Registration - -This view enables the simple rigid registration of two images. The registered image will be displayed in transparent blue color overlayed over the fixed image. To regain normal coloring, right-click on the data node and adjust the corresponding settings. -*/ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/files.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/files.cmake index b20be9d47b..88ebeda4b0 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/files.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/files.cmake @@ -1,46 +1,46 @@ set(SRC_CPP_FILES ) set(INTERNAL_CPP_FILES mitkPluginActivator.cpp - QmitkDiffusionRegistrationView.cpp - QmitkSimpleRigidRegistrationView.cpp + QmitkHeadMotionCorrectionView.cpp + QmitkSimpleRegistrationView.cpp QmitkDwiRegistrationPerspective.cpp ) set(UI_FILES - src/internal/QmitkDiffusionRegistrationViewControls.ui - src/internal/QmitkSimpleRigidRegistrationViewControls.ui + src/internal/QmitkHeadMotionCorrectionViewControls.ui + src/internal/QmitkSimpleRegistrationViewControls.ui ) set(MOC_H_FILES src/internal/mitkPluginActivator.h - src/internal/QmitkDiffusionRegistrationView.h - src/internal/QmitkSimpleRigidRegistrationView.h + src/internal/QmitkHeadMotionCorrectionView.h + src/internal/QmitkSimpleRegistrationView.h src/internal/QmitkDwiRegistrationPerspective.h ) set(CACHED_RESOURCE_FILES plugin.xml resources/diffusionregistration.png ) set(QRC_FILES ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/plugin.xml b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/plugin.xml index 3a030cdea7..c66c507de8 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/plugin.xml +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/plugin.xml @@ -1,52 +1,52 @@ - - + - - + This perspective contains views for rigid image registration and head motion correction. - - - - - - - - + + + + + + + + - + diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDwiRegistrationPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDwiRegistrationPerspective.cpp index a5762d2bd2..ed5f3f8a56 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDwiRegistrationPerspective.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDwiRegistrationPerspective.cpp @@ -1,49 +1,49 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkDwiRegistrationPerspective.h" #include "berryIViewLayout.h" void QmitkDwiRegistrationPerspective::CreateInitialLayout(berry::IPageLayout::Pointer layout) { ///////////////////////////////////////////////////// // all di-app perspectives should have the following: ///////////////////////////////////////////////////// QString editorArea = layout->GetEditorArea(); layout->AddStandaloneViewPlaceholder("org.mitk.views.viewnavigatorview", berry::IPageLayout::LEFT, 0.3f, editorArea, false); layout->AddStandaloneView("org.mitk.views.datamanager", false, berry::IPageLayout::LEFT, 0.3f, editorArea); layout->AddStandaloneView("org.mitk.views.controlvisualizationpropertiesview", false, berry::IPageLayout::BOTTOM, .15f, "org.mitk.views.datamanager"); berry::IFolderLayout::Pointer left = layout->CreateFolder("org.mbi.diffusionimaginginternal.leftcontrols", berry::IPageLayout::BOTTOM, 0.15f, "org.mitk.views.controlvisualizationpropertiesview"); layout->AddStandaloneViewPlaceholder("org.mitk.views.imagenavigator", berry::IPageLayout::BOTTOM, .7f, "org.mbi.diffusionimaginginternal.leftcontrols", false); ///////////////////////////////////////////// // here goes the perspective specific stuff ///////////////////////////////////////////// - left->AddView("org.mitk.views.simplerigidregistrationview"); - left->AddView("org.mitk.views.diffusionregistrationview"); + left->AddView("org.mitk.views.simpleregistrationview"); + left->AddView("org.mitk.views.headmotioncorrectionview"); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.cpp similarity index 81% rename from Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationView.cpp rename to Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.cpp index e004e5dd4a..322f900ba4 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.cpp @@ -1,124 +1,124 @@ /*=================================================================== 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. ===================================================================*/ //misc #define _USE_MATH_DEFINES #include // Blueberry #include #include // Qmitk -#include "QmitkDiffusionRegistrationView.h" +#include "QmitkHeadMotionCorrectionView.h" // MITK #include #include // Qt #include #include #include #include #include #include #define _USE_MATH_DEFINES #include -const std::string QmitkDiffusionRegistrationView::VIEW_ID = "org.mitk.views.diffusionregistrationview"; +const std::string QmitkHeadMotionCorrectionView::VIEW_ID = "org.mitk.views.headmotioncorrectionview"; -QmitkDiffusionRegistrationView::QmitkDiffusionRegistrationView() +QmitkHeadMotionCorrectionView::QmitkHeadMotionCorrectionView() : QmitkAbstractView() , m_Controls( 0 ) , m_DiffusionImage( nullptr ) { } // Destructor -QmitkDiffusionRegistrationView::~QmitkDiffusionRegistrationView() +QmitkHeadMotionCorrectionView::~QmitkHeadMotionCorrectionView() { } -void QmitkDiffusionRegistrationView::CreateQtPartControl( QWidget *parent ) +void QmitkHeadMotionCorrectionView::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::QmitkDiffusionRegistrationViewControls; + m_Controls = new Ui::QmitkHeadMotionCorrectionViewControls; m_Controls->setupUi( parent ); connect( m_Controls->m_ImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGUI()) ); connect( m_Controls->m_RegistrationStartButton, SIGNAL(clicked()), this, SLOT(StartRegistration()) ); this->m_Parent = parent; m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isImagePredicate = mitk::TNodePredicateDataType::New(); m_Controls->m_ImageBox->SetPredicate(isImagePredicate); UpdateGUI(); } } -void QmitkDiffusionRegistrationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& ) +void QmitkHeadMotionCorrectionView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& ) { } -void QmitkDiffusionRegistrationView::UpdateGUI() +void QmitkHeadMotionCorrectionView::UpdateGUI() { if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull()) { m_Controls->m_RegistrationStartButton->setEnabled(true); m_Controls->m_RegistrationStartButton->setToolTip("Start Registration"); } else { m_Controls->m_RegistrationStartButton->setEnabled(false); m_Controls->m_RegistrationStartButton->setToolTip("No Diffusion image selected."); } } -void QmitkDiffusionRegistrationView::SetFocus() +void QmitkHeadMotionCorrectionView::SetFocus() { UpdateGUI(); m_Controls->m_RegistrationStartButton->setFocus(); } -void QmitkDiffusionRegistrationView::StartRegistration() +void QmitkHeadMotionCorrectionView::StartRegistration() { mitk::DataNode::Pointer node = m_Controls->m_ImageBox->GetSelectedNode(); mitk::Image::Pointer inImage = dynamic_cast(node->GetData()); if (!mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(inImage)) { QMessageBox::warning(nullptr, "Warning", "Input node is not a diffusion-weighted image!"); return; } DWIHeadMotionCorrectionFilterType::Pointer registerer = DWIHeadMotionCorrectionFilterType::New(); registerer->SetInput(inImage); registerer->Update(); mitk::Image::Pointer image = registerer->GetCorrectedImage(); mitk::DataNode::Pointer corrected_node = mitk::DataNode::New(); corrected_node->SetData( image ); QString name(node->GetName().c_str()); name += "_Corrected"; corrected_node->SetName(name.toStdString()); GetDataStorage()->Add(corrected_node, node); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.h similarity index 88% rename from Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationView.h rename to Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.h index 999723a38d..d849893c05 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.h @@ -1,78 +1,78 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include -#include "ui_QmitkDiffusionRegistrationViewControls.h" +#include "ui_QmitkHeadMotionCorrectionViewControls.h" #include #include #include #include typedef short DiffusionPixelType; /*! \brief View for diffusion image registration / head motion correction */ -class QmitkDiffusionRegistrationView : public QmitkAbstractView +class QmitkHeadMotionCorrectionView : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; - QmitkDiffusionRegistrationView(); - virtual ~QmitkDiffusionRegistrationView(); + QmitkHeadMotionCorrectionView(); + virtual ~QmitkHeadMotionCorrectionView(); virtual void CreateQtPartControl(QWidget *parent) override; void SetFocus() override; typedef mitk::DWIHeadMotionCorrectionFilter DWIHeadMotionCorrectionFilterType; protected slots: void StartRegistration(); void UpdateGUI(); ///< update button activity etc. dpending on current datamanager selection protected: /// \brief called by QmitkAbstractView when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override; - Ui::QmitkDiffusionRegistrationViewControls* m_Controls; + Ui::QmitkHeadMotionCorrectionViewControls* m_Controls; mitk::Image::Pointer m_DiffusionImage; std::vector< mitk::DataNode::Pointer > m_SelectedDiffusionNodes; private: void UpdateRegistrationStatus(); ///< update textual status display of the Registration process // the Qt parent of our GUI (NOT of this object) QWidget* m_Parent; }; diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionViewControls.ui similarity index 92% rename from Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationViewControls.ui rename to Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionViewControls.ui index f051e3f25c..a86cc9f1e0 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkDiffusionRegistrationViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionViewControls.ui @@ -1,88 +1,88 @@ - QmitkDiffusionRegistrationViewControls - + QmitkHeadMotionCorrectionViewControls + 0 0 435 744 Form false Start DWI registration/Head Motion Correction Start Head Motion Correction Qt::Vertical 20 40 QFrame::NoFrame QFrame::Raised 0 0 0 0 Input Image: QmitkDataStorageComboBox QComboBox -
QmitkDataStorageComboBox.h
+
QmitkDataStorageComboBox.h
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.cpp similarity index 54% rename from Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationView.cpp rename to Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.cpp index 2954bc3839..c13e1f5199 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.cpp @@ -1,275 +1,388 @@ /*=================================================================== 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. ===================================================================*/ //misc #define _USE_MATH_DEFINES #include // Blueberry #include #include // Qmitk -#include "QmitkSimpleRigidRegistrationView.h" +#include "QmitkSimpleRegistrationView.h" // MITK #include #include #include #include #include #include +#include +#include +#include +#include +#include // Qt #include #define _USE_MATH_DEFINES #include -const std::string QmitkSimpleRigidRegistrationView::VIEW_ID = "org.mitk.views.simplerigidregistrationview"; +const std::string QmitkSimpleRegistrationView::VIEW_ID = "org.mitk.views.simpleregistrationview"; -QmitkSimpleRigidRegistrationView::QmitkSimpleRigidRegistrationView() +QmitkSimpleRegistrationView::QmitkSimpleRegistrationView() : QmitkAbstractView() , m_Controls( 0 ) + , m_RegistrationType(0) { } // Destructor -QmitkSimpleRigidRegistrationView::~QmitkSimpleRigidRegistrationView() +QmitkSimpleRegistrationView::~QmitkSimpleRegistrationView() { } -void QmitkSimpleRigidRegistrationView::StartRegistration() +void QmitkSimpleRegistrationView::StartRegistration() { - typedef itk::Image< float, 3 > ItkFloatImageType; - mitk::MultiModalRigidDefaultRegistrationAlgorithm< ItkFloatImageType >::Pointer algo = mitk::MultiModalRigidDefaultRegistrationAlgorithm< ItkFloatImageType >::New(); + QmitkRegistrationJob* pJob; + + if (m_Controls->m_RegBox->currentIndex()==0) + { + mitk::MultiModalRigidDefaultRegistrationAlgorithm< ItkFloatImageType >::Pointer algo = mitk::MultiModalRigidDefaultRegistrationAlgorithm< ItkFloatImageType >::New(); + pJob = new QmitkRegistrationJob(algo); + m_RegistrationType = 0; + } + else + { + mitk::MultiModalAffineDefaultRegistrationAlgorithm< ItkFloatImageType >::Pointer algo = mitk::MultiModalAffineDefaultRegistrationAlgorithm< ItkFloatImageType >::New(); + pJob = new QmitkRegistrationJob(algo); + m_RegistrationType = 1; + } - QmitkRegistrationJob* pJob = new QmitkRegistrationJob(algo); pJob->setAutoDelete(true); m_MovingImageNode = m_Controls->m_MovingImageBox->GetSelectedNode(); mitk::Image::Pointer movingImage = dynamic_cast(m_MovingImageNode->GetData()); if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(movingImage)) { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(movingImage, itkVectorImagePointer); itk::ExtractDwiChannelFilter< short >::Pointer filter = itk::ExtractDwiChannelFilter< short >::New(); filter->SetInput( itkVectorImagePointer); filter->SetChannelIndex(m_Controls->m_MovingChannelBox->value()); filter->Update(); mitk::Image::Pointer newImage = mitk::Image::New(); newImage->InitializeByItk( filter->GetOutput() ); newImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() ); pJob->m_spMovingData = newImage; } else pJob->m_spMovingData = movingImage; mitk::Image::Pointer fixedImage = dynamic_cast(m_Controls->m_FixedImageBox->GetSelectedNode()->GetData()); if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(fixedImage)) { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(fixedImage, itkVectorImagePointer); itk::ExtractDwiChannelFilter< short >::Pointer filter = itk::ExtractDwiChannelFilter< short >::New(); filter->SetInput( itkVectorImagePointer); filter->SetChannelIndex(m_Controls->m_MovingChannelBox->value()); filter->Update(); mitk::Image::Pointer newImage = mitk::Image::New(); newImage->InitializeByItk( filter->GetOutput() ); newImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() ); pJob->m_spTargetData = newImage; } else pJob->m_spTargetData = fixedImage; pJob->m_TargetDataUID = mitk::EnsureUID(m_Controls->m_FixedImageBox->GetSelectedNode()->GetData()); pJob->m_MovingDataUID = mitk::EnsureUID(m_Controls->m_MovingImageBox->GetSelectedNode()->GetData()); connect(pJob, SIGNAL(RegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer, const QmitkRegistrationJob*)), this, SLOT(OnRegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer, const QmitkRegistrationJob*)), Qt::BlockingQueuedConnection); -// connect(pJob, SIGNAL(AlgorithmInfo(QString)), this, SLOT(OnAlgorithmInfo(QString))); -// connect(pJob, SIGNAL(AlgorithmStatusChanged(QString)), this, SLOT(OnAlgorithmStatusChanged(QString))); -// connect(pJob, SIGNAL(AlgorithmIterated(QString, bool, unsigned long)), this, SLOT(OnAlgorithmIterated(QString, bool, unsigned long))); -// connect(pJob, SIGNAL(LevelChanged(QString, bool, unsigned long)), this, SLOT(OnLevelChanged(QString, bool, unsigned long))); - QThreadPool* threadPool = QThreadPool::globalInstance(); threadPool->start(pJob); m_Controls->m_RegistrationStartButton->setEnabled(false); m_Controls->m_RegistrationStartButton->setText("Registration in progress ..."); } -void QmitkSimpleRigidRegistrationView::OnRegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer spResultRegistration, const QmitkRegistrationJob* ) +void QmitkSimpleRegistrationView::OnRegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer spResultRegistration, const QmitkRegistrationJob* job) { mitk::Image::Pointer movingImage = dynamic_cast(m_MovingImageNode->GetData()); - mitk::Image::Pointer image = mitk::ImageMappingHelper::refineGeometry(movingImage, spResultRegistration, true); + mitk::Image::Pointer image; + + if (m_RegistrationType==0) + { + image = mitk::ImageMappingHelper::refineGeometry(movingImage, spResultRegistration, true); + } + else + { + if (!mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(movingImage)) + { + image = mitk::ImageMappingHelper::map(movingImage, spResultRegistration, false, 0, job->m_spTargetData->GetGeometry(), false, 0, mitk::ImageMappingInterpolator::BSpline_3); + } + else + { + typedef itk::ComposeImageFilter < ITKDiffusionVolumeType > ComposeFilterType; + ComposeFilterType::Pointer composer = ComposeFilterType::New(); + + ItkDwiType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::GetItkVectorImage(movingImage); + for (unsigned int i=0; iGetVectorLength(); ++i) + { + itk::ExtractDwiChannelFilter< short >::Pointer filter = itk::ExtractDwiChannelFilter< short >::New(); + filter->SetInput( itkVectorImagePointer); + filter->SetChannelIndex(i); + filter->Update(); + + mitk::Image::Pointer gradientVolume = mitk::Image::New(); + gradientVolume->InitializeByItk( filter->GetOutput() ); + gradientVolume->SetImportChannel( filter->GetOutput()->GetBufferPointer() ); + + mitk::Image::Pointer registered_mitk_image = mitk::ImageMappingHelper::map(gradientVolume, spResultRegistration, false, 0, job->m_spTargetData->GetGeometry(), false, 0, mitk::ImageMappingInterpolator::BSpline_3); + + ITKDiffusionVolumeType::Pointer registered_itk_image = ITKDiffusionVolumeType::New(); + mitk::CastToItkImage(registered_mitk_image, registered_itk_image); + composer->SetInput(i, registered_itk_image); + } + + composer->Update(); + + image = mitk::GrabItkImageMemory( composer->GetOutput() ); + mitk::DiffusionPropertyHelper::CopyProperties(movingImage, image, true); + } + } if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image)) { mitk::DiffusionPropertyHelper propertyHelper( image ); propertyHelper.InitializeImage(); } mitk::DataNode::Pointer resultNode = mitk::DataNode::New(); resultNode->SetData(image); if (m_MovingImageNode.IsNotNull()) { m_MovingImageNode->SetVisibility(false); QString name = m_MovingImageNode->GetName().c_str(); - resultNode->SetName((name+"_registered").toStdString().c_str()); + if (m_RegistrationType==0) + resultNode->SetName((name+"_registered (rigid)").toStdString().c_str()); + else + resultNode->SetName((name+"_registered (affine)").toStdString().c_str()); } else - resultNode->SetName("Registered"); + { + if (m_RegistrationType==0) + resultNode->SetName("Registered (rigid)"); + else + resultNode->SetName("Registered (affine)"); + } resultNode->SetOpacity(0.6); resultNode->SetColor(0.0, 0.0, 1.0); - GetDataStorage()->Add(resultNode); + if (m_Controls->m_RegOutputBox->isChecked()) + { + mitk::DataNode::Pointer registration_node = mitk::DataNode::New(); + registration_node->SetData(spResultRegistration); + if (m_RegistrationType==0) + registration_node->SetName("Registration Object (rigid)"); + else + registration_node->SetName("Registration Object (affine)"); + GetDataStorage()->Add(registration_node, resultNode); + } + this->GetRenderWindowPart()->RequestUpdate(); m_Controls->m_RegistrationStartButton->setEnabled(true); m_Controls->m_RegistrationStartButton->setText("Start Registration"); m_MovingImageNode = nullptr; + + TractoChanged(); } -void QmitkSimpleRigidRegistrationView::CreateQtPartControl( QWidget *parent ) +void QmitkSimpleRegistrationView::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::QmitkSimpleRigidRegistrationViewControls; + m_Controls = new Ui::QmitkSimpleRegistrationViewControls; m_Controls->setupUi( parent ); m_Controls->m_FixedImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_MovingImageBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isImagePredicate = mitk::TNodePredicateDataType::New(); m_Controls->m_FixedImageBox->SetPredicate(isImagePredicate); m_Controls->m_MovingImageBox->SetPredicate(isImagePredicate); + mitk::TNodePredicateDataType::Pointer isFib = mitk::TNodePredicateDataType::New(); + mitk::TNodePredicateDataType::Pointer isReg = mitk::TNodePredicateDataType::New(); + + m_Controls->m_TractoBox->SetDataStorage(this->GetDataStorage()); + m_Controls->m_RegObjectBox->SetDataStorage(this->GetDataStorage()); + m_Controls->m_TractoBox->SetPredicate(isFib); + m_Controls->m_RegObjectBox->SetPredicate(isReg); + connect( m_Controls->m_FixedImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(FixedImageChanged()) ); connect( m_Controls->m_MovingImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(MovingImageChanged()) ); + + connect( m_Controls->m_TractoBox, SIGNAL(currentIndexChanged(int)), this, SLOT(TractoChanged()) ); + connect( m_Controls->m_RegObjectBox, SIGNAL(currentIndexChanged(int)), this, SLOT(TractoChanged()) ); + connect( m_Controls->m_RegistrationStartButton, SIGNAL(clicked()), this, SLOT(StartRegistration()) ); + connect( m_Controls->m_TractoRegistrationStartButton, SIGNAL(clicked()), this, SLOT(StartTractoRegistration()) ); FixedImageChanged(); MovingImageChanged(); + TractoChanged(); } } -void QmitkSimpleRigidRegistrationView::FixedImageChanged() +void QmitkSimpleRegistrationView::StartTractoRegistration() +{ + mitk::FiberBundle::Pointer fib = dynamic_cast(m_Controls->m_TractoBox->GetSelectedNode()->GetData()); + mitk::MAPRegistrationWrapper::Pointer reg = dynamic_cast(m_Controls->m_RegObjectBox->GetSelectedNode()->GetData()); + + mitk::MITKRegistrationHelper::Affine3DTransformType::Pointer affine = mitk::MITKRegistrationHelper::getAffineMatrix(reg, false); + + mitk::FiberBundle::Pointer fib_copy = fib->GetDeepCopy(); + fib_copy->TransformFibers(affine); + + mitk::DataNode::Pointer registration_node = mitk::DataNode::New(); + registration_node->SetData(fib_copy); + QString name = m_Controls->m_TractoBox->GetSelectedNode()->GetName().c_str(); + registration_node->SetName((name+"_registered").toStdString().c_str()); + GetDataStorage()->Add(registration_node, m_Controls->m_TractoBox->GetSelectedNode()); +} + +void QmitkSimpleRegistrationView::TractoChanged() +{ + if (m_Controls->m_RegObjectBox->GetSelectedNode().IsNotNull() && m_Controls->m_TractoBox->GetSelectedNode().IsNotNull()) + m_Controls->m_TractoRegistrationStartButton->setEnabled(true); + else + m_Controls->m_TractoRegistrationStartButton->setEnabled(false); +} + +void QmitkSimpleRegistrationView::FixedImageChanged() { if (m_Controls->m_FixedImageBox->GetSelectedNode().IsNotNull()) { mitk::Image::Pointer image = dynamic_cast(m_Controls->m_FixedImageBox->GetSelectedNode()->GetData()); int channels = image->GetNumberOfChannels(); int dims = image->GetDimension(); int fourth_dim_size = image->GetTimeSteps(); bool isdiff = mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image); if (dims==4 || channels>1) { m_Controls->m_FixedChannelBox->setEnabled(false); m_Controls->m_RegistrationStartButton->setEnabled(false); } if (isdiff) { m_Controls->m_FixedChannelBox->setEnabled(true); if (fourth_dim_size>1) m_Controls->m_FixedChannelBox->setMaximum(fourth_dim_size-1); else if (isdiff) m_Controls->m_FixedChannelBox->setMaximum(mitk::DiffusionPropertyHelper::GetGradientContainer(image)->Size()-1); } else { m_Controls->m_FixedChannelBox->setEnabled(false); } m_Controls->m_RegistrationStartButton->setEnabled(true); } else { m_Controls->m_FixedChannelBox->setEnabled(false); m_Controls->m_RegistrationStartButton->setEnabled(false); } } -void QmitkSimpleRigidRegistrationView::MovingImageChanged() +void QmitkSimpleRegistrationView::MovingImageChanged() { if (m_Controls->m_MovingImageBox->GetSelectedNode().IsNotNull()) { mitk::Image::Pointer image = dynamic_cast(m_Controls->m_MovingImageBox->GetSelectedNode()->GetData()); int channels = image->GetNumberOfChannels(); int dims = image->GetDimension(); int fourth_dim_size = image->GetTimeSteps(); bool isdiff = mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image); if (dims==4 || channels>1) { m_Controls->m_MovingChannelBox->setEnabled(false); m_Controls->m_RegistrationStartButton->setEnabled(false); } if (isdiff) { m_Controls->m_MovingChannelBox->setEnabled(true); if (fourth_dim_size>1) m_Controls->m_MovingChannelBox->setMaximum(fourth_dim_size-1); else if (isdiff) m_Controls->m_MovingChannelBox->setMaximum(mitk::DiffusionPropertyHelper::GetGradientContainer(image)->Size()-1); } else { m_Controls->m_MovingChannelBox->setEnabled(false); } m_Controls->m_RegistrationStartButton->setEnabled(true); } else { m_Controls->m_MovingChannelBox->setEnabled(false); m_Controls->m_RegistrationStartButton->setEnabled(false); } } -void QmitkSimpleRigidRegistrationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& ) +void QmitkSimpleRegistrationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& ) { FixedImageChanged(); MovingImageChanged(); + TractoChanged(); } -void QmitkSimpleRigidRegistrationView::SetFocus() +void QmitkSimpleRegistrationView::SetFocus() { m_Controls->m_RegistrationStartButton->setFocus(); FixedImageChanged(); MovingImageChanged(); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.h similarity index 78% rename from Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationView.h rename to Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.h index 23f278e3f4..777508b956 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.h @@ -1,71 +1,75 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include -#include "ui_QmitkSimpleRigidRegistrationViewControls.h" +#include "ui_QmitkSimpleRegistrationViewControls.h" #include #include -#include typedef short DiffusionPixelType; /*! \brief View for diffusion image registration / head motion correction */ // Forward Qt class declarations -class QmitkSimpleRigidRegistrationView : public QmitkAbstractView +class QmitkSimpleRegistrationView : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: + typedef itk::Image< float, 3 > ItkFloatImageType; + typedef itk::Image ITKDiffusionVolumeType; typedef itk::VectorImage< short, 3 > ItkDwiType; static const std::string VIEW_ID; - QmitkSimpleRigidRegistrationView(); - virtual ~QmitkSimpleRigidRegistrationView(); + QmitkSimpleRegistrationView(); + virtual ~QmitkSimpleRegistrationView(); virtual void CreateQtPartControl(QWidget *parent) override; void SetFocus() override; protected slots: void MovingImageChanged(); void FixedImageChanged(); + void TractoChanged(); void StartRegistration(); + void StartTractoRegistration(); void OnRegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer spResultRegistration, const QmitkRegistrationJob* pRegJob); protected: /// \brief called by QmitkAbstractView when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override; - Ui::QmitkSimpleRigidRegistrationViewControls* m_Controls; + Ui::QmitkSimpleRegistrationViewControls* m_Controls; mitk::DataNode::Pointer m_MovingImageNode; + int m_RegistrationType; private: }; diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationViewControls.ui new file mode 100644 index 0000000000..67cb63db27 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationViewControls.ui @@ -0,0 +1,231 @@ + + + QmitkSimpleRegistrationViewControls + + + + 0 + 0 + 435 + 744 + + + + Form + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + Moving Image: + + + + + + + + + + false + + + Select dMRI volume used to calculate transformation. + + + + + + + false + + + Select dMRI volume used to calculate transformation. + + + + + + + Fixed Image: + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + Rigid + + + + + Affine + + + + + + + + Registration Type: + + + + + + + + + + + + + + Output Registration Object: + + + + + + + + + + false + + + + + + Start Registration + + + + + + + Tractography Registration + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Registration Object: + + + + + + + + + + Tractogram: + + + + + + + + + + + + + false + + + + + + Start Tractography Registration + + + + + + + + QmitkDataStorageComboBox + QComboBox +
QmitkDataStorageComboBox.h
+
+
+ + +
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationViewControls.ui deleted file mode 100644 index 38a25a4afe..0000000000 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRigidRegistrationViewControls.ui +++ /dev/null @@ -1,118 +0,0 @@ - - - QmitkSimpleRigidRegistrationViewControls - - - - 0 - 0 - 435 - 744 - - - - Form - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - Moving Image: - - - - - - - Fixed Image: - - - - - - - - - - false - - - Select dMRI volume used to calculate transformation. - - - - - - - false - - - Select dMRI volume used to calculate transformation. - - - - - - - - - - false - - - - - - Start Registration - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - QmitkDataStorageComboBox - QComboBox -
QmitkDataStorageComboBox.h
-
-
- - -
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.cpp index 581c7cf5d6..ee12c7bdca 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.cpp @@ -1,43 +1,43 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPluginActivator.h" -#include "src/internal/QmitkDiffusionRegistrationView.h" -#include "src/internal/QmitkSimpleRigidRegistrationView.h" +#include "src/internal/QmitkHeadMotionCorrectionView.h" +#include "src/internal/QmitkSimpleRegistrationView.h" #include "src/internal/QmitkDwiRegistrationPerspective.h" ctkPluginContext* mitk::PluginActivator::m_Context = nullptr; ctkPluginContext* mitk::PluginActivator::GetContext() { return m_Context; } void mitk::PluginActivator::start(ctkPluginContext* context) { - BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionRegistrationView, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkSimpleRigidRegistrationView, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkHeadMotionCorrectionView, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkSimpleRegistrationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDwiRegistrationPerspective, context) m_Context = context; } void mitk::PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) m_Context = nullptr; } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingPortalPage.dox b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingPortalPage.dox index 41cb380913..d2052b2ff2 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingPortalPage.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingPortalPage.dox @@ -1,48 +1,48 @@ /** \page org_mitk_gui_qt_diffusionimaging MITK Diffusion \tableofcontents MITK Diffusion offers a selection of image analysis methods for dMRI processing. It encompasses the research of the Division of Medical Image Computing of the German Cancer Research Center (DKFZ). \section org_mitk_gui_qt_diffusionimagingComponents Components MITK Diffusion consists of multiple components with their own documentation: \subsection sub1 Data formats, import and export \li \subpage QmitkDiffusionImagingDataImportPage \subsection sub2 Preprocessing and Reconstruction \li \subpage org_mitk_views_diffusionpreprocessing -\li \subpage org_mitk_views_simplerigidregistrationview -\li \subpage org_mitk_views_diffusionregistrationview +\li \subpage org_mitk_views_simpleregistrationview +\li \subpage org_mitk_views_headmotioncorrectionview \li \subpage org_mitk_views_denoisingview \li \subpage org_mitk_views_tensorreconstruction \li \subpage org_mitk_views_qballreconstruction \subsection sub3 Visualization and Quantification \li \subpage org_mitk_views_controlvisualizationpropertiesview \li \subpage org_mitk_views_odfdetails \li \subpage org_mitk_views_odfmaximaextraction \li \subpage org_mitk_views_partialvolumeanalysisview \li \subpage org_mitk_views_diffusionquantification \li \subpage org_mitk_views_ivim \subsection sub4 Fiber Tractography \li \subpage org_mitk_views_streamlinetracking \li \subpage org_mitk_views_gibbstracking \li \subpage org_mitk_views_mlbtview \li \subpage org_mitk_views_fiberprocessing \li \subpage org_mitk_views_fiberquantification \li \subpage org_mitk_views_fiberfit \li \subpage org_mitk_views_fiberclustering \subsection sub5 Fiberfox dMRI Simulation \li \subpage org_mitk_views_fiberfoxview \li \subpage org_mitk_views_fieldmapgenerator \subsection sub6 TBSS and Connectomics \li \subpage org_mitk_views_tractbasedspatialstatistics \li \subpage org_mitk_diffusionimagingapp_perspectives_connectomics */