diff --git a/Applications/Diffusion/CMakeLists.txt b/Applications/Diffusion/CMakeLists.txt index 5952f3fe15..feeb951778 100644 --- a/Applications/Diffusion/CMakeLists.txt +++ b/Applications/Diffusion/CMakeLists.txt @@ -1,105 +1,109 @@ -if(MITK_USE_Python) - 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.datamanager org.mitk.gui.qt.measurementtoolbox org.mitk.gui.qt.segmentation org.mitk.gui_qt.multilabelsegmentation org.mitk.gui.qt.python 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.registration org.mitk.gui.qt.diffusionimaging.python org.mitk.gui.qt.diffusionimaging.denoising org.mitk.gui.qt.diffusionimaging.partialvolume org.mitk.gui.qt.matchpoint.algorithm.browser org.mitk.gui.qt.matchpoint.algorithm.control org.mitk.gui.qt.matchpoint.mapper 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 ) +if(NOT MITK_USE_Python) + list(REMOVE_ITEM _plugins org.mitk.gui.qt.diffusionimaging.python) + list(REMOVE_ITEM _plugins org.mitk.gui.qt.python) +endif() + + + # 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() -endif() # MITK_USE_PYTHON diff --git a/Applications/Diffusion/target_libraries.cmake b/Applications/Diffusion/target_libraries.cmake index 80346af347..0b880357cb 100644 --- a/Applications/Diffusion/target_libraries.cmake +++ b/Applications/Diffusion/target_libraries.cmake @@ -1,37 +1,42 @@ # A list of plug-in targets which should be automatically enabled # (or be available in external projects) for this application set(target_libraries org_blueberry_ui_qt org_blueberry_ui_qt_help org_mitk_planarfigure org_mitk_gui_qt_diffusionimagingapp org_mitk_gui_qt_ext org_mitk_gui_qt_datamanager org_mitk_gui_qt_segmentation org_mitk_gui_qt_multilabelsegmentation org_mitk_gui_qt_python 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_registration org_mitk_gui_qt_diffusionimaging_python org_mitk_gui_qt_diffusionimaging_denoising org_mitk_gui_qt_diffusionimaging_partialvolume org_mitk_gui_qt_matchpoint_algorithm_browser org_mitk_gui_qt_matchpoint_algorithm_control org_mitk_gui_qt_matchpoint_mapper org_mitk_gui_qt_imagenavigator org_mitk_gui_qt_moviemaker org_mitk_gui_qt_measurementtoolbox org_mitk_gui_qt_basicimageprocessing org_mitk_gui_qt_viewnavigator ) + +if(NOT MITK_USE_Python) + list(REMOVE_ITEM target_libraries org_mitk_gui_qt_diffusionimaging_python) + list(REMOVE_ITEM target_libraries org_mitk_gui_qt_python) +endif() diff --git a/CMake/BuildConfigurations/DiffusionRelease.cmake b/CMake/BuildConfigurations/DiffusionRelease.cmake index 57d55104c6..7de513dd9a 100644 --- a/CMake/BuildConfigurations/DiffusionRelease.cmake +++ b/CMake/BuildConfigurations/DiffusionRelease.cmake @@ -1,42 +1,46 @@ message(STATUS "Configuring MITK Diffusion Release Build") # Enable non-optional external dependencies set(MITK_USE_Vigra ON CACHE BOOL "MITK Use Vigra Library" FORCE) set(MITK_USE_HDF5 ON CACHE BOOL "MITK Use HDF5 Library" FORCE) set(MITK_USE_MatchPoint ON CACHE BOOL "" FORCE) set(MITK_USE_DCMTK ON CACHE BOOL "" FORCE) set(MITK_USE_DCMQI ON CACHE BOOL "" FORCE) set(MITK_USE_OpenMP ON CACHE BOOL "" FORCE) -set(MITK_USE_Python ON CACHE BOOL "" FORCE) +if(UNIX AND NOT APPLE) + set(MITK_USE_Python ON CACHE BOOL "" FORCE) +else() + set(MITK_USE_Python OFF CACHE BOOL "" FORCE) +endif() set(MITK_USE_BetData ON CACHE BOOL "" FORCE) # Disable all apps but MITK Diffusion set(MITK_BUILD_ALL_APPS OFF CACHE BOOL "Build all MITK applications" FORCE) set(MITK_BUILD_APP_CoreApp OFF CACHE BOOL "Build the MITK CoreApp" FORCE) set(MITK_BUILD_APP_Workbench OFF CACHE BOOL "Build the MITK Workbench" FORCE) set(MITK_BUILD_APP_Diffusion ON CACHE BOOL "Build MITK Diffusion" FORCE) # Activate Diffusion Mini Apps set(BUILD_DiffusionFiberProcessingCmdApps ON CACHE BOOL "Build commandline tools for diffusion fiber processing" FORCE) set(BUILD_DiffusionFiberfoxCmdApps ON CACHE BOOL "Build commandline tools for diffusion data simulation (Fiberfox)" FORCE) set(BUILD_DiffusionMiscCmdApps ON CACHE BOOL "Build miscellaneous commandline tools for diffusion" FORCE) set(BUILD_DiffusionQuantificationCmdApps ON CACHE BOOL "Build commandline tools for diffusion quantification (IVIM, ADC, ...)" FORCE) set(BUILD_DiffusionTractographyCmdApps ON CACHE BOOL "Build commandline tools for diffusion fiber tractography" FORCE) set(BUILD_DiffusionTractographyEvaluationCmdApps ON CACHE BOOL "Build commandline tools for diffusion fiber tractography evaluation" FORCE) set(BUILD_DiffusionConnectomicsCmdApps OFF CACHE BOOL "Build commandline tools for diffusion connectomics" FORCE) set(BUILD_DiffusionPythonCmdApps ON CACHE BOOL "Build commandline tools for diffusion with python" FORCE) # Build neither all plugins nor examples set(MITK_BUILD_ALL_PLUGINS OFF CACHE BOOL "Build all MITK plugins" FORCE) set(MITK_BUILD_EXAMPLES OFF CACHE BOOL "Build the MITK examples" FORCE) set(BUILD_TESTING OFF CACHE BOOL "Build the MITK tests" FORCE) # Activate in-application help generation set(MITK_DOXYGEN_GENERATE_QCH_FILES ON CACHE BOOL "Use doxygen to generate Qt compressed help files for MITK docs" FORCE) set(BLUEBERRY_USE_QT_HELP ON CACHE BOOL "Enable support for integrating bundle documentation into Qt Help" FORCE) # Enable console window set(MITK_SHOW_CONSOLE_WINDOW ON CACHE BOOL "Use this to enable or disable the console window when starting MITK GUI Applications" FORCE) set(MITK_VTK_DEBUG_LEAKS OFF CACHE BOOL "" FORCE) set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE) diff --git a/Modules/DiffusionImaging/DiffusionCmdApps/Fiberfox/RandomFiberPhantom.cpp b/Modules/DiffusionImaging/DiffusionCmdApps/Fiberfox/RandomFiberPhantom.cpp index 31e0ce11ee..13b019f8b3 100755 --- a/Modules/DiffusionImaging/DiffusionCmdApps/Fiberfox/RandomFiberPhantom.cpp +++ b/Modules/DiffusionImaging/DiffusionCmdApps/Fiberfox/RandomFiberPhantom.cpp @@ -1,166 +1,172 @@ /*=================================================================== 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 "mitkCommandLineParser.h" #include #include #include #include #include int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Random Fiber Phantom"); parser.setCategory("Diffusion Simulation Tools"); parser.setContributor("MIC"); parser.setDescription("Create Random Fiber Configurations"); parser.setArgumentPrefix("--", "-"); parser.addArgument("num_bundles", "", mitkCommandLineParser::Int, "", "", 50); parser.addArgument("min_density", "", mitkCommandLineParser::Int, "", "", 50); parser.addArgument("max_density", "", mitkCommandLineParser::Int, "", "", 200); parser.addArgument("size_x", "", mitkCommandLineParser::Int, "", "", 250); parser.addArgument("size_y", "", mitkCommandLineParser::Int, "", "", 250); parser.addArgument("size_z", "", mitkCommandLineParser::Int, "", "", 250); parser.addArgument("min_stepsize", "", mitkCommandLineParser::Int, "", "", 15); parser.addArgument("max_stepsize", "", mitkCommandLineParser::Int, "", "", 30); parser.addArgument("min_curve", "", mitkCommandLineParser::Int, "", "", 5); parser.addArgument("max_curve", "", mitkCommandLineParser::Int, "", "", 45); parser.addArgument("min_radius", "", mitkCommandLineParser::Int, "", "", 5); parser.addArgument("max_radius", "", mitkCommandLineParser::Int, "", "", 25); parser.addArgument("min_twist", "", mitkCommandLineParser::Int, "", "", 15); parser.addArgument("max_twist", "", mitkCommandLineParser::Int, "", "", 30); parser.addArgument("compress", "", mitkCommandLineParser::Float, "Compress:", "Compress fiber using the given error threshold (in mm)", 0.1); parser.addArgument("", "o", mitkCommandLineParser::String, "Output folder:", "output folder", us::Any(), false); + parser.addArgument("fix_seed", "", mitkCommandLineParser::Bool, "Fix random seed:", "Produce same random values on each run.", us::Any()); std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; std::string out_folder = us::any_cast(parsedArgs["o"]); float compress=0.1; if (parsedArgs.count("compress")) compress = us::any_cast(parsedArgs["compress"]); int num_bundles=50; if (parsedArgs.count("num_bundles")) num_bundles = us::any_cast(parsedArgs["num_bundles"]); int min_density=50; if (parsedArgs.count("min_density")) min_density = us::any_cast(parsedArgs["min_density"]); int max_density=200; if (parsedArgs.count("max_density")) max_density = us::any_cast(parsedArgs["max_density"]); int size_x=250; if (parsedArgs.count("size_x")) size_x = us::any_cast(parsedArgs["size_x"]); int size_y=250; if (parsedArgs.count("size_y")) size_y = us::any_cast(parsedArgs["size_y"]); int size_z=250; if (parsedArgs.count("size_z")) size_z = us::any_cast(parsedArgs["size_z"]); int min_stepsize=15; if (parsedArgs.count("min_stepsize")) min_stepsize = us::any_cast(parsedArgs["min_stepsize"]); int max_stepsize=30; if (parsedArgs.count("max_stepsize")) max_stepsize = us::any_cast(parsedArgs["max_stepsize"]); int min_curve=5; if (parsedArgs.count("min_curve")) min_curve = us::any_cast(parsedArgs["min_curve"]); int max_curve=45; if (parsedArgs.count("max_curve")) max_curve = us::any_cast(parsedArgs["max_curve"]); int min_radius=5; if (parsedArgs.count("min_radius")) min_radius = us::any_cast(parsedArgs["min_radius"]); int max_radius=25; if (parsedArgs.count("max_radius")) max_radius = us::any_cast(parsedArgs["max_radius"]); int min_twist=15; if (parsedArgs.count("min_twist")) min_twist = us::any_cast(parsedArgs["min_twist"]); int max_twist=30; if (parsedArgs.count("max_twist")) max_twist = us::any_cast(parsedArgs["max_twist"]); + bool fix_seed = false; + if (parsedArgs.count("fix_seed")) + fix_seed = us::any_cast(parsedArgs["fix_seed"]); + try { itk::RandomPhantomFilter::Pointer filter = itk::RandomPhantomFilter::New(); - filter->SetNumTracts(num_bundles); - filter->setMinStreamlineDensity(min_density); - filter->setMaxStreamlineDensity(max_density); + filter->SetNumTracts(static_cast(num_bundles)); + filter->SetMinStreamlineDensity(static_cast(min_density)); + filter->SetMaxStreamlineDensity(static_cast(max_density)); mitk::Vector3D vol; vol[0] = size_x; vol[1] = size_y; vol[2] = size_z; - filter->setVolumeSize(vol); - filter->setStepSizeMin(min_stepsize); - filter->setStepSizeMax(max_stepsize); - filter->setCurvynessMin(min_curve); - filter->setCurvynessMax(max_curve); - filter->setStartRadiusMin(min_radius); - filter->setStartRadiusMax(max_radius); - filter->setMinTwist(min_twist); - filter->setMaxTwist(max_twist); + filter->SetVolumeSize(vol); + filter->SetStepSizeMin(static_cast(min_stepsize)); + filter->SetStepSizeMax(static_cast(max_stepsize)); + filter->SetCurvynessMin(static_cast(min_curve)); + filter->SetCurvynessMax(static_cast(max_curve)); + filter->SetStartRadiusMin(static_cast(min_radius)); + filter->SetStartRadiusMax(static_cast(max_radius)); + filter->SetMinTwist(static_cast(min_twist)); + filter->SetMaxTwist(static_cast(max_twist)); + filter->SetFixSeed(fix_seed); filter->Update(); auto fibs = filter->GetFiberBundles(); std::vector< mitk::DataNode::Pointer > fiber_nodes; int c = 1; for (auto fib : fibs) { if (compress>0) fib->Compress(compress); mitk::IOUtil::Save(fib, out_folder + "Bundle_" + boost::lexical_cast(c) + ".fib"); ++c; } } 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/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.cpp index be51ca4621..a96514f0ef 100644 --- a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.cpp @@ -1,239 +1,248 @@ /*=================================================================== 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 __itkibersFromPlanarFiguresFilter_cpp #define __itkibersFromPlanarFiguresFilter_cpp #include "itkFibersFromPlanarFiguresFilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace itk{ FibersFromPlanarFiguresFilter::FibersFromPlanarFiguresFilter() + : m_FixSeed(false) { } FibersFromPlanarFiguresFilter::~FibersFromPlanarFiguresFilter() { } void FibersFromPlanarFiguresFilter::GeneratePoints() { Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New(); - randGen->SetSeed((unsigned int)0); + if (m_FixSeed) + randGen->SetSeed(0); + else + randGen->SetSeed(); m_2DPoints.clear(); unsigned int count = 0; while (count < m_Parameters.m_Density) { mitk::Vector2D p; switch (m_Parameters.m_Distribution) { case FiberGenerationParameters::DISTRIBUTE_GAUSSIAN: p[0] = randGen->GetNormalVariate(0, m_Parameters.m_Variance); p[1] = randGen->GetNormalVariate(0, m_Parameters.m_Variance); break; default: p[0] = randGen->GetUniformVariate(-1, 1); p[1] = randGen->GetUniformVariate(-1, 1); } if (sqrt(p[0]*p[0]+p[1]*p[1]) <= 1) { m_2DPoints.push_back(p); count++; } } } +void FibersFromPlanarFiguresFilter::SetFixSeed(bool FixSeed) +{ + m_FixSeed = FixSeed; +} + void FibersFromPlanarFiguresFilter::GenerateData() { // check if enough fiducials are available for (unsigned int i=0; i m_VtkCellArray = vtkSmartPointer::New(); vtkSmartPointer m_VtkPoints = vtkSmartPointer::New(); std::vector< mitk::PlanarEllipse::Pointer > bundle = m_Parameters.m_Fiducials.at(i); std::vector< unsigned int > fliplist; if (i container = vtkSmartPointer::New(); mitk::PlanarEllipse::Pointer figure = bundle.at(0); mitk::Point2D p0 = figure->GetControlPoint(0); mitk::Point2D p1 = figure->GetControlPoint(1); mitk::Point2D p2 = figure->GetControlPoint(2); mitk::Point2D p3 = figure->GetControlPoint(3); double r1 = p0.EuclideanDistanceTo(p1); double r2 = p0.EuclideanDistanceTo(p2); mitk::Vector2D eDir = p1-p0; eDir.Normalize(); mitk::Vector2D tDir = p3-p0; tDir.Normalize(); // apply twist vnl_matrix_fixed tRot; tRot[0][0] = tDir[0]; tRot[1][1] = tRot[0][0]; tRot[1][0] = sin(acos(tRot[0][0])); tRot[0][1] = -tRot[1][0]; if (tDir[1]<0) tRot.inplace_transpose(); m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector()); // apply new ellipse shape vnl_vector_fixed< double, 2 > newP; newP[0] = m_2DPoints.at(j)[0]; newP[1] = m_2DPoints.at(j)[1]; double alpha = acos(eDir[0]); if (eDir[1]>0) alpha = 2*itk::Math::pi-alpha; vnl_matrix_fixed eRot; eRot[0][0] = cos(alpha); eRot[1][1] = eRot[0][0]; eRot[1][0] = sin(alpha); eRot[0][1] = -eRot[1][0]; newP = eRot*newP; newP[0] *= r1; newP[1] *= r2; newP = eRot.transpose()*newP; p0[0] += newP[0]; p0[1] += newP[1]; const mitk::PlaneGeometry* planeGeo = figure->GetPlaneGeometry(); mitk::Point3D w, wc; planeGeo->Map(p0, w); wc = figure->GetWorldControlPoint(0); vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer()); container->GetPointIds()->InsertNextId(id); vnl_vector_fixed< double, 3 > n = planeGeo->GetNormalVnl(); for (unsigned int k=1; kGetControlPoint(0); p1 = figure->GetControlPoint(1); p2 = figure->GetControlPoint(2); p3 = figure->GetControlPoint(3); r1 = p0.EuclideanDistanceTo(p1); r2 = p0.EuclideanDistanceTo(p2); eDir = p1-p0; eDir.Normalize(); mitk::Vector2D tDir2 = p3-p0; tDir2.Normalize(); mitk::Vector2D temp; temp.Fill(0); temp.SetVnlVector(tRot.transpose() * tDir2.GetVnlVector()); // apply twist tRot[0][0] = tDir[0]*tDir2[0] + tDir[1]*tDir2[1]; if (tRot[0][0]>1.0) tRot[0][0] = 1.0; tRot[1][1] = tRot[0][0]; tRot[1][0] = sin(acos(tRot[0][0])); tRot[0][1] = -tRot[1][0]; if (temp[1]<0) tRot.inplace_transpose(); m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector()); tDir = tDir2; // apply new ellipse shape newP[0] = m_2DPoints.at(j)[0]; newP[1] = m_2DPoints.at(j)[1]; // calculate normal mitk::PlaneGeometry* planeGeo = const_cast(figure->GetPlaneGeometry()); mitk::Vector3D perp = wc-planeGeo->ProjectPointOntoPlane(wc); perp.Normalize(); vnl_vector_fixed< double, 3 > n2 = planeGeo->GetNormalVnl(); wc = figure->GetWorldControlPoint(0); // is flip needed? if (dot_product(perp.GetVnlVector(),n2)>0 && dot_product(n,n2)<=0.00001) newP[0] *= -1; if (fliplist.at(k)>0) newP[0] *= -1; n = n2; alpha = acos(eDir[0]); if (eDir[1]>0) alpha = 2*itk::Math::pi-alpha; eRot[0][0] = cos(alpha); eRot[1][1] = eRot[0][0]; eRot[1][0] = sin(alpha); eRot[0][1] = -eRot[1][0]; newP = eRot*newP; newP[0] *= r1; newP[1] *= r2; newP = eRot.transpose()*newP; p0[0] += newP[0]; p0[1] += newP[1]; mitk::Point3D w; planeGeo->Map(p0, w); vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer()); container->GetPointIds()->InsertNextId(id); } m_VtkCellArray->InsertNextCell(container); } vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); fiberPolyData->SetPoints(m_VtkPoints); fiberPolyData->SetLines(m_VtkCellArray); mitk::FiberBundle::Pointer mitkFiberBundle = mitk::FiberBundle::New(fiberPolyData); mitkFiberBundle->ResampleSpline(m_Parameters.m_Sampling, m_Parameters.m_Tension, m_Parameters.m_Continuity, m_Parameters.m_Bias); m_FiberBundles.push_back(mitkFiberBundle); } } } #endif // __itkFibersFromPlanarFiguresFilter_cpp diff --git a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.h b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.h index 22693e1730..ea1445b073 100644 --- a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.h @@ -1,85 +1,88 @@ /*=================================================================== 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 itkFibersFromPlanarFiguresFilter_h #define itkFibersFromPlanarFiguresFilter_h // MITK #include #include #include // ITK #include // VTK #include #include #include #include #include namespace itk{ /** * \brief Generates artificial fibers distributed in and interpolated between the input planar figures. */ class FibersFromPlanarFiguresFilter : public ProcessObject { public: typedef FibersFromPlanarFiguresFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef mitk::FiberBundle::Pointer FiberType; typedef std::vector< mitk::FiberBundle::Pointer > FiberContainerType; itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkTypeMacro( FibersFromPlanarFiguresFilter, ProcessObject ) void Update() override{ this->GenerateData(); } // input void SetParameters( FiberGenerationParameters param ) ///< Simulation parameters. { m_Parameters = param; } // output FiberContainerType GetFiberBundles(){ return m_FiberBundles; } + void SetFixSeed(bool FixSeed); + protected: void GenerateData() override; FibersFromPlanarFiguresFilter(); ~FibersFromPlanarFiguresFilter() override; void GeneratePoints(); FiberContainerType m_FiberBundles; ///< container for the output fiber bundles std::vector< mitk::Vector2D > m_2DPoints; ///< container for the 2D fiber waypoints FiberGenerationParameters m_Parameters; + bool m_FixSeed; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkFibersFromPlanarFiguresFilter.cpp" #endif #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkRandomPhantomFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkRandomPhantomFilter.cpp index e774d4f4ba..66ea6ef4d3 100644 --- a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkRandomPhantomFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkRandomPhantomFilter.cpp @@ -1,450 +1,463 @@ /*=================================================================== 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 __itkRandomPhantomFilter_cpp //#define __itkRandomPhantomFilter_cpp #include "itkRandomPhantomFilter.h" #include #include #include namespace itk{ RandomPhantomFilter::RandomPhantomFilter() : m_NumTracts(1) , m_MinStreamlineDensity(25) , m_MaxStreamlineDensity(200) , m_StartRadiusMin(5) , m_StartRadiusMax(30) , m_CurvynessMin(10) , m_CurvynessMax(45) , m_StepSizeMin(15) , m_StepSizeMax(30) , m_MinTwist(10) , m_MaxTwist(30) + , m_FixSeed(false) { m_VolumeSize[0] = 500; m_VolumeSize[1] = 500; m_VolumeSize[2] = 500; } RandomPhantomFilter::~RandomPhantomFilter() { } void RandomPhantomFilter::TransformPlanarFigure(mitk::PlanarEllipse* pe, mitk::Vector3D translation, mitk::Vector3D rotation, double twistangle, double radius1, double radius2) { mitk::BaseGeometry* geom = pe->GetGeometry(); // translate geom->Translate(translation); // calculate rotation matrix double x = rotation[0]*itk::Math::pi/180; double y = rotation[1]*itk::Math::pi/180; double z = rotation[2]*itk::Math::pi/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); // adjust control points auto p0 = pe->GetControlPoint(0); auto p1 = pe->GetControlPoint(1); auto p2 = pe->GetControlPoint(2); auto p3 = pe->GetControlPoint(3); auto v1 = p1 - p0; auto v2 = p2 - p0; auto dot = std::cos(itk::Math::pi*twistangle/180.0); vnl_matrix_fixed tRot; tRot[0][0] = dot; tRot[1][1] = tRot[0][0]; tRot[1][0] = sin(acos(tRot[0][0])); tRot[0][1] = -tRot[1][0]; if (twistangle<0) tRot = tRot.transpose(); vnl_vector_fixed vt; vt[0]=1; vt[1]=0; vnl_vector_fixed v3 = tRot*vt; v1.Normalize(); v2.Normalize(); p1 = p0 + radius1; p2 = p0 + radius2; p3 = p0 + mitk::Vector2D(v3); pe->SetControlPoint(1, p1); pe->SetControlPoint(2, p2); pe->SetControlPoint(3, p3); pe->Modified(); } mitk::PlanarEllipse::Pointer RandomPhantomFilter::CreatePlanarFigure() { mitk::PlaneGeometry::Pointer pl = mitk::PlaneGeometry::New(); pl->SetIdentity(); // mitk::Point3D o; o.Fill(10.0); // pl->SetOrigin(o); mitk::PlanarEllipse::Pointer figure = mitk::PlanarEllipse::New(); figure->ResetNumberOfControlPoints(0); figure->SetPlaneGeometry(pl); mitk::Point2D p0; p0.Fill(0.0); mitk::Point2D p1; p1.Fill(0.0); p1[0] = 1; mitk::Point2D p2; p2.Fill(0.0); p2[1] = 1; figure->PlaceFigure(p0); figure->AddControlPoint(p0); figure->AddControlPoint(p1); figure->AddControlPoint(p2); figure->AddControlPoint(p2); figure->SetProperty("initiallyplaced", mitk::BoolProperty::New(true)); return figure; } void RandomPhantomFilter::SetNumTracts(unsigned int NumTracts) { m_NumTracts = NumTracts; } void RandomPhantomFilter::GetPfOnBoundingPlane(mitk::Vector3D& pos, mitk::Vector3D& rot) { Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New(); - randGen->SetSeed(); - int plane = randGen->GetIntegerVariate(5) + 1; + if (m_FixSeed) + randGen->SetSeed(13); + else + randGen->SetSeed(); + auto plane = randGen->GetIntegerVariate(5) + 1; MITK_INFO << "Plane: " << plane; switch(plane) { case 1: { pos[0] = randGen->GetUniformVariate(0, m_VolumeSize[0]); pos[1] = randGen->GetUniformVariate(0, m_VolumeSize[1]); pos[2] = 0; rot[0] = 0; rot[1] = 0; rot[2] = 0; break; } case 2: { pos[0] = 0; pos[1] = randGen->GetUniformVariate(0, m_VolumeSize[1]); pos[2] = randGen->GetUniformVariate(0, m_VolumeSize[2]); rot[0] = 0; rot[1] = 90; rot[2] = 0; break; } case 3: { pos[0] = randGen->GetUniformVariate(0, m_VolumeSize[0]); pos[1] = 0; pos[2] = randGen->GetUniformVariate(0, m_VolumeSize[2]); rot[0] = -90; rot[1] = 0; rot[2] = 0; break; } case 4: { pos[0] = randGen->GetUniformVariate(0, m_VolumeSize[0]); pos[1] = m_VolumeSize[1]; pos[2] = randGen->GetUniformVariate(0, m_VolumeSize[2]); rot[0] = 90; rot[1] = 0; rot[2] = 0; break; } case 5: { pos[0] = m_VolumeSize[0]; pos[1] = randGen->GetUniformVariate(0, m_VolumeSize[1]); pos[2] = randGen->GetUniformVariate(0, m_VolumeSize[2]); rot[0] = 0; rot[1] = -90; rot[2] = 0; break; } case 6: { pos[0] = randGen->GetUniformVariate(0, m_VolumeSize[0]); pos[1] = randGen->GetUniformVariate(0, m_VolumeSize[1]); pos[2] = m_VolumeSize[2]; rot[0] = 180; rot[1] = 0; rot[2] = 0; break; } } } bool RandomPhantomFilter::IsInVolume(mitk::Vector3D pos) { if (pos[0]>=0 && pos[0]<=m_VolumeSize[0] && pos[1]>=0 && pos[1]<=m_VolumeSize[1] && pos[2]>=0 && pos[2]<=m_VolumeSize[2]) return true; return false; } -void RandomPhantomFilter::setMinTwist(unsigned int MinTwist) +void RandomPhantomFilter::SetFixSeed(bool FixSeed) +{ + m_FixSeed = FixSeed; +} + +void RandomPhantomFilter::SetMinTwist(unsigned int MinTwist) { m_MinTwist = MinTwist; } -void RandomPhantomFilter::setMaxStreamlineDensity(unsigned int MaxStreamlineDensity) +void RandomPhantomFilter::SetMaxStreamlineDensity(unsigned int MaxStreamlineDensity) { m_MaxStreamlineDensity = MaxStreamlineDensity; } -void RandomPhantomFilter::setMinStreamlineDensity(unsigned int MinStreamlinDensity) +void RandomPhantomFilter::SetMinStreamlineDensity(unsigned int MinStreamlinDensity) { m_MinStreamlineDensity = MinStreamlinDensity; } -void RandomPhantomFilter::setMaxTwist(unsigned int MaxTwist) +void RandomPhantomFilter::SetMaxTwist(unsigned int MaxTwist) { m_MaxTwist = MaxTwist; } -void RandomPhantomFilter::setVolumeSize(const mitk::Vector3D &VolumeSize) +void RandomPhantomFilter::SetVolumeSize(const mitk::Vector3D &VolumeSize) { m_VolumeSize = VolumeSize; } -void RandomPhantomFilter::setStepSizeMax(unsigned int StepSizeMax) +void RandomPhantomFilter::SetStepSizeMax(unsigned int StepSizeMax) { m_StepSizeMax = StepSizeMax; } -void RandomPhantomFilter::setStepSizeMin(unsigned int StepSizeMin) +void RandomPhantomFilter::SetStepSizeMin(unsigned int StepSizeMin) { m_StepSizeMin = StepSizeMin; } -void RandomPhantomFilter::setCurvynessMax(unsigned int CurvynessMax) +void RandomPhantomFilter::SetCurvynessMax(unsigned int CurvynessMax) { m_CurvynessMax = CurvynessMax; } -void RandomPhantomFilter::setCurvynessMin(unsigned int CurvynessMin) +void RandomPhantomFilter::SetCurvynessMin(unsigned int CurvynessMin) { m_CurvynessMin = CurvynessMin; } -void RandomPhantomFilter::setStartRadiusMax(unsigned int StartRadiusMax) +void RandomPhantomFilter::SetStartRadiusMax(unsigned int StartRadiusMax) { m_StartRadiusMax = StartRadiusMax; } -void RandomPhantomFilter::setStartRadiusMin(unsigned int StartRadiusMin) +void RandomPhantomFilter::SetStartRadiusMin(unsigned int StartRadiusMin) { m_StartRadiusMin = StartRadiusMin; } void RandomPhantomFilter::GenerateData() { Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New(); - randGen->SetSeed(); + if (m_FixSeed) + randGen->SetSeed(42); + else + randGen->SetSeed(); for (unsigned int i=0; i bundle_waypoints; double curvyness = randGen->GetUniformVariate(m_CurvynessMin, m_CurvynessMax); int twistdir = static_cast(randGen->GetIntegerVariate(2)) - 1; double dtwist = randGen->GetUniformVariate(m_MinTwist, m_MaxTwist); mitk::Vector3D pos; pos.Fill(0.0); mitk::Vector3D rot; rot.Fill(0.0); double twist = 0; double radius1 = randGen->GetUniformVariate(m_StartRadiusMin, m_StartRadiusMax); double radius2 = randGen->GetUniformVariate(m_StartRadiusMin, m_StartRadiusMax); GetPfOnBoundingPlane(pos, rot); rot[0] += randGen->GetUniformVariate(-curvyness, curvyness); rot[1] += randGen->GetUniformVariate(-curvyness, curvyness); rot[2] += randGen->GetUniformVariate(-curvyness, curvyness); mitk::PlanarEllipse::Pointer start = CreatePlanarFigure(); TransformPlanarFigure(start, pos, rot, twist, radius1, radius2); bundle_waypoints.push_back(start); double c_area = itk::Math::pi*radius1*radius2; int sizestrategy = static_cast(randGen->GetIntegerVariate(2)) - 1; MITK_INFO << "Twist: " << dtwist; MITK_INFO << "Twist direction: " << twistdir; MITK_INFO << "Curvyness: " << curvyness; MITK_INFO << "Size strategy: " << sizestrategy; int c = 1; while(IsInVolume(pos)) { pos += bundle_waypoints.at(c-1)->GetPlaneGeometry()->GetNormal() * randGen->GetUniformVariate(m_StepSizeMin, m_StepSizeMax); rot[0] += randGen->GetUniformVariate(-curvyness, curvyness); rot[1] += randGen->GetUniformVariate(-curvyness, curvyness); rot[2] += randGen->GetUniformVariate(-curvyness, curvyness); twist += dtwist * twistdir; if (randGen->GetUniformVariate(0.0, 1.0) < 0.25) { int temp = static_cast(randGen->GetIntegerVariate(2)) - 1; if (temp!=twistdir) { twistdir = temp; MITK_INFO << "Twist direction change: " << twistdir; } } if (randGen->GetUniformVariate(0.0, 1.0) < 0.25) { int temp = static_cast(randGen->GetIntegerVariate(2)) - 1; if (temp!=sizestrategy) { sizestrategy = temp; MITK_INFO << "Size strategy change: " << sizestrategy; } } double dsize = 3.0; double minradius = 5.0; double maxradius = 2.0*m_StartRadiusMax; if (sizestrategy==0) { radius1 += randGen->GetUniformVariate(-dsize, dsize); radius2 += randGen->GetUniformVariate(-dsize, dsize); while (radius1 < 5) radius1 += randGen->GetUniformVariate(-dsize, dsize); while (radius2 < 5) radius2 += randGen->GetUniformVariate(-dsize, dsize); } else if (sizestrategy==1) { radius1 += randGen->GetUniformVariate(0, dsize); radius2 += randGen->GetUniformVariate(0, dsize); if (radius1 > maxradius) { radius1 = maxradius; sizestrategy = static_cast(randGen->GetIntegerVariate(1)) - 1; } if (radius2 > maxradius) { radius2 = maxradius; sizestrategy = static_cast(randGen->GetIntegerVariate(1)) - 1; } } else if (sizestrategy==-1) { radius1 += randGen->GetUniformVariate(-dsize, 0); radius2 += randGen->GetUniformVariate(-dsize, 0); if (radius1 < minradius) { radius1 = minradius; sizestrategy = static_cast(randGen->GetIntegerVariate(1)); } if (radius2 < minradius) { radius2 = minradius; sizestrategy = static_cast(randGen->GetIntegerVariate(1)); } } c_area += itk::Math::pi*radius1*radius2; mitk::PlanarEllipse::Pointer pf = CreatePlanarFigure(); TransformPlanarFigure(pf, pos, rot, twist, radius1, radius2); bundle_waypoints.push_back(pf); ++c; } c_area /= c; c_area /= 100; MITK_INFO << "Average crossectional area: " << c_area << "cm²"; fiber_params.m_Fiducials.push_back(bundle_waypoints); auto density = randGen->GetUniformVariate(m_MinStreamlineDensity, m_MaxStreamlineDensity); MITK_INFO << "Density: " << density; MITK_INFO << "Num. fibers: " << fiber_params.m_Density; fiber_params.m_Density = static_cast(std::ceil(c_area*density)); if (randGen->GetIntegerVariate(1)==0) { fiber_params.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; MITK_INFO << "Distribution: uniform"; } else { fiber_params.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN; MITK_INFO << "Distribution: Gaussian"; } MITK_INFO << "Num. fiducials: " << c; MITK_INFO << "------------\n"; std::streambuf *old = cout.rdbuf(); // <-- save std::stringstream ss; std::cout.rdbuf (ss.rdbuf()); // <-- redirect itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New(); filter->SetParameters(fiber_params); + filter->SetFixSeed(m_FixSeed); filter->Update(); m_FiberBundles.push_back(filter->GetFiberBundles().at(0)); std::cout.rdbuf (old); // <-- restore } } } //#endif // __itkRandomPhantomFilter_cpp diff --git a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkRandomPhantomFilter.h b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkRandomPhantomFilter.h index 6d0cdf079a..87f0e0a338 100644 --- a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkRandomPhantomFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkRandomPhantomFilter.h @@ -1,109 +1,112 @@ /*=================================================================== 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 itkRandomPhantomFilter_h #define itkRandomPhantomFilter_h // MITK #include #include #include // ITK #include namespace itk{ /** * \brief */ class RandomPhantomFilter : public ProcessObject { public: typedef RandomPhantomFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef mitk::FiberBundle::Pointer FiberType; typedef std::vector< mitk::FiberBundle::Pointer > FiberContainerType; itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkTypeMacro( RandomPhantomFilter, ProcessObject ) void Update() override{ this->GenerateData(); } // output FiberContainerType GetFiberBundles(){ return m_FiberBundles; } void SetNumTracts(unsigned int NumTracts); - void setStartRadiusMin(unsigned int StartRadiusMin); + void SetStartRadiusMin(unsigned int StartRadiusMin); - void setStartRadiusMax(unsigned int StartRadiusMax); + void SetStartRadiusMax(unsigned int StartRadiusMax); - void setCurvynessMin(unsigned int CurvynessMin); + void SetCurvynessMin(unsigned int CurvynessMin); - void setCurvynessMax(unsigned int CurvynessMax); + void SetCurvynessMax(unsigned int CurvynessMax); - void setStepSizeMin(unsigned int StepSizeMin); + void SetStepSizeMin(unsigned int StepSizeMin); - void setStepSizeMax(unsigned int StepSizeMax); + void SetStepSizeMax(unsigned int StepSizeMax); - void setVolumeSize(const mitk::Vector3D &VolumeSize); + void SetVolumeSize(const mitk::Vector3D &VolumeSize); - void setMaxTwist(unsigned int MaxTwist); + void SetMaxTwist(unsigned int MaxTwist); - void setMinStreamlineDensity(unsigned int MinStreamlinDensity); + void SetMinStreamlineDensity(unsigned int MinStreamlinDensity); - void setMaxStreamlineDensity(unsigned int MaxStreamlineDensity); + void SetMaxStreamlineDensity(unsigned int MaxStreamlineDensity); - void setMinTwist(unsigned int MinTwist); + void SetMinTwist(unsigned int MinTwist); + + void SetFixSeed(bool FixSeed); protected: void GenerateData() override; RandomPhantomFilter(); ~RandomPhantomFilter() override; void TransformPlanarFigure(mitk::PlanarEllipse* pe, mitk::Vector3D translation, mitk::Vector3D rotation, double twistangle, double radius1, double radius2); mitk::PlanarEllipse::Pointer CreatePlanarFigure(); void GetPfOnBoundingPlane(mitk::Vector3D& pos, mitk::Vector3D& rot); bool IsInVolume(mitk::Vector3D pos); FiberContainerType m_FiberBundles; ///< container for the output fiber bundles unsigned int m_NumTracts; unsigned int m_MinStreamlineDensity; unsigned int m_MaxStreamlineDensity; unsigned int m_StartRadiusMin; unsigned int m_StartRadiusMax; unsigned int m_CurvynessMin; unsigned int m_CurvynessMax; unsigned int m_StepSizeMin; unsigned int m_StepSizeMax; unsigned int m_MinTwist; unsigned int m_MaxTwist; mitk::Vector3D m_VolumeSize; + bool m_FixSeed; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkRandomPhantomFilter.cpp" #endif #endif diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp index dc37d11497..8b517283c0 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp @@ -1,1165 +1,1165 @@ /*=================================================================== 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 "QmitkFiberGenerationView.h" // MITK #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RAPIDXML_NO_EXCEPTIONS #include #include #include #include #include "usModuleRegistry.h" #include #include #include #include #include #include #include #include #include #include #include "mitkNodePredicateDataType.h" #include #include #include #include #define _USE_MATH_DEFINES #include const std::string QmitkFiberGenerationView::VIEW_ID = "org.mitk.views.fibergenerationview"; QmitkFiberGenerationView::QmitkFiberGenerationView() : QmitkAbstractView() , m_Controls( 0 ) , m_SelectedImageNode( nullptr ) { } // Destructor QmitkFiberGenerationView::~QmitkFiberGenerationView() { } void QmitkFiberGenerationView::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::QmitkFiberGenerationViewControls; m_Controls->setupUi( parent ); m_ParameterFile = QDir::currentPath()+"/param.ffp"; connect(static_cast(m_Controls->m_RandomPhantomButton), SIGNAL(clicked()), static_cast(this), SLOT(RandomPhantom())); connect(static_cast(m_Controls->m_GenerateFibersButton), SIGNAL(clicked()), static_cast(this), SLOT(GenerateFibers())); connect(static_cast(m_Controls->m_CircleButton), SIGNAL(clicked()), static_cast(this), SLOT(OnDrawROI())); connect(static_cast(m_Controls->m_FlipButton), SIGNAL(clicked()), static_cast(this), SLOT(OnFlipButton())); connect(static_cast(m_Controls->m_JoinBundlesButton), SIGNAL(clicked()), static_cast(this), SLOT(JoinBundles())); connect(static_cast(m_Controls->m_VarianceBox), SIGNAL(valueChanged(double)), static_cast(this), SLOT(OnVarianceChanged(double))); connect(static_cast(m_Controls->m_DistributionBox), SIGNAL(currentIndexChanged(int)), static_cast(this), SLOT(OnDistributionChanged(int))); connect(static_cast(m_Controls->m_FiberDensityBox), SIGNAL(valueChanged(int)), static_cast(this), SLOT(OnFiberDensityChanged(int))); connect(static_cast(m_Controls->m_FiberSamplingBox), SIGNAL(valueChanged(double)), static_cast(this), SLOT(OnFiberSamplingChanged(double))); connect(static_cast(m_Controls->m_TensionBox), SIGNAL(valueChanged(double)), static_cast(this), SLOT(OnTensionChanged(double))); connect(static_cast(m_Controls->m_ContinuityBox), SIGNAL(valueChanged(double)), static_cast(this), SLOT(OnContinuityChanged(double))); connect(static_cast(m_Controls->m_BiasBox), SIGNAL(valueChanged(double)), static_cast(this), SLOT(OnBiasChanged(double))); connect(static_cast(m_Controls->m_ConstantRadiusBox), SIGNAL(stateChanged(int)), static_cast(this), SLOT(OnConstantRadius(int))); connect(static_cast(m_Controls->m_CopyBundlesButton), SIGNAL(clicked()), static_cast(this), SLOT(CopyBundles())); connect(static_cast(m_Controls->m_TransformBundlesButton), SIGNAL(clicked()), static_cast(this), SLOT(ApplyTransform())); connect(static_cast(m_Controls->m_AlignOnGrid), SIGNAL(clicked()), static_cast(this), SLOT(AlignOnGrid())); connect(static_cast(m_Controls->m_FidAxis1), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); connect(static_cast(m_Controls->m_FidAxis2), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); connect(static_cast(m_Controls->m_FidPosX), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); connect(static_cast(m_Controls->m_FidPosY), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); connect(static_cast(m_Controls->m_FidPosZ), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); connect(static_cast(m_Controls->m_FidTwist), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); connect(static_cast(m_Controls->m_AdvancedOptionsBox), SIGNAL( stateChanged(int)), static_cast(this), SLOT(ShowAdvancedOptions(int))); connect(static_cast(m_Controls->m_SaveParametersButton), SIGNAL(clicked()), static_cast(this), SLOT(SaveParameters())); connect(static_cast(m_Controls->m_LoadParametersButton), SIGNAL(clicked()), static_cast(this), SLOT(LoadParameters())); OnDistributionChanged(0); } UpdateGui(); } void QmitkFiberGenerationView::RandomPhantom() { itk::RandomPhantomFilter::Pointer filter = itk::RandomPhantomFilter::New(); filter->SetNumTracts(m_Controls->m_NumBundlesBox->value()); - filter->setMinStreamlineDensity(m_Controls->m_MinDensityBox->value()); - filter->setMaxStreamlineDensity(m_Controls->m_MaxDensityBox->value()); + filter->SetMinStreamlineDensity(m_Controls->m_MinDensityBox->value()); + filter->SetMaxStreamlineDensity(m_Controls->m_MaxDensityBox->value()); mitk::Vector3D vol; vol[0] = m_Controls->m_VolumeSizeX->value(); vol[1] = m_Controls->m_VolumeSizeY->value(); vol[2] = m_Controls->m_VolumeSizeZ->value(); - filter->setVolumeSize(vol); - filter->setStepSizeMin(m_Controls->m_StepSizeMinBox->value()); - filter->setStepSizeMax(m_Controls->m_StepSizeMaxBox->value()); - filter->setCurvynessMin(m_Controls->m_CurvyMinBox->value()); - filter->setCurvynessMax(m_Controls->m_CurvyMaxBox->value()); - filter->setStartRadiusMin(m_Controls->m_SizeMinBox->value()); - filter->setStartRadiusMax(m_Controls->m_SizeMaxBox->value()); - filter->setMinTwist(m_Controls->m_MinTwistBox->value()); - filter->setMaxTwist(m_Controls->m_MaxTwistBox->value()); + filter->SetVolumeSize(vol); + filter->SetStepSizeMin(m_Controls->m_StepSizeMinBox->value()); + filter->SetStepSizeMax(m_Controls->m_StepSizeMaxBox->value()); + filter->SetCurvynessMin(m_Controls->m_CurvyMinBox->value()); + filter->SetCurvynessMax(m_Controls->m_CurvyMaxBox->value()); + filter->SetStartRadiusMin(m_Controls->m_SizeMinBox->value()); + filter->SetStartRadiusMax(m_Controls->m_SizeMaxBox->value()); + filter->SetMinTwist(m_Controls->m_MinTwistBox->value()); + filter->SetMaxTwist(m_Controls->m_MaxTwistBox->value()); filter->Update(); auto fibs = filter->GetFiberBundles(); std::vector< mitk::DataNode::Pointer > fiber_nodes; int c = 1; for (auto fib : fibs) { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( fib ); node->SetName("Bundle_" + boost::lexical_cast(c)); GetDataStorage()->Add(node); fiber_nodes.push_back(node); ++c; } // mitk::RenderingManager::GetInstance()->RequestUpdateAll(); mitk::RenderingManager::GetInstance()->InitializeViews(GetDataStorage()->ComputeVisibleBoundingGeometry3D()); } void QmitkFiberGenerationView::UpdateParametersFromGui() { m_Parameters.ClearFiberParameters(); m_Parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); switch(m_Controls->m_DistributionBox->currentIndex()) { case 0: m_Parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; break; case 1: m_Parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN; break; default: m_Parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; } m_Parameters.m_FiberGen.m_Variance = m_Controls->m_VarianceBox->value(); m_Parameters.m_FiberGen.m_Density = m_Controls->m_FiberDensityBox->value(); m_Parameters.m_FiberGen.m_Sampling = m_Controls->m_FiberSamplingBox->value(); m_Parameters.m_FiberGen.m_Tension = m_Controls->m_TensionBox->value(); m_Parameters.m_FiberGen.m_Continuity = m_Controls->m_ContinuityBox->value(); m_Parameters.m_FiberGen.m_Bias = m_Controls->m_BiasBox->value(); m_Parameters.m_FiberGen.m_Rotation[0] = m_Controls->m_XrotBox->value(); m_Parameters.m_FiberGen.m_Rotation[1] = m_Controls->m_YrotBox->value(); m_Parameters.m_FiberGen.m_Rotation[2] = m_Controls->m_ZrotBox->value(); m_Parameters.m_FiberGen.m_Translation[0] = m_Controls->m_XtransBox->value(); m_Parameters.m_FiberGen.m_Translation[1] = m_Controls->m_YtransBox->value(); m_Parameters.m_FiberGen.m_Translation[2] = m_Controls->m_ZtransBox->value(); m_Parameters.m_FiberGen.m_Scale[0] = m_Controls->m_XscaleBox->value(); m_Parameters.m_FiberGen.m_Scale[1] = m_Controls->m_YscaleBox->value(); m_Parameters.m_FiberGen.m_Scale[2] = m_Controls->m_ZscaleBox->value(); m_Parameters.m_Misc.m_CheckRealTimeFibersBox = m_Controls->m_RealTimeFibers->isChecked(); m_Parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); m_Parameters.m_Misc.m_CheckIncludeFiducialsBox = m_Controls->m_IncludeFiducials->isChecked(); m_Parameters.m_Misc.m_CheckConstantRadiusBox = m_Controls->m_ConstantRadiusBox->isChecked(); } void QmitkFiberGenerationView::SaveParameters(QString filename) { UpdateParametersFromGui(); m_Parameters.SaveParameters(filename.toStdString()); m_ParameterFile = filename; } void QmitkFiberGenerationView::SaveParameters() { QString filename = QFileDialog::getSaveFileName( 0, tr("Save Parameters"), m_ParameterFile, tr("Fiberfox Parameters (*.ffp)") ); SaveParameters(filename); } void QmitkFiberGenerationView::LoadParameters() { QString filename = QFileDialog::getOpenFileName(0, tr("Load Parameters"), QString(itksys::SystemTools::GetFilenamePath(m_ParameterFile.toStdString()).c_str()), tr("Fiberfox Parameters (*.ffp)") ); if(filename.isEmpty() || filename.isNull()) return; m_ParameterFile = filename; m_Parameters.LoadParameters(filename.toStdString()); if (m_Parameters.m_MissingTags.size()>0) { QString missing("Parameter file might be corrupted. The following parameters could not be read: "); missing += QString(m_Parameters.m_MissingTags.c_str()); missing += "\nDefault values have been assigned to the missing parameters."; QMessageBox::information( nullptr, "Warning!", missing); } m_Controls->m_RealTimeFibers->setChecked(m_Parameters.m_Misc.m_CheckRealTimeFibersBox); m_Controls->m_AdvancedOptionsBox->setChecked(m_Parameters.m_Misc.m_CheckAdvancedFiberOptionsBox); m_Controls->m_IncludeFiducials->setChecked(m_Parameters.m_Misc.m_CheckIncludeFiducialsBox); m_Controls->m_ConstantRadiusBox->setChecked(m_Parameters.m_Misc.m_CheckConstantRadiusBox); m_Controls->m_DistributionBox->setCurrentIndex(m_Parameters.m_FiberGen.m_Distribution); m_Controls->m_VarianceBox->setValue(m_Parameters.m_FiberGen.m_Variance); m_Controls->m_FiberDensityBox->setValue(m_Parameters.m_FiberGen.m_Density); m_Controls->m_FiberSamplingBox->setValue(m_Parameters.m_FiberGen.m_Sampling); m_Controls->m_TensionBox->setValue(m_Parameters.m_FiberGen.m_Tension); m_Controls->m_ContinuityBox->setValue(m_Parameters.m_FiberGen.m_Continuity); m_Controls->m_BiasBox->setValue(m_Parameters.m_FiberGen.m_Bias); m_Controls->m_XrotBox->setValue(m_Parameters.m_FiberGen.m_Rotation[0]); m_Controls->m_YrotBox->setValue(m_Parameters.m_FiberGen.m_Rotation[1]); m_Controls->m_ZrotBox->setValue(m_Parameters.m_FiberGen.m_Rotation[2]); m_Controls->m_XtransBox->setValue(m_Parameters.m_FiberGen.m_Translation[0]); m_Controls->m_YtransBox->setValue(m_Parameters.m_FiberGen.m_Translation[1]); m_Controls->m_ZtransBox->setValue(m_Parameters.m_FiberGen.m_Translation[2]); m_Controls->m_XscaleBox->setValue(m_Parameters.m_FiberGen.m_Scale[0]); m_Controls->m_YscaleBox->setValue(m_Parameters.m_FiberGen.m_Scale[1]); m_Controls->m_ZscaleBox->setValue(m_Parameters.m_FiberGen.m_Scale[2]); } void QmitkFiberGenerationView::ShowAdvancedOptions(int state) { if (state) { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(true); m_Controls->m_AdvancedOptionsBox->setChecked(true); } else { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false); m_Controls->m_AdvancedOptionsBox->setChecked(false); } } void QmitkFiberGenerationView::OnConstantRadius(int value) { if (value>0 && m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnDistributionChanged(int value) { if (value==1) m_Controls->m_VarianceBox->setVisible(true); else m_Controls->m_VarianceBox->setVisible(false); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnVarianceChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnFiberDensityChanged(int) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnFiberSamplingChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnTensionChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnContinuityChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnBiasChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::UpdateFiducialPosition() { if (m_SelectedFiducials.size()!=1) return; mitk::PlanarEllipse* pe = dynamic_cast(m_SelectedFiducials.at(0)->GetData()); mitk::BaseGeometry* geom = pe->GetGeometry(); // translate mitk::Point3D origin; origin[0] = m_Controls->m_FidPosX->value(); origin[1] = m_Controls->m_FidPosY->value(); origin[2] = m_Controls->m_FidPosZ->value(); // transform control point coordinate into geometry translation auto p0 = pe->GetControlPoint(0); auto p1 = pe->GetControlPoint(1); auto p2 = pe->GetControlPoint(2); auto p3 = pe->GetControlPoint(3); auto v1 = p1 - p0; auto v2 = p2 - p0; auto angle_deg = m_Controls->m_FidTwist->value(); auto dot = std::cos(itk::Math::pi*angle_deg/180.0); vnl_matrix_fixed tRot; tRot[0][0] = dot; tRot[1][1] = tRot[0][0]; tRot[1][0] = sin(acos(tRot[0][0])); tRot[0][1] = -tRot[1][0]; if (angle_deg<0) tRot = tRot.transpose(); vnl_vector_fixed vt; vt[0]=1; vt[1]=0; vnl_vector_fixed v3 = tRot*vt; if (v1.GetNorm()<0.0001 || v2.GetNorm()<0.0001) { QMessageBox::information( nullptr, "", "Please select exactly one fiducial."); return; } v1.Normalize(); v2.Normalize(); p1 = p0 + v1*m_Controls->m_FidAxis1->value(); p2 = p0 + v2*m_Controls->m_FidAxis2->value(); p3 = p0 + mitk::Vector2D(v3); pe->SetControlPoint(1, p1); pe->SetControlPoint(2, p2); pe->SetControlPoint(3, p3); geom->SetOrigin(origin); pe->Modified(); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); UpdateGui(); } void QmitkFiberGenerationView::AlignOnGrid() { for (unsigned int i=0; i(m_SelectedFiducials.at(i)->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::DataStorage::SetOfObjects::ConstPointer parentFibs = GetDataStorage()->GetSources(m_SelectedFiducials.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = parentFibs->begin(); it != parentFibs->end(); ++it ) { mitk::DataNode::Pointer pFibNode = *it; if ( pFibNode.IsNotNull() && dynamic_cast(pFibNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(pFibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 ) { mitk::DataNode::Pointer pImgNode = *it2; if ( pImgNode.IsNotNull() && dynamic_cast(pImgNode->GetData()) ) { mitk::Image::Pointer img = dynamic_cast(pImgNode->GetData()); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); break; } } break; } } } for(unsigned int i=0; iGetSources(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it = sources->begin(); it != sources->end(); ++it ) { mitk::DataNode::Pointer imgNode = *it; if ( imgNode.IsNotNull() && dynamic_cast(imgNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::Image::Pointer img = dynamic_cast(imgNode->GetData()); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); } } break; } } } for(unsigned int i=0; i(m_SelectedImages.at(i)->GetData()); mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(m_SelectedImages.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it ) { mitk::DataNode::Pointer fibNode = *it; if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer derivations2 = GetDataStorage()->GetDerivations(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations2->begin(); it2 != derivations2->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); } } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnFlipButton() { if (m_SelectedFiducial.IsNull()) return; std::map::iterator it = m_DataNodeToPlanarFigureData.find(m_SelectedFiducial.GetPointer()); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; data.m_Flipped += 1; data.m_Flipped %= 2; } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnAddBundle() { if (m_SelectedImageNode.IsNull()) return; mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedImageNode); mitk::FiberBundle::Pointer bundle = mitk::FiberBundle::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( bundle ); QString name = QString("Bundle_%1").arg(children->size()); node->SetName(name.toStdString()); m_SelectedBundles.push_back(node); UpdateGui(); GetDataStorage()->Add(node, m_SelectedImageNode); } void QmitkFiberGenerationView::OnDrawROI() { if (m_SelectedBundles.empty()) OnAddBundle(); if (m_SelectedBundles.empty()) return; mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedBundles.at(0)); mitk::PlanarEllipse::Pointer figure = mitk::PlanarEllipse::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( figure ); node->SetBoolProperty("planarfigure.3drendering", true); node->SetBoolProperty("planarfigure.3drendering.fill", true); QList nodes = this->GetDataManagerSelection(); for( int i=0; iSetSelected(false); m_SelectedFiducial = node; QString name = QString("Fiducial_%1").arg(children->size()); node->SetName(name.toStdString()); node->SetSelected(true); this->DisableCrosshairNavigation(); mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetDataInteractor().GetPointer()); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( node ); } UpdateGui(); GetDataStorage()->Add(node, m_SelectedBundles.at(0)); } bool QmitkFiberGenerationView::CompareLayer(mitk::DataNode::Pointer i,mitk::DataNode::Pointer j) { int li = -1; i->GetPropertyValue("layer", li); int lj = -1; j->GetPropertyValue("layer", lj); return liGetSources(m_SelectedFiducial); for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it ) if(dynamic_cast((*it)->GetData())) m_SelectedBundles.push_back(*it); if (m_SelectedBundles.empty()) return; } UpdateParametersFromGui(); for (unsigned int i=0; iGetDerivations(m_SelectedBundles.at(i)); std::vector< mitk::DataNode::Pointer > childVector; for( mitk::DataStorage::SetOfObjects::const_iterator it = children->begin(); it != children->end(); ++it ) childVector.push_back(*it); std::sort(childVector.begin(), childVector.end(), CompareLayer); std::vector< mitk::PlanarEllipse::Pointer > fib; std::vector< unsigned int > flip; float radius = 1; int count = 0; for( std::vector< mitk::DataNode::Pointer >::const_iterator it = childVector.begin(); it != childVector.end(); ++it ) { mitk::DataNode::Pointer node = *it; if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { mitk::PlanarEllipse* ellipse = dynamic_cast(node->GetData()); if (m_Controls->m_ConstantRadiusBox->isChecked()) { ellipse->SetTreatAsCircle(true); mitk::Point2D c = ellipse->GetControlPoint(0); mitk::Point2D p = ellipse->GetControlPoint(1); mitk::Vector2D v = p-c; if (count==0) { radius = v.GetVnlVector().magnitude(); ellipse->SetControlPoint(1, p); ellipse->Modified(); } else { v.Normalize(); v *= radius; ellipse->SetControlPoint(1, c+v); ellipse->Modified(); } } fib.push_back(ellipse); std::map::iterator it = m_DataNodeToPlanarFigureData.find(node.GetPointer()); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; flip.push_back(data.m_Flipped); } else flip.push_back(0); } count++; } if (fib.size()>1) { m_Parameters.m_FiberGen.m_Fiducials.push_back(fib); m_Parameters.m_FiberGen.m_FlipList.push_back(flip); } else if (fib.size()>0) m_SelectedBundles.at(i)->SetData( mitk::FiberBundle::New() ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New(); filter->SetParameters(m_Parameters.m_FiberGen); filter->Update(); std::vector< mitk::FiberBundle::Pointer > fiberBundles = filter->GetFiberBundles(); for (unsigned int i=0; iSetData( fiberBundles.at(i) ); if (fiberBundles.at(i)->GetNumFibers()>50000) m_SelectedBundles.at(i)->SetVisibility(false); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberGenerationView::ApplyTransform() { std::vector< mitk::DataNode::Pointer > selectedBundles; for(unsigned int i=0; iGetDerivations(m_SelectedImages.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it ) { mitk::DataNode::Pointer fibNode = *it; if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) selectedBundles.push_back(fibNode); } } if (selectedBundles.empty()) selectedBundles = m_SelectedBundles2; if (!selectedBundles.empty()) { for (std::vector::const_iterator it = selectedBundles.begin(); it!=selectedBundles.end(); ++it) { mitk::FiberBundle::Pointer fib = dynamic_cast((*it)->GetData()); fib->RotateAroundAxis(m_Controls->m_XrotBox->value(), m_Controls->m_YrotBox->value(), m_Controls->m_ZrotBox->value()); fib->TranslateFibers(m_Controls->m_XtransBox->value(), m_Controls->m_YtransBox->value(), m_Controls->m_ZtransBox->value()); fib->ScaleFibers(m_Controls->m_XscaleBox->value(), m_Controls->m_YscaleBox->value(), m_Controls->m_ZscaleBox->value()); // handle child fiducials if (m_Controls->m_IncludeFiducials->isChecked()) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse* pe = dynamic_cast(fiducialNode->GetData()); mitk::BaseGeometry* geom = pe->GetGeometry(); // translate mitk::Vector3D world; world[0] = m_Controls->m_XtransBox->value(); world[1] = m_Controls->m_YtransBox->value(); world[2] = m_Controls->m_ZtransBox->value(); geom->Translate(world); // calculate rotation matrix double x = m_Controls->m_XrotBox->value()*itk::Math::pi/180; double y = m_Controls->m_YrotBox->value()*itk::Math::pi/180; double z = m_Controls->m_ZrotBox->value()*itk::Math::pi/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; // transform control point coordinate into geometry translation geom->SetOrigin(pe->GetWorldControlPoint(0)); mitk::Point2D cp; cp.Fill(0.0); pe->SetControlPoint(0, cp); // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); // implicit translation mitk::Vector3D trans; trans[0] = geom->GetOrigin()[0]-fib->GetGeometry()->GetCenter()[0]; trans[1] = geom->GetOrigin()[1]-fib->GetGeometry()->GetCenter()[1]; trans[2] = geom->GetOrigin()[2]-fib->GetGeometry()->GetCenter()[2]; mitk::Vector3D newWc = rot*trans; newWc = newWc-trans; geom->Translate(newWc); pe->Modified(); } } } } } else { for (unsigned int i=0; i(m_SelectedFiducials.at(i)->GetData()); mitk::BaseGeometry* geom = pe->GetGeometry(); // translate mitk::Vector3D world; world[0] = m_Controls->m_XtransBox->value(); world[1] = m_Controls->m_YtransBox->value(); world[2] = m_Controls->m_ZtransBox->value(); geom->Translate(world); // calculate rotation matrix double x = m_Controls->m_XrotBox->value()*itk::Math::pi/180; double y = m_Controls->m_YrotBox->value()*itk::Math::pi/180; double z = m_Controls->m_ZrotBox->value()*itk::Math::pi/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; // transform control point coordinate into geometry translation geom->SetOrigin(pe->GetWorldControlPoint(0)); mitk::Point2D cp; cp.Fill(0.0); pe->SetControlPoint(0, cp); // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); pe->Modified(); } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberGenerationView::CopyBundles() { if ( m_SelectedBundles.size()<1 ){ QMessageBox::information( nullptr, "Warning", "Select at least one fiber bundle!"); MITK_WARN("QmitkFiberGenerationView") << "Select at least one fiber bundle!"; return; } for (std::vector::const_iterator it = m_SelectedBundles.begin(); it!=m_SelectedBundles.end(); ++it) { // find parent image mitk::DataNode::Pointer parentNode; mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 ) { mitk::DataNode::Pointer pImgNode = *it2; if ( pImgNode.IsNotNull() && dynamic_cast(pImgNode->GetData()) ) { parentNode = pImgNode; break; } } mitk::FiberBundle::Pointer fib = dynamic_cast((*it)->GetData()); mitk::FiberBundle::Pointer newBundle = fib->GetDeepCopy(); QString name((*it)->GetName().c_str()); name += "_copy"; mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); if (parentNode.IsNotNull()) GetDataStorage()->Add(fbNode, parentNode); else GetDataStorage()->Add(fbNode); // copy child fiducials if (m_Controls->m_IncludeFiducials->isChecked()) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData())->Clone(); mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetData(pe); newNode->SetName(fiducialNode->GetName()); newNode->SetBoolProperty("planarfigure.3drendering", true); GetDataStorage()->Add(newNode, fbNode); } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberGenerationView::JoinBundles() { if ( m_SelectedBundles.size()<2 ){ QMessageBox::information( nullptr, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberGenerationView") << "Select at least two fiber bundles!"; return; } std::vector< mitk::FiberBundle::Pointer > to_add; std::vector::const_iterator it = m_SelectedBundles.begin(); (*it)->SetVisibility(false); mitk::FiberBundle::Pointer newBundle = dynamic_cast((*it)->GetData()); QString name(""); name += QString((*it)->GetName().c_str()); ++it; for (; it!=m_SelectedBundles.end(); ++it) { (*it)->SetVisibility(false); to_add.push_back(dynamic_cast((*it)->GetData())); } newBundle = newBundle->AddBundles(to_add); mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName("Joined"); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberGenerationView::UpdateGui() { m_Controls->m_FiberGenMessage->setVisible(true); m_Controls->m_TransformBundlesButton->setEnabled(false); m_Controls->m_CopyBundlesButton->setEnabled(false); m_Controls->m_GenerateFibersButton->setEnabled(false); m_Controls->m_FlipButton->setEnabled(false); m_Controls->m_CircleButton->setEnabled(false); m_Controls->m_JoinBundlesButton->setEnabled(false); m_Controls->m_AlignOnGrid->setEnabled(false); m_Controls->m_FiducialAttributeBox->setEnabled(false); // Fiber generation gui if (m_SelectedFiducial.IsNotNull()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_FlipButton->setEnabled(true); m_Controls->m_AlignOnGrid->setEnabled(true); } if (m_SelectedFiducials.size()==1) { m_Controls->m_FiducialAttributeBox->setEnabled(true); mitk::PlanarEllipse* pe = dynamic_cast(m_SelectedFiducials.at(0)->GetData()); auto origin = pe->GetGeometry()->GetOrigin(); m_Controls->m_FidPosX->setValue(origin[0]); m_Controls->m_FidPosY->setValue(origin[1]); m_Controls->m_FidPosZ->setValue(origin[2]); auto p0 = pe->GetControlPoint(0); auto p1 = pe->GetControlPoint(1); auto p2 = pe->GetControlPoint(2); auto p3 = pe->GetControlPoint(3); auto v1 = p1 - p0; auto v2 = p2 - p0; m_Controls->m_FidAxis1->setValue(v1.GetNorm()); m_Controls->m_FidAxis2->setValue(v2.GetNorm()); vnl_vector_fixed vt; vt[0]=1; vt[1]=0; auto v3 = p3-p0; v3.Normalize(); auto angle = dot_product(vt, v3.GetVnlVector()); angle = std::acos(angle)*180.0/itk::Math::pi; if (v3[1]<0) angle *= -1; m_Controls->m_FidTwist->setValue(angle); } else { m_Controls->m_FidPosX->setValue(0); m_Controls->m_FidPosY->setValue(0); m_Controls->m_FidPosZ->setValue(0); m_Controls->m_FidAxis1->setValue(1); m_Controls->m_FidAxis2->setValue(1); m_Controls->m_FidTwist->setValue(0); } if (m_SelectedImageNode.IsNotNull() || !m_SelectedBundles.empty()) { m_Controls->m_CircleButton->setEnabled(true); m_Controls->m_FiberGenMessage->setVisible(false); } if (m_SelectedImageNode.IsNotNull() && !m_SelectedBundles.empty()) m_Controls->m_AlignOnGrid->setEnabled(true); if (!m_SelectedBundles.empty()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_CopyBundlesButton->setEnabled(true); m_Controls->m_GenerateFibersButton->setEnabled(true); if (m_SelectedBundles.size()>1) m_Controls->m_JoinBundlesButton->setEnabled(true); } } void QmitkFiberGenerationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& nodes) { m_SelectedBundles2.clear(); m_SelectedImages.clear(); m_SelectedFiducials.clear(); m_SelectedFiducial = nullptr; m_SelectedBundles.clear(); m_SelectedImageNode = nullptr; // iterate all selected objects, adjust warning visibility for( int i=0; i(node->GetData()) ) { m_SelectedImages.push_back(node); m_SelectedImageNode = node; } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedBundles2.push_back(node); if (m_Controls->m_RealTimeFibers->isChecked()) { m_SelectedBundles.push_back(node); mitk::FiberBundle::Pointer newFib = dynamic_cast(node->GetData()); if (newFib->GetNumFibers()!=static_cast(m_Controls->m_FiberDensityBox->value())) GenerateFibers(); } else m_SelectedBundles.push_back(node); } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedFiducials.push_back(node); m_SelectedFiducial = node; m_SelectedBundles.clear(); mitk::DataStorage::SetOfObjects::ConstPointer parents = GetDataStorage()->GetSources(node); for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it ) { mitk::DataNode::Pointer pNode = *it; if ( pNode.IsNotNull() && dynamic_cast(pNode->GetData()) ) m_SelectedBundles.push_back(pNode); } } } UpdateGui(); } void QmitkFiberGenerationView::EnableCrosshairNavigation() { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::DisableCrosshairNavigation() { } void QmitkFiberGenerationView::NodeRemoved(const mitk::DataNode* node) { mitk::DataNode* nonConstNode = const_cast(node); std::map::iterator it = m_DataNodeToPlanarFigureData.find(nonConstNode); if (dynamic_cast(node->GetData())) { m_SelectedBundles.clear(); m_SelectedBundles2.clear(); } else if (dynamic_cast(node->GetData())) m_SelectedImages.clear(); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; // remove observers data.m_Figure->RemoveObserver( data.m_EndPlacementObserverTag ); data.m_Figure->RemoveObserver( data.m_SelectObserverTag ); data.m_Figure->RemoveObserver( data.m_StartInteractionObserverTag ); data.m_Figure->RemoveObserver( data.m_EndInteractionObserverTag ); m_DataNodeToPlanarFigureData.erase( it ); } } void QmitkFiberGenerationView::NodeAdded( const mitk::DataNode* node ) { // add observer for selection in renderwindow mitk::PlanarFigure* figure = dynamic_cast(node->GetData()); bool isPositionMarker (false); node->GetBoolProperty("isContourMarker", isPositionMarker); if( figure && !isPositionMarker ) { MITK_DEBUG << "figure added. will add interactor if needed."; mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetDataInteractor().GetPointer()); mitk::DataNode* nonConstNode = const_cast( node ); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( nonConstNode ); } MITK_DEBUG << "will now add observers for planarfigure"; QmitkPlanarFigureData data; data.m_Figure = figure; // // add observer for event when figure has been placed typedef itk::SimpleMemberCommand< QmitkFiberGenerationView > SimpleCommandType; // SimpleCommandType::Pointer initializationCommand = SimpleCommandType::New(); // initializationCommand->SetCallbackFunction( this, &QmitkFiberGenerationView::PlanarFigureInitialized ); // data.m_EndPlacementObserverTag = figure->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand ); // add observer for event when figure is picked (selected) typedef itk::MemberCommand< QmitkFiberGenerationView > MemberCommandType; MemberCommandType::Pointer selectCommand = MemberCommandType::New(); selectCommand->SetCallbackFunction( this, &QmitkFiberGenerationView::PlanarFigureSelected ); data.m_SelectObserverTag = figure->AddObserver( mitk::SelectPlanarFigureEvent(), selectCommand ); // add observer for event when interaction with figure starts SimpleCommandType::Pointer startInteractionCommand = SimpleCommandType::New(); startInteractionCommand->SetCallbackFunction( this, &QmitkFiberGenerationView::DisableCrosshairNavigation); data.m_StartInteractionObserverTag = figure->AddObserver( mitk::StartInteractionPlanarFigureEvent(), startInteractionCommand ); // add observer for event when interaction with figure starts SimpleCommandType::Pointer endInteractionCommand = SimpleCommandType::New(); endInteractionCommand->SetCallbackFunction( this, &QmitkFiberGenerationView::EnableCrosshairNavigation); data.m_EndInteractionObserverTag = figure->AddObserver( mitk::EndInteractionPlanarFigureEvent(), endInteractionCommand ); m_DataNodeToPlanarFigureData[nonConstNode] = data; } } void QmitkFiberGenerationView::PlanarFigureSelected( itk::Object* object, const itk::EventObject& ) { mitk::TNodePredicateDataType::Pointer isPf = mitk::TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer allPfs = this->GetDataStorage()->GetSubset( isPf ); for ( mitk::DataStorage::SetOfObjects::const_iterator it = allPfs->begin(); it!=allPfs->end(); ++it) { mitk::DataNode* node = *it; if( node->GetData() == object ) { node->SetSelected(true); m_SelectedFiducial = node; } else node->SetSelected(false); } UpdateGui(); this->RequestRenderWindowUpdate(); } void QmitkFiberGenerationView::SetFocus() { m_Controls->m_CircleButton->setFocus(); } diff --git a/Plugins/org.mitk.gui.qt.python/CMakeLists.txt b/Plugins/org.mitk.gui.qt.python/CMakeLists.txt index 42115978c2..3a784c3ba4 100644 --- a/Plugins/org.mitk.gui.qt.python/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.python/CMakeLists.txt @@ -1,6 +1,10 @@ +if(MITK_USE_Python) + project(org_mitk_gui_qt_python) mitk_create_plugin( EXPORT_DIRECTIVE org_mitk_gui_qt_python_EXPORT EXPORTED_INCLUDE_SUFFIXES src MODULE_DEPENDS MitkQtWidgetsExt MitkPython MitkQtPython) + +endif()