diff --git a/Applications/CMakeLists.txt b/Applications/CMakeLists.txt index 8e4124be00..bcaa425c30 100644 --- a/Applications/CMakeLists.txt +++ b/Applications/CMakeLists.txt @@ -1,27 +1,31 @@ set(MITK_CPACK_PACKAGE_EXECUTABLES "" CACHE INTERNAL "Collecting windows shortcuts to executables" FORCE) set(MITK_DIR ${PROJECT_BINARY_DIR}) set(MITK_EXPORTS_FILE_INCLUDED 1) if(MITK_USE_QT AND QT4_FOUND) if(MITK_USE_CTK) add_subdirectory(PluginGenerator) endif() - if(MITK_BUILD_APP_CoreApp OR MITK_BUILD_ALL_APPS) - add_subdirectory(CoreApp) - endif() - - if(MITK_BUILD_APP_ExtApp OR MITK_BUILD_ALL_APPS) - add_subdirectory(ExtApp) + if(MITK_USE_BLUEBERRY) + + foreach(mitk_app ${MITK_APPS}) + # extract target_dir and option_name + string(REPLACE "^^" "\\;" target_info ${mitk_app}) + set(target_info_list ${target_info}) + list(GET target_info_list 0 target_dir) + list(GET target_info_list 1 option_name) + # check if the application is enabled + if(${option_name} OR MITK_BUILD_ALL_APPS) + add_subdirectory(${target_dir}) + endif() + endforeach() + endif() if(MITK_BUILD_TUTORIAL) add_subdirectory(Tutorial) endif() - - if(MITK_BUILD_APP_mitkDiffusion OR MITK_BUILD_ALL_APPS) - add_subdirectory(mitkDiffusion) - endif() endif() diff --git a/Applications/Tutorial/Step1.cpp b/Applications/Tutorial/Step1.cpp index d97a7ecc92..295d1f596f 100644 --- a/Applications/Tutorial/Step1.cpp +++ b/Applications/Tutorial/Step1.cpp @@ -1,122 +1,116 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkRegisterClasses.h" #include "QmitkRenderWindow.h" -#include +#include #include #include #include //##Documentation //## @brief Load image (pic format) and display it in a 2D view int main(int argc, char* argv[]) { QApplication qtapplication( argc, argv ); if (argc < 2) { fprintf( stderr, "Usage: %s [filename] \n\n", itksys::SystemTools::GetFilenameName(argv[0]).c_str() ); return 1; } // Register Qmitk-dependent global instances QmitkRegisterClasses(); //************************************************************************* // Part I: Basic initialization //************************************************************************* // Create a DataStorage // The DataStorage manages all data objects. It is used by the // rendering mechanism to render all data objects // We use the standard implementation mitk::StandaloneDataStorage. mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); //************************************************************************* // Part II: Create some data by reading a file //************************************************************************* - // Create a PicFileReader to read a .pic-file - mitk::PicFileReader::Pointer reader = mitk::PicFileReader::New(); + // Create a DataNodeFactory to read a data format supported + // by the DataNodeFactory (many image formats, surface formats, etc.) + mitk::DataNodeFactory::Pointer reader=mitk::DataNodeFactory::New(); const char * filename = argv[1]; try { reader->SetFileName(filename); reader->Update(); + //************************************************************************* + // Part III: Put the data into the datastorage + //************************************************************************* + + // Add the node to the DataStorage + ds->Add(reader->GetOutput()); } catch(...) { fprintf( stderr, "Could not open file %s \n\n", filename ); exit(2); } - //************************************************************************* - // Part III: Put the data into the datastorage - //************************************************************************* - - // Create a node and add the Image (which is read from the file) to it - mitk::DataNode::Pointer node = mitk::DataNode::New(); - node->SetData(reader->GetOutput()); - - // Add the node to the DataStorage - ds->Add(node); - - //************************************************************************* // Part IV: Create window and pass the datastorage to it //************************************************************************* // Create a RenderWindow QmitkRenderWindow renderWindow; // Tell the RenderWindow which (part of) the datastorage to render renderWindow.GetRenderer()->SetDataStorage(ds); // Initialize the RenderWindow mitk::TimeSlicedGeometry::Pointer geo = ds->ComputeBoundingGeometry3D(ds->GetAll()); mitk::RenderingManager::GetInstance()->InitializeViews( geo ); //mitk::RenderingManager::GetInstance()->InitializeViews(); // Select a slice mitk::SliceNavigationController::Pointer sliceNaviController = renderWindow.GetSliceNavigationController(); if (sliceNaviController) sliceNaviController->GetSlice()->SetPos( 0 ); //************************************************************************* // Part V: Qt-specific initialization //************************************************************************* renderWindow.show(); renderWindow.resize( 256, 256 ); // for testing #include "QtTesting.h" if (strcmp(argv[argc-1], "-testing") != 0) return qtapplication.exec(); else return QtTesting(); - // cleanup: Remove References to node and DataStorage. This will delete the two objects - node = NULL; + // cleanup: Remove References to DataStorage. This will delete the object ds = NULL; } /** \example Step1.cpp */ diff --git a/Applications/mitkDiffusion/CMakeLists.txt b/Applications/mitkDiffusion/CMakeLists.txt index 76b5b46354..4a0a2467a4 100644 --- a/Applications/mitkDiffusion/CMakeLists.txt +++ b/Applications/mitkDiffusion/CMakeLists.txt @@ -1,59 +1,77 @@ project(mitkDiffusion) set(DIFFUSIONAPP_NAME mitkDiffusion) set(_app_options) if(MITK_SHOW_CONSOLE_WINDOW) list(APPEND _app_options SHOW_CONSOLE) endif() MITK_USE_MODULE(qtsingleapplication) include_directories(${ALL_INCLUDE_DIRECTORIES}) # 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) set(_plugins + org.commontk.configadmin + org.commontk.eventadmin + org.blueberry.osgi org.blueberry.compat + org.blueberry.core.runtime + org.blueberry.core.expressions + org.blueberry.solstice.common + org.blueberry.core.commands + org.blueberry.core.jobs + org.blueberry.ui + org.blueberry.ui.qt org.blueberry.ui.qt.help + org.blueberry.ui.qt.log + org.blueberry.ui.qt.objectinspector + org.mitk.core.services + org.mitk.gui.common + org.mitk.planarfigure + org.mitk.core.ext org.mitk.diffusionimaging + org.mitk.gui.qt.application + org.mitk.gui.qt.ext org.mitk.gui.qt.diffusionimagingapp + org.mitk.gui.qt.common + org.mitk.gui.qt.stdmultiwidgeteditor org.mitk.gui.qt.common.legacy - org.mitk.gui.qt.ext org.mitk.gui.qt.datamanager org.mitk.gui.qt.measurementtoolbox org.mitk.gui.qt.segmentation org.mitk.gui.qt.volumevisualization org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.imagenavigator org.mitk.gui.qt.moviemaker - org.mitk.planarfigure ) # 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 ) FunctionCreateBlueBerryApplication( NAME ${DIFFUSIONAPP_NAME} DESCRIPTION "MITK Diffusion" PLUGINS ${_plugins} EXCLUDE_PLUGINS ${_exclude_plugins} LINK_LIBRARIES ${ALL_LIBRARIES} ${_app_options} ) # Add a build time dependency to legacy BlueBerry bundles. if(MITK_MODULES_ENABLED_PLUGINS) add_dependencies(${DIFFUSIONAPP_NAME} ${MITK_MODULES_ENABLED_PLUGINS}) endif() \ No newline at end of file diff --git a/CMake/CPackDiffusionConfig.cmake.in b/Applications/mitkDiffusion/CPackConfig.cmake.in similarity index 100% rename from CMake/CPackDiffusionConfig.cmake.in rename to Applications/mitkDiffusion/CPackConfig.cmake.in diff --git a/CMake/CPackOptionsDiffusion.cmake b/Applications/mitkDiffusion/CPackOptions.cmake similarity index 82% rename from CMake/CPackOptionsDiffusion.cmake rename to Applications/mitkDiffusion/CPackOptions.cmake index 71e2c064c1..2eeee3871b 100644 --- a/CMake/CPackOptionsDiffusion.cmake +++ b/Applications/mitkDiffusion/CPackOptions.cmake @@ -1,29 +1,29 @@ # Set Diffusion specific CPack options set(CPACK_PACKAGE_EXECUTABLES "mitkDiffusion;MITK Diffusion") set(CPACK_PACKAGE_NAME "MITK-Diffusion") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MITK application for processing of MR diffusion imaging data.") # Major version is the year of release -set(CPACK_PACKAGE_VERSION_MAJOR "2011") +set(CPACK_PACKAGE_VERSION_MAJOR "2012") # Minor version is assigned depending on the number of releases that year, order is "", "a", "b"..., "z" set(CPACK_PACKAGE_VERSION_MINOR "") # Patch versioning is not intended to be done set(CPACK_PACKAGE_VERSION_PATCH "") # this should result in names like 2011, 2011a, ... # version has to be set explicitly to avoid such things as CMake creating the install directory "MITK Diffusion 2011.." set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}${CPACK_PACKAGE_VERSION_MINOR}") -set(CPACK_PACKAGE_DESCRIPTION_FILE "${MITK_SOURCE_DIR}/DiffusionCopyright.txt") -set(CPACK_RESOURCE_FILE_LICENSE "${MITK_SOURCE_DIR}/DiffusionCopyright.txt") +set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/Copyright.txt") +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/Copyright.txt") if(CMAKE_CL_64) set(CPACK_PACKAGE_FILE_NAME "MITK-Diffusion-${CPACK_PACKAGE_VERSION}-win64") elseif(MINGW) set(CPACK_PACKAGE_FILE_NAME "MITK-Diffusion-${CPACK_PACKAGE_VERSION}-mingw32") elseif(WIN32) set(CPACK_PACKAGE_FILE_NAME "MITK-Diffusion-${CPACK_PACKAGE_VERSION}-win32") else() set(CPACK_PACKAGE_FILE_NAME "MITK-Diffusion-${CPACK_PACKAGE_VERSION}") endif() diff --git a/DiffusionCopyright.txt b/Applications/mitkDiffusion/Copyright.txt similarity index 100% rename from DiffusionCopyright.txt rename to Applications/mitkDiffusion/Copyright.txt diff --git a/CMake/PackageDepends/MITK_X11_Config.cmake b/CMake/PackageDepends/MITK_X11_Config.cmake new file mode 100644 index 0000000000..84a05878b9 --- /dev/null +++ b/CMake/PackageDepends/MITK_X11_Config.cmake @@ -0,0 +1,4 @@ +find_package(X11 REQUIRED) +list(APPEND ALL_INCLUDE_DIRECTORIES ${X11_INCLUDE_DIR}) +list(APPEND ALL_LIBRARIES ${X11_LIBRARIES}) + diff --git a/CMake/mitkSetupCPack.cmake b/CMake/mitkSetupCPack.cmake index 199eb85181..c5a93977b6 100644 --- a/CMake/mitkSetupCPack.cmake +++ b/CMake/mitkSetupCPack.cmake @@ -1,58 +1,57 @@ # # First, set the generator variable # if(NOT CPACK_GENERATOR) if(WIN32) find_program(NSIS_MAKENSIS NAMES makensis PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS] DOC "Where is makensis.exe located" ) if(NOT NSIS_MAKENSIS) set(CPACK_GENERATOR ZIP) else() set(CPACK_GENERATOR "NSIS;ZIP") endif(NOT NSIS_MAKENSIS) else() if(APPLE) set(CPACK_GENERATOR DragNDrop) else() set(CPACK_GENERATOR TGZ) endif() endif() endif(NOT CPACK_GENERATOR) # include required mfc libraries include(InstallRequiredSystemLibraries) set(CPACK_PACKAGE_NAME "MITK") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MITK is a medical image processing tool") set(CPACK_PACKAGE_VENDOR "German Cancer Research Center (DKFZ)") -set(CPACK_CREATE_DESKTOP_LINKS "ExtApp") set(CPACK_PACKAGE_DESCRIPTION_FILE "${MITK_SOURCE_DIR}/MITKCopyright.txt") set(CPACK_RESOURCE_FILE_LICENSE "${MITK_SOURCE_DIR}/MITKCopyright.txt") set(CPACK_PACKAGE_VERSION_MAJOR "${MITK_VERSION_MAJOR}") set(CPACK_PACKAGE_VERSION_MINOR "${MITK_VERSION_MINOR}") # tell cpack to strip all debug symbols from all files set(CPACK_STRIP_FILES ON) # append revision number if available if(MITK_REVISION_ID) if(MITK_WC_TYPE STREQUAL "git") set(git_hash ${MITK_REVISION_ID}) string(LENGTH "${git_hash}" hash_length) if(hash_length GREATER 6) string(SUBSTRING ${git_hash} 0 6 git_hash) endif() set(CPACK_PACKAGE_VERSION_PATCH "${MITK_VERSION_PATCH}_r${git_hash}") else() set(CPACK_PACKAGE_VERSION_PATCH "${MITK_VERSION_PATCH}_r${MITK_REVISION_ID}") endif() else() set(CPACK_PACKAGE_VERSION_PATCH "${MITK_VERSION_PATCH}") endif() diff --git a/CMake/mitkSetupVariables.cmake b/CMake/mitkSetupVariables.cmake index 0adae41d27..d3303a6677 100644 --- a/CMake/mitkSetupVariables.cmake +++ b/CMake/mitkSetupVariables.cmake @@ -1,160 +1,161 @@ if(MITK_BUILD_ALL_PLUGINS) set(MITK_BUILD_ALL_PLUGINS_OPTION "FORCE_BUILD_ALL") endif() set(LIBPOSTFIX "") # MITK_VERSION set(MITK_VERSION_MAJOR "2012") set(MITK_VERSION_MINOR "02") set(MITK_VERSION_PATCH "99") set(MITK_VERSION_STRING "${MITK_VERSION_MAJOR}.${MITK_VERSION_MINOR}.${MITK_VERSION_PATCH}") if(MITK_VERSION_PATCH STREQUAL "99") set(MITK_VERSION_STRING "${MITK_VERSION_STRING}-${MITK_REVISION_SHORTID}") endif() #----------------------------------- # Configuration of module system #----------------------------------- set(MODULES_CONF_DIRNAME modulesConf) set(MODULES_CONF_DIRS ${MITK_BINARY_DIR}/${MODULES_CONF_DIRNAME}) if(NOT UNIX AND NOT MINGW) set(MITK_WIN32_FORCE_STATIC "STATIC" CACHE INTERNAL "Use this variable to always build static libraries on non-unix platforms") endif() # build the MITK_INCLUDE_DIRS variable set(MITK_INCLUDE_DIRS ${PROJECT_BINARY_DIR}) set(CORE_DIRECTORIES DataManagement Algorithms IO Rendering Interactions Controllers Service) foreach(d ${CORE_DIRECTORIES}) list(APPEND MITK_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/Core/Code/${d}) endforeach() #list(APPEND MITK_INCLUDE_DIRS #${ITK_INCLUDE_DIRS} #${VTK_INCLUDE_DIRS} # ) -foreach(d Utilities Utilities/ipPic Utilities/IIL4MITK Utilities/pic2vtk Utilities/tinyxml Utilities/mbilog) +#foreach(d Utilities Utilities/ipPic Utilities/IIL4MITK Utilities/pic2vtk Utilities/tinyxml Utilities/mbilog) +foreach(d Utilities Utilities/ipPic Utilities/pic2vtk Utilities/tinyxml Utilities/mbilog) list(APPEND MITK_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/${d}) endforeach() list(APPEND MITK_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/Utilities/mbilog) if(WIN32) list(APPEND MITK_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ipPic/win32) endif() # additional include dirs variables set(ANN_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ann/include) set(IPSEGMENTATION_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ipSegmentation) # variables containing librariy names set(MITK_CORE_LIBRARIES Mitk) set(VTK_FOR_MITK_LIBRARIES vtkGraphics vtkCommon vtkFiltering vtkftgl vtkGraphics vtkHybrid vtkImaging vtkIO vtkParallel vtkRendering vtkVolumeRendering vtkWidgets ${VTK_JPEG_LIBRARIES} ${VTK_PNG_LIBRARIES} ${VTK_ZLIB_LIBRARIES} ${VTK_EXPAT_LIBRARIES} ${VTK_FREETYPE_LIBRARIES} ) # TODO: maybe solve this with lib depends mechanism of CMake set(UTIL_FOR_MITK_LIBRARIES mitkIpPic mitkIpFunc mbilog) set(LIBRARIES_FOR_MITK_CORE ${UTIL_FOR_MITK_LIBRARIES} ${VTK_FOR_MITK_LIBRARIES} ${ITK_LIBRARIES} ) set(MITK_LIBRARIES ${MITK_CORE_LIBRARIES} ${LIBRARIES_FOR_MITK_CORE} pic2vtk - IIL4MITK + #IIL4MITK ipSegmentation ann ) # variables used in CMake macros which are called from external projects set(MITK_VTK_LIBRARY_DIRS ${VTK_LIBRARY_DIRS}) set(MITK_ITK_LIBRARY_DIRS ${ITK_LIBRARY_DIRS}) # variables containing link directories set(MITK_LIBRARY_DIRS ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) set(MITK_LINK_DIRECTORIES ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${ITK_LIBRARY_DIRS} ${VTK_LIBRARY_DIRS} ${GDCM_LIBRARY_DIRS}) # Qt support if(MITK_USE_QT) find_package(Qt4 REQUIRED) set(QMITK_INCLUDE_DIRS ${MITK_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/CoreUI/Qmitk ${PROJECT_BINARY_DIR}/CoreUI/Qmitk ) foreach(d QmitkApplicationBase QmitkModels QmitkPropertyObservers) list(APPEND QMITK_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/CoreUI/Qmitk/${d}) endforeach() list(APPEND QMITK_INCLUDE_DIRS ${QWT_INCLUDE_DIR}) set(QMITK_LIBRARIES Qmitk ${MITK_LIBRARIES} ${QT_LIBRARIES}) set(QMITK_LINK_DIRECTORIES ${MITK_LINK_DIRECTORIES} ${QT_LIBRARY_DIR}) endif() if(MITK_BUILD_ALL_PLUGINS) set(MITK_BUILD_ALL_PLUGINS_OPTION "FORCE_BUILD_ALL") endif() # create a list of types for template instantiations of itk image access functions function(_create_type_seq TYPES seq_var seqdim_var) set(_seq ) set(_seq_dim ) string(REPLACE "," ";" _pixeltypes "${TYPES}") foreach(_pixeltype ${_pixeltypes}) set(_seq "${_seq}(${_pixeltype})") set(_seq_dim "${_seq_dim}((${_pixeltype},dim))") endforeach() set(${seq_var} "${_seq}" PARENT_SCOPE) set(${seqdim_var} "${_seq_dim}" PARENT_SCOPE) endfunction() set(MITK_ACCESSBYITK_PIXEL_TYPES ) set(MITK_ACCESSBYITK_PIXEL_TYPES_SEQ ) set(MITK_ACCESSBYITK_TYPES_DIMN_SEQ ) foreach(_type INTEGRAL FLOATING COMPOSITE) set(_typelist "${MITK_ACCESSBYITK_${_type}_PIXEL_TYPES}") if(_typelist) if(MITK_ACCESSBYITK_PIXEL_TYPES) set(MITK_ACCESSBYITK_PIXEL_TYPES "${MITK_ACCESSBYITK_PIXEL_TYPES},${_typelist}") else() set(MITK_ACCESSBYITK_PIXEL_TYPES "${_typelist}") endif() endif() _create_type_seq("${_typelist}" MITK_ACCESSBYITK_${_type}_PIXEL_TYPES_SEQ MITK_ACCESSBYITK_${_type}_TYPES_DIMN_SEQ) set(MITK_ACCESSBYITK_PIXEL_TYPES_SEQ "${MITK_ACCESSBYITK_PIXEL_TYPES_SEQ}${MITK_ACCESSBYITK_${_type}_PIXEL_TYPES_SEQ}") set(MITK_ACCESSBYITK_TYPES_DIMN_SEQ "${MITK_ACCESSBYITK_TYPES_DIMN_SEQ}${MITK_ACCESSBYITK_${_type}_TYPES_DIMN_SEQ}") endforeach() set(MITK_ACCESSBYITK_DIMENSIONS_SEQ ) string(REPLACE "," ";" _dimensions "${MITK_ACCESSBYITK_DIMENSIONS}") foreach(_dimension ${_dimensions}) set(MITK_ACCESSBYITK_DIMENSIONS_SEQ "${MITK_ACCESSBYITK_DIMENSIONS_SEQ}(${_dimension})") endforeach() diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d72e624e2..9a384b8aec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,813 +1,867 @@ cmake_minimum_required(VERSION 2.8.4) #----------------------------------------------------------------------------- # Set a default build type if none was specified #----------------------------------------------------------------------------- if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'Debug' as none was specified.") set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() #----------------------------------------------------------------------------- # Superbuild Option - Enabled by default #----------------------------------------------------------------------------- option(MITK_USE_SUPERBUILD "Build MITK and the projects it depends on via SuperBuild.cmake." ON) if(MITK_USE_SUPERBUILD) project(MITK-superbuild) set(MITK_SOURCE_DIR ${PROJECT_SOURCE_DIR}) set(MITK_BINARY_DIR ${PROJECT_BINARY_DIR}) else() project(MITK) endif() #----------------------------------------------------------------------------- # Warn if source or build path is too long #----------------------------------------------------------------------------- if(WIN32) set(_src_dir_length_max 50) set(_bin_dir_length_max 50) if(MITK_USE_SUPERBUILD) set(_src_dir_length_max 43) # _src_dir_length_max - strlen(ITK-src) set(_bin_dir_length_max 40) # _bin_dir_length_max - strlen(MITK-build) endif() string(LENGTH "${MITK_SOURCE_DIR}" _src_n) string(LENGTH "${MITK_BINARY_DIR}" _bin_n) # The warnings should be converted to errors if(_src_n GREATER _src_dir_length_max) message(WARNING "MITK source code directory path length is too long (${_src_n} > ${_src_dir_length_max})." "Please move the MITK source code directory to a directory with a shorter path." ) endif() if(_bin_n GREATER _bin_dir_length_max) message(WARNING "MITK build directory path length is too long (${_bin_n} > ${_bin_dir_length_max})." "Please move the MITK build directory to a directory with a shorter path." ) endif() endif() #----------------------------------------------------------------------------- # See http://cmake.org/cmake/help/cmake-2-8-docs.html#section_Policies for details #----------------------------------------------------------------------------- set(project_policies CMP0001 # NEW: CMAKE_BACKWARDS_COMPATIBILITY should no longer be used. CMP0002 # NEW: Logical target names must be globally unique. CMP0003 # NEW: Libraries linked via full path no longer produce linker search paths. CMP0004 # NEW: Libraries linked may NOT have leading or trailing whitespace. CMP0005 # NEW: Preprocessor definition values are now escaped automatically. CMP0006 # NEW: Installing MACOSX_BUNDLE targets requires a BUNDLE DESTINATION. CMP0007 # NEW: List command no longer ignores empty elements. CMP0008 # NEW: Libraries linked by full-path must have a valid library file name. CMP0009 # NEW: FILE GLOB_RECURSE calls should not follow symlinks by default. CMP0010 # NEW: Bad variable reference syntax is an error. CMP0011 # NEW: Included scripts do automatic cmake_policy PUSH and POP. CMP0012 # NEW: if() recognizes numbers and boolean constants. CMP0013 # NEW: Duplicate binary directories are not allowed. CMP0014 # NEW: Input directories must have CMakeLists.txt ) foreach(policy ${project_policies}) if(POLICY ${policy}) cmake_policy(SET ${policy} NEW) endif() endforeach() #----------------------------------------------------------------------------- # Update CMake module path #------------------------------------------------------------------------------ set(CMAKE_MODULE_PATH ${MITK_SOURCE_DIR}/CMake ${CMAKE_MODULE_PATH} ) #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- include(mitkMacroEmptyExternalProject) include(mitkFunctionGenerateProjectXml) include(mitkFunctionSuppressWarnings) SUPPRESS_VC_DEPRECATED_WARNINGS() #----------------------------------------------------------------------------- # Output directories. #----------------------------------------------------------------------------- foreach(type LIBRARY RUNTIME ARCHIVE) # Make sure the directory exists if(DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY AND NOT EXISTS ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}) message("Creating directory MITK_CMAKE_${type}_OUTPUT_DIRECTORY: ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}") file(MAKE_DIRECTORY "${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}") endif() if(MITK_USE_SUPERBUILD) set(output_dir ${MITK_BINARY_DIR}/bin) if(NOT DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY) set(MITK_CMAKE_${type}_OUTPUT_DIRECTORY ${MITK_BINARY_DIR}/MITK-build/bin) endif() else() if(NOT DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY) set(output_dir ${MITK_BINARY_DIR}/bin) else() set(output_dir ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}) endif() endif() set(CMAKE_${type}_OUTPUT_DIRECTORY ${output_dir} CACHE INTERNAL "Single output directory for building all libraries.") mark_as_advanced(CMAKE_${type}_OUTPUT_DIRECTORY) endforeach() #----------------------------------------------------------------------------- # Additional MITK Options (also shown during superbuild) #----------------------------------------------------------------------------- option(BUILD_SHARED_LIBS "Build MITK with shared libraries" ON) option(WITH_COVERAGE "Enable/Disable coverage" OFF) option(BUILD_TESTING "Test the project" ON) option(MITK_BUILD_ALL_APPS "Build all MITK applications" OFF) option(MITK_BUILD_TUTORIAL "Build the MITK tutorial" ON) option(MITK_USE_Boost "Use the Boost C++ library" OFF) option(MITK_USE_BLUEBERRY "Build the BlueBerry platform" ON) option(MITK_USE_CTK "Use CTK in MITK" ${MITK_USE_BLUEBERRY}) option(MITK_USE_QT "Use Nokia's Qt library" ${MITK_USE_CTK}) option(MITK_USE_DCMTK "EXEPERIMENTAL, superbuild only: Use DCMTK in MITK" OFF) option(MITK_USE_OpenCV "Use Intel's OpenCV library" OFF) option(MITK_USE_Python "Use Python wrapping in MITK" OFF) set(MITK_USE_CableSwig ${MITK_USE_Python}) mark_as_advanced(MITK_BUILD_ALL_APPS MITK_USE_CTK MITK_USE_DCMTK ) if(MITK_USE_Boost) option(MITK_USE_SYSTEM_Boost "Use the system Boost" OFF) set(MITK_USE_Boost_LIBRARIES "" CACHE STRING "A semi-colon separated list of required Boost libraries") endif() if(MITK_USE_BLUEBERRY) option(MITK_BUILD_ALL_PLUGINS "Build all MITK plugins" OFF) mark_as_advanced(MITK_BUILD_ALL_PLUGINS) if(NOT MITK_USE_CTK) message("Forcing MITK_USE_CTK to ON because of MITK_USE_BLUEBERRY") set(MITK_USE_CTK ON CACHE BOOL "Use CTK in MITK" FORCE) endif() endif() if(MITK_USE_CTK AND NOT MITK_USE_QT) message("Forcing MITK_USE_QT to ON because of MITK_USE_CTK") set(MITK_USE_QT ON CACHE BOOL "Use Nokia's Qt library in MITK" FORCE) endif() if(MITK_USE_QT) # find the package at the very beginning, so that QT4_FOUND is available find_package(Qt4 4.6.2 REQUIRED) endif() # Customize the default pixel types for multiplex macros set(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES "int, unsigned int, short, unsigned short, char, unsigned char" CACHE STRING "List of integral pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES "double, float" CACHE STRING "List of floating pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES "" CACHE STRING "List of composite pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_DIMENSIONS "2,3" CACHE STRING "List of dimensions used in AccessByItk and InstantiateAccessFunction macros") mark_as_advanced(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES MITK_ACCESSBYITK_DIMENSIONS ) # consistency checks if(NOT MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES) set(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES "int, unsigned int, short, unsigned short, char, unsigned char" CACHE STRING "List of integral pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES) set(MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES "double, float" CACHE STRING "List of floating pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_DIMENSIONS) set(MITK_ACCESSBYITK_DIMENSIONS "2,3" CACHE STRING "List of dimensions used in AccessByItk and InstantiateAccessFunction macros") endif() #----------------------------------------------------------------------------- # Additional CXX/C Flags #----------------------------------------------------------------------------- set(ADDITIONAL_C_FLAGS "" CACHE STRING "Additional C Flags") mark_as_advanced(ADDITIONAL_C_FLAGS) set(ADDITIONAL_CXX_FLAGS "" CACHE STRING "Additional CXX Flags") mark_as_advanced(ADDITIONAL_CXX_FLAGS) #----------------------------------------------------------------------------- # Project.xml #----------------------------------------------------------------------------- # A list of topologically ordered targets set(CTEST_PROJECT_SUBPROJECTS) if(MITK_USE_BLUEBERRY) list(APPEND CTEST_PROJECT_SUBPROJECTS BlueBerry) endif() list(APPEND CTEST_PROJECT_SUBPROJECTS MITK-Core MITK-CoreUI MITK-IGT MITK-ToF MITK-DTI MITK-Registration MITK-Modules # all modules not contained in a specific subproject MITK-Plugins # all plugins not contained in a specific subproject Unlabeled # special "subproject" catching all unlabeled targets and tests ) # Configure CTestConfigSubProject.cmake that could be used by CTest scripts configure_file(${MITK_SOURCE_DIR}/CTestConfigSubProject.cmake.in ${MITK_BINARY_DIR}/CTestConfigSubProject.cmake) if(CTEST_PROJECT_ADDITIONAL_TARGETS) # those targets will be executed at the end of the ctest driver script # and they also get their own subproject label set(subproject_list "${CTEST_PROJECT_SUBPROJECTS};${CTEST_PROJECT_ADDITIONAL_TARGETS}") else() set(subproject_list "${CTEST_PROJECT_SUBPROJECTS}") endif() # Generate Project.xml file expected by the CTest driver script mitkFunctionGenerateProjectXml(${MITK_BINARY_DIR} MITK "${subproject_list}" ${MITK_USE_SUPERBUILD}) #----------------------------------------------------------------------------- # Superbuild script #----------------------------------------------------------------------------- if(MITK_USE_SUPERBUILD) include("${CMAKE_CURRENT_SOURCE_DIR}/SuperBuild.cmake") return() endif() #***************************************************************************** #**************************** END OF SUPERBUILD **************************** #***************************************************************************** #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- include(CheckCXXSourceCompiles) include(mitkFunctionCheckCompilerFlags) include(mitkFunctionGetGccVersion) include(MacroParseArguments) include(mitkFunctionSuppressWarnings) # includes several functions include(mitkFunctionOrganizeSources) include(mitkFunctionGetVersion) include(mitkFunctionCreateWindowsBatchScript) include(mitkFunctionInstallProvisioningFiles) include(mitkFunctionCompileSnippets) include(mitkMacroCreateModuleConf) include(mitkMacroCreateModule) include(mitkMacroCheckModule) include(mitkMacroCreateModuleTests) include(mitkFunctionAddCustomModuleTest) include(mitkMacroUseModule) include(mitkMacroMultiplexPicType) include(mitkMacroInstall) include(mitkMacroInstallHelperApp) include(mitkMacroInstallTargets) include(mitkMacroGenerateToolsLibrary) include(mitkMacroGetLinuxDistribution) #----------------------------------------------------------------------------- # Prerequesites #----------------------------------------------------------------------------- find_package(ITK REQUIRED) find_package(VTK REQUIRED) if(ITK_USE_SYSTEM_GDCM) find_package(GDCM PATHS ${ITK_GDCM_DIR} REQUIRED) endif() #----------------------------------------------------------------------------- # Set MITK specific options and variables (NOT available during superbuild) #----------------------------------------------------------------------------- # ASK THE USER TO SHOW THE CONSOLE WINDOW FOR CoreApp and ExtApp option(MITK_SHOW_CONSOLE_WINDOW "Use this to enable or disable the console window when starting MITK GUI Applications" ON) mark_as_advanced(MITK_SHOW_CONSOLE_WINDOW) # TODO: check if necessary option(USE_ITKZLIB "Use the ITK zlib for pic compression." ON) mark_as_advanced(USE_ITKZLIB) if(NOT MITK_FAST_TESTING) if(DEFINED MITK_CTEST_SCRIPT_MODE AND (MITK_CTEST_SCRIPT_MODE STREQUAL "continuous" OR MITK_CTEST_SCRIPT_MODE STREQUAL "experimental") ) set(MITK_FAST_TESTING 1) endif() endif() #----------------------------------------------------------------------------- # Get MITK version info #----------------------------------------------------------------------------- mitkFunctionGetVersion(${MITK_SOURCE_DIR} MITK) #----------------------------------------------------------------------------- # Installation preparation # # These should be set before any MITK install macros are used #----------------------------------------------------------------------------- # on Mac OSX all BlueBerry plugins get copied into every # application bundle (.app directory) specified here if(APPLE) if(MITK_BUILD_org.mitk.gui.qt.extapplication) set(MACOSX_BUNDLE_NAMES ${MACOSX_BUNDLE_NAMES} ExtApp) endif() if(MITK_BUILD_org.mitk.gui.qt.application) set(MACOSX_BUNDLE_NAMES ${MACOSX_BUNDLE_NAMES} CoreApp) endif() if(MITK_BUILD_org.mitk.gui.qt.diffusionimagingapp) set(MACOSX_BUNDLE_NAMES ${MACOSX_BUNDLE_NAMES} mitkDiffusion) endif() endif(APPLE) #----------------------------------------------------------------------------- # Set symbol visibility Flags #----------------------------------------------------------------------------- # MinGW does not export all symbols automatically, so no need to set flags if(CMAKE_COMPILER_IS_GNUCXX AND NOT MINGW) set(VISIBILITY_CXX_FLAGS ) #"-fvisibility=hidden -fvisibility-inlines-hidden") endif() #----------------------------------------------------------------------------- # Set coverage Flags #----------------------------------------------------------------------------- if(WITH_COVERAGE) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(coverage_flags "-g -fprofile-arcs -ftest-coverage -O0 -DNDEBUG") set(COVERAGE_CXX_FLAGS ${coverage_flags}) set(COVERAGE_C_FLAGS ${coverage_flags}) endif() endif() #----------------------------------------------------------------------------- # MITK C/CXX Flags #----------------------------------------------------------------------------- set(MITK_C_FLAGS "${COVERAGE_C_FLAGS} ${ADDITIONAL_C_FLAGS}") set(MITK_CXX_FLAGS "${VISIBILITY_CXX_FLAGS} ${COVERAGE_CXX_FLAGS} ${ADDITIONAL_CXX_FLAGS}") include(mitkSetupC++0xVariables) set(cflags ) if(WIN32) set(cflags "${cflags} -DPOCO_NO_UNWINDOWS -DWIN32_LEAN_AND_MEAN") endif() if(CMAKE_COMPILER_IS_GNUCXX) set(cflags "${cflags} -Wall -Wextra -Wpointer-arith -Winvalid-pch -Wcast-align -Wwrite-strings -D_FORTIFY_SOURCE=2") mitkFunctionCheckCompilerFlags("-fdiagnostics-show-option" cflags) mitkFunctionCheckCompilerFlags("-Wl,--no-undefined" cflags) mitkFunctionCheckCompilerFlags("-Wl,--as-needed" cflags) if(MITK_USE_C++0x) mitkFunctionCheckCompilerFlags("-std=c++0x" MITK_CXX_FLAGS) endif() mitkFunctionGetGccVersion(${CMAKE_CXX_COMPILER} GCC_VERSION) # With older version of gcc supporting the flag -fstack-protector-all, an extra dependency to libssp.so # is introduced. If gcc is smaller than 4.4.0 and the build type is Release let's not include the flag. # Doing so should allow to build package made for distribution using older linux distro. if(${GCC_VERSION} VERSION_GREATER "4.4.0" OR (CMAKE_BUILD_TYPE STREQUAL "Debug" AND ${GCC_VERSION} VERSION_LESS "4.4.0")) mitkFunctionCheckCompilerFlags("-fstack-protector-all" cflags) endif() if(MINGW) # suppress warnings about auto imported symbols set(MITK_CXX_FLAGS "-Wl,--enable-auto-import ${MITK_CXX_FLAGS}") # we need to define a Windows version set(MITK_CXX_FLAGS "-D_WIN32_WINNT=0x0500 ${MITK_CXX_FLAGS}") endif() #set(MITK_CXX_FLAGS "-Woverloaded-virtual -Wold-style-cast -Wstrict-null-sentinel -Wsign-promo ${MITK_CXX_FLAGS}") set(MITK_CXX_FLAGS "-Woverloaded-virtual -Wstrict-null-sentinel ${MITK_CXX_FLAGS}") endif() set(MITK_C_FLAGS "${cflags} ${MITK_C_FLAGS}") set(MITK_CXX_FLAGS "${cflags} ${MITK_CXX_FLAGS}") #----------------------------------------------------------------------------- # MITK Packages #----------------------------------------------------------------------------- set(MITK_MODULES_PACKAGE_DEPENDS_DIR ${MITK_SOURCE_DIR}/CMake/PackageDepends) set(MODULES_PACKAGE_DEPENDS_DIRS ${MITK_MODULES_PACKAGE_DEPENDS_DIR}) #----------------------------------------------------------------------------- # Testing #----------------------------------------------------------------------------- if(BUILD_TESTING) enable_testing() include(CTest) mark_as_advanced(TCL_TCLSH DART_ROOT) option(MITK_ENABLE_GUI_TESTING OFF "Enable the MITK GUI tests") # Setup file for setting custom ctest vars configure_file( CMake/CTestCustom.cmake.in ${MITK_BINARY_DIR}/CTestCustom.cmake @ONLY ) # Configuration for the CMake-generated test driver set(CMAKE_TESTDRIVER_EXTRA_INCLUDES "#include ") set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN " try {") set(CMAKE_TESTDRIVER_AFTER_TESTMAIN " } catch( std::exception & excp ) { fprintf(stderr,\"%s\\n\",excp.what()); return EXIT_FAILURE; } catch( ... ) { printf(\"Exception caught in the test driver\\n\"); return EXIT_FAILURE; } ") set(MITK_TEST_OUTPUT_DIR "${MITK_BINARY_DIR}/test_output") if(NOT EXISTS ${MITK_TEST_OUTPUT_DIR}) file(MAKE_DIRECTORY ${MITK_TEST_OUTPUT_DIR}) endif() # Test the external project template if(MITK_USE_BLUEBERRY) include(mitkTestProjectTemplate) endif() # Test the package target include(mitkPackageTest) endif() configure_file(mitkTestingConfig.h.in ${MITK_BINARY_DIR}/mitkTestingConfig.h) #----------------------------------------------------------------------------- # MITK_SUPERBUILD_BINARY_DIR #----------------------------------------------------------------------------- # If MITK_SUPERBUILD_BINARY_DIR isn't defined, it means MITK is *NOT* build using Superbuild. # In that specific case, MITK_SUPERBUILD_BINARY_DIR should default to MITK_BINARY_DIR if(NOT DEFINED MITK_SUPERBUILD_BINARY_DIR) set(MITK_SUPERBUILD_BINARY_DIR ${MITK_BINARY_DIR}) endif() #----------------------------------------------------------------------------- # Compile Utilities and set-up MITK variables #----------------------------------------------------------------------------- include(mitkSetupVariables) #----------------------------------------------------------------------------- # Cleanup #----------------------------------------------------------------------------- file(GLOB _MODULES_CONF_FILES ${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME}/*.cmake) if(_MODULES_CONF_FILES) file(REMOVE ${_MODULES_CONF_FILES}) endif() add_subdirectory(Utilities) if(MITK_USE_BLUEBERRY) # We need to hack a little bit because MITK applications may need # to enable certain BlueBerry plug-ins. However, these plug-ins # are validated separately from the MITK plug-ins and know nothing # about potential MITK plug-in dependencies of the applications. Hence # we cannot pass the MITK application list to the BlueBerry # ctkMacroSetupPlugins call but need to extract the BlueBerry dependencies # from the applications and set them explicitly. include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") foreach(mitk_app ${MITK_APPS}) # extract target_dir and option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 0 target_dir) list(GET target_info_list 1 option_name) # check if the application is enabled and if target_libraries.cmake exists if(${option_name} AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/target_libraries.cmake") include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/target_libraries.cmake") foreach(_target_dep ${target_libraries}) if(_target_dep MATCHES org_blueberry_) string(REPLACE _ . _app_bb_dep ${_target_dep}) # explicitly set the build option for the BlueBerry plug-in set(BLUEBERRY_BUILD_${_app_bb_dep} ON CACHE BOOL "Build the ${_app_bb_dep} plug-in") endif() endforeach() endif() endforeach() set(mbilog_DIR "${mbilog_BINARY_DIR}") if(MITK_BUILD_ALL_PLUGINS) set(BLUEBERRY_BUILD_ALL_PLUGINS ON) endif() add_subdirectory(BlueBerry) set(BlueBerry_DIR ${CMAKE_CURRENT_BINARY_DIR}/BlueBerry CACHE PATH "The directory containing a CMake configuration file for BlueBerry" FORCE) include(mitkMacroCreateCTKPlugin) endif() #----------------------------------------------------------------------------- # Set C/CXX Flags for MITK code #----------------------------------------------------------------------------- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MITK_CXX_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MITK_C_FLAGS}") if(MITK_USE_QT) add_definitions(-DQWT_DLL) endif() #----------------------------------------------------------------------------- # Add custom targets representing CDash subprojects #----------------------------------------------------------------------------- foreach(subproject ${CTEST_PROJECT_SUBPROJECTS}) if(NOT TARGET ${subproject} AND NOT subproject MATCHES "Unlabeled") add_custom_target(${subproject}) endif() endforeach() #----------------------------------------------------------------------------- # Add subdirectories #----------------------------------------------------------------------------- link_directories(${MITK_LINK_DIRECTORIES}) add_subdirectory(Core) add_subdirectory(Modules) if(MITK_USE_BLUEBERRY) find_package(BlueBerry REQUIRED) set(MITK_DEFAULT_SUBPROJECTS MITK-Plugins) # Plug-in testing (needs some work to be enabled again) if(BUILD_TESTING) include(berryTestingHelpers) set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CoreApp") get_target_property(_is_macosx_bundle CoreApp MACOSX_BUNDLE) if(APPLE AND _is_macosx_bundle) set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CoreApp.app/Contents/MacOS/CoreApp") endif() set(BLUEBERRY_TEST_APP_ID "org.mitk.qt.coreapplication") endif() include("${CMAKE_CURRENT_SOURCE_DIR}/Plugins/PluginList.cmake") set(mitk_plugins_fullpath ) foreach(mitk_plugin ${MITK_EXT_PLUGINS}) list(APPEND mitk_plugins_fullpath Plugins/${mitk_plugin}) endforeach() if(EXISTS ${MITK_PRIVATE_MODULES}/PluginList.cmake) include(${MITK_PRIVATE_MODULES}/PluginList.cmake) foreach(mitk_plugin ${MITK_PRIVATE_PLUGINS}) list(APPEND mitk_plugins_fullpath ${MITK_PRIVATE_MODULES}/${mitk_plugin}) endforeach() endif() # Specify which plug-ins belong to this project macro(GetMyTargetLibraries all_target_libraries varname) set(re_ctkplugin_mitk "^org_mitk_[a-zA-Z0-9_]+$") set(re_ctkplugin_bb "^org_blueberry_[a-zA-Z0-9_]+$") set(_tmp_list) list(APPEND _tmp_list ${all_target_libraries}) ctkMacroListFilter(_tmp_list re_ctkplugin_mitk re_ctkplugin_bb OUTPUT_VARIABLE ${varname}) endmacro() # Get infos about application directories and build options include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") set(mitk_apps_fullpath ) foreach(mitk_app ${MITK_APPS}) list(APPEND mitk_apps_fullpath "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${mitk_app}") endforeach() ctkMacroSetupPlugins(${mitk_plugins_fullpath} BUILD_OPTION_PREFIX MITK_BUILD_ APPS ${mitk_apps_fullpath} BUILD_ALL ${MITK_BUILD_ALL_PLUGINS} COMPACT_OPTIONS) set(MITK_PLUGIN_USE_FILE "${MITK_BINARY_DIR}/MitkPluginUseFile.cmake") if(${PROJECT_NAME}_PLUGIN_LIBRARIES) ctkFunctionGeneratePluginUseFile(${MITK_PLUGIN_USE_FILE}) else() file(REMOVE ${MITK_PLUGIN_USE_FILE}) set(MITK_PLUGIN_USE_FILE ) endif() endif() # Construct a list of paths containing runtime directories # for MITK applications on Windows set(MITK_RUNTIME_PATH "${VTK_LIBRARY_DIRS}/%VS_BUILD_TYPE%;${ITK_LIBRARY_DIRS}/%VS_BUILD_TYPE%;${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/%VS_BUILD_TYPE%" ) if(QT4_FOUND) set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${QT_LIBRARY_DIR}/../bin") endif() if(MITK_USE_BLUEBERRY) set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${CTK_RUNTIME_LIBRARY_DIRS}/%VS_BUILD_TYPE%") if(DEFINED CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY) if(IS_ABSOLUTE "${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}/%VS_BUILD_TYPE%") else() set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}/%VS_BUILD_TYPE%") endif() else() set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/plugins/%VS_BUILD_TYPE%") endif() endif() if(GDCM_DIR) set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${GDCM_DIR}/bin/%VS_BUILD_TYPE%") endif() if(OpenCV_DIR) set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${OpenCV_DIR}/bin/%VS_BUILD_TYPE%") endif() # DCMTK is statically build #if(DCMTK_DIR) # set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${DCMTK_DIR}/bin/%VS_BUILD_TYPE%") #endif() if(MITK_USE_Boost AND MITK_USE_Boost_LIBRARIES AND NOT MITK_USE_SYSTEM_Boost) set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${Boost_LIBRARY_DIRS}") endif() #----------------------------------------------------------------------------- # Python Wrapping #----------------------------------------------------------------------------- set(MITK_WRAPPING_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Wrapping) set(MITK_WRAPPING_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/Wrapping) option(MITK_USE_Python "Build cswig Python wrapper support (requires CableSwig)." OFF) if(MITK_USE_Python) add_subdirectory(Wrapping) endif() #----------------------------------------------------------------------------- # Documentation #----------------------------------------------------------------------------- add_subdirectory(Documentation) #----------------------------------------------------------------------------- # Installation #----------------------------------------------------------------------------- # set MITK cpack variables +# These are the default variables, which can be overwritten ( see below ) include(mitkSetupCPack) -if(MITK_BUILD_org.mitk.gui.qt.application) - list(APPEND CPACK_CREATE_DESKTOP_LINKS "CoreApp") -endif() -if(MITK_BUILD_org.mitk.gui.qt.extapplication) - list(APPEND CPACK_CREATE_DESKTOP_LINKS "ExtApp") -endif() +set(use_default_config ON) -if(MITK_BUILD_org.mitk.gui.qt.diffusionimagingapp) - include(CMake/CPackOptionsDiffusion.cmake) - configure_file(${PROJECT_SOURCE_DIR}/CMake/CPackDiffusionConfig.cmake.in ${PROJECT_BINARY_DIR}/CPackDiffusionConfig.cmake @ONLY) - set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/CPackDiffusionConfig.cmake") -endif() +# MITK_APPS is set in Applications/AppList.cmake (included somewhere above +# if MITK_USE_BLUEBERRY is set to ON). +if(MITK_APPS) + + set(activated_apps_no 0) + list(LENGTH MITK_APPS app_count) + + # Check how many apps have been enabled + # If more than one app has been activated, the we use the + # default CPack configuration. Otherwise that apps configuration + # will be used, if present. + foreach(mitk_app ${MITK_APPS}) + # extract option_name + string(REPLACE "^^" "\\;" target_info ${mitk_app}) + set(target_info_list ${target_info}) + list(GET target_info_list 1 option_name) + # check if the application is enabled + if(${option_name}) + MATH(EXPR activated_apps_no "${activated_apps_no} + 1") + endif() + endforeach() + + if(app_count EQUAL 1 AND (activated_apps_no EQUAL 1 OR MITK_BUILD_ALL_APPS)) + # Corner case if there is only one app in total + set(use_project_cpack ON) + elseif(activated_apps_no EQUAL 1 AND NOT MITK_BUILD_ALL_APPS) + # Only one app is enabled (no "build all" flag set) + set(use_project_cpack ON) + else() + # Less or more then one app is enabled + set(use_project_cpack OFF) + endif() + foreach(mitk_app ${MITK_APPS}) + # extract target_dir and option_name + string(REPLACE "^^" "\\;" target_info ${mitk_app}) + set(target_info_list ${target_info}) + list(GET target_info_list 0 target_dir) + list(GET target_info_list 1 option_name) + # check if the application is enabled + if(${option_name}) + # check whether application specific configuration files will be used + if(use_project_cpack) + # use files if they exist + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/CPackOptions.cmake") + include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/CPackOptions.cmake") + endif() -configure_file(${MITK_SOURCE_DIR}/MITKCPackOptions.cmake.in - ${MITK_BINARY_DIR}/MITKCPackOptions.cmake @ONLY) -set(CPACK_PROJECT_CONFIG_FILE "${MITK_BINARY_DIR}/MITKCPackOptions.cmake") + if(EXISTS "${PROJECT_SOURCE_DIR}/Applications/${target_dir}/CPackConfig.cmake.in") + set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/Applications/${target_dir}/CPackConfig.cmake") + configure_file(${PROJECT_SOURCE_DIR}/Applications/${target_dir}/CPackConfig.cmake.in + ${CPACK_PROJECT_CONFIG_FILE} @ONLY) + set(use_default_config OFF) + endif() + endif() + # add link to the list + list(APPEND CPACK_CREATE_DESKTOP_LINKS "${target_dir}") + endif() + endforeach() + +endif() + +# if no application specific configuration file was used, use default +if(use_default_config) + configure_file(${MITK_SOURCE_DIR}/MITKCPackOptions.cmake.in + ${MITK_BINARY_DIR}/MITKCPackOptions.cmake @ONLY) + set(CPACK_PROJECT_CONFIG_FILE "${MITK_BINARY_DIR}/MITKCPackOptions.cmake") +endif() # include CPack model once all variables are set include(CPack) # Additional installation rules include(mitkInstallRules) #----------------------------------------------------------------------------- # Last configuration steps #----------------------------------------------------------------------------- set(MITK_EXPORTS_FILE "${MITK_BINARY_DIR}/MitkExports.cmake") file(REMOVE ${MITK_EXPORTS_FILE}) if(MITK_USE_BLUEBERRY) # This is for installation support of external projects depending on # MITK plugins. The export file should not be used for linking to MITK # libraries without using LINK_DIRECTORIES, since the exports are incomplete # yet(depending libraries are not exported). if(MITK_PLUGIN_LIBRARIES) export(TARGETS ${MITK_PLUGIN_LIBRARIES} APPEND FILE ${MITK_EXPORTS_FILE}) endif() endif() configure_file(${MITK_SOURCE_DIR}/CMake/ToolExtensionITKFactory.cpp.in ${MITK_BINARY_DIR}/ToolExtensionITKFactory.cpp.in COPYONLY) configure_file(${MITK_SOURCE_DIR}/CMake/ToolExtensionITKFactoryLoader.cpp.in ${MITK_BINARY_DIR}/ToolExtensionITKFactoryLoader.cpp.in COPYONLY) configure_file(${MITK_SOURCE_DIR}/CMake/ToolGUIExtensionITKFactory.cpp.in ${MITK_BINARY_DIR}/ToolGUIExtensionITKFactory.cpp.in COPYONLY) configure_file(mitkVersion.h.in ${MITK_BINARY_DIR}/mitkVersion.h) configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h) set(VECMATH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/vecmath) set(IPFUNC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ipFunc) set(UTILITIES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities) file(GLOB _MODULES_CONF_FILES RELATIVE ${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME} ${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME}/*.cmake) set(MITK_MODULE_NAMES) foreach(_module ${_MODULES_CONF_FILES}) string(REPLACE Config.cmake "" _module_name ${_module}) list(APPEND MITK_MODULE_NAMES ${_module_name}) endforeach() configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h) configure_file(MITKConfig.cmake.in ${MITK_BINARY_DIR}/MITKConfig.cmake @ONLY) # If we are under Windows, create two batch files which correctly # set up the environment for the application and for Visual Studio if(WIN32) include(mitkFunctionCreateWindowsBatchScript) set(VS_SOLUTION_FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.sln") foreach(VS_BUILD_TYPE debug release) mitkFunctionCreateWindowsBatchScript("${MITK_SOURCE_DIR}/CMake/StartVS.bat.in" ${PROJECT_BINARY_DIR}/StartVS_${VS_BUILD_TYPE}.bat ${VS_BUILD_TYPE}) endforeach() endif(WIN32) #----------------------------------------------------------------------------- # MITK Applications #----------------------------------------------------------------------------- # This must come after MITKConfig.h was generated, since applications # might do a find_package(MITK REQUIRED). add_subdirectory(Applications) diff --git a/Core/Code/CMakeLists.txt b/Core/Code/CMakeLists.txt index ecddfa4002..729fde0d47 100644 --- a/Core/Code/CMakeLists.txt +++ b/Core/Code/CMakeLists.txt @@ -1,80 +1,80 @@ -find_package(OpenGL) -if(NOT OPENGL_FOUND) - message("GL is required for MITK rendering") -endif(NOT OPENGL_FOUND ) +#FIND_PACKAGE(OpenGL) +#IF(NOT OPENGL_FOUND) +# MESSAGE("GL is required for MITK rendering") +#ENDIF(NOT OPENGL_FOUND ) # Configure the C++ Micro Services Code for MITK find_package(ITK REQUIRED) include(${ITK_USE_FILE}) set(US_NAMESPACE "mitk") set(US_HEADER_PREFIX "mitk") set(US_BASECLASS_NAME "itk::LightObject") set(US_BASECLASS_HEADER "itkLightObject.h") set(US_BASECLASS_PACKAGE "ITK") set(US_ENABLE_THREADING_SUPPORT 1) set(US_EMBEDDING_LIBRARY Mitk) set(US_BUILD_TESTING ${BUILD_TESTING}) if(BUILD_TESTING) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Testing) set(US_BASECLASS_HEADER "uServicesBaseObject.h") set(US_TEST_LABELS MITK-Core) endif() add_subdirectory(CppMicroServices) include(${CMAKE_CURRENT_BINARY_DIR}/CppMicroServices/CppMicroServicesConfig.cmake) set(TOOL_CPPS "") MITK_CREATE_MODULE( Mitk INCLUDE_DIRS ${CppMicroServices_INCLUDE_DIRS} Algorithms DataManagement Controllers Interactions Interfaces IO Rendering ${MITK_BINARY_DIR} INTERNAL_INCLUDE_DIRS ${OPENGL_INCLUDE_DIR} ${IPSEGMENTATION_INCLUDE_DIR} ${ANN_INCLUDE_DIR} ${CppMicroServices_INTERNAL_INCLUDE_DIRS} DEPENDS mbilog tinyxml - DEPENDS_INTERNAL IIL4MITK pic2vtk + DEPENDS_INTERNAL pic2vtk #IIL4MITK PACKAGE_DEPENDS ITK VTK EXPORT_DEFINE MITK_CORE_EXPORT ) # this is needed for libraries which link to Mitk and need # symbols from explicitly instantiated templates like # mitk::SurfaceVtkWriter which is referenced in # QmitkCommonFunctionality in the QmitkExt library. if(MINGW) get_target_property(_mitkCore_MINGW_linkflags Mitk LINK_FLAGS) if(NOT _mitkCore_MINGW_linkflags) set(_mitkCore_MINGW_linkflags "") endif(NOT _mitkCore_MINGW_linkflags) set_target_properties(Mitk PROPERTIES LINK_FLAGS "${_mitkCore_MINGW_linkflags} -Wl,--export-all-symbols") endif(MINGW) # replacing Mitk by Mitk [due to removing the PROVIDES macro -target_link_libraries(Mitk ${LIBRARIES_FOR_${KITNAME}_CORE} ${IPFUNC_LIBRARY} ipSegmentation ann) -target_link_libraries(Mitk ${OPENGL_LIBRARIES} ) -target_link_libraries(Mitk gdcmCommon gdcmIOD gdcmDSED) +TARGET_LINK_LIBRARIES(Mitk ${LIBRARIES_FOR_${KITNAME}_CORE} ${IPFUNC_LIBRARY} ipSegmentation ann) +#TARGET_LINK_LIBRARIES(Mitk ${OPENGL_LIBRARIES} ) +TARGET_LINK_LIBRARIES(Mitk gdcmCommon gdcmIOD gdcmDSED) if(MSVC_IDE OR MSVC_VERSION OR MINGW) target_link_libraries(Mitk psapi.lib) endif(MSVC_IDE OR MSVC_VERSION OR MINGW) # verify ITK has been built with GDCM >= 2.0.14 set(GDCM_FULL_VERSION "${GDCM_MAJOR_VERSION}.${GDCM_MINOR_VERSION}.${GDCM_BUILD_VERSION}") set(MITK_REQUIRED_GDCM_VERSION "2.0.14") if(GDCM_FULL_VERSION VERSION_LESS MITK_REQUIRED_GDCM_VERSION) message(SEND_ERROR "Mitk: MITK requires ITK with at least GDCM version ${MITK_REQUIRED_GDCM_VERSION}.\nFound version ${GDCM_FULL_VERSION} (GDCM NOT found if you don't see a version here)") else(GDCM_FULL_VERSION VERSION_LESS MITK_REQUIRED_GDCM_VERSION) message(STATUS "Mitk: Found GDCM version ${GDCM_FULL_VERSION}") endif(GDCM_FULL_VERSION VERSION_LESS MITK_REQUIRED_GDCM_VERSION) # build tests? option(BUILD_TESTING "Build the MITK Core tests." ON) if(BUILD_TESTING) enable_testing() add_subdirectory(Testing) endif(BUILD_TESTING) diff --git a/Core/Code/IO/mitkDicomSeriesReader.cpp b/Core/Code/IO/mitkDicomSeriesReader.cpp index 4dedd37388..66ecb910a6 100644 --- a/Core/Code/IO/mitkDicomSeriesReader.cpp +++ b/Core/Code/IO/mitkDicomSeriesReader.cpp @@ -1,1117 +1,1129 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ // uncomment for learning more about the internal sorting mechanisms //#define MBILOG_ENABLE_DEBUG #include #include #include #include #include #include #include #include "mitkProperties.h" namespace mitk { typedef itk::GDCMSeriesFileNames DcmFileNamesGeneratorType; const DicomSeriesReader::TagToPropertyMapType& DicomSeriesReader::GetDICOMTagsToMITKPropertyMap() { static bool initialized = false; static TagToPropertyMapType dictionary; if (!initialized) { /* Selection criteria: - no sequences because we cannot represent that - nothing animal related (specied, breed registration number), MITK focusses on human medical image processing. - only general attributes so far When extending this, we should make use of a real dictionary (GDCM/DCMTK and lookup the tag names there) */ // Patient module dictionary["0010|0010"] = "dicom.patient.PatientsName"; dictionary["0010|0020"] = "dicom.patient.PatientID"; dictionary["0010|0030"] = "dicom.patient.PatientsBirthDate"; dictionary["0010|0040"] = "dicom.patient.PatientsSex"; dictionary["0010|0032"] = "dicom.patient.PatientsBirthTime"; dictionary["0010|1000"] = "dicom.patient.OtherPatientIDs"; dictionary["0010|1001"] = "dicom.patient.OtherPatientNames"; dictionary["0010|2160"] = "dicom.patient.EthnicGroup"; dictionary["0010|4000"] = "dicom.patient.PatientComments"; dictionary["0012|0062"] = "dicom.patient.PatientIdentityRemoved"; dictionary["0012|0063"] = "dicom.patient.DeIdentificationMethod"; // General Study module dictionary["0020|000d"] = "dicom.study.StudyInstanceUID"; dictionary["0008|0020"] = "dicom.study.StudyDate"; dictionary["0008|0030"] = "dicom.study.StudyTime"; dictionary["0008|0090"] = "dicom.study.ReferringPhysiciansName"; dictionary["0020|0010"] = "dicom.study.StudyID"; dictionary["0008|0050"] = "dicom.study.AccessionNumber"; dictionary["0008|1030"] = "dicom.study.StudyDescription"; dictionary["0008|1048"] = "dicom.study.PhysiciansOfRecord"; dictionary["0008|1060"] = "dicom.study.NameOfPhysicianReadingStudy"; // General Series module dictionary["0008|0060"] = "dicom.series.Modality"; dictionary["0020|000e"] = "dicom.series.SeriesInstanceUID"; dictionary["0020|0011"] = "dicom.series.SeriesNumber"; dictionary["0020|0060"] = "dicom.series.Laterality"; dictionary["0008|0021"] = "dicom.series.SeriesDate"; dictionary["0008|0031"] = "dicom.series.SeriesTime"; dictionary["0008|1050"] = "dicom.series.PerformingPhysiciansName"; dictionary["0018|1030"] = "dicom.series.ProtocolName"; dictionary["0008|103e"] = "dicom.series.SeriesDescription"; dictionary["0008|1070"] = "dicom.series.OperatorsName"; dictionary["0018|0015"] = "dicom.series.BodyPartExamined"; dictionary["0018|5100"] = "dicom.series.PatientPosition"; dictionary["0028|0108"] = "dicom.series.SmallestPixelValueInSeries"; dictionary["0028|0109"] = "dicom.series.LargestPixelValueInSeries"; // VOI LUT module dictionary["0028|1050"] = "dicom.voilut.WindowCenter"; dictionary["0028|1051"] = "dicom.voilut.WindowWidth"; dictionary["0028|1055"] = "dicom.voilut.WindowCenterAndWidthExplanation"; initialized = true; } return dictionary; } DataNode::Pointer DicomSeriesReader::LoadDicomSeries(const StringContainer &filenames, bool sort, bool check_4d, UpdateCallBackMethod callback) { DataNode::Pointer node = DataNode::New(); if (DicomSeriesReader::LoadDicomSeries(filenames, *node, sort, check_4d, callback)) { if( filenames.empty() ) { return NULL; } return node; } else { return NULL; } } bool DicomSeriesReader::LoadDicomSeries(const StringContainer &filenames, DataNode &node, bool sort, bool check_4d, UpdateCallBackMethod callback) { if( filenames.empty() ) { MITK_WARN << "Calling LoadDicomSeries with empty filename string container. Probably invalid application logic."; node.SetData(NULL); return true; // this is not actually an error but the result is very simple } DcmIoType::Pointer io = DcmIoType::New(); try { if (io->CanReadFile(filenames.front().c_str())) { io->SetFileName(filenames.front().c_str()); io->ReadImageInformation(); switch (io->GetComponentType()) { case DcmIoType::UCHAR: DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); break; case DcmIoType::CHAR: DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); break; case DcmIoType::USHORT: DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); break; case DcmIoType::SHORT: DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); break; case DcmIoType::UINT: DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); break; case DcmIoType::INT: DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); break; case DcmIoType::ULONG: DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); break; case DcmIoType::LONG: DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); break; case DcmIoType::FLOAT: DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); break; case DcmIoType::DOUBLE: DicomSeriesReader::LoadDicom(filenames, node, sort, check_4d, callback); break; default: MITK_ERROR << "Found unsupported DICOM pixel type: (enum value) " << io->GetComponentType(); } if (node.GetData()) { return true; } } } catch(itk::MemoryAllocationError& e) { MITK_ERROR << "Out of memory. Cannot load DICOM series: " << e.what(); } catch(std::exception& e) { MITK_ERROR << "Error encountered when loading DICOM series:" << e.what(); } catch(...) { MITK_ERROR << "Unspecified error encountered when loading DICOM series."; } return false; } bool DicomSeriesReader::IsDicom(const std::string &filename) { DcmIoType::Pointer io = DcmIoType::New(); return io->CanReadFile(filename.c_str()); } bool DicomSeriesReader::IsPhilips3DDicom(const std::string &filename) { DcmIoType::Pointer io = DcmIoType::New(); if (io->CanReadFile(filename.c_str())) { //Look at header Tag 3001,0010 if it is "Philips3D" gdcm::Reader reader; reader.SetFileName(filename.c_str()); reader.Read(); gdcm::DataSet &data_set = reader.GetFile().GetDataSet(); gdcm::StringFilter sf; sf.SetFile(reader.GetFile()); if (data_set.FindDataElement(gdcm::Tag(0x3001, 0x0010)) && (sf.ToString(gdcm::Tag(0x3001, 0x0010)) == "Philips3D ")) { return true; } } return false; } bool DicomSeriesReader::ReadPhilips3DDicom(const std::string &filename, mitk::Image::Pointer output_image) { // Now get PhilipsSpecific Tags gdcm::PixmapReader reader; reader.SetFileName(filename.c_str()); reader.Read(); gdcm::DataSet &data_set = reader.GetFile().GetDataSet(); gdcm::StringFilter sf; sf.SetFile(reader.GetFile()); gdcm::Attribute<0x0028,0x0011> dimTagX; // coloumns || sagittal gdcm::Attribute<0x3001,0x1001, gdcm::VR::UL, gdcm::VM::VM1> dimTagZ; //I have no idea what is VM1. // (Philips specific) // transversal gdcm::Attribute<0x0028,0x0010> dimTagY; // rows || coronal gdcm::Attribute<0x0028,0x0008> dimTagT; // how many frames gdcm::Attribute<0x0018,0x602c> spaceTagX; // Spacing in X , unit is "physicalTagx" (usually centimeter) gdcm::Attribute<0x0018,0x602e> spaceTagY; gdcm::Attribute<0x3001,0x1003, gdcm::VR::FD, gdcm::VM::VM1> spaceTagZ; // (Philips specific) gdcm::Attribute<0x0018,0x6024> physicalTagX; // if 3, then spacing params are centimeter gdcm::Attribute<0x0018,0x6026> physicalTagY; gdcm::Attribute<0x3001,0x1002, gdcm::VR::US, gdcm::VM::VM1> physicalTagZ; // (Philips specific) dimTagX.Set(data_set); dimTagY.Set(data_set); dimTagZ.Set(data_set); dimTagT.Set(data_set); spaceTagX.Set(data_set); spaceTagY.Set(data_set); spaceTagZ.Set(data_set); physicalTagX.Set(data_set); physicalTagY.Set(data_set); physicalTagZ.Set(data_set); unsigned int dimX = dimTagX.GetValue(), dimY = dimTagY.GetValue(), dimZ = dimTagZ.GetValue(), dimT = dimTagT.GetValue(), physicalX = physicalTagX.GetValue(), physicalY = physicalTagY.GetValue(), physicalZ = physicalTagZ.GetValue(); float spaceX = spaceTagX.GetValue(), spaceY = spaceTagY.GetValue(), spaceZ = spaceTagZ.GetValue(); if (physicalX == 3) // spacing parameter in cm, have to convert it to mm. spaceX = spaceX * 10; if (physicalY == 3) // spacing parameter in cm, have to convert it to mm. spaceY = spaceY * 10; if (physicalZ == 3) // spacing parameter in cm, have to convert it to mm. spaceZ = spaceZ * 10; // Ok, got all necessary Tags! // Now read Pixeldata (7fe0,0010) X x Y x Z x T Elements const gdcm::Pixmap &pixels = reader.GetPixmap(); gdcm::RAWCodec codec; codec.SetPhotometricInterpretation(gdcm::PhotometricInterpretation::MONOCHROME2); codec.SetPixelFormat(pixels.GetPixelFormat()); codec.SetPlanarConfiguration(0); gdcm::DataElement out; codec.Decode(data_set.GetDataElement(gdcm::Tag(0x7fe0, 0x0010)), out); const gdcm::ByteValue *bv = out.GetByteValue(); const char *new_pixels = bv->GetPointer(); // Create MITK Image + Geometry typedef itk::Image ImageType; //Pixeltype might be different sometimes? Maybe read it out from header ImageType::RegionType myRegion; ImageType::SizeType mySize; ImageType::IndexType myIndex; ImageType::SpacingType mySpacing; ImageType::Pointer imageItk = ImageType::New(); mySpacing[0] = spaceX; mySpacing[1] = spaceY; mySpacing[2] = spaceZ; mySpacing[3] = 1; myIndex[0] = 0; myIndex[1] = 0; myIndex[2] = 0; myIndex[3] = 0; mySize[0] = dimX; mySize[1] = dimY; mySize[2] = dimZ; mySize[3] = dimT; myRegion.SetSize( mySize); myRegion.SetIndex( myIndex ); imageItk->SetSpacing(mySpacing); imageItk->SetRegions( myRegion); imageItk->Allocate(); imageItk->FillBuffer(0); itk::ImageRegionIterator iterator(imageItk, imageItk->GetLargestPossibleRegion()); iterator.GoToBegin(); unsigned long pixCount = 0; unsigned long planeSize = dimX*dimY; unsigned long planeCount = 0; unsigned long timeCount = 0; unsigned long numberOfSlices = dimZ; while (!iterator.IsAtEnd()) { unsigned long adressedPixel = pixCount + (numberOfSlices-1-planeCount)*planeSize // add offset to adress the first pixel of current plane + timeCount*numberOfSlices*planeSize; // add time offset iterator.Set( new_pixels[ adressedPixel ] ); pixCount++; ++iterator; if (pixCount == planeSize) { pixCount = 0; planeCount++; } if (planeCount == numberOfSlices) { planeCount = 0; timeCount++; } if (timeCount == dimT) { break; } } mitk::CastToMitkImage(imageItk, output_image); return true; // actually never returns false yet.. but exception possible } DicomSeriesReader::TwoStringContainers DicomSeriesReader::AnalyzeFileForITKImageSeriesReaderSpacingAssumption( const StringContainer& files, const gdcm::Scanner::MappingType& tagValueMappings_) { // result.first = files that fit ITK's assumption // result.second = files that do not fit, should be run through AnalyzeFileForITKImageSeriesReaderSpacingAssumption() again TwoStringContainers result; // we const_cast here, because I could not use a map.at(), which would make the code much more readable gdcm::Scanner::MappingType& tagValueMappings = const_cast(tagValueMappings_); const gdcm::Tag tagImagePositionPatient(0x0020,0x0032); // Image Position (Patient) const gdcm::Tag tagImageOrientation(0x0020, 0x0037); // Image Orientation Vector3D fromFirstToSecondOrigin; fromFirstToSecondOrigin.Fill(0.0); bool fromFirstToSecondOriginInitialized(false); Point3D thisOrigin; Point3D lastOrigin; Point3D lastDifferentOrigin; bool lastOriginInitialized(false); MITK_DEBUG << "--------------------------------------------------------------------------------"; MITK_DEBUG << "Analyzing files for z-spacing assumption of ITK's ImageSeriesReader "; unsigned int fileIndex(0); for (StringContainer::const_iterator fileIter = files.begin(); fileIter != files.end(); ++fileIter, ++fileIndex) { bool fileFitsIntoPattern(false); std::string thisOriginString; // Read tag value into point3D. PLEASE replace this by appropriate GDCM code if you figure out how to do that const char* value = tagValueMappings[fileIter->c_str()][tagImagePositionPatient]; if (value) { thisOriginString = value; } std::istringstream originReader(thisOriginString); std::string coordinate; unsigned int dim(0); while( std::getline( originReader, coordinate, '\\' ) ) thisOrigin[dim++] = atof(coordinate.c_str()); if (dim != 3) { MITK_ERROR << "Reader implementation made wrong assumption on tag (0020,0032). Found " << dim << "instead of 3 values."; } MITK_DEBUG << " " << fileIndex << " " << *fileIter << " at " << thisOriginString << "(" << thisOrigin[0] << "," << thisOrigin[1] << "," << thisOrigin[2] << ")"; if ( lastOriginInitialized && (thisOrigin == lastOrigin) ) { MITK_DEBUG << " ==> Sort away " << *fileIter << " for separate time step"; // we already have one occupying this position result.second.push_back( *fileIter ); fileFitsIntoPattern = false; } else { if (!fromFirstToSecondOriginInitialized && lastOriginInitialized) // calculate vector as soon as possible when we get a new position { fromFirstToSecondOrigin = thisOrigin - lastDifferentOrigin; fromFirstToSecondOriginInitialized = true; // Now make sure this direction is along the normal vector of the first slice // If this is NOT the case, then we have a data set with a TILTED GANTRY geometry, // which cannot be loaded into a single mitk::Image at the moment // Again ugly code to read tag Image Orientation into two vEctors Vector3D right; right.Fill(0.0); Vector3D up; right.Fill(0.0); // might be down as well, but it is just a name at this point std::string thisOrientationString; const char* value = tagValueMappings[fileIter->c_str()][tagImageOrientation]; if (value) { thisOrientationString = value; } std::istringstream orientationReader(thisOrientationString); std::string coordinate; unsigned int dim(0); while( std::getline( orientationReader, coordinate, '\\' ) ) if (dim<3) right[dim++] = atof(coordinate.c_str()); else up[dim++ - 3] = atof(coordinate.c_str()); if (dim != 6) { MITK_ERROR << "Reader implementation made wrong assumption on tag (0020,0037). Found " << dim << "instead of 6 values."; } /* Determine if line (thisOrigin + l * normal) contains lastDifferentOrigin. Done by calculating the distance of lastDifferentOrigin from line (thisOrigin + l *normal) E.g. http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html squared distance = | (pointAlongNormal - thisOrign) x (thisOrigin - lastDifferentOrigin) | ^ 2 / |pointAlongNormal - thisOrigin| ^ 2 ( x meaning the cross product ) MITK_DEBUG << "Tilt check: right vector (" << right[0] << "," << right[1] << "," << right[2] << "), " "up vector (" << up[0] << "," << up[1] << "," << up[2] << ")"; */ Vector3D normal = itk::CrossProduct(right, up); Point3D pointAlongNormal = thisOrigin + normal; double numerator = itk::CrossProduct( pointAlongNormal - thisOrigin , thisOrigin - lastDifferentOrigin ).GetSquaredNorm(); double denominator = (pointAlongNormal - thisOrigin).GetSquaredNorm(); double distance = sqrt(numerator / denominator); if (distance > 0.001) // mitk::eps is too small; 1/1000 of a mm should be enough to detect tilt { MITK_DEBUG << " Series might contain a tilted geometry"; MITK_DEBUG << " Distance of expected slice origin from actual slice origin: " << distance; MITK_DEBUG << " ==> Sort away " << *fileIter << " for later analysis"; /* Pessimistic approach: split block right here result.first.assign( files.begin(), fileIter ); result.second.insert( result.second.end(), fileIter, files.end() ); return result; // stop processing with first split */ /* optimistic approach: save file for later, check all further files */ result.second.push_back(*fileIter); fileFitsIntoPattern = false; } else { result.first.push_back(*fileIter); // this file is good for current block fileFitsIntoPattern = true; } } else if (fromFirstToSecondOriginInitialized) // we already know the offset between slices { Point3D assumedOrigin = lastDifferentOrigin + fromFirstToSecondOrigin; Vector3D originError = assumedOrigin - thisOrigin; double norm = originError.GetNorm(); double toleratedError(0.005); // max. 1/10mm error when measurement crosses 20 slices in z direction if (norm > toleratedError) { MITK_DEBUG << " File does not fit into the inter-slice distance pattern (diff = " << norm << ", allowed " << toleratedError << ")."; MITK_DEBUG << " Expected position (" << assumedOrigin[0] << "," << assumedOrigin[1] << "," << assumedOrigin[2] << "), got position (" << thisOrigin[0] << "," << thisOrigin[1] << "," << thisOrigin[2] << ")"; MITK_DEBUG << " ==> Sort away " << *fileIter << " for later analysis"; // At this point we know we deviated from the expectation of ITK's ImageSeriesReader // We split the input file list at this point, i.e. all files up to this one (excluding it) // are returned as group 1, the remaining files (including the faulty one) are group 2 /* Pessimistic approach: split right here: result.first.assign( files.begin(), fileIter ); result.second.insert( result.second.end(), fileIter, files.end() ); return result; // stop processing with first split */ /* Optimistic approach: check if any of the remaining slices fits in */ result.second.push_back( *fileIter ); // sort away for further analysis fileFitsIntoPattern = false; } else { result.first.push_back(*fileIter); // this file is good for current block fileFitsIntoPattern = true; } } else // this should be the very first slice { result.first.push_back(*fileIter); // this file is good for current block fileFitsIntoPattern = true; } } // recored current origin for reference in later iterations if ( !lastOriginInitialized || ( fileFitsIntoPattern && (thisOrigin != lastOrigin) ) ) { lastDifferentOrigin = thisOrigin; } lastOrigin = thisOrigin; lastOriginInitialized = true; } return result; } DicomSeriesReader::UidFileNamesMap DicomSeriesReader::GetSeries(const StringContainer& files, const StringContainer &restrictions) { return GetSeries(files, true, restrictions); } DicomSeriesReader::UidFileNamesMap DicomSeriesReader::GetSeries(const StringContainer& files, bool sortTo3DPlust, const StringContainer& /*restrictions*/) { /** assumption about this method: returns a map of uid-like-key --> list(filename) each entry should contain filenames that have images of same - series instance uid (automatically done by GDCMSeriesFileNames - 0020,0037 image orientation (patient) - 0028,0030 pixel spacing (x,y) - 0018,0050 slice thickness */ UidFileNamesMap groupsOfSimilarImages; // preliminary result, refined into the final result mapOf3DPlusTBlocks // use GDCM directly, itk::GDCMSeriesFileNames does not work with GDCM 2 // PART I: scan files for sorting relevant DICOM tags, // separate images that differ in any of those // attributes (they cannot possibly form a 3D block) // scan for relevant tags in dicom files gdcm::Scanner scanner; const gdcm::Tag tagSeriesInstanceUID(0x0020,0x000e); // Series Instance UID scanner.AddTag( tagSeriesInstanceUID ); const gdcm::Tag tagImageOrientation(0x0020, 0x0037); // image orientation scanner.AddTag( tagImageOrientation ); const gdcm::Tag tagPixelSpacing(0x0028, 0x0030); // pixel spacing scanner.AddTag( tagPixelSpacing ); const gdcm::Tag tagSliceThickness(0x0018, 0x0050); // slice thickness scanner.AddTag( tagSliceThickness ); const gdcm::Tag tagNumberOfRows(0x0028, 0x0010); // number rows scanner.AddTag( tagNumberOfRows ); const gdcm::Tag tagNumberOfColumns(0x0028, 0x0011); // number cols scanner.AddTag( tagNumberOfColumns ); // additional tags read in this scan to allow later analysis // THESE tag are not used for initial separating of files const gdcm::Tag tagImagePositionPatient(0x0020,0x0032); // Image Position (Patient) scanner.AddTag( tagImagePositionPatient ); // TODO add further restrictions from arguments // let GDCM scan files if ( !scanner.Scan( files ) ) { MITK_ERROR << "gdcm::Scanner failed when scanning " << files.size() << " input files."; return groupsOfSimilarImages; } // assign files IDs that will separate them for loading into image blocks for (gdcm::Scanner::ConstIterator fileIter = scanner.Begin(); fileIter != scanner.End(); ++fileIter) { //MITK_DEBUG << "Scan file " << fileIter->first << std::endl; if ( std::string(fileIter->first).empty() ) continue; // TODO understand why Scanner has empty string entries // we const_cast here, because I could not use a map.at() function in CreateMoreUniqueSeriesIdentifier. // doing the same thing with find would make the code less readable. Since we forget the Scanner results // anyway after this function, we can simply tolerate empty map entries introduced by bad operator[] access std::string moreUniqueSeriesId = CreateMoreUniqueSeriesIdentifier( const_cast(fileIter->second) ); groupsOfSimilarImages [ moreUniqueSeriesId ].push_back( fileIter->first ); } // PART III: sort slices spatially for ( UidFileNamesMap::const_iterator groupIter = groupsOfSimilarImages.begin(); groupIter != groupsOfSimilarImages.end(); ++groupIter ) { try { groupsOfSimilarImages[ groupIter->first ] = SortSeriesSlices( groupIter->second ); // sort each slice group spatially } catch(...) { MITK_ERROR << "Catched something."; } } // PART II: analyze pre-sorted images for valid blocks (i.e. blocks of equal z-spacing), // separate into multiple blocks if necessary. // // Analysis performs the following steps: // * imitate itk::ImageSeriesReader: use the distance between the first two images as z-spacing // * check what images actually fulfill ITK's z-spacing assumption // * separate all images that fail the test into new blocks, re-iterate analysis for these blocks UidFileNamesMap mapOf3DPlusTBlocks; // final result of this function for ( UidFileNamesMap::const_iterator groupIter = groupsOfSimilarImages.begin(); groupIter != groupsOfSimilarImages.end(); ++groupIter ) { UidFileNamesMap mapOf3DBlocks; // intermediate result for only this group(!) StringContainer filesStillToAnalyze = groupIter->second; std::string groupUID = groupIter->first; unsigned int subgroup(0); MITK_DEBUG << "Analyze group " << groupUID; while (!filesStillToAnalyze.empty()) // repeat until all files are grouped somehow { TwoStringContainers analysisResult = AnalyzeFileForITKImageSeriesReaderSpacingAssumption( filesStillToAnalyze, scanner.GetMappings() ); // enhance the UID for additional groups std::stringstream newGroupUID; newGroupUID << groupUID << '.' << subgroup; mapOf3DBlocks[ newGroupUID.str() ] = analysisResult.first; MITK_DEBUG << "Result: sorted 3D group " << newGroupUID.str() << " with " << mapOf3DBlocks[ newGroupUID.str() ].size() << " files"; ++subgroup; filesStillToAnalyze = analysisResult.second; // remember what needs further analysis } // end of grouping, now post-process groups // PART IV: attempt to group blocks to 3D+t blocks if requested // inspect entries of mapOf3DBlocks // - if number of files is identical to previous entry, collect for 3D+t block // - as soon as number of files changes from previous entry, record collected blocks as 3D+t block, start a new one, continue // decide whether or not to group 3D blocks into 3D+t blocks where possible if ( !sortTo3DPlust ) { // copy 3D blocks to output // TODO avoid collisions (or prove impossibility) mapOf3DPlusTBlocks.insert( mapOf3DBlocks.begin(), mapOf3DBlocks.end() ); } else { // sort 3D+t (as described in "PART IV") MITK_DEBUG << "================================================================================"; MITK_DEBUG << "3D+t analysis:"; unsigned int numberOfFilesInPreviousBlock(0); std::string previousBlockKey; for ( UidFileNamesMap::const_iterator block3DIter = mapOf3DBlocks.begin(); block3DIter != mapOf3DBlocks.end(); ++block3DIter ) { unsigned int numberOfFilesInThisBlock = block3DIter->second.size(); std::string thisBlockKey = block3DIter->first; if (numberOfFilesInPreviousBlock == 0) { numberOfFilesInPreviousBlock = numberOfFilesInThisBlock; mapOf3DPlusTBlocks[thisBlockKey].insert( mapOf3DPlusTBlocks[thisBlockKey].end(), block3DIter->second.begin(), block3DIter->second.end() ); MITK_DEBUG << " 3D+t group " << thisBlockKey << " started"; previousBlockKey = thisBlockKey; } else { bool identicalOrigins; try { // check whether this and the previous block share a comon origin // TODO should be safe, but a little try/catch or other error handling wouldn't hurt const char *origin_value = scanner.GetValue( mapOf3DBlocks[thisBlockKey].front().c_str(), tagImagePositionPatient ), *previous_origin_value = scanner.GetValue( mapOf3DBlocks[previousBlockKey].front().c_str(), tagImagePositionPatient ), *destination_value = scanner.GetValue( mapOf3DBlocks[thisBlockKey].back().c_str(), tagImagePositionPatient ), *previous_destination_value = scanner.GetValue( mapOf3DBlocks[previousBlockKey].back().c_str(), tagImagePositionPatient ); if (!origin_value || !previous_origin_value || !destination_value || !previous_destination_value) { identicalOrigins = false; } else { std::string thisOriginString = origin_value; std::string previousOriginString = previous_origin_value; // also compare last origin, because this might differ if z-spacing is different std::string thisDestinationString = destination_value; std::string previousDestinationString = previous_destination_value; identicalOrigins = ( (thisOriginString == previousOriginString) && (thisDestinationString == previousDestinationString) ); } } catch(...) { identicalOrigins = false; } if (identicalOrigins && (numberOfFilesInPreviousBlock == numberOfFilesInThisBlock)) { // group with previous block mapOf3DPlusTBlocks[previousBlockKey].insert( mapOf3DPlusTBlocks[previousBlockKey].end(), block3DIter->second.begin(), block3DIter->second.end() ); MITK_DEBUG << " --> group enhanced with another timestep"; } else { // start a new block mapOf3DPlusTBlocks[thisBlockKey].insert( mapOf3DPlusTBlocks[thisBlockKey].end(), block3DIter->second.begin(), block3DIter->second.end() ); MITK_DEBUG << " ==> group closed with " << mapOf3DPlusTBlocks[previousBlockKey].size() / numberOfFilesInPreviousBlock << " time steps"; previousBlockKey = thisBlockKey; MITK_DEBUG << " 3D+t group " << thisBlockKey << " started"; } } numberOfFilesInPreviousBlock = numberOfFilesInThisBlock; } } } MITK_DEBUG << "================================================================================"; MITK_DEBUG << "Summary: "; for ( UidFileNamesMap::const_iterator groupIter = mapOf3DPlusTBlocks.begin(); groupIter != mapOf3DPlusTBlocks.end(); ++groupIter ) { MITK_DEBUG << " Image volume " << groupIter->first << " with " << groupIter->second.size() << " files"; } MITK_DEBUG << "Done. "; MITK_DEBUG << "================================================================================"; return mapOf3DPlusTBlocks; } DicomSeriesReader::UidFileNamesMap DicomSeriesReader::GetSeries(const std::string &dir, const StringContainer &restrictions) { gdcm::Directory directoryLister; directoryLister.Load( dir.c_str(), false ); // non-recursive return GetSeries(directoryLister.GetFilenames(), restrictions); } std::string DicomSeriesReader::CreateSeriesIdentifierPart( gdcm::Scanner::TagToValue& tagValueMap, const gdcm::Tag& tag ) { std::string result; try { result = IDifyTagValue( tagValueMap[ tag ] ? tagValueMap[ tag ] : std::string("") ); } catch (std::exception& e) { MITK_WARN << "Could not access tag " << tag << ": " << e.what(); } return result; } std::string DicomSeriesReader::CreateMoreUniqueSeriesIdentifier( gdcm::Scanner::TagToValue& tagValueMap ) { const gdcm::Tag tagSeriesInstanceUID(0x0020,0x000e); // Series Instance UID const gdcm::Tag tagImageOrientation(0x0020, 0x0037); // image orientation const gdcm::Tag tagPixelSpacing(0x0028, 0x0030); // pixel spacing const gdcm::Tag tagSliceThickness(0x0018, 0x0050); // slice thickness const gdcm::Tag tagNumberOfRows(0x0028, 0x0010); // number rows const gdcm::Tag tagNumberOfColumns(0x0028, 0x0011); // number cols std::string constructedID; try { constructedID = tagValueMap[ tagSeriesInstanceUID ]; } catch (std::exception& e) { MITK_ERROR << "CreateMoreUniqueSeriesIdentifier() could not access series instance UID. Something is seriously wrong with this image."; MITK_ERROR << "Error from exception: " << e.what(); } constructedID += CreateSeriesIdentifierPart( tagValueMap, tagNumberOfRows ); constructedID += CreateSeriesIdentifierPart( tagValueMap, tagNumberOfColumns ); constructedID += CreateSeriesIdentifierPart( tagValueMap, tagPixelSpacing ); constructedID += CreateSeriesIdentifierPart( tagValueMap, tagSliceThickness ); constructedID += CreateSeriesIdentifierPart( tagValueMap, tagImageOrientation ); constructedID.resize( constructedID.length() - 1 ); // cut of trailing '.' return constructedID; } std::string DicomSeriesReader::IDifyTagValue(const std::string& value) { std::string IDifiedValue( value ); if (value.empty()) throw std::logic_error("IDifyTagValue() illegaly called with empty tag value"); // Eliminate non-alnum characters, including whitespace... // that may have been introduced by concats. for(std::size_t i=0; i= 'a' && IDifiedValue[i] <= 'z') || (IDifiedValue[i] >= '0' && IDifiedValue[i] <= '9') || (IDifiedValue[i] >= 'A' && IDifiedValue[i] <= 'Z'))) { IDifiedValue.erase(i, 1); } } IDifiedValue += "."; return IDifiedValue; } DicomSeriesReader::StringContainer DicomSeriesReader::GetSeries(const std::string &dir, const std::string &series_uid, const StringContainer &restrictions) { UidFileNamesMap allSeries = GetSeries(dir, restrictions); StringContainer resultingFileList; for ( UidFileNamesMap::const_iterator idIter = allSeries.begin(); idIter != allSeries.end(); ++idIter ) { if ( idIter->first.find( series_uid ) == 0 ) // this ID starts with given series_uid { resultingFileList.insert( resultingFileList.end(), idIter->second.begin(), idIter->second.end() ); // append } } return resultingFileList; } DicomSeriesReader::StringContainer DicomSeriesReader::SortSeriesSlices(const StringContainer &unsortedFilenames) { gdcm::Sorter sorter; sorter.SetSortFunction(DicomSeriesReader::GdcmSortFunction); try { sorter.Sort(unsortedFilenames); return sorter.GetFilenames(); } catch(std::logic_error&) { MITK_WARN << "Sorting error. Leaving series unsorted."; return unsortedFilenames; } } bool DicomSeriesReader::GdcmSortFunction(const gdcm::DataSet &ds1, const gdcm::DataSet &ds2) { // make sure we habe Image Position and Orientation if ( ! ( ds1.FindDataElement(gdcm::Tag(0x0020,0x0032)) && ds1.FindDataElement(gdcm::Tag(0x0020,0x0037)) && ds2.FindDataElement(gdcm::Tag(0x0020,0x0032)) && ds2.FindDataElement(gdcm::Tag(0x0020,0x0037)) ) ) { MITK_WARN << "Dicom images are missing attributes for a meaningful sorting."; throw std::logic_error("Dicom images are missing attributes for a meaningful sorting."); } gdcm::Attribute<0x0020,0x0032> image_pos1; // Image Position (Patient) gdcm::Attribute<0x0020,0x0037> image_orientation1; // Image Orientation (Patient) image_pos1.Set(ds1); image_orientation1.Set(ds1); gdcm::Attribute<0x0020,0x0032> image_pos2; gdcm::Attribute<0x0020,0x0037> image_orientation2; image_pos2.Set(ds2); image_orientation2.Set(ds2); if (image_orientation1 != image_orientation2) { MITK_ERROR << "Dicom images have different orientations."; throw std::logic_error("Dicom images have different orientations. Call GetSeries() first to separate images."); } double normal[3]; normal[0] = image_orientation1[1] * image_orientation1[5] - image_orientation1[2] * image_orientation1[4]; normal[1] = image_orientation1[2] * image_orientation1[3] - image_orientation1[0] * image_orientation1[5]; normal[2] = image_orientation1[0] * image_orientation1[4] - image_orientation1[1] * image_orientation1[3]; double dist1 = 0.0, dist2 = 0.0; for (unsigned char i = 0u; i < 3u; ++i) { dist1 += normal[i] * image_pos1[i]; dist2 += normal[i] * image_pos2[i]; } if ( fabs(dist1 - dist2) < mitk::eps) { - gdcm::Attribute<0x0008,0x0032> acq_time1; // Acquisition time (may be missing, so we check existence first) + gdcm::Attribute<0x0008,0x0032> acq_time1; // Acquisition time (may be missing, so we check existence first) gdcm::Attribute<0x0008,0x0032> acq_time2; - if (ds1.FindDataElement(gdcm::Tag(0x0008,0x0032))) - acq_time1.Set(ds1); + gdcm::Attribute<0x0020,0x0012> acq_number1; // Acquisition number (may also be missing, so we check existence first) + gdcm::Attribute<0x0020,0x0012> acq_number2; - if (ds2.FindDataElement(gdcm::Tag(0x0008,0x0032))) + if (ds1.FindDataElement(gdcm::Tag(0x0008,0x0032)) && ds2.FindDataElement(gdcm::Tag(0x0008,0x0032))) + { + acq_time1.Set(ds1); acq_time2.Set(ds2); - // TODO this could lead to comparison of unset times (does Attribute initialize to good defaults?) - // exception: same position: compare by acquisition time - return acq_time1 < acq_time2; + return acq_time1 < acq_time2; + } + else if (ds1.FindDataElement(gdcm::Tag(0x0020,0x0012)) && ds2.FindDataElement(gdcm::Tag(0x0020,0x0012))) + { + acq_number1.Set(ds1); + acq_number2.Set(ds2); + + return acq_number1 < acq_number2; + } + else + { + return true; + } } else { // default: compare position return dist1 < dist2; } } std::string DicomSeriesReader::GetConfigurationString() { std::stringstream configuration; configuration << "MITK_USE_GDCMIO: "; configuration << "true"; configuration << "\n"; configuration << "GDCM_VERSION: "; #ifdef GDCM_MAJOR_VERSION configuration << GDCM_VERSION; #endif //configuration << "\n"; return configuration.str(); } void DicomSeriesReader::CopyMetaDataToImageProperties(StringContainer filenames, const gdcm::Scanner::MappingType &tagValueMappings_, DcmIoType *io, Image *image) { std::list imageBlock; imageBlock.push_back(filenames); CopyMetaDataToImageProperties(imageBlock, tagValueMappings_, io, image); } void DicomSeriesReader::CopyMetaDataToImageProperties( std::list imageBlock, const gdcm::Scanner::MappingType& tagValueMappings_, DcmIoType* io, Image* image) { if (!io || !image) return; StringLookupTable filesForSlices; StringLookupTable sliceLocationForSlices; StringLookupTable instanceNumberForSlices; StringLookupTable SOPInstanceNumberForSlices; gdcm::Scanner::MappingType& tagValueMappings = const_cast(tagValueMappings_); //DICOM tags which should be added to the image properties const gdcm::Tag tagSliceLocation(0x0020, 0x1041); // slice location const gdcm::Tag tagInstanceNumber(0x0020, 0x0013); // (image) instance number const gdcm::Tag tagSOPInstanceNumber(0x0008, 0x0018); // SOP instance number unsigned int timeStep(0); std::string propertyKeySliceLocation = "dicom.image.0020.1041"; std::string propertyKeyInstanceNumber = "dicom.image.0020.0013"; std::string propertyKeySOPInstanceNumber = "dicom.image.0008.0018"; // tags for each image for ( std::list::iterator i = imageBlock.begin(); i != imageBlock.end(); i++, timeStep++ ) { const StringContainer& files = (*i); unsigned int slice(0); for ( StringContainer::const_iterator fIter = files.begin(); fIter != files.end(); ++fIter, ++slice ) { filesForSlices.SetTableValue( slice, *fIter ); gdcm::Scanner::TagToValue tagValueMapForFile = tagValueMappings[fIter->c_str()]; if(tagValueMapForFile.find(tagSliceLocation) != tagValueMapForFile.end()) sliceLocationForSlices.SetTableValue(slice, tagValueMapForFile[tagSliceLocation]); if(tagValueMapForFile.find(tagInstanceNumber) != tagValueMapForFile.end()) instanceNumberForSlices.SetTableValue(slice, tagValueMapForFile[tagInstanceNumber]); if(tagValueMapForFile.find(tagSOPInstanceNumber) != tagValueMapForFile.end()) SOPInstanceNumberForSlices.SetTableValue(slice, tagValueMapForFile[tagSOPInstanceNumber]); } image->SetProperty( "files", StringLookupTableProperty::New( filesForSlices ) ); //If more than one time step add postfix ".t" + timestep if(timeStep != 0) { propertyKeySliceLocation.append(".t" + timeStep); propertyKeyInstanceNumber.append(".t" + timeStep); propertyKeySOPInstanceNumber.append(".t" + timeStep); } image->SetProperty( propertyKeySliceLocation.c_str(), StringLookupTableProperty::New( sliceLocationForSlices ) ); image->SetProperty( propertyKeyInstanceNumber.c_str(), StringLookupTableProperty::New( instanceNumberForSlices ) ); image->SetProperty( propertyKeySOPInstanceNumber.c_str(), StringLookupTableProperty::New( SOPInstanceNumberForSlices ) ); } // Copy tags for series, study, patient level (leave interpretation to application). // These properties will be copied to the DataNode by DicomSeriesReader. // tags for the series (we just use the one that ITK copied to its dictionary (proably that of the last slice) const itk::MetaDataDictionary& dict = io->GetMetaDataDictionary(); const TagToPropertyMapType& propertyLookup = DicomSeriesReader::GetDICOMTagsToMITKPropertyMap(); itk::MetaDataDictionary::ConstIterator dictIter = dict.Begin(); while ( dictIter != dict.End() ) { MITK_DEBUG << "Key " << dictIter->first; std::string value; if ( itk::ExposeMetaData( dict, dictIter->first, value ) ) { MITK_DEBUG << "Value " << value; TagToPropertyMapType::const_iterator valuePosition = propertyLookup.find( dictIter->first ); if ( valuePosition != propertyLookup.end() ) { std::string propertyKey = valuePosition->second; MITK_DEBUG << "--> " << propertyKey; image->SetProperty( propertyKey.c_str(), StringProperty::New(value) ); } } else { MITK_WARN << "Tag " << dictIter->first << " not read as string as expected. Ignoring..." ; } ++dictIter; } } } // end namespace mitk #include diff --git a/Core/Code/IO/mitkImageWriter.cpp b/Core/Code/IO/mitkImageWriter.cpp index 6d75717b28..ac55776989 100644 --- a/Core/Code/IO/mitkImageWriter.cpp +++ b/Core/Code/IO/mitkImageWriter.cpp @@ -1,332 +1,338 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkImageWriter.h" #include "mitkItkPictureWrite.h" #include "mitkImage.h" #include "mitkImageTimeSelector.h" #include "mitkImageAccessByItk.h" #include #include mitk::ImageWriter::ImageWriter() { this->SetNumberOfRequiredInputs( 1 ); m_MimeType = ""; SetDefaultExtension(); } mitk::ImageWriter::~ImageWriter() { } void mitk::ImageWriter::SetDefaultExtension() { m_Extension = ".mhd"; } #include #include #include static void writeVti(const char * filename, mitk::Image* image, int t=0) { vtkXMLImageDataWriter * vtkwriter = vtkXMLImageDataWriter::New(); vtkwriter->SetFileName( filename ); vtkwriter->SetInput(image->GetVtkImageData(t)); vtkwriter->Write(); vtkwriter->Delete(); } void mitk::ImageWriter::WriteByITK(mitk::Image* image, const std::string& fileName) { // Pictures and picture series like .png are written via a different mechanism then volume images. // So, they are still multiplexed and thus not support vector images. if (fileName.find(".png") != std::string::npos || fileName.find(".tif") != std::string::npos || fileName.find(".jpg") != std::string::npos) { AccessByItk_1( image, _mitkItkPictureWrite, fileName ); return; } // Implementation of writer using itkImageIO directly. This skips the use // of templated itkImageFileWriter, which saves the multiplexing on MITK side. unsigned int dimension = image->GetDimension(); unsigned int* dimensions = image->GetDimensions(); mitk::PixelType pixelType = image->GetPixelType(); mitk::Vector3D spacing = image->GetGeometry()->GetSpacing(); mitk::Point3D origin = image->GetGeometry()->GetOrigin(); itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO( fileName.c_str(), itk::ImageIOFactory::WriteMode ); if(imageIO.IsNull()) { itkExceptionMacro(<< "Error: Could not create itkImageIO via factory for file " << fileName); } // Set the necessary information for imageIO imageIO->SetNumberOfDimensions(dimension); imageIO->SetPixelTypeInfo( pixelType.GetTypeId() ); if(pixelType.GetNumberOfComponents() > 1) imageIO->SetNumberOfComponents(pixelType.GetNumberOfComponents()); itk::ImageIORegion ioRegion( dimension ); for(unsigned int i=0; iSetDimensions(i,dimensions[i]); imageIO->SetSpacing(i,spacing[i]); imageIO->SetOrigin(i,origin[i]); mitk::Vector3D direction; direction.Set_vnl_vector(image->GetGeometry()->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(i)); vnl_vector< double > axisDirection(dimension); for(unsigned int j=0; jSetDirection( i, axisDirection ); ioRegion.SetSize(i, image->GetLargestPossibleRegion().GetSize(i) ); ioRegion.SetIndex(i, image->GetLargestPossibleRegion().GetIndex(i) ); } //use compression if available imageIO->UseCompressionOn(); imageIO->SetIORegion(ioRegion); imageIO->SetFileName(fileName); const void * data = image->GetData(); imageIO->Write(data); } void mitk::ImageWriter::GenerateData() { const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, NULL ); if ( locale.compare(currLocale)!=0 ) { try { setlocale(LC_ALL, locale.c_str()); } catch(...) { MITK_INFO << "Could not set locale " << locale; } } if ( m_FileName == "" ) { itkWarningMacro( << "Sorry, filename has not been set!" ); return ; } FILE* tempFile = fopen(m_FileName.c_str(),"w"); if (tempFile==NULL) { itkExceptionMacro(<<"File location not writeable"); return; } fclose(tempFile); remove(m_FileName.c_str()); mitk::Image::Pointer input = const_cast(this->GetInput()); bool vti = (m_Extension.find(".vti") != std::string::npos); - // If the extension is NOT .pic and NOT .nrrd the following block is entered + // If the extension is NOT .pic and NOT .nrrd and NOT .nii and NOT .nii.gz the following block is entered if ( m_Extension.find(".pic") == std::string::npos - && m_Extension.find(".nrrd") == std::string::npos) + && m_Extension.find(".nrrd") == std::string::npos + && m_Extension.find(".nii") == std::string::npos + && m_Extension.find(".nii.gz") == std::string::npos + ) { if(input->GetDimension() > 3) { int t, timesteps; timesteps = input->GetDimension(3); ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput(input); mitk::Image::Pointer image = timeSelector->GetOutput(); for(t = 0; t < timesteps; ++t) { ::itk::OStringStream filename; timeSelector->SetTimeNr(t); timeSelector->Update(); if(input->GetTimeSlicedGeometry()->IsValidTime(t)) { const mitk::TimeBounds& timebounds = input->GetTimeSlicedGeometry()->GetGeometry3D(t)->GetTimeBounds(); filename << m_FileName.c_str() << "_S" << std::setprecision(0) << timebounds[0] << "_E" << std::setprecision(0) << timebounds[1] << "_T" << t << m_Extension; } else { itkWarningMacro(<<"Error on write: TimeSlicedGeometry invalid of image " << filename << "."); filename << m_FileName.c_str() << "_T" << t << m_Extension; } if ( vti ) { writeVti(filename.str().c_str(), input, t); } else { - WriteByITK(input, filename.str()); + WriteByITK(image, filename.str()); } } } else if ( vti ) { ::itk::OStringStream filename; filename << m_FileName.c_str() << m_Extension; writeVti(filename.str().c_str(), input); } else { ::itk::OStringStream filename; filename << m_FileName.c_str() << m_Extension; WriteByITK(input, filename.str()); } } else { // use the PicFileWriter for the .pic data type if( m_Extension.find(".pic") != std::string::npos ) { /* PicFileWriter::Pointer picWriter = PicFileWriter::New(); size_t found; found = m_FileName.find( m_Extension ); // !!! HAS to be at the very end of the filename (not somewhere in the middle) if( m_FileName.length() > 3 && found != m_FileName.length() - 4 ) { //if Extension not in Filename ::itk::OStringStream filename; filename << m_FileName.c_str() << m_Extension; picWriter->SetFileName( filename.str().c_str() ); } else { picWriter->SetFileName( m_FileName.c_str() ); } picWriter->SetInputImage( input ); picWriter->Write(); */ } // use the ITK .nrrd Image writer - if( m_Extension.find(".nrrd") != std::string::npos ) + if( m_Extension.find(".nrrd") != std::string::npos + || m_Extension.find(".nii") != std::string::npos + || m_Extension.find(".nii.gz") != std::string::npos + ) { ::itk::OStringStream filename; filename << this->m_FileName.c_str() << this->m_Extension; WriteByITK(input, filename.str()); } } m_MimeType = "application/MITK.Pic"; try { setlocale(LC_ALL, currLocale.c_str()); } catch(...) { MITK_INFO << "Could not reset locale " << currLocale; } } bool mitk::ImageWriter::CanWriteDataType( DataNode* input ) { if ( input ) { mitk::BaseData* data = input->GetData(); if ( data ) { mitk::Image::Pointer image = dynamic_cast( data ); if( image.IsNotNull() ) { //"SetDefaultExtension()" set m_Extension to ".mhd" ????? m_Extension = ".pic"; return true; } } } return false; } void mitk::ImageWriter::SetInput( DataNode* input ) { if( input && CanWriteDataType( input ) ) this->ProcessObject::SetNthInput( 0, dynamic_cast( input->GetData() ) ); } std::string mitk::ImageWriter::GetWritenMIMEType() { return m_MimeType; } std::vector mitk::ImageWriter::GetPossibleFileExtensions() { std::vector possibleFileExtensions; possibleFileExtensions.push_back(".pic"); possibleFileExtensions.push_back(".bmp"); possibleFileExtensions.push_back(".dcm"); possibleFileExtensions.push_back(".DCM"); possibleFileExtensions.push_back(".dicom"); possibleFileExtensions.push_back(".DICOM"); possibleFileExtensions.push_back(".gipl"); possibleFileExtensions.push_back(".gipl.gz"); possibleFileExtensions.push_back(".mha"); possibleFileExtensions.push_back(".nii"); possibleFileExtensions.push_back(".nii.gz"); possibleFileExtensions.push_back(".nrrd"); possibleFileExtensions.push_back(".nhdr"); possibleFileExtensions.push_back(".png"); possibleFileExtensions.push_back(".PNG"); possibleFileExtensions.push_back(".spr"); possibleFileExtensions.push_back(".mhd"); possibleFileExtensions.push_back(".vtk"); possibleFileExtensions.push_back(".vti"); possibleFileExtensions.push_back(".hdr"); possibleFileExtensions.push_back(".img"); possibleFileExtensions.push_back(".img.gz"); possibleFileExtensions.push_back(".png"); possibleFileExtensions.push_back(".tif"); possibleFileExtensions.push_back(".jpg"); return possibleFileExtensions; } std::string mitk::ImageWriter::GetFileExtension() { return m_Extension; } void mitk::ImageWriter::SetInput( mitk::Image* image ) { this->ProcessObject::SetNthInput( 0, image ); } const mitk::Image* mitk::ImageWriter::GetInput() { if ( this->GetNumberOfInputs() < 1 ) { return NULL; } else { return static_cast< const mitk::Image * >( this->ProcessObject::GetInput( 0 ) ); } } diff --git a/Core/Code/Interactions/StateMachine.xml b/Core/Code/Interactions/StateMachine.xml index 606e976576..f4585e53f7 100644 --- a/Core/Code/Interactions/StateMachine.xml +++ b/Core/Code/Interactions/StateMachine.xml @@ -1,3913 +1,3913 @@ - + diff --git a/Documentation/Doxygen/Tutorial/Step09.dox b/Documentation/Doxygen/Tutorial/Step09.dox index 283c04379f..d60e22c07a 100644 --- a/Documentation/Doxygen/Tutorial/Step09.dox +++ b/Documentation/Doxygen/Tutorial/Step09.dox @@ -1,226 +1,219 @@ /** \page Step09Page MITK Tutorial - Step 9: A plug-in MITK uses a very modular concept to maximize reusability and portability. You start an application (for example ExtApp, the sample application provided by MITK). An application has several bundles (or plug-ins). A bundle can be a functionality, which in turn can be a view, each of these terms specifying certain behaviour and attributes. The creation of a MITK plug-in is considerably facilitated by using the MITK BundleGenerator as described in \ref NewPluginPage . The mentioned tool was used to create a plug-in QmitkRegionGrowing. Let's first look at what files the BundleGenerator created: \verbatim - documentation\doxygen\ modules.dox............................. Doxygen file for documenting your plug-in -META-INF\ - MANIFEST.MF............................. Information about your plug-in - resources\ icon.xpm................................ The icon of your plug-in. GIMP or other programs (including your text editor) can be used to change this - QmitkMITKRegionGrowingView.qrc.......... QT file for managing resources src\internal\ QmitkMITKRegionGrowingView.cpp.......... The most important file, implementing behaviour QmitkMITKRegionGrowingView.h............ Header file of the functionality QmitkMITKRegionGrowingViewControls.ui... XML file of the Qt Designer, describes buttons, combo boxes, etc. of your controls -src\ - RegiongrowingDll.h...................... Manages the import/export of your plug-in dll CMakeLists.txt \.......................... Build system related files for CMake files.cmake / -manifest.cpp \............................ BlueBerry integration -plugin.xml / - +manifest_headers.cmake.................... Information about your plug-in +plugin.xml ............................... BlueBerry integration \endverbatim If you are not familiar with Qt development, please look into this Trolltech page describing .ui files (no, forget about the please, DO it!) -The C++ files implement a subclass of QmitkFunctionality, so they ARE functionalities. In this -special case of QmitkRegionGrowing, we added the ability to set some seed points and run a region grower. -If your are interested in the concrete changes necessary to turn a freshly generated QmitkRegionGrowing into an integrated one: +The C++ files implement a subclass of QmitkAbstractView. In this special case of QmitkRegionGrowing, we added the ability to set some seed points and run a region grower. If you are interested in the concrete changes necessary to turn a freshly generated QmitkRegionGrowing into an integrated one: + +Since an access to the StdMultiWidget is needed, manifest_headers.cmake has to be edited: +\verbatim +set(Require-Plugin org.mitk.gui.qt.common org.mitk.gui.qt.stdmultiwidgeteditor) +\endverbatim To add a PointSet for the seed points: QmitkRegionGrowingView.h Add includes: \verbatim -#include "mitkPointSet.h" -#include +#include "QmitkPointListWidget.h" +#include "QmitkStdMultiWidget.h" +#include "QmitkStdMultiWidgetEditor.h" \endverbatim -Add the point set as protected object: +Add the point set as protected object and add Pointers for a QmitkPointListWidget and a QmitkStdMultiWidget: \verbatim /// \brief This is the actual seed point data object mitk::PointSet::Pointer m_PointSet; + +QmitkPointListWidget* lstPoints; +QmitkStdMultiWidget* m_MultiWidget; \endverbatim QmitkRegionGrowingView.cpp -Add includes: -\verbatim -#include "QmitkPointListWidget.h" -\endverbatim - CreateQtPartControl(): \verbatim +// create a QmitkPointListWidget and add it to the widget created from .ui file +lstPoints = new QmitkPointListWidget(); +m_Controls.verticalLayout->addWidget(lstPoints); + +// get access to StdMultiWidget by using RenderWindowPart +QmitkStdMultiWidgetEditor* qSMWE = dynamic_cast(GetRenderWindowPart()); +m_MultiWidget = qSMWE->GetStdMultiWidget(); + // let the point set widget know about the multi widget (crosshair updates) -m_Controls->lstPoints->SetMultiWidget( m_MultiWidget ); - +lstPoints->SetMultiWidget( m_MultiWidget ); + // create a new DataTreeNode containing a PointSet with some interaction m_PointSet = mitk::PointSet::New(); -mitk::DataTreeNode::Pointer pointSetNode = mitk::DataTreeNode::New(); +mitk::DataNode::Pointer pointSetNode = mitk::DataNode::New(); pointSetNode->SetData( m_PointSet ); pointSetNode->SetName("seed points for region growing"); pointSetNode->SetProperty("helper object", mitk::BoolProperty::New(true) ); pointSetNode->SetProperty("layer", mitk::IntProperty::New(1024) ); // add the pointset to the data tree (for rendering and access by other modules) -GetDefaultDataStorage()->Add( pointSetNode ); +GetDataStorage()->Add( pointSetNode ); // tell the GUI widget about out point set -m_Controls->lstPoints->SetPointSetNode( pointSetNode ); -\endverbatim - -StdMultiWidgetAvailable(): -\verbatim -m_Controls->lstPoints->SetMultiWidget( m_MultiWidget ); -\endverbatim -StdMultiWidgetNotAvailable(): -\verbatim -m_Controls->lstPoints->SetMultiWidget( NULL ); +lstPoints->SetPointSetNode( pointSetNode ); \endverbatim To use the ITK region grower: QmitkRegionGrowingView.h Add protected method: \verbatim /*! \brief ITK image processing function This function is templated like an ITK image. The MITK-Macro AccessByItk determines the actual pixel type and dimensionality of a given MITK image and calls this function for further processing (in our case region growing) */ template < typename TPixel, unsigned int VImageDimension > void ItkImageProcessing( itk::Image< TPixel, VImageDimension >* itkImage, mitk::Geometry3D* imageGeometry ); \endverbatim QmitkRegionGrowingView.cpp Add includes: \verbatim // MITK #include "mitkImageAccessByItk.h" #include "mitkITKImageImport.h" #include "mitkProperties.h" #include "mitkColorProperty.h" // ITK #include \endverbatim DoImageProcessing(); \verbatim // So we have an image. Let's see if the user has set some seed points already if ( m_PointSet->GetSize() == 0 ) { // no points there. Not good for region growing QMessageBox::information( NULL, "Region growing functionality", "Please set some seed points inside the image first.\n" "(hold Shift key and click left mouse button inside the image.)" ); return; } // actually perform region growing. Here we have both an image and some seed points AccessByItk_1( image, ItkImageProcessing, image->GetGeometry() ); // some magic to call the correctly templated function \endverbatim And add the new method: \verbatim template < typename TPixel, unsigned int VImageDimension > void QmitkRegionGrowingView::ItkImageProcessing( itk::Image< TPixel, VImageDimension >* itkImage, mitk::Geometry3D* imageGeometry ) { typedef itk::Image< TPixel, VImageDimension > InputImageType; typedef typename InputImageType::IndexType IndexType; // instantiate an ITK region growing filter, set its parameters typedef itk::ConnectedThresholdImageFilter RegionGrowingFilterType; typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New(); regionGrower->SetInput( itkImage ); // don't forget this // determine a thresholding interval IndexType seedIndex; TPixel min( std::numeric_limits::max() ); TPixel max( std::numeric_limits::min() ); mitk::PointSet::PointsContainer* points = m_PointSet->GetPointSet()->GetPoints(); for ( mitk::PointSet::PointsConstIterator pointsIterator = points->Begin(); pointsIterator != points->End(); ++pointsIterator ) { // first test if this point is inside the image at all if ( !imageGeometry->IsInside( pointsIterator.Value()) ) { continue; } // convert world coordinates to image indices imageGeometry->WorldToIndex( pointsIterator.Value(), seedIndex); // get the pixel value at this point TPixel currentPixelValue = itkImage->GetPixel( seedIndex ); // adjust minimum and maximum values if (currentPixelValue > max) max = currentPixelValue; if (currentPixelValue < min) min = currentPixelValue; regionGrower->AddSeed( seedIndex ); } std::cout << "Values between " << min << " and " << max << std::endl; min -= 30; max += 30; // set thresholds and execute filter regionGrower->SetLower( min ); regionGrower->SetUpper( max ); regionGrower->Update(); mitk::Image::Pointer resultImage = mitk::ImportItkImage( regionGrower->GetOutput() ); mitk::DataTreeNode::Pointer newNode = mitk::DataTreeNode::New(); newNode->SetData( resultImage ); // set some properties newNode->SetProperty("binary", mitk::BoolProperty::New(true)); newNode->SetProperty("name", mitk::StringProperty::New("dumb segmentation")); newNode->SetProperty("color", mitk::ColorProperty::New(1.0,0.0,0.0)); newNode->SetProperty("volumerendering", mitk::BoolProperty::New(true)); newNode->SetProperty("layer", mitk::IntProperty::New(1)); newNode->SetProperty("opacity", mitk::FloatProperty::New(0.5)); // add result to data tree this->GetDefaultDataStorage()->Add( newNode ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } \endverbatim Have fun using MITK! If you meet any difficulties during your first steps, don't hesitate to ask on the MITK mailing list mitk-users@lists.sourceforge.net! People there are kind and will try to help you. \ref Step08Page "[Previous step]" \ref Step10Page "[Next Step]" \ref TutorialPage "[Main tutorial page]" */ diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsNetworkCreator.cpp b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsNetworkCreator.cpp index 12317bfb1a..51069ccf02 100644 --- a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsNetworkCreator.cpp +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsNetworkCreator.cpp @@ -1,758 +1,758 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkConnectomicsNetworkCreator.h" #include #include #include "mitkConnectomicsConstantsManager.h" // VTK #include #include #include mitk::ConnectomicsNetworkCreator::ConnectomicsNetworkCreator() : m_FiberBundle() , m_Segmentation() , m_ConNetwork( mitk::ConnectomicsNetwork::New() ) , idCounter(0) , m_LabelToVertexMap() , m_LabelToNodePropertyMap() , allowLoops( false ) { } mitk::ConnectomicsNetworkCreator::ConnectomicsNetworkCreator( mitk::Image::Pointer segmentation, mitk::FiberBundleX::Pointer fiberBundle ) : m_FiberBundle(fiberBundle) , m_Segmentation(segmentation) , m_ConNetwork( mitk::ConnectomicsNetwork::New() ) , idCounter(0) , m_LabelToVertexMap() , m_LabelToNodePropertyMap() , allowLoops( false ) { } mitk::ConnectomicsNetworkCreator::~ConnectomicsNetworkCreator() { } void mitk::ConnectomicsNetworkCreator::SetFiberBundle(mitk::FiberBundleX::Pointer fiberBundle) { m_FiberBundle = fiberBundle; } void mitk::ConnectomicsNetworkCreator::SetSegmentation(mitk::Image::Pointer segmentation) { m_Segmentation = segmentation; } itk::Point mitk::ConnectomicsNetworkCreator::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } void mitk::ConnectomicsNetworkCreator::CreateNetworkFromFibersAndSegmentation() { //empty graph m_ConNetwork->clear(); m_LabelToVertexMap.clear(); m_LabelToNodePropertyMap.clear(); vtkSmartPointer fiberPolyData = m_FiberBundle->GetFiberPolyData(); vtkSmartPointer vLines = fiberPolyData->GetLines(); vLines->InitTraversal(); - //int numFibers = m_FiberBundle->GetNumFibers(); - int numFibers= 10; + int numFibers = m_FiberBundle->GetNumFibers(); for( int fiberID( 0 ); fiberID < numFibers; fiberID++ ) { vtkIdType numPointsInCell(0); vtkIdType* pointsInCell(NULL); vLines->GetNextCell ( numPointsInCell, pointsInCell ); TractType::Pointer singleTract = TractType::New(); for( int pointInCellID( 0 ); pointInCellID < numPointsInCell ; pointInCellID++) { // push back point PointType point = GetItkPoint( fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] ) ); singleTract->InsertElement( singleTract->Size(), point ); } //MappingStrategy strategy = EndElementPosition; //MappingStrategy strategy = JustEndPointVerticesNoLabel; MappingStrategy strategy = EndElementPositionAvoidingWhiteMatter; if ( singleTract && ( singleTract->Size() > 0 ) ) { AddConnectionToNetwork( ReturnAssociatedVertexPairForLabelPair( ReturnLabelForFiberTract( singleTract, strategy ) ) ); } } // provide network with geometry m_ConNetwork->SetGeometry( m_Segmentation->GetGeometry() ); + m_ConNetwork->UpdateBounds(); m_ConNetwork->SetIsModified( true ); MBI_INFO << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_INFO_NETWORK_CREATED; } void mitk::ConnectomicsNetworkCreator::AddConnectionToNetwork(ConnectionType newConnection) { VertexType vertexA = newConnection.first; VertexType vertexB = newConnection.second; // if vertices A and B exist if( vertexA && vertexB) { // check for loops (if they are not allowed if( allowLoops || !( vertexA == vertexB ) ) { // If the connection already exists, increment weight, else create connection if ( m_ConNetwork->EdgeExists( vertexA, vertexB ) ) { m_ConNetwork->IncreaseEdgeWeight( vertexA, vertexB ); } else { m_ConNetwork->AddEdge( vertexA, vertexB ); } } } } mitk::ConnectomicsNetworkCreator::VertexType mitk::ConnectomicsNetworkCreator::ReturnAssociatedVertexForLabel( ImageLabelType label ) { // if label is not known, create entry if( ! ( m_LabelToVertexMap.count( label ) > 0 ) ) { VertexType newVertex = m_ConNetwork->AddVertex( idCounter ); idCounter++; SupplyVertexWithInformation(label, newVertex); m_LabelToVertexMap.insert( std::pair< ImageLabelType, VertexType >( label, newVertex ) ); } //return associated vertex return m_LabelToVertexMap.find( label )->second; } mitk::ConnectomicsNetworkCreator::ConnectionType mitk::ConnectomicsNetworkCreator::ReturnAssociatedVertexPairForLabelPair( ImageLabelPairType labelpair ) { //hand both labels through to the single label function ConnectionType connection( ReturnAssociatedVertexForLabel(labelpair.first), ReturnAssociatedVertexForLabel(labelpair.second) ); return connection; } mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::ReturnLabelForFiberTract( TractType::Pointer singleTract, mitk::ConnectomicsNetworkCreator::MappingStrategy strategy) { switch( strategy ) { case EndElementPosition: { return EndElementPositionLabel( singleTract ); } case PrecomputeAndDistance: { return PrecomputeVertexLocationsBySegmentation( singleTract ); } case JustEndPointVerticesNoLabel: { return JustEndPointVerticesNoLabelTest( singleTract ); } case EndElementPositionAvoidingWhiteMatter: { return EndElementPositionLabelAvoidingWhiteMatter( singleTract ); } } // To remove warnings, this code should never be reached MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_MAPPING; ImageLabelPairType nullPair( NULL, NULL ); return nullPair; } mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::EndElementPositionLabel( TractType::Pointer singleTract ) { ImageLabelPairType labelpair; {// Note: .fib image tracts are safed using index coordinates mitk::Point3D firstElementFiberCoord, lastElementFiberCoord; mitk::Point3D firstElementSegCoord, lastElementSegCoord; mitk::Index3D firstElementSegIndex, lastElementSegIndex; if( singleTract->front().Size() != 3 ) { MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3; } for( int index = 0; index < singleTract->front().Size(); index++ ) { firstElementFiberCoord.SetElement( index, singleTract->front().GetElement( index ) ); lastElementFiberCoord.SetElement( index, singleTract->back().GetElement( index ) ); } // convert from fiber index coordinates to segmentation index coordinates FiberToSegmentationCoords( firstElementFiberCoord, firstElementSegCoord ); FiberToSegmentationCoords( lastElementFiberCoord, lastElementSegCoord ); for( int index = 0; index < 3; index++ ) { firstElementSegIndex.SetElement( index, firstElementSegCoord.GetElement( index ) ); lastElementSegIndex.SetElement( index, lastElementSegCoord.GetElement( index ) ); } int firstLabel = m_Segmentation->GetPixelValueByIndex( firstElementSegIndex ); int lastLabel = m_Segmentation->GetPixelValueByIndex( lastElementSegIndex ); labelpair.first = firstLabel; labelpair.second = lastLabel; // Add property to property map if( ! ( m_LabelToNodePropertyMap.count( firstLabel ) > 0 ) ) { NetworkNode firstNode; firstNode.coordinates.resize( 3 ); for( unsigned int index = 0; index < firstNode.coordinates.size() ; index++ ) { firstNode.coordinates[ index ] = firstElementSegIndex[ index ] ; } firstNode.label = LabelToString( firstLabel ); m_LabelToNodePropertyMap.insert( std::pair< ImageLabelType, NetworkNode >( firstLabel, firstNode ) ); } if( ! ( m_LabelToNodePropertyMap.count( lastLabel ) > 0 ) ) { NetworkNode lastNode; lastNode.coordinates.resize( 3 ); for( unsigned int index = 0; index < lastNode.coordinates.size() ; index++ ) { lastNode.coordinates[ index ] = lastElementSegIndex[ index ] ; } lastNode.label = LabelToString( lastLabel ); m_LabelToNodePropertyMap.insert( std::pair< ImageLabelType, NetworkNode >( lastLabel, lastNode ) ); } } return labelpair; } mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::PrecomputeVertexLocationsBySegmentation( TractType::Pointer singleTract ) { ImageLabelPairType labelpair; return labelpair; } mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::EndElementPositionLabelAvoidingWhiteMatter( TractType::Pointer singleTract ) { ImageLabelPairType labelpair; {// Note: .fib image tracts are safed using index coordinates mitk::Point3D firstElementFiberCoord, lastElementFiberCoord; mitk::Point3D firstElementSegCoord, lastElementSegCoord; mitk::Index3D firstElementSegIndex, lastElementSegIndex; if( singleTract->front().Size() != 3 ) { MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3; } for( int index = 0; index < singleTract->front().Size(); index++ ) { firstElementFiberCoord.SetElement( index, singleTract->front().GetElement( index ) ); lastElementFiberCoord.SetElement( index, singleTract->back().GetElement( index ) ); } // convert from fiber index coordinates to segmentation index coordinates FiberToSegmentationCoords( firstElementFiberCoord, firstElementSegCoord ); FiberToSegmentationCoords( lastElementFiberCoord, lastElementSegCoord ); for( int index = 0; index < 3; index++ ) { firstElementSegIndex.SetElement( index, firstElementSegCoord.GetElement( index ) ); lastElementSegIndex.SetElement( index, lastElementSegCoord.GetElement( index ) ); } int firstLabel = m_Segmentation->GetPixelValueByIndex( firstElementSegIndex ); int lastLabel = m_Segmentation->GetPixelValueByIndex( lastElementSegIndex ); // Check whether the labels belong to the white matter (which means, that the fibers ended early) bool extendFront(false), extendEnd(false), retractFront(false), retractEnd(false); extendFront = !IsNonWhiteMatterLabel( firstLabel ); extendEnd = !IsNonWhiteMatterLabel( lastLabel ); retractFront = IsBackgroundLabel( firstLabel ); retractEnd = IsBackgroundLabel( lastLabel ); //if( extendFront || extendEnd ) //{ //MBI_INFO << "Before Start: " << firstLabel << " at " << firstElementSegIndex[ 0 ] << " " << firstElementSegIndex[ 1 ] << " " << firstElementSegIndex[ 2 ] << " End: " << lastLabel << " at " << lastElementSegIndex[ 0 ] << " " << lastElementSegIndex[ 1 ] << " " << lastElementSegIndex[ 2 ]; //} if ( extendFront ) { std::vector< int > indexVectorOfPointsToUse; //Use first two points for direction indexVectorOfPointsToUse.push_back( 1 ); indexVectorOfPointsToUse.push_back( 0 ); // label and coordinate temp storage int tempLabel( firstLabel ); mitk::Index3D tempIndex = firstElementSegIndex; LinearExtensionUntilGreyMatter( indexVectorOfPointsToUse, singleTract, tempLabel, tempIndex ); firstLabel = tempLabel; firstElementSegIndex = tempIndex; } if ( extendEnd ) { std::vector< int > indexVectorOfPointsToUse; //Use last two points for direction indexVectorOfPointsToUse.push_back( singleTract->Size() - 2 ); indexVectorOfPointsToUse.push_back( singleTract->Size() - 1 ); // label and coordinate temp storage int tempLabel( lastLabel ); mitk::Index3D tempIndex = lastElementSegIndex; LinearExtensionUntilGreyMatter( indexVectorOfPointsToUse, singleTract, tempLabel, tempIndex ); lastLabel = tempLabel; lastElementSegIndex = tempIndex; } if ( retractFront ) { // label and coordinate temp storage int tempLabel( firstLabel ); mitk::Index3D tempIndex = firstElementSegIndex; RetractionUntilBrainMatter( true, singleTract, tempLabel, tempIndex ); firstLabel = tempLabel; firstElementSegIndex = tempIndex; } if ( retractEnd ) { // label and coordinate temp storage int tempLabel( lastLabel ); mitk::Index3D tempIndex = lastElementSegIndex; RetractionUntilBrainMatter( false, singleTract, tempLabel, tempIndex ); lastLabel = tempLabel; lastElementSegIndex = tempIndex; } //if( extendFront || extendEnd ) //{ // MBI_INFO << "After Start: " << firstLabel << " at " << firstElementSegIndex[ 0 ] << " " << firstElementSegIndex[ 1 ] << " " << firstElementSegIndex[ 2 ] << " End: " << lastLabel << " at " << lastElementSegIndex[ 0 ] << " " << lastElementSegIndex[ 1 ] << " " << lastElementSegIndex[ 2 ]; //} labelpair.first = firstLabel; labelpair.second = lastLabel; // Add property to property map if( ! ( m_LabelToNodePropertyMap.count( firstLabel ) > 0 ) ) { NetworkNode firstNode; firstNode.coordinates.resize( 3 ); for( unsigned int index = 0; index < firstNode.coordinates.size() ; index++ ) { firstNode.coordinates[ index ] = firstElementSegIndex[ index ] ; } firstNode.label = LabelToString( firstLabel ); m_LabelToNodePropertyMap.insert( std::pair< ImageLabelType, NetworkNode >( firstLabel, firstNode ) ); } if( ! ( m_LabelToNodePropertyMap.count( lastLabel ) > 0 ) ) { NetworkNode lastNode; lastNode.coordinates.resize( 3 ); for( unsigned int index = 0; index < lastNode.coordinates.size() ; index++ ) { lastNode.coordinates[ index ] = lastElementSegIndex[ index ] ; } lastNode.label = LabelToString( lastLabel ); m_LabelToNodePropertyMap.insert( std::pair< ImageLabelType, NetworkNode >( lastLabel, lastNode ) ); } } return labelpair; } mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::JustEndPointVerticesNoLabelTest( TractType::Pointer singleTract ) { ImageLabelPairType labelpair; {// Note: .fib image tracts are safed using index coordinates mitk::Point3D firstElementFiberCoord, lastElementFiberCoord; mitk::Point3D firstElementSegCoord, lastElementSegCoord; mitk::Index3D firstElementSegIndex, lastElementSegIndex; if( singleTract->front().Size() != 3 ) { MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3; } for( int index = 0; index < singleTract->front().Size(); index++ ) { firstElementFiberCoord.SetElement( index, singleTract->front().GetElement( index ) ); lastElementFiberCoord.SetElement( index, singleTract->back().GetElement( index ) ); } // convert from fiber index coordinates to segmentation index coordinates FiberToSegmentationCoords( firstElementFiberCoord, firstElementSegCoord ); FiberToSegmentationCoords( lastElementFiberCoord, lastElementSegCoord ); for( int index = 0; index < 3; index++ ) { firstElementSegIndex.SetElement( index, firstElementSegCoord.GetElement( index ) ); lastElementSegIndex.SetElement( index, lastElementSegCoord.GetElement( index ) ); } int firstLabel = 1 * firstElementSegIndex[ 0 ] + 1000 * firstElementSegIndex[ 1 ] + 1000000 * firstElementSegIndex[ 2 ]; int lastLabel = 1 * firstElementSegIndex[ 0 ] + 1000 * firstElementSegIndex[ 1 ] + 1000000 * firstElementSegIndex[ 2 ]; labelpair.first = firstLabel; labelpair.second = lastLabel; // Add property to property map if( ! ( m_LabelToNodePropertyMap.count( firstLabel ) > 0 ) ) { NetworkNode firstNode; firstNode.coordinates.resize( 3 ); for( unsigned int index = 0; index < firstNode.coordinates.size() ; index++ ) { firstNode.coordinates[ index ] = firstElementSegIndex[ index ] ; } firstNode.label = LabelToString( firstLabel ); m_LabelToNodePropertyMap.insert( std::pair< ImageLabelType, NetworkNode >( firstLabel, firstNode ) ); } if( ! ( m_LabelToNodePropertyMap.count( lastLabel ) > 0 ) ) { NetworkNode lastNode; lastNode.coordinates.resize( 3 ); for( unsigned int index = 0; index < lastNode.coordinates.size() ; index++ ) { lastNode.coordinates[ index ] = lastElementSegIndex[ index ] ; } lastNode.label = LabelToString( lastLabel ); m_LabelToNodePropertyMap.insert( std::pair< ImageLabelType, NetworkNode >( lastLabel, lastNode ) ); } } return labelpair; } void mitk::ConnectomicsNetworkCreator::SupplyVertexWithInformation( ImageLabelType& label, VertexType& vertex ) { // supply a vertex with the additional information belonging to the label // TODO: Implement additional information acquisition m_ConNetwork->SetLabel( vertex, m_LabelToNodePropertyMap.find( label )->second.label ); m_ConNetwork->SetCoordinates( vertex, m_LabelToNodePropertyMap.find( label )->second.coordinates ); } std::string mitk::ConnectomicsNetworkCreator::LabelToString( ImageLabelType& label ) { int tempInt = (int) label; std::stringstream ss;//create a stringstream std::string tempString; ss << tempInt;//add number to the stream tempString = ss.str(); return tempString;//return a string with the contents of the stream } mitk::ConnectomicsNetwork::Pointer mitk::ConnectomicsNetworkCreator::GetNetwork() { return m_ConNetwork; } void mitk::ConnectomicsNetworkCreator::FiberToSegmentationCoords( mitk::Point3D& fiberCoord, mitk::Point3D& segCoord ) { mitk::Point3D tempPoint; // convert from fiber index coordinates to segmentation index coordinates m_FiberBundle->GetGeometry()->IndexToWorld( fiberCoord, tempPoint ); m_Segmentation->GetGeometry()->WorldToIndex( tempPoint, segCoord ); } void mitk::ConnectomicsNetworkCreator::SegmentationToFiberCoords( mitk::Point3D& segCoord, mitk::Point3D& fiberCoord ) { mitk::Point3D tempPoint; // convert from fiber index coordinates to segmentation index coordinates m_Segmentation->GetGeometry()->IndexToWorld( segCoord, tempPoint ); m_FiberBundle->GetGeometry()->WorldToIndex( tempPoint, fiberCoord ); } bool mitk::ConnectomicsNetworkCreator::IsNonWhiteMatterLabel( int labelInQuestion ) { bool isWhite( false ); isWhite = ( ( labelInQuestion == freesurfer_Left_Cerebral_White_Matter ) || ( labelInQuestion == freesurfer_Left_Cerebellum_White_Matter ) || ( labelInQuestion == freesurfer_Right_Cerebral_White_Matter ) || ( labelInQuestion == freesurfer_Right_Cerebellum_White_Matter ) ); return !isWhite; } bool mitk::ConnectomicsNetworkCreator::IsBackgroundLabel( int labelInQuestion ) { bool isBackground( false ); isBackground = ( labelInQuestion == 0 ); return isBackground; } void mitk::ConnectomicsNetworkCreator::LinearExtensionUntilGreyMatter( std::vector & indexVectorOfPointsToUse, TractType::Pointer singleTract, int & label, mitk::Index3D & mitkIndex ) { if( indexVectorOfPointsToUse.size() > singleTract->Size() ) { MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_MORE_POINTS_THAN_PRESENT; return; } if( indexVectorOfPointsToUse.size() < 2 ) { MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_LESS_THAN_2; return; } for( int index( 0 ); index < indexVectorOfPointsToUse.size(); index++ ) { if( indexVectorOfPointsToUse[ index ] > singleTract->Size() ) { MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_BEYOND_END; return; } if( indexVectorOfPointsToUse[ index ] < 0 ) { MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_BEYOND_START; return; } } mitk::Point3D startPoint, endPoint; std::vector< double > differenceVector; differenceVector.resize( singleTract->front().Size() ); { // which points to use, currently only last two //TODO correct using all points int endPointIndex = indexVectorOfPointsToUse.size() - 1; int startPointIndex = indexVectorOfPointsToUse.size() - 2; // convert to segmentation coords mitk::Point3D startFiber, endFiber; for( int index = 0; index < singleTract->front().Size(); index++ ) { endFiber.SetElement( index, singleTract->GetElement( indexVectorOfPointsToUse[ endPointIndex ] ).GetElement( index ) ); startFiber.SetElement( index, singleTract->GetElement( indexVectorOfPointsToUse[ startPointIndex ] ).GetElement( index ) ); } FiberToSegmentationCoords( endFiber, endPoint ); FiberToSegmentationCoords( startFiber, startPoint ); // calculate straight line for( int index = 0; index < singleTract->front().Size(); index++ ) { differenceVector[ index ] = endPoint.GetElement( index ) - startPoint.GetElement( index ); } // normalizing direction vector double length( 0.0 ); double sum( 0.0 ); for( int index = 0; index < differenceVector.size() ; index++ ) { sum = sum + differenceVector[ index ] * differenceVector[ index ]; } length = std::sqrt( sum ); for( int index = 0; index < differenceVector.size() ; index++ ) { differenceVector[ index ] = differenceVector[ index ] / length; } // follow line until first non white matter label mitk::Index3D tempIndex; int tempLabel( label ); bool keepOn( true ); for( int parameter( 0 ) ; keepOn ; parameter++ ) { if( parameter > 1000 ) { MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_DID_NOT_FIND_WHITE; break; } for( int index( 0 ); index < 3; index++ ) { tempIndex.SetElement( index, endPoint.GetElement( index ) + parameter * differenceVector[ index ] ); } tempLabel = m_Segmentation->GetPixelValueByIndex( tempIndex ); if( IsNonWhiteMatterLabel( tempLabel ) ) { if( tempLabel < 1 ) { keepOn = false; MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_NOT_EXTEND_TO_WHITE; } else { label = tempLabel; mitkIndex = tempIndex; keepOn = false; } } } } } void mitk::ConnectomicsNetworkCreator::RetractionUntilBrainMatter( bool retractFront, TractType::Pointer singleTract, int & label, mitk::Index3D & mitkIndex ) { int retractionStartIndex( singleTract->Size() - 1 ); int retractionStepIndexSize( -1 ); int retractionTerminationIndex( 0 ); if( retractFront ) { retractionStartIndex = 0; retractionStepIndexSize = 1; retractionTerminationIndex = singleTract->Size() - 1; } int currentRetractionIndex = retractionStartIndex; bool keepRetracting( true ); mitk::Point3D currentPoint, nextPoint; std::vector< double > differenceVector; differenceVector.resize( singleTract->front().Size() ); while( keepRetracting && ( currentRetractionIndex != retractionTerminationIndex ) ) { // convert to segmentation coords mitk::Point3D currentPointFiberCoord, nextPointFiberCoord; for( int index = 0; index < singleTract->front().Size(); index++ ) { currentPointFiberCoord.SetElement( index, singleTract->GetElement( currentRetractionIndex ).GetElement( index ) ); nextPointFiberCoord.SetElement( index, singleTract->GetElement( currentRetractionIndex + retractionStepIndexSize ).GetElement( index ) ); } FiberToSegmentationCoords( currentPointFiberCoord, currentPoint ); FiberToSegmentationCoords( nextPointFiberCoord, nextPoint ); // calculate straight line for( int index = 0; index < singleTract->front().Size(); index++ ) { differenceVector[ index ] = nextPoint.GetElement( index ) - currentPoint.GetElement( index ); } // calculate length of direction vector double length( 0.0 ); double sum( 0.0 ); for( int index = 0; index < differenceVector.size() ; index++ ) { sum = sum + differenceVector[ index ] * differenceVector[ index ]; } length = std::sqrt( sum ); // retract mitk::Index3D tempIndex; int tempLabel( label ); for( int parameter( 0 ) ; parameter < length ; parameter++ ) { for( int index( 0 ); index < 3; index++ ) { tempIndex.SetElement( index, currentPoint.GetElement( index ) + ( 1.0 + parameter ) / ( 1.0 + length ) * differenceVector[ index ] ); } tempLabel = m_Segmentation->GetPixelValueByIndex( tempIndex ); if( !IsBackgroundLabel( tempLabel ) ) { label = tempLabel; mitkIndex = tempIndex; return; } // hit next point without finding brain matter currentRetractionIndex = currentRetractionIndex + retractionStepIndexSize; if( ( currentRetractionIndex < 1 ) || ( currentRetractionIndex > ( singleTract->Size() - 2 ) ) ) { keepRetracting = false; } } } } diff --git a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.cpp b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.cpp index 927ae173c6..d71742d711 100644 --- a/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.cpp +++ b/Modules/DiffusionImaging/Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.cpp @@ -1,350 +1,352 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkConnectomicsSyntheticNetworkGenerator.h" #include #include #include "mitkConnectomicsConstantsManager.h" #include //for random number generation #include "vxl/core/vnl/vnl_random.h" #include "vxl/core/vnl/vnl_math.h" mitk::ConnectomicsSyntheticNetworkGenerator::ConnectomicsSyntheticNetworkGenerator() { } mitk::ConnectomicsSyntheticNetworkGenerator::~ConnectomicsSyntheticNetworkGenerator() { } mitk::ConnectomicsNetwork::Pointer mitk::ConnectomicsSyntheticNetworkGenerator::CreateSyntheticNetwork(int networkTypeId, int paramterOne, double parameterTwo) { mitk::ConnectomicsNetwork::Pointer network = mitk::ConnectomicsNetwork::New(); // give the network an artificial geometry network->SetGeometry( this->GenerateDefaultGeometry() ); switch (networkTypeId) { case 0: GenerateSyntheticCubeNetwork( network, paramterOne, parameterTwo ); break; case 1: GenerateSyntheticCenterToSurfaceNetwork( network, paramterOne, parameterTwo ); break; case 2: GenerateSyntheticRandomNetwork( network, paramterOne, parameterTwo ); break; case 3: //GenerateSyntheticScaleFreeNetwork( network, 1000 ); break; case 4: //GenerateSyntheticSmallWorldNetwork( network, 1000 ); break; default: MBI_ERROR << "Unrecognized Network ID"; } + network->UpdateBounds(); + return network; } mitk::Geometry3D::Pointer mitk::ConnectomicsSyntheticNetworkGenerator::GenerateDefaultGeometry() { mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); double zero( 0.0 ); double one( 1.0 ); // origin = {0,0,0} mitk::Point3D origin; origin[0] = zero; origin[1] = zero; origin[2] = zero; geometry->SetOrigin(origin); // spacing = {1,1,1} float spacing[3]; spacing[0] = one; spacing[1] = one; spacing[2] = one; geometry->SetSpacing(spacing); // transform vtkMatrix4x4* transformMatrix = vtkMatrix4x4::New(); transformMatrix->SetElement(0,0,one); transformMatrix->SetElement(1,0,zero); transformMatrix->SetElement(2,0,zero); transformMatrix->SetElement(0,1,zero); transformMatrix->SetElement(1,1,one); transformMatrix->SetElement(2,1,zero); transformMatrix->SetElement(0,2,zero); transformMatrix->SetElement(1,2,zero); transformMatrix->SetElement(2,2,one); transformMatrix->SetElement(0,3,origin[0]); transformMatrix->SetElement(1,3,origin[1]); transformMatrix->SetElement(2,3,origin[2]); transformMatrix->SetElement(3,3,1); geometry->SetIndexToWorldTransformByVtkMatrix( transformMatrix ); geometry->SetImageGeometry(true); return geometry; } void mitk::ConnectomicsSyntheticNetworkGenerator::GenerateSyntheticCubeNetwork( mitk::ConnectomicsNetwork::Pointer network, int cubeExtent, double distance ) { // map for storing the conversion from indices to vertex descriptor std::map< int, mitk::ConnectomicsNetwork::VertexDescriptorType > idToVertexMap; int vertexID(0); for( int loopX( 0 ); loopX < cubeExtent; loopX++ ) { for( int loopY( 0 ); loopY < cubeExtent; loopY++ ) { for( int loopZ( 0 ); loopZ < cubeExtent; loopZ++ ) { std::vector< float > position; std::string label; std::stringstream labelStream; labelStream << vertexID; label = labelStream.str(); position.push_back( loopX * distance ); position.push_back( loopY * distance ); position.push_back( loopZ * distance ); mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = network->AddVertex( vertexID ); network->SetLabel( newVertex, label ); network->SetCoordinates( newVertex, position ); if ( idToVertexMap.count( vertexID ) > 0 ) { MITK_ERROR << "Aborting network creation, duplicate vertex ID generated."; return; } idToVertexMap.insert( std::pair< int, mitk::ConnectomicsNetwork::VertexDescriptorType >( vertexID, newVertex) ); vertexID++; } } } int edgeID(0), edgeSourceID(0), edgeTargetID(0); // uniform weight of one int edgeWeight(1); mitk::ConnectomicsNetwork::VertexDescriptorType source; mitk::ConnectomicsNetwork::VertexDescriptorType target; for( int loopX( 0 ); loopX < cubeExtent; loopX++ ) { for( int loopY( 0 ); loopY < cubeExtent; loopY++ ) { for( int loopZ( 0 ); loopZ < cubeExtent; loopZ++ ) { // to avoid creating an edge twice (this being an undirected graph) we only generate // edges in three directions, the others will be supplied by the corresponding nodes if( loopX != 0 ) { edgeTargetID = edgeSourceID - cubeExtent * cubeExtent; source = idToVertexMap.find( edgeSourceID )->second; target = idToVertexMap.find( edgeTargetID )->second; network->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight); edgeID++; } if( loopY != 0 ) { edgeTargetID = edgeSourceID - cubeExtent; source = idToVertexMap.find( edgeSourceID )->second; target = idToVertexMap.find( edgeTargetID )->second; network->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight); edgeID++; } if( loopZ != 0 ) { edgeTargetID = edgeSourceID - 1; source = idToVertexMap.find( edgeSourceID )->second; target = idToVertexMap.find( edgeTargetID )->second; network->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight); edgeID++; } edgeSourceID++; } // end for( int loopZ( 0 ); loopZ < cubeExtent; loopZ++ ) } // end for( int loopY( 0 ); loopY < cubeExtent; loopY++ ) } // end for( int loopX( 0 ); loopX < cubeExtent; loopX++ ) } void mitk::ConnectomicsSyntheticNetworkGenerator::GenerateSyntheticCenterToSurfaceNetwork( mitk::ConnectomicsNetwork::Pointer network, int numberOfPoints, double radius ) { //the random number generators unsigned int randomOne = (unsigned int) rand(); unsigned int randomTwo = (unsigned int) rand(); vnl_random rng( (unsigned int) rand() ); vnl_random rng2( (unsigned int) rand() ); mitk::ConnectomicsNetwork::VertexDescriptorType centerVertex; int vertexID(0); { //add center vertex std::vector< float > position; std::string label; std::stringstream labelStream; labelStream << vertexID; label = labelStream.str(); position.push_back( 0 ); position.push_back( 0 ); position.push_back( 0 ); centerVertex = network->AddVertex( vertexID ); network->SetLabel( centerVertex, label ); network->SetCoordinates( centerVertex, position ); }//end add center vertex // uniform weight of one int edgeWeight(1); mitk::ConnectomicsNetwork::VertexDescriptorType source; mitk::ConnectomicsNetwork::VertexDescriptorType target; //add vertices on sphere surface for( int loopID( 1 ); loopID < numberOfPoints; loopID++ ) { std::vector< float > position; std::string label; std::stringstream labelStream; labelStream << loopID; label = labelStream.str(); //generate random, uniformly distributed points on a sphere surface const double uVariable = rng.drand64( 0.0 , 1.0); const double vVariable = rng.drand64( 0.0 , 1.0); const double phi = 2 * vnl_math::pi * uVariable; const double theta = std::acos( 2 * vVariable - 1 ); double xpos = radius * std::cos( phi ) * std::sin( theta ); double ypos = radius * std::sin( phi ) * std::sin( theta ); double zpos = radius * std::cos( theta ); position.push_back( xpos ); position.push_back( ypos ); position.push_back( zpos ); mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = network->AddVertex( loopID ); network->SetLabel( newVertex, label ); network->SetCoordinates( newVertex, position ); network->AddEdge( newVertex, centerVertex, loopID, 0, edgeWeight); } } void mitk::ConnectomicsSyntheticNetworkGenerator::GenerateSyntheticRandomNetwork( mitk::ConnectomicsNetwork::Pointer network, int numberOfPoints, double threshold ) { // as the surface is proportional to the square of the radius the density stays the same double radius = 5 * std::sqrt( (float) numberOfPoints ); //the random number generators unsigned int randomOne = (unsigned int) rand(); unsigned int randomTwo = (unsigned int) rand(); vnl_random rng( (unsigned int) rand() ); vnl_random rng2( (unsigned int) rand() ); // map for storing the conversion from indices to vertex descriptor std::map< int, mitk::ConnectomicsNetwork::VertexDescriptorType > idToVertexMap; //add vertices on sphere surface for( int loopID( 0 ); loopID < numberOfPoints; loopID++ ) { std::vector< float > position; std::string label; std::stringstream labelStream; labelStream << loopID; label = labelStream.str(); //generate random, uniformly distributed points on a sphere surface const double uVariable = rng.drand64( 0.0 , 1.0); const double vVariable = rng.drand64( 0.0 , 1.0); const double phi = 2 * vnl_math::pi * uVariable; const double theta = std::acos( 2 * vVariable - 1 ); double xpos = radius * std::cos( phi ) * std::sin( theta ); double ypos = radius * std::sin( phi ) * std::sin( theta ); double zpos = radius * std::cos( theta ); position.push_back( xpos ); position.push_back( ypos ); position.push_back( zpos ); mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = network->AddVertex( loopID ); network->SetLabel( newVertex, label ); network->SetCoordinates( newVertex, position ); if ( idToVertexMap.count( loopID ) > 0 ) { MITK_ERROR << "Aborting network creation, duplicate vertex ID generated."; return; } idToVertexMap.insert( std::pair< int, mitk::ConnectomicsNetwork::VertexDescriptorType >( loopID, newVertex) ); } int edgeID(0); // uniform weight of one int edgeWeight(1); mitk::ConnectomicsNetwork::VertexDescriptorType source; mitk::ConnectomicsNetwork::VertexDescriptorType target; for( int loopID( 0 ); loopID < numberOfPoints; loopID++ ) { // to avoid creating an edge twice (this being an undirected graph) we only // potentially generate edges with all nodes with a bigger ID for( int innerLoopID( loopID ); innerLoopID < numberOfPoints; innerLoopID++ ) { if( rng.drand64( 0.0 , 1.0) > threshold) { // do nothing } else { source = idToVertexMap.find( loopID )->second; target = idToVertexMap.find( innerLoopID )->second; network->AddEdge( source, target, loopID, innerLoopID, edgeWeight); edgeID++; } } // end for( int innerLoopID( loopID ); innerLoopID < numberOfPoints; innerLoopID++ ) } // end for( int loopID( 0 ); loopID < numberOfPoints; loopID++ ) } \ No newline at end of file diff --git a/Modules/DiffusionImaging/Algorithms/itkExtractChannelFromRgbaImageFilter.cpp b/Modules/DiffusionImaging/Algorithms/itkExtractChannelFromRgbaImageFilter.cpp new file mode 100644 index 0000000000..b3d0bc068a --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/itkExtractChannelFromRgbaImageFilter.cpp @@ -0,0 +1,159 @@ +#include "itkExtractChannelFromRgbaImageFilter.h" + +// VTK +#include +#include +#include + +// misc +#include + +namespace itk{ + + template< class OutputImageType > + ExtractChannelFromRgbaImageFilter< OutputImageType >::ExtractChannelFromRgbaImageFilter(): + m_Channel(RED) + { + + } + + template< class OutputImageType > + ExtractChannelFromRgbaImageFilter< OutputImageType >::~ExtractChannelFromRgbaImageFilter() + { + } + + template< class OutputImageType > + void ExtractChannelFromRgbaImageFilter< OutputImageType >::GenerateData() + { + + typename InputImageType::Pointer rgbaImage = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) ); + + typename OutputImageType::Pointer outputImage = + static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0)); + + typename InputImageType::RegionType region = rgbaImage->GetLargestPossibleRegion(); + outputImage->SetSpacing( m_ReferenceImage->GetSpacing() ); // Set the image spacing + outputImage->SetOrigin( m_ReferenceImage->GetOrigin() ); // Set the image origin + outputImage->SetDirection( m_ReferenceImage->GetDirection() ); // Set the image direction + outputImage->SetRegions( m_ReferenceImage->GetLargestPossibleRegion()); + outputImage->Allocate(); + outputImage->FillBuffer(0); + float* outImageBufferPointer = outputImage->GetBufferPointer(); + + itk::Image< short, 3 >::Pointer counterImage = itk::Image< short, 3 >::New(); + counterImage->SetSpacing( m_ReferenceImage->GetSpacing() ); // Set the image spacing + counterImage->SetOrigin( m_ReferenceImage->GetOrigin() ); // Set the image origin + counterImage->SetDirection( m_ReferenceImage->GetDirection() ); // Set the image direction + counterImage->SetRegions( m_ReferenceImage->GetLargestPossibleRegion()); + counterImage->Allocate(); + counterImage->FillBuffer(0); + short* counterImageBufferPointer = counterImage->GetBufferPointer(); + + int w = m_ReferenceImage->GetLargestPossibleRegion().GetSize().GetElement(0); + int h = m_ReferenceImage->GetLargestPossibleRegion().GetSize().GetElement(1); + int d = m_ReferenceImage->GetLargestPossibleRegion().GetSize().GetElement(2); + + typedef ImageRegionConstIterator< InputImageType > InImageIteratorType; + InImageIteratorType rgbaIt(rgbaImage, region); + rgbaIt.GoToBegin(); + while(!rgbaIt.IsAtEnd()){ + + InPixelType x = rgbaIt.Get(); + + itk::Point vertex; + itk::Index<3> index = rgbaIt.GetIndex(); + + rgbaImage->TransformIndexToPhysicalPoint(index, vertex); + outputImage->TransformPhysicalPointToIndex(vertex, index); + + itk::ContinuousIndex contIndex; + outputImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex); + + float frac_x = contIndex[0] - index[0]; + float frac_y = contIndex[1] - index[1]; + float frac_z = contIndex[2] - index[2]; + int px = index[0]; + if (frac_x<0) + { + px -= 1; + frac_x += 1; + } + int py = index[1]; + if (frac_y<0) + { + py -= 1; + frac_y += 1; + } + int pz = index[2]; + if (frac_z<0) + { + pz -= 1; + frac_z += 1; + } + frac_x = 1-frac_x; + frac_y = 1-frac_y; + frac_z = 1-frac_z; + + // int coordinates inside image? + if (px < 0 || px >= w-1) + continue; + if (py < 0 || py >= h-1) + continue; + if (pz < 0 || pz >= d-1) + continue; + + OutPixelType out; + switch (m_Channel) + { + case RED: + out = (float)x.GetRed()/255; + break; + case GREEN: + out = (float)x.GetGreen()/255; + break; + case BLUE: + out = (float)x.GetBlue()/255; + break; + case ALPHA: + out = (float)x.GetAlpha()/255; + } + + outImageBufferPointer[( px + w*(py + h*pz ))] += out*( frac_x)*( frac_y)*( frac_z); + outImageBufferPointer[( px + w*(py+1+ h*pz ))] += out*( frac_x)*(1-frac_y)*( frac_z); + outImageBufferPointer[( px + w*(py + h*pz+h))] += out*( frac_x)*( frac_y)*(1-frac_z); + outImageBufferPointer[( px + w*(py+1+ h*pz+h))] += out*( frac_x)*(1-frac_y)*(1-frac_z); + outImageBufferPointer[( px+1 + w*(py + h*pz ))] += out*(1-frac_x)*( frac_y)*( frac_z); + outImageBufferPointer[( px+1 + w*(py + h*pz+h))] += out*(1-frac_x)*( frac_y)*(1-frac_z); + outImageBufferPointer[( px+1 + w*(py+1+ h*pz ))] += out*(1-frac_x)*(1-frac_y)*( frac_z); + outImageBufferPointer[( px+1 + w*(py+1+ h*pz+h))] += out*(1-frac_x)*(1-frac_y)*(1-frac_z); + + counterImageBufferPointer[( px + w*(py + h*pz ))] += 1; + counterImageBufferPointer[( px + w*(py+1+ h*pz ))] += 1; + counterImageBufferPointer[( px + w*(py + h*pz+h))] += 1; + counterImageBufferPointer[( px + w*(py+1+ h*pz+h))] += 1; + counterImageBufferPointer[( px+1 + w*(py + h*pz ))] += 1; + counterImageBufferPointer[( px+1 + w*(py + h*pz+h))] += 1; + counterImageBufferPointer[( px+1 + w*(py+1+ h*pz ))] += 1; + counterImageBufferPointer[( px+1 + w*(py+1+ h*pz+h))] += 1; + +// outputImage->SetPixel(index, outputImage->GetPixel(index)+out); +// counterImage->SetPixel(index, counterImage->GetPixel(index)+1); + + ++rgbaIt; + } + + typedef ImageRegionIterator< OutputImageType > OutImageIteratorType; + OutImageIteratorType outIt(outputImage, outputImage->GetLargestPossibleRegion()); + outIt.GoToBegin(); + typedef ImageRegionConstIterator< itk::Image< short, 3 > > CountImageIteratorType; + CountImageIteratorType counterIt(counterImage, counterImage->GetLargestPossibleRegion()); + counterIt.GoToBegin(); + + while(!outIt.IsAtEnd() && !counterIt.IsAtEnd()){ + if (counterIt.Value()>0) + outIt.Set(outIt.Value()/counterIt.Value()); + ++outIt; + ++counterIt; + } + } +} diff --git a/Modules/DiffusionImaging/Algorithms/itkExtractChannelFromRgbaImageFilter.h b/Modules/DiffusionImaging/Algorithms/itkExtractChannelFromRgbaImageFilter.h new file mode 100644 index 0000000000..e9fdc6e6f4 --- /dev/null +++ b/Modules/DiffusionImaging/Algorithms/itkExtractChannelFromRgbaImageFilter.h @@ -0,0 +1,59 @@ +#ifndef __itkExtractChannelFromRgbaImageFilter_h__ +#define __itkExtractChannelFromRgbaImageFilter_h__ + +#include +#include +#include +#include + +namespace itk{ + +template< class OutputImageType > +class ExtractChannelFromRgbaImageFilter : public ImageToImageFilter< itk::Image,3>, OutputImageType > +{ + +public: + + enum Channel { + RED, + GREEN, + BLUE, + ALPHA + }; + + typedef ExtractChannelFromRgbaImageFilter Self; + typedef ProcessObject Superclass; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + + typedef itk::Image,3> InputImageType; + typedef typename OutputImageType::PixelType OutPixelType; + typedef typename InputImageType::PixelType InPixelType; + + typedef itk::VectorImage< short int, 3 > ReferenceImageType; + + itkNewMacro(Self); + itkTypeMacro( ExtractChannelFromRgbaImageFilter, ImageSource ); + + /** Upsampling factor **/ + + void GenerateData(); + + itkSetMacro(Channel, Channel) + itkSetMacro(ReferenceImage, ReferenceImageType::Pointer) + +protected: + + ExtractChannelFromRgbaImageFilter(); + virtual ~ExtractChannelFromRgbaImageFilter(); + Channel m_Channel; + ReferenceImageType::Pointer m_ReferenceImage; +}; + +} + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkExtractChannelFromRgbaImageFilter.cpp" +#endif + +#endif // __itkExtractChannelFromRgbaImageFilter_h__ diff --git a/Modules/DiffusionImaging/Algorithms/itkTractDensityImageFilter.cpp b/Modules/DiffusionImaging/Algorithms/itkTractDensityImageFilter.cpp index 69cc220f6e..0785d38b97 100644 --- a/Modules/DiffusionImaging/Algorithms/itkTractDensityImageFilter.cpp +++ b/Modules/DiffusionImaging/Algorithms/itkTractDensityImageFilter.cpp @@ -1,200 +1,203 @@ #include "itkTractDensityImageFilter.h" // VTK #include #include #include // misc #include namespace itk{ template< class OutputImageType > TractDensityImageFilter< OutputImageType >::TractDensityImageFilter() : m_BinaryOutput(false) , m_InvertImage(false) , m_UpsamplingFactor(1) , m_InputImage(NULL) , m_UseImageGeometry(false) { } template< class OutputImageType > TractDensityImageFilter< OutputImageType >::~TractDensityImageFilter() { } template< class OutputImageType > itk::Point TractDensityImageFilter< OutputImageType >::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } template< class OutputImageType > void TractDensityImageFilter< OutputImageType >::GenerateData() { // generate upsampled image mitk::Geometry3D::Pointer geometry = m_FiberBundle->GetGeometry(); typename OutputImageType::Pointer outImage = this->GetOutput(); // calculate new image parameters mitk::Vector3D newSpacing; mitk::Point3D newOrigin; itk::Matrix newDirection; ImageRegion<3> upsampledRegion; if (m_UseImageGeometry && !m_InputImage.IsNull()) { newSpacing = m_InputImage->GetSpacing()/m_UpsamplingFactor; upsampledRegion = m_InputImage->GetLargestPossibleRegion(); newOrigin = m_InputImage->GetOrigin(); typename OutputImageType::RegionType::SizeType size = upsampledRegion.GetSize(); size[0] *= m_UpsamplingFactor; size[1] *= m_UpsamplingFactor; size[2] *= m_UpsamplingFactor; upsampledRegion.SetSize(size); newDirection = m_InputImage->GetDirection(); } else { newSpacing = geometry->GetSpacing()/m_UpsamplingFactor; newOrigin = geometry->GetOrigin(); mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds(); newOrigin[0] += bounds.GetElement(0); newOrigin[1] += bounds.GetElement(2); newOrigin[2] += bounds.GetElement(4); for (int i=0; i<3; i++) for (int j=0; j<3; j++) newDirection[j][i] = geometry->GetMatrixColumn(i)[j]; upsampledRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor); upsampledRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor); upsampledRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor); } typename OutputImageType::RegionType::SizeType upsampledSize = upsampledRegion.GetSize(); // apply new image parameters outImage->SetSpacing( newSpacing ); outImage->SetOrigin( newOrigin ); outImage->SetDirection( newDirection ); outImage->SetRegions( upsampledRegion ); outImage->Allocate(); int w = upsampledSize[0]; int h = upsampledSize[1]; int d = upsampledSize[2]; // set/initialize output OutPixelType* outImageBufferPointer = (OutPixelType*)outImage->GetBufferPointer(); for (int i=0; iGetDeepCopy(); m_FiberBundle->ResampleFibers(minSpacing/10); vtkSmartPointer fiberPolyData = m_FiberBundle->GetFiberPolyData(); vtkSmartPointer vLines = fiberPolyData->GetLines(); vLines->InitTraversal(); int numFibers = m_FiberBundle->GetNumFibers(); for( int i=0; iGetNextCell ( numPoints, points ); // fill output image for( int j=0; j vertex = GetItkPoint(fiberPolyData->GetPoint(points[j])); itk::Index<3> index; itk::ContinuousIndex contIndex; outImage->TransformPhysicalPointToIndex(vertex, index); outImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex); float frac_x = contIndex[0] - index[0]; float frac_y = contIndex[1] - index[1]; float frac_z = contIndex[2] - index[2]; int px = index[0]; if (frac_x<0) { px -= 1; frac_x += 1; } int py = index[1]; if (frac_y<0) { py -= 1; frac_y += 1; } int pz = index[2]; if (frac_z<0) { pz -= 1; frac_z += 1; } + frac_x = 1-frac_x; + frac_y = 1-frac_y; + frac_z = 1-frac_z; // int coordinates inside image? if (px < 0 || px >= w-1) continue; if (py < 0 || py >= h-1) continue; if (pz < 0 || pz >= d-1) continue; if (m_BinaryOutput) { outImageBufferPointer[( px + w*(py + h*pz ))] = 1; outImageBufferPointer[( px + w*(py+1+ h*pz ))] = 1; outImageBufferPointer[( px + w*(py + h*pz+h))] = 1; outImageBufferPointer[( px + w*(py+1+ h*pz+h))] = 1; outImageBufferPointer[( px+1 + w*(py + h*pz ))] = 1; outImageBufferPointer[( px+1 + w*(py + h*pz+h))] = 1; outImageBufferPointer[( px+1 + w*(py+1+ h*pz ))] = 1; outImageBufferPointer[( px+1 + w*(py+1+ h*pz+h))] = 1; } else { outImageBufferPointer[( px + w*(py + h*pz ))] += ( frac_x)*( frac_y)*( frac_z); outImageBufferPointer[( px + w*(py+1+ h*pz ))] += ( frac_x)*(1-frac_y)*( frac_z); outImageBufferPointer[( px + w*(py + h*pz+h))] += ( frac_x)*( frac_y)*(1-frac_z); outImageBufferPointer[( px + w*(py+1+ h*pz+h))] += ( frac_x)*(1-frac_y)*(1-frac_z); outImageBufferPointer[( px+1 + w*(py + h*pz ))] += (1-frac_x)*( frac_y)*( frac_z); outImageBufferPointer[( px+1 + w*(py + h*pz+h))] += (1-frac_x)*( frac_y)*(1-frac_z); outImageBufferPointer[( px+1 + w*(py+1+ h*pz ))] += (1-frac_x)*(1-frac_y)*( frac_z); outImageBufferPointer[( px+1 + w*(py+1+ h*pz+h))] += (1-frac_x)*(1-frac_y)*(1-frac_z); } } } if (!m_BinaryOutput) { OutPixelType max = 0; for (int i=0; i0) for (int i=0; i #include #include // misc #include namespace itk{ template< class OutputImageType > TractsToRgbaImageFilter< OutputImageType >::TractsToRgbaImageFilter() : m_BinaryOutput(false) , m_InvertImage(false) , m_UpsamplingFactor(1) , m_InputImage(NULL) , m_UseImageGeometry(false) { } template< class OutputImageType > TractsToRgbaImageFilter< OutputImageType >::~TractsToRgbaImageFilter() { } template< class OutputImageType > itk::Point TractsToRgbaImageFilter< OutputImageType >::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } template< class OutputImageType > void TractsToRgbaImageFilter< OutputImageType >::GenerateData() { if(&typeid(OutPixelType) != &typeid(itk::RGBAPixel)) return; // generate upsampled image mitk::Geometry3D::Pointer geometry = m_FiberBundle->GetGeometry(); typename OutputImageType::Pointer outImage = this->GetOutput(); // calculate new image parameters mitk::Vector3D newSpacing; mitk::Point3D newOrigin; itk::Matrix newDirection; ImageRegion<3> upsampledRegion; if (m_UseImageGeometry && !m_InputImage.IsNull()) { newSpacing = m_InputImage->GetSpacing()/m_UpsamplingFactor; upsampledRegion = m_InputImage->GetLargestPossibleRegion(); newOrigin = m_InputImage->GetOrigin(); typename OutputImageType::RegionType::SizeType size = upsampledRegion.GetSize(); size[0] *= m_UpsamplingFactor; size[1] *= m_UpsamplingFactor; size[2] *= m_UpsamplingFactor; upsampledRegion.SetSize(size); newDirection = m_InputImage->GetDirection(); } else { newSpacing = geometry->GetSpacing()/m_UpsamplingFactor; newOrigin = geometry->GetOrigin(); mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds(); newOrigin[0] += bounds.GetElement(0); newOrigin[1] += bounds.GetElement(2); newOrigin[2] += bounds.GetElement(4); for (int i=0; i<3; i++) for (int j=0; j<3; j++) newDirection[j][i] = geometry->GetMatrixColumn(i)[j]; upsampledRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor); upsampledRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor); upsampledRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor); } typename OutputImageType::RegionType::SizeType upsampledSize = upsampledRegion.GetSize(); // apply new image parameters outImage->SetSpacing( newSpacing ); outImage->SetOrigin( newOrigin ); outImage->SetDirection( newDirection ); outImage->SetRegions( upsampledRegion ); outImage->Allocate(); int w = upsampledSize[0]; int h = upsampledSize[1]; int d = upsampledSize[2]; // set/initialize output unsigned char* outImageBufferPointer = (unsigned char*)outImage->GetBufferPointer(); float* buffer = new float[w*h*d*4]; for (int i=0; iGetDeepCopy(); m_FiberBundle->ResampleFibers(minSpacing/10); vtkSmartPointer fiberPolyData = m_FiberBundle->GetFiberPolyData(); vtkSmartPointer vLines = fiberPolyData->GetLines(); vLines->InitTraversal(); int numFibers = m_FiberBundle->GetNumFibers(); for( int i=0; iGetNextCell ( numPoints, points ); // calc directions (which are used as weights) std::list< itk::Point > rgbweights; std::list intensities; for( int j=0; j vertex = GetItkPoint(fiberPolyData->GetPoint(points[j])); itk::Point vertexPost = GetItkPoint(fiberPolyData->GetPoint(points[j+1])); itk::Point dir; dir[0] = fabs((vertexPost[0] - vertex[0]) * outImage->GetSpacing()[0]); dir[1] = fabs((vertexPost[1] - vertex[1]) * outImage->GetSpacing()[1]); dir[2] = fabs((vertexPost[2] - vertex[2]) * outImage->GetSpacing()[2]); rgbweights.push_back(dir); float intensity = sqrt(dir[0]*dir[0]+dir[1]*dir[1]+dir[2]*dir[2]); intensities.push_back(intensity); // last point gets same as previous one if(j==numPoints-2) { rgbweights.push_back(dir); intensities.push_back(intensity); } } // fill output image for( int j=0; j vertex = GetItkPoint(fiberPolyData->GetPoint(points[j])); itk::Index<3> index; itk::ContinuousIndex contIndex; outImage->TransformPhysicalPointToIndex(vertex, index); outImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex); - int ix = Math::Round(contIndex[0]); - int iy = Math::Round(contIndex[1]); - int iz = Math::Round(contIndex[2]); + float frac_x = contIndex[0] - index[0]; + float frac_y = contIndex[1] - index[1]; + float frac_z = contIndex[2] - index[2]; - float frac_x = contIndex[0] - ix; - float frac_y = contIndex[1] - iy; - float frac_z = contIndex[2] - iz; - - int px = (int)contIndex[0]; + int px = index[0]; if (frac_x<0) { px -= 1; - frac_x *= -1; + frac_x += 1; } - int py = (int)contIndex[1]; + + int py = index[1]; if (frac_y<0) { py -= 1; - frac_y *= -1; + frac_y += 1; } - int pz = (int)contIndex[2]; + + int pz = index[2]; if (frac_z<0) { pz -= 1; - frac_z *= -1; + frac_z += 1; } // int coordinates inside image? if (px < 0 || px >= w-1) continue; if (py < 0 || py >= h-1) continue; if (pz < 0 || pz >= d-1) continue; float scale = 100 * pow((float)m_UpsamplingFactor,3); itk::Point rgbweight = rgbweights.front(); rgbweights.pop_front(); float intweight = intensities.front(); intensities.pop_front(); // add to r-channel in output image buffer[0+4*( px + w*(py + h*pz ))] += (1-frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[0] * scale; buffer[0+4*( px + w*(py+1+ h*pz ))] += (1-frac_x)*( frac_y)*(1-frac_z) * rgbweight[0] * scale; buffer[0+4*( px + w*(py + h*pz+h))] += (1-frac_x)*(1-frac_y)*( frac_z) * rgbweight[0] * scale; buffer[0+4*( px + w*(py+1+ h*pz+h))] += (1-frac_x)*( frac_y)*( frac_z) * rgbweight[0] * scale; buffer[0+4*( px+1 + w*(py + h*pz ))] += ( frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[0] * scale; buffer[0+4*( px+1 + w*(py + h*pz+h))] += ( frac_x)*(1-frac_y)*( frac_z) * rgbweight[0] * scale; buffer[0+4*( px+1 + w*(py+1+ h*pz ))] += ( frac_x)*( frac_y)*(1-frac_z) * rgbweight[0] * scale; buffer[0+4*( px+1 + w*(py+1+ h*pz+h))] += ( frac_x)*( frac_y)*( frac_z) * rgbweight[0] * scale; // add to g-channel in output image buffer[1+4*( px + w*(py + h*pz ))] += (1-frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[1] * scale; buffer[1+4*( px + w*(py+1+ h*pz ))] += (1-frac_x)*( frac_y)*(1-frac_z) * rgbweight[1] * scale; buffer[1+4*( px + w*(py + h*pz+h))] += (1-frac_x)*(1-frac_y)*( frac_z) * rgbweight[1] * scale; buffer[1+4*( px + w*(py+1+ h*pz+h))] += (1-frac_x)*( frac_y)*( frac_z) * rgbweight[1] * scale; buffer[1+4*( px+1 + w*(py + h*pz ))] += ( frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[1] * scale; buffer[1+4*( px+1 + w*(py + h*pz+h))] += ( frac_x)*(1-frac_y)*( frac_z) * rgbweight[1] * scale; buffer[1+4*( px+1 + w*(py+1+ h*pz ))] += ( frac_x)*( frac_y)*(1-frac_z) * rgbweight[1] * scale; buffer[1+4*( px+1 + w*(py+1+ h*pz+h))] += ( frac_x)*( frac_y)*( frac_z) * rgbweight[1] * scale; // add to b-channel in output image buffer[2+4*( px + w*(py + h*pz ))] += (1-frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[2] * scale; buffer[2+4*( px + w*(py+1+ h*pz ))] += (1-frac_x)*( frac_y)*(1-frac_z) * rgbweight[2] * scale; buffer[2+4*( px + w*(py + h*pz+h))] += (1-frac_x)*(1-frac_y)*( frac_z) * rgbweight[2] * scale; buffer[2+4*( px + w*(py+1+ h*pz+h))] += (1-frac_x)*( frac_y)*( frac_z) * rgbweight[2] * scale; buffer[2+4*( px+1 + w*(py + h*pz ))] += ( frac_x)*(1-frac_y)*(1-frac_z) * rgbweight[2] * scale; buffer[2+4*( px+1 + w*(py + h*pz+h))] += ( frac_x)*(1-frac_y)*( frac_z) * rgbweight[2] * scale; buffer[2+4*( px+1 + w*(py+1+ h*pz ))] += ( frac_x)*( frac_y)*(1-frac_z) * rgbweight[2] * scale; buffer[2+4*( px+1 + w*(py+1+ h*pz+h))] += ( frac_x)*( frac_y)*( frac_z) * rgbweight[2] * scale; // add to a-channel in output image buffer[3+4*( px + w*(py + h*pz ))] += (1-frac_x)*(1-frac_y)*(1-frac_z) * intweight * scale; buffer[3+4*( px + w*(py+1+ h*pz ))] += (1-frac_x)*( frac_y)*(1-frac_z) * intweight * scale; buffer[3+4*( px + w*(py + h*pz+h))] += (1-frac_x)*(1-frac_y)*( frac_z) * intweight * scale; buffer[3+4*( px + w*(py+1+ h*pz+h))] += (1-frac_x)*( frac_y)*( frac_z) * intweight * scale; buffer[3+4*( px+1 + w*(py + h*pz ))] += ( frac_x)*(1-frac_y)*(1-frac_z) * intweight * scale; buffer[3+4*( px+1 + w*(py + h*pz+h))] += ( frac_x)*(1-frac_y)*( frac_z) * intweight * scale; buffer[3+4*( px+1 + w*(py+1+ h*pz ))] += ( frac_x)*( frac_y)*(1-frac_z) * intweight * scale; buffer[3+4*( px+1 + w*(py+1+ h*pz+h))] += ( frac_x)*( frac_y)*( frac_z) * intweight * scale; } } float maxRgb = 0.000000001; float maxInt = 0.000000001; int numPix; numPix = w*h*d*4; // calc maxima for(int i=0; i maxRgb) maxRgb = buffer[i]; } else { if(buffer[i] > maxInt) maxInt = buffer[i]; } } // write output, normalized uchar 0..255 for(int i=0; i #include #include #include #include #include "itkResampleImageFilter.h" #include "itkGaussianInterpolateImageFunction.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "itkGaussianInterpolateImageFunction.h" #include "itkBSplineInterpolateImageFunction.h" #include "itkNearestNeighborInterpolateImageFunction.h" #include "itkImageMaskSpatialObject.h" #include "itkRegionOfInterestImageFilter.h" #include "itkListSample.h" #include #include namespace mitk { PartialVolumeAnalysisHistogramCalculator::PartialVolumeAnalysisHistogramCalculator() : m_MaskingMode( MASKING_MODE_NONE ), m_MaskingModeChanged( false ), m_NumberOfBins(256), m_UpsamplingFactor(1), m_GaussianSigma(0), m_ForceUpdate(false), m_PlanarFigureThickness(0) { m_EmptyHistogram = HistogramType::New(); HistogramType::SizeType histogramSize; histogramSize.Fill( 256 ); m_EmptyHistogram->Initialize( histogramSize ); m_EmptyStatistics.Reset(); } PartialVolumeAnalysisHistogramCalculator::~PartialVolumeAnalysisHistogramCalculator() { } void PartialVolumeAnalysisHistogramCalculator::SetImage( const mitk::Image *image ) { if ( m_Image != image ) { m_Image = image; this->Modified(); m_ImageStatisticsTimeStamp.Modified(); m_ImageStatisticsCalculationTriggerBool = true; } } void PartialVolumeAnalysisHistogramCalculator::AddAdditionalResamplingImage( const mitk::Image *image ) { m_AdditionalResamplingImages.push_back(image); this->Modified(); m_ImageStatisticsTimeStamp.Modified(); m_ImageStatisticsCalculationTriggerBool = true; } void PartialVolumeAnalysisHistogramCalculator::SetModified( ) { this->Modified(); m_ImageStatisticsTimeStamp.Modified(); m_ImageStatisticsCalculationTriggerBool = true; m_MaskedImageStatisticsTimeStamp.Modified(); m_MaskedImageStatisticsCalculationTriggerBool = true; m_PlanarFigureStatisticsTimeStamp.Modified(); m_PlanarFigureStatisticsCalculationTriggerBool = true; } void PartialVolumeAnalysisHistogramCalculator::SetImageMask( const mitk::Image *imageMask ) { if ( m_Image.IsNull() ) { itkExceptionMacro( << "Image needs to be set first!" ); } if ( m_Image->GetTimeSteps() != imageMask->GetTimeSteps() ) { itkExceptionMacro( << "Image and image mask need to have equal number of time steps!" ); } if ( m_ImageMask != imageMask ) { m_ImageMask = imageMask; this->Modified(); m_MaskedImageStatisticsTimeStamp.Modified(); m_MaskedImageStatisticsCalculationTriggerBool = true; } } void PartialVolumeAnalysisHistogramCalculator::SetPlanarFigure( const mitk::PlanarFigure *planarFigure ) { if ( m_Image.IsNull() ) { itkExceptionMacro( << "Image needs to be set first!" ); } if ( m_PlanarFigure != planarFigure ) { m_PlanarFigure = planarFigure; this->Modified(); m_PlanarFigureStatisticsTimeStamp.Modified(); m_PlanarFigureStatisticsCalculationTriggerBool = true; } } void PartialVolumeAnalysisHistogramCalculator::SetMaskingMode( unsigned int mode ) { if ( m_MaskingMode != mode ) { m_MaskingMode = mode; m_MaskingModeChanged = true; this->Modified(); } } void PartialVolumeAnalysisHistogramCalculator::SetMaskingModeToNone() { if ( m_MaskingMode != MASKING_MODE_NONE ) { m_MaskingMode = MASKING_MODE_NONE; m_MaskingModeChanged = true; this->Modified(); } } void PartialVolumeAnalysisHistogramCalculator::SetMaskingModeToImage() { if ( m_MaskingMode != MASKING_MODE_IMAGE ) { m_MaskingMode = MASKING_MODE_IMAGE; m_MaskingModeChanged = true; this->Modified(); } } void PartialVolumeAnalysisHistogramCalculator::SetMaskingModeToPlanarFigure() { if ( m_MaskingMode != MASKING_MODE_PLANARFIGURE ) { m_MaskingMode = MASKING_MODE_PLANARFIGURE; m_MaskingModeChanged = true; this->Modified(); } } bool PartialVolumeAnalysisHistogramCalculator::ComputeStatistics() { MITK_INFO << "ComputeStatistics() start"; if ( m_Image.IsNull() ) { itkExceptionMacro( << "Image not set!" ); } if ( m_Image->GetReferenceCount() == 1 ) { MITK_INFO << "No Stats calculated; no one else holds a reference on it"; return false; } // If a mask was set but we are the only ones to still hold a reference on // it, delete it. if ( m_ImageMask.IsNotNull() && (m_ImageMask->GetReferenceCount() == 1) ) { m_ImageMask = NULL; } // Check if statistics is already up-to-date unsigned long imageMTime = m_ImageStatisticsTimeStamp.GetMTime(); unsigned long maskedImageMTime = m_MaskedImageStatisticsTimeStamp.GetMTime(); unsigned long planarFigureMTime = m_PlanarFigureStatisticsTimeStamp.GetMTime(); bool imageStatisticsCalculationTrigger = m_ImageStatisticsCalculationTriggerBool; bool maskedImageStatisticsCalculationTrigger = m_MaskedImageStatisticsCalculationTriggerBool; bool planarFigureStatisticsCalculationTrigger = m_PlanarFigureStatisticsCalculationTriggerBool; if ( /*prevent calculation without mask*/!m_ForceUpdate &&( m_MaskingMode == MASKING_MODE_NONE || ( ((m_MaskingMode != MASKING_MODE_NONE) || (imageMTime > m_Image->GetMTime() && !imageStatisticsCalculationTrigger)) && ((m_MaskingMode != MASKING_MODE_IMAGE) || (m_ImageMask.IsNotNull() && maskedImageMTime > m_ImageMask->GetMTime() && !maskedImageStatisticsCalculationTrigger)) && ((m_MaskingMode != MASKING_MODE_PLANARFIGURE) || (m_PlanarFigure.IsNotNull() && planarFigureMTime > m_PlanarFigure->GetMTime() && !planarFigureStatisticsCalculationTrigger)) ) ) ) { MITK_INFO << "Returning, statistics already up to date!"; if ( m_MaskingModeChanged ) { m_MaskingModeChanged = false; return true; } else { return false; } } // Reset state changed flag m_MaskingModeChanged = false; // Depending on masking mode, extract and/or generate the required image // and mask data from the user input this->ExtractImageAndMask( ); Statistics *statistics; HistogramType::ConstPointer *histogram; switch ( m_MaskingMode ) { case MASKING_MODE_NONE: default: statistics = &m_ImageStatistics; histogram = &m_ImageHistogram; m_ImageStatisticsTimeStamp.Modified(); m_ImageStatisticsCalculationTriggerBool = false; break; case MASKING_MODE_IMAGE: statistics = &m_MaskedImageStatistics; histogram = &m_MaskedImageHistogram; m_MaskedImageStatisticsTimeStamp.Modified(); m_MaskedImageStatisticsCalculationTriggerBool = false; break; case MASKING_MODE_PLANARFIGURE: statistics = &m_PlanarFigureStatistics; histogram = &m_PlanarFigureHistogram; m_PlanarFigureStatisticsTimeStamp.Modified(); m_PlanarFigureStatisticsCalculationTriggerBool = false; break; } // Calculate statistics and histogram(s) if ( m_InternalImage->GetDimension() == 3 ) { if ( m_MaskingMode == MASKING_MODE_NONE ) { // Reset state changed flag AccessFixedDimensionByItk_2( m_InternalImage, InternalCalculateStatisticsUnmasked, 3, *statistics, histogram ); } else { AccessFixedDimensionByItk_3( m_InternalImage, InternalCalculateStatisticsMasked, 3, m_InternalImageMask3D.GetPointer(), *statistics, histogram ); } } else if ( m_InternalImage->GetDimension() == 2 ) { if ( m_MaskingMode == MASKING_MODE_NONE ) { AccessFixedDimensionByItk_2( m_InternalImage, InternalCalculateStatisticsUnmasked, 2, *statistics, histogram ); } else { AccessFixedDimensionByItk_3( m_InternalImage, InternalCalculateStatisticsMasked, 2, m_InternalImageMask2D.GetPointer(), *statistics, histogram ); } } else { MITK_ERROR << "ImageStatistics: Image dimension not supported!"; } // Release unused image smart pointers to free memory // m_InternalImage = mitk::Image::Pointer(); m_InternalImageMask3D = MaskImage3DType::Pointer(); m_InternalImageMask2D = MaskImage2DType::Pointer(); return true; } const PartialVolumeAnalysisHistogramCalculator::HistogramType * PartialVolumeAnalysisHistogramCalculator::GetHistogram( ) const { if ( m_Image.IsNull() ) { return NULL; } switch ( m_MaskingMode ) { case MASKING_MODE_NONE: default: return m_ImageHistogram; case MASKING_MODE_IMAGE: return m_MaskedImageHistogram; case MASKING_MODE_PLANARFIGURE: return m_PlanarFigureHistogram; } } const PartialVolumeAnalysisHistogramCalculator::Statistics & PartialVolumeAnalysisHistogramCalculator::GetStatistics( ) const { if ( m_Image.IsNull() ) { return m_EmptyStatistics; } switch ( m_MaskingMode ) { case MASKING_MODE_NONE: default: return m_ImageStatistics; case MASKING_MODE_IMAGE: return m_MaskedImageStatistics; case MASKING_MODE_PLANARFIGURE: return m_PlanarFigureStatistics; } } void PartialVolumeAnalysisHistogramCalculator::ExtractImageAndMask( ) { MITK_INFO << "ExtractImageAndMask( ) start"; if ( m_Image.IsNull() ) { throw std::runtime_error( "Error: image empty!" ); } mitk::Image *timeSliceImage = const_cast(m_Image.GetPointer());//imageTimeSelector->GetOutput(); switch ( m_MaskingMode ) { case MASKING_MODE_NONE: { m_InternalImage = timeSliceImage; int s = m_AdditionalResamplingImages.size(); m_InternalAdditionalResamplingImages.resize(s); for(int i=0; i(m_AdditionalResamplingImages[i].GetPointer()); } m_InternalImageMask2D = NULL; m_InternalImageMask3D = NULL; break; } case MASKING_MODE_IMAGE: { if ( m_ImageMask.IsNotNull() && (m_ImageMask->GetReferenceCount() > 1) ) { ImageTimeSelector::Pointer maskedImageTimeSelector = ImageTimeSelector::New(); maskedImageTimeSelector->SetInput( m_ImageMask ); maskedImageTimeSelector->SetTimeNr( 0 ); maskedImageTimeSelector->UpdateLargestPossibleRegion(); mitk::Image *timeSliceMaskedImage = maskedImageTimeSelector->GetOutput(); InternalMaskImage(timeSliceMaskedImage); if(m_UpsamplingFactor != 1) { InternalResampleImage(m_InternalImageMask3D); } AccessFixedDimensionByItk_1( timeSliceImage, InternalResampleImageFromMask, 3, -1 ); int s = m_AdditionalResamplingImages.size(); m_InternalAdditionalResamplingImages.resize(s); for(int i=0; iIsClosed() ) { throw std::runtime_error( "Masking not possible for non-closed figures" ); } const Geometry3D *imageGeometry = timeSliceImage->GetUpdatedGeometry(); if ( imageGeometry == NULL ) { throw std::runtime_error( "Image geometry invalid!" ); } const Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D(); if ( planarFigureGeometry2D == NULL ) { throw std::runtime_error( "Planar-Figure not yet initialized!" ); } const PlaneGeometry *planarFigureGeometry = dynamic_cast< const PlaneGeometry * >( planarFigureGeometry2D ); if ( planarFigureGeometry == NULL ) { throw std::runtime_error( "Non-planar planar figures not supported!" ); } // unsigned int axis = 2; // unsigned int slice = 0; AccessFixedDimensionByItk_3( timeSliceImage, InternalReorientImagePlane, 3, timeSliceImage->GetGeometry(), m_PlanarFigure->GetGeometry(), -1 ); AccessFixedDimensionByItk_1( m_InternalImage, InternalCalculateMaskFromPlanarFigure, 3, 2 ); int s = m_AdditionalResamplingImages.size(); for(int i=0; iGetGeometry(), m_PlanarFigure->GetGeometry(), i ); AccessFixedDimensionByItk_1( m_InternalAdditionalResamplingImages[i], InternalCropAdditionalImage, 3, i ); } } } } bool PartialVolumeAnalysisHistogramCalculator::GetPrincipalAxis( const Geometry3D *geometry, Vector3D vector, unsigned int &axis ) { vector.Normalize(); for ( unsigned int i = 0; i < 3; ++i ) { Vector3D axisVector = geometry->GetAxisVector( i ); axisVector.Normalize(); if ( fabs( fabs( axisVector * vector ) - 1.0) < mitk::eps ) { axis = i; return true; } } return false; } void PartialVolumeAnalysisHistogramCalculator::InternalMaskImage( mitk::Image *image ) { typedef itk::ImageMaskSpatialObject<3> ImageMaskSpatialObject; typedef itk::Image< unsigned char, 3 > ImageType; typedef itk::ImageRegion<3> RegionType; typedef mitk::ImageToItk CastType; CastType::Pointer caster = CastType::New(); caster->SetInput(image); caster->Update(); ImageMaskSpatialObject::Pointer maskSO = ImageMaskSpatialObject::New(); maskSO->SetImage ( caster->GetOutput() ); m_InternalMask3D = maskSO->GetAxisAlignedBoundingBoxRegion(); MITK_INFO << "Bounding Box Region: " << m_InternalMask3D; typedef itk::RegionOfInterestImageFilter< ImageType, MaskImage3DType > ROIFilterType; ROIFilterType::Pointer roi = ROIFilterType::New(); roi->SetRegionOfInterest(m_InternalMask3D); roi->SetInput(caster->GetOutput()); roi->Update(); m_InternalImageMask3D = roi->GetOutput(); MITK_INFO << "Created m_InternalImageMask3D"; } template < typename TPixel, unsigned int VImageDimension > void PartialVolumeAnalysisHistogramCalculator::InternalReorientImagePlane( const itk::Image< TPixel, VImageDimension > *image, mitk::Geometry3D* imggeo, mitk::Geometry3D* planegeo3D, int additionalIndex ) { MITK_INFO << "InternalReorientImagePlane() start"; typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::Image< float, VImageDimension > FloatImageType; typedef itk::ResampleImageFilter ResamplerType; typename ResamplerType::Pointer resampler = ResamplerType::New(); mitk::PlaneGeometry* planegeo = dynamic_cast(planegeo3D); float upsamp = m_UpsamplingFactor; float gausssigma = m_GaussianSigma; // Spacing typename ResamplerType::SpacingType spacing = planegeo->GetSpacing(); spacing[0] = image->GetSpacing()[0] / upsamp; spacing[1] = image->GetSpacing()[1] / upsamp; spacing[2] = image->GetSpacing()[2]; if(m_PlanarFigureThickness) { spacing[2] = image->GetSpacing()[2] / upsamp; } resampler->SetOutputSpacing( spacing ); - MITK_INFO << "resampling spacing: " << spacing[0] << ", " << spacing[1] << ", " << spacing[2]; - // Size typename ResamplerType::SizeType size; size[0] = planegeo->GetParametricExtentInMM(0) / spacing[0]; size[1] = planegeo->GetParametricExtentInMM(1) / spacing[1]; size[2] = 1+2*m_PlanarFigureThickness; // klaus add +2*m_PlanarFigureThickness MITK_INFO << "setting size2:="<SetSize( size ); - MITK_INFO << "resampling size: " << size[0] << ", " << size[1] << ", " << size[2]; - // Origin typename mitk::Point3D orig = planegeo->GetOrigin(); typename mitk::Point3D corrorig; planegeo3D->WorldToIndex(orig,corrorig); corrorig[0] += 0.5/upsamp; corrorig[1] += 0.5/upsamp; if(m_PlanarFigureThickness) { float thickyyy = m_PlanarFigureThickness; thickyyy/=upsamp; - MITK_INFO << "setting origin2-="<IndexToWorld(corrorig,corrorig); resampler->SetOutputOrigin(corrorig ); // Direction typename ResamplerType::DirectionType direction; typename mitk::AffineTransform3D::MatrixType matrix = planegeo->GetIndexToWorldTransform()->GetMatrix(); for(int c=0; cSetOutputDirection( direction ); // Gaussian interpolation if(gausssigma != 0) { double sigma[3]; for( unsigned int d = 0; d < 3; d++ ) { sigma[d] = gausssigma * image->GetSpacing()[d]; } double alpha = 2.0; typedef itk::GaussianInterpolateImageFunction GaussianInterpolatorType; typename GaussianInterpolatorType::Pointer interpolator = GaussianInterpolatorType::New(); interpolator->SetInputImage( image ); interpolator->SetParameters( sigma, alpha ); resampler->SetInterpolator( interpolator ); } else { // typedef typename itk::BSplineInterpolateImageFunction // InterpolatorType; typedef typename itk::LinearInterpolateImageFunction InterpolatorType; typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); interpolator->SetInputImage( image ); resampler->SetInterpolator( interpolator ); } // Other resampling options resampler->SetInput( image ); resampler->SetDefaultPixelValue(0); MITK_INFO << "Resampling requested image plane ... "; resampler->Update(); MITK_INFO << " ... done"; if(additionalIndex < 0) { this->m_InternalImage = mitk::Image::New(); this->m_InternalImage->InitializeByItk( resampler->GetOutput() ); this->m_InternalImage->SetVolume( resampler->GetOutput()->GetBufferPointer() ); } else { unsigned int myIndex = additionalIndex; this->m_InternalAdditionalResamplingImages.push_back(mitk::Image::New()); this->m_InternalAdditionalResamplingImages[myIndex]->InitializeByItk( resampler->GetOutput() ); this->m_InternalAdditionalResamplingImages[myIndex]->SetVolume( resampler->GetOutput()->GetBufferPointer() ); } } template < typename TPixel, unsigned int VImageDimension > void PartialVolumeAnalysisHistogramCalculator::InternalResampleImageFromMask( const itk::Image< TPixel, VImageDimension > *image, int additionalIndex ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typename ImageType::Pointer outImage = ImageType::New(); outImage->SetSpacing( m_InternalImageMask3D->GetSpacing() ); // Set the image spacing outImage->SetOrigin( m_InternalImageMask3D->GetOrigin() ); // Set the image origin outImage->SetDirection( m_InternalImageMask3D->GetDirection() ); // Set the image direction outImage->SetRegions( m_InternalImageMask3D->GetLargestPossibleRegion() ); outImage->Allocate(); outImage->FillBuffer(0); typedef itk::InterpolateImageFunction BaseInterpType; typedef itk::GaussianInterpolateImageFunction GaussianInterpolatorType; typedef itk::LinearInterpolateImageFunction LinearInterpolatorType; typename BaseInterpType::Pointer interpolator; if(m_GaussianSigma != 0) { double sigma[3]; for( unsigned int d = 0; d < 3; d++ ) { sigma[d] = m_GaussianSigma * image->GetSpacing()[d]; } double alpha = 2.0; interpolator = GaussianInterpolatorType::New(); dynamic_cast(interpolator.GetPointer())->SetParameters( sigma, alpha ); } else { interpolator = LinearInterpolatorType::New(); } interpolator->SetInputImage( image ); itk::ImageRegionConstIterator itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion()); itk::ImageRegionIterator itimage(outImage, outImage->GetLargestPossibleRegion()); itmask = itmask.Begin(); itimage = itimage.Begin(); itk::Point< double, 3 > point; itk::ContinuousIndex< double, 3 > index; while( !itmask.IsAtEnd() ) { if(itmask.Get() != 0) { outImage->TransformIndexToPhysicalPoint (itimage.GetIndex(), point); image->TransformPhysicalPointToContinuousIndex(point, index); itimage.Set(interpolator->EvaluateAtContinuousIndex(index)); } ++itmask; ++itimage; } if(additionalIndex < 0) { this->m_InternalImage = mitk::Image::New(); this->m_InternalImage->InitializeByItk( outImage.GetPointer() ); this->m_InternalImage->SetVolume( outImage->GetBufferPointer() ); } else { this->m_InternalAdditionalResamplingImages[additionalIndex] = mitk::Image::New(); this->m_InternalAdditionalResamplingImages[additionalIndex]->InitializeByItk( outImage.GetPointer() ); this->m_InternalAdditionalResamplingImages[additionalIndex]->SetVolume( outImage->GetBufferPointer() ); } } void PartialVolumeAnalysisHistogramCalculator::InternalResampleImage( const MaskImage3DType *image ) { typedef itk::ResampleImageFilter ResamplerType; ResamplerType::Pointer resampler = ResamplerType::New(); // Size ResamplerType::SizeType size; size[0] = m_UpsamplingFactor * image->GetLargestPossibleRegion().GetSize()[0]; size[1] = m_UpsamplingFactor * image->GetLargestPossibleRegion().GetSize()[1]; size[2] = m_UpsamplingFactor * image->GetLargestPossibleRegion().GetSize()[2];; resampler->SetSize( size ); // Origin mitk::Point3D orig = image->GetOrigin(); resampler->SetOutputOrigin(orig ); // Spacing ResamplerType::SpacingType spacing; spacing[0] = image->GetSpacing()[0] / m_UpsamplingFactor; spacing[1] = image->GetSpacing()[1] / m_UpsamplingFactor; spacing[2] = image->GetSpacing()[2] / m_UpsamplingFactor; resampler->SetOutputSpacing( spacing ); resampler->SetOutputDirection( image->GetDirection() ); typedef itk::NearestNeighborInterpolateImageFunction InterpolatorType; InterpolatorType::Pointer interpolator = InterpolatorType::New(); interpolator->SetInputImage( image ); resampler->SetInterpolator( interpolator ); // Other resampling options resampler->SetInput( image ); resampler->SetDefaultPixelValue(0); resampler->Update(); m_InternalImageMask3D = resampler->GetOutput(); } template < typename TPixel, unsigned int VImageDimension > void PartialVolumeAnalysisHistogramCalculator::InternalCalculateStatisticsUnmasked( const itk::Image< TPixel, VImageDimension > *image, Statistics &statistics, typename HistogramType::ConstPointer *histogram ) { MITK_INFO << "InternalCalculateStatisticsUnmasked()"; typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::Image< unsigned char, VImageDimension > MaskImageType; typedef typename ImageType::IndexType IndexType; // Progress listening... typedef itk::SimpleMemberCommand< PartialVolumeAnalysisHistogramCalculator > ITKCommandType; ITKCommandType::Pointer progressListener; progressListener = ITKCommandType::New(); progressListener->SetCallbackFunction( this, &PartialVolumeAnalysisHistogramCalculator::UnmaskedStatisticsProgressUpdate ); // Issue 100 artificial progress events since ScalarIMageToHistogramGenerator // does not (yet?) support progress reporting this->InvokeEvent( itk::StartEvent() ); for ( unsigned int i = 0; i < 100; ++i ) { this->UnmaskedStatisticsProgressUpdate(); } // Calculate statistics (separate filter) typedef itk::StatisticsImageFilter< ImageType > StatisticsFilterType; typename StatisticsFilterType::Pointer statisticsFilter = StatisticsFilterType::New(); statisticsFilter->SetInput( image ); unsigned long observerTag = statisticsFilter->AddObserver( itk::ProgressEvent(), progressListener ); statisticsFilter->Update(); statisticsFilter->RemoveObserver( observerTag ); this->InvokeEvent( itk::EndEvent() ); statistics.N = image->GetBufferedRegion().GetNumberOfPixels(); statistics.Min = statisticsFilter->GetMinimum(); statistics.Max = statisticsFilter->GetMaximum(); statistics.Mean = statisticsFilter->GetMean(); statistics.Median = 0.0; statistics.Sigma = statisticsFilter->GetSigma(); statistics.RMS = sqrt( statistics.Mean * statistics.Mean + statistics.Sigma * statistics.Sigma ); typename ImageType::Pointer inImage = const_cast(image); // Calculate histogram typedef itk::Statistics::ScalarImageToHistogramGenerator< ImageType > HistogramGeneratorType; typename HistogramGeneratorType::Pointer histogramGenerator = HistogramGeneratorType::New(); histogramGenerator->SetInput( inImage ); histogramGenerator->SetMarginalScale( 10 ); // Defines y-margin width of histogram histogramGenerator->SetNumberOfBins( m_NumberOfBins ); // CT range [-1024, +2048] --> bin size 4 values histogramGenerator->SetHistogramMin( statistics.Min ); histogramGenerator->SetHistogramMax( statistics.Max ); histogramGenerator->Compute(); *histogram = histogramGenerator->GetOutput(); } template < typename TPixel, unsigned int VImageDimension > void PartialVolumeAnalysisHistogramCalculator::InternalCalculateStatisticsMasked( const itk::Image< TPixel, VImageDimension > *image, itk::Image< unsigned char, VImageDimension > *maskImage, Statistics &statistics, typename HistogramType::ConstPointer *histogram ) { MITK_INFO << "InternalCalculateStatisticsMasked() start"; typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::Image< unsigned char, VImageDimension > MaskImageType; typedef typename ImageType::IndexType IndexType; // generate a list sample of angles at positions // where the fiber-prob is higher than .2*maxprob typedef TPixel MeasurementType; const unsigned int MeasurementVectorLength = 1; typedef itk::Vector< MeasurementType , MeasurementVectorLength > MeasurementVectorType; typedef itk::Statistics::ListSample< MeasurementVectorType > ListSampleType; typename ListSampleType::Pointer listSample = ListSampleType::New(); listSample->SetMeasurementVectorSize( MeasurementVectorLength ); itk::ImageRegionConstIterator itmask(maskImage, maskImage->GetLargestPossibleRegion()); itk::ImageRegionConstIterator itimage(image, image->GetLargestPossibleRegion()); itmask = itmask.Begin(); itimage = itimage.Begin(); while( !itmask.IsAtEnd() ) { if(itmask.Get() != 0) { // apend to list MeasurementVectorType mv; mv[0] = ( MeasurementType ) itimage.Get(); listSample->PushBack(mv); } ++itmask; ++itimage; } // generate a histogram from the list sample typedef float HistogramMeasurementType; typedef itk::Statistics::ListSampleToHistogramGenerator < ListSampleType, HistogramMeasurementType, itk::Statistics::DenseFrequencyContainer, MeasurementVectorLength > GeneratorType; typename GeneratorType::Pointer generator = GeneratorType::New(); typename GeneratorType::HistogramType::SizeType size; size.Fill(m_NumberOfBins); generator->SetNumberOfBins( size ); generator->SetListSample( listSample ); generator->SetMarginalScale( 10.0 ); generator->Update(); *histogram = generator->GetOutput(); } template < typename TPixel, unsigned int VImageDimension > void PartialVolumeAnalysisHistogramCalculator::InternalCropAdditionalImage( itk::Image< TPixel, VImageDimension > *image, int additionalIndex ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::RegionOfInterestImageFilter< ImageType, ImageType > ROIFilterType; typename ROIFilterType::Pointer roi = ROIFilterType::New(); roi->SetRegionOfInterest(m_CropRegion); roi->SetInput(image); roi->Update(); m_InternalAdditionalResamplingImages[additionalIndex] = mitk::Image::New(); m_InternalAdditionalResamplingImages[additionalIndex]->InitializeByItk(roi->GetOutput()); m_InternalAdditionalResamplingImages[additionalIndex]->SetVolume(roi->GetOutput()->GetBufferPointer()); } template < typename TPixel, unsigned int VImageDimension > void PartialVolumeAnalysisHistogramCalculator::InternalCalculateMaskFromPlanarFigure( itk::Image< TPixel, VImageDimension > *image, unsigned int axis ) { MITK_INFO << "InternalCalculateMaskFromPlanarFigure() start"; typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::CastImageFilter< ImageType, MaskImage3DType > CastFilterType; // Generate mask image as new image with same header as input image and // initialize with "1". MaskImage3DType::Pointer newMaskImage = MaskImage3DType::New(); newMaskImage->SetSpacing( image->GetSpacing() ); // Set the image spacing newMaskImage->SetOrigin( image->GetOrigin() ); // Set the image origin newMaskImage->SetDirection( image->GetDirection() ); // Set the image direction newMaskImage->SetRegions( image->GetLargestPossibleRegion() ); newMaskImage->Allocate(); newMaskImage->FillBuffer( 1 ); // Generate VTK polygon from (closed) PlanarFigure polyline // (The polyline points are shifted by -0.5 in z-direction to make sure // that the extrusion filter, which afterwards elevates all points by +0.5 // in z-direction, creates a 3D object which is cut by the the plane z=0) const mitk::Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D(); const typename PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 ); const mitk::Geometry3D *imageGeometry3D = m_InternalImage->GetGeometry( 0 ); vtkPolyData *polyline = vtkPolyData::New(); polyline->Allocate( 1, 1 ); // Determine x- and y-dimensions depending on principal axis int i0, i1; switch ( axis ) { case 0: i0 = 1; i1 = 2; break; case 1: i0 = 0; i1 = 2; break; case 2: default: i0 = 0; i1 = 1; break; } // Create VTK polydata object of polyline contour bool outOfBounds = false; vtkPoints *points = vtkPoints::New(); typename PlanarFigure::PolyLineType::const_iterator it; for ( it = planarFigurePolyline.begin(); it != planarFigurePolyline.end(); ++it ) { Point3D point3D; // Convert 2D point back to the local index coordinates of the selected // image mitk::Point2D point2D = it->Point; planarFigureGeometry2D->WorldToIndex(point2D, point2D); point2D[0] -= 0.5/m_UpsamplingFactor; point2D[1] -= 0.5/m_UpsamplingFactor; planarFigureGeometry2D->IndexToWorld(point2D, point2D); planarFigureGeometry2D->Map( point2D, point3D ); // Polygons (partially) outside of the image bounds can not be processed // further due to a bug in vtkPolyDataToImageStencil if ( !imageGeometry3D->IsInside( point3D ) ) { - MITK_INFO << point3D << " not inside resampled image plane.. :("; outOfBounds = true; } imageGeometry3D->WorldToIndex( point3D, point3D ); point3D[i0] += 0.5; point3D[i1] += 0.5; // Add point to polyline array points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 ); } polyline->SetPoints( points ); points->Delete(); if ( outOfBounds ) { polyline->Delete(); throw std::runtime_error( "Figure at least partially outside of image bounds!" ); } unsigned int numberOfPoints = planarFigurePolyline.size(); vtkIdType *ptIds = new vtkIdType[numberOfPoints]; for ( vtkIdType i = 0; i < numberOfPoints; ++i ) { ptIds[i] = i; } polyline->InsertNextCell( VTK_POLY_LINE, numberOfPoints, ptIds ); // Extrude the generated contour polygon vtkLinearExtrusionFilter *extrudeFilter = vtkLinearExtrusionFilter::New(); extrudeFilter->SetInput( polyline ); extrudeFilter->SetScaleFactor( 1 ); extrudeFilter->SetExtrusionTypeToNormalExtrusion(); extrudeFilter->SetVector( 0.0, 0.0, 1.0 ); // Make a stencil from the extruded polygon vtkPolyDataToImageStencil *polyDataToImageStencil = vtkPolyDataToImageStencil::New(); polyDataToImageStencil->SetInput( extrudeFilter->GetOutput() ); // Export from ITK to VTK (to use a VTK filter) typedef itk::VTKImageImport< MaskImage3DType > ImageImportType; typedef itk::VTKImageExport< MaskImage3DType > ImageExportType; typename ImageExportType::Pointer itkExporter = ImageExportType::New(); itkExporter->SetInput( newMaskImage ); vtkImageImport *vtkImporter = vtkImageImport::New(); this->ConnectPipelines( itkExporter, vtkImporter ); vtkImporter->Update(); // Apply the generated image stencil to the input image vtkImageStencil *imageStencilFilter = vtkImageStencil::New(); imageStencilFilter->SetInput( vtkImporter->GetOutput() ); imageStencilFilter->SetStencil( polyDataToImageStencil->GetOutput() ); imageStencilFilter->ReverseStencilOff(); imageStencilFilter->SetBackgroundValue( 0 ); imageStencilFilter->Update(); // Export from VTK back to ITK vtkImageExport *vtkExporter = vtkImageExport::New(); vtkExporter->SetInput( imageStencilFilter->GetOutput() ); vtkExporter->Update(); typename ImageImportType::Pointer itkImporter = ImageImportType::New(); this->ConnectPipelines( vtkExporter, itkImporter ); itkImporter->Update(); // calculate cropping bounding box m_InternalImageMask3D = itkImporter->GetOutput(); m_InternalImageMask3D->SetDirection(image->GetDirection()); itk::ImageRegionIterator itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion()); itmask = itmask.Begin(); while( !itmask.IsAtEnd() ) { if(itmask.Get() != 0) { typename ImageType::IndexType index = itmask.GetIndex(); for(int thick=0; thick<2*m_PlanarFigureThickness+1; thick++) { index[axis] = thick; m_InternalImageMask3D->SetPixel(index, itmask.Get()); } } ++itmask; } itmask = itmask.Begin(); itk::ImageRegionIterator itimage(image, image->GetLargestPossibleRegion()); itimage = itimage.Begin(); typename ImageType::SizeType lowersize = {{9999999999.0,9999999999.0,9999999999.0}}; typename ImageType::SizeType uppersize = {{0,0,0}}; while( !itmask.IsAtEnd() ) { if(itmask.Get() == 0) { itimage.Set(0); } else { typename ImageType::IndexType index = itimage.GetIndex(); typename ImageType::SizeType signedindex; signedindex[0] = index[0]; signedindex[1] = index[1]; signedindex[2] = index[2]; lowersize[0] = signedindex[0] < lowersize[0] ? signedindex[0] : lowersize[0]; lowersize[1] = signedindex[1] < lowersize[1] ? signedindex[1] : lowersize[1]; lowersize[2] = signedindex[2] < lowersize[2] ? signedindex[2] : lowersize[2]; uppersize[0] = signedindex[0] > uppersize[0] ? signedindex[0] : uppersize[0]; uppersize[1] = signedindex[1] > uppersize[1] ? signedindex[1] : uppersize[1]; uppersize[2] = signedindex[2] > uppersize[2] ? signedindex[2] : uppersize[2]; } ++itmask; ++itimage; } typename ImageType::IndexType index; index[0] = lowersize[0]; index[1] = lowersize[1]; index[2] = lowersize[2]; typename ImageType::SizeType size; size[0] = uppersize[0] - lowersize[0] + 1; size[1] = uppersize[1] - lowersize[1] + 1; size[2] = uppersize[2] - lowersize[2] + 1; m_CropRegion = itk::ImageRegion<3>(index, size); // crop internal image typedef itk::RegionOfInterestImageFilter< ImageType, ImageType > ROIFilterType; typename ROIFilterType::Pointer roi = ROIFilterType::New(); roi->SetRegionOfInterest(m_CropRegion); roi->SetInput(image); roi->Update(); m_InternalImage = mitk::Image::New(); m_InternalImage->InitializeByItk(roi->GetOutput()); m_InternalImage->SetVolume(roi->GetOutput()->GetBufferPointer()); // crop internal mask typedef itk::RegionOfInterestImageFilter< MaskImage3DType, MaskImage3DType > ROIMaskFilterType; typename ROIMaskFilterType::Pointer roi2 = ROIMaskFilterType::New(); roi2->SetRegionOfInterest(m_CropRegion); roi2->SetInput(m_InternalImageMask3D); roi2->Update(); m_InternalImageMask3D = roi2->GetOutput(); // Clean up VTK objects polyline->Delete(); extrudeFilter->Delete(); polyDataToImageStencil->Delete(); vtkImporter->Delete(); imageStencilFilter->Delete(); //vtkExporter->Delete(); // TODO: crashes when outcommented; memory leak?? delete[] ptIds; } void PartialVolumeAnalysisHistogramCalculator::UnmaskedStatisticsProgressUpdate() { // Need to throw away every second progress event to reach a final count of // 100 since two consecutive filters are used in this case static int updateCounter = 0; if ( updateCounter++ % 2 == 0 ) { this->InvokeEvent( itk::ProgressEvent() ); } } void PartialVolumeAnalysisHistogramCalculator::MaskedStatisticsProgressUpdate() { this->InvokeEvent( itk::ProgressEvent() ); } } diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.cpp b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.cpp index 144e4227c5..b93ae625d4 100644 --- a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.cpp +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.cpp @@ -1,454 +1,505 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date$ Version: $Revision: 11989 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkConnectomicsNetwork.h" #include /* Constructor and Destructor */ mitk::ConnectomicsNetwork::ConnectomicsNetwork() : m_IsModified( false ) { } mitk::ConnectomicsNetwork::~ConnectomicsNetwork() { } /* Wrapper methods */ bool mitk::ConnectomicsNetwork::EdgeExists( mitk::ConnectomicsNetwork::VertexDescriptorType vertexA, mitk::ConnectomicsNetwork::VertexDescriptorType vertexB ) const { return boost::edge(vertexA, vertexB, m_Network ).second; } void mitk::ConnectomicsNetwork::IncreaseEdgeWeight( mitk::ConnectomicsNetwork::VertexDescriptorType vertexA, mitk::ConnectomicsNetwork::VertexDescriptorType vertexB ) { m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].weight++; SetIsModified( true ); } void mitk::ConnectomicsNetwork::AddEdge( mitk::ConnectomicsNetwork::VertexDescriptorType vertexA, mitk::ConnectomicsNetwork::VertexDescriptorType vertexB ) { AddEdge(vertexA, vertexB, m_Network[ vertexA ].id, m_Network[ vertexB ].id ); } void mitk::ConnectomicsNetwork::AddEdge( mitk::ConnectomicsNetwork::VertexDescriptorType vertexA, mitk::ConnectomicsNetwork::VertexDescriptorType vertexB, int sourceID, int targetID, int weight ) { boost::add_edge( vertexA, vertexB, m_Network ); m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].sourceId = sourceID; m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].targetId = targetID; m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].weight = weight; m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].edge_weight = 1.0; SetIsModified( true ); } mitk::ConnectomicsNetwork::VertexDescriptorType mitk::ConnectomicsNetwork::AddVertex( int id ) { VertexDescriptorType vertex = boost::add_vertex( m_Network ); m_Network[vertex].id = id; SetIsModified( true ); return vertex; } void mitk::ConnectomicsNetwork::SetLabel( mitk::ConnectomicsNetwork::VertexDescriptorType vertex, std::string inLabel ) { m_Network[vertex].label = inLabel; SetIsModified( true ); } void mitk::ConnectomicsNetwork::SetCoordinates( mitk::ConnectomicsNetwork::VertexDescriptorType vertex, std::vector< float > inCoordinates ) { m_Network[vertex].coordinates = inCoordinates; SetIsModified( true ); } void mitk::ConnectomicsNetwork::clear() { m_Network.clear(); SetIsModified( true ); } /* Superclass methods, that need to be implemented */ void mitk::ConnectomicsNetwork::UpdateOutputInformation() { } void mitk::ConnectomicsNetwork::SetRequestedRegionToLargestPossibleRegion() { } bool mitk::ConnectomicsNetwork::RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } bool mitk::ConnectomicsNetwork::VerifyRequestedRegion() { return true; } void mitk::ConnectomicsNetwork::SetRequestedRegion( itk::DataObject *data ) { } std::vector< mitk::ConnectomicsNetwork::NetworkNode > mitk::ConnectomicsNetwork::GetVectorOfAllNodes() const { boost::graph_traits::vertex_iterator iterator, end; // sets iterator to start end end to end boost::tie(iterator, end) = boost::vertices( m_Network ); std::vector< NetworkNode > vectorOfNodes; for ( ; iterator != end; ++iterator) { NetworkNode tempNode; // the value of an iterator is a descriptor tempNode = m_Network[ *iterator ]; vectorOfNodes.push_back( tempNode ); } return vectorOfNodes; } std::vector< mitk::ConnectomicsNetwork::VertexDescriptorType > mitk::ConnectomicsNetwork::GetVectorOfAllVertexDescriptors() const { boost::graph_traits::vertex_iterator iterator, end; // sets iterator to start end end to end boost::tie(iterator, end) = boost::vertices( m_Network ); std::vector< VertexDescriptorType > vectorOfDescriptors; for ( ; iterator != end; ++iterator) { vectorOfDescriptors.push_back( *iterator ); } return vectorOfDescriptors; } std::vector< std::pair< std::pair< mitk::ConnectomicsNetwork::NetworkNode, mitk::ConnectomicsNetwork::NetworkNode > , mitk::ConnectomicsNetwork::NetworkEdge > > mitk::ConnectomicsNetwork::GetVectorOfAllEdges() const { boost::graph_traits::edge_iterator iterator, end; // sets iterator to start end end to end boost::tie(iterator, end) = boost::edges( m_Network ); std::vector< std::pair< std::pair< NetworkNode, NetworkNode > , NetworkEdge > > vectorOfEdges; for ( ; iterator != end; ++iterator) { NetworkNode sourceNode, targetNode; NetworkEdge tempEdge; // the value of an iterator is a descriptor tempEdge = m_Network[ *iterator ]; sourceNode = m_Network[ boost::source( *iterator, m_Network ) ]; targetNode = m_Network[ boost::target( *iterator, m_Network ) ]; std::pair< NetworkNode, NetworkNode > nodePair( sourceNode, targetNode ); std::pair< std::pair< NetworkNode, NetworkNode > , NetworkEdge > edgePair( nodePair, tempEdge); vectorOfEdges.push_back( edgePair ); } return vectorOfEdges; } int mitk::ConnectomicsNetwork::GetNumberOfVertices() const { return boost::num_vertices( m_Network ); } int mitk::ConnectomicsNetwork::GetNumberOfEdges() { return boost::num_edges( m_Network ); } int mitk::ConnectomicsNetwork::GetMaximumWeight() const { int maxWeight( 0 ); boost::graph_traits::edge_iterator iterator, end; // sets iterator to start end end to end boost::tie(iterator, end) = boost::edges( m_Network ); for ( ; iterator != end; ++iterator) { int tempWeight; // the value of an iterator is a descriptor tempWeight = m_Network[ *iterator ].weight; if( tempWeight > maxWeight ) { maxWeight = tempWeight; } } return maxWeight; } int mitk::ConnectomicsNetwork::GetNumberOfSelfLoops() { int noOfSelfLoops( 0 ); std::vector< std::pair< std::pair< NetworkNode, NetworkNode > , NetworkEdge > > edgeVector = GetVectorOfAllEdges(); for( int index = 0; index < edgeVector.size() ; index++ ) { double sourceX, sourceY, sourceZ, targetX, targetY, targetZ; sourceX = edgeVector[ index ].first.first.coordinates[0] ; sourceY = edgeVector[ index ].first.first.coordinates[1] ; sourceZ = edgeVector[ index ].first.first.coordinates[2] ; targetX = edgeVector[ index ].first.second.coordinates[0] ; targetY = edgeVector[ index ].first.second.coordinates[1] ; targetZ = edgeVector[ index ].first.second.coordinates[2] ; // if the coordinates are the same if( sourceX > ( targetX - 0.01 ) && sourceX < ( targetX + 0.01 ) && sourceY > ( targetY - 0.01 ) && sourceY < ( targetY + 0.01 ) && sourceZ > ( targetZ - 0.01 ) && sourceZ < ( targetZ + 0.01 ) ) { noOfSelfLoops++; } } return noOfSelfLoops; } double mitk::ConnectomicsNetwork::GetAverageDegree() { double vertices = (double) GetNumberOfVertices(); double edges = (double) GetNumberOfEdges(); return ( ( edges * 2.0 ) / vertices ); } double mitk::ConnectomicsNetwork::GetConnectionDensity() { double vertices = (double) GetNumberOfVertices(); double edges = (double) GetNumberOfEdges(); double numberOfPossibleEdges = vertices * ( vertices - 1 ) / 2 ; return ( edges / numberOfPossibleEdges ); } std::vector< int > mitk::ConnectomicsNetwork::GetDegreeOfNodes( ) const { std::vector< int > vectorOfDegree; boost::graph_traits::vertex_iterator iterator, end; // sets iterator to start end end to end boost::tie( iterator, end ) = boost::vertices( m_Network ); vectorOfDegree.resize( this->GetNumberOfVertices() ); for ( ; iterator != end; ++iterator) { // the value of an iterator is a descriptor vectorOfDegree[ m_Network[ *iterator ].id ] = GetVectorOfAdjacentNodes( *iterator ).size(); } return vectorOfDegree; } std::vector< mitk::ConnectomicsNetwork::VertexDescriptorType > mitk::ConnectomicsNetwork::GetVectorOfAdjacentNodes( mitk::ConnectomicsNetwork::VertexDescriptorType vertex ) const { std::vector< mitk::ConnectomicsNetwork::VertexDescriptorType > vectorOfAdjacentNodes; boost::graph_traits::adjacency_iterator adjIter, adjEnd; boost::tie( adjIter, adjEnd ) = boost::adjacent_vertices( vertex, m_Network); for ( ; adjIter != adjEnd; ++adjIter) { vectorOfAdjacentNodes.push_back( *adjIter ); } return vectorOfAdjacentNodes; } int mitk::ConnectomicsNetwork::GetMaximumDegree() const { int maximumDegree( 0 ); std::vector< int > vectorOfDegree = GetDegreeOfNodes(); for( int index( 0 ); index < vectorOfDegree.size(); ++index ) { if( maximumDegree < vectorOfDegree[ index ] ) { maximumDegree = vectorOfDegree[ index ]; } } return maximumDegree; } std::vector< double > mitk::ConnectomicsNetwork::GetLocalClusteringCoefficients( ) { std::vector< double > vectorOfClusteringCoefficients; typedef boost::graph_traits::vertex_iterator vertexIter; vectorOfClusteringCoefficients.resize( this->GetNumberOfVertices() ); std::pair vertexPair; //for every vertex calculate the clustering coefficient for (vertexPair = vertices(m_Network); vertexPair.first != vertexPair.second; ++vertexPair.first) { vectorOfClusteringCoefficients[ m_Network[ *vertexPair.first ].id ] = boost::clustering_coefficient(m_Network,*vertexPair.first) ; } return vectorOfClusteringCoefficients; } std::vector< double > mitk::ConnectomicsNetwork::GetClusteringCoefficientsByDegree( ) { std::vector< double > vectorOfClusteringCoefficients = GetLocalClusteringCoefficients(); std::vector< int > vectorOfDegree = GetDegreeOfNodes(); std::vector< double > vectorOfClusteringCoefficientsByDegree; vectorOfClusteringCoefficientsByDegree.resize( GetMaximumDegree() + 1, 0 ); // c_{mean}(k) = frac{1}_{N_{k}} sum_{i in Y(k)} c_{i} // where N_{k} is the number of vertices of degree k // Y(k) is the set of vertices of degree k // c_{i} is the local clustering coefficient of vertex i for( int degree( 0 ); degree < vectorOfClusteringCoefficientsByDegree.size(); ++degree ) { vectorOfClusteringCoefficientsByDegree[ degree ] = 0; int n_k( 0 ); for( int index( 0 ); index < vectorOfDegree.size(); ++index ) { if( degree == vectorOfDegree[ index ] ) {// if in Y( degree ) vectorOfClusteringCoefficientsByDegree[ degree ] += vectorOfClusteringCoefficients[ index ]; n_k++; } } if( n_k != 0 ) { vectorOfClusteringCoefficientsByDegree[ degree ] = vectorOfClusteringCoefficientsByDegree[ degree ] / n_k; } } return vectorOfClusteringCoefficientsByDegree; } double mitk::ConnectomicsNetwork::GetGlobalClusteringCoefficient( ) { double globalClusteringCoefficient( 0.0 ); std::vector< double > vectorOfClusteringCoefficientsByDegree = GetClusteringCoefficientsByDegree(); std::vector< int > vectorOfDegree = GetDegreeOfNodes(); std::vector< int > degreeDistribution; degreeDistribution.resize( vectorOfClusteringCoefficientsByDegree.size(), 0 ); int normalizationParameter( 0 ); for( int index( 0 ); index < vectorOfDegree.size(); ++index ) { degreeDistribution[ vectorOfDegree[ index ] ]++; normalizationParameter++; } // c_{mean} = sum_{k} P_{k} c_{mean}(k) // where P_{k} is the degree distribution // k is the degree for( int degree( 0 ); degree < degreeDistribution.size(); ++degree ) { globalClusteringCoefficient += degreeDistribution[ degree ] / ( (double) normalizationParameter) * vectorOfClusteringCoefficientsByDegree[ degree ]; } return globalClusteringCoefficient; } mitk::ConnectomicsNetwork::NetworkType* mitk::ConnectomicsNetwork::GetBoostGraph() { return &m_Network; } bool mitk::ConnectomicsNetwork::GetIsModified() const { return m_IsModified; } void mitk::ConnectomicsNetwork::SetIsModified( bool value) { m_IsModified = value; } mitk::ConnectomicsNetwork::NetworkNode mitk::ConnectomicsNetwork::GetNode( VertexDescriptorType vertex ) const { return m_Network[ vertex ]; } mitk::ConnectomicsNetwork::NetworkEdge mitk::ConnectomicsNetwork::GetEdge( VertexDescriptorType vertexA, VertexDescriptorType vertexB ) const { return m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ]; +} + +void mitk::ConnectomicsNetwork::UpdateBounds( ) +{ + float min = itk::NumericTraits::min(); + float max = itk::NumericTraits::max(); + float bounds[] = {max, min, max, min, max, min}; + + std::vector< mitk::ConnectomicsNetwork::NetworkNode > nodeVector = this->GetVectorOfAllNodes(); + + if( nodeVector.size() == 0 ) + { + bounds[0] = 0; + bounds[1] = 1; + bounds[2] = 0; + bounds[3] = 1; + bounds[4] = 0; + bounds[5] = 1; + } + + // for each direction, make certain the point is in between + for( int index(0), end(nodeVector.size()) ; index < end; index++ ) + { + for( int direction(0); direction < nodeVector.at( index ).coordinates.size(); direction++ ) + { + if( nodeVector.at( index ).coordinates.at(direction) < bounds[ 2 * direction ] ) + { + bounds[ 2 * direction ] = nodeVector.at( index ).coordinates.at(direction); + } + + if( nodeVector.at( index ).coordinates.at(direction) > bounds[ 2 * direction + 1] ) + { + bounds[ 2 * direction + 1] = nodeVector.at( index ).coordinates.at(direction); + } + } + } + + + // provide some border margin + for(int i=0; i<=4; i+=2) + { + bounds[i] -=10; + } + + for(int i=1; i<=5; i+=2) + { + bounds[i] +=10; + } + + this->GetGeometry()->SetFloatBounds(bounds); + this->GetTimeSlicedGeometry()->UpdateInformation(); } \ No newline at end of file diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.h b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.h index 0f60898443..bed837ce1e 100644 --- a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.h +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.h @@ -1,177 +1,180 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date$ Version: $Revision: 11989 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _MITK_ConnectomicsNetwork_H #define _MITK_ConnectomicsNetwork_H #include "MitkDiffusionImagingExports.h" #include "mitkBaseData.h" #include namespace mitk { /** * \brief Base Class for Connectomics Networks */ class MitkDiffusionImaging_EXPORT ConnectomicsNetwork : public BaseData { public: /** Structs for the graph */ /** The Node */ struct NetworkNode { int id; std::string label; std::vector< float > coordinates; }; /** The Edge */ struct NetworkEdge { int sourceId; int targetId; int weight; // For now the number of times it was present double edge_weight; // For boost, currently set to 1 by default for unweighted calculations }; /** Typedefs **/ //typedef boost::adjacency_list< boost::listS, boost::listS, boost::undirectedS, NetworkNode, NetworkEdge > NetworkType; typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::undirectedS, NetworkNode, NetworkEdge > NetworkType; typedef boost::graph_traits::vertex_descriptor VertexDescriptorType; typedef boost::graph_traits::edge_descriptor EdgeDescriptorType; // virtual methods that need to be implemented virtual void UpdateOutputInformation(); virtual void SetRequestedRegionToLargestPossibleRegion(); virtual bool RequestedRegionIsOutsideOfTheBufferedRegion(); virtual bool VerifyRequestedRegion(); virtual void SetRequestedRegion( itk::DataObject *data ); // Macros mitkClassMacro( ConnectomicsNetwork, BaseData ); itkNewMacro( Self ); ////////////////// Interface /////////////////// /** return whether an edge exists between the two given vertices */ bool EdgeExists( VertexDescriptorType vertexA, VertexDescriptorType vertexB ) const; /** increase the weight of an edge between the two given vertices */ void IncreaseEdgeWeight( VertexDescriptorType vertexA, VertexDescriptorType vertexB ); /** add an edge between two given vertices */ void AddEdge( VertexDescriptorType vertexA, VertexDescriptorType vertexB); /** add an edge between two given vertices ( with a specific weight ) */ void AddEdge( VertexDescriptorType vertexA, VertexDescriptorType vertexB, int sourceID, int targetID, int weight = 1 ); /** add a vertex with a specified id */ VertexDescriptorType AddVertex( int id); /** set the label of a vertex */ void SetLabel( VertexDescriptorType vertex, std::string inLabel ); /** set the coordinates of a vertex */ void SetCoordinates( VertexDescriptorType vertex, std::vector< float > inCoordinates ); /** clear the graph */ void clear(); /** return the node struct for a given node descriptor */ NetworkNode GetNode( VertexDescriptorType vertex ) const; /** return the edge struct for two given node descriptors */ NetworkEdge GetEdge( VertexDescriptorType vertexA, VertexDescriptorType vertexB ) const; /** get vector containing all the nodes of the network */ std::vector< NetworkNode > GetVectorOfAllNodes() const; /** get vector containing all the vertex descriptors of the network */ std::vector< VertexDescriptorType > GetVectorOfAllVertexDescriptors() const; /** get vector containing the descriptors of nodes adjacent to the vertex denoted by the given descriptor */ std::vector< VertexDescriptorType > GetVectorOfAdjacentNodes( VertexDescriptorType vertex ) const; /** get vector containing all the edges of the network and the connected nodes */ std::vector< std::pair< std::pair< NetworkNode, NetworkNode > , NetworkEdge > > GetVectorOfAllEdges() const; /** get overall number of vertices in the network */ int GetNumberOfVertices() const; /** get overall number of edges in the network */ int GetNumberOfEdges(); /** get number of vertices, that are connected to themselves */ int GetNumberOfSelfLoops(); /** get number of vertices, that are connected to themselves */ double GetAverageDegree(); /** get number of edges divided by number of possible edges */ double GetConnectionDensity(); /** Get the maximum weight of all edges */ int GetMaximumWeight() const; /** Get a vector in the format vector[ vertexID ] = degree */ std::vector< int > GetDegreeOfNodes( ) const; /** Get the maximum degree of all nodes */ int GetMaximumDegree() const; /** Get a vector in the format vector[ vertexID ] = clustering coefficient */ std::vector< double > GetLocalClusteringCoefficients( ); /** Get a vector in the format vector[ degree ] = average clustering coefficient */ std::vector< double > GetClusteringCoefficientsByDegree( ); /** Get the global clustering coefficient */ double GetGlobalClusteringCoefficient( ); /** Access boost graph directly */ NetworkType* GetBoostGraph(); /** Get the modified flag */ bool GetIsModified() const; /** Set the modified flag */ void SetIsModified( bool ); + /** Update the bounds of the geometry to fit the network */ + void UpdateBounds( ); + protected: ConnectomicsNetwork(); virtual ~ConnectomicsNetwork(); NetworkType m_Network; /// Flag which indicates whether the network has been modified since the last check /// /// mainly for rendering purposes bool m_IsModified; private: }; } // namespace mitk #endif /* _MITK_ConnectomicsNetwork_H */ diff --git a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.cpp b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.cpp index a1d3fcd1e2..0d6a39a44a 100644 --- a/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.cpp +++ b/Modules/DiffusionImaging/IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.cpp @@ -1,252 +1,253 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-07-14 19:11:20 +0200 (Tue, 14 Jul 2009) $ Version: $Revision: 18127 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkConnectomicsNetworkReader.h" #include "mitkConnectomicsNetworkDefinitions.h" #include #include "itksys/SystemTools.hxx" #include void mitk::ConnectomicsNetworkReader::GenerateData() { MITK_INFO << "Reading connectomics network"; if ( ( ! m_OutputCache ) ) { Superclass::SetNumberOfRequiredOutputs(0); this->GenerateOutputInformation(); } if (!m_OutputCache) { itkWarningMacro("Tree cache is empty!"); } Superclass::SetNumberOfRequiredOutputs(1); Superclass::SetNthOutput(0, m_OutputCache.GetPointer()); } void mitk::ConnectomicsNetworkReader::GenerateOutputInformation() { m_OutputCache = OutputType::New(); std::string ext = itksys::SystemTools::GetFilenameLastExtension(m_FileName); ext = itksys::SystemTools::LowerCase(ext); if ( m_FileName == "") { MITK_ERROR << "No file name specified."; } else if (ext == ".cnf") { try { TiXmlDocument doc( m_FileName ); doc.LoadFile(); TiXmlHandle hDoc(&doc); TiXmlElement* pElem; TiXmlHandle hRoot(0); pElem = hDoc.FirstChildElement().Element(); // save this for later hRoot = TiXmlHandle(pElem); pElem = hRoot.FirstChildElement(mitk::ConnectomicsNetworkDefinitions::XML_GEOMETRY).Element(); // read geometry mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); // read origin mitk::Point3D origin; double temp = 0; pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_X, &temp); origin[0] = temp; pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Y, &temp); origin[1] = temp; pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Z, &temp); origin[2] = temp; geometry->SetOrigin(origin); // read spacing float spacing[3]; pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_X, &temp); spacing[0] = temp; pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Y, &temp); spacing[1] = temp; pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Z, &temp); spacing[2] = temp; geometry->SetSpacing(spacing); // read transform vtkMatrix4x4* m = vtkMatrix4x4::New(); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XX, &temp); m->SetElement(0,0,temp); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XY, &temp); m->SetElement(1,0,temp); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XZ, &temp); m->SetElement(2,0,temp); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YX, &temp); m->SetElement(0,1,temp); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YY, &temp); m->SetElement(1,1,temp); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YZ, &temp); m->SetElement(2,1,temp); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZX, &temp); m->SetElement(0,2,temp); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZY, &temp); m->SetElement(1,2,temp); pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZZ, &temp); m->SetElement(2,2,temp); m->SetElement(0,3,origin[0]); m->SetElement(1,3,origin[1]); m->SetElement(2,3,origin[2]); m->SetElement(3,3,1); geometry->SetIndexToWorldTransformByVtkMatrix(m); geometry->SetImageGeometry(true); m_OutputCache->SetGeometry(geometry); // read network std::map< int, mitk::ConnectomicsNetwork::VertexDescriptorType > idToVertexMap; // read vertices pElem = hRoot.FirstChildElement(mitk::ConnectomicsNetworkDefinitions::XML_VERTICES).Element(); { // walk through the vertices TiXmlElement* vertexElement = pElem->FirstChildElement(); for( vertexElement; vertexElement; vertexElement=vertexElement->NextSiblingElement()) { std::vector< float > pos; std::string label; int vertexID(0); vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_X, &temp); pos.push_back(temp); vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Y, &temp); pos.push_back(temp); vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Z, &temp); pos.push_back(temp); vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_ID, &vertexID); vertexElement->QueryStringAttribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_LABEL, &label); mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = m_OutputCache->AddVertex( vertexID ); m_OutputCache->SetLabel( newVertex, label ); m_OutputCache->SetCoordinates( newVertex, pos ); if ( idToVertexMap.count( vertexID ) > 0 ) { MITK_ERROR << "Aborting network creation, duplicate vertex ID in file."; return; } idToVertexMap.insert( std::pair< int, mitk::ConnectomicsNetwork::VertexDescriptorType >( vertexID, newVertex) ); } } // read edges pElem = hRoot.FirstChildElement(mitk::ConnectomicsNetworkDefinitions::XML_EDGES).Element(); { // walk through the edges TiXmlElement* edgeElement = pElem->FirstChildElement(); for( edgeElement; edgeElement; edgeElement=edgeElement->NextSiblingElement()) { int edgeID(0), edgeSourceID(0), edgeTargetID(0), edgeWeight(0); edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_ID, &edgeID); edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_SOURCE_ID, &edgeSourceID); edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_TARGET_ID, &edgeTargetID); edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_WEIGHT_ID, &edgeWeight); mitk::ConnectomicsNetwork::VertexDescriptorType source = idToVertexMap.find( edgeSourceID )->second; mitk::ConnectomicsNetwork::VertexDescriptorType target = idToVertexMap.find( edgeTargetID )->second; m_OutputCache->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight); } } + m_OutputCache->UpdateBounds(); MITK_INFO << "Network read"; } catch(...) { MITK_INFO << "Could not read file "; } } } void mitk::ConnectomicsNetworkReader::Update() { this->GenerateData(); } const char* mitk::ConnectomicsNetworkReader::GetFileName() const { return m_FileName.c_str(); } void mitk::ConnectomicsNetworkReader::SetFileName(const char* aFileName) { m_FileName = aFileName; } const char* mitk::ConnectomicsNetworkReader::GetFilePrefix() const { return m_FilePrefix.c_str(); } void mitk::ConnectomicsNetworkReader::SetFilePrefix(const char* aFilePrefix) { m_FilePrefix = aFilePrefix; } const char* mitk::ConnectomicsNetworkReader::GetFilePattern() const { return m_FilePattern.c_str(); } void mitk::ConnectomicsNetworkReader::SetFilePattern(const char* aFilePattern) { m_FilePattern = aFilePattern; } bool mitk::ConnectomicsNetworkReader::CanReadFile( const std::string filename, const std::string /*filePrefix*/, const std::string /*filePattern*/) { // First check the extension if( filename == "" ) { return false; } std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename); ext = itksys::SystemTools::LowerCase(ext); if (ext == ".cnf") { return true; } return false; } diff --git a/Modules/DiffusionImaging/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx b/Modules/DiffusionImaging/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx index fda6ad539e..075a64a8c6 100644 --- a/Modules/DiffusionImaging/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx +++ b/Modules/DiffusionImaging/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx @@ -1,411 +1,418 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2008-02-08 11:19:03 +0100 (Fr, 08 Feb 2008) $ Version: $Revision: 11989 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "itkImageRegionIterator.h" #include "itkImageRegionConstIterator.h" #include "mitkImageCast.h" template mitk::DiffusionImage::DiffusionImage() : m_VectorImage(0), m_Directions(0), m_OriginalDirections(0), m_B_Value(-1.0), m_VectorImageAdaptor(0) { MeasurementFrameType mf; for(int i=0; i<3; i++) for(int j=0; j<3; j++) mf[i][j] = 0; for(int i=0; i<3; i++) mf[i][i] = 1; m_MeasurementFrame = mf; } template mitk::DiffusionImage::~DiffusionImage() { } template void mitk::DiffusionImage ::InitializeFromVectorImage() { if(!m_VectorImage || !m_Directions || m_B_Value==-1.0) { MITK_INFO << "DiffusionImage could not be initialized. Set all members first!" << std::endl; return; } // find bzero index int firstZeroIndex = -1; for(GradientDirectionContainerType::ConstIterator it = m_Directions->Begin(); it != m_Directions->End(); ++it) { firstZeroIndex++; GradientDirectionType g = it.Value(); if(g[0] == 0 && g[1] == 0 && g[2] == 0 ) break; } typedef itk::Image ImgType; typename ImgType::Pointer img = ImgType::New(); img->SetSpacing( m_VectorImage->GetSpacing() ); // Set the image spacing img->SetOrigin( m_VectorImage->GetOrigin() ); // Set the image origin img->SetDirection( m_VectorImage->GetDirection() ); // Set the image direction img->SetLargestPossibleRegion( m_VectorImage->GetLargestPossibleRegion()); img->SetBufferedRegion( m_VectorImage->GetLargestPossibleRegion() ); img->Allocate(); int vecLength = m_VectorImage->GetVectorLength(); InitializeByItk( img.GetPointer(), 1, vecLength ); //for(int i=0; i itw (img, img->GetLargestPossibleRegion() ); itw = itw.Begin(); itk::ImageRegionConstIterator itr (m_VectorImage, m_VectorImage->GetLargestPossibleRegion() ); itr = itr.Begin(); while(!itr.IsAtEnd()) { itw.Set(itr.Get().GetElement(firstZeroIndex)); ++itr; ++itw; } // init SetImportVolume(img->GetBufferPointer());//, 0, 0, CopyMemory); //SetVolume( img->GetBufferPointer(), i ); //} m_DisplayIndex = firstZeroIndex; MITK_INFO << "Diffusion-Image successfully initialized."; } template void mitk::DiffusionImage ::SetDisplayIndexForRendering(int displayIndex) { int index = displayIndex; int vecLength = m_VectorImage->GetVectorLength(); index = index > vecLength-1 ? vecLength-1 : index; if( m_DisplayIndex != index ) { typedef itk::Image ImgType; typename ImgType::Pointer img = ImgType::New(); CastToItkImage(this, img); itk::ImageRegionIterator itw (img, img->GetLargestPossibleRegion() ); itw = itw.Begin(); itk::ImageRegionConstIterator itr (m_VectorImage, m_VectorImage->GetLargestPossibleRegion() ); itr = itr.Begin(); while(!itr.IsAtEnd()) { itw.Set(itr.Get().GetElement(index)); ++itr; ++itw; } } m_DisplayIndex = index; } //template //bool mitk::DiffusionImage::RequestedRegionIsOutsideOfTheBufferedRegion() //{ // return false; //} // //template //void mitk::DiffusionImage::SetRequestedRegion(itk::DataObject * /*data*/) //{ //} // //template //void mitk::DiffusionImage::SetRequestedRegionToLargestPossibleRegion() //{ //} // //template //bool mitk::DiffusionImage::VerifyRequestedRegion() //{ // return true; //} //template //void mitk::DiffusionImage::DuplicateIfSingleSlice() //{ // // new image // typename ImageType::Pointer oldImage = m_Image; // m_Image = ImageType::New(); // m_Image->SetSpacing( oldImage->GetSpacing() ); // Set the image spacing // m_Image->SetOrigin( oldImage->GetOrigin() ); // Set the image origin // m_Image->SetDirection( oldImage->GetDirection() ); // Set the image direction // typename ImageType::RegionType region = oldImage->GetLargestPossibleRegion(); // if(region.GetSize(0) == 1) // region.SetSize(0,3); // if(region.GetSize(1) == 1) // region.SetSize(1,3); // if(region.GetSize(2) == 1) // region.SetSize(2,3); // m_Image->SetLargestPossibleRegion( region ); // m_Image->SetVectorLength( m_Directions->size() ); // m_Image->SetBufferedRegion( region ); // m_Image->Allocate(); // // // average image data that corresponds to identical directions // itk::ImageRegionIterator< ImageType > newIt(m_Image, region); // newIt.GoToBegin(); // itk::ImageRegionIterator< ImageType > oldIt(oldImage, oldImage->GetLargestPossibleRegion()); // oldIt.GoToBegin(); // // while(!newIt.IsAtEnd()) // { // newIt.Set(oldIt.Get()); // ++newIt; // ++oldIt; // if(oldIt.IsAtEnd()) // oldIt.GoToBegin(); // } // //} template bool mitk::DiffusionImage::AreAlike(GradientDirectionType g1, GradientDirectionType g2, double precision) { GradientDirectionType diff = g1 - g2; return diff.two_norm() < precision; } template void mitk::DiffusionImage::CorrectDKFZBrokenGradientScheme(double precision) { GradientDirectionContainerType::Pointer directionSet = CalcAveragedDirectionSet(precision, m_Directions); if(directionSet->size() < 7) { MITK_INFO << "Too few directions, assuming and correcting DKFZ-bogus sequence details."; double v [7][3] = {{ 0, 0, 0 }, {-0.707057, 0, 0.707057 }, { 0.707057, 0, 0.707057 }, { 0, 0.707057, 0.707057 }, { 0, 0.707057, -0.707057 }, {-0.707057, 0.707057, 0 }, { 0.707057, 0.707057, 0 } }; int i=0; for(GradientDirectionContainerType::Iterator it = m_OriginalDirections->Begin(); it != m_OriginalDirections->End(); ++it) { it.Value().set(v[i++%7]); } ApplyMeasurementFrame(); } } template mitk::DiffusionImage::GradientDirectionContainerType::Pointer mitk::DiffusionImage::CalcAveragedDirectionSet(double precision, GradientDirectionContainerType::Pointer directions) { // save old and construct new direction container GradientDirectionContainerType::Pointer newDirections = GradientDirectionContainerType::New(); // fill new direction container for(GradientDirectionContainerType::ConstIterator gdcitOld = directions->Begin(); gdcitOld != directions->End(); ++gdcitOld) { // already exists? bool found = false; for(GradientDirectionContainerType::ConstIterator gdcitNew = newDirections->Begin(); gdcitNew != newDirections->End(); ++gdcitNew) { if(AreAlike(gdcitNew.Value(), gdcitOld.Value(), precision)) { found = true; break; } } // if not found, add it to new container if(!found) { newDirections->push_back(gdcitOld.Value()); } } return newDirections; } template void mitk::DiffusionImage::AverageRedundantGradients(double precision) { GradientDirectionContainerType::Pointer newDirs = CalcAveragedDirectionSet(precision, m_Directions); GradientDirectionContainerType::Pointer newOriginalDirs = - CalcAveragedDirectionSet(precision, m_OriginalDirections); + CalcAveragedDirectionSet(precision, m_OriginalDirections); // if sizes equal, we do not need to do anything in this function if(m_Directions->size() == newDirs->size() || m_OriginalDirections->size() == newOriginalDirs->size()) return; GradientDirectionContainerType::Pointer oldDirections = m_Directions; GradientDirectionContainerType::Pointer oldOriginalDirections = m_OriginalDirections; m_Directions = newDirs; m_OriginalDirections = newOriginalDirs; // new image typename ImageType::Pointer oldImage = m_VectorImage; m_VectorImage = ImageType::New(); m_VectorImage->SetSpacing( oldImage->GetSpacing() ); // Set the image spacing m_VectorImage->SetOrigin( oldImage->GetOrigin() ); // Set the image origin m_VectorImage->SetDirection( oldImage->GetDirection() ); // Set the image direction m_VectorImage->SetLargestPossibleRegion( oldImage->GetLargestPossibleRegion() ); m_VectorImage->SetVectorLength( m_Directions->size() ); m_VectorImage->SetBufferedRegion( oldImage->GetLargestPossibleRegion() ); m_VectorImage->Allocate(); // average image data that corresponds to identical directions itk::ImageRegionIterator< ImageType > newIt(m_VectorImage, m_VectorImage->GetLargestPossibleRegion()); newIt.GoToBegin(); itk::ImageRegionIterator< ImageType > oldIt(oldImage, oldImage->GetLargestPossibleRegion()); oldIt.GoToBegin(); // initial new value of voxel typename ImageType::PixelType newVec; newVec.SetSize(m_Directions->size()); newVec.AllocateElements(m_Directions->size()); std::vector > dirIndices; for(GradientDirectionContainerType::ConstIterator gdcitNew = m_Directions->Begin(); gdcitNew != m_Directions->End(); ++gdcitNew) { dirIndices.push_back(std::vector(0)); for(GradientDirectionContainerType::ConstIterator gdcitOld = oldDirections->Begin(); gdcitOld != oldDirections->End(); ++gdcitOld) { if(AreAlike(gdcitNew.Value(), gdcitOld.Value(), precision)) { dirIndices[gdcitNew.Index()].push_back(gdcitOld.Index()); } } } - int ind1 = -1; + //int ind1 = -1; while(!newIt.IsAtEnd()) { // progress - typename ImageType::IndexType ind = newIt.GetIndex(); - ind1 = ind.m_Index[2]; + //typename ImageType::IndexType ind = newIt.GetIndex(); + //ind1 = ind.m_Index[2]; // init new vector with zeros newVec.Fill(0.0); // the old voxel value with duplicates typename ImageType::PixelType oldVec = oldIt.Get(); for(unsigned int i=0; i void mitk::DiffusionImage::ApplyMeasurementFrame() { m_Directions = GradientDirectionContainerType::New(); int c = 0; for(GradientDirectionContainerType::ConstIterator gdcit = m_OriginalDirections->Begin(); gdcit != m_OriginalDirections->End(); ++gdcit) { vnl_vector vec = gdcit.Value(); vec = vec.pre_multiply(m_MeasurementFrame); m_Directions->InsertElement(c, vec); c++; } } // returns number of gradients template int mitk::DiffusionImage::GetNumDirections() { int gradients = m_OriginalDirections->Size(); for (int i=0; iSize(); i++) if (GetB_Value(i)<=0) { gradients--; } return gradients; } // returns number of not diffusion weighted images template int mitk::DiffusionImage::GetNumB0() { int b0 = 0; for (int i=0; iSize(); i++) if (GetB_Value(i)<=0) { b0++; } return b0; } // returns a list of indices belonging to the not diffusion weighted images template std::vector mitk::DiffusionImage::GetB0Indices() { std::vector indices; for (int i=0; iSize(); i++) if (GetB_Value(i)<=0) { indices.push_back(i); } return indices; } template bool mitk::DiffusionImage::IsMultiBval() { int gradients = m_OriginalDirections->Size(); for (int i=0; i0 && std::fabs(m_B_Value-GetB_Value(i))>50) return true; return false; } diff --git a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp index 6d860362c1..6a7af4c788 100644 --- a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp +++ b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp @@ -1,1262 +1,1263 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $ Version: $Revision: 21975 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkFiberBundleX.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const char* mitk::FiberBundleX::COLORCODING_ORIENTATION_BASED = "Color_Orient"; //const char* mitk::FiberBundleX::COLORCODING_FA_AS_OPACITY = "Color_Orient_FA_Opacity"; const char* mitk::FiberBundleX::COLORCODING_FA_BASED = "FA_Values"; const char* mitk::FiberBundleX::COLORCODING_CUSTOM = "custom"; const char* mitk::FiberBundleX::FIBER_ID_ARRAY = "Fiber_IDs"; mitk::FiberBundleX::FiberBundleX( vtkPolyData* fiberPolyData ) : m_CurrentColorCoding(NULL) , m_NumFibers(0) { m_FiberPolyData = vtkSmartPointer::New(); if (fiberPolyData != NULL) { vtkSmartPointer cleaner = vtkSmartPointer::New(); cleaner->SetInput(fiberPolyData); cleaner->Update(); fiberPolyData = cleaner->GetOutput(); m_FiberPolyData->DeepCopy(fiberPolyData); this->DoColorCodingOrientationBased(); } if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)) MITK_DEBUG << "ok"; vtkUnsignedCharArray* tmpColors = (vtkUnsignedCharArray*) m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED); if (tmpColors!=NULL) { int tmpColorss = tmpColors->GetNumberOfTuples(); int tmpColorc = tmpColors->GetNumberOfComponents(); } m_NumFibers = m_FiberPolyData->GetNumberOfLines(); this->UpdateFiberGeometry(); this->SetColorCoding(COLORCODING_ORIENTATION_BASED); this->GenerateFiberIds(); } mitk::FiberBundleX::~FiberBundleX() { } mitk::FiberBundleX::Pointer mitk::FiberBundleX::GetDeepCopy() { mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(m_FiberPolyData); if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)) MITK_DEBUG << "ok"; vtkUnsignedCharArray* tmpColors = (vtkUnsignedCharArray*) m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED); int tmpColorss = tmpColors->GetNumberOfTuples(); int tmpColorc = tmpColors->GetNumberOfComponents(); newFib->SetColorCoding(m_CurrentColorCoding); return newFib; } vtkSmartPointer mitk::FiberBundleX::GeneratePolyDataByIds(std::vector fiberIds) { MITK_DEBUG << "\n=====FINAL RESULT: fib_id ======\n"; MITK_DEBUG << "Number of new Fibers: " << fiberIds.size(); // iterate through the vectorcontainer hosting all desired fiber Ids vtkSmartPointer newFiberPolyData = vtkSmartPointer::New(); vtkSmartPointer newLineSet = vtkSmartPointer::New(); vtkSmartPointer newPointSet = vtkSmartPointer::New(); // if FA array available, initialize fa double array // if color orient array is available init color array vtkSmartPointer faValueArray; vtkSmartPointer colorsT; //colors and alpha value for each single point, RGBA = 4 components unsigned char rgba[4] = {0,0,0,0}; int componentSize = sizeof(rgba); if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_FA_BASED)){ MITK_DEBUG << "FA VALUES AVAILABLE, init array for new fiberbundle"; faValueArray = vtkSmartPointer::New(); } if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)){ MITK_DEBUG << "colorValues available, init array for new fiberbundle"; colorsT = vtkUnsignedCharArray::New(); colorsT->SetNumberOfComponents(componentSize); colorsT->SetName(COLORCODING_ORIENTATION_BASED); } std::vector::iterator finIt = fiberIds.begin(); while ( finIt != fiberIds.end() ) { if (*finIt < 0 || *finIt>GetNumFibers()){ MITK_INFO << "FiberID can not be negative or >NumFibers!!! check id Extraction!" << *finIt; break; } vtkSmartPointer fiber = m_FiberIdDataSet->GetCell(*finIt);//->DeepCopy(fiber); vtkSmartPointer fibPoints = fiber->GetPoints(); vtkSmartPointer newFiber = vtkSmartPointer::New(); newFiber->GetPointIds()->SetNumberOfIds( fibPoints->GetNumberOfPoints() ); for(int i=0; iGetNumberOfPoints(); i++) { // MITK_DEBUG << "id: " << fiber->GetPointId(i); // MITK_DEBUG << fibPoints->GetPoint(i)[0] << " | " << fibPoints->GetPoint(i)[1] << " | " << fibPoints->GetPoint(i)[2]; newFiber->GetPointIds()->SetId(i, newPointSet->GetNumberOfPoints()); newPointSet->InsertNextPoint(fibPoints->GetPoint(i)[0], fibPoints->GetPoint(i)[1], fibPoints->GetPoint(i)[2]); if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_FA_BASED)){ // MITK_DEBUG << m_FiberIdDataSet->GetPointData()->GetArray(FA_VALUE_ARRAY)->GetTuple(fiber->GetPointId(i)); } if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)){ // MITK_DEBUG << "ColorValue: " << m_FiberIdDataSet->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)->GetTuple(fiber->GetPointId(i))[0]; } } newLineSet->InsertNextCell(newFiber); ++finIt; } newFiberPolyData->SetPoints(newPointSet); newFiberPolyData->SetLines(newLineSet); MITK_DEBUG << "new fiberbundle polydata points: " << newFiberPolyData->GetNumberOfPoints(); MITK_DEBUG << "new fiberbundle polydata lines: " << newFiberPolyData->GetNumberOfLines(); MITK_DEBUG << "=====================\n"; // mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(newFiberPolyData); return newFiberPolyData; } // merge two fiber bundles mitk::FiberBundleX::Pointer mitk::FiberBundleX::AddBundle(mitk::FiberBundleX* fib) { vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); vtkSmartPointer vLines = m_FiberPolyData->GetLines(); vLines->InitTraversal(); // add current fiber bundle int numFibers = GetNumFibers(); for( int i=0; iGetNextCell ( numPoints, points ); vtkSmartPointer container = vtkSmartPointer::New(); for( int j=0; jInsertNextPoint(m_FiberPolyData->GetPoint(points[j])); container->GetPointIds()->InsertNextId(id); } vNewLines->InsertNextCell(container); } vLines = fib->m_FiberPolyData->GetLines(); vLines->InitTraversal(); // add new fiber bundle numFibers = fib->GetNumFibers(); for( int i=0; iGetNextCell ( numPoints, points ); vtkSmartPointer container = vtkSmartPointer::New(); for( int j=0; jInsertNextPoint(fib->m_FiberPolyData->GetPoint(points[j])); container->GetPointIds()->InsertNextId(id); } vNewLines->InsertNextCell(container); } // initialize polydata vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(vNewPolyData); return newFib; } // subtract two fiber bundles mitk::FiberBundleX::Pointer mitk::FiberBundleX::SubtractBundle(mitk::FiberBundleX* fib) { vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); vtkSmartPointer vLines = m_FiberPolyData->GetLines(); vLines->InitTraversal(); // iterate over current fibers int numFibers = GetNumFibers(); for( int i=0; iGetNextCell ( numPoints, points ); vtkSmartPointer vLines2 = fib->m_FiberPolyData->GetLines(); vLines2->InitTraversal(); int numFibers2 = fib->GetNumFibers(); bool contained = false; for( int i2=0; i2GetNextCell ( numPoints2, points2 ); // check endpoints itk::Point point_start = GetItkPoint(m_FiberPolyData->GetPoint(points[0])); itk::Point point_end = GetItkPoint(m_FiberPolyData->GetPoint(points[numPoints-1])); itk::Point point2_start = GetItkPoint(fib->m_FiberPolyData->GetPoint(points2[0])); itk::Point point2_end = GetItkPoint(fib->m_FiberPolyData->GetPoint(points2[numPoints2-1])); if (point_start.SquaredEuclideanDistanceTo(point2_start)<=mitk::eps && point_end.SquaredEuclideanDistanceTo(point2_end)<=mitk::eps || point_start.SquaredEuclideanDistanceTo(point2_end)<=mitk::eps && point_end.SquaredEuclideanDistanceTo(point2_start)<=mitk::eps) { // further checking ??? contained = true; } } // add to result because fiber is not subtracted if (!contained) { vtkSmartPointer container = vtkSmartPointer::New(); for( int j=0; jInsertNextPoint(m_FiberPolyData->GetPoint(points[j])); container->GetPointIds()->InsertNextId(id); } vNewLines->InsertNextCell(container); } } - + if(vNewLines->GetNumberOfCells()==0) + return NULL; // initialize polydata vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(vNewPolyData); return newFib; } itk::Point mitk::FiberBundleX::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } /* * set polydata (additional flag to recompute fiber geometry, default = true) */ void mitk::FiberBundleX::SetFiberPolyData(vtkSmartPointer fiberPD, bool updateGeometry) { if (fiberPD == NULL) this->m_FiberPolyData = vtkSmartPointer::New(); else { m_FiberPolyData->DeepCopy(fiberPD); DoColorCodingOrientationBased(); } m_NumFibers = m_FiberPolyData->GetNumberOfLines(); if (updateGeometry) UpdateFiberGeometry(); SetColorCoding(COLORCODING_ORIENTATION_BASED); GenerateFiberIds(); } /* * return vtkPolyData */ vtkSmartPointer mitk::FiberBundleX::GetFiberPolyData() { return m_FiberPolyData; } void mitk::FiberBundleX::DoColorCodingOrientationBased() { //===== FOR WRITING A TEST ======================== // colorT size == tupelComponents * tupelElements // compare color results // to cover this code 100% also polydata needed, where colorarray already exists // + one fiber with exactly 1 point // + one fiber with 0 points //================================================= /* make sure that processing colorcoding is only called when necessary */ if ( m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED) && m_FiberPolyData->GetNumberOfPoints() == m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)->GetNumberOfTuples() ) { // fiberstructure is already colorcoded MITK_DEBUG << " NO NEED TO REGENERATE COLORCODING! " ; this->ResetFiberOpacity(); this->SetColorCoding(COLORCODING_ORIENTATION_BASED); return; } /* Finally, execute color calculation */ vtkPoints* extrPoints = NULL; extrPoints = m_FiberPolyData->GetPoints(); int numOfPoints = 0; if (extrPoints!=NULL) numOfPoints = extrPoints->GetNumberOfPoints(); //colors and alpha value for each single point, RGBA = 4 components unsigned char rgba[4] = {0,0,0,0}; // int componentSize = sizeof(rgba); int componentSize = 4; vtkSmartPointer colorsT = vtkUnsignedCharArray::New(); colorsT->Allocate(numOfPoints * componentSize); colorsT->SetNumberOfComponents(componentSize); colorsT->SetName(COLORCODING_ORIENTATION_BASED); /* checkpoint: does polydata contain any fibers */ int numOfFibers = m_FiberPolyData->GetNumberOfLines(); if (numOfFibers < 1) { MITK_DEBUG << "\n ========= Number of Fibers is 0 and below ========= \n"; return; } /* extract single fibers of fiberBundle */ vtkCellArray* fiberList = m_FiberPolyData->GetLines(); fiberList->InitTraversal(); for (int fi=0; fiGetNextCell(pointsPerFiber, idList); // MITK_DEBUG << "Fib#: " << fi << " of " << numOfFibers << " pnts in fiber: " << pointsPerFiber ; /* single fiber checkpoints: is number of points valid */ if (pointsPerFiber > 1) { /* operate on points of single fiber */ for (int i=0; i 0) { /* The color value of the current point is influenced by the previous point and next point. */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); vnl_vector_fixed< double, 3 > diff1; diff1 = currentPntvtk - nextPntvtk; vnl_vector_fixed< double, 3 > diff2; diff2 = currentPntvtk - prevPntvtk; vnl_vector_fixed< double, 3 > diff; diff = (diff1 - diff2) / 2.0; diff.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff[2])); rgba[3] = (unsigned char) (255.0); } else if (i==0) { /* First point has no previous point, therefore only diff1 is taken */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); vnl_vector_fixed< double, 3 > diff1; diff1 = currentPntvtk - nextPntvtk; diff1.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff1[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff1[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff1[2])); rgba[3] = (unsigned char) (255.0); } else if (i==pointsPerFiber-1) { /* Last point has no next point, therefore only diff2 is taken */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); vnl_vector_fixed< double, 3 > diff2; diff2 = currentPntvtk - prevPntvtk; diff2.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff2[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff2[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff2[2])); rgba[3] = (unsigned char) (255.0); } colorsT->InsertTupleValue(idList[i], rgba); } //end for loop } else if (pointsPerFiber == 1) { /* a single point does not define a fiber (use vertex mechanisms instead */ continue; // colorsT->InsertTupleValue(0, rgba); } else { MITK_DEBUG << "Fiber with 0 points detected... please check your tractography algorithm!" ; continue; } }//end for loop m_FiberPolyData->GetPointData()->AddArray(colorsT); /*========================= - this is more relevant for renderer than for fiberbundleX datastructure - think about sourcing this to a explicit method which coordinates colorcoding */ this->SetColorCoding(COLORCODING_ORIENTATION_BASED); // =========================== //mini test, shall be ported to MITK TESTINGS! if (colorsT->GetSize() != numOfPoints*componentSize) MITK_DEBUG << "ALLOCATION ERROR IN INITIATING COLOR ARRAY"; } void mitk::FiberBundleX::DoColorCodingFaBased() { if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED) != 1 ) return; this->SetColorCoding(COLORCODING_FA_BASED); MITK_DEBUG << "FBX: done CC FA based"; this->GenerateFiberIds(); } void mitk::FiberBundleX::DoUseFaFiberOpacity() { if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED) != 1 ) return; if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED) != 1 ) return; vtkDoubleArray* FAValArray = (vtkDoubleArray*) m_FiberPolyData->GetPointData()->GetArray(COLORCODING_FA_BASED); vtkUnsignedCharArray* ColorArray = dynamic_cast (m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)); for(long i=0; iGetNumberOfTuples(); i++) { double faValue = FAValArray->GetValue(i); faValue = faValue * 255.0; ColorArray->SetComponent(i,3, (unsigned char) faValue ); } this->SetColorCoding(COLORCODING_ORIENTATION_BASED); MITK_DEBUG << "FBX: done CC OPACITY"; this->GenerateFiberIds(); } void mitk::FiberBundleX::ResetFiberOpacity() { vtkUnsignedCharArray* ColorArray = dynamic_cast (m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)); for(long i=0; iGetNumberOfTuples(); i++) { ColorArray->SetComponent(i,3, 255.0 ); } } void mitk::FiberBundleX::SetFAMap(mitk::Image::Pointer FAimage) { MITK_DEBUG << "SetFAMap"; vtkSmartPointer faValues = vtkDoubleArray::New(); faValues->SetName(COLORCODING_FA_BASED); faValues->Allocate(m_FiberPolyData->GetNumberOfPoints()); // MITK_DEBUG << faValues->GetNumberOfTuples(); // MITK_DEBUG << faValues->GetSize(); faValues->SetNumberOfValues(m_FiberPolyData->GetNumberOfPoints()); // MITK_DEBUG << faValues->GetNumberOfTuples(); // MITK_DEBUG << faValues->GetSize(); vtkPoints* pointSet = m_FiberPolyData->GetPoints(); for(long i=0; iGetNumberOfPoints(); ++i) { Point3D px; px[0] = pointSet->GetPoint(i)[0]; px[1] = pointSet->GetPoint(i)[1]; px[2] = pointSet->GetPoint(i)[2]; - double faPixelValue = FAimage->GetPixelValueByWorldCoordinate(px) * 0.01; + double faPixelValue = 1-FAimage->GetPixelValueByWorldCoordinate(px); // faValues->InsertNextTuple1(faPixelValue); faValues->InsertValue(i, faPixelValue); // MITK_DEBUG << faPixelValue; // MITK_DEBUG << faValues->GetValue(i); } m_FiberPolyData->GetPointData()->AddArray(faValues); this->GenerateFiberIds(); if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED)) MITK_DEBUG << "FA VALUE ARRAY SET"; // vtkDoubleArray* valueArray = (vtkDoubleArray*) m_FiberPolyData->GetPointData()->GetArray(FA_VALUE_ARRAY); // for(long i=0; iGetNumberOfPoints(); i++) // { // MITK_DEBUG << "value at pos "<< i << ": " << valueArray->GetValue(i); // } } void mitk::FiberBundleX::GenerateFiberIds() { if (m_FiberPolyData == NULL) return; vtkSmartPointer idFiberFilter = vtkSmartPointer::New(); idFiberFilter->SetInput(m_FiberPolyData); idFiberFilter->CellIdsOn(); // idFiberFilter->PointIdsOn(); // point id's are not needed idFiberFilter->SetIdsArrayName(FIBER_ID_ARRAY); idFiberFilter->FieldDataOn(); idFiberFilter->Update(); m_FiberIdDataSet = idFiberFilter->GetOutput(); MITK_DEBUG << "Generating Fiber Ids...[done] | " << m_FiberIdDataSet->GetNumberOfCells(); } mitk::FiberBundleX::Pointer mitk::FiberBundleX::ExtractFiberSubset(mitk::PlanarFigure::Pointer pf) { std::vector tmp = ExtractFiberIdSubset(pf); if (tmp.size()<=0) return mitk::FiberBundleX::New(); vtkSmartPointer pTmp = GeneratePolyDataByIds(tmp); return mitk::FiberBundleX::New(pTmp); } std::vector mitk::FiberBundleX::ExtractFiberIdSubset(mitk::PlanarFigure::Pointer pf) { MITK_DEBUG << "Extracting fibers!"; // vector which is returned, contains all extracted FiberIds std::vector FibersInROI; /* Handle type of planarfigure */ // if incoming pf is a pfc mitk::PlanarFigureComposite::Pointer pfcomp= dynamic_cast(pf.GetPointer()); if (!pfcomp.IsNull()) { // process requested boolean operation of PFC switch (pfcomp->getOperationType()) { case 0: { MITK_DEBUG << "AND PROCESSING"; //AND //temporarly store results of the child in this vector, we need that to accumulate the std::vector childResults = this->ExtractFiberIdSubset(pfcomp->getChildAt(0)); MITK_DEBUG << "first roi got fibers in ROI: " << childResults.size(); MITK_DEBUG << "sorting..."; std::sort(childResults.begin(), childResults.end()); MITK_DEBUG << "sorting done"; std::vector AND_Assamblage(childResults.size()); //std::vector AND_Assamblage; fill(AND_Assamblage.begin(), AND_Assamblage.end(), -1); //AND_Assamblage.reserve(childResults.size()); //max size AND can reach anyway std::vector::iterator it; for (int i=1; igetNumberOfChildren(); ++i) { std::vector tmpChild = this->ExtractFiberIdSubset(pfcomp->getChildAt(i)); MITK_DEBUG << "ROI " << i << " has fibers in ROI: " << tmpChild.size(); sort(tmpChild.begin(), tmpChild.end()); it = std::set_intersection(childResults.begin(), childResults.end(), tmpChild.begin(), tmpChild.end(), AND_Assamblage.begin() ); } MITK_DEBUG << "resize Vector"; long i=0; while (i < AND_Assamblage.size() && AND_Assamblage[i] != -1){ //-1 represents a placeholder in the array ++i; } AND_Assamblage.resize(i); MITK_DEBUG << "returning AND vector, size: " << AND_Assamblage.size(); return AND_Assamblage; // break; } case 1: { //OR std::vector OR_Assamblage = this->ExtractFiberIdSubset(pfcomp->getChildAt(0)); std::vector::iterator it; MITK_DEBUG << OR_Assamblage.size(); for (int i=1; igetNumberOfChildren(); ++i) { it = OR_Assamblage.end(); std::vector tmpChild = this->ExtractFiberIdSubset(pfcomp->getChildAt(i)); OR_Assamblage.insert(it, tmpChild.begin(), tmpChild.end()); MITK_DEBUG << "ROI " << i << " has fibers in ROI: " << tmpChild.size() << " OR Assamblage: " << OR_Assamblage.size(); } sort(OR_Assamblage.begin(), OR_Assamblage.end()); it = unique(OR_Assamblage.begin(), OR_Assamblage.end()); OR_Assamblage.resize( it - OR_Assamblage.begin() ); MITK_DEBUG << "returning OR vector, size: " << OR_Assamblage.size(); return OR_Assamblage; } case 2: { //NOT //get IDs of all fibers std::vector childResults; childResults.reserve(this->GetNumFibers()); vtkSmartPointer idSet = m_FiberIdDataSet->GetCellData()->GetArray(FIBER_ID_ARRAY); MITK_DEBUG << "m_NumOfFib: " << this->GetNumFibers() << " cellIdNum: " << idSet->GetNumberOfTuples(); for(long i=0; iGetNumFibers(); i++) { MITK_DEBUG << "i: " << i << " idset: " << idSet->GetTuple(i)[0]; childResults.push_back(idSet->GetTuple(i)[0]); } std::sort(childResults.begin(), childResults.end()); std::vector NOT_Assamblage(childResults.size()); //fill it with -1, otherwise 0 will be stored and 0 can also be an ID of fiber! fill(NOT_Assamblage.begin(), NOT_Assamblage.end(), -1); std::vector::iterator it; for (long i=0; igetNumberOfChildren(); ++i) { std::vector tmpChild = ExtractFiberIdSubset(pfcomp->getChildAt(i)); sort(tmpChild.begin(), tmpChild.end()); it = std::set_difference(childResults.begin(), childResults.end(), tmpChild.begin(), tmpChild.end(), NOT_Assamblage.begin() ); } MITK_DEBUG << "resize Vector"; long i=0; while (NOT_Assamblage[i] != -1){ //-1 represents a placeholder in the array ++i; } NOT_Assamblage.resize(i); return NOT_Assamblage; } default: MITK_DEBUG << "we have an UNDEFINED composition... ERROR" ; break; } } else { mitk::Geometry2D::ConstPointer pfgeometry = pf->GetGeometry2D(); const mitk::PlaneGeometry* planeGeometry = dynamic_cast (pfgeometry.GetPointer()); Vector3D planeNormal = planeGeometry->GetNormal(); planeNormal.Normalize(); Point3D planeOrigin = planeGeometry->GetOrigin(); MITK_DEBUG << "planeOrigin: " << planeOrigin[0] << " | " << planeOrigin[1] << " | " << planeOrigin[2] << endl; MITK_DEBUG << "planeNormal: " << planeNormal[0] << " | " << planeNormal[1] << " | " << planeNormal[2] << endl; std::vector PointsOnPlane; // contains all pointIds which are crossing the cutting plane std::vector PointsInROI; // based on PointsOnPlane, all ROI relevant point IDs are stored here /* Define cutting plane by ROI (PlanarFigure) */ vtkSmartPointer plane = vtkSmartPointer::New(); plane->SetOrigin(planeOrigin[0],planeOrigin[1],planeOrigin[2]); plane->SetNormal(planeNormal[0],planeNormal[1],planeNormal[2]); //same plane but opposite normal direction. so point cloud will be reduced -> better performance // vtkSmartPointer planeR = vtkSmartPointer::New(); //define new origin along the normal but close to the original one // OriginNew = OriginOld + 1*Normal // Vector3D extendedNormal; // int multiplyFactor = 1; // extendedNormal[0] = planeNormal[0] * multiplyFactor; // extendedNormal[1] = planeNormal[1] * multiplyFactor; // extendedNormal[2] = planeNormal[2] * multiplyFactor; // Point3D RplaneOrigin = planeOrigin - extendedNormal; // planeR->SetOrigin(RplaneOrigin[0],RplaneOrigin[1],RplaneOrigin[2]); // planeR->SetNormal(-planeNormal[0],-planeNormal[1],-planeNormal[2]); // MITK_DEBUG << "RPlaneOrigin: " << RplaneOrigin[0] << " | " << RplaneOrigin[1] // << " | " << RplaneOrigin[2]; /* get all points/fibers cutting the plane */ MITK_DEBUG << "start clipping"; vtkSmartPointer clipper = vtkSmartPointer::New(); clipper->SetInput(m_FiberIdDataSet); clipper->SetClipFunction(plane); clipper->GenerateClipScalarsOn(); clipper->GenerateClippedOutputOn(); vtkSmartPointer clipperout = clipper->GetClippedOutput(); MITK_DEBUG << "end clipping"; /* for some reason clipperoutput is not initialized for futher processing * so far only writing out clipped polydata provides requested */ // MITK_DEBUG << "writing clipper output"; // vtkSmartPointer writerC = vtkSmartPointer::New(); // writerC->SetInput(clipperout1); // writerC->SetFileName("/vtkOutput/Clipping.vtk"); // writerC->SetFileTypeToASCII(); // writerC->Write(); // MITK_DEBUG << "writing done"; MITK_DEBUG << "init and update clipperoutput"; clipperout->GetPointData()->Initialize(); clipperout->Update(); MITK_DEBUG << "init and update clipperoutput completed"; // MITK_DEBUG << "start clippingRecursive"; // vtkSmartPointer Rclipper = vtkSmartPointer::New(); // Rclipper->SetInput(clipperout1); // Rclipper->SetClipFunction(planeR); // Rclipper->GenerateClipScalarsOn(); // Rclipper->GenerateClippedOutputOn(); // vtkSmartPointer clipperout = Rclipper->GetClippedOutput(); // MITK_DEBUG << "end clipping recursive"; // MITK_DEBUG << "writing clipper output 2"; // vtkSmartPointer writerC1 = vtkSmartPointer::New(); // writerC1->SetInput(clipperout); // writerC1->SetFileName("/vtkOutput/RClipping.vtk"); // writerC1->SetFileTypeToASCII(); // writerC1->Write(); // MITK_DEBUG << "init and update clipperoutput"; // clipperout->GetPointData()->Initialize(); // clipperout->Update(); // MITK_DEBUG << "init and update clipperoutput completed"; MITK_DEBUG << "STEP 1: find all points which have distance 0 to the given plane"; /*======STEP 1====== * extract all points, which are crossing the plane */ // Scalar values describe the distance between each remaining point to the given plane. Values sorted by point index vtkSmartPointer distanceList = clipperout->GetPointData()->GetScalars(); vtkIdType sizeOfList = distanceList->GetNumberOfTuples(); PointsOnPlane.reserve(sizeOfList); /* use reserve for high-performant push_back, no hidden copy procedures are processed then! * size of list can be optimized by reducing allocation, but be aware of iterator and vector size*/ for (int i=0; iGetTuple(i); // check if point is on plane. // 0.01 due to some approximation errors when calculating distance if (distance[0] >= -0.01 && distance[0] <= 0.01) PointsOnPlane.push_back(i); } // DEBUG print out all interesting points, stop where array starts with value -1. after -1 no more interesting idx are set! // std::vector::iterator rit = PointsOnPlane.begin(); // while (rit != PointsOnPlane.end() ) { // std::cout << "interesting point: " << *rit << " coord: " << clipperout->GetPoint(*rit)[0] << " | " << clipperout->GetPoint(*rit)[1] << " | " << clipperout->GetPoint(*rit)[2] << endl; // rit++; // } MITK_DEBUG << "Num Of points on plane: " << PointsOnPlane.size(); MITK_DEBUG << "Step 2: extract Interesting points with respect to given extraction planarFigure"; PointsInROI.reserve(PointsOnPlane.size()); /*=======STEP 2===== * extract ROI relevant pointIds */ mitk::PlanarCircle::Pointer circleName = mitk::PlanarCircle::New(); mitk::PlanarPolygon::Pointer polyName = mitk::PlanarPolygon::New(); if ( pf->GetNameOfClass() == circleName->GetNameOfClass() ) { //calculate circle radius mitk::Point3D V1w = pf->GetWorldControlPoint(0); //centerPoint mitk::Point3D V2w = pf->GetWorldControlPoint(1); //radiusPoint double distPF = V1w.EuclideanDistanceTo(V2w); for (int i=0; iGetPoint(PointsOnPlane[i])[0] - V1w[0]) * (clipperout->GetPoint(PointsOnPlane[i])[0] - V1w[0]) + (clipperout->GetPoint(PointsOnPlane[i])[1] - V1w[1]) * (clipperout->GetPoint(PointsOnPlane[i])[1] - V1w[1]) + (clipperout->GetPoint(PointsOnPlane[i])[2] - V1w[2]) * (clipperout->GetPoint(PointsOnPlane[i])[2] - V1w[2])) ; if( XdistPnt <= distPF) PointsInROI.push_back(PointsOnPlane[i]); } } else if ( pf->GetNameOfClass() == polyName->GetNameOfClass() ) { //create vtkPolygon using controlpoints from planarFigure polygon vtkSmartPointer polygonVtk = vtkPolygon::New(); //get the control points from pf and insert them to vtkPolygon unsigned int nrCtrlPnts = pf->GetNumberOfControlPoints(); for (int i=0; iGetPoints()->InsertNextPoint((double)pf->GetWorldControlPoint(i)[0], (double)pf->GetWorldControlPoint(i)[1], (double)pf->GetWorldControlPoint(i)[2] ); } //prepare everything for using pointInPolygon function double n[3]; polygonVtk->ComputeNormal(polygonVtk->GetPoints()->GetNumberOfPoints(), static_cast(polygonVtk->GetPoints()->GetData()->GetVoidPointer(0)), n); double bounds[6]; polygonVtk->GetPoints()->GetBounds(bounds); for (int i=0; iGetPoint(PointsOnPlane[i])[0], clipperout->GetPoint(PointsOnPlane[i])[1], clipperout->GetPoint(PointsOnPlane[i])[2]}; int isInPolygon = polygonVtk->PointInPolygon(checkIn, polygonVtk->GetPoints()->GetNumberOfPoints() , static_cast(polygonVtk->GetPoints()->GetData()->GetVoidPointer(0)), bounds, n); if( isInPolygon ) PointsInROI.push_back(PointsOnPlane[i]); } } MITK_DEBUG << "Step3: Identify fibers"; // we need to access the fiberId Array, so make sure that this array is available if (!clipperout->GetCellData()->HasArray(FIBER_ID_ARRAY)) { MITK_DEBUG << "ERROR: FiberID array does not exist, no correlation between points and fiberIds possible! Make sure calling GenerateFiberIds()"; return FibersInROI; // FibersInRoi is empty then } if (PointsInROI.size()<=0) return FibersInROI; // prepare a structure where each point id is represented as an indexId. // vector looks like: | pntId | fiberIdx | std::vector< long > pointindexFiberMap; // walk through the whole subline section and create an vector sorted by point index vtkCellArray *clipperlines = clipperout->GetLines(); clipperlines->InitTraversal(); long numOfLineCells = clipperlines->GetNumberOfCells(); long numofClippedPoints = clipperout->GetNumberOfPoints(); pointindexFiberMap.reserve(numofClippedPoints); //prepare resulting vector FibersInROI.reserve(PointsInROI.size()); MITK_DEBUG << "\n===== Pointindex based structure initialized ======\n"; // go through resulting "sub"lines which are stored as cells, "i" corresponds to current line id. for (int i=0, ic=0 ; iGetCell(ic, npts, pts); // go through point ids in hosting subline, "j" corresponds to current pointindex in current line i. eg. idx[0]=45; idx[1]=46 for (long j=0; jGetCellData()->GetArray(FIBER_ID_ARRAY)->GetTuple(i)[0] << " to pointId: " << pts[j]; pointindexFiberMap[ pts[j] ] = clipperout->GetCellData()->GetArray(FIBER_ID_ARRAY)->GetTuple(i)[0]; // MITK_DEBUG << "in array: " << pointindexFiberMap[ pts[j] ]; } } MITK_DEBUG << "\n===== Pointindex based structure finalized ======\n"; // get all Points in ROI with according fiberID for (long k = 0; k < PointsInROI.size(); k++) { //MITK_DEBUG << "point " << PointsInROI[k] << " belongs to fiber " << pointindexFiberMap[ PointsInROI[k] ]; if (pointindexFiberMap[ PointsInROI[k] ]<=GetNumFibers() && pointindexFiberMap[ PointsInROI[k] ]>=0) FibersInROI.push_back(pointindexFiberMap[ PointsInROI[k] ]); else MITK_INFO << "ERROR in ExtractFiberIdSubset; impossible fiber id detected"; } } // detecting fiberId duplicates MITK_DEBUG << "check for duplicates"; sort(FibersInROI.begin(), FibersInROI.end()); bool hasDuplicats = false; for(long i=0; i::iterator it; it = unique (FibersInROI.begin(), FibersInROI.end()); FibersInROI.resize( it - FibersInROI.begin() ); } return FibersInROI; } void mitk::FiberBundleX::UpdateFiberGeometry() { if (m_NumFibers<=0) { mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->SetImageGeometry(true); float b[] = {0, 1, 0, 1, 0, 1}; geometry->SetFloatBounds(b); SetGeometry(geometry); return; } float min = itk::NumericTraits::min(); float max = itk::NumericTraits::max(); float b[] = {max, min, max, min, max, min}; vtkCellArray* cells = m_FiberPolyData->GetLines(); cells->InitTraversal(); for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int p = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j, p); if (p[0]b[1]) b[1]=p[0]; if (p[1]b[3]) b[3]=p[1]; if (p[2]b[5]) b[5]=p[2]; } } // provide some border margin for(int i=0; i<=4; i+=2) b[i] -=10; for(int i=1; i<=5; i+=2) b[i] +=10; mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->SetImageGeometry(true); geometry->SetFloatBounds(b); this->SetGeometry(geometry); } QStringList mitk::FiberBundleX::GetAvailableColorCodings() { QStringList availableColorCodings; int numColors = m_FiberPolyData->GetPointData()->GetNumberOfArrays(); for(int i=0; iGetPointData()->GetArrayName(i)); } //this controlstructure shall be implemented by the calling method if (availableColorCodings.isEmpty()) MITK_DEBUG << "no colorcodings available in fiberbundleX"; // for(int i=0; im_CurrentColorCoding = (char*) COLORCODING_ORIENTATION_BASED; } else if( strcmp (COLORCODING_FA_BASED,requestedColorCoding) == 0 ) { this->m_CurrentColorCoding = (char*) COLORCODING_FA_BASED; } else if( strcmp (COLORCODING_CUSTOM,requestedColorCoding) == 0 ) { this->m_CurrentColorCoding = (char*) COLORCODING_CUSTOM; } else { MITK_DEBUG << "FIBERBUNDLE X: UNKNOWN COLORCODING in FIBERBUNDLEX Datastructure"; this->m_CurrentColorCoding = (char*) COLORCODING_CUSTOM; //will cause blank colorcoding of fibers } } void mitk::FiberBundleX::DoFiberSmoothing(int pointsPerCm) { vtkSmartPointer vtkSmoothPoints = vtkPoints::New(); //in smoothpoints the interpolated points representing a fiber are stored. //in vtkcells all polylines are stored, actually all id's of them are stored vtkSmartPointer vtkSmoothCells = vtkCellArray::New(); //cellcontainer for smoothed lines vtkSmartPointer vLines = m_FiberPolyData->GetLines(); vLines->InitTraversal(); vtkIdType pointHelperCnt = 0; for (int i=0; iGetNextCell ( numPoints, pointIds ); vtkSmartPointer points = vtkSmartPointer::New(); float length = 0; itk::Point lastP; for (int j=0; jGetPoint(pointIds[j]); points->InsertNextPoint(p); if (j>0) length += sqrt(pow(p[0]-lastP[0], 2)+pow(p[1]-lastP[1], 2)+pow(p[2]-lastP[2], 2)); lastP[0] = p[0]; lastP[1] = p[1]; lastP[2] = p[2]; } length /=10; int sampling = pointsPerCm*length; /////PROCESS POLYLINE SMOOTHING///// vtkSmartPointer xSpline = vtkKochanekSpline::New(); vtkSmartPointer ySpline = vtkKochanekSpline::New(); vtkSmartPointer zSpline = vtkKochanekSpline::New(); vtkSmartPointer spline = vtkParametricSpline::New(); spline->SetXSpline(xSpline); spline->SetYSpline(ySpline); spline->SetZSpline(zSpline); spline->SetPoints(points); vtkSmartPointer functionSource = vtkParametricFunctionSource::New(); functionSource->SetParametricFunction(spline); functionSource->SetUResolution(sampling); functionSource->SetVResolution(sampling); functionSource->SetWResolution(sampling); functionSource->Update(); vtkPolyData* outputFunction = functionSource->GetOutput(); vtkPoints* tmpSmoothPnts = outputFunction->GetPoints(); //smoothPoints of current fiber vtkSmartPointer smoothLine = vtkPolyLine::New(); smoothLine->GetPointIds()->SetNumberOfIds(tmpSmoothPnts->GetNumberOfPoints()); for (int j=0; jGetNumberOfPoints(); j++) { smoothLine->GetPointIds()->SetId(j, j+pointHelperCnt); vtkSmoothPoints->InsertNextPoint(tmpSmoothPnts->GetPoint(j)); } vtkSmoothCells->InsertNextCell(smoothLine); pointHelperCnt += tmpSmoothPnts->GetNumberOfPoints(); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkSmoothPoints); m_FiberPolyData->SetLines(vtkSmoothCells); UpdateColorCoding(); UpdateFiberGeometry(); } // Resample fiber to get equidistant points void mitk::FiberBundleX::ResampleFibers(float pointDistance) { vtkSmartPointer newPoly = vtkSmartPointer::New(); vtkSmartPointer newCellArray = vtkSmartPointer::New(); vtkSmartPointer newPoints = vtkSmartPointer::New(); vtkSmartPointer vLines = m_FiberPolyData->GetLines(); vLines->InitTraversal(); int numberOfLines = m_NumFibers; for (int i=0; iGetNextCell ( numPoints, points ); vtkSmartPointer container = vtkSmartPointer::New(); double* point = m_FiberPolyData->GetPoint(points[0]); vtkIdType pointId = newPoints->InsertNextPoint(point); container->GetPointIds()->InsertNextId(pointId); float dtau = 0; int cur_p = 1; itk::Vector dR; float normdR = 0; for (;;) { while (dtau <= pointDistance && cur_p < numPoints) { itk::Vector v1; point = m_FiberPolyData->GetPoint(points[cur_p-1]); v1[0] = point[0]; v1[1] = point[1]; v1[2] = point[2]; itk::Vector v2; point = m_FiberPolyData->GetPoint(points[cur_p]); v2[0] = point[0]; v2[1] = point[1]; v2[2] = point[2]; dR = v2 - v1; normdR = std::sqrt(dR.GetSquaredNorm()); dtau += normdR; cur_p++; } if (dtau >= pointDistance) { itk::Vector v1; point = m_FiberPolyData->GetPoint(points[cur_p-1]); v1[0] = point[0]; v1[1] = point[1]; v1[2] = point[2]; itk::Vector v2 = v1 - dR*( (dtau-pointDistance)/normdR ); pointId = newPoints->InsertNextPoint(v2.GetDataPointer()); container->GetPointIds()->InsertNextId(pointId); } else { point = m_FiberPolyData->GetPoint(points[numPoints-1]); pointId = newPoints->InsertNextPoint(point); container->GetPointIds()->InsertNextId(pointId); break; } dtau = dtau-pointDistance; } newCellArray->InsertNextCell(container); } newPoly->SetPoints(newPoints); newPoly->SetLines(newCellArray); m_FiberPolyData = newPoly; UpdateFiberGeometry(); UpdateColorCoding(); } // reapply selected colorcoding in case polydata structure has changed void mitk::FiberBundleX::UpdateColorCoding() { char* cc = GetCurrentColorCoding(); if( strcmp (COLORCODING_ORIENTATION_BASED,cc) == 0 ) DoColorCodingOrientationBased(); else if( strcmp (COLORCODING_FA_BASED,cc) == 0 ) DoColorCodingFaBased(); } /* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */ void mitk::FiberBundleX::UpdateOutputInformation() { } void mitk::FiberBundleX::SetRequestedRegionToLargestPossibleRegion() { } bool mitk::FiberBundleX::RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } bool mitk::FiberBundleX::VerifyRequestedRegion() { return true; } void mitk::FiberBundleX::SetRequestedRegion( itk::DataObject *data ) { } diff --git a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper2D.cpp b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper2D.cpp index 676f219b52..6d3115e871 100644 --- a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper2D.cpp +++ b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper2D.cpp @@ -1,321 +1,321 @@ /* * mitkFiberBundleMapper2D.cpp * mitk-all * * Created by HAL9000 on 1/17/11. * Copyright 2011 __MyCompanyName__. All rights reserved. * */ #include "mitkFiberBundleXMapper2D.h" #include #include #include #include #include //#include //#include #include #include #include #include #include #include #include #include //#include #include #include #include #include #include #include #include mitk::FiberBundleXMapper2D::FiberBundleXMapper2D() { m_lut = vtkLookupTable::New(); m_lut->Build(); } mitk::FiberBundleXMapper2D::~FiberBundleXMapper2D() { } mitk::FiberBundleX* mitk::FiberBundleXMapper2D::GetInput() { return dynamic_cast< mitk::FiberBundleX * > ( GetData() ); } void mitk::FiberBundleXMapper2D::Update(mitk::BaseRenderer * renderer) { if ( !this->IsVisible( renderer ) ) { return; } - + MITK_INFO << "MapperFBX 2D update: "; // Calculate time step of the input data for the specified renderer (integer value) // this method is implemented in mitkMapper this->CalculateTimeStep( renderer ); //check if updates occured in the node or on the display FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); const DataNode *node = this->GetDataNode(); if ( (localStorage->m_LastUpdateTime < node->GetMTime()) || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) { // MITK_INFO << "UPDATE NEEDED FOR _ " << renderer->GetName(); this->GenerateDataForRenderer( renderer ); } if ((localStorage->m_LastUpdateTime < renderer->GetDisplayGeometry()->GetMTime()) ) //was the display geometry modified? e.g. zooming, panning) { this->UpdateShaderParameter(renderer); } } void mitk::FiberBundleXMapper2D::UpdateShaderParameter(mitk::BaseRenderer * renderer) { FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //get information about current position of views mitk::SliceNavigationController::Pointer sliceContr = renderer->GetSliceNavigationController(); mitk::PlaneGeometry::ConstPointer planeGeo = sliceContr->GetCurrentPlaneGeometry(); //generate according cutting planes based on the view position float sliceN[3], planeOrigin[3]; // since shader uses camera coordinates, transform origin and normal from worldcoordinates to cameracoordinates planeOrigin[0] = (float) planeGeo->GetOrigin()[0]; planeOrigin[1] = (float) planeGeo->GetOrigin()[1]; planeOrigin[2] = (float) planeGeo->GetOrigin()[2]; sliceN[0] = planeGeo->GetNormal()[0]; sliceN[1] = planeGeo->GetNormal()[1]; sliceN[2] = planeGeo->GetNormal()[2]; float tmp1 = planeOrigin[0] * sliceN[0]; float tmp2 = planeOrigin[1] * sliceN[1]; float tmp3 = planeOrigin[2] * sliceN[2]; float d1 = tmp1 + tmp2 + tmp3; //attention, correct normalvector float plane1[4]; plane1[0] = sliceN[0]; plane1[1] = sliceN[1]; plane1[2] = sliceN[2]; plane1[3] = d1; float thickness = 2.0; if(!this->GetDataNode()->GetPropertyValue("Fiber2DSliceThickness",thickness)) MITK_INFO << "FIBER2D SLICE THICKNESS PROPERTY ERROR"; bool fiberfading = false; if(!this->GetDataNode()->GetPropertyValue("Fiber2DfadeEFX",fiberfading)) MITK_INFO << "FIBER2D SLICE FADE EFX PROPERTY ERROR"; int fiberfading_i = 1; if (!fiberfading) fiberfading_i = 0; // set Opacity float fiberOpacity; this->GetDataNode()->GetOpacity(fiberOpacity, NULL); localStorage->m_PointActor->GetProperty()->AddShaderVariable("slicingPlane",4, plane1); localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberThickness",1, &thickness); localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberFadingON",1, &fiberfading_i); localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberOpacity", 1, &fiberOpacity); } // ALL RAW DATA FOR VISUALIZATION IS GENERATED HERE. // vtkActors and Mappers are feeded here void mitk::FiberBundleXMapper2D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { //the handler of local storage gets feeded in this method with requested data for related renderwindow FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //this procedure is depricated, //not needed after initializaton anymore mitk::DataNode* node = this->GetDataNode(); if ( node == NULL ) { MITK_INFO << "check DATANODE: ....[Fail] "; return; } /////////////////////////////////// ///THIS GET INPUT mitk::FiberBundleX* fbx = this->GetInput(); localStorage->m_PointMapper->ScalarVisibilityOn(); localStorage->m_PointMapper->SetScalarModeToUsePointFieldData(); localStorage->m_PointMapper->SetLookupTable(m_lut); //apply the properties after the slice was set localStorage->m_PointActor->GetProperty()->SetOpacity(0.999); // set color if (fbx->GetCurrentColorCoding() != NULL){ // localStorage->m_PointMapper->SelectColorArray(""); localStorage->m_PointMapper->SelectColorArray(fbx->GetCurrentColorCoding()); - MITK_INFO << "MapperFBX 2D: " << fbx->GetCurrentColorCoding(); + MITK_DEBUG << "MapperFBX 2D: " << fbx->GetCurrentColorCoding(); if(fbx->GetCurrentColorCoding() == fbx->COLORCODING_CUSTOM){ float temprgb[3]; this->GetDataNode()->GetColor( temprgb, NULL ); double trgb[3] = { (double) temprgb[0], (double) temprgb[1], (double) temprgb[2] }; localStorage->m_PointActor->GetProperty()->SetColor(trgb); } } localStorage->m_PointMapper->SetInput(fbx->GetFiberPolyData()); localStorage->m_PointActor->SetMapper(localStorage->m_PointMapper); localStorage->m_PointActor->GetProperty()->ShadingOn(); // Applying shading properties { mitk::ShaderRepository::GetGlobalShaderRepository()->ApplyProperties(this->GetDataNode(),localStorage->m_PointActor,renderer, localStorage->m_LastUpdateTime); } this->UpdateShaderParameter(renderer); // We have been modified => save this for next Update() localStorage->m_LastUpdateTime.Modified(); } vtkProp* mitk::FiberBundleXMapper2D::GetVtkProp(mitk::BaseRenderer *renderer) { //MITK_INFO << "FiberBundleMapper2D GetVtkProp(renderer)"; this->Update(renderer); return m_LSH.GetLocalStorage(renderer)->m_PointActor; } void mitk::FiberBundleXMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { //add shader to datano //####### load shader from file ######### QString applicationDir = QCoreApplication::applicationDirPath(); if (applicationDir.endsWith("bin")) applicationDir.append("/"); else if (applicationDir.endsWith("MacOS")) { //on osx, check if path for installer or MITK development is needed applicationDir.append("/"); QFile f( applicationDir+"FiberTrackingLUTBaryCoords.bin" ); if( !f.exists() ) // if file does not exist, then look in MITK development build directory applicationDir.append("../../../"); }else applicationDir.append("\\..\\"); mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch( applicationDir.toStdString().c_str(), false ); mitk::ShaderRepository::Pointer shaderRepository = mitk::ShaderRepository::GetGlobalShaderRepository(); shaderRepository->LoadShader(mitk::StandardFileLocations::GetInstance()->FindFile("mitkShaderFiberClipping.xml")); //#################################################################### node->SetProperty("shader",mitk::ShaderProperty::New("mitkShaderFiberClipping")); mitk::ShaderRepository::GetGlobalShaderRepository()->AddDefaultProperties(node,renderer,overwrite); //add other parameters to propertylist node->AddProperty( "Fiber2DSliceThickness", mitk::FloatProperty::New(2.0f), renderer, overwrite ); node->AddProperty( "Fiber2DfadeEFX", mitk::BoolProperty::New(true), renderer, overwrite ); Superclass::SetDefaultProperties(node, renderer, overwrite); } // following methods are essential, they actually call the GetVtkProp() method // which returns the desired actors void mitk::FiberBundleXMapper2D::MitkRenderOverlay(BaseRenderer* renderer) { // MITK_INFO << "FiberBundleMapper2D MitkRenderOVerlay(renderer)"; if ( this->IsVisible(renderer)==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) { this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); } } void mitk::FiberBundleXMapper2D::MitkRenderOpaqueGeometry(BaseRenderer* renderer) { // MITK_INFO << "FiberBundleMapper2D MitkRenderOpaqueGeometry(renderer)"; if ( this->IsVisible( renderer )==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); } void mitk::FiberBundleXMapper2D::MitkRenderTranslucentGeometry(BaseRenderer* renderer) { // MITK_INFO << "FiberBundleMapper2D MitkRenderTranslucentGeometry(renderer)"; if ( this->IsVisible(renderer)==false ) return; //TODO is it possible to have a visible BaseRenderer AND an invisible VtkRenderer??? if ( this->GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); } void mitk::FiberBundleXMapper2D::MitkRenderVolumetricGeometry(BaseRenderer* renderer) { // MITK_INFO << "FiberBundleMapper2D MitkRenderVolumentricGeometry(renderer)"; if(IsVisible(renderer)==false) return; //TODO is it possible to have a visible BaseRenderer AND an invisible VtkRenderer??? if ( GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderVolumetricGeometry(renderer->GetVtkRenderer()); } mitk::FiberBundleXMapper2D::FBXLocalStorage::FBXLocalStorage() { m_PointActor = vtkSmartPointer::New(); m_PointMapper = vtkSmartPointer::New(); } diff --git a/Modules/DiffusionImaging/Rendering/mitkOdfVtkMapper2D.h b/Modules/DiffusionImaging/Rendering/mitkOdfVtkMapper2D.h index 0356bc14c2..66af4586f2 100644 --- a/Modules/DiffusionImaging/Rendering/mitkOdfVtkMapper2D.h +++ b/Modules/DiffusionImaging/Rendering/mitkOdfVtkMapper2D.h @@ -1,148 +1,146 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2008-02-08 13:23:19 +0100 (Fr, 08 Feb 2008) $ Version: $Revision: 13561 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef ODFVTKMAPPER2D_H_HEADER_INCLUDED #define ODFVTKMAPPER2D_H_HEADER_INCLUDED #include "mitkVtkMapper2D.h" #include "vtkPropAssembly.h" #include "vtkAppendPolyData.h" #include "vtkActor.h" #include "vtkPolyDataMapper.h" #include "vtkPlane.h" #include "vtkCutter.h" #include "vtkClipPolyData.h" #include "vtkTransform.h" #include "vtkDataArrayTemplate.h" #include "vtkSmartPointer.h" #include "vtkOdfSource.h" #include "vtkThickPlane.h" //#include "mitkTrackingCameraController.h" namespace mitk { //##Documentation //## @brief Mapper for spherical object densitiy function representations //## template class OdfVtkMapper2D : public VtkMapper2D { struct OdfDisplayGeometry { vtkFloatingPointType vp[ 3 ], vnormal[ 3 ]; Vector3D normal; double d, d1, d2; mitk::Point3D M3D, L3D, O3D; - + vtkFloatingPointType vp_original[ 3 ], vnormal_original[ 3 ]; mitk::Vector2D size, origin; bool Equals(OdfDisplayGeometry other) { return other.vp_original[0] == vp[0] && other.vp_original[1] == vp[1] && other.vp_original[2] == vp[2] && other.vnormal_original[0] == vnormal[0] && other.vnormal_original[1] == vnormal[1] && other.vnormal_original[2] == vnormal[2] && other.size[0] == size[0] && other.size[1] == size[1] && other.origin[0] == origin[0] && other.origin[1] == origin[1]; } }; public: mitkClassMacro(OdfVtkMapper2D,VtkMapper2D); itkNewMacro(Self); virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); bool IsVisibleOdfs(mitk::BaseRenderer* renderer); virtual void MitkRenderOverlay(mitk::BaseRenderer* renderer); virtual void MitkRenderOpaqueGeometry(mitk::BaseRenderer* renderer); virtual void MitkRenderTranslucentGeometry(mitk::BaseRenderer* renderer); virtual void MitkRenderVolumetricGeometry(mitk::BaseRenderer* /*renderer*/){}; - + OdfDisplayGeometry MeasureDisplayedGeometry(mitk::BaseRenderer* renderer); - void AdaptOdfScalingToImageSpacing( int index ); - void SetRendererLightSources( mitk::BaseRenderer *renderer ); + double GetMinImageSpacing( int index ); void ApplyPropertySettings(); virtual void Slice(mitk::BaseRenderer* renderer, OdfDisplayGeometry dispGeo); virtual int GetIndex(mitk::BaseRenderer* renderer); static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false); virtual void GenerateData(); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); virtual bool IsLODEnabled( BaseRenderer * /*renderer*/ ) const { return true; } protected: OdfVtkMapper2D(); virtual ~OdfVtkMapper2D(); static void GlyphMethod(void *arg); bool IsPlaneRotated(mitk::BaseRenderer* renderer); private: std::vector m_PropAssemblies; std::vector m_OdfsPlanes; - std::vector m_OdfsActors; + std::vector m_OdfsActors; std::vector m_OdfsMappers; vtkPolyData* m_TemplateOdf; static vtkSmartPointer m_OdfTransform; - static vtkSmartPointer m_OdfVals; static vtkSmartPointer m_OdfSource; - static float m_Scaling; - static int m_Normalization; - static int m_ScaleBy; - static float m_IndexParam1; - static float m_IndexParam2; + static float m_Scaling; + static int m_Normalization; + static int m_ScaleBy; + static float m_IndexParam1; + static float m_IndexParam2; int m_ShowMaxNumber; std::vector m_Planes; std::vector m_Cutters; std::vector m_ThickPlanes1; std::vector m_Clippers1; - + std::vector m_ThickPlanes2; std::vector m_Clippers2; vtkImageData* m_VtkImage ; mitk::Image* GetInput(); OdfDisplayGeometry m_LastDisplayGeometry; }; } // namespace mitk #include "mitkOdfVtkMapper2D.txx" #endif /* ODFVTKMAPPER2D_H_HEADER_INCLUDED */ diff --git a/Modules/DiffusionImaging/Rendering/mitkOdfVtkMapper2D.txx b/Modules/DiffusionImaging/Rendering/mitkOdfVtkMapper2D.txx index ce854fcf7c..2eaea78a74 100644 --- a/Modules/DiffusionImaging/Rendering/mitkOdfVtkMapper2D.txx +++ b/Modules/DiffusionImaging/Rendering/mitkOdfVtkMapper2D.txx @@ -1,1015 +1,944 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2008-08-25 18:10:57 +0200 (Mo, 25 Aug 2008) $ Version: $Revision: 15062 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef __mitkOdfVtkMapper2D_txx__ #define __mitkOdfVtkMapper2D_txx__ #include "mitkOdfVtkMapper2D.h" #include "mitkDataNode.h" #include "mitkBaseRenderer.h" #include "mitkMatrixConvert.h" #include "mitkGeometry3D.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include "mitkProperties.h" #include "mitkTensorImage.h" #include "vtkSphereSource.h" #include "vtkPropCollection.h" #include "vtkMaskedGlyph3D.h" #include "vtkGlyph2D.h" #include "vtkGlyph3D.h" #include "vtkMaskedProgrammableGlyphFilter.h" #include "vtkImageData.h" #include "vtkLinearTransform.h" #include "vtkCamera.h" #include "vtkPointData.h" #include "vtkTransformPolyDataFilter.h" #include "vtkTransform.h" #include "vtkOdfSource.h" #include "vtkDoubleArray.h" #include "vtkLookupTable.h" #include "vtkProperty.h" #include "vtkPolyDataNormals.h" #include "vtkLight.h" #include "vtkLightCollection.h" #include "vtkMath.h" #include "vtkFloatArray.h" #include "vtkDelaunay2D.h" #include "vtkMapper.h" #include "vtkRenderer.h" #include "itkOrientationDistributionFunction.h" #include "itkFixedArray.h" #include #include "vtkOpenGLRenderer.h" #define _USE_MATH_DEFINES #include template vtkSmartPointer mitk::OdfVtkMapper2D::m_OdfTransform = vtkSmartPointer::New(); -template -vtkSmartPointer mitk::OdfVtkMapper2D::m_OdfVals = vtkSmartPointer::New(); - template vtkSmartPointer mitk::OdfVtkMapper2D::m_OdfSource = vtkSmartPointer::New(); template float mitk::OdfVtkMapper2D::m_Scaling; template int mitk::OdfVtkMapper2D::m_Normalization; template int mitk::OdfVtkMapper2D::m_ScaleBy; template float mitk::OdfVtkMapper2D::m_IndexParam1; template float mitk::OdfVtkMapper2D::m_IndexParam2; #define ODF_MAPPER_PI M_PI template mitk::OdfVtkMapper2D ::OdfVtkMapper2D() { m_PropAssemblies.push_back(vtkPropAssembly::New()); m_PropAssemblies.push_back(vtkPropAssembly::New()); m_PropAssemblies.push_back(vtkPropAssembly::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes[0]->AddInput(vtkPolyData::New()); m_OdfsPlanes[1]->AddInput(vtkPolyData::New()); m_OdfsPlanes[2]->AddInput(vtkPolyData::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors[0]->GetProperty()->SetInterpolationToGouraud(); m_OdfsActors[1]->GetProperty()->SetInterpolationToGouraud(); m_OdfsActors[2]->GetProperty()->SetInterpolationToGouraud(); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); vtkLookupTable *lut = vtkLookupTable::New(); m_OdfsMappers[0]->SetLookupTable(lut); m_OdfsMappers[1]->SetLookupTable(lut); m_OdfsMappers[2]->SetLookupTable(lut); m_OdfsActors[0]->SetMapper(m_OdfsMappers[0]); m_OdfsActors[1]->SetMapper(m_OdfsMappers[1]); m_OdfsActors[2]->SetMapper(m_OdfsMappers[2]); m_Planes.push_back(vtkPlane::New()); m_Planes.push_back(vtkPlane::New()); m_Planes.push_back(vtkPlane::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters[0]->SetCutFunction( m_Planes[0] ); m_Cutters[0]->GenerateValues( 1, 0, 1 ); m_Cutters[1]->SetCutFunction( m_Planes[1] ); m_Cutters[1]->GenerateValues( 1, 0, 1 ); m_Cutters[2]->SetCutFunction( m_Planes[2] ); m_Cutters[2]->GenerateValues( 1, 0, 1 ); // Windowing the cutted planes in direction 1 m_ThickPlanes1.push_back(vtkThickPlane::New()); m_ThickPlanes1.push_back(vtkThickPlane::New()); m_ThickPlanes1.push_back(vtkThickPlane::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1[0]->SetClipFunction( m_ThickPlanes1[0] ); m_Clippers1[1]->SetClipFunction( m_ThickPlanes1[1] ); m_Clippers1[2]->SetClipFunction( m_ThickPlanes1[2] ); // Windowing the cutted planes in direction 2 m_ThickPlanes2.push_back(vtkThickPlane::New()); m_ThickPlanes2.push_back(vtkThickPlane::New()); m_ThickPlanes2.push_back(vtkThickPlane::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2[0]->SetClipFunction( m_ThickPlanes2[0] ); m_Clippers2[1]->SetClipFunction( m_ThickPlanes2[1] ); m_Clippers2[2]->SetClipFunction( m_ThickPlanes2[2] ); - m_TemplateOdf = itk::OrientationDistributionFunction::GetBaseMesh(); - - m_OdfVals->Allocate(N); - m_OdfSource->SetTemplateOdf(m_TemplateOdf); - m_OdfSource->SetOdfVals(m_OdfVals); - m_ShowMaxNumber = 500; } template mitk::OdfVtkMapper2D ::~OdfVtkMapper2D() { m_PropAssemblies[0]->Delete(); m_PropAssemblies[1]->Delete(); m_PropAssemblies[2]->Delete(); m_OdfsPlanes[0]->Delete(); m_OdfsPlanes[1]->Delete(); m_OdfsPlanes[2]->Delete(); m_OdfsActors[0]->Delete(); m_OdfsActors[1]->Delete(); m_OdfsActors[2]->Delete(); m_OdfsMappers[0]->Delete(); m_OdfsMappers[1]->Delete(); m_OdfsMappers[2]->Delete(); m_Planes[0]->Delete(); m_Planes[1]->Delete(); m_Planes[2]->Delete(); m_Cutters[0]->Delete(); m_Cutters[1]->Delete(); m_Cutters[2]->Delete(); m_ThickPlanes1[0]->Delete(); m_ThickPlanes1[1]->Delete(); m_ThickPlanes1[2]->Delete(); m_ThickPlanes2[0]->Delete(); m_ThickPlanes2[1]->Delete(); m_ThickPlanes2[2]->Delete(); m_Clippers1[0]->Delete(); m_Clippers1[1]->Delete(); m_Clippers1[2]->Delete(); m_Clippers2[0]->Delete(); m_Clippers2[1]->Delete(); m_Clippers2[2]->Delete(); } template mitk::Image* mitk::OdfVtkMapper2D ::GetInput() { return static_cast ( m_DataNode->GetData() ); } template vtkProp* mitk::OdfVtkMapper2D ::GetVtkProp(mitk::BaseRenderer* renderer) { return m_PropAssemblies[GetIndex(renderer)]; } template int mitk::OdfVtkMapper2D ::GetIndex(mitk::BaseRenderer* renderer) { if(!strcmp(renderer->GetName(),"stdmulti.widget1")) return 0; if(!strcmp(renderer->GetName(),"stdmulti.widget2")) return 1; if(!strcmp(renderer->GetName(),"stdmulti.widget3")) return 2; return 0; } template void mitk::OdfVtkMapper2D ::GlyphMethod(void *arg) { vtkMaskedProgrammableGlyphFilter *pfilter=(vtkMaskedProgrammableGlyphFilter*)arg; double point[3]; double debugpoint[3]; pfilter->GetPoint(point); pfilter->GetPoint(debugpoint); itk::Point p(point); Vector3D spacing = pfilter->GetGeometry()->GetSpacing(); p[0] /= spacing[0]; p[1] /= spacing[1]; p[2] /= spacing[2]; mitk::Point3D p2; pfilter->GetGeometry()->IndexToWorld( p, p2 ); point[0] = p2[0]; point[1] = p2[1]; point[2] = p2[2]; vtkPointData* data = pfilter->GetPointData(); vtkDataArray* odfvals = data->GetArray("vector"); vtkIdType id = pfilter->GetPointId(); m_OdfTransform->Identity(); m_OdfTransform->Translate(point[0],point[1],point[2]); typedef itk::OrientationDistributionFunction OdfType; OdfType odf; if(odfvals->GetNumberOfComponents()==6) { float tensorelems[6] = { (float)odfvals->GetComponent(id,0), (float)odfvals->GetComponent(id,1), (float)odfvals->GetComponent(id,2), (float)odfvals->GetComponent(id,3), (float)odfvals->GetComponent(id,4), (float)odfvals->GetComponent(id,5), }; itk::DiffusionTensor3D tensor(tensorelems); odf.InitFromTensor(tensor); } else { for(int i=0; iGetComponent(id,i); } - switch(m_Normalization) - { - case ODFN_MINMAX: - odf = odf.MinMaxNormalize(); - break; - case ODFN_MAX: - odf = odf.MaxNormalize(); - break; - case ODFN_NONE: - // nothing - break; - case ODFN_GLOBAL_MAX: - // global max not implemented yet - break; - default: - odf = odf.MinMaxNormalize(); - } - switch(m_ScaleBy) { case ODFSB_NONE: - m_OdfSource->SetAdditionalScale(1.0); + m_OdfSource->SetScale(m_Scaling); break; case ODFSB_GFA: - m_OdfSource->SetAdditionalScale(odf.GetGeneralizedGFA(m_IndexParam1, m_IndexParam2)); + m_OdfSource->SetScale(m_Scaling*odf.GetGeneralizedGFA(m_IndexParam1, m_IndexParam2)); break; case ODFSB_PC: - m_OdfSource->SetAdditionalScale(odf.GetPrincipleCurvature(m_IndexParam1, m_IndexParam2, 0)); + m_OdfSource->SetScale(m_Scaling*odf.GetPrincipleCurvature(m_IndexParam1, m_IndexParam2, 0)); break; } - for(int i=0; iSetComponent(0,i,0.5*odf[i]*m_Scaling); - - + m_OdfSource->SetNormalization(m_Normalization); + m_OdfSource->SetOdf(odf); m_OdfSource->Modified(); } template typename mitk::OdfVtkMapper2D::OdfDisplayGeometry mitk::OdfVtkMapper2D ::MeasureDisplayedGeometry(mitk::BaseRenderer* renderer) { Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast( worldGeometry.GetPointer() ); // set up the cutter orientation according to the current geometry of // the renderers plane vtkFloatingPointType vp[ 3 ], vnormal[ 3 ]; Point3D point = worldPlaneGeometry->GetOrigin(); Vector3D normal = worldPlaneGeometry->GetNormal(); normal.Normalize(); vnl2vtk( point.Get_vnl_vector(), vp ); vnl2vtk( normal.Get_vnl_vector(), vnormal ); mitk::DisplayGeometry::Pointer dispGeometry = renderer->GetDisplayGeometry(); mitk::Vector2D size = dispGeometry->GetSizeInMM(); mitk::Vector2D origin = dispGeometry->GetOriginInMM(); // // |------O------| // | d2 | // L d1 M | // | | // |-------------| // mitk::Vector2D M; mitk::Vector2D L; mitk::Vector2D O; M[0] = origin[0] + size[0]/2; M[1] = origin[1] + size[1]/2; L[0] = origin[0]; L[1] = origin[1] + size[1]/2; O[0] = origin[0] + size[0]/2; O[1] = origin[1] + size[1]; mitk::Point2D point1; point1[0] = M[0]; point1[1] = M[1]; mitk::Point3D M3D; dispGeometry->Map(point1, M3D); point1[0] = L[0]; point1[1] = L[1]; mitk::Point3D L3D; dispGeometry->Map(point1, L3D); point1[0] = O[0]; point1[1] = O[1]; mitk::Point3D O3D; dispGeometry->Map(point1, O3D); double d1 = sqrt((M3D[0]-L3D[0])*(M3D[0]-L3D[0]) + (M3D[1]-L3D[1])*(M3D[1]-L3D[1]) + (M3D[2]-L3D[2])*(M3D[2]-L3D[2])); double d2 = sqrt((M3D[0]-O3D[0])*(M3D[0]-O3D[0]) + (M3D[1]-O3D[1])*(M3D[1]-O3D[1]) + (M3D[2]-O3D[2])*(M3D[2]-O3D[2])); double d = d1>d2 ? d1 : d2; d = d2; OdfDisplayGeometry retval; retval.vp[0] = vp[0]; retval.vp[1] = vp[1]; retval.vp[2] = vp[2]; retval.vnormal[0] = vnormal[0]; retval.vnormal[1] = vnormal[1]; retval.vnormal[2] = vnormal[2]; retval.normal[0] = normal[0]; retval.normal[1] = normal[1]; retval.normal[2] = normal[2]; retval.d = d; retval.d1 = d1; retval.d2 = d2; retval.M3D[0] = M3D[0]; retval.M3D[1] = M3D[1]; retval.M3D[2] = M3D[2]; retval.L3D[0] = L3D[0]; retval.L3D[1] = L3D[1]; retval.L3D[2] = L3D[2]; retval.O3D[0] = O3D[0]; retval.O3D[1] = O3D[1]; retval.O3D[2] = O3D[2]; retval.vp_original[0] = vp[0]; retval.vp_original[1] = vp[1]; retval.vp_original[2] = vp[2]; retval.vnormal_original[0] = vnormal[0]; retval.vnormal_original[1] = vnormal[1]; retval.vnormal_original[2] = vnormal[2]; retval.size[0] = size[0]; retval.size[1] = size[1]; retval.origin[0] = origin[0]; retval.origin[1] = origin[1]; return retval; } template void mitk::OdfVtkMapper2D ::Slice(mitk::BaseRenderer* renderer, OdfDisplayGeometry dispGeo) { vtkLinearTransform * vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); int index = GetIndex(renderer); vtkTransform* inversetransform = vtkTransform::New(); inversetransform->Identity(); inversetransform->Concatenate(vtktransform->GetLinearInverse()); double myscale[3]; ((vtkTransform*)vtktransform)->GetScale(myscale); inversetransform->PostMultiply(); inversetransform->Scale(1*myscale[0],1*myscale[1],1*myscale[2]); inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp ); inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal ); // vtk works in axis align coords // thus the normal also must be axis align, since // we do not allow arbitrary cutting through volume // // vnormal should already be axis align, but in order // to get rid of precision effects, we set the two smaller // components to zero here int dims[3]; m_VtkImage->GetDimensions(dims); double spac[3]; m_VtkImage->GetSpacing(spac); if(fabs(dispGeo.vnormal[0]) > fabs(dispGeo.vnormal[1]) && fabs(dispGeo.vnormal[0]) > fabs(dispGeo.vnormal[2]) ) { if(fabs(dispGeo.vp[0]/spac[0]) < 0.4) dispGeo.vp[0] = 0.4*spac[0]; if(fabs(dispGeo.vp[0]/spac[0]) > (dims[0]-1)-0.4) dispGeo.vp[0] = ((dims[0]-1)-0.4)*spac[0]; dispGeo.vnormal[1] = 0; dispGeo.vnormal[2] = 0; } if(fabs(dispGeo.vnormal[1]) > fabs(dispGeo.vnormal[0]) && fabs(dispGeo.vnormal[1]) > fabs(dispGeo.vnormal[2]) ) { if(fabs(dispGeo.vp[1]/spac[1]) < 0.4) dispGeo.vp[1] = 0.4*spac[1]; if(fabs(dispGeo.vp[1]/spac[1]) > (dims[1]-1)-0.4) dispGeo.vp[1] = ((dims[1]-1)-0.4)*spac[1]; dispGeo.vnormal[0] = 0; dispGeo.vnormal[2] = 0; } if(fabs(dispGeo.vnormal[2]) > fabs(dispGeo.vnormal[1]) && fabs(dispGeo.vnormal[2]) > fabs(dispGeo.vnormal[0]) ) { if(fabs(dispGeo.vp[2]/spac[2]) < 0.4) dispGeo.vp[2] = 0.4*spac[2]; if(fabs(dispGeo.vp[2]/spac[2]) > (dims[2]-1)-0.4) dispGeo.vp[2] = ((dims[2]-1)-0.4)*spac[2]; dispGeo.vnormal[0] = 0; dispGeo.vnormal[1] = 0; } m_Planes[index]->SetTransform( (vtkAbstractTransform*)NULL ); m_Planes[index]->SetOrigin( dispGeo.vp ); m_Planes[index]->SetNormal( dispGeo.vnormal ); vtkPoints* points = NULL; vtkPoints* tmppoints = NULL; vtkPolyData* polydata = NULL; vtkFloatArray* pointdata = NULL; vtkDelaunay2D *delaunay = NULL; vtkPolyData* cuttedPlane = NULL; // the cutter only works if we do not have a 2D-image // or if we have a 2D-image and want to see the whole image. // // for side views of 2D-images, we need some special treatment if(!( (dims[0] == 1 && dispGeo.vnormal[0] != 0) || (dims[1] == 1 && dispGeo.vnormal[1] != 0) || (dims[2] == 1 && dispGeo.vnormal[2] != 0) )) { m_Cutters[index]->SetCutFunction( m_Planes[index] ); m_Cutters[index]->SetInput( m_VtkImage ); m_Cutters[index]->Update(); cuttedPlane = m_Cutters[index]->GetOutput(); } else { // cutting of a 2D-Volume does not work, // so we have to build up our own polydata object cuttedPlane = vtkPolyData::New(); points = vtkPoints::New(); points->SetNumberOfPoints(m_VtkImage->GetNumberOfPoints()); for(int i=0; iGetNumberOfPoints(); i++) { points->SetPoint(i, m_VtkImage->GetPoint(i)); } cuttedPlane->SetPoints(points); pointdata = vtkFloatArray::New(); int comps = m_VtkImage->GetPointData()->GetScalars()->GetNumberOfComponents(); pointdata->SetNumberOfComponents(comps); int tuples = m_VtkImage->GetPointData()->GetScalars()->GetNumberOfTuples(); pointdata->SetNumberOfTuples(tuples); for(int i=0; iSetTuple(i,m_VtkImage->GetPointData()->GetScalars()->GetTuple(i)); pointdata->SetName( "vector" ); cuttedPlane->GetPointData()->AddArray(pointdata); int nZero1, nZero2; if(dims[0]==1) { nZero1 = 1; nZero2 = 2; } else if(dims[1]==1) { nZero1 = 0; nZero2 = 2; } else { nZero1 = 0; nZero2 = 1; } tmppoints = vtkPoints::New(); for(int j=0; jGetNumberOfPoints(); j++){ double pt[3]; m_VtkImage->GetPoint(j,pt); tmppoints->InsertNextPoint(pt[nZero1],pt[nZero2],0); } polydata = vtkPolyData::New(); polydata->SetPoints( tmppoints ); delaunay = vtkDelaunay2D::New(); delaunay->SetInput( polydata ); delaunay->Update(); vtkCellArray* polys = delaunay->GetOutput()->GetPolys(); cuttedPlane->SetPolys(polys); } if(cuttedPlane->GetNumberOfPoints()) { // WINDOWING HERE inversetransform = vtkTransform::New(); inversetransform->Identity(); inversetransform->Concatenate(vtktransform->GetLinearInverse()); double myscale[3]; ((vtkTransform*)vtktransform)->GetScale(myscale); inversetransform->PostMultiply(); inversetransform->Scale(1*myscale[0],1*myscale[1],1*myscale[2]); dispGeo.vnormal[0] = dispGeo.M3D[0]-dispGeo.O3D[0]; dispGeo.vnormal[1] = dispGeo.M3D[1]-dispGeo.O3D[1]; dispGeo.vnormal[2] = dispGeo.M3D[2]-dispGeo.O3D[2]; vtkMath::Normalize(dispGeo.vnormal); dispGeo.vp[0] = dispGeo.M3D[0]; dispGeo.vp[1] = dispGeo.M3D[1]; dispGeo.vp[2] = dispGeo.M3D[2]; inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp ); inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal ); m_ThickPlanes1[index]->count = 0; m_ThickPlanes1[index]->SetTransform((vtkAbstractTransform*)NULL ); m_ThickPlanes1[index]->SetPose( dispGeo.vnormal, dispGeo.vp ); m_ThickPlanes1[index]->SetThickness(dispGeo.d2); m_Clippers1[index]->SetClipFunction( m_ThickPlanes1[index] ); m_Clippers1[index]->SetInput( cuttedPlane ); m_Clippers1[index]->SetInsideOut(1); m_Clippers1[index]->Update(); dispGeo.vnormal[0] = dispGeo.M3D[0]-dispGeo.L3D[0]; dispGeo.vnormal[1] = dispGeo.M3D[1]-dispGeo.L3D[1]; dispGeo.vnormal[2] = dispGeo.M3D[2]-dispGeo.L3D[2]; vtkMath::Normalize(dispGeo.vnormal); dispGeo.vp[0] = dispGeo.M3D[0]; dispGeo.vp[1] = dispGeo.M3D[1]; dispGeo.vp[2] = dispGeo.M3D[2]; inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp ); inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal ); m_ThickPlanes2[index]->count = 0; m_ThickPlanes2[index]->SetTransform((vtkAbstractTransform*)NULL ); m_ThickPlanes2[index]->SetPose( dispGeo.vnormal, dispGeo.vp ); m_ThickPlanes2[index]->SetThickness(dispGeo.d1); m_Clippers2[index]->SetClipFunction( m_ThickPlanes2[index] ); m_Clippers2[index]->SetInput( m_Clippers1[index]->GetOutput() ); m_Clippers2[index]->SetInsideOut(1); m_Clippers2[index]->Update(); cuttedPlane = m_Clippers2[index]->GetOutput (); if(cuttedPlane->GetNumberOfPoints()) { m_OdfsPlanes[index]->RemoveAllInputs(); vtkPolyDataNormals* normals = vtkPolyDataNormals::New(); normals->SetInputConnection( m_OdfSource->GetOutputPort() ); normals->SplittingOff(); normals->ConsistencyOff(); normals->AutoOrientNormalsOff(); normals->ComputePointNormalsOn(); normals->ComputeCellNormalsOff(); normals->FlipNormalsOff(); normals->NonManifoldTraversalOff(); vtkTransformPolyDataFilter* trans = vtkTransformPolyDataFilter::New(); trans->SetInputConnection( normals->GetOutputPort() ); trans->SetTransform(m_OdfTransform); vtkMaskedProgrammableGlyphFilter* glyphGenerator = vtkMaskedProgrammableGlyphFilter::New(); glyphGenerator->SetMaximumNumberOfPoints(m_ShowMaxNumber); glyphGenerator->SetRandomMode(1); glyphGenerator->SetUseMaskPoints(1); glyphGenerator->SetSource( trans->GetOutput() ); glyphGenerator->SetInput(cuttedPlane); glyphGenerator->SetColorModeToColorBySource(); glyphGenerator->SetInputArrayToProcess(0,0,0, vtkDataObject::FIELD_ASSOCIATION_POINTS , "vector"); glyphGenerator->SetGeometry(this->GetDataNode()->GetData()->GetGeometry()); glyphGenerator->SetGlyphMethod(&(GlyphMethod),(void *)glyphGenerator); try { glyphGenerator->Update(); } catch( itk::ExceptionObject& err ) { std::cout << err << std::endl; } + m_OdfsPlanes[index]->AddInput(glyphGenerator->GetOutput()); trans->Delete(); glyphGenerator->Delete(); normals->Delete(); m_OdfsPlanes[index]->Update(); } } m_PropAssemblies[index]->VisibilityOn(); if(m_PropAssemblies[index]->GetParts()->IsItemPresent(m_OdfsActors[index])) m_PropAssemblies[index]->RemovePart(m_OdfsActors[index]); m_OdfsMappers[index]->SetInput(m_OdfsPlanes[index]->GetOutput()); m_PropAssemblies[index]->AddPart(m_OdfsActors[index]); if(inversetransform) inversetransform->Delete(); if(points) points->Delete(); if(pointdata) pointdata->Delete(); if(tmppoints) tmppoints->Delete(); if(polydata) polydata->Delete(); if(delaunay) delaunay->Delete(); } template bool mitk::OdfVtkMapper2D ::IsVisibleOdfs(mitk::BaseRenderer* renderer) { if(this->IsPlaneRotated(renderer)) return false; bool retval = false; switch(GetIndex(renderer)) { case 0: retval = this->IsVisible(renderer, "VisibleOdfs_T"); break; case 1: retval = this->IsVisible(renderer, "VisibleOdfs_S"); break; case 2: retval = this->IsVisible(renderer, "VisibleOdfs_C"); break; } return retval; } template void mitk::OdfVtkMapper2D ::MitkRenderOverlay(mitk::BaseRenderer* renderer) { if ( this->IsVisibleOdfs(renderer)==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) { this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); } } template void mitk::OdfVtkMapper2D ::MitkRenderOpaqueGeometry(mitk::BaseRenderer* renderer) { if ( this->IsVisibleOdfs( renderer )==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) { // adapt cam pos OdfDisplayGeometry dispGeo = MeasureDisplayedGeometry( renderer); this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); } } template void mitk::OdfVtkMapper2D ::MitkRenderTranslucentGeometry(mitk::BaseRenderer* renderer) { if ( this->IsVisibleOdfs(renderer)==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); } template void mitk::OdfVtkMapper2D ::GenerateData() { mitk::Image::Pointer input = const_cast( this->GetInput() ); if ( input.IsNull() ) return ; std::string classname("TensorImage"); if(classname.compare(input->GetNameOfClass())==0) { m_VtkImage = dynamic_cast( this->GetInput() )->GetNonRgbVtkImageData(); } std::string qclassname("QBallImage"); if(qclassname.compare(input->GetNameOfClass())==0) { m_VtkImage = dynamic_cast( this->GetInput() )->GetNonRgbVtkImageData(); } if( m_VtkImage ) { // make sure, that we have point data with more than 1 component (as vectors) vtkPointData* pointData = m_VtkImage->GetPointData(); if ( pointData == NULL ) { itkWarningMacro( << "m_VtkImage->GetPointData() returns NULL!" ); return ; } if ( pointData->GetNumberOfArrays() == 0 ) { itkWarningMacro( << "m_VtkImage->GetPointData()->GetNumberOfArrays() is 0!" ); return ; } else if ( pointData->GetArray(0)->GetNumberOfComponents() != N && pointData->GetArray(0)->GetNumberOfComponents() != 6 /*for tensor visualization*/) { itkWarningMacro( << "number of components != number of directions in ODF!" ); return; } else if ( pointData->GetArrayName( 0 ) == NULL ) { m_VtkImage->GetPointData()->GetArray(0)->SetName("vector"); } } else { itkWarningMacro( << "m_VtkImage is NULL!" ); return ; } } template -void mitk::OdfVtkMapper2D -::AdaptOdfScalingToImageSpacing( int index ) +double mitk::OdfVtkMapper2D::GetMinImageSpacing( int index ) { // Spacing adapted scaling double spacing[3]; m_VtkImage->GetSpacing(spacing); double min; if(index==0) { min = spacing[0]; min = min > spacing[1] ? spacing[1] : min; } if(index==1) { min = spacing[1]; min = min > spacing[2] ? spacing[2] : min; } if(index==2) { min = spacing[0]; min = min > spacing[2] ? spacing[2] : min; } - m_OdfSource->SetScale(min); -} - -template -void mitk::OdfVtkMapper2D -::SetRendererLightSources( mitk::BaseRenderer *renderer ) -{ - // Light Sources - vtkCollectionSimpleIterator sit; - vtkLight* light; - for(renderer->GetVtkRenderer()->GetLights()->InitTraversal(sit); - (light = renderer->GetVtkRenderer()->GetLights()->GetNextLight(sit)); ) - { - renderer->GetVtkRenderer()->RemoveLight(light); - } - - light = vtkLight::New(); - light->SetFocalPoint(0,0,0); - light->SetLightTypeToSceneLight(); - light->SwitchOn(); - light->SetIntensity(1.0); - light->PositionalOff(); - - itk::Point p; - int index = GetIndex(renderer); - if(index==0) - { - p[0] = 0; p[1] = 0; p[2] = 10000; - } - if(index==1) - { - p[0] = 0; p[1] = 10000; p[2] = 0; - } - if(index==2) - { - p[0] = 10000; p[1] = 0; p[2] = 0; - } - - mitk::Point3D p2; - this->GetInput()->GetGeometry()->IndexToWorld(p,p2); - light->SetPosition(p2[0],p2[1],p2[2]); - renderer->GetVtkRenderer()->AddLight(light); + return min; } template void mitk::OdfVtkMapper2D ::ApplyPropertySettings() { this->GetDataNode()->GetFloatProperty( "Scaling", m_Scaling ); this->GetDataNode()->GetIntProperty( "ShowMaxNumber", m_ShowMaxNumber ); OdfNormalizationMethodProperty* nmp = dynamic_cast ( this->GetDataNode()->GetProperty( "Normalization" )); if(nmp) { m_Normalization = nmp->GetNormalization(); } OdfScaleByProperty* sbp = dynamic_cast ( this->GetDataNode()->GetProperty( "ScaleBy" )); if(sbp) { m_ScaleBy = sbp->GetScaleBy(); } this->GetDataNode()->GetFloatProperty( "IndexParam1", m_IndexParam1); this->GetDataNode()->GetFloatProperty( "IndexParam2", m_IndexParam2); } template bool mitk::OdfVtkMapper2D ::IsPlaneRotated(mitk::BaseRenderer* renderer) { Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast( worldGeometry.GetPointer() ); vtkFloatingPointType vnormal[ 3 ]; Vector3D normal = worldPlaneGeometry->GetNormal(); normal.Normalize(); vnl2vtk( normal.Get_vnl_vector(), vnormal ); vtkLinearTransform * vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); vtkTransform* inversetransform = vtkTransform::New(); inversetransform->Identity(); inversetransform->Concatenate(vtktransform->GetLinearInverse()); double* n = inversetransform->TransformNormal(vnormal); int nonZeros = 0; for (int j=0; j<3; j++) { - if (fabs(n[j])>1e-7){ + if (fabs(n[j])>mitk::eps){ nonZeros++; } } if(nonZeros>1) return true; return false; } template void mitk::OdfVtkMapper2D ::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { if(!m_VtkImage) { itkWarningMacro( << "m_VtkImage is NULL!" ); return ; } int index = GetIndex(renderer); if(IsVisibleOdfs(renderer)==false) { m_OdfsActors[0]->VisibilityOff(); m_OdfsActors[1]->VisibilityOff(); m_OdfsActors[2]->VisibilityOff(); return; } else { m_OdfsActors[0]->VisibilityOn(); m_OdfsActors[1]->VisibilityOn(); m_OdfsActors[2]->VisibilityOn(); OdfDisplayGeometry dispGeo = MeasureDisplayedGeometry( renderer); - AdaptOdfScalingToImageSpacing(index); - //SetRendererLightSources(renderer); + m_OdfSource->SetAdditionalScale(GetMinImageSpacing(index)); ApplyPropertySettings(); Slice(renderer, dispGeo); m_LastDisplayGeometry = dispGeo; } // Get the TimeSlicedGeometry of the input object mitk::Image::Pointer input = const_cast(this->GetInput()); const TimeSlicedGeometry *inputTimeGeometry = input->GetTimeSlicedGeometry(); if (( inputTimeGeometry == NULL ) || ( inputTimeGeometry->GetTimeSteps() == 0 )) { m_PropAssemblies[0]->VisibilityOff(); m_PropAssemblies[1]->VisibilityOff(); m_PropAssemblies[2]->VisibilityOff(); return; } if( inputTimeGeometry->IsValidTime( this->GetTimestep() ) == false ) { m_PropAssemblies[0]->VisibilityOff(); m_PropAssemblies[1]->VisibilityOff(); m_PropAssemblies[2]->VisibilityOff(); return; } } template void mitk::OdfVtkMapper2D ::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* /*renderer*/, bool /*overwrite*/) { node->SetProperty( "ShowMaxNumber", mitk::IntProperty::New( 150 ) ); node->SetProperty( "Scaling", mitk::FloatProperty::New( 1.0 ) ); node->SetProperty( "Normalization", mitk::OdfNormalizationMethodProperty::New()); node->SetProperty( "ScaleBy", mitk::OdfScaleByProperty::New()); node->SetProperty( "IndexParam1", mitk::FloatProperty::New(2)); node->SetProperty( "IndexParam2", mitk::FloatProperty::New(1)); node->SetProperty( "visible", mitk::BoolProperty::New( true ) ); node->SetProperty( "VisibleOdfs_T", mitk::BoolProperty::New( false ) ); node->SetProperty( "VisibleOdfs_C", mitk::BoolProperty::New( false ) ); node->SetProperty( "VisibleOdfs_S", mitk::BoolProperty::New( false ) ); node->SetProperty ("layer", mitk::IntProperty::New(100)); node->SetProperty( "DoRefresh", mitk::BoolProperty::New( true ) ); } #endif // __mitkOdfVtkMapper2D_txx__ diff --git a/Modules/DiffusionImaging/Rendering/mitkPlanarCircleMapper3D.cpp b/Modules/DiffusionImaging/Rendering/mitkPlanarCircleMapper3D.cpp index bd84e82cbc..657cfbfe18 100644 --- a/Modules/DiffusionImaging/Rendering/mitkPlanarCircleMapper3D.cpp +++ b/Modules/DiffusionImaging/Rendering/mitkPlanarCircleMapper3D.cpp @@ -1,150 +1,151 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-05-12 19:56:03 +0200 (Di, 12 Mai 2009) $ Version: $Revision: 17179 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkPlanarCircleMapper3D.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include mitk::PlanarCircleMapper3D::PlanarCircleMapper3D() : m_vtkCircleList(NULL), m_VtkCircleDataMapperGL(NULL) { m_CircleAssembly = vtkPropAssembly::New(); m_CircleActor = vtkOpenGLActor::New(); m_polygonSource = vtkRegularPolygonSource::New(); } mitk::PlanarCircleMapper3D::~PlanarCircleMapper3D() { } const mitk::PlanarCircle* mitk::PlanarCircleMapper3D::GetInput() { return static_cast ( GetData() ); } /* This method is called once the mapper gets new input, for UI rotation or changes in colorcoding this method is NOT called */ void mitk::PlanarCircleMapper3D::GenerateData() { mitk::PlanarCircle* PFCircle = dynamic_cast< mitk::PlanarCircle* > (this->GetData()); try { mitk::Point3D V1 = PFCircle->GetWorldControlPoint(0); //centerPoint mitk::Point3D V2 = PFCircle->GetWorldControlPoint(1); //radiusPoint const mitk::Geometry2D* pfgeometry = PFCircle->GetGeometry2D(); const mitk::PlaneGeometry* planeGeo = dynamic_cast (pfgeometry); mitk::Vector3D N = planeGeo->GetNormal(); double circleRadius = V1.EuclideanDistanceTo(V2); m_polygonSource->SetNormal((double)N[0],(double)N[1],(double)N[2]); m_polygonSource->SetNumberOfSides(50); m_polygonSource->SetRadius(circleRadius); m_polygonSource->SetCenter(V1[0],V1[1],V1[2]); m_polygonSource->Update(); // Visualize m_VtkCircleDataMapperGL = vtkOpenGLPolyDataMapper::New(); m_VtkCircleDataMapperGL->SetInputConnection(m_polygonSource->GetOutputPort()); m_CircleActor = vtkOpenGLActor::New(); m_CircleActor->SetMapper(m_VtkCircleDataMapperGL); - m_CircleActor->GetProperty()->SetOpacity(0.8); m_CircleAssembly->AddPart(m_CircleActor); } catch(...) { } } void mitk::PlanarCircleMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { try { mitk::PlanarCircle* PFCircle = dynamic_cast< mitk::PlanarCircle* > (this->GetData()); mitk::Point3D V1 = PFCircle->GetWorldControlPoint(0); //centerPoint mitk::Point3D V2 = PFCircle->GetWorldControlPoint(1); //radiusPoint double circleRadius = V1.EuclideanDistanceTo(V2); m_polygonSource->SetCenter((double)V1[0],(double)V1[1],(double)V1[2]); m_polygonSource->SetRadius(circleRadius); m_polygonSource->Update(); float polyOpaq; this->GetDataNode()->GetOpacity(polyOpaq, NULL); + if (polyOpaq>=1) // hack to avoid wrong color if opacity==1 + polyOpaq = 0.999; m_CircleActor->GetProperty()->SetOpacity((double) polyOpaq); float temprgb[3]; this->GetDataNode()->GetColor( temprgb, NULL ); double trgb[3] = { (double) temprgb[0], (double) temprgb[1], (double) temprgb[2] }; m_CircleActor->GetProperty()->SetColor(trgb); } catch (...) { } } void mitk::PlanarCircleMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { Superclass::SetDefaultProperties(node, renderer, overwrite); } vtkProp* mitk::PlanarCircleMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { return m_CircleAssembly; } void mitk::PlanarCircleMapper3D::ApplyProperties(mitk::BaseRenderer* renderer) { } void mitk::PlanarCircleMapper3D::UpdateVtkObjects() { } void mitk::PlanarCircleMapper3D::SetVtkMapperImmediateModeRendering(vtkMapper *) { } diff --git a/Modules/DiffusionImaging/Rendering/vtkOdfSource.cxx b/Modules/DiffusionImaging/Rendering/vtkOdfSource.cxx index f206a13c01..8c96d3a592 100644 --- a/Modules/DiffusionImaging/Rendering/vtkOdfSource.cxx +++ b/Modules/DiffusionImaging/Rendering/vtkOdfSource.cxx @@ -1,119 +1,119 @@ #include "vtkOdfSource.h" #include "vtkCellArray.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkPoints.h" #include "vtkStreamingDemandDrivenPipeline.h" #include "vtkObjectFactory.h" #include "vtkDoubleArray.h" #include "vtkCellData.h" #include vtkCxxRevisionMacro(vtkOdfSource, "$Revision: 1.1 $"); vtkStandardNewMacro(vtkOdfSource); vtkOdfSource::vtkOdfSource() { + Scale = 1; this->SetNumberOfInputPorts(0); } //---------------------------------------------------------------------------- int vtkOdfSource::RequestData( vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) { + vtkPolyData* TemplateOdf = OdfType::GetBaseMesh(); // get the info object vtkInformation *outInfo = outputVector->GetInformationObject(0); // get the ouptut vtkPolyData *output = vtkPolyData::SafeDownCast( outInfo->Get(vtkDataObject::DATA_OBJECT())); - vtkPoints *newPoints; - newPoints = vtkPoints::New(); - int numPoints = TemplateOdf->GetPoints()->GetNumberOfPoints(); - newPoints->Allocate(numPoints); - for(int j=0; jGetPoints()->GetPoint(j,p); - if(OdfVals->GetNumberOfComponents()) - { - double val = OdfVals->GetComponent(0,j); - //if(val >= 0.2) - // val = 0.4; - p[0] *= val*Scale*AdditionalScale; - p[1] *= val*Scale*AdditionalScale; - p[2] *= val*Scale*AdditionalScale; - //double tmp = p[0]; - //p[0] = p[1] * val; - //p[1] = tmp * -val; - //p[2] *= val; - } - newPoints->InsertNextPoint(p); + OdfType colorOdf; + switch(Normalization) + { + case mitk::ODFN_MINMAX: + Odf = Odf.MinMaxNormalize(); + colorOdf = Odf; + break; + case mitk::ODFN_MAX: + Odf = Odf.MaxNormalize(); + colorOdf = Odf; + break; + case mitk::ODFN_NONE: + colorOdf = Odf.MaxNormalize(); + break; + default: + Odf = Odf.MinMaxNormalize(); + colorOdf = Odf; } - output->SetPoints(newPoints); - newPoints->Delete(); + + vtkIdType cellId = 0; + vtkIdType npts; vtkIdType *pts; + vtkPoints *newPoints; vtkCellArray* polys = TemplateOdf->GetPolys(); output->SetPolys(polys); - - //vtkCellArray *newPolys; - //newPolys = vtkCellArray::New(); - //int numCells = polys->GetNumberOfCells(); - //newPolys->Allocate(numCells); - //polys->InitTraversal(); - //vtkIdType npts; vtkIdType *pts; - //while(polys->GetNextCell(npts,pts)) - //{ - // newPolys->InsertNextCell(npts, pts); - //} - //output->SetPolys(newPolys); - //newPolys->Delete(); - vtkDoubleArray* colors = vtkDoubleArray::New(); int numCells = polys->GetNumberOfCells(); colors->Allocate(numCells); polys->InitTraversal(); - vtkIdType cellId = 0; - vtkIdType npts; vtkIdType *pts; + newPoints = vtkPoints::New(); + int numPoints = TemplateOdf->GetPoints()->GetNumberOfPoints(); + newPoints->Allocate(numPoints); + while(polys->GetNextCell(npts,pts)) { double val = 0; for(int i=0; iGetComponent(0,pointId); + val += colorOdf.GetElement(pointId); } val /= npts; - colors->SetComponent(0,cellId++,-(val-0.5/*level*/)*(1/0.5/*window*/)); + colors->SetComponent(0,cellId++, 1-val); } + + for(int j=0; jGetPoints()->GetPoint(j,p); + double val = Odf.GetElement(j); + p[0] *= val*Scale*AdditionalScale*0.5; + p[1] *= val*Scale*AdditionalScale*0.5; + p[2] *= val*Scale*AdditionalScale*0.5; + newPoints->InsertNextPoint(p); + } + output->SetPoints(newPoints); output->GetCellData()->SetScalars(colors); colors->Delete(); + newPoints->Delete(); return 1; } //---------------------------------------------------------------------------- void vtkOdfSource::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } //---------------------------------------------------------------------------- int vtkOdfSource::RequestInformation( vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) { // get the info object vtkInformation *outInfo = outputVector->GetInformationObject(0); outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), -1); outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_BOUNDING_BOX(),1,1,1,1,1,1); return 1; } diff --git a/Modules/DiffusionImaging/Rendering/vtkOdfSource.h b/Modules/DiffusionImaging/Rendering/vtkOdfSource.h index f56e338520..e53013561f 100644 --- a/Modules/DiffusionImaging/Rendering/vtkOdfSource.h +++ b/Modules/DiffusionImaging/Rendering/vtkOdfSource.h @@ -1,67 +1,70 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-07-14 19:11:20 +0200 (Tue, 14 Jul 2009) $ Version: $Revision: 18127 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef __vtkOdfSource_h #define __vtkOdfSource_h #include "MitkDiffusionImagingExports.h" #include "vtkPolyDataAlgorithm.h" #include "mitkCommon.h" +#include +#include +#include class MitkDiffusionImaging_EXPORT vtkOdfSource : public vtkPolyDataAlgorithm { public: vtkTypeRevisionMacro(vtkOdfSource,vtkPolyDataAlgorithm); void PrintSelf(ostream& os, vtkIndent indent); + typedef itk::OrientationDistributionFunction OdfType; // Description: // Construct sphere with radius=0.5 and default resolution 8 in both Phi // and Theta directions. Theta ranges from (0,360) and phi (0,180) degrees. static vtkOdfSource *New(); - vtkSetMacro(TemplateOdf,vtkPolyData*); - vtkGetMacro(TemplateOdf,vtkPolyData*); - - vtkSetMacro(OdfVals,vtkDoubleArray*); - vtkGetMacro(OdfVals,vtkDoubleArray*); - vtkSetMacro(Scale,double); vtkGetMacro(Scale,double); vtkSetMacro(AdditionalScale,double); vtkGetMacro(AdditionalScale,double); + vtkSetMacro(Normalization,int); + vtkGetMacro(Normalization,int); + + vtkSetMacro(Odf,OdfType); + vtkGetMacro(Odf,OdfType); + protected: vtkOdfSource(); ~vtkOdfSource() {} int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); - vtkPolyData* TemplateOdf; - vtkDoubleArray* OdfVals; - - double Scale; - double AdditionalScale; + OdfType Odf; + double Scale; + double AdditionalScale; + int Normalization; private: vtkOdfSource(const vtkOdfSource&); // Not implemented. void operator=(const vtkOdfSource&); // Not implemented. }; #endif //__vtkOdfSource_h diff --git a/Modules/DiffusionImaging/files.cmake b/Modules/DiffusionImaging/files.cmake index a637ddc986..59d5212562 100644 --- a/Modules/DiffusionImaging/files.cmake +++ b/Modules/DiffusionImaging/files.cmake @@ -1,215 +1,216 @@ set(CPP_FILES # DicomImport DicomImport/mitkDicomDiffusionImageReader.cpp DicomImport/mitkGroupDiffusionHeadersFilter.cpp DicomImport/mitkDicomDiffusionImageHeaderReader.cpp DicomImport/mitkGEDicomDiffusionImageHeaderReader.cpp DicomImport/mitkPhilipsDicomDiffusionImageHeaderReader.cpp DicomImport/mitkSiemensDicomDiffusionImageHeaderReader.cpp DicomImport/mitkSiemensMosaicDicomDiffusionImageHeaderReader.cpp # DataStructures IODataStructures/mitkDiffusionImagingObjectFactory.cpp # DataStructures -> DWI IODataStructures/DiffusionWeightedImages/mitkDiffusionImageHeaderInformation.cpp IODataStructures/DiffusionWeightedImages/mitkDiffusionImageSource.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageReader.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageWriter.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageIOFactory.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageWriterFactory.cpp IODataStructures/DiffusionWeightedImages/mitkDiffusionImageSerializer.cpp # DataStructures -> QBall IODataStructures/QBallImages/mitkQBallImageSource.cpp IODataStructures/QBallImages/mitkNrrdQBallImageReader.cpp IODataStructures/QBallImages/mitkNrrdQBallImageWriter.cpp IODataStructures/QBallImages/mitkNrrdQBallImageIOFactory.cpp IODataStructures/QBallImages/mitkNrrdQBallImageWriterFactory.cpp IODataStructures/QBallImages/mitkQBallImage.cpp IODataStructures/QBallImages/mitkQBallImageSerializer.cpp # DataStructures -> Tensor IODataStructures/TensorImages/mitkTensorImageSource.cpp IODataStructures/TensorImages/mitkNrrdTensorImageReader.cpp IODataStructures/TensorImages/mitkNrrdTensorImageWriter.cpp IODataStructures/TensorImages/mitkNrrdTensorImageIOFactory.cpp IODataStructures/TensorImages/mitkNrrdTensorImageWriterFactory.cpp IODataStructures/TensorImages/mitkTensorImage.cpp IODataStructures/TensorImages/mitkTensorImageSerializer.cpp # DataStructures -> FiberBundleX IODataStructures/FiberBundleX/mitkFiberBundleX.cpp IODataStructures/FiberBundleX/mitkFiberBundleXWriter.cpp IODataStructures/FiberBundleX/mitkFiberBundleXReader.cpp IODataStructures/FiberBundleX/mitkFiberBundleXIOFactory.cpp IODataStructures/FiberBundleX/mitkFiberBundleXWriterFactory.cpp IODataStructures/FiberBundleX/mitkFiberBundleXSerializer.cpp IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.cpp # DataStructures -> PlanarFigureComposite IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp # DataStructures -> Tbss IODataStructures/TbssImages/mitkTbssImageSource.cpp IODataStructures/TbssImages/mitkTbssRoiImageSource.cpp IODataStructures/TbssImages/mitkNrrdTbssImageReader.cpp IODataStructures/TbssImages/mitkNrrdTbssImageIOFactory.cpp IODataStructures/TbssImages/mitkNrrdTbssRoiImageReader.cpp IODataStructures/TbssImages/mitkNrrdTbssRoiImageIOFactory.cpp IODataStructures/TbssImages/mitkTbssImage.cpp IODataStructures/TbssImages/mitkTbssRoiImage.cpp IODataStructures/TbssImages/mitkNrrdTbssImageWriter.cpp IODataStructures/TbssImages/mitkNrrdTbssImageWriterFactory.cpp IODataStructures/TbssImages/mitkNrrdTbssRoiImageWriter.cpp IODataStructures/TbssImages/mitkNrrdTbssRoiImageWriterFactory.cpp IODataStructures/TbssImages/mitkTbssImporter.cpp - + # DataStructures Connectomics IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkIOFactory.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkSerializer.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriter.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriterFactory.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkDefinitions.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsConstantsManager.cpp # Rendering Rendering/vtkMaskedProgrammableGlyphFilter.cpp Rendering/mitkCompositeMapper.cpp Rendering/mitkVectorImageVtkGlyphMapper3D.cpp Rendering/vtkOdfSource.cxx Rendering/vtkThickPlane.cxx Rendering/mitkOdfNormalizationMethodProperty.cpp Rendering/mitkOdfScaleByProperty.cpp Rendering/mitkFiberBundleXMapper2D.cpp Rendering/mitkFiberBundleXMapper3D.cpp Rendering/mitkFiberBundleXThreadMonitorMapper3D.cpp Rendering/mitkTbssImageMapper.cpp Rendering/mitkPlanarCircleMapper3D.cpp Rendering/mitkPlanarPolygonMapper3D.cpp Rendering/mitkConnectomicsNetworkMapper3D.cpp # Interactions Interactions/mitkFiberBundleInteractor.cpp # Algorithms Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.cpp Algorithms/mitkTractAnalyzer.cpp - + # Algorithms Connectomics Algorithms/Connectomics/mitkConnectomicsNetworkCreator.cpp Algorithms/Connectomics/mitkConnectomicsHistogramBase.cpp Algorithms/Connectomics/mitkConnectomicsDegreeHistogram.cpp Algorithms/Connectomics/mitkConnectomicsShortestPathHistogram.cpp Algorithms/Connectomics/mitkConnectomicsBetweennessHistogram.cpp Algorithms/Connectomics/mitkConnectomicsHistogramCache.cpp Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.cpp Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationBase.cpp Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationModularity.cpp Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingManager.cpp Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionBase.cpp Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.cpp # Tractography Tractography/itkStochasticTractographyFilter.h ) set(H_FILES # Rendering Rendering/mitkDiffusionImageMapper.h Rendering/mitkTbssImageMapper.h Rendering/mitkOdfVtkMapper2D.h Rendering/mitkFiberBundleXMapper3D.h Rendering/mitkFiberBundleXMapper2D.h Rendering/mitkFiberBundleXThreadMonitorMapper3D.h Rendering/mitkPlanarCircleMapper3D.h Rendering/mitkPlanarPolygonMapper3D.h Rendering/mitkConnectomicsNetworkMapper3D.h # Reconstruction Reconstruction/itkDiffusionQballReconstructionImageFilter.h Reconstruction/mitkTeemDiffusionTensor3DReconstructionImageFilter.h Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.h Reconstruction/itkPointShell.h Reconstruction/itkOrientationDistributionFunction.h Reconstruction/itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h Reconstruction/itkRegularizedIVIMLocalVariationImageFilter.h Reconstruction/itkRegularizedIVIMReconstructionFilter.h Reconstruction/itkRegularizedIVIMReconstructionSingleIteration.h # IO Datastructures IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.h IODataStructures/TbssImages/mitkTbssImporter.h # DataStructures -> FiberBundleX IODataStructures/FiberBundleX/mitkFiberBundleX.h IODataStructures/FiberBundleX/mitkFiberBundleXWriter.h IODataStructures/FiberBundleX/mitkFiberBundleXReader.h IODataStructures/FiberBundleX/mitkFiberBundleXIOFactory.h IODataStructures/FiberBundleX/mitkFiberBundleXWriterFactory.h IODataStructures/FiberBundleX/mitkFiberBundleXSerializer.h IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.h - + # Datastructures Connectomics IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkIOFactory.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkSerializer.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriter.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriterFactory.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkDefinitions.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsConstantsManager.h # Tractography Tractography/itkGibbsTrackingFilter.h Tractography/itkStochasticTractographyFilter.h # Algorithms Algorithms/itkDiffusionQballGeneralizedFaImageFilter.h Algorithms/itkDiffusionQballPrepareVisualizationImageFilter.h Algorithms/itkTensorDerivedMeasurementsFilter.h Algorithms/itkBrainMaskExtractionImageFilter.h Algorithms/itkB0ImageExtractionImageFilter.h Algorithms/itkTensorImageToDiffusionImageFilter.h Algorithms/itkTensorToL2NormImageFilter.h Algorithms/itkTractDensityImageFilter.h Algorithms/itkTractsToFiberEndingsImageFilter.h Algorithms/itkTractsToRgbaImageFilter.h Algorithms/itkGaussianInterpolateImageFunction.h Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.h Algorithms/itkDiffusionTensorPrincipleDirectionImageFilter.h Algorithms/itkCartesianToPolarVectorImageFilter.h Algorithms/itkPolarToCartesianVectorImageFilter.h Algorithms/itkDistanceMapFilter.h Algorithms/itkProjectionFilter.h Algorithms/itkSkeletonizationFilter.h Algorithms/itkReduceDirectionGradientsFilter.h Algorithms/itkResidualImageFilter.h - + Algorithms/itkExtractChannelFromRgbaImageFilter.h + # Algorithms Connectomics Algorithms/Connectomics/mitkConnectomicsNetworkCreator.h Algorithms/Connectomics/mitkConnectomicsHistogramBase.h Algorithms/Connectomics/mitkConnectomicsDegreeHistogram.h Algorithms/Connectomics/mitkConnectomicsShortestPathHistogram.h Algorithms/Connectomics/mitkConnectomicsBetweennessHistogram.h Algorithms/Connectomics/mitkConnectomicsHistogramCache.h Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.h Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationBase.h Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationModularity.h Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingManager.h Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionBase.h Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h ) set( TOOL_FILES ) if(WIN32) endif(WIN32) #MITK_MULTIPLEX_PICTYPE( Algorithms/mitkImageRegistrationMethod-TYPE.cpp ) diff --git a/Modules/GPGPU/CMakeLists.txt b/Modules/GPGPU/CMakeLists.txt index 6273843070..fb600fb51b 100644 --- a/Modules/GPGPU/CMakeLists.txt +++ b/Modules/GPGPU/CMakeLists.txt @@ -1,14 +1,19 @@ if(APPLE) message(STATUS "Module GPGPU is not ported to MacOS yet") else(APPLE) +set(package_deps) +if(UNIX) + list(APPEND package_deps X11) +endif() + MITK_CREATE_MODULE(mitkGPGPU # INCLUDE_DIRS . DEPENDS Mitk glew - PACKAGE_DEPENDS QT + PACKAGE_DEPENDS QT ${package_deps} EXPORT_DEFINE GPGPU_DLL_API QT_MODULE ) endif(APPLE) diff --git a/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageDeserializer.cpp b/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageDeserializer.cpp index 0c68ef0ac6..6b67761c75 100644 --- a/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageDeserializer.cpp +++ b/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageDeserializer.cpp @@ -1,110 +1,117 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-05-28 17:19:30 +0200 (Do, 28 Mai 2009) $ Version: $Revision $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ //Poco headers #include "Poco/Zip/Decompress.h" #include "Poco/Path.h" #include "Poco/File.h" #include "mitkNavigationToolStorageDeserializer.h" #include #include #include "mitkNavigationToolReader.h" //POCO #include mitk::NavigationToolStorageDeserializer::NavigationToolStorageDeserializer(mitk::DataStorage::Pointer dataStorage) { m_DataStorage = dataStorage; //create temp directory for this reader m_tempDirectory = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory() + Poco::Path::separator() + "tempNavigationToolDeserializer"; Poco::File myFile(m_tempDirectory); myFile.createDirectory(); } mitk::NavigationToolStorageDeserializer::~NavigationToolStorageDeserializer() { //remove temp directory Poco::File myFile(m_tempDirectory); - if (myFile.exists()) myFile.remove(true); + try + { + if (myFile.exists()) myFile.remove(); + } + catch(...) + { + MITK_ERROR << "Can't remove temp directory " << m_tempDirectory << "!"; + } } mitk::NavigationToolStorage::Pointer mitk::NavigationToolStorageDeserializer::Deserialize(std::string filename) { bool success = false; //decomress zip file into temporary directory success = decomressFiles(filename,m_tempDirectory); //currently returns an empty storage in case of an error. TODO when exception handling is availiable in MITK: Throw an exception? if (!success) {return mitk::NavigationToolStorage::New();} //now read all files and convert them to navigation tools mitk::NavigationToolStorage::Pointer returnValue = mitk::NavigationToolStorage::New(m_DataStorage); bool cont = true; int i; for (i=0; cont==true; i++) { std::string fileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool"; mitk::NavigationToolReader::Pointer myReader = mitk::NavigationToolReader::New(); mitk::NavigationTool::Pointer readTool = myReader->DoRead(fileName); if (readTool.IsNull()) cont = false; else returnValue->AddTool(readTool); //delete file std::remove(fileName.c_str()); } if(i==1) { m_ErrorMessage = "Error: did not find any tool. \n Is this a tool storage file?"; MITK_ERROR << "Error: did not find any tool. Is this a tool storage file?"; } return returnValue; } std::string mitk::NavigationToolStorageDeserializer::convertIntToString(int i) { std::string s; std::stringstream out; out << i; s = out.str(); return s; } bool mitk::NavigationToolStorageDeserializer::decomressFiles(std::string filename,std::string path) { std::ifstream file( filename.c_str(), std::ios::binary ); if (!file.good()) { m_ErrorMessage = "Cannot open '" + filename + "' for reading"; return false; } try { Poco::Zip::Decompress unzipper( file, Poco::Path( path ) ); unzipper.decompressAllFiles(); file.close(); } catch(Poco::IllegalStateException e) //temporary solution: replace this by defined exception handling later! { m_ErrorMessage = "Error: wrong file format! \n (please only load tool storage files)"; MITK_ERROR << "Error: wrong file format! (please only load tool storage files)"; return false; } return true; - } + } \ No newline at end of file diff --git a/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageSerializer.cpp b/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageSerializer.cpp index 9ba5328b4c..7eed30687d 100644 --- a/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageSerializer.cpp +++ b/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageSerializer.cpp @@ -1,89 +1,96 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-05-28 17:19:30 +0200 (Do, 28 Mai 2009) $ Version: $Revision $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ //Poco headers #include "Poco/Zip/Compress.h" #include "Poco/Path.h" #include "Poco/File.h" #include "mitkNavigationToolStorageSerializer.h" #include "mitkNavigationToolWriter.h" #include #include #include #include mitk::NavigationToolStorageSerializer::NavigationToolStorageSerializer() { //create temp directory m_tempDirectory = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory() + Poco::Path::separator() + "tempNavigationToolSerializer"; Poco::File myFile(m_tempDirectory); myFile.createDirectory(); } mitk::NavigationToolStorageSerializer::~NavigationToolStorageSerializer() { //remove temp directory Poco::File myFile(m_tempDirectory); - if (myFile.exists()) myFile.remove(); + try + { + if (myFile.exists()) myFile.remove(); + } + catch(...) + { + MITK_ERROR << "Can't remove temp directory " << m_tempDirectory << "!"; + } } bool mitk::NavigationToolStorageSerializer::Serialize(std::string filename, mitk::NavigationToolStorage::Pointer storage) { //save every tool to temp directory mitk::NavigationToolWriter::Pointer myToolWriter = mitk::NavigationToolWriter::New(); for(int i=0; iGetToolCount();i++) { std::string fileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool"; if (!myToolWriter->DoWrite(fileName,storage->GetTool(i))) return false; } //add all files to zip archive std::ofstream file( filename.c_str(), std::ios::binary | std::ios::out); if (!file.good()) { m_ErrorMessage = "Could not open a zip file for writing: '" + filename + "'"; for (int i=0; iGetToolCount();i++) { std::string fileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool"; std::remove(fileName.c_str()); } return false; } Poco::Zip::Compress zipper( file, true ); for (int i=0; iGetToolCount();i++) { std::string fileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool"; zipper.addFile(fileName,myToolWriter->GetFileWithoutPath(fileName)); //delete file: std::remove(fileName.c_str()); } zipper.close(); file.close(); return true; } std::string mitk::NavigationToolStorageSerializer::convertIntToString(int i) { std::string s; std::stringstream out; out << i; s = out.str(); return s; } diff --git a/Modules/MitkExt/CMakeLists.txt b/Modules/MitkExt/CMakeLists.txt index 141d5ad27c..7d60b5a2eb 100644 --- a/Modules/MitkExt/CMakeLists.txt +++ b/Modules/MitkExt/CMakeLists.txt @@ -1,28 +1,28 @@ #if(WIN32) # option(MITK_USE_TD_MOUSE "Enable support for 3D Connexion SpaceNavigator" OFF) #endif(WIN32) configure_file(${PROJECT_SOURCE_DIR}/CMake/ToolExtensionITKFactory.cpp.in ${PROJECT_BINARY_DIR}/ToolExtensionITKFactory.cpp.in COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/CMake/ToolExtensionITKFactoryLoader.cpp.in ${PROJECT_BINARY_DIR}/ToolExtensionITKFactoryLoader.cpp.in COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/CMake/ToolGUIExtensionITKFactory.cpp.in ${PROJECT_BINARY_DIR}/ToolGUIExtensionITKFactory.cpp.in COPYONLY) MITK_CREATE_MODULE( MitkExt INCLUDE_DIRS Algorithms Controllers DataManagement Interactions IO Rendering DEPENDS Mitk LegacyAdaptors IpPicSupport ipSegmentation mitkIpFunc PlanarFigure ImageStatistics - DEPENDS_INTERNAL pic2vtk IIL4MITK + DEPENDS_INTERNAL pic2vtk #IIL4MITK ) # this is needed for libraries which link to mitkCoreExt and need # symbols from explicitly instantiated templates like # mitk::UnstructuredGridVtkWriter which is referenced in # mitk::UnstructuredGridVtkWriterTest in the MitkExtTestDriver executable. if(MINGW) get_target_property(_mitkCoreExt_MINGW_linkflags mitkCoreExt LINK_FLAGS) if(NOT _mitkCoreExt_MINGW_linkflags) set(_mitkCoreExt_MINGW_linkflags "") endif(NOT _mitkCoreExt_MINGW_linkflags) set_target_properties(mitkCoreExt PROPERTIES LINK_FLAGS "${_mitkCoreExt_MINGW_linkflags} -Wl,--export-all-symbols") endif(MINGW) add_subdirectory(Testing) diff --git a/Modules/MitkExt/Interactions/mitkContourTool.cpp b/Modules/MitkExt/Interactions/mitkContourTool.cpp index 021b9e73e5..1e43ef3665 100644 --- a/Modules/MitkExt/Interactions/mitkContourTool.cpp +++ b/Modules/MitkExt/Interactions/mitkContourTool.cpp @@ -1,160 +1,160 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkContourTool.h" #include "mitkToolManager.h" #include "mitkOverwriteSliceImageFilter.h" #include "mitkOverwriteDirectedPlaneImageFilter.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" //#include "mitkProperties.h" #include "mitkPlanarCircle.h" mitk::ContourTool::ContourTool(int paintingPixelValue) :FeedbackContourTool("PressMoveReleaseWithCTRLInversion"), m_PaintingPixelValue(paintingPixelValue) { } mitk::ContourTool::~ContourTool() { } void mitk::ContourTool::Activated() { Superclass::Activated(); } void mitk::ContourTool::Deactivated() { Superclass::Deactivated(); } /** Just show the contour, insert the first point. */ bool mitk::ContourTool::OnMousePressed (Action* action, const StateEvent* stateEvent) { if (!FeedbackContourTool::OnMousePressed( action, stateEvent )) return false; const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; Contour* contour = FeedbackContourTool::GetFeedbackContour(); contour->Initialize(); contour->AddVertex( positionEvent->GetWorldPosition() ); FeedbackContourTool::SetFeedbackContourVisible(true); assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } /** Insert the point to the feedback contour. */ bool mitk::ContourTool::OnMouseMoved (Action* action, const StateEvent* stateEvent) { if (!FeedbackContourTool::OnMouseMoved( action, stateEvent )) return false; const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; Contour* contour = FeedbackContourTool::GetFeedbackContour(); contour->AddVertex( positionEvent->GetWorldPosition() ); assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } /** Close the contour, project it to the image slice and fill it in 2D. */ bool mitk::ContourTool::OnMouseReleased(Action* action, const StateEvent* stateEvent) { // 1. Hide the feedback contour, find out which slice the user clicked, find out which slice of the toolmanager's working image corresponds to that FeedbackContourTool::SetFeedbackContourVisible(false); const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); if (!FeedbackContourTool::OnMouseReleased( action, stateEvent )) return false; DataNode* workingNode( m_ToolManager->GetWorkingData(0) ); if (!workingNode) return false; Image* image = dynamic_cast(workingNode->GetData()); const PlaneGeometry* planeGeometry( dynamic_cast (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) ); if ( !image || !planeGeometry ) return false; // 2. Slice is known, now we try to get it as a 2D image and project the contour into index coordinates of this slice Image::Pointer slice = SegTool2D::GetAffectedImageSliceAs2DImage( positionEvent, image ); if ( slice.IsNull() ) { MITK_ERROR << "Unable to extract slice." << std::endl; return false; } Contour* feedbackContour( FeedbackContourTool::GetFeedbackContour() ); Contour::Pointer projectedContour = FeedbackContourTool::ProjectContourTo2DSlice( slice, feedbackContour, true, false ); // true: actually no idea why this is neccessary, but it works :-( if (projectedContour.IsNull()) return false; FeedbackContourTool::FillContourInSlice( projectedContour, slice, m_PaintingPixelValue ); this->WriteBackSegmentationResult(positionEvent, slice); // 4. Make sure the result is drawn again --> is visible then. assert( positionEvent->GetSender()->GetRenderWindow() ); - mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); - + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + return true; } /** Called when the CTRL key is pressed. Will change the painting pixel value from 0 to 1 or from 1 to 0. */ bool mitk::ContourTool::OnInvertLogic(Action* action, const StateEvent* stateEvent) { if (!FeedbackContourTool::OnInvertLogic(action, stateEvent)) return false; // Inversion only for 0 and 1 as painting values if (m_PaintingPixelValue == 1) { m_PaintingPixelValue = 0; FeedbackContourTool::SetFeedbackContourColor( 1.0, 0.0, 0.0 ); } else if (m_PaintingPixelValue == 0) { m_PaintingPixelValue = 1; FeedbackContourTool::SetFeedbackContourColorDefault(); } return true; } diff --git a/Modules/PlanarFigure/Algorithms/mitkPlanarFigureObjectFactory.cpp b/Modules/PlanarFigure/Algorithms/mitkPlanarFigureObjectFactory.cpp index 814a3bbbe7..74059e8f35 100644 --- a/Modules/PlanarFigure/Algorithms/mitkPlanarFigureObjectFactory.cpp +++ b/Modules/PlanarFigure/Algorithms/mitkPlanarFigureObjectFactory.cpp @@ -1,137 +1,139 @@ /*========================================================================= - + Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-04-16 16:53:19 +0200 (Fr, 16 Apr 2010) $ Version: $Revision: 16916 $ - + Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. - + This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. - + =========================================================================*/ #include "mitkPlanarFigureObjectFactory.h" #include "mitkPlanarFigureWriter.h" #include "mitkCoreObjectFactory.h" #include "mitkPlanarFigureIOFactory.h" #include "mitkPlanarFigureWriterFactory.h" #include "mitkPlanarFigure.h" #include "mitkPlanarFigureMapper2D.h" typedef std::multimap MultimapType; -mitk::PlanarFigureObjectFactory::PlanarFigureObjectFactory() +mitk::PlanarFigureObjectFactory::PlanarFigureObjectFactory() { static bool alreadyDone = false; if ( !alreadyDone ) { RegisterIOFactories(); itk::ObjectFactoryBase::RegisterFactory( PlanarFigureIOFactory::New() ); PlanarFigureWriterFactory::RegisterOneFactory(); m_FileWriters.push_back( PlanarFigureWriter::New().GetPointer() ); mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory(this); CreateFileExtensionsMap(); alreadyDone = true; } } -mitk::Mapper::Pointer mitk::PlanarFigureObjectFactory::CreateMapper(mitk::DataNode* node, MapperSlotId id) +mitk::Mapper::Pointer mitk::PlanarFigureObjectFactory::CreateMapper(mitk::DataNode* node, MapperSlotId id) { mitk::Mapper::Pointer newMapper=NULL; mitk::BaseData *data = node->GetData(); if ( id == mitk::BaseRenderer::Standard2D ) { if ( dynamic_cast(data) != NULL ) { newMapper = mitk::PlanarFigureMapper2D::New(); newMapper->SetDataNode(node); } } else if ( id == mitk::BaseRenderer::Standard3D ) { } return newMapper; } void mitk::PlanarFigureObjectFactory::SetDefaultProperties(mitk::DataNode* node) { - + if ( node == NULL ) { return; } mitk::DataNode::Pointer nodePointer = node; mitk::PlanarFigure::Pointer pf = dynamic_cast( node->GetData() ); if ( pf.IsNotNull() ) { mitk::PlanarFigureMapper2D::SetDefaultProperties(node); - } + node->AddProperty( "color", mitk::ColorProperty::New(1.0,1.0,1.0), NULL, true ); + node->AddProperty( "opacity", mitk::FloatProperty::New(0.8), NULL, true ); + } } -const char* mitk::PlanarFigureObjectFactory::GetFileExtensions() +const char* mitk::PlanarFigureObjectFactory::GetFileExtensions() { return ""; }; mitk::CoreObjectFactoryBase::MultimapType mitk::PlanarFigureObjectFactory::GetFileExtensionsMap() { return m_FileExtensionsMap; } -const char* mitk::PlanarFigureObjectFactory::GetSaveFileExtensions() -{ +const char* mitk::PlanarFigureObjectFactory::GetSaveFileExtensions() +{ //return ";;Planar Figures (*.pf)"; // for mitk::PlanarFigure and derived classes std::string fileExtension; this->CreateFileExtensions(m_SaveFileExtensionsMap, fileExtension); return fileExtension.c_str(); }; mitk::CoreObjectFactoryBase::MultimapType mitk::PlanarFigureObjectFactory::GetSaveFileExtensionsMap() { return m_SaveFileExtensionsMap; } void mitk::PlanarFigureObjectFactory::CreateFileExtensionsMap() { m_SaveFileExtensionsMap.insert(std::pair("*.pf", "Planar Figure Files")); } -void mitk::PlanarFigureObjectFactory::RegisterIOFactories() +void mitk::PlanarFigureObjectFactory::RegisterIOFactories() { } struct RegisterPlanarFigureObjectFactory{ RegisterPlanarFigureObjectFactory() : m_Factory( mitk::PlanarFigureObjectFactory::New() ) { mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory( m_Factory ); } ~RegisterPlanarFigureObjectFactory() { mitk::CoreObjectFactory::GetInstance()->UnRegisterExtraFactory( m_Factory ); } mitk::PlanarFigureObjectFactory::Pointer m_Factory; }; static RegisterPlanarFigureObjectFactory registerPlanarFigureObjectFactory; diff --git a/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.cpp b/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.cpp index 05457a92b3..f8fa12fbb5 100644 --- a/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.cpp +++ b/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.cpp @@ -1,978 +1,980 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2008-10-02 16:21:08 +0200 (Do, 02 Okt 2008) $ Version: $Revision: 13129 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkPlanarFigureInteractor.h" #include "mitkPointOperation.h" #include "mitkPositionEvent.h" #include "mitkPlanarFigure.h" #include "mitkStatusBar.h" #include "mitkDataNode.h" #include "mitkInteractionConst.h" #include "mitkAction.h" #include "mitkStateEvent.h" #include "mitkOperationEvent.h" #include "mitkUndoController.h" #include "mitkStateMachineFactory.h" #include "mitkStateTransitionOperation.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" #include "mitkNodePredicateDataType.h" #include "mitkNodePredicateOr.h" //how precise must the user pick the point //default value mitk::PlanarFigureInteractor ::PlanarFigureInteractor(const char * type, DataNode* dataNode, int /* n */ ) : Interactor( type, dataNode ), m_Precision( 6.5 ), m_MinimumPointDistance( 25.0 ), m_IsHovering( false ), m_LastPointWasValid( false ) { } mitk::PlanarFigureInteractor::~PlanarFigureInteractor() { } void mitk::PlanarFigureInteractor::SetPrecision( mitk::ScalarType precision ) { m_Precision = precision; } void mitk::PlanarFigureInteractor::SetMinimumPointDistance( ScalarType minimumDistance ) { m_MinimumPointDistance = minimumDistance; } // Overwritten since this class can handle it better! float mitk::PlanarFigureInteractor ::CanHandleEvent(StateEvent const* stateEvent) const { float returnValue = 0.5; // If it is a key event that can be handled in the current state, // then return 0.5 mitk::DisplayPositionEvent const *disPosEvent = dynamic_cast (stateEvent->GetEvent()); // Key event handling: if (disPosEvent == NULL) { // Check if the current state has a transition waiting for that key event. if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL) { return 0.5; } else { return 0.0; } } mitk::PlanarFigure *planarFigure = dynamic_cast( m_DataNode->GetData() ); if ( planarFigure != NULL ) { // Give higher priority if this figure is currently selected if ( planarFigure->GetSelectedControlPoint() >= 0 ) { return 1.0; } } return returnValue; } bool mitk::PlanarFigureInteractor ::ExecuteAction( Action *action, mitk::StateEvent const *stateEvent ) { bool ok = false; // Check corresponding data; has to be sub-class of mitk::PlanarFigure mitk::PlanarFigure *planarFigure = dynamic_cast< mitk::PlanarFigure * >( m_DataNode->GetData() ); if ( planarFigure == NULL ) { return false; } // Get the timestep to also support 3D+t const mitk::Event *theEvent = stateEvent->GetEvent(); int timeStep = 0; //mitk::ScalarType timeInMS = 0.0; if ( theEvent ) { if (theEvent->GetSender() != NULL) { timeStep = theEvent->GetSender()->GetTimeStep( planarFigure ); //timeInMS = theEvent->GetSender()->GetTime(); } } // Get Geometry2D of PlanarFigure mitk::Geometry2D *planarFigureGeometry = dynamic_cast< mitk::Geometry2D * >( planarFigure->GetGeometry( timeStep ) ); // Get the Geometry2D of the window the user interacts with (for 2D point // projection) mitk::BaseRenderer *renderer = NULL; const Geometry2D *projectionPlane = NULL; if ( theEvent ) { renderer = theEvent->GetSender(); projectionPlane = renderer->GetCurrentWorldGeometry2D(); } // TODO: Check if display and PlanarFigure geometries are parallel (if they are PlaneGeometries) switch (action->GetActionId()) { case AcDONOTHING: ok = true; break; case AcCHECKOBJECT: { if ( planarFigure->IsPlaced() ) { this->HandleEvent( new mitk::StateEvent( EIDYES, NULL ) ); } else { this->HandleEvent( new mitk::StateEvent( EIDNO, NULL ) ); } ok = false; break; } case AcADD: { // Invoke event to notify listeners that placement of this PF starts now planarFigure->InvokeEvent( StartPlacementPlanarFigureEvent() ); // Use Geometry2D of the renderer clicked on for this PlanarFigure mitk::PlaneGeometry *planeGeometry = const_cast< mitk::PlaneGeometry * >( dynamic_cast< const mitk::PlaneGeometry * >( renderer->GetSliceNavigationController()->GetCurrentPlaneGeometry() ) ); if ( planeGeometry != NULL ) { planarFigureGeometry = planeGeometry; planarFigure->SetGeometry2D( planeGeometry ); } else { ok = false; break; } // Extract point in 2D world coordinates (relative to Geometry2D of // PlanarFigure) Point2D point2D; if ( !this->TransformPositionEventToPoint2D( stateEvent, point2D, planarFigureGeometry ) ) { ok = false; break; } // Place PlanarFigure at this point planarFigure->PlaceFigure( point2D ); // Re-evaluate features planarFigure->EvaluateFeatures(); //this->LogPrintPlanarFigureQuantities( planarFigure ); // Set a bool property indicating that the figure has been placed in // the current RenderWindow. This is required so that the same render // window can be re-aligned to the Geometry2D of the PlanarFigure later // on in an application. m_DataNode->SetBoolProperty( "PlanarFigureInitializedWindow", true, renderer ); // Update rendered scene renderer->GetRenderingManager()->RequestUpdateAll(); ok = true; break; } case AcMOVEPOINT: { bool isEditable = true; m_DataNode->GetBoolProperty( "planarfigure.iseditable", isEditable ); // Extract point in 2D world coordinates (relative to Geometry2D of // PlanarFigure) Point2D point2D; if ( !this->TransformPositionEventToPoint2D( stateEvent, point2D, planarFigureGeometry ) || !isEditable ) { ok = false; break; } // check if the control points shall be hidden during interaction bool hidecontrolpointsduringinteraction = false; m_DataNode->GetBoolProperty( "planarfigure.hidecontrolpointsduringinteraction", hidecontrolpointsduringinteraction ); // hide the control points if necessary m_DataNode->SetBoolProperty( "planarfigure.drawcontrolpoints", !hidecontrolpointsduringinteraction ); // Move current control point to this point planarFigure->SetCurrentControlPoint( point2D ); // Re-evaluate features planarFigure->EvaluateFeatures(); //this->LogPrintPlanarFigureQuantities( planarFigure ); // Update rendered scene renderer->GetRenderingManager()->RequestUpdateAll(); ok = true; break; } case AcCHECKNMINUS1: { if ( planarFigure->GetNumberOfControlPoints() >= planarFigure->GetMaximumNumberOfControlPoints() ) { // Initial placement finished: deselect control point and send an // event to notify application listeners planarFigure->Modified(); planarFigure->DeselectControlPoint(); planarFigure->InvokeEvent( EndPlacementPlanarFigureEvent() ); planarFigure->InvokeEvent( EndInteractionPlanarFigureEvent() ); planarFigure->SetProperty( "initiallyplaced", mitk::BoolProperty::New( true ) ); m_DataNode->SetBoolProperty( "planarfigure.drawcontrolpoints", true ); m_DataNode->Modified(); this->HandleEvent( new mitk::StateEvent( EIDYES, stateEvent->GetEvent() ) ); } else { this->HandleEvent( new mitk::StateEvent( EIDNO, stateEvent->GetEvent() ) ); } // Update rendered scene renderer->GetRenderingManager()->RequestUpdateAll(); ok = true; break; } case AcCHECKEQUALS1: { // NOTE: Action name is a bit misleading; this action checks whether // the figure has already the minimum number of required points to // be finished (by double-click) const mitk::PositionEvent *positionEvent = dynamic_cast< const mitk::PositionEvent * > ( stateEvent->GetEvent() ); if ( positionEvent == NULL ) { ok = false; break; } if ( planarFigure->GetNumberOfControlPoints() > planarFigure->GetMinimumNumberOfControlPoints() ) { // Initial placement finished: deselect control point and send an // event to notify application listeners planarFigure->Modified(); planarFigure->DeselectControlPoint(); planarFigure->RemoveLastControlPoint(); planarFigure->SetProperty( "initiallyplaced", mitk::BoolProperty::New( true ) ); m_DataNode->SetBoolProperty( "planarfigure.drawcontrolpoints", true ); m_DataNode->Modified(); planarFigure->InvokeEvent( EndPlacementPlanarFigureEvent() ); planarFigure->InvokeEvent( EndInteractionPlanarFigureEvent() ); this->HandleEvent( new mitk::StateEvent( EIDYES, NULL ) ); } else { this->HandleEvent( new mitk::StateEvent( EIDNO, NULL ) ); } // Update rendered scene renderer->GetRenderingManager()->RequestUpdateAll(); ok = true; break; } case AcCHECKPOINT: { // Check if the distance of the current point to the previously set point in display coordinates // is sufficient (if a previous point exists) // Extract display position const mitk::PositionEvent *positionEvent = dynamic_cast< const mitk::PositionEvent * > ( stateEvent->GetEvent() ); if ( positionEvent == NULL ) { ok = false; break; } m_LastPointWasValid = IsMousePositionAcceptableAsNewControlPoint( positionEvent, planarFigure ); if (m_LastPointWasValid) { this->HandleEvent( new mitk::StateEvent( EIDYES, stateEvent->GetEvent() ) ); } else { this->HandleEvent( new mitk::StateEvent( EIDNO, stateEvent->GetEvent() ) ); } ok = true; break; } case AcADDPOINT: { bool selected = false; bool isEditable = true; m_DataNode->GetBoolProperty("selected", selected); m_DataNode->GetBoolProperty( "planarfigure.iseditable", isEditable ); if ( !selected || !isEditable ) { ok = false; break; } // Extract point in 2D world coordinates (relative to Geometry2D of // PlanarFigure) Point2D point2D, projectedPoint; if ( !this->TransformPositionEventToPoint2D( stateEvent, point2D, planarFigureGeometry ) ) { ok = false; break; } // TODO: check segement of polyline we clicked in int nextIndex = this->IsPositionOverFigure( stateEvent, planarFigure, planarFigureGeometry, projectionPlane, renderer->GetDisplayGeometry(), projectedPoint ); // Add point as new control point renderer->GetDisplayGeometry()->DisplayToWorld( projectedPoint, projectedPoint ); if ( planarFigure->IsPreviewControlPointVisible() ) { point2D = planarFigure->GetPreviewControlPoint(); } planarFigure->AddControlPoint( point2D, nextIndex ); if ( planarFigure->IsPreviewControlPointVisible() ) { planarFigure->SelectControlPoint( nextIndex ); planarFigure->ResetPreviewContolPoint(); } // Re-evaluate features planarFigure->EvaluateFeatures(); //this->LogPrintPlanarFigureQuantities( planarFigure ); // Update rendered scene renderer->GetRenderingManager()->RequestUpdateAll(); ok = true; break; } case AcDESELECTPOINT: { planarFigure->DeselectControlPoint(); // Issue event so that listeners may update themselves planarFigure->Modified(); planarFigure->InvokeEvent( EndInteractionPlanarFigureEvent() ); m_DataNode->SetBoolProperty( "planarfigure.drawcontrolpoints", true ); + m_DataNode->SetBoolProperty( "planarfigure.ishovering", false ); m_DataNode->Modified(); // falls through + break; } case AcCHECKHOVERING: { mitk::Point2D pointProjectedOntoLine; int previousControlPoint = mitk::PlanarFigureInteractor::IsPositionOverFigure( stateEvent, planarFigure, planarFigureGeometry, projectionPlane, renderer->GetDisplayGeometry(), pointProjectedOntoLine ); bool isHovering = ( previousControlPoint != -1 ); int pointIndex = mitk::PlanarFigureInteractor::IsPositionInsideMarker( stateEvent, planarFigure, planarFigureGeometry, projectionPlane, renderer->GetDisplayGeometry() ); int initiallySelectedControlPoint = planarFigure->GetSelectedControlPoint(); if ( pointIndex >= 0 ) { // If mouse is above control point, mark it as selected planarFigure->SelectControlPoint( pointIndex ); // If mouse is hovering above a marker, it is also hovering above the figure isHovering = true; } else { // Mouse in not above control point --> deselect point planarFigure->DeselectControlPoint(); } bool renderingUpdateNeeded = true; if ( isHovering ) { if ( !m_IsHovering ) { // Invoke hover event once when the mouse is entering the figure area m_IsHovering = true; planarFigure->InvokeEvent( StartHoverPlanarFigureEvent() ); // Set bool property to indicate that planar figure is currently in "hovering" mode m_DataNode->SetBoolProperty( "planarfigure.ishovering", true ); renderingUpdateNeeded = true; } bool selected = false; bool isExtendable = false; bool isEditable = true; m_DataNode->GetBoolProperty("selected", selected); m_DataNode->GetBoolProperty("planarfigure.isextendable", isExtendable); m_DataNode->GetBoolProperty( "planarfigure.iseditable", isEditable ); if ( selected && isHovering && isExtendable && pointIndex == -1 && isEditable ) { const mitk::PositionEvent *positionEvent = dynamic_cast< const mitk::PositionEvent * > ( stateEvent->GetEvent() ); if ( positionEvent != NULL ) { renderer->GetDisplayGeometry()->DisplayToWorld( pointProjectedOntoLine, pointProjectedOntoLine ); planarFigure->SetPreviewControlPoint( pointProjectedOntoLine ); renderingUpdateNeeded = true; } } else { planarFigure->ResetPreviewContolPoint(); } if ( planarFigure->GetSelectedControlPoint() != initiallySelectedControlPoint ) { // the selected control point has changed -> rendering update necessary renderingUpdateNeeded = true; } this->HandleEvent( new mitk::StateEvent( EIDYES, stateEvent->GetEvent() ) ); // Return true: only this interactor is eligible to react on this event ok = true; } else { if ( m_IsHovering ) { planarFigure->ResetPreviewContolPoint(); // Invoke end-hover event once the mouse is exiting the figure area m_IsHovering = false; planarFigure->InvokeEvent( EndHoverPlanarFigureEvent() ); // Set bool property to indicate that planar figure is no longer in "hovering" mode m_DataNode->SetBoolProperty( "planarfigure.ishovering", false ); renderingUpdateNeeded = true; } this->HandleEvent( new mitk::StateEvent( EIDNO, NULL ) ); // Return false so that other (PlanarFigure) Interactors may react on this // event as well ok = false; } // Update rendered scene if necessray if ( renderingUpdateNeeded ) { renderer->GetRenderingManager()->RequestUpdateAll(); } break; } case AcCHECKSELECTED: { bool selected = false; m_DataNode->GetBoolProperty("selected", selected); if ( selected ) { this->HandleEvent( new mitk::StateEvent( EIDYES, stateEvent->GetEvent() ) ); } else { // Invoke event to notify listeners that this planar figure should be selected planarFigure->InvokeEvent( SelectPlanarFigureEvent() ); this->HandleEvent( new mitk::StateEvent( EIDNO, NULL ) ); } } case AcSELECTPICKEDOBJECT: { //// Invoke event to notify listeners that this planar figure should be selected //planarFigure->InvokeEvent( SelectPlanarFigureEvent() ); // Check if planar figure is marked as "editable" bool isEditable = true; m_DataNode->GetBoolProperty( "planarfigure.iseditable", isEditable ); int pointIndex = -1; if ( isEditable ) { // If planar figure is editable, check if mouse is over a control point pointIndex = mitk::PlanarFigureInteractor::IsPositionInsideMarker( stateEvent, planarFigure, planarFigureGeometry, projectionPlane, renderer->GetDisplayGeometry() ); } // If editing is enabled and the mouse is currently over a control point, select it if ( pointIndex >= 0 ) { this->HandleEvent( new mitk::StateEvent( EIDYES, stateEvent->GetEvent() ) ); // Return true: only this interactor is eligible to react on this event ok = true; } else { this->HandleEvent( new mitk::StateEvent( EIDNO, stateEvent->GetEvent() ) ); // Return false so that other (PlanarFigure) Interactors may react on this // event as well ok = false; } ok = true; break; } case AcENTEROBJECT: { bool selected = false; m_DataNode->GetBoolProperty("selected", selected); // no need to invoke this if the figure is already selected if ( !selected ) { planarFigure->InvokeEvent( SelectPlanarFigureEvent() ); } // if this was a right mouse button click, invoke the event if ( theEvent->GetButton() == 2 ) { planarFigure->InvokeEvent( ContextMenuPlanarFigureEvent() ); ok = true; } else { ok = false; } // we HAVE TO proceed with 'EIDNO' here to ensure correct states // and convenient application behaviour this->HandleEvent( new mitk::StateEvent( EIDNO, stateEvent->GetEvent() ) ); break; } case AcSELECTPOINT: { // Invoke event to notify listeners that interaction with this PF starts now planarFigure->InvokeEvent( StartInteractionPlanarFigureEvent() ); // Reset the PlanarFigure if required if ( planarFigure->ResetOnPointSelect() ) { this->HandleEvent( new mitk::StateEvent( EIDYES, stateEvent->GetEvent() ) ); } else { this->HandleEvent( new mitk::StateEvent( EIDNO, stateEvent->GetEvent() ) ); } ok = true; break; } case AcREMOVEPOINT: { bool isExtendable = false; m_DataNode->GetBoolProperty("planarfigure.isextendable", isExtendable); if ( isExtendable ) { int selectedControlPoint = planarFigure->GetSelectedControlPoint(); planarFigure->RemoveControlPoint( selectedControlPoint ); // Re-evaluate features planarFigure->EvaluateFeatures(); planarFigure->Modified(); m_DataNode->SetBoolProperty( "planarfigure.drawcontrolpoints", true ); planarFigure->InvokeEvent( EndInteractionPlanarFigureEvent() ); renderer->GetRenderingManager()->RequestUpdateAll(); this->HandleEvent( new mitk::StateEvent( EIDYES, NULL ) ); } else { this->HandleEvent( new mitk::StateEvent( EIDNO, NULL ) ); } } //case AcMOVEPOINT: //case AcMOVESELECTED: // { // // Update the display // renderer->GetRenderingManager()->RequestUpdateAll(); // ok = true; // break; // } //case AcFINISHMOVE: // { // ok = true; // break; // } default: return Superclass::ExecuteAction( action, stateEvent ); } return ok; } bool mitk::PlanarFigureInteractor::TransformPositionEventToPoint2D( const StateEvent *stateEvent, Point2D &point2D, const Geometry2D *planarFigureGeometry ) { // Extract world position, and from this position on geometry, if // available const mitk::PositionEvent *positionEvent = dynamic_cast< const mitk::PositionEvent * > ( stateEvent->GetEvent() ); if ( positionEvent == NULL ) { return false; } mitk::Point3D worldPoint3D = positionEvent->GetWorldPosition(); // TODO: proper handling of distance tolerance if ( planarFigureGeometry->Distance( worldPoint3D ) > 0.1 ) { return false; } // Project point onto plane of this PlanarFigure planarFigureGeometry->Map( worldPoint3D, point2D ); return true; } bool mitk::PlanarFigureInteractor::TransformObjectToDisplay( const mitk::Point2D &point2D, mitk::Point2D &displayPoint, const mitk::Geometry2D *objectGeometry, const mitk::Geometry2D *rendererGeometry, const mitk::DisplayGeometry *displayGeometry ) const { mitk::Point3D point3D; // Map circle point from local 2D geometry into 3D world space objectGeometry->Map( point2D, point3D ); // TODO: proper handling of distance tolerance if ( displayGeometry->Distance( point3D ) < 0.1 ) { // Project 3D world point onto display geometry rendererGeometry->Map( point3D, displayPoint ); displayGeometry->WorldToDisplay( displayPoint, displayPoint ); return true; } return false; } bool mitk::PlanarFigureInteractor::IsPointNearLine( const mitk::Point2D& point, const mitk::Point2D& startPoint, const mitk::Point2D& endPoint, mitk::Point2D& projectedPoint ) const { mitk::Vector2D n1 = endPoint - startPoint; n1.Normalize(); // Determine dot products between line vector and startpoint-point / endpoint-point vectors double l1 = n1 * (point - startPoint); double l2 = -n1 * (point - endPoint); // Determine projection of specified point onto line defined by start / end point mitk::Point2D crossPoint = startPoint + n1 * l1; projectedPoint = crossPoint; // Point is inside encompassing rectangle IF // - its distance to its projected point is small enough // - it is not further outside of the line than the defined tolerance if (((crossPoint.SquaredEuclideanDistanceTo(point) < 20.0) && (l1 > 0.0) && (l2 > 0.0)) || endPoint.SquaredEuclideanDistanceTo(point) < 20.0 || startPoint.SquaredEuclideanDistanceTo(point) < 20.0) { return true; } return false; } int mitk::PlanarFigureInteractor::IsPositionOverFigure( const StateEvent *stateEvent, PlanarFigure *planarFigure, const Geometry2D *planarFigureGeometry, const Geometry2D *rendererGeometry, const DisplayGeometry *displayGeometry, Point2D& pointProjectedOntoLine ) const { // Extract display position const mitk::PositionEvent *positionEvent = dynamic_cast< const mitk::PositionEvent * > ( stateEvent->GetEvent() ); if ( positionEvent == NULL ) { return -1; } mitk::Point2D displayPosition = positionEvent->GetDisplayPosition(); // Iterate over all polylines of planar figure, and check if // any one is close to the current display position typedef mitk::PlanarFigure::PolyLineType VertexContainerType; mitk::Point2D worldPoint2D, displayControlPoint; mitk::Point3D worldPoint3D; for ( unsigned short loop = 0; loop < planarFigure->GetPolyLinesSize(); ++loop ) { const VertexContainerType polyLine = planarFigure->GetPolyLine( loop ); Point2D polyLinePoint; Point2D firstPolyLinePoint; Point2D previousPolyLinePoint; bool firstPoint = true; for ( VertexContainerType::const_iterator it = polyLine.begin(); it != polyLine.end(); ++it ) { // Get plane coordinates of this point of polyline (if possible) if ( !this->TransformObjectToDisplay( it->Point, polyLinePoint, planarFigureGeometry, rendererGeometry, displayGeometry ) ) { break; // Poly line invalid (not on current 2D plane) --> skip it } if ( firstPoint ) { firstPolyLinePoint = polyLinePoint; firstPoint = false; } else if ( this->IsPointNearLine( displayPosition, previousPolyLinePoint, polyLinePoint, pointProjectedOntoLine ) ) { // Point is close enough to line segment --> Return index of the segment return it->Index; } previousPolyLinePoint = polyLinePoint; } // For closed figures, also check last line segment if ( planarFigure->IsClosed() && this->IsPointNearLine( displayPosition, polyLinePoint, firstPolyLinePoint, pointProjectedOntoLine ) ) { return 0; // Return index of first control point } } return -1; } int mitk::PlanarFigureInteractor::IsPositionInsideMarker( const StateEvent *stateEvent, const PlanarFigure *planarFigure, const Geometry2D *planarFigureGeometry, const Geometry2D *rendererGeometry, const DisplayGeometry *displayGeometry ) const { // Extract display position const mitk::PositionEvent *positionEvent = dynamic_cast< const mitk::PositionEvent * > ( stateEvent->GetEvent() ); if ( positionEvent == NULL ) { return -1; } mitk::Point2D displayPosition = positionEvent->GetDisplayPosition(); // Iterate over all control points of planar figure, and check if // any one is close to the current display position mitk::Point2D worldPoint2D, displayControlPoint; mitk::Point3D worldPoint3D; int numberOfControlPoints = planarFigure->GetNumberOfControlPoints(); for ( int i=0; iTransformObjectToDisplay( planarFigure->GetControlPoint(i), displayControlPoint, planarFigureGeometry, rendererGeometry, displayGeometry ) ) { // TODO: variable size of markers if ( displayPosition.SquaredEuclideanDistanceTo( displayControlPoint ) < 20.0 ) { return i; } } } //for ( it = controlPoints.begin(); it != controlPoints.end(); ++it ) //{ // Point2D displayControlPoint; // if ( this->TransformObjectToDisplay( it->Point, displayControlPoint, // planarFigureGeometry, rendererGeometry, displayGeometry ) ) // { // // TODO: variable size of markers // if ( (abs(displayPosition[0] - displayControlPoint[0]) < 4 ) // && (abs(displayPosition[1] - displayControlPoint[1]) < 4 ) ) // { // return index; // } // } //} return -1; } void mitk::PlanarFigureInteractor::LogPrintPlanarFigureQuantities( const PlanarFigure *planarFigure ) { MITK_INFO << "PlanarFigure: " << planarFigure->GetNameOfClass(); for ( unsigned int i = 0; i < planarFigure->GetNumberOfFeatures(); ++i ) { MITK_INFO << "* " << planarFigure->GetFeatureName( i ) << ": " << planarFigure->GetQuantity( i ) << " " << planarFigure->GetFeatureUnit( i ); } } bool mitk::PlanarFigureInteractor::IsMousePositionAcceptableAsNewControlPoint( const PositionEvent* positionEvent, const PlanarFigure* planarFigure ) { assert(positionEvent && planarFigure); BaseRenderer* renderer = positionEvent->GetSender(); assert(renderer); // Get the timestep to support 3D+t int timeStep( renderer->GetTimeStep( planarFigure ) ); // Get current display position of the mouse Point2D currentDisplayPosition = positionEvent->GetDisplayPosition(); // Check if a previous point has been set bool tooClose = false; for( int i=0; i < (int)planarFigure->GetNumberOfControlPoints(); i++ ) { if ( i != planarFigure->GetSelectedControlPoint() ) { // Try to convert previous point to current display coordinates mitk::Geometry2D *planarFigureGeometry = dynamic_cast< mitk::Geometry2D * >( planarFigure->GetGeometry( timeStep ) ); const Geometry2D *projectionPlane = renderer->GetCurrentWorldGeometry2D(); mitk::Point3D previousPoint3D; planarFigureGeometry->Map( planarFigure->GetControlPoint( i ), previousPoint3D ); if ( renderer->GetDisplayGeometry()->Distance( previousPoint3D ) < 0.1 ) // ugly, but assert makes this work { mitk::Point2D previousDisplayPosition; projectionPlane->Map( previousPoint3D, previousDisplayPosition ); renderer->GetDisplayGeometry()->WorldToDisplay( previousDisplayPosition, previousDisplayPosition ); double a = currentDisplayPosition[0] - previousDisplayPosition[0]; double b = currentDisplayPosition[1] - previousDisplayPosition[1]; // If point is to close, do not set a new point tooClose = (a * a + b * b < m_MinimumPointDistance ); } if ( tooClose ) return false; // abort loop early } } return !tooClose; // default } diff --git a/Modules/Qmitk/QmitkRenderWindowMenu.cpp b/Modules/Qmitk/QmitkRenderWindowMenu.cpp index 34b89a7006..2f8434c1b3 100644 --- a/Modules/Qmitk/QmitkRenderWindowMenu.cpp +++ b/Modules/Qmitk/QmitkRenderWindowMenu.cpp @@ -1,987 +1,992 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-05-12 20:04:59 +0200 (Di, 12 Mai 2009) $ Version: $Revision: 17180 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkRenderWindowMenu.h" #include "mitkResliceMethodProperty.h" #include "mitkProperties.h" #include #include #include #include #include #include #include #include #include #include #include #include "QmitkStdMultiWidget.h" //#include"iconClose.xpm" #include"iconFullScreen.xpm" #include"iconCrosshairMode.xpm" //#include"iconHoriSplit.xpm" #include"iconSettings.xpm" //#include"iconVertiSplit.xpm" #include"iconLeaveFullScreen.xpm" #include #ifdef QMITK_USE_EXTERNAL_RENDERWINDOW_MENU QmitkRenderWindowMenu::QmitkRenderWindowMenu(QWidget *parent, Qt::WindowFlags f, mitk::BaseRenderer *b, QmitkStdMultiWidget* mw ) :QWidget(parent, Qt::Tool | Qt::FramelessWindowHint ), #else QmitkRenderWindowMenu::QmitkRenderWindowMenu(QWidget *parent, Qt::WindowFlags f, mitk::BaseRenderer *b, QmitkStdMultiWidget* mw ) :QWidget(parent,f), #endif m_Settings(NULL), m_CrosshairMenu(NULL), m_Layout(0), m_LayoutDesign(0), m_OldLayoutDesign(0), m_FullScreenMode(false), m_Entered(false), m_Hidden(true), m_Renderer(b), m_MultiWidget(mw) { MITK_DEBUG << "creating renderwindow menu on baserenderer " << b; this->setFocusPolicy( Qt::NoFocus ); //Create Menu Widget this->CreateMenuWidget(); this->setMinimumWidth(61); //DIRTY.. If you add or remove a button, you need to change the size. this->setMaximumWidth(61); this->setAutoFillBackground( true ); - this->show(); - this->setWindowOpacity(0.0); +// this->show(); + this->setVisible(false); +// this->setWindowOpacity(0.0); //this->setAttribute( Qt::WA_NoSystemBackground ); //this->setBackgroundRole( QPalette::Dark ); //this->update(); //SetOpacity -- its just posible if the widget is a window. //Windows indicates that the widget is a window, usually with a window system frame and a title bar, //irrespective of whether the widget has a parent or not. /* this->setWindowFlags( Qt::Window | Qt::FramelessWindowHint); */ //this->setAttribute(Qt::WA_TranslucentBackground); //this->setWindowOpacity(0.75); currentCrosshairRotationMode = 0; // for autorotating m_AutoRotationTimer.setInterval( 75 ); connect( &m_AutoRotationTimer, SIGNAL(timeout()), this, SLOT(AutoRotateNextStep()) ); } QmitkRenderWindowMenu::~QmitkRenderWindowMenu() { if( m_AutoRotationTimer.isActive() ) m_AutoRotationTimer.stop(); } void QmitkRenderWindowMenu::CreateMenuWidget() { QHBoxLayout* layout = new QHBoxLayout(this); layout->setAlignment( Qt::AlignRight ); layout->setContentsMargins(1,1,1,1); QSize size( 13, 13 ); m_CrosshairMenu = new QMenu(this); connect( m_CrosshairMenu, SIGNAL( aboutToShow() ), this, SLOT(OnCrossHairMenuAboutToShow()) ); // button for changing rotation mode m_CrosshairModeButton = new QPushButton(this); m_CrosshairModeButton->setMaximumSize(15, 15); m_CrosshairModeButton->setIconSize(size); m_CrosshairModeButton->setFlat( true ); m_CrosshairModeButton->setMenu( m_CrosshairMenu ); m_CrosshairModeButton->setIcon( QIcon( iconCrosshairMode_xpm ) ); layout->addWidget( m_CrosshairModeButton ); //fullScreenButton m_FullScreenButton = new QPushButton(this); m_FullScreenButton->setMaximumSize(15, 15); m_FullScreenButton->setIconSize(size); m_FullScreenButton->setFlat( true ); m_FullScreenButton->setIcon( QIcon( iconFullScreen_xpm )); layout->addWidget( m_FullScreenButton ); //settingsButton m_SettingsButton = new QPushButton(this); m_SettingsButton->setMaximumSize(15, 15); m_SettingsButton->setIconSize(size); m_SettingsButton->setFlat( true ); m_SettingsButton->setIcon( QIcon( iconSettings_xpm )); layout->addWidget( m_SettingsButton ); //Create Connections -- coming soon? connect( m_FullScreenButton, SIGNAL( clicked(bool) ), this, SLOT(OnFullScreenButton(bool)) ); connect( m_SettingsButton, SIGNAL( clicked(bool) ), this, SLOT(OnSettingsButton(bool)) ); } void QmitkRenderWindowMenu::CreateSettingsWidget() { m_Settings = new QMenu(this); m_DefaultLayoutAction = new QAction( "standard layout", m_Settings ); m_DefaultLayoutAction->setDisabled( true ); m_2DImagesUpLayoutAction = new QAction( "2D images top, 3D bottom", m_Settings ); m_2DImagesUpLayoutAction->setDisabled( false ); m_2DImagesLeftLayoutAction = new QAction( "2D images left, 3D right", m_Settings ); m_2DImagesLeftLayoutAction->setDisabled( false ); m_Big3DLayoutAction = new QAction( "Big 3D", m_Settings ); m_Big3DLayoutAction->setDisabled( false ); m_Widget1LayoutAction = new QAction( "Transversal plane", m_Settings ); m_Widget1LayoutAction->setDisabled( false ); m_Widget2LayoutAction = new QAction( "Sagittal plane", m_Settings ); m_Widget2LayoutAction->setDisabled( false ); m_Widget3LayoutAction = new QAction( "Coronal plane", m_Settings ); m_Widget3LayoutAction->setDisabled( false ); m_RowWidget3And4LayoutAction = new QAction( "Coronal top, 3D bottom", m_Settings ); m_RowWidget3And4LayoutAction->setDisabled( false ); m_ColumnWidget3And4LayoutAction = new QAction( "Coronal left, 3D right", m_Settings ); m_ColumnWidget3And4LayoutAction->setDisabled( false ); m_SmallUpperWidget2Big3and4LayoutAction = new QAction( "Sagittal top, Coronal n 3D bottom", m_Settings ); m_SmallUpperWidget2Big3and4LayoutAction->setDisabled( false ); m_2x2Dand3DWidgetLayoutAction = new QAction( "Transversal n Sagittal left, 3D right", m_Settings ); m_2x2Dand3DWidgetLayoutAction->setDisabled( false ); m_Left2Dand3DRight2DLayoutAction = new QAction( "Transversal n 3D left, Sagittal right", m_Settings ); m_Left2Dand3DRight2DLayoutAction->setDisabled( false ); m_Settings->addAction(m_DefaultLayoutAction); m_Settings->addAction(m_2DImagesUpLayoutAction); m_Settings->addAction(m_2DImagesLeftLayoutAction); m_Settings->addAction(m_Big3DLayoutAction); m_Settings->addAction(m_Widget1LayoutAction); m_Settings->addAction(m_Widget2LayoutAction); m_Settings->addAction(m_Widget3LayoutAction); m_Settings->addAction(m_RowWidget3And4LayoutAction); m_Settings->addAction(m_ColumnWidget3And4LayoutAction); m_Settings->addAction(m_SmallUpperWidget2Big3and4LayoutAction); m_Settings->addAction(m_2x2Dand3DWidgetLayoutAction); m_Settings->addAction(m_Left2Dand3DRight2DLayoutAction); m_Settings->setVisible( false ); connect( m_DefaultLayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToDefault(bool)) ); connect( m_2DImagesUpLayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutTo2DImagesUp(bool)) ); connect( m_2DImagesLeftLayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutTo2DImagesLeft(bool)) ); connect( m_Big3DLayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToBig3D(bool)) ); connect( m_Widget1LayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToWidget1(bool)) ); connect( m_Widget2LayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToWidget2(bool)) ); connect( m_Widget3LayoutAction , SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToWidget3(bool)) ); connect( m_RowWidget3And4LayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToRowWidget3And4(bool)) ); connect( m_ColumnWidget3And4LayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToColumnWidget3And4(bool)) ); connect( m_SmallUpperWidget2Big3and4LayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToSmallUpperWidget2Big3and4(bool)) ); connect( m_2x2Dand3DWidgetLayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutTo2x2Dand3DWidget(bool)) ); connect( m_Left2Dand3DRight2DLayoutAction, SIGNAL( triggered(bool) ), this, SLOT(OnChangeLayoutToLeft2Dand3DRight2D(bool)) ); } void QmitkRenderWindowMenu::paintEvent( QPaintEvent* /*e*/ ) { QPainter painter(this); QColor semiTransparentColor = Qt::black; semiTransparentColor.setAlpha(255); painter.fillRect(rect(), semiTransparentColor); } void QmitkRenderWindowMenu::SetLayoutIndex( unsigned int layoutIndex ) { m_Layout = layoutIndex; } void QmitkRenderWindowMenu::HideMenu( ) { MITK_DEBUG << "menu hideEvent"; m_Hidden = true; if( ! m_Entered ) - setWindowOpacity(0.0f); - //hide(); + setVisible(false); +// setWindowOpacity(0.0f); +// hide(); } void QmitkRenderWindowMenu::ShowMenu( ) { MITK_DEBUG << "menu showMenu"; m_Hidden = false; - setWindowOpacity(1.0f); + setVisible(true); +// setWindowOpacity(1.0f); } void QmitkRenderWindowMenu::enterEvent( QEvent * /*e*/ ) { MITK_DEBUG << "menu enterEvent"; m_Entered=true; m_Hidden=false; // setWindowOpacity(1.0f); } void QmitkRenderWindowMenu::DeferredHideMenu( ) { MITK_DEBUG << "menu deferredhidemenu"; if(m_Hidden) - setWindowOpacity(0.0f); + setVisible(false); +// setWindowOpacity(0.0f); ///hide(); } void QmitkRenderWindowMenu::leaveEvent( QEvent * /*e*/ ) { MITK_DEBUG << "menu leaveEvent"; smoothHide(); } /* This method is responsible for non fluttering of the renderWindowMenu when mouse cursor moves along the renderWindowMenu*/ void QmitkRenderWindowMenu::smoothHide() { MITK_DEBUG<< "menu leaveEvent"; m_Entered=false; m_Hidden = true; QTimer::singleShot(10,this,SLOT( DeferredHideMenu( ) ) ); } void QmitkRenderWindowMenu::ChangeFullScreenMode( bool state ) { this->OnFullScreenButton( state ); } /// \brief void QmitkRenderWindowMenu::OnFullScreenButton( bool /*checked*/ ) { if( !m_FullScreenMode ) { m_FullScreenMode = true; m_OldLayoutDesign = m_LayoutDesign; switch( m_Layout ) { case TRANSVERSAL: { emit SignalChangeLayoutDesign( LAYOUT_TRANSVERSAL ); break; } case SAGITTAL: { emit SignalChangeLayoutDesign( LAYOUT_SAGITTAL ); break; } case CORONAL: { emit SignalChangeLayoutDesign( LAYOUT_CORONAL ); break; } case THREE_D: { emit SignalChangeLayoutDesign( LAYOUT_BIG3D ); break; } } //Move Widget and show again this->MoveWidgetToCorrectPos(1.0f); //change icon this->ChangeFullScreenIcon(); } else { m_FullScreenMode = false; emit SignalChangeLayoutDesign( m_OldLayoutDesign ); //Move Widget and show again this->MoveWidgetToCorrectPos(1.0f); //change icon this->ChangeFullScreenIcon(); } DeferredShowMenu( ); } /// \brief void QmitkRenderWindowMenu::OnSettingsButton( bool /*checked*/ ) { if( m_Settings == NULL ) this->CreateSettingsWidget(); QPoint point = this->mapToGlobal( m_SettingsButton->geometry().topLeft() ); m_Settings->setVisible( true ); m_Settings->exec( point ); } void QmitkRenderWindowMenu::OnChangeLayoutTo2DImagesUp(bool) { //set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_2DIMAGEUP; emit SignalChangeLayoutDesign( LAYOUT_2DIMAGEUP ); DeferredShowMenu( ); } void QmitkRenderWindowMenu::OnChangeLayoutTo2DImagesLeft(bool) { //set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_2DIMAGELEFT; emit SignalChangeLayoutDesign( LAYOUT_2DIMAGELEFT ); DeferredShowMenu( ); } void QmitkRenderWindowMenu::OnChangeLayoutToDefault(bool) { //set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_DEFAULT; emit SignalChangeLayoutDesign( LAYOUT_DEFAULT ); DeferredShowMenu( ); } void QmitkRenderWindowMenu::DeferredShowMenu() { MITK_DEBUG << "deferred show menu"; show(); - setWindowOpacity(1.0); + setVisible(true); +// setWindowOpacity(1.0); } void QmitkRenderWindowMenu::OnChangeLayoutToBig3D(bool) { MITK_DEBUG << "OnChangeLayoutToBig3D"; //set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_BIG3D; emit SignalChangeLayoutDesign( LAYOUT_BIG3D ); DeferredShowMenu( ); } void QmitkRenderWindowMenu::OnChangeLayoutToWidget1(bool) { //set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_TRANSVERSAL; emit SignalChangeLayoutDesign( LAYOUT_TRANSVERSAL ); DeferredShowMenu( ); } void QmitkRenderWindowMenu::OnChangeLayoutToWidget2(bool) { //set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_SAGITTAL; emit SignalChangeLayoutDesign( LAYOUT_SAGITTAL ); DeferredShowMenu( ); } void QmitkRenderWindowMenu::OnChangeLayoutToWidget3(bool) { //set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_CORONAL; emit SignalChangeLayoutDesign( LAYOUT_CORONAL ); DeferredShowMenu( ); } void QmitkRenderWindowMenu::OnChangeLayoutToRowWidget3And4(bool) { //set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_ROWWIDGET3AND4; emit SignalChangeLayoutDesign( LAYOUT_ROWWIDGET3AND4 ); DeferredShowMenu( ); } void QmitkRenderWindowMenu::OnChangeLayoutToColumnWidget3And4(bool) { //set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_COLUMNWIDGET3AND4; emit SignalChangeLayoutDesign( LAYOUT_COLUMNWIDGET3AND4 ); DeferredShowMenu( ); } void QmitkRenderWindowMenu::OnChangeLayoutToSmallUpperWidget2Big3and4(bool) { //set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_SMALLUPPERWIDGET2BIGAND4; emit SignalChangeLayoutDesign( LAYOUT_SMALLUPPERWIDGET2BIGAND4 ); DeferredShowMenu( ); } void QmitkRenderWindowMenu::OnChangeLayoutTo2x2Dand3DWidget(bool) { //set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_2X2DAND3DWIDGET; emit SignalChangeLayoutDesign( LAYOUT_2X2DAND3DWIDGET ); DeferredShowMenu( ); } void QmitkRenderWindowMenu::OnChangeLayoutToLeft2Dand3DRight2D(bool) { //set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_LEFT2DAND3DRIGHT2D; emit SignalChangeLayoutDesign( LAYOUT_LEFT2DAND3DRIGHT2D ); DeferredShowMenu( ); } void QmitkRenderWindowMenu::UpdateLayoutDesignList( int layoutDesignIndex ) { m_LayoutDesign = layoutDesignIndex; if( m_Settings == NULL ) this->CreateSettingsWidget(); switch( m_LayoutDesign ) { case LAYOUT_DEFAULT: { m_DefaultLayoutAction->setEnabled(false); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_2DIMAGEUP: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(false); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_2DIMAGELEFT: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(false); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_BIG3D: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(false); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_TRANSVERSAL: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(false); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_SAGITTAL: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(false); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_CORONAL: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(false); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_2X2DAND3DWIDGET: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(false); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_ROWWIDGET3AND4: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(false); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_COLUMNWIDGET3AND4: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(false); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_SMALLUPPERWIDGET2BIGAND4: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(false); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_LEFT2DAND3DRIGHT2D: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(false); break; } } } #ifdef QMITK_USE_EXTERNAL_RENDERWINDOW_MENU void QmitkRenderWindowMenu::MoveWidgetToCorrectPos(float opacity) #else void QmitkRenderWindowMenu::MoveWidgetToCorrectPos(float /*opacity*/) #endif { #ifdef QMITK_USE_EXTERNAL_RENDERWINDOW_MENU int X=floor( double(this->parentWidget()->width() - this->width() - 8.0) ); int Y=7; QPoint pos = this->parentWidget()->mapToGlobal( QPoint(0,0) ); this->move( X+pos.x(), Y+pos.y() ); if(opacity<0) opacity=0; else if(opacity>1) opacity=1; this->setWindowOpacity(opacity); #else int moveX= floor( double(this->parentWidget()->width() - this->width() - 4.0) ); this->move( moveX, 3 ); this->show(); #endif } void QmitkRenderWindowMenu::ChangeFullScreenIcon() { if( m_FullScreenMode ) { const QIcon icon( iconLeaveFullScreen_xpm ); m_FullScreenButton->setIcon(icon); } else { const QIcon icon( iconFullScreen_xpm ); m_FullScreenButton->setIcon(icon); } } void QmitkRenderWindowMenu::OnCrosshairRotationModeSelected(QAction* action) { MITK_DEBUG << "selected crosshair mode " << action->data().toInt() ; emit ChangeCrosshairRotationMode( action->data().toInt() ); } void QmitkRenderWindowMenu::SetCrossHairVisibility( bool state ) { if(m_Renderer.IsNotNull()) { mitk::DataNode *n; if(this->m_MultiWidget) { n = this->m_MultiWidget->GetWidgetPlane1(); if(n) n->SetVisibility(state); n = this->m_MultiWidget->GetWidgetPlane2(); if(n) n->SetVisibility(state); n = this->m_MultiWidget->GetWidgetPlane3(); if(n) n->SetVisibility(state); m_Renderer->GetRenderingManager()->RequestUpdateAll(); } } } void QmitkRenderWindowMenu::OnTSNumChanged(int num) { MITK_DEBUG << "Thickslices num: " << num << " on renderer " << m_Renderer.GetPointer(); if(m_Renderer.IsNotNull()) { if(num==0) { m_Renderer->GetCurrentWorldGeometry2DNode()->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 0 ) ); m_Renderer->GetCurrentWorldGeometry2DNode()->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( false ) ); } else { m_Renderer->GetCurrentWorldGeometry2DNode()->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 1 ) ); m_Renderer->GetCurrentWorldGeometry2DNode()->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) ); m_Renderer->GetCurrentWorldGeometry2DNode()->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( num > 1 ) ); } m_TSLabel->setText(QString::number(num*2+1)); m_Renderer->SendUpdateSlice(); m_Renderer->GetRenderingManager()->RequestUpdateAll(); } } void QmitkRenderWindowMenu::OnCrossHairMenuAboutToShow() { QMenu *crosshairModesMenu = m_CrosshairMenu; crosshairModesMenu->clear(); QAction* resetViewAction = new QAction(crosshairModesMenu); resetViewAction->setText("Reset view"); crosshairModesMenu->addAction( resetViewAction ); connect( resetViewAction, SIGNAL(triggered()), this, SIGNAL(ResetView())); // Show hide crosshairs { bool currentState = true; if(m_Renderer.IsNotNull()) { mitk::DataStorage *ds=m_Renderer->GetDataStorage(); mitk::DataNode *n; if(ds) { n = this->m_MultiWidget->GetWidgetPlane1(); if(n) { bool v; if(n->GetVisibility(v,0)) currentState&=v; } n = this->m_MultiWidget->GetWidgetPlane2(); if(n) { bool v; if(n->GetVisibility(v,0)) currentState&=v; } n = this->m_MultiWidget->GetWidgetPlane3(); if(n) { bool v; if(n->GetVisibility(v,0)) currentState&=v; } } } QAction* showHideCrosshairVisibilityAction = new QAction(crosshairModesMenu); showHideCrosshairVisibilityAction->setText("Show crosshair"); showHideCrosshairVisibilityAction->setCheckable(true); showHideCrosshairVisibilityAction->setChecked(currentState); crosshairModesMenu->addAction( showHideCrosshairVisibilityAction ); connect( showHideCrosshairVisibilityAction, SIGNAL(toggled(bool)), this, SLOT(SetCrossHairVisibility(bool))); } // Rotation mode { QAction* rotationGroupSeparator = new QAction(crosshairModesMenu); rotationGroupSeparator->setSeparator(true); rotationGroupSeparator->setText("Rotation mode"); crosshairModesMenu->addAction( rotationGroupSeparator ); QActionGroup* rotationModeActionGroup = new QActionGroup(crosshairModesMenu); rotationModeActionGroup->setExclusive(true); QAction* noCrosshairRotation = new QAction(crosshairModesMenu); noCrosshairRotation->setActionGroup(rotationModeActionGroup); noCrosshairRotation->setText("No crosshair rotation"); noCrosshairRotation->setCheckable(true); noCrosshairRotation->setChecked(currentCrosshairRotationMode==0); noCrosshairRotation->setData( 0 ); crosshairModesMenu->addAction( noCrosshairRotation ); QAction* singleCrosshairRotation = new QAction(crosshairModesMenu); singleCrosshairRotation->setActionGroup(rotationModeActionGroup); singleCrosshairRotation->setText("Crosshair rotation"); singleCrosshairRotation->setCheckable(true); singleCrosshairRotation->setChecked(currentCrosshairRotationMode==1); singleCrosshairRotation->setData( 1 ); crosshairModesMenu->addAction( singleCrosshairRotation ); QAction* coupledCrosshairRotation = new QAction(crosshairModesMenu); coupledCrosshairRotation->setActionGroup(rotationModeActionGroup); coupledCrosshairRotation->setText("Coupled crosshair rotation"); coupledCrosshairRotation->setCheckable(true); coupledCrosshairRotation->setChecked(currentCrosshairRotationMode==2); coupledCrosshairRotation->setData( 2 ); crosshairModesMenu->addAction( coupledCrosshairRotation ); QAction* swivelMode = new QAction(crosshairModesMenu); swivelMode->setActionGroup(rotationModeActionGroup); swivelMode->setText("Swivel mode"); swivelMode->setCheckable(true); swivelMode->setChecked(currentCrosshairRotationMode==3); swivelMode->setData( 3 ); crosshairModesMenu->addAction( swivelMode ); connect( rotationModeActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(OnCrosshairRotationModeSelected(QAction*)) ); } // auto rotation support if( m_Renderer.IsNotNull() && m_Renderer->GetMapperID() == mitk::BaseRenderer::Standard3D ) { QAction* autoRotationGroupSeparator = new QAction(crosshairModesMenu); autoRotationGroupSeparator->setSeparator(true); crosshairModesMenu->addAction( autoRotationGroupSeparator ); QAction* autoRotationAction = crosshairModesMenu->addAction( "Auto Rotation" ); autoRotationAction->setCheckable(true); autoRotationAction->setChecked( m_AutoRotationTimer.isActive() ); connect( autoRotationAction, SIGNAL(triggered()), this, SLOT(OnAutoRotationActionTriggered()) ); } // Thickslices support if( m_Renderer.IsNotNull() && m_Renderer->GetMapperID() == mitk::BaseRenderer::Standard2D ) { QAction* thickSlicesGroupSeparator = new QAction(crosshairModesMenu); thickSlicesGroupSeparator->setSeparator(true); thickSlicesGroupSeparator->setText("ThickSlices mode"); crosshairModesMenu->addAction( thickSlicesGroupSeparator ); QActionGroup* thickSlicesActionGroup = new QActionGroup(crosshairModesMenu); thickSlicesActionGroup->setExclusive(true); int currentMode = 0; { mitk::ResliceMethodProperty::Pointer m = dynamic_cast(m_Renderer->GetCurrentWorldGeometry2DNode()->GetProperty( "reslice.thickslices" )); if( m.IsNotNull() ) currentMode = m->GetValueAsId(); } int currentNum = 1; { mitk::IntProperty::Pointer m = dynamic_cast(m_Renderer->GetCurrentWorldGeometry2DNode()->GetProperty( "reslice.thickslices.num" )); if( m.IsNotNull() ) { currentNum = m->GetValue(); if(currentNum < 1) currentNum = 1; if(currentNum > 10) currentNum = 10; } } if(currentMode==0) currentNum=0; QSlider *m_TSSlider = new QSlider(crosshairModesMenu); m_TSSlider->setMinimum(0); m_TSSlider->setMaximum(9); m_TSSlider->setValue(currentNum); m_TSSlider->setOrientation(Qt::Horizontal); connect( m_TSSlider, SIGNAL( valueChanged(int) ), this, SLOT( OnTSNumChanged(int) ) ); QHBoxLayout* _TSLayout = new QHBoxLayout; _TSLayout->setContentsMargins(4,4,4,4); _TSLayout->addWidget(new QLabel("TS: ")); _TSLayout->addWidget(m_TSSlider); _TSLayout->addWidget(m_TSLabel=new QLabel(QString::number(currentNum*2+1),this)); QWidget* _TSWidget = new QWidget; _TSWidget->setLayout(_TSLayout); QWidgetAction *m_TSSliderAction = new QWidgetAction(crosshairModesMenu); m_TSSliderAction->setDefaultWidget(_TSWidget); crosshairModesMenu->addAction(m_TSSliderAction); } } void QmitkRenderWindowMenu::NotifyNewWidgetPlanesMode( int mode ) { currentCrosshairRotationMode = mode; } void QmitkRenderWindowMenu::OnAutoRotationActionTriggered() { if(m_AutoRotationTimer.isActive()) { m_AutoRotationTimer.stop(); m_Renderer->GetCameraRotationController()->GetSlice()->PingPongOff(); } else { m_Renderer->GetCameraRotationController()->GetSlice()->PingPongOn(); m_AutoRotationTimer.start(); } } void QmitkRenderWindowMenu::AutoRotateNextStep() { if(m_Renderer->GetCameraRotationController()) m_Renderer->GetCameraRotationController()->GetSlice()->Next(); } diff --git a/Modules/QmitkExt/QmitkSlicesInterpolator.cpp b/Modules/QmitkExt/QmitkSlicesInterpolator.cpp index 0fc5c3d1a2..c1e943d86b 100644 --- a/Modules/QmitkExt/QmitkSlicesInterpolator.cpp +++ b/Modules/QmitkExt/QmitkSlicesInterpolator.cpp @@ -1,993 +1,1008 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2008-10-30 12:33:31 +0100 (Do, 30 Okt 2008) $ Version: $Revision: 15606 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkSlicesInterpolator.h" #include "QmitkStdMultiWidget.h" #include "QmitkSelectableGLWidget.h" #include "mitkToolManager.h" #include "mitkDataNodeFactory.h" #include "mitkLevelWindowProperty.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkRenderingManager.h" #include "mitkOverwriteSliceImageFilter.h" #include "mitkProgressBar.h" #include "mitkGlobalInteraction.h" #include "mitkOperationEvent.h" #include "mitkUndoController.h" #include "mitkInteractionConst.h" #include "mitkApplyDiffImageOperation.h" #include "mitkDiffImageApplier.h" #include "mitkSegTool2D.h" #include "mitkCoreObjectFactory.h" #include "mitkSurfaceToImageFilter.h" #include #include #include #include #include #include #include #define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a))) const std::map QmitkSlicesInterpolator::createActionToSliceDimension() { std::map actionToSliceDimension; actionToSliceDimension[new QAction("Transversal (red window)", 0)] = 2; actionToSliceDimension[new QAction("Sagittal (green window)", 0)] = 0; actionToSliceDimension[new QAction("Coronal (blue window)", 0)] = 1; return actionToSliceDimension; } QmitkSlicesInterpolator::QmitkSlicesInterpolator(QWidget* parent, const char* /*name*/) :QWidget(parent), ACTION_TO_SLICEDIMENSION( createActionToSliceDimension() ), m_Interpolator( mitk::SegmentationInterpolationController::New() ), m_MultiWidget(NULL), m_ToolManager(NULL), m_Initialized(false), m_LastSliceDimension(2), m_LastSliceIndex(0), m_2DInterpolationEnabled(false), m_3DInterpolationEnabled(false) { m_SurfaceInterpolator = mitk::SurfaceInterpolationController::GetInstance(); QHBoxLayout* layout = new QHBoxLayout(this); m_GroupBoxEnableExclusiveInterpolationMode = new QGroupBox("Interpolation", this); QGridLayout* grid = new QGridLayout(m_GroupBoxEnableExclusiveInterpolationMode); m_RBtnEnable3DInterpolation = new QRadioButton("3D",this); connect(m_RBtnEnable3DInterpolation, SIGNAL(toggled(bool)), this, SLOT(On3DInterpolationEnabled(bool))); connect(m_RBtnEnable3DInterpolation, SIGNAL(toggled(bool)), this, SIGNAL(Signal3DInterpolationEnabled(bool))); m_RBtnEnable3DInterpolation->setChecked(true); grid->addWidget(m_RBtnEnable3DInterpolation,0,0); m_BtnAccept3DInterpolation = new QPushButton("Accept", this); m_BtnAccept3DInterpolation->setEnabled(false); connect(m_BtnAccept3DInterpolation, SIGNAL(clicked()), this, SLOT(OnAccept3DInterpolationClicked())); grid->addWidget(m_BtnAccept3DInterpolation, 0,1); m_CbShowMarkers = new QCheckBox("Show Position Nodes", this); m_CbShowMarkers->setChecked(true); connect(m_CbShowMarkers, SIGNAL(toggled(bool)), this, SLOT(OnShowMarkers(bool))); connect(m_CbShowMarkers, SIGNAL(toggled(bool)), this, SIGNAL(SignalShowMarkerNodes(bool))); grid->addWidget(m_CbShowMarkers,0,2); m_RBtnEnable2DInterpolation = new QRadioButton("2D",this); connect(m_RBtnEnable2DInterpolation, SIGNAL(toggled(bool)), this, SLOT(On2DInterpolationEnabled(bool))); grid->addWidget(m_RBtnEnable2DInterpolation,1,0); m_BtnAcceptInterpolation = new QPushButton("Accept", this); m_BtnAcceptInterpolation->setEnabled( false ); connect( m_BtnAcceptInterpolation, SIGNAL(clicked()), this, SLOT(OnAcceptInterpolationClicked()) ); grid->addWidget(m_BtnAcceptInterpolation,1,1); m_BtnAcceptAllInterpolations = new QPushButton("... for all slices", this); m_BtnAcceptAllInterpolations->setEnabled( false ); connect( m_BtnAcceptAllInterpolations, SIGNAL(clicked()), this, SLOT(OnAcceptAllInterpolationsClicked()) ); grid->addWidget(m_BtnAcceptAllInterpolations,1,2); m_RBtnDisableInterpolation = new QRadioButton("Disable", this); connect(m_RBtnDisableInterpolation, SIGNAL(toggled(bool)), this, SLOT(OnInterpolationDisabled(bool))); grid->addWidget(m_RBtnDisableInterpolation, 2,0); layout->addWidget(m_GroupBoxEnableExclusiveInterpolationMode); this->setLayout(layout); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnInterpolationInfoChanged ); InterpolationInfoChangedObserverTag = m_Interpolator->AddObserver( itk::ModifiedEvent(), command ); itk::ReceptorMemberCommand::Pointer command2 = itk::ReceptorMemberCommand::New(); command2->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged ); SurfaceInterpolationInfoChangedObserverTag = m_SurfaceInterpolator->AddObserver( itk::ModifiedEvent(), command2 ); // feedback node and its visualization properties m_FeedbackNode = mitk::DataNode::New(); mitk::CoreObjectFactory::GetInstance()->SetDefaultProperties( m_FeedbackNode ); m_FeedbackNode->SetProperty( "binary", mitk::BoolProperty::New(true) ); m_FeedbackNode->SetProperty( "outline binary", mitk::BoolProperty::New(true) ); m_FeedbackNode->SetProperty( "color", mitk::ColorProperty::New(255.0, 255.0, 0.0) ); m_FeedbackNode->SetProperty( "texture interpolation", mitk::BoolProperty::New(false) ); m_FeedbackNode->SetProperty( "layer", mitk::IntProperty::New( 20 ) ); m_FeedbackNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( mitk::LevelWindow(0, 1) ) ); m_FeedbackNode->SetProperty( "name", mitk::StringProperty::New("Interpolation feedback") ); m_FeedbackNode->SetProperty( "opacity", mitk::FloatProperty::New(0.8) ); m_FeedbackNode->SetProperty( "helper object", mitk::BoolProperty::New(true) ); m_InterpolatedSurfaceNode = mitk::DataNode::New(); m_InterpolatedSurfaceNode->SetProperty( "color", mitk::ColorProperty::New(255.0,255.0,0.0) ); m_InterpolatedSurfaceNode->SetProperty( "name", mitk::StringProperty::New("Surface Interpolation feedback") ); m_InterpolatedSurfaceNode->SetProperty( "opacity", mitk::FloatProperty::New(0.5) ); m_InterpolatedSurfaceNode->SetProperty( "includeInBoundingBox", mitk::BoolProperty::New(false)); m_InterpolatedSurfaceNode->SetProperty( "helper object", mitk::BoolProperty::New(true) ); m_InterpolatedSurfaceNode->SetVisibility(false); m_3DContourNode = mitk::DataNode::New(); m_3DContourNode->SetProperty( "color", mitk::ColorProperty::New(0.0, 0.0, 0.0) ); m_3DContourNode->SetProperty("helper object", mitk::BoolProperty::New(true)); m_3DContourNode->SetProperty( "name", mitk::StringProperty::New("Drawn Contours") ); m_3DContourNode->SetProperty("material.representation", mitk::VtkRepresentationProperty::New(VTK_WIREFRAME)); m_3DContourNode->SetProperty("material.wireframeLineWidth", mitk::FloatProperty::New(2.0f)); m_3DContourNode->SetProperty("3DContourContainer", mitk::BoolProperty::New(true)); m_3DContourNode->SetProperty( "includeInBoundingBox", mitk::BoolProperty::New(false)); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1"))); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget2"))); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); QWidget::setContentsMargins(0, 0, 0, 0); if ( QWidget::layout() != NULL ) { QWidget::layout()->setContentsMargins(0, 0, 0, 0); } //For running 3D Interpolation in background // create a QFuture and a QFutureWatcher connect(&m_Watcher, SIGNAL(started()), this, SLOT(StartUpdateInterpolationTimer())); connect(&m_Watcher, SIGNAL(finished()), this, SLOT(SurfaceInterpolationFinished())); connect(&m_Watcher, SIGNAL(finished()), this, SLOT(StopUpdateInterpolationTimer())); m_Timer = new QTimer(this); connect(m_Timer, SIGNAL(timeout()), this, SLOT(ChangeSurfaceColor())); } void QmitkSlicesInterpolator::SetDataStorage( mitk::DataStorage& storage ) { m_DataStorage = &storage; m_SurfaceInterpolator->SetDataStorage(storage); } mitk::DataStorage* QmitkSlicesInterpolator::GetDataStorage() { if ( m_DataStorage.IsNotNull() ) { return m_DataStorage; } else { return NULL; } } void QmitkSlicesInterpolator::Initialize(mitk::ToolManager* toolManager, QmitkStdMultiWidget* multiWidget) { if (m_Initialized) { // remove old observers if (m_ToolManager) { m_ToolManager->WorkingDataChanged -= mitk::MessageDelegate( this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified ); m_ToolManager->ReferenceDataChanged -= mitk::MessageDelegate( this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified ); } if (m_MultiWidget) { disconnect( m_MultiWidget, SIGNAL(destroyed(QObject*)), this, SLOT(OnMultiWidgetDeleted(QObject*)) ); mitk::SliceNavigationController* slicer = m_MultiWidget->mitkWidget1->GetSliceNavigationController(); slicer->RemoveObserver( TSliceObserverTag ); slicer->RemoveObserver( TTimeObserverTag ); slicer = m_MultiWidget->mitkWidget2->GetSliceNavigationController(); slicer->RemoveObserver( SSliceObserverTag ); slicer->RemoveObserver( STimeObserverTag ); slicer = m_MultiWidget->mitkWidget3->GetSliceNavigationController(); slicer->RemoveObserver( FSliceObserverTag ); slicer->RemoveObserver( FTimeObserverTag ); } //return; } m_MultiWidget = multiWidget; connect( m_MultiWidget, SIGNAL(destroyed(QObject*)), this, SLOT(OnMultiWidgetDeleted(QObject*)) ); m_ToolManager = toolManager; if (m_ToolManager) { // set enabled only if a segmentation is selected mitk::DataNode* node = m_ToolManager->GetWorkingData(0); QWidget::setEnabled( node != NULL ); // react whenever the set of selected segmentation changes m_ToolManager->WorkingDataChanged += mitk::MessageDelegate( this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified ); m_ToolManager->ReferenceDataChanged += mitk::MessageDelegate( this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified ); // connect to the steppers of the three multi widget widgets. after each change, call the interpolator if (m_MultiWidget) { mitk::SliceNavigationController* slicer = m_MultiWidget->mitkWidget1->GetSliceNavigationController(); m_TimeStep.resize(3); m_TimeStep[2] = slicer->GetTime()->GetPos(); { itk::MemberCommand::Pointer command = itk::MemberCommand::New(); command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnTransversalTimeChanged ); TTimeObserverTag = slicer->AddObserver( mitk::SliceNavigationController::GeometryTimeEvent(NULL, 0), command ); } { itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnTransversalSliceChanged ); TSliceObserverTag = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(NULL, 0), command ); } // connect to the steppers of the three multi widget widgets. after each change, call the interpolator slicer = m_MultiWidget->mitkWidget2->GetSliceNavigationController(); m_TimeStep[0] = slicer->GetTime()->GetPos(); { itk::MemberCommand::Pointer command = itk::MemberCommand::New(); command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSagittalTimeChanged ); STimeObserverTag = slicer->AddObserver( mitk::SliceNavigationController::GeometryTimeEvent(NULL, 0), command ); } { itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSagittalSliceChanged ); SSliceObserverTag = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(NULL, 0), command ); } // connect to the steppers of the three multi widget widgets. after each change, call the interpolator slicer = m_MultiWidget->mitkWidget3->GetSliceNavigationController(); m_TimeStep[1] = slicer->GetTime()->GetPos(); { itk::MemberCommand::Pointer command = itk::MemberCommand::New(); command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnFrontalTimeChanged ); FTimeObserverTag = slicer->AddObserver( mitk::SliceNavigationController::GeometryTimeEvent(NULL, 0), command ); } { itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnFrontalSliceChanged ); FSliceObserverTag = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(NULL, 0), command ); } } } m_Initialized = true; } QmitkSlicesInterpolator::~QmitkSlicesInterpolator() { if (m_MultiWidget) { mitk::SliceNavigationController* slicer; if(m_MultiWidget->mitkWidget1 != NULL) { slicer = m_MultiWidget->mitkWidget1->GetSliceNavigationController(); slicer->RemoveObserver( TSliceObserverTag ); slicer->RemoveObserver( TTimeObserverTag ); } if(m_MultiWidget->mitkWidget2 != NULL) { slicer = m_MultiWidget->mitkWidget2->GetSliceNavigationController(); slicer->RemoveObserver( SSliceObserverTag ); slicer->RemoveObserver( STimeObserverTag ); } if(m_MultiWidget->mitkWidget3 != NULL) { slicer = m_MultiWidget->mitkWidget3->GetSliceNavigationController(); slicer->RemoveObserver( FSliceObserverTag ); slicer->RemoveObserver( FTimeObserverTag ); } } if(m_DataStorage->Exists(m_3DContourNode)) m_DataStorage->Remove(m_3DContourNode); if(m_DataStorage->Exists(m_InterpolatedSurfaceNode)) m_DataStorage->Remove(m_InterpolatedSurfaceNode); delete m_Timer; } void QmitkSlicesInterpolator::On2DInterpolationEnabled(bool status) { OnInterpolationActivated(status); } void QmitkSlicesInterpolator::On3DInterpolationEnabled(bool status) { On3DInterpolationActivated(status); } void QmitkSlicesInterpolator::OnInterpolationDisabled(bool status) { if (status) { OnInterpolationActivated(!status); On3DInterpolationActivated(!status); } } void QmitkSlicesInterpolator::OnShowMarkers(bool state) { mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers = m_DataStorage->GetSubset(mitk::NodePredicateProperty::New("isContourMarker" , mitk::BoolProperty::New(true))); for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End(); ++it) { it->Value()->SetProperty("helper object", mitk::BoolProperty::New(!state)); } } void QmitkSlicesInterpolator::OnToolManagerWorkingDataModified() { if (m_2DInterpolationEnabled) { OnInterpolationActivated( true ); // re-initialize if needed } if (m_3DInterpolationEnabled) { On3DInterpolationActivated( true); } } void QmitkSlicesInterpolator::OnToolManagerReferenceDataModified() { if (m_2DInterpolationEnabled) { OnInterpolationActivated( true ); // re-initialize if needed } if (m_3DInterpolationEnabled) { m_InterpolatedSurfaceNode->SetVisibility(false); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); } } void QmitkSlicesInterpolator::OnTransversalTimeChanged(itk::Object* sender, const itk::EventObject& e) { const mitk::SliceNavigationController::GeometryTimeEvent& event = dynamic_cast(e); m_TimeStep[2] = event.GetPos(); if (m_LastSliceDimension == 2) { mitk::SliceNavigationController* snc = dynamic_cast( sender ); if (snc) snc->SendSlice(); // will trigger a new interpolation } } void QmitkSlicesInterpolator::OnSagittalTimeChanged(itk::Object* sender, const itk::EventObject& e) { const mitk::SliceNavigationController::GeometryTimeEvent& event = dynamic_cast(e); m_TimeStep[0] = event.GetPos(); if (m_LastSliceDimension == 0) { mitk::SliceNavigationController* snc = dynamic_cast( sender ); if (snc) snc->SendSlice(); // will trigger a new interpolation } } void QmitkSlicesInterpolator::OnFrontalTimeChanged(itk::Object* sender, const itk::EventObject& e) { const mitk::SliceNavigationController::GeometryTimeEvent& event = dynamic_cast(e); m_TimeStep[1] = event.GetPos(); if (m_LastSliceDimension == 1) { mitk::SliceNavigationController* snc = dynamic_cast( sender ); if (snc) snc->SendSlice(); // will trigger a new interpolation } } void QmitkSlicesInterpolator::OnTransversalSliceChanged(const itk::EventObject& e) { if ( TranslateAndInterpolateChangedSlice( e, 2 ) ) { if (m_MultiWidget) { mitk::BaseRenderer::GetInstance(m_MultiWidget->mitkWidget1->GetRenderWindow())->RequestUpdate(); } } } void QmitkSlicesInterpolator::OnSagittalSliceChanged(const itk::EventObject& e) { if ( TranslateAndInterpolateChangedSlice( e, 0 ) ) { if (m_MultiWidget) { mitk::BaseRenderer::GetInstance(m_MultiWidget->mitkWidget2->GetRenderWindow())->RequestUpdate(); } } } void QmitkSlicesInterpolator::OnFrontalSliceChanged(const itk::EventObject& e) { if ( TranslateAndInterpolateChangedSlice( e, 1 ) ) { if (m_MultiWidget) { mitk::BaseRenderer::GetInstance(m_MultiWidget->mitkWidget3->GetRenderWindow())->RequestUpdate(); } } } bool QmitkSlicesInterpolator::TranslateAndInterpolateChangedSlice(const itk::EventObject& e, unsigned int windowID) { if (!m_2DInterpolationEnabled) return false; try { const mitk::SliceNavigationController::GeometrySliceEvent& event = dynamic_cast(e); mitk::TimeSlicedGeometry* tsg = event.GetTimeSlicedGeometry(); if (tsg && m_TimeStep.size() > windowID) { mitk::SlicedGeometry3D* slicedGeometry = dynamic_cast(tsg->GetGeometry3D(m_TimeStep[windowID])); if (slicedGeometry) { mitk::PlaneGeometry* plane = dynamic_cast(slicedGeometry->GetGeometry2D( event.GetPos() )); if (plane) Interpolate( plane, m_TimeStep[windowID] ); return true; } } } catch(std::bad_cast) { return false; // so what } return false; } void QmitkSlicesInterpolator::Interpolate( mitk::PlaneGeometry* plane, unsigned int timeStep ) { if (m_ToolManager) { mitk::DataNode* node = m_ToolManager->GetWorkingData(0); if (node) { m_Segmentation = dynamic_cast(node->GetData()); if (m_Segmentation) { int clickedSliceDimension(-1); int clickedSliceIndex(-1); // calculate real slice position, i.e. slice of the image and not slice of the TimeSlicedGeometry mitk::SegTool2D::DetermineAffectedImageSlice( m_Segmentation, plane, clickedSliceDimension, clickedSliceIndex ); mitk::Image::Pointer interpolation = m_Interpolator->Interpolate( clickedSliceDimension, clickedSliceIndex, timeStep ); - m_FeedbackNode->SetData( interpolation ); + + // Workaround for Bug 11318 + if ((interpolation.IsNotNull()) && (interpolation->GetGeometry() != NULL)) + { + if(clickedSliceDimension == 1) + { + mitk::Point3D orig = interpolation->GetGeometry()->GetOrigin(); + orig[0] = orig[0]; + orig[1] = orig[1] + 0.5; + orig[2] = orig[2]; + interpolation->GetGeometry()->SetOrigin(orig); + } + } + + // Workaround for Bug 11318 END + m_LastSliceDimension = clickedSliceDimension; m_LastSliceIndex = clickedSliceIndex; } } } } void QmitkSlicesInterpolator::SurfaceInterpolationFinished() { mitk::Surface::Pointer interpolatedSurface = m_SurfaceInterpolator->GetInterpolationResult(); if(interpolatedSurface.IsNotNull()) { m_BtnAccept3DInterpolation->setEnabled(true); m_InterpolatedSurfaceNode->SetData(interpolatedSurface); m_3DContourNode->SetData(m_SurfaceInterpolator->GetContoursAsSurface()); m_InterpolatedSurfaceNode->SetVisibility(true); m_3DContourNode->SetVisibility(true, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); if( !m_DataStorage->Exists(m_InterpolatedSurfaceNode) && !m_DataStorage->Exists(m_3DContourNode)) { m_DataStorage->Add(m_3DContourNode); m_DataStorage->Add(m_InterpolatedSurfaceNode); } } else if (interpolatedSurface.IsNull()) { m_BtnAccept3DInterpolation->setEnabled(false); if (m_DataStorage->Exists(m_InterpolatedSurfaceNode)) { m_InterpolatedSurfaceNode->SetVisibility(false); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); } } if (m_MultiWidget) { mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSlicesInterpolator::OnAcceptInterpolationClicked() { if (m_Segmentation && m_FeedbackNode->GetData()) { //making interpolation separately undoable mitk::UndoStackItem::IncCurrObjectEventId(); mitk::UndoStackItem::IncCurrGroupEventId(); mitk::UndoStackItem::ExecuteIncrement(); mitk::OverwriteSliceImageFilter::Pointer slicewriter = mitk::OverwriteSliceImageFilter::New(); slicewriter->SetInput( m_Segmentation ); slicewriter->SetCreateUndoInformation( true ); slicewriter->SetSliceImage( dynamic_cast(m_FeedbackNode->GetData()) ); slicewriter->SetSliceDimension( m_LastSliceDimension ); slicewriter->SetSliceIndex( m_LastSliceIndex ); slicewriter->SetTimeStep( m_TimeStep[m_LastSliceDimension] ); slicewriter->Update(); m_FeedbackNode->SetData(NULL); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSlicesInterpolator::AcceptAllInterpolations(unsigned int windowID) { // first creates a 3D diff image, then applies this diff to the segmentation if (m_Segmentation) { int sliceDimension(-1); int dummySliceIndex(-1); if (!GetSliceForWindowsID(windowID, sliceDimension, dummySliceIndex)) { return; // cannot determine slice orientation } //making interpolation separately undoable mitk::UndoStackItem::IncCurrObjectEventId(); mitk::UndoStackItem::IncCurrGroupEventId(); mitk::UndoStackItem::ExecuteIncrement(); // create a diff image for the undo operation mitk::Image::Pointer diffImage = mitk::Image::New(); diffImage->Initialize( m_Segmentation ); mitk::PixelType pixelType( mitk::MakeScalarPixelType() ); diffImage->Initialize( pixelType, 3, m_Segmentation->GetDimensions() ); memset( diffImage->GetData(), 0, (pixelType.GetBpe() >> 3) * diffImage->GetDimension(0) * diffImage->GetDimension(1) * diffImage->GetDimension(2) ); // now the diff image is all 0 unsigned int timeStep( m_TimeStep[windowID] ); // a slicewriter to create the diff image mitk::OverwriteSliceImageFilter::Pointer diffslicewriter = mitk::OverwriteSliceImageFilter::New(); diffslicewriter->SetCreateUndoInformation( false ); diffslicewriter->SetInput( diffImage ); diffslicewriter->SetSliceDimension( sliceDimension ); diffslicewriter->SetTimeStep( timeStep ); unsigned int totalChangedSlices(0); unsigned int zslices = m_Segmentation->GetDimension( sliceDimension ); mitk::ProgressBar::GetInstance()->AddStepsToDo(zslices); for (unsigned int sliceIndex = 0; sliceIndex < zslices; ++sliceIndex) { mitk::Image::Pointer interpolation = m_Interpolator->Interpolate( sliceDimension, sliceIndex, timeStep ); if (interpolation.IsNotNull()) // we don't check if interpolation is necessary/sensible - but m_Interpolator does { diffslicewriter->SetSliceImage( interpolation ); diffslicewriter->SetSliceIndex( sliceIndex ); diffslicewriter->Update(); ++totalChangedSlices; } mitk::ProgressBar::GetInstance()->Progress(); } if (totalChangedSlices > 0) { // store undo stack items if ( true ) { // create do/undo operations (we don't execute the doOp here, because it has already been executed during calculation of the diff image mitk::ApplyDiffImageOperation* doOp = new mitk::ApplyDiffImageOperation( mitk::OpTEST, m_Segmentation, diffImage, timeStep ); mitk::ApplyDiffImageOperation* undoOp = new mitk::ApplyDiffImageOperation( mitk::OpTEST, m_Segmentation, diffImage, timeStep ); undoOp->SetFactor( -1.0 ); std::stringstream comment; comment << "Accept all interpolations (" << totalChangedSlices << ")"; mitk::OperationEvent* undoStackItem = new mitk::OperationEvent( mitk::DiffImageApplier::GetInstanceForUndo(), doOp, undoOp, comment.str() ); mitk::UndoController::GetCurrentUndoModel()->SetOperationEvent( undoStackItem ); // acutally apply the changes here mitk::DiffImageApplier::GetInstanceForUndo()->ExecuteOperation( doOp ); } } m_FeedbackNode->SetData(NULL); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSlicesInterpolator::FinishInterpolation(int windowID) { //this redirect is for calling from outside if (windowID < 0) OnAcceptAllInterpolationsClicked(); else AcceptAllInterpolations( (unsigned int)windowID ); } void QmitkSlicesInterpolator::OnAcceptAllInterpolationsClicked() { QMenu orientationPopup(this); std::map::const_iterator it; for(it = ACTION_TO_SLICEDIMENSION.begin(); it != ACTION_TO_SLICEDIMENSION.end(); it++) orientationPopup.addAction(it->first); connect( &orientationPopup, SIGNAL(triggered(QAction*)), this, SLOT(OnAcceptAllPopupActivated(QAction*)) ); orientationPopup.exec( QCursor::pos() ); } void QmitkSlicesInterpolator::OnAccept3DInterpolationClicked() { if (m_InterpolatedSurfaceNode.IsNotNull() && m_InterpolatedSurfaceNode->GetData()) { mitk::SurfaceToImageFilter::Pointer s2iFilter = mitk::SurfaceToImageFilter::New(); s2iFilter->MakeOutputBinaryOn(); s2iFilter->SetInput(dynamic_cast(m_InterpolatedSurfaceNode->GetData())); s2iFilter->SetImage(dynamic_cast(m_ToolManager->GetReferenceData(0)->GetData())); s2iFilter->Update(); mitk::DataNode* segmentationNode = m_ToolManager->GetWorkingData(0); segmentationNode->SetData(s2iFilter->GetOutput()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSlicesInterpolator::OnAcceptAllPopupActivated(QAction* action) { try { std::map::const_iterator iter = ACTION_TO_SLICEDIMENSION.find( action ); if (iter != ACTION_TO_SLICEDIMENSION.end()) { int windowID = iter->second; AcceptAllInterpolations( windowID ); } } catch(...) { /* Showing message box with possible memory error */ QMessageBox errorInfo; errorInfo.setWindowTitle("Interpolation Process"); errorInfo.setIcon(QMessageBox::Critical); errorInfo.setText("An error occurred during interpolation. Possible cause: Not enough memory!"); errorInfo.exec(); //additional error message on std::cerr std::cerr << "Ill construction in " __FILE__ " l. " << __LINE__ << std::endl; } } void QmitkSlicesInterpolator::OnInterpolationActivated(bool on) { m_2DInterpolationEnabled = on; try { if ( m_DataStorage.IsNotNull() ) { if (on && !m_DataStorage->Exists(m_FeedbackNode)) { m_DataStorage->Add( m_FeedbackNode ); } //else //{ // m_DataStorage->Remove( m_FeedbackNode ); //} } } catch(...) { // don't care (double add/remove) } if (m_ToolManager) { mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); mitk::DataNode* referenceNode = m_ToolManager->GetReferenceData(0); QWidget::setEnabled( workingNode != NULL ); m_BtnAcceptAllInterpolations->setEnabled( on ); m_BtnAcceptInterpolation->setEnabled( on ); m_FeedbackNode->SetVisibility( on ); if (!on) { mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return; } if (workingNode) { mitk::Image* segmentation = dynamic_cast(workingNode->GetData()); if (segmentation) { m_Interpolator->SetSegmentationVolume( segmentation ); if (referenceNode) { mitk::Image* referenceImage = dynamic_cast(referenceNode->GetData()); m_Interpolator->SetReferenceVolume( referenceImage ); // may be NULL } } } } UpdateVisibleSuggestion(); } void QmitkSlicesInterpolator::Run3DInterpolation() { m_SurfaceInterpolator->Interpolate(); } void QmitkSlicesInterpolator::StartUpdateInterpolationTimer() { m_Timer->start(500); } void QmitkSlicesInterpolator::StopUpdateInterpolationTimer() { m_Timer->stop(); m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(255.0,255.0,0.0)); mitk::RenderingManager::GetInstance()->RequestUpdate(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetRenderWindow()); } void QmitkSlicesInterpolator::ChangeSurfaceColor() { float currentColor[3]; m_InterpolatedSurfaceNode->GetColor(currentColor); float yellow[3] = {255.0,255.0,0.0}; if( currentColor[2] == yellow[2]) { m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(255.0,255.0,255.0)); } else { m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(yellow)); } m_InterpolatedSurfaceNode->Update(); mitk::RenderingManager::GetInstance()->RequestUpdate(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetRenderWindow()); } void QmitkSlicesInterpolator::On3DInterpolationActivated(bool on) { m_3DInterpolationEnabled = on; try { if ( m_DataStorage.IsNotNull() && m_ToolManager && m_3DInterpolationEnabled) { mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); if (workingNode) { int listID; bool isInterpolationResult(false); workingNode->GetBoolProperty("3DInterpolationResult",isInterpolationResult); if ((workingNode->IsSelected() && workingNode->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3")))) && !isInterpolationResult) { if (workingNode->GetIntProperty("3DInterpolationListID", listID)) { m_SurfaceInterpolator->SetCurrentListID(listID); if (m_Watcher.isRunning()) m_Watcher.waitForFinished(); m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation); m_Watcher.setFuture(m_Future); } else { listID = m_SurfaceInterpolator->CreateNewContourList(); workingNode->SetIntProperty("3DInterpolationListID", listID); m_InterpolatedSurfaceNode->SetVisibility(false); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); m_BtnAccept3DInterpolation->setEnabled(false); } mitk::Vector3D spacing = workingNode->GetData()->GetGeometry( m_MultiWidget->GetRenderWindow3()->GetRenderer()->GetTimeStep() )->GetSpacing(); double minSpacing (100); double maxSpacing (0); for (int i =0; i < 3; i++) { if (spacing[i] < minSpacing) { minSpacing = spacing[i]; } else if (spacing[i] > maxSpacing) { maxSpacing = spacing[i]; } } m_SurfaceInterpolator->SetWorkingImage(dynamic_cast(workingNode->GetData())); m_SurfaceInterpolator->SetMaxSpacing(maxSpacing); m_SurfaceInterpolator->SetMinSpacing(minSpacing); m_SurfaceInterpolator->SetDistanceImageVolume(50000); } } QWidget::setEnabled( workingNode != NULL ); m_CbShowMarkers->setEnabled(m_3DInterpolationEnabled); } else if (!m_3DInterpolationEnabled) { m_InterpolatedSurfaceNode->SetVisibility(false); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); m_BtnAccept3DInterpolation->setEnabled(m_3DInterpolationEnabled); } } catch(...) { MITK_ERROR<<"Error with 3D surface interpolation!"; } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSlicesInterpolator::EnableInterpolation(bool on) { // only to be called from the outside world // just a redirection to OnInterpolationActivated OnInterpolationActivated(on); } void QmitkSlicesInterpolator::Enable3DInterpolation(bool on) { // only to be called from the outside world // just a redirection to OnInterpolationActivated On3DInterpolationActivated(on); } void QmitkSlicesInterpolator::UpdateVisibleSuggestion() { if (m_2DInterpolationEnabled) { // determine which one is the current view, try to do an initial interpolation mitk::BaseRenderer* renderer = mitk::GlobalInteraction::GetInstance()->GetFocus(); if (renderer && renderer->GetMapperID() == mitk::BaseRenderer::Standard2D) { const mitk::TimeSlicedGeometry* timeSlicedGeometry = dynamic_cast( renderer->GetWorldGeometry() ); if (timeSlicedGeometry) { mitk::SliceNavigationController::GeometrySliceEvent event( const_cast(timeSlicedGeometry), renderer->GetSlice() ); if ( renderer->GetCurrentWorldGeometry2DNode() ) { if ( renderer->GetCurrentWorldGeometry2DNode()==this->m_MultiWidget->GetWidgetPlane1() ) { TranslateAndInterpolateChangedSlice( event, 2 ); } else if ( renderer->GetCurrentWorldGeometry2DNode()==this->m_MultiWidget->GetWidgetPlane2() ) { TranslateAndInterpolateChangedSlice( event, 0 ); } else if ( renderer->GetCurrentWorldGeometry2DNode()==this->m_MultiWidget->GetWidgetPlane3() ) { TranslateAndInterpolateChangedSlice( event, 1 ); } } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSlicesInterpolator::OnInterpolationInfoChanged(const itk::EventObject& /*e*/) { // something (e.g. undo) changed the interpolation info, we should refresh our display UpdateVisibleSuggestion(); } void QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged(const itk::EventObject& /*e*/) { if(m_3DInterpolationEnabled) { if (m_Watcher.isRunning()) m_Watcher.waitForFinished(); m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation); m_Watcher.setFuture(m_Future); } } bool QmitkSlicesInterpolator::GetSliceForWindowsID(unsigned windowID, int& sliceDimension, int& sliceIndex) { mitk::BaseRenderer* renderer(NULL); // find sliceDimension for windowID: // windowID 2: transversal window = renderWindow1 // windowID 1: frontal window = renderWindow3 // windowID 0: sagittal window = renderWindow2 if ( m_MultiWidget ) { switch (windowID) { case 2: default: renderer = m_MultiWidget->mitkWidget1->GetRenderer(); break; case 1: renderer = m_MultiWidget->mitkWidget3->GetRenderer(); break; case 0: renderer = m_MultiWidget->mitkWidget2->GetRenderer(); break; } } if ( m_Segmentation && renderer && renderer->GetMapperID() == mitk::BaseRenderer::Standard2D) { const mitk::TimeSlicedGeometry* timeSlicedGeometry = dynamic_cast( renderer->GetWorldGeometry() ); if (timeSlicedGeometry) { mitk::SlicedGeometry3D* slicedGeometry = dynamic_cast(timeSlicedGeometry->GetGeometry3D(m_TimeStep[windowID])); if (slicedGeometry) { mitk::PlaneGeometry* plane = dynamic_cast(slicedGeometry->GetGeometry2D( renderer->GetSlice() )); Interpolate( plane, m_TimeStep[windowID] ); return mitk::SegTool2D::DetermineAffectedImageSlice( m_Segmentation, plane, sliceDimension, sliceIndex ); } } } return false; } void QmitkSlicesInterpolator::OnMultiWidgetDeleted(QObject*) { if (m_MultiWidget) { m_MultiWidget = NULL; } } diff --git a/Modules/ToFHardware/Testing/files.cmake b/Modules/ToFHardware/Testing/files.cmake index 77fd5af217..c2997f92f5 100644 --- a/Modules/ToFHardware/Testing/files.cmake +++ b/Modules/ToFHardware/Testing/files.cmake @@ -1,30 +1,29 @@ set(MODULE_TESTS mitkThreadedToFRawDataReconstructionTest.cpp mitkToFCameraMITKPlayerControllerTest.cpp mitkToFCameraMITKPlayerDeviceTest.cpp mitkToFCameraPMDCamBoardControllerTest.cpp mitkToFCameraPMDCamBoardDeviceTest.cpp #mitkToFCameraPMDRawDataCamBoardDeviceTest.cpp mitkToFCameraPMDCamCubeControllerTest.cpp mitkToFCameraPMDCamCubeDeviceTest.cpp #mitkToFCameraPMDRawDataCamCubeDeviceTest.cpp mitkToFCameraPMDControllerTest.cpp mitkToFCameraPMDDeviceTest.cpp mitkToFCameraPMDRawDataDeviceTest.cpp mitkToFCameraPMDMITKPlayerControllerTest.cpp mitkToFCameraPMDMITKPlayerDeviceTest.cpp mitkToFCameraPMDO3ControllerTest.cpp mitkToFCameraPMDO3DeviceTest.cpp mitkToFCameraPMDPlayerControllerTest.cpp mitkToFCameraPMDPlayerDeviceTest.cpp mitkToFImageCsvWriterTest.cpp mitkToFImageGrabberTest.cpp - mitkToFImageGrabberCreatorTest.cpp mitkToFImageRecorderTest.cpp mitkToFImageRecorderFilterTest.cpp mitkToFImageWriterTest.cpp mitkToFNrrdImageWriterTest.cpp mitkToFPicImageWriterTest.cpp mitkToFOpenCVImageGrabberTest.cpp ) diff --git a/Modules/ToFHardware/Testing/mitkToFImageGrabberCreatorTest.cpp b/Modules/ToFHardware/Testing/mitkToFImageGrabberCreatorTest.cpp deleted file mode 100644 index cbcf0cf5b9..0000000000 --- a/Modules/ToFHardware/Testing/mitkToFImageGrabberCreatorTest.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/*========================================================================= - -Program: Medical Imaging & Interaction Toolkit -Language: C++ -Date: $Date: 2010-03-12 14:05:50 +0100 (Fr, 12 Mrz 2010) $ -Version: $Revision: 16010 $ - -Copyright (c) German Cancer Research Center, Division of Medical and -Biological Informatics. All rights reserved. -See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. - -This software is distributed WITHOUT ANY WARRANTY; without even -the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/**Documentation - * test for the class "ToFImageGrabberCreatorCreator". - */ -int mitkToFImageGrabberCreatorTest(int /* argc */, char* /*argv*/[]) -{ - MITK_TEST_BEGIN("ToFImageGrabberCreator"); - - MITK_TEST_CONDITION_REQUIRED(mitk::ToFImageGrabberCreator::GetInstance()!=NULL,"Test GetInstance()"); - mitk::ToFImageGrabber::Pointer imageGrabber = NULL; - // ToFCameraMITKPlayer - imageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetMITKPlayerImageGrabber(); - MITK_TEST_CONDITION_REQUIRED(imageGrabber.IsNotNull(),"Test if MITKPlayerImageGrabber could be created"); - mitk::ToFCameraMITKPlayerDevice* mitkPlayerDevice - = dynamic_cast(imageGrabber->GetCameraDevice()); - MITK_TEST_CONDITION_REQUIRED(mitkPlayerDevice!=NULL,"Test if image grabber was initialized with ToFCameraMITKPlayerDevice"); - // ToFCameraPMDCamCube - imageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetPMDCamCubeImageGrabber(); - MITK_TEST_CONDITION_REQUIRED(imageGrabber.IsNotNull(),"Test if MITKPlayerImageGrabber could be created"); - mitk::ToFCameraPMDCamCubeDevice* camCubeDevice - = dynamic_cast(imageGrabber->GetCameraDevice()); - MITK_TEST_CONDITION_REQUIRED(camCubeDevice!=NULL,"Test if image grabber was initialized with ToFCameraPMDCamCubeDevice"); - // ToFCameraPMDRawDataCamCube - imageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetPMDRawDataCamCubeImageGrabber(); - MITK_TEST_CONDITION_REQUIRED(imageGrabber.IsNotNull(),"Test if MITKPlayerImageGrabber could be created"); - mitk::ToFCameraPMDRawDataCamCubeDevice* camCubeRawDevice - = dynamic_cast(imageGrabber->GetCameraDevice()); - MITK_TEST_CONDITION_REQUIRED(camCubeRawDevice!=NULL,"Test if image grabber was initialized"); - MITK_TEST_CONDITION_REQUIRED(!strcmp(camCubeRawDevice->GetNameOfClass(), "ToFCameraPMDRawDataCamCubeDevice"), "Test if image grabber was initialized with ToFCameraPMDRawDataCamCubeDevice"); - // ToFCameraPMDCamBoard - imageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetPMDCamBoardImageGrabber(); - MITK_TEST_CONDITION_REQUIRED(imageGrabber.IsNotNull(),"Test if MITKPlayerImageGrabber could be created"); - mitk::ToFCameraPMDCamBoardDevice* camBoardDevice - = dynamic_cast(imageGrabber->GetCameraDevice()); - MITK_TEST_CONDITION_REQUIRED(camBoardDevice!=NULL,"Test if image grabber was initialized with ToFCameraPMDCamBoardDevice"); - // ToFCameraPMDRawDataCamBoard - imageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetPMDRawDataCamBoardImageGrabber(); - MITK_TEST_CONDITION_REQUIRED(imageGrabber.IsNotNull(),"Test if MITKPlayerImageGrabber could be created"); - mitk::ToFCameraPMDRawDataCamBoardDevice* camBoardRawDevice - = dynamic_cast(imageGrabber->GetCameraDevice()); - MITK_TEST_CONDITION_REQUIRED(camBoardRawDevice!=NULL,"Test if image grabber was initialized with ToFCameraPMDRawDataCamBoardDevice"); - MITK_TEST_CONDITION_REQUIRED(!strcmp(camBoardRawDevice->GetNameOfClass(), "ToFCameraPMDRawDataCamBoardDevice"), "Test if image grabber was initialized with ToFCameraPMDRawDataCamCubeDevice"); - // ToFCameraPMDPlayer - imageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetPMDPlayerImageGrabber(); - MITK_TEST_CONDITION_REQUIRED(imageGrabber.IsNotNull(),"Test if MITKPlayerImageGrabber could be created"); - mitk::ToFCameraPMDPlayerDevice* pmdPlayerDevice - = dynamic_cast(imageGrabber->GetCameraDevice()); - MITK_TEST_CONDITION_REQUIRED(pmdPlayerDevice!=NULL,"Test if image grabber was initialized with ToFCameraPMDPlayerDevice"); - // ToFCameraPMDMITKPlayer - imageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetPMDMITKPlayerImageGrabber(); - MITK_TEST_CONDITION_REQUIRED(imageGrabber.IsNotNull(),"Test if MITKPlayerImageGrabber could be created"); - mitk::ToFCameraPMDMITKPlayerDevice* pmdMITKPlayerDevice - = dynamic_cast(imageGrabber->GetCameraDevice()); - MITK_TEST_CONDITION_REQUIRED(pmdMITKPlayerDevice!=NULL,"Test if image grabber was initialized with ToFCameraPMDMITKPlayerDevice"); - - MITK_TEST_END(); -} - - diff --git a/Modules/ToFHardware/Testing/mitkToFOpenCVImageGrabberTest.cpp b/Modules/ToFHardware/Testing/mitkToFOpenCVImageGrabberTest.cpp index 98150702c5..4418d9da61 100644 --- a/Modules/ToFHardware/Testing/mitkToFOpenCVImageGrabberTest.cpp +++ b/Modules/ToFHardware/Testing/mitkToFOpenCVImageGrabberTest.cpp @@ -1,99 +1,100 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-03-12 14:05:50 +0100 (Fr, 12 Mrz 2010) $ Version: $Revision: 16010 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include #include #include #include +#include #include -#include static bool CompareImages(mitk::Image::Pointer mitkImage, cv::Mat openCVImage) { float equal = true; if ((mitkImage->GetDimension(0)!=openCVImage.cols)||(mitkImage->GetDimension(1)!=openCVImage.rows)) { equal = false; } for (unsigned int i=0; iGetPixelValueByIndex(currentIndex); float openCVImageValue = openCVImage.at(j,i); if (!mitk::Equal(mitkImageValue,openCVImageValue)) { equal = false; } } } return equal; } /**Documentation * test for the class "ToFOpenCVImageGrabber". */ int mitkToFOpenCVImageGrabberTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("ToFOpenCVImageGrabber"); std::string dirName = MITK_TOF_DATA_DIR; - mitk::ToFImageGrabber::Pointer tofImageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetMITKPlayerImageGrabber(); + mitk::ToFImageGrabber::Pointer tofImageGrabber = mitk::ToFImageGrabber::New(); + tofImageGrabber->SetCameraDevice(mitk::ToFCameraMITKPlayerDevice::New()); std::string distanceFileName = dirName + "/PMDCamCube2_MF0_IT0_1Images_DistanceImage.pic"; tofImageGrabber->SetProperty("DistanceImageFileName",mitk::StringProperty::New(distanceFileName)); std::string amplitudeFileName = dirName + "/PMDCamCube2_MF0_IT0_1Images_AmplitudeImage.pic"; tofImageGrabber->SetProperty("AmplitudeImageFileName",mitk::StringProperty::New(amplitudeFileName)); std::string intensityFileName = dirName + "/PMDCamCube2_MF0_IT0_1Images_IntensityImage.pic"; tofImageGrabber->SetProperty("IntensityImageFileName",mitk::StringProperty::New(intensityFileName)); mitk::PicFileReader::Pointer mitkFileReader = mitk::PicFileReader::New(); mitkFileReader->SetFileName(distanceFileName); mitkFileReader->Update(); mitk::Image::Pointer image = mitkFileReader->GetOutput(); mitk::ToFOpenCVImageGrabber::Pointer tofOpenCVImageGrabber = mitk::ToFOpenCVImageGrabber::New(); tofOpenCVImageGrabber->SetToFImageGrabber(tofImageGrabber); MITK_TEST_CONDITION_REQUIRED(tofImageGrabber==tofOpenCVImageGrabber->GetToFImageGrabber(),"Test Set/GetToFImageGrabber()"); MITK_TEST_OUTPUT(<<"Call StartCapturing()"); tofOpenCVImageGrabber->StartCapturing(); cv::Mat cvImage = tofOpenCVImageGrabber->GetImage(); MITK_TEST_CONDITION_REQUIRED(CompareImages(image,cvImage),"Test distance image"); mitkFileReader->SetFileName(amplitudeFileName); mitkFileReader->Update(); image = mitkFileReader->GetOutput(); tofOpenCVImageGrabber->SetImageType(1); cvImage = tofOpenCVImageGrabber->GetImage(); MITK_TEST_CONDITION_REQUIRED(CompareImages(image,cvImage),"Test amplitude image"); mitkFileReader->SetFileName(intensityFileName); mitkFileReader->Update(); image = mitkFileReader->GetOutput(); tofOpenCVImageGrabber->SetImageType(2); cvImage = tofOpenCVImageGrabber->GetImage(); MITK_TEST_CONDITION_REQUIRED(CompareImages(image,cvImage),"Test intensity image"); MITK_TEST_OUTPUT(<<"Call StopCapturing()"); tofOpenCVImageGrabber->StopCapturing(); MITK_TEST_END(); } diff --git a/Modules/ToFHardware/files.cmake b/Modules/ToFHardware/files.cmake index 03e6cd4390..ae37b3d22f 100644 --- a/Modules/ToFHardware/files.cmake +++ b/Modules/ToFHardware/files.cmake @@ -1,96 +1,95 @@ set(CPP_FILES - mitkToFImageGrabberCreator.cpp mitkToFImageGrabber.cpp mitkToFOpenCVImageGrabber.cpp mitkToFCameraDevice.cpp mitkToFCameraMITKPlayerController.cpp mitkToFCameraMITKPlayerDevice.cpp mitkToFCameraPMDDevice.cpp mitkToFCameraPMDRawDataDevice.cpp mitkToFCameraPMDPlayerDevice.cpp mitkToFCameraPMDMITKPlayerDevice.cpp mitkToFCameraPMDO3Device.cpp mitkToFCameraPMDCamCubeDevice.cpp mitkToFCameraPMDRawDataCamCubeDevice.cpp mitkToFCameraPMDCamBoardDevice.cpp mitkToFCameraPMDRawDataCamBoardDevice.cpp mitkToFCameraMESADevice.cpp mitkToFCameraMESASR4000Device.cpp mitkToFImageRecorder.cpp mitkToFImageRecorderFilter.cpp mitkToFImageWriter.cpp mitkToFNrrdImageWriter.cpp mitkToFPicImageWriter.cpp mitkToFImageCsvWriter.cpp mitkThreadedToFRawDataReconstruction.cpp ) if(MITK_USE_TOF_PMDCAMCUBE) set(CPP_FILES ${CPP_FILES} mitkToFCameraPMDMITKPlayerController.cpp mitkToFCameraPMDCamCubeController.cpp mitkToFCameraPMDController.cpp ) if(WIN32) if(CMAKE_CL_64) set(CPP_FILES ${CPP_FILES} mitkToFCameraPMDPlayerControllerStub.cpp) else(CMAKE_CL_64) set(CPP_FILES ${CPP_FILES} mitkToFCameraPMDPlayerController.cpp) endif(CMAKE_CL_64) else(WIN32) set(CPP_FILES ${CPP_FILES} mitkToFCameraPMDPlayerControllerStub.cpp) endif(WIN32) else() set(CPP_FILES ${CPP_FILES} mitkToFCameraPMDMITKPlayerControllerStub.cpp mitkToFCameraPMDCamCubeControllerStub.cpp mitkToFCameraPMDPlayerControllerStub.cpp ) endif(MITK_USE_TOF_PMDCAMCUBE) if(MITK_USE_TOF_PMDCAMBOARD) set(CPP_FILES ${CPP_FILES} mitkToFCameraPMDCamBoardController.cpp mitkToFCameraPMDController.cpp ) else() set(CPP_FILES ${CPP_FILES} mitkToFCameraPMDCamBoardControllerStub.cpp ) endif(MITK_USE_TOF_PMDCAMBOARD) if(MITK_USE_TOF_PMDO3) set(CPP_FILES ${CPP_FILES} mitkToFCameraPMDO3Controller.cpp mitkToFCameraPMDController.cpp ) else() set(CPP_FILES ${CPP_FILES} mitkToFCameraPMDO3ControllerStub.cpp ) endif(MITK_USE_TOF_PMDO3) if(NOT MITK_USE_TOF_PMDCAMCUBE) if(NOT MITK_USE_TOF_PMDCAMBOARD) if(NOT MITK_USE_TOF_PMDO3) set(CPP_FILES ${CPP_FILES} mitkToFCameraPMDControllerStub.cpp ) endif(NOT MITK_USE_TOF_PMDO3) endif(NOT MITK_USE_TOF_PMDCAMBOARD) endif(NOT MITK_USE_TOF_PMDCAMCUBE) if(MITK_USE_TOF_MESASR4000) set(CPP_FILES ${CPP_FILES} mitkToFCameraMESASR4000Controller.cpp mitkToFCameraMESAController.cpp ) else() set(CPP_FILES ${CPP_FILES} mitkToFCameraMESAControllerStub.cpp mitkToFCameraMESASR4000ControllerStub.cpp ) endif(MITK_USE_TOF_MESASR4000) diff --git a/Modules/ToFHardware/mitkToFImageGrabber.h b/Modules/ToFHardware/mitkToFImageGrabber.h index fa02437c58..9e46100624 100644 --- a/Modules/ToFHardware/mitkToFImageGrabber.h +++ b/Modules/ToFHardware/mitkToFImageGrabber.h @@ -1,173 +1,172 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date: 2010-05-27 16:06:53 +0200 (Do, 27 Mai 2010) $ Version: $Revision: $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef __mitkToFImageGrabber_h #define __mitkToFImageGrabber_h #include "mitkToFHardwareExports.h" #include "mitkCommon.h" #include "mitkImageSource.h" #include "mitkToFCameraDevice.h" #include "itkObject.h" #include "itkObjectFactory.h" namespace mitk { /**Documentation * \brief Image source providing ToF images. Interface for filters provided in ToFProcessing module * * This class internally holds a ToFCameraDevice to access the images acquired by a ToF camera. - * A pre-configured instance for a specific ToF camera (e.g. PMD CamCube 3) can be obtained using - * the class ToFImageGrabberCreator. + * * Provided images include: distance image (output 0), amplitude image (output 1), intensity image (output 2) * * \ingroup ToFHardware */ class MITK_TOFHARDWARE_EXPORT ToFImageGrabber : public mitk::ImageSource { public: mitkClassMacro( ToFImageGrabber , ImageSource ); itkNewMacro( Self ); /*! \brief Establish a connection to the ToF camera \param device specifies the actually used ToF Camera. 0: PMD O3D, 1: PMD CamCube 2.0 */ virtual bool ConnectCamera(); /*! \brief Disconnects the ToF camera */ virtual bool DisconnectCamera(); /*! \brief Starts the continuous updating of the camera. A separate thread updates the source data, the main thread processes the source data and creates images and coordinates */ virtual void StartCamera(); /*! \brief Stops the continuous updating of the camera */ virtual void StopCamera(); /*! \brief Returns true if the camera is connected and started */ virtual bool IsCameraActive(); /*! \brief Sets the ToF device, the image grabber is grabbing the images from \param aToFCameraDevice device internally used for grabbing the images from the camera */ void SetCameraDevice(ToFCameraDevice* aToFCameraDevice); /*! \brief Get the currently set ToF camera device \return device currently used for grabbing images from the camera */ ToFCameraDevice* GetCameraDevice(); /*! \brief Set the modulation frequency used by the ToF camera. For default values see the corresponding device classes \param modulationFrequency modulation frequency in Hz */ int SetModulationFrequency(int modulationFrequency); /*! \brief Get the modulation frequency used by the ToF camera. \return modulation frequency in MHz */ int GetModulationFrequency(); /*! \brief Set the integration time used by the ToF camera. For default values see the corresponding device classes \param integrationTime integration time in ms */ int SetIntegrationTime(int integrationTime); /*! \brief Get the integration time in used by the ToF camera. \return integration time in ms */ int GetIntegrationTime(); /*! \brief Get the dimension in x direction of the ToF image \return width of the image */ int GetCaptureWidth(); /*! \brief Get the dimension in y direction of the ToF image \return height of the image */ int GetCaptureHeight(); /*! \brief Get the number of pixel in the ToF image \return number of pixel */ int GetPixelNumber(); // properties void SetBoolProperty( const char* propertyKey, bool boolValue ); void SetIntProperty( const char* propertyKey, int intValue ); void SetFloatProperty( const char* propertyKey, float floatValue ); void SetStringProperty( const char* propertyKey, const char* stringValue ); void SetProperty( const char *propertyKey, BaseProperty* propertyValue ); protected: /// /// called when the ToFCameraDevice was modified /// void OnToFCameraDeviceModified(); /*! \brief clean up memory allocated for the image arrays m_IntensityArray, m_DistanceArray, m_AmplitudeArray and m_SourceDataArray */ virtual void CleanUpImageArrays(); /*! \brief Allocate memory for the image arrays m_IntensityArray, m_DistanceArray, m_AmplitudeArray and m_SourceDataArray */ virtual void AllocateImageArrays(); ToFCameraDevice::Pointer m_ToFCameraDevice; ///< Device allowing acces to ToF image data int m_CaptureWidth; ///< Width of the captured ToF image int m_CaptureHeight; ///< Height of the captured ToF image int m_PixelNumber; ///< Number of pixels in the image int m_ImageSequence; ///< counter for currently acquired images int m_SourceDataSize; ///< size of the source data in bytes float* m_IntensityArray; ///< member holding the current intensity array float* m_DistanceArray; ///< member holding the current distance array float* m_AmplitudeArray; ///< member holding the current amplitude array char* m_SourceDataArray;///< member holding the current source data array unsigned long m_DeviceObserverTag; ///< tag of the oberver for the the ToFCameraDevice ToFImageGrabber(); ~ToFImageGrabber(); /*! \brief Method generating the outputs of this filter. Called in the updated process of the pipeline. 0: distance image 1: amplitude image 2: intensity image */ void GenerateData(); private: }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/mitkToFImageGrabberCreator.cpp b/Modules/ToFHardware/mitkToFImageGrabberCreator.cpp deleted file mode 100644 index e3093d0656..0000000000 --- a/Modules/ToFHardware/mitkToFImageGrabberCreator.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/*========================================================================= - -Program: Medical Imaging & Interaction Toolkit -Module: $RCSfile$ -Language: C++ -Date: $Date: 2010-05-27 16:06:53 +0200 (Do, 27 Mai 2010) $ -Version: $Revision: $ - -Copyright (c) German Cancer Research Center, Division of Medical and -Biological Informatics. All rights reserved. -See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. - -This software is distributed WITHOUT ANY WARRANTY; without even -the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ -#include "mitkToFImageGrabberCreator.h" -#include "mitkToFImageGrabber.h" -#include "mitkToFCameraPMDCamCubeDevice.h" -#include "mitkToFCameraPMDRawDataCamCubeDevice.h" -#include "mitkToFCameraPMDCamBoardDevice.h" -#include "mitkToFCameraPMDRawDataCamBoardDevice.h" -#include "mitkToFCameraPMDO3Device.h" -#include "mitkToFCameraPMDPlayerDevice.h" -#include "mitkToFCameraPMDMITKPlayerDevice.h" -#include "mitkToFCameraMITKPlayerDevice.h" -#include "mitkToFCameraMESASR4000Device.h" - -namespace mitk -{ - - ToFImageGrabberCreator::Pointer ToFImageGrabberCreator::s_Instance = NULL; - - ToFImageGrabberCreator::ToFImageGrabberCreator() - { - m_ToFImageGrabber = mitk::ToFImageGrabber::New(); - } - - ToFImageGrabberCreator::~ToFImageGrabberCreator() - { - } - - ToFImageGrabberCreator* ToFImageGrabberCreator::GetInstance() - { - if ( !ToFImageGrabberCreator::s_Instance ) - { - s_Instance = ToFImageGrabberCreator::New(); - } - return s_Instance; - } - - ToFImageGrabber::Pointer ToFImageGrabberCreator::GetPMDCamCubeImageGrabber() - { - m_ToFCameraDevice = mitk::ToFCameraPMDCamCubeDevice::New(); - m_ToFImageGrabber->SetCameraDevice(m_ToFCameraDevice); - return m_ToFImageGrabber; - } - - ToFImageGrabber::Pointer ToFImageGrabberCreator::GetPMDRawDataCamCubeImageGrabber() - { - m_ToFCameraDevice = mitk::ToFCameraPMDRawDataCamCubeDevice::New(); - m_ToFImageGrabber->SetCameraDevice(m_ToFCameraDevice); - return m_ToFImageGrabber; - } - - ToFImageGrabber::Pointer ToFImageGrabberCreator::GetPMDO3ImageGrabber() - { - m_ToFCameraDevice = mitk::ToFCameraPMDO3Device::New(); - m_ToFImageGrabber->SetCameraDevice(m_ToFCameraDevice); - return m_ToFImageGrabber; - } - - ToFImageGrabber::Pointer ToFImageGrabberCreator::GetPMDCamBoardImageGrabber() - { - m_ToFCameraDevice = mitk::ToFCameraPMDCamBoardDevice::New(); - m_ToFImageGrabber->SetCameraDevice(m_ToFCameraDevice); - return m_ToFImageGrabber; - } - - ToFImageGrabber::Pointer ToFImageGrabberCreator::GetPMDRawDataCamBoardImageGrabber() - { - m_ToFCameraDevice = mitk::ToFCameraPMDRawDataCamBoardDevice::New(); - m_ToFImageGrabber->SetCameraDevice(m_ToFCameraDevice); - return m_ToFImageGrabber; - } - - ToFImageGrabber::Pointer ToFImageGrabberCreator::GetPMDPlayerImageGrabber() - { - m_ToFCameraDevice = mitk::ToFCameraPMDPlayerDevice::New(); - m_ToFImageGrabber->SetCameraDevice(m_ToFCameraDevice); - return m_ToFImageGrabber; - } - - ToFImageGrabber::Pointer ToFImageGrabberCreator::GetPMDMITKPlayerImageGrabber() - { - m_ToFCameraDevice = mitk::ToFCameraPMDMITKPlayerDevice::New(); - m_ToFImageGrabber->SetCameraDevice(m_ToFCameraDevice); - return m_ToFImageGrabber; - } - - ToFImageGrabber::Pointer ToFImageGrabberCreator::GetMITKPlayerImageGrabber() - { - m_ToFCameraDevice = mitk::ToFCameraMITKPlayerDevice::New(); - m_ToFImageGrabber->SetCameraDevice(m_ToFCameraDevice); - return m_ToFImageGrabber; - } - - ToFImageGrabber::Pointer ToFImageGrabberCreator::GetMESASR4000ImageGrabber() - { - m_ToFCameraDevice = mitk::ToFCameraMESASR4000Device::New(); - m_ToFImageGrabber->SetCameraDevice(m_ToFCameraDevice); - return m_ToFImageGrabber; - } - -} diff --git a/Modules/ToFHardware/mitkToFImageGrabberCreator.h b/Modules/ToFHardware/mitkToFImageGrabberCreator.h deleted file mode 100644 index af32c44505..0000000000 --- a/Modules/ToFHardware/mitkToFImageGrabberCreator.h +++ /dev/null @@ -1,114 +0,0 @@ -/*========================================================================= - -Program: Medical Imaging & Interaction Toolkit -Module: $RCSfile$ -Language: C++ -Date: $Date: 2010-05-27 16:06:53 +0200 (Do, 27 Mai 2010) $ -Version: $Revision: $ - -Copyright (c) German Cancer Research Center, Division of Medical and -Biological Informatics. All rights reserved. -See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. - -This software is distributed WITHOUT ANY WARRANTY; without even -the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ -#ifndef __mitkToFImageGrabberCreator_h -#define __mitkToFImageGrabberCreator_h - -#include "mitkToFHardwareExports.h" -#include "mitkCommon.h" -#include "mitkToFImageGrabber.h" -#include "mitkToFCameraDevice.h" - -#include "itkObject.h" -#include "itkObjectFactory.h" - -namespace mitk -{ - /** - * @brief Class providing ready-to-use instances of ToFImageGrabbers - * This singleton can be used to create ToFImageGrabber objects of - * the supported ToF cameras. The ImageGrabbers are already initialized - * with the correct device object. - * When new hardware is added to MITK-ToF they should also be included in - * this creator class. - * - * @ingroup ToFHardware - */ - class MITK_TOFHARDWARE_EXPORT ToFImageGrabberCreator : public itk::Object - { - public: - - mitkClassMacro( ToFImageGrabberCreator , itk::Object ); - - itkNewMacro( Self ); - - /*! - \brief Get the RenderingManager singleton instance. - */ - static ToFImageGrabberCreator* GetInstance(); - - /*! - \brief Create a ImageGrabber object with a PMD CamCube Camera - */ - ToFImageGrabber::Pointer GetPMDCamCubeImageGrabber(); - - /*! - \brief Create a ImageGrabber object with a PMD raw data CamCube Camera - */ - ToFImageGrabber::Pointer GetPMDRawDataCamCubeImageGrabber(); - - /*! - \brief Create a ImageGrabber object with a PMD O3 Camera - */ - ToFImageGrabber::Pointer GetPMDO3ImageGrabber(); - - /*! - \brief Create a ImageGrabber object with a PMD CamBoard Camera - */ - ToFImageGrabber::Pointer GetPMDCamBoardImageGrabber(); - - /*! - \brief Create a ImageGrabber object with a PMD raw data CamBoard Camera - */ - ToFImageGrabber::Pointer GetPMDRawDataCamBoardImageGrabber(); - - /*! - \brief Create a ImageGrabber object with a PMD Player Camera - */ - ToFImageGrabber::Pointer GetPMDPlayerImageGrabber(); - - /*! - \brief Create a ImageGrabber object with a PMD MITK Player Camera - */ - ToFImageGrabber::Pointer GetPMDMITKPlayerImageGrabber(); - - /*! - \brief Create a ImageGrabber object with a MITK Player Camera - */ - ToFImageGrabber::Pointer GetMITKPlayerImageGrabber(); - - /*! - \brief Create a ImageGrabber object with a MESA SR4000 Camera - */ - ToFImageGrabber::Pointer GetMESASR4000ImageGrabber(); - - protected: - - static ToFImageGrabberCreator::Pointer s_Instance; ///< Instance to the singleton ToFImageGrabberCreator. Can be accessed by GetInstance() - - ToFCameraDevice::Pointer m_ToFCameraDevice; ///< ToFCameraDevice currently used in the provided ToFImageGrabber - - ToFImageGrabber::Pointer m_ToFImageGrabber; ///< ToFImageGrabber that will be returned configured with the specific ToFCameraDevice - - ToFImageGrabberCreator(); - - ~ToFImageGrabberCreator(); - private: - - }; -} //END mitk namespace -#endif diff --git a/Modules/ToFUI/Qmitk/QmitkToFConnectionWidget.cpp b/Modules/ToFUI/Qmitk/QmitkToFConnectionWidget.cpp index 325e52f9fe..17f50c9982 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFConnectionWidget.cpp +++ b/Modules/ToFUI/Qmitk/QmitkToFConnectionWidget.cpp @@ -1,346 +1,352 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date: 2009-05-20 13:35:09 +0200 (Mi, 20 Mai 2009) $ Version: $Revision: 17332 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ //#define _USE_MATH_DEFINES #include //QT headers #include #include #include //mitk headers #include "mitkToFConfig.h" -#include +#include "mitkToFCameraPMDCamCubeDevice.h" +#include "mitkToFCameraPMDRawDataCamCubeDevice.h" +#include "mitkToFCameraPMDCamBoardDevice.h" +#include "mitkToFCameraPMDRawDataCamBoardDevice.h" +#include "mitkToFCameraPMDO3Device.h" +#include "mitkToFCameraPMDPlayerDevice.h" +#include "mitkToFCameraPMDMITKPlayerDevice.h" +#include "mitkToFCameraMITKPlayerDevice.h" +#include "mitkToFCameraMESASR4000Device.h" //itk headers #include const std::string QmitkToFConnectionWidget::VIEW_ID = "org.mitk.views.qmitktofconnectionwidget"; QmitkToFConnectionWidget::QmitkToFConnectionWidget(QWidget* parent, Qt::WindowFlags f): QWidget(parent, f) { this->m_IntegrationTime = 0; this->m_ModulationFrequency = 0; - this->m_ToFImageGrabber = NULL; - + this->m_ToFImageGrabber = mitk::ToFImageGrabber::New(); m_Controls = NULL; CreateQtPartControl(this); } QmitkToFConnectionWidget::~QmitkToFConnectionWidget() { } void QmitkToFConnectionWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkToFConnectionWidgetControls; m_Controls->setupUi(parent); this->CreateConnections(); // set available cameras to combo box QString string(MITK_TOF_CAMERAS); string.replace(";"," "); QStringList list = string.split(","); m_Controls->m_SelectCameraCombobox->addItems(list); ShowParameterWidget(); } } void QmitkToFConnectionWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_ConnectCameraButton), SIGNAL(clicked()),(QObject*) this, SLOT(OnConnectCamera()) ); connect( m_Controls->m_SelectCameraCombobox, SIGNAL(currentIndexChanged(const QString)), this, SLOT(OnSelectCamera(const QString)) ); connect( m_Controls->m_SelectCameraCombobox, SIGNAL(activated(const QString)), this, SLOT(OnSelectCamera(const QString)) ); connect( m_Controls->m_SelectCameraCombobox, SIGNAL(activated(const QString)), this, SIGNAL(ToFCameraSelected(const QString)) ); } } void QmitkToFConnectionWidget::ShowParameterWidget() { QString selectedCamera = m_Controls->m_SelectCameraCombobox->currentText(); if ((selectedCamera == "PMD CamCube 2.0/3.0")||(selectedCamera == "PMD CamBoard")||(selectedCamera=="PMD O3D")|| (selectedCamera=="PMD CamBoardRaw")||(selectedCamera=="PMD CamCubeRaw") ) { ShowPMDParameterWidget(); } else if (selectedCamera=="MESA Swissranger 4000") { ShowMESAParameterWidget(); } else { this->m_Controls->m_PMDParameterWidget->hide(); this->m_Controls->m_MESAParameterWidget->hide(); } } void QmitkToFConnectionWidget::ShowPMDParameterWidget() { this->m_Controls->m_PMDParameterWidget->show(); this->m_Controls->m_MESAParameterWidget->hide(); } void QmitkToFConnectionWidget::ShowMESAParameterWidget() { this->m_Controls->m_PMDParameterWidget->hide(); this->m_Controls->m_MESAParameterWidget->show(); } void QmitkToFConnectionWidget::ShowPlayerParameterWidget() { this->m_Controls->m_PMDParameterWidget->hide(); this->m_Controls->m_MESAParameterWidget->hide(); } mitk::ToFImageGrabber* QmitkToFConnectionWidget::GetToFImageGrabber() { return m_ToFImageGrabber; } void QmitkToFConnectionWidget::OnSelectCamera(const QString selectedText) { if (selectedText == "PMD CamCube 2.0/3.0" || selectedText == "PMD CamCubeRaw 2.0/3.0" ) // PMD camcube 2 { ShowPMDParameterWidget(); } else if (selectedText == "PMD CamBoard" || selectedText == "PMD CamBoardRaw" ) // pmd camboard { ShowPMDParameterWidget(); } else if (selectedText == "PMD O3D") // pmd O3d { ShowPMDParameterWidget(); } else if (selectedText == "MESA Swissranger 4000") // MESA 4000 { ShowMESAParameterWidget(); } else if (selectedText == "PMD Player") // pmd file player { ShowPlayerParameterWidget(); } else if (selectedText == "PMD Raw Data Player") // pmd raw data player { ShowPlayerParameterWidget(); } else if (selectedText == "MITK Player") // mitk player { ShowPlayerParameterWidget(); } } void QmitkToFConnectionWidget::OnConnectCamera() { bool playerMode = false; if (m_Controls->m_ConnectCameraButton->text()=="Connect") { //reset the status of the GUI buttons m_Controls->m_ConnectCameraButton->setEnabled(false); m_Controls->m_SelectCameraCombobox->setEnabled(false); //repaint the widget this->repaint(); QString tmpFileName(""); QString fileFilter(""); //select the camera to connect with QString selectedCamera = m_Controls->m_SelectCameraCombobox->currentText(); if (selectedCamera == "PMD CamCube 2.0/3.0") { //PMD CamCube - this->m_ToFImageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetPMDCamCubeImageGrabber(); + this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraPMDCamCubeDevice::New()); } else if (selectedCamera == "PMD CamCubeRaw 2.0/3.0") { //PMD CamCube - this->m_ToFImageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetPMDRawDataCamCubeImageGrabber(); + this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraPMDRawDataCamCubeDevice::New()); } else if (selectedCamera == "PMD CamBoard") { //PMD CamBoard - this->m_ToFImageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetPMDCamBoardImageGrabber(); + this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraPMDCamBoardDevice::New()); } else if (selectedCamera == "PMD CamBoardRaw") { //PMD CamBoard - this->m_ToFImageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetPMDRawDataCamBoardImageGrabber(); + this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraPMDRawDataCamBoardDevice::New()); } else if (selectedCamera == "PMD O3D") {//PMD O3 - this->m_ToFImageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetPMDO3ImageGrabber(); + this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraPMDO3Device::New()); } else if (selectedCamera == "MESA Swissranger 4000") {//MESA SR4000 - this->m_ToFImageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetMESASR4000ImageGrabber(); - } + this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraMESASR4000Device::New()); + } else if (selectedCamera == "PMD Player") {//PMD player playerMode = true; fileFilter.append("PMD Files (*.pmd)"); - this->m_ToFImageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetPMDPlayerImageGrabber(); + this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraPMDPlayerDevice::New()); } else if (selectedCamera == "PMD Raw Data Player") {//PMD MITK player playerMode = true; fileFilter.append("NRRD Images (*.nrrd);;PIC Images - deprecated (*.pic)"); - this->m_ToFImageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetPMDMITKPlayerImageGrabber(); + this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraPMDRawDataDevice::New()); } else if (selectedCamera == "MITK Player") {//MITK player playerMode = true; fileFilter.append("NRRD Images (*.nrrd);;PIC Images - deprecated (*.pic)"); - this->m_ToFImageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetMITKPlayerImageGrabber(); + this->m_ToFImageGrabber->SetCameraDevice(mitk::ToFCameraMITKPlayerDevice::New()); } // if a player was selected ... if (playerMode) { //... open a QFileDialog to chose the corresponding file from the disc tmpFileName = QFileDialog::getOpenFileName(NULL, "Play Image From...", "", fileFilter); if (tmpFileName.isEmpty()) { m_Controls->m_ConnectCameraButton->setChecked(false); m_Controls->m_ConnectCameraButton->setEnabled(true); m_Controls->m_SelectCameraCombobox->setEnabled(true); this->OnSelectCamera(m_Controls->m_SelectCameraCombobox->currentText()); QMessageBox::information( this, "Template functionality", "Please select a valid image before starting some action."); return; } if(selectedCamera == "PMD Player") { //set the PMD file name this->m_ToFImageGrabber->SetStringProperty("PMDFileName", tmpFileName.toStdString().c_str() ); } if (selectedCamera == "PMD Raw Data Player" || selectedCamera == "MITK Player") { std::string msg = ""; try { //get 3 corresponding file names std::string dir = itksys::SystemTools::GetFilenamePath( tmpFileName.toStdString() ); std::string baseFilename = itksys::SystemTools::GetFilenameWithoutLastExtension( tmpFileName.toStdString() ); std::string extension = itksys::SystemTools::GetFilenameLastExtension( tmpFileName.toStdString() ); if (extension != ".pic" && extension != ".nrrd") { msg = msg + "Invalid file format, please select a \".nrrd\"-file"; throw std::logic_error(msg.c_str()); } int found = baseFilename.rfind("_DistanceImage"); if (found == std::string::npos) { found = baseFilename.rfind("_AmplitudeImage"); } if (found == std::string::npos) { found = baseFilename.rfind("_IntensityImage"); } if (found == std::string::npos) { msg = msg + "Input file name must end with \"_DistanceImage.pic\", \"_AmplitudeImage.pic\" or \"_IntensityImage.pic\"!"; throw std::logic_error(msg.c_str()); } std::string baseFilenamePrefix = baseFilename.substr(0,found); std::string distanceImageFileName = dir + "/" + baseFilenamePrefix + "_DistanceImage" + extension; std::string amplitudeImageFileName = dir + "/" + baseFilenamePrefix + "_AmplitudeImage" + extension; std::string intensityImageFileName = dir + "/" + baseFilenamePrefix + "_IntensityImage" + extension; if (!itksys::SystemTools::FileExists(distanceImageFileName.c_str(), true)) { msg = msg + "Inputfile not exist! " + distanceImageFileName; throw std::logic_error(msg.c_str()); } if (!itksys::SystemTools::FileExists(amplitudeImageFileName.c_str(), true)) { msg = msg + "Inputfile not exist! " + amplitudeImageFileName; throw std::logic_error(msg.c_str()); } if (!itksys::SystemTools::FileExists(intensityImageFileName.c_str(), true)) { msg = msg + "Inputfile not exist! " + intensityImageFileName; throw std::logic_error(msg.c_str()); } //set the file names this->m_ToFImageGrabber->SetStringProperty("DistanceImageFileName", distanceImageFileName.c_str()); this->m_ToFImageGrabber->SetStringProperty("AmplitudeImageFileName", amplitudeImageFileName.c_str()); this->m_ToFImageGrabber->SetStringProperty("IntensityImageFileName", intensityImageFileName.c_str()); } catch (std::exception &e) { MITK_ERROR << e.what(); QMessageBox::critical( this, "Error", e.what() ); m_Controls->m_ConnectCameraButton->setChecked(false); m_Controls->m_ConnectCameraButton->setEnabled(true); m_Controls->m_SelectCameraCombobox->setEnabled(true); this->OnSelectCamera(m_Controls->m_SelectCameraCombobox->currentText()); return; } } } //if a connection could be established if (this->m_ToFImageGrabber->ConnectCamera()) { this->m_Controls->m_PMDParameterWidget->SetToFImageGrabber(this->m_ToFImageGrabber); this->m_Controls->m_MESAParameterWidget->SetToFImageGrabber(this->m_ToFImageGrabber); if ((selectedCamera == "PMD CamCube 2.0/3.0")||(selectedCamera == "PMD CamBoard")||(selectedCamera=="PMD O3D")|| (selectedCamera=="PMD CamBoardRaw")||(selectedCamera=="PMD CamCubeRaw 2.0/3.0")) { this->m_Controls->m_PMDParameterWidget->ActivateAllParameters(); } else if (selectedCamera=="MESA Swissranger 4000") { this->m_Controls->m_MESAParameterWidget->ActivateAllParameters(); } m_Controls->m_ConnectCameraButton->setText("Disconnect"); // send connect signal to the caller functionality emit ToFCameraConnected(); } else { QMessageBox::critical( this, "Error", "Connection failed. Check if you have installed the latest driver for your system." ); m_Controls->m_ConnectCameraButton->setChecked(false); m_Controls->m_ConnectCameraButton->setEnabled(true); m_Controls->m_SelectCameraCombobox->setEnabled(true); this->OnSelectCamera(m_Controls->m_SelectCameraCombobox->currentText()); return; } m_Controls->m_ConnectCameraButton->setEnabled(true); } else if (m_Controls->m_ConnectCameraButton->text()=="Disconnect") { this->m_ToFImageGrabber->StopCamera(); this->m_ToFImageGrabber->DisconnectCamera(); m_Controls->m_ConnectCameraButton->setText("Connect"); m_Controls->m_SelectCameraCombobox->setEnabled(true); this->OnSelectCamera(m_Controls->m_SelectCameraCombobox->currentText()); - this->m_ToFImageGrabber = NULL; // send disconnect signal to the caller functionality emit ToFCameraDisconnected(); } } diff --git a/Modules/ToFUI/Qmitk/QmitkToFConnectionWidget.h b/Modules/ToFUI/Qmitk/QmitkToFConnectionWidget.h index ae46b113c1..b31fd101ed 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFConnectionWidget.h +++ b/Modules/ToFUI/Qmitk/QmitkToFConnectionWidget.h @@ -1,111 +1,111 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date: 2009-05-20 13:35:09 +0200 (Mi, 20 Mai 2009) $ Version: $Revision: 17332 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _QMITKTOFCONNECTIONWIDGET_H_INCLUDED #define _QMITKTOFCONNECTIONWIDGET_H_INCLUDED #include "mitkTOFUIExports.h" #include "ui_QmitkToFConnectionWidgetControls.h" //QT headers #include //mitk headers #include "mitkToFImageGrabber.h" /** * @brief Widget allowing to connect to different ToF / range cameras (located in module ToFProcessing) * * The widget basically allows to connect/disconnect to different ToF cameras * * @ingroup ToFUI */ class mitkTOFUI_EXPORT QmitkToFConnectionWidget :public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkToFConnectionWidget(QWidget* p = 0, Qt::WindowFlags f1 = 0); virtual ~QmitkToFConnectionWidget(); /* @brief This method is part of the widget an needs not to be called seperately. */ virtual void CreateQtPartControl(QWidget *parent); /* @brief This method is part of the widget an needs not to be called seperately. (Creation of the connections of main and control widget.)*/ virtual void CreateConnections(); /*! - \brief returns the ToFImageGrabber which was provided by the ToFImageGrabberCreator after selecting a camera / player + \brief returns the ToFImageGrabber which was configured after selecting a camera / player \return ToFImageGrabber currently used by the widget */ mitk::ToFImageGrabber* GetToFImageGrabber(); signals: /*! \brief This signal is sent if the user has connected the TOF camera. * The ToFImageGrabber is now availiable if the method GetToFImageGrabber() is called. */ void ToFCameraConnected(); /*! \brief This signal is sent if the user has disconnect the TOF camera. */ void ToFCameraDisconnected(); /*! \brief signal that is emitted when a ToF camera is selected in the combo box */ void ToFCameraSelected(const QString selectedText); protected slots: /*! \brief slot called when the "Connect Camera" button was pressed - * According to the selection in the camera combo box, the ToFImageGrabberCreator provides + * According to the selection in the camera combo box, the widget provides * the desired instance of the ToFImageGrabber */ void OnConnectCamera(); /*! \brief slot updating the GUI elements after the selection of the camera combo box has changed */ void OnSelectCamera(const QString selectedText); protected: Ui::QmitkToFConnectionWidgetControls* m_Controls; ///< member holding the UI elements of this widget - mitk::ToFImageGrabber* m_ToFImageGrabber; ///< member holding the current ToFImageGrabber + mitk::ToFImageGrabber::Pointer m_ToFImageGrabber; ///< member holding the current ToFImageGrabber int m_IntegrationTime; ///< member for the current integration time of the ToF device int m_ModulationFrequency; ///< member for the current modulation frequency of the ToF device private: void ShowParameterWidget(); void ShowPMDParameterWidget(); void ShowMESAParameterWidget(); void ShowPlayerParameterWidget(); }; #endif // _QMITKTOFCONNECTIONWIDGET_H_INCLUDED diff --git a/Modules/ToFUI/Qmitk/QmitkToFMESAParameterWidget.cpp b/Modules/ToFUI/Qmitk/QmitkToFMESAParameterWidget.cpp index 2f21b1a895..4a5e21eefa 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFMESAParameterWidget.cpp +++ b/Modules/ToFUI/Qmitk/QmitkToFMESAParameterWidget.cpp @@ -1,176 +1,173 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date: 2009-05-20 13:35:09 +0200 (Mi, 20 Mai 2009) $ Version: $Revision: 17332 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ //#define _USE_MATH_DEFINES #include //QT headers #include #include #include -//mitk headers -#include - //itk headers #include const std::string QmitkToFMESAParameterWidget::VIEW_ID = "org.mitk.views.qmitktofpmdparameterwidget"; QmitkToFMESAParameterWidget::QmitkToFMESAParameterWidget(QWidget* parent, Qt::WindowFlags f): QWidget(parent, f) { this->m_IntegrationTime = 0; this->m_ModulationFrequency = 0; this->m_ToFImageGrabber = NULL; m_Controls = NULL; CreateQtPartControl(this); } QmitkToFMESAParameterWidget::~QmitkToFMESAParameterWidget() { } void QmitkToFMESAParameterWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkToFMESAParameterWidgetControls; m_Controls->setupUi(parent); this->CreateConnections(); } } void QmitkToFMESAParameterWidget::CreateConnections() { if ( m_Controls ) { connect( m_Controls->m_IntegrationTimeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnChangeIntegrationTimeSpinBox(int)) ); connect( m_Controls->m_ModulationFrequencyComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnChangeModulationFrequencyComboBox(int)) ); connect( m_Controls->m_FPNCB, SIGNAL(toggled(bool)), this, SLOT(OnChangeFPNCheckBox(bool)) ); connect( m_Controls->m_ConvGrayCB, SIGNAL(toggled(bool)), this, SLOT(OnChangeConvGrayCheckBox(bool)) ); connect( m_Controls->m_MedianCB, SIGNAL(toggled(bool)), this, SLOT(OnChangeMedianCheckBox(bool)) ); connect( m_Controls->m_ANFCB, SIGNAL(toggled(bool)), this, SLOT(OnChangeANFCheckBox(bool)) ); } } mitk::ToFImageGrabber* QmitkToFMESAParameterWidget::GetToFImageGrabber() { return this->m_ToFImageGrabber; } void QmitkToFMESAParameterWidget::SetToFImageGrabber(mitk::ToFImageGrabber* aToFImageGrabber) { this->m_ToFImageGrabber = aToFImageGrabber; } void QmitkToFMESAParameterWidget::ActivateAllParameters() { this->m_IntegrationTime = m_Controls->m_IntegrationTimeSpinBox->value(); this->m_IntegrationTime = this->m_ToFImageGrabber->SetIntegrationTime(this->m_IntegrationTime); switch(m_Controls->m_ModulationFrequencyComboBox->currentIndex()) { case 0: this->m_ModulationFrequency = 29; break; case 1: this->m_ModulationFrequency = 30; break; case 2: this->m_ModulationFrequency = 31; break; default: this->m_ModulationFrequency = 30; break; } this->m_ModulationFrequency = this->m_ToFImageGrabber->SetModulationFrequency(this->m_ModulationFrequency); //set the MESA acquire mode according to the check boxes bool boolValue = false; boolValue = m_Controls->m_FPNCB->isChecked(); this->m_ToFImageGrabber->SetBoolProperty("SetFPN", boolValue); boolValue = m_Controls->m_ConvGrayCB->isChecked(); this->m_ToFImageGrabber->SetBoolProperty("SetConvGray", boolValue); boolValue = m_Controls->m_MedianCB->isChecked(); this->m_ToFImageGrabber->SetBoolProperty("SetMedian", boolValue); boolValue = m_Controls->m_ANFCB->isChecked(); this->m_ToFImageGrabber->SetBoolProperty("SetANF", boolValue); //reset the GUI elements m_Controls->m_IntegrationTimeSpinBox->setValue(this->m_IntegrationTime); //m_Controls->m_ModulationFrequencyComboBox->setValue(this->m_ModulationFrequency); } void QmitkToFMESAParameterWidget::OnChangeFPNCheckBox(bool checked) { this->m_ToFImageGrabber->SetBoolProperty("SetFPN", checked); } void QmitkToFMESAParameterWidget::OnChangeConvGrayCheckBox(bool checked) { this->m_ToFImageGrabber->SetBoolProperty("SetConvGray", checked); } void QmitkToFMESAParameterWidget::OnChangeMedianCheckBox(bool checked) { this->m_ToFImageGrabber->SetBoolProperty("SetMedian", checked); } void QmitkToFMESAParameterWidget::OnChangeANFCheckBox(bool checked) { this->m_ToFImageGrabber->SetBoolProperty("SetANF", checked); } void QmitkToFMESAParameterWidget::OnChangeIntegrationTimeSpinBox(int value) { if (this->m_ToFImageGrabber != NULL) { // stop camera if active bool active = m_ToFImageGrabber->IsCameraActive(); if (active) { m_ToFImageGrabber->StopCamera(); } this->m_IntegrationTime = m_Controls->m_IntegrationTimeSpinBox->value(); this->m_IntegrationTime = this->m_ToFImageGrabber->SetIntegrationTime(this->m_IntegrationTime); if (active) { m_ToFImageGrabber->StartCamera(); } } } void QmitkToFMESAParameterWidget::OnChangeModulationFrequencyComboBox(int index) { if (this->m_ToFImageGrabber != NULL) { // stop camera if active bool active = m_ToFImageGrabber->IsCameraActive(); if (active) { m_ToFImageGrabber->StopCamera(); } switch(index) { case 0: this->m_ModulationFrequency = 29; break; case 1: this->m_ModulationFrequency = 30; break; case 2: this->m_ModulationFrequency = 31; break; default: this->m_ModulationFrequency = 30; break; } this->m_ModulationFrequency = this->m_ToFImageGrabber->SetModulationFrequency(this->m_ModulationFrequency); if (active) { m_ToFImageGrabber->StartCamera(); } } } diff --git a/Modules/ToFUI/Qmitk/QmitkToFMESAParameterWidget.h b/Modules/ToFUI/Qmitk/QmitkToFMESAParameterWidget.h index 0e392ce3b8..8ad027a5ff 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFMESAParameterWidget.h +++ b/Modules/ToFUI/Qmitk/QmitkToFMESAParameterWidget.h @@ -1,128 +1,128 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date: 2009-05-20 13:35:09 +0200 (Mi, 20 Mai 2009) $ Version: $Revision: 17332 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _QMITKTOFMESAPARAMETERWIDGET_H_INCLUDED #define _QMITKTOFMESAPARAMETERWIDGET_H_INCLUDED #include "mitkTOFUIExports.h" #include "ui_QmitkToFMESAParameterWidgetControls.h" //QT headers #include //mitk headers #include "mitkToFImageGrabber.h" /** * @brief Widget allowing to connect to different ToF / range cameras (located in module ToFProcessing) * * The widget basically allows to connect/disconnect to different ToF cameras * * @ingroup ToFUI */ class mitkTOFUI_EXPORT QmitkToFMESAParameterWidget :public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkToFMESAParameterWidget(QWidget* p = 0, Qt::WindowFlags f1 = 0); virtual ~QmitkToFMESAParameterWidget(); /* @brief This method is part of the widget an needs not to be called seperately. */ virtual void CreateQtPartControl(QWidget *parent); /* @brief This method is part of the widget an needs not to be called seperately. (Creation of the connections of main and control widget.)*/ virtual void CreateConnections(); /*! - \brief returns the ToFImageGrabber which was provided by the ToFImageGrabberCreator after selecting a camera / player + \brief returns the ToFImageGrabber which was configured after selecting a camera / player \return ToFImageGrabber currently used by the widget */ mitk::ToFImageGrabber* GetToFImageGrabber(); /*! - \brief sets the ToFImageGrabber which was provided by the ToFImageGrabberCreator after selecting a camera / player + \brief sets the ToFImageGrabber which was configured after selecting a camera / player */ void SetToFImageGrabber(mitk::ToFImageGrabber* aToFImageGrabber); /*! \brief activate camera settings according to the parameters from GUI */ void ActivateAllParameters(); signals: /*! \brief This signal is sent if the user has connected the TOF camera. * The ToFImageGrabber is now availiable if the method GetToFImageGrabber() is called. */ void ToFCameraConnected(); /*! \brief This signal is sent if the user has disconnect the TOF camera. */ void ToFCameraDisconnected(); /*! \brief signal that is emitted when the ToF camera is started */ void ToFCameraStart(); /*! \brief signal that is emitted when the ToF camera is stopped */ void ToFCameraStop(); /*! \brief signal that is emitted when a ToF camera is selected in the combo box */ void ToFCameraSelected(int); protected slots: /*! \brief slot updating the member m_IntegrationTime and the parameter "integration time" of the current ToFImageGrabber */ void OnChangeIntegrationTimeSpinBox(int value); /*! \brief slot updating the member m_ModulationFrequency and the parameter "modulation frequency" of the current ToFImageGrabber */ void OnChangeModulationFrequencyComboBox(int index); void OnChangeFPNCheckBox(bool checked); void OnChangeConvGrayCheckBox(bool checked); void OnChangeMedianCheckBox(bool checked); void OnChangeANFCheckBox(bool checked); protected: Ui::QmitkToFMESAParameterWidgetControls* m_Controls; ///< member holding the UI elements of this widget mitk::ToFImageGrabber* m_ToFImageGrabber; ///< member holding the current ToFImageGrabber int m_IntegrationTime; ///< member for the current integration time of the ToF device int m_ModulationFrequency; ///< member for the current modulation frequency of the ToF device private: }; #endif // _QMITKTOFCONNECTIONWIDGET_H_INCLUDED diff --git a/Modules/ToFUI/Qmitk/QmitkToFPMDParameterWidget.cpp b/Modules/ToFUI/Qmitk/QmitkToFPMDParameterWidget.cpp index 223faacf41..37df9718f8 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFPMDParameterWidget.cpp +++ b/Modules/ToFUI/Qmitk/QmitkToFPMDParameterWidget.cpp @@ -1,142 +1,139 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date: 2009-05-20 13:35:09 +0200 (Mi, 20 Mai 2009) $ Version: $Revision: 17332 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ //#define _USE_MATH_DEFINES #include //QT headers #include #include #include -//mitk headers -#include - //itk headers #include const std::string QmitkToFPMDParameterWidget::VIEW_ID = "org.mitk.views.qmitktofpmdparameterwidget"; QmitkToFPMDParameterWidget::QmitkToFPMDParameterWidget(QWidget* parent, Qt::WindowFlags f): QWidget(parent, f) { this->m_IntegrationTime = 0; this->m_ModulationFrequency = 0; this->m_ToFImageGrabber = NULL; m_Controls = NULL; CreateQtPartControl(this); } QmitkToFPMDParameterWidget::~QmitkToFPMDParameterWidget() { } void QmitkToFPMDParameterWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkToFPMDParameterWidgetControls; m_Controls->setupUi(parent); this->CreateConnections(); } } void QmitkToFPMDParameterWidget::CreateConnections() { if ( m_Controls ) { connect( m_Controls->m_IntegrationTimeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnChangeIntegrationTimeSpinBox(int)) ); connect( m_Controls->m_ModulationFrequencySpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnChangeModulationFrequencySpinBox(int)) ); } } mitk::ToFImageGrabber* QmitkToFPMDParameterWidget::GetToFImageGrabber() { return this->m_ToFImageGrabber; } void QmitkToFPMDParameterWidget::SetToFImageGrabber(mitk::ToFImageGrabber* aToFImageGrabber) { this->m_ToFImageGrabber = aToFImageGrabber; } void QmitkToFPMDParameterWidget::ActivateAllParameters() { this->m_IntegrationTime = m_Controls->m_IntegrationTimeSpinBox->value(); this->m_IntegrationTime = this->m_ToFImageGrabber->SetIntegrationTime(this->m_IntegrationTime); this->m_ModulationFrequency = m_Controls->m_ModulationFrequencySpinBox->value(); this->m_ModulationFrequency = this->m_ToFImageGrabber->SetModulationFrequency(this->m_ModulationFrequency); //set the PMD calibration according to the check boxes bool boolValue = false; boolValue = m_Controls->m_FPNCalibCB->isChecked(); this->m_ToFImageGrabber->SetBoolProperty("SetFPNCalibration", boolValue); boolValue = m_Controls->m_FPPNCalibCB->isChecked(); this->m_ToFImageGrabber->SetBoolProperty("SetFPPNCalibration", boolValue); boolValue = m_Controls->m_LinearityCalibCB->isChecked(); this->m_ToFImageGrabber->SetBoolProperty("SetLinearityCalibration", boolValue); boolValue = m_Controls->m_LensCorrection->isChecked(); this->m_ToFImageGrabber->SetBoolProperty("SetLensCalibration", boolValue); boolValue = m_Controls->m_ExposureModeCB->isChecked(); this->m_ToFImageGrabber->SetBoolProperty("SetExposureMode", boolValue); //reset the GUI elements m_Controls->m_IntegrationTimeSpinBox->setValue(this->m_IntegrationTime); m_Controls->m_ModulationFrequencySpinBox->setValue(this->m_ModulationFrequency); } void QmitkToFPMDParameterWidget::OnChangeIntegrationTimeSpinBox(int value) { if (this->m_ToFImageGrabber != NULL) { // stop camera if active bool active = m_ToFImageGrabber->IsCameraActive(); if (active) { m_ToFImageGrabber->StopCamera(); } this->m_IntegrationTime = m_Controls->m_IntegrationTimeSpinBox->value(); this->m_IntegrationTime = this->m_ToFImageGrabber->SetIntegrationTime(this->m_IntegrationTime); if (active) { m_ToFImageGrabber->StartCamera(); } } } void QmitkToFPMDParameterWidget::OnChangeModulationFrequencySpinBox(int value) { if (this->m_ToFImageGrabber != NULL) { // stop camera if active bool active = m_ToFImageGrabber->IsCameraActive(); if (active) { m_ToFImageGrabber->StopCamera(); } this->m_ModulationFrequency = m_Controls->m_ModulationFrequencySpinBox->value(); this->m_ModulationFrequency = this->m_ToFImageGrabber->SetModulationFrequency(this->m_ModulationFrequency); if (active) { m_ToFImageGrabber->StartCamera(); } } } diff --git a/Modules/ToFUI/Qmitk/QmitkToFPMDParameterWidget.h b/Modules/ToFUI/Qmitk/QmitkToFPMDParameterWidget.h index 9b24d80916..6f9ec700f1 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFPMDParameterWidget.h +++ b/Modules/ToFUI/Qmitk/QmitkToFPMDParameterWidget.h @@ -1,120 +1,120 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date: 2009-05-20 13:35:09 +0200 (Mi, 20 Mai 2009) $ Version: $Revision: 17332 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _QMITKTOFPMDPARAMETERWIDGET_H_INCLUDED #define _QMITKTOFPMDPARAMETERWIDGET_H_INCLUDED #include "mitkTOFUIExports.h" #include "ui_QmitkToFPMDParameterWidgetControls.h" //QT headers #include //mitk headers #include "mitkToFImageGrabber.h" /** * @brief Widget allowing to connect to different ToF / range cameras (located in module ToFProcessing) * * The widget basically allows to connect/disconnect to different ToF cameras * * @ingroup ToFUI */ class mitkTOFUI_EXPORT QmitkToFPMDParameterWidget :public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkToFPMDParameterWidget(QWidget* p = 0, Qt::WindowFlags f1 = 0); virtual ~QmitkToFPMDParameterWidget(); /* @brief This method is part of the widget an needs not to be called seperately. */ virtual void CreateQtPartControl(QWidget *parent); /* @brief This method is part of the widget an needs not to be called seperately. (Creation of the connections of main and control widget.)*/ virtual void CreateConnections(); /*! - \brief returns the ToFImageGrabber which was provided by the ToFImageGrabberCreator after selecting a camera / player + \brief returns the ToFImageGrabber which was configured after selecting a camera / player \return ToFImageGrabber currently used by the widget */ mitk::ToFImageGrabber* GetToFImageGrabber(); /*! - \brief sets the ToFImageGrabber which was provided by the ToFImageGrabberCreator after selecting a camera / player + \brief sets the ToFImageGrabber which was configured after selecting a camera / player */ void SetToFImageGrabber(mitk::ToFImageGrabber* aToFImageGrabber); /*! \brief activate camera settings according to the parameters from GUI */ void ActivateAllParameters(); signals: /*! \brief This signal is sent if the user has connected the TOF camera. * The ToFImageGrabber is now availiable if the method GetToFImageGrabber() is called. */ void ToFCameraConnected(); /*! \brief This signal is sent if the user has disconnect the TOF camera. */ void ToFCameraDisconnected(); /*! \brief signal that is emitted when the ToF camera is started */ void ToFCameraStart(); /*! \brief signal that is emitted when the ToF camera is stopped */ void ToFCameraStop(); /*! \brief signal that is emitted when a ToF camera is selected in the combo box */ void ToFCameraSelected(int); protected slots: /*! \brief slot updating the member m_IntegrationTime and the parameter "integration time" of the current ToFImageGrabber */ void OnChangeIntegrationTimeSpinBox(int value); /*! \brief slot updating the member m_ModulationFrequency and the parameter "modulation frequency" of the current ToFImageGrabber */ void OnChangeModulationFrequencySpinBox(int value); protected: Ui::QmitkToFPMDParameterWidgetControls* m_Controls; ///< member holding the UI elements of this widget mitk::ToFImageGrabber* m_ToFImageGrabber; ///< member holding the current ToFImageGrabber int m_IntegrationTime; ///< member for the current integration time of the ToF device int m_ModulationFrequency; ///< member for the current modulation frequency of the ToF device private: }; #endif // _QMITKTOFCONNECTIONWIDGET_H_INCLUDED diff --git a/Plugins/org.mitk.diffusionimaging/src/internal/mitkDiffusionImagingActivator.cpp b/Plugins/org.mitk.diffusionimaging/src/internal/mitkDiffusionImagingActivator.cpp index c07be3af1f..9608bb65d1 100644 --- a/Plugins/org.mitk.diffusionimaging/src/internal/mitkDiffusionImagingActivator.cpp +++ b/Plugins/org.mitk.diffusionimaging/src/internal/mitkDiffusionImagingActivator.cpp @@ -1,60 +1,63 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-07-14 19:11:20 +0200 (Tue, 14 Jul 2009) $ Version: $Revision: 18127 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkDiffusionImagingActivator.h" #include "mitkDiffusionImagingObjectFactory.h" #include "QmitkNodeDescriptorManager.h" #include "mitkNodePredicateDataType.h" #include void mitk::DiffusionImagingActivator::start(ctkPluginContext* context) { Q_UNUSED(context) RegisterDiffusionImagingObjectFactory(); QmitkNodeDescriptorManager* manager = QmitkNodeDescriptorManager::GetInstance(); mitk::NodePredicateDataType::Pointer isDiffusionImage = mitk::NodePredicateDataType::New("DiffusionImage"); QmitkNodeDescriptor* desc = new QmitkNodeDescriptor(QObject::tr("DiffusionImage"), QString(":/QmitkDiffusionImaging/QBallData24.png"), isDiffusionImage, manager); manager->AddDescriptor(desc); mitk::NodePredicateDataType::Pointer isTensorImage = mitk::NodePredicateDataType::New("TensorImage"); manager->AddDescriptor(new QmitkNodeDescriptor(QObject::tr("TensorImage"), QString(":/QmitkDiffusionImaging/recontensor.png"), isTensorImage, manager)); mitk::NodePredicateDataType::Pointer isQBallImage = mitk::NodePredicateDataType::New("QBallImage"); manager->AddDescriptor(new QmitkNodeDescriptor(QObject::tr("QBallImage"), QString(":/QmitkDiffusionImaging/reconodf.png"), isQBallImage, manager)); mitk::NodePredicateDataType::Pointer isFiberBundle = mitk::NodePredicateDataType::New("FiberBundle"); manager->AddDescriptor(new QmitkNodeDescriptor(QObject::tr("FiberBundle"), QString(":/QmitkDiffusionImaging/FiberBundle.png"), isFiberBundle, manager)); mitk::NodePredicateDataType::Pointer isFiberBundleX = mitk::NodePredicateDataType::New("FiberBundleX"); manager->AddDescriptor(new QmitkNodeDescriptor(QObject::tr("FiberBundleX"), QString(":/QmitkDiffusionImaging/FiberBundleX.png"), isFiberBundleX, manager)); + mitk::NodePredicateDataType::Pointer isConnectomicsNetwork = mitk::NodePredicateDataType::New("ConnectomicsNetwork"); + manager->AddDescriptor(new QmitkNodeDescriptor(QObject::tr("ConnectomicsNetwork"), QString(":/QmitkDiffusionImaging/ConnectomicsNetwork.png"), isConnectomicsNetwork, manager)); + } void mitk::DiffusionImagingActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } Q_EXPORT_PLUGIN2(org_mitk_diffusionimaging, mitk::DiffusionImagingActivator) diff --git a/Plugins/org.mitk.gui.qt.common.legacy/src/QmitkFunctionality.cpp b/Plugins/org.mitk.gui.qt.common.legacy/src/QmitkFunctionality.cpp index e70d6a235d..e261421d69 100755 --- a/Plugins/org.mitk.gui.qt.common.legacy/src/QmitkFunctionality.cpp +++ b/Plugins/org.mitk.gui.qt.common.legacy/src/QmitkFunctionality.cpp @@ -1,354 +1,357 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkFunctionality.h" #include "internal/QmitkFunctionalityUtil.h" // other includes #include // mitk Includes #include #include // berry Includes #include #include #include // Qmitk Includes #include // Qt Includes #include #include #include #include QmitkFunctionality::QmitkFunctionality() : m_Parent(0) , m_Active(false) , m_Visible(false) , m_SelectionProvider(0) , m_HandlesMultipleDataStorages(false) , m_InDataStorageChanged(false) { m_PreferencesService = berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); } void QmitkFunctionality::SetHandleMultipleDataStorages(bool multiple) { m_HandlesMultipleDataStorages = multiple; } bool QmitkFunctionality::HandlesMultipleDataStorages() const { return m_HandlesMultipleDataStorages; } mitk::DataStorage::Pointer QmitkFunctionality::GetDataStorage() const { mitk::IDataStorageService::Pointer service = berry::Platform::GetServiceRegistry().GetServiceById(mitk::IDataStorageService::ID); if (service.IsNotNull()) { if (m_HandlesMultipleDataStorages) return service->GetActiveDataStorage()->GetDataStorage(); else return service->GetDefaultDataStorage()->GetDataStorage(); } return 0; } mitk::DataStorage::Pointer QmitkFunctionality::GetDefaultDataStorage() const { mitk::IDataStorageService::Pointer service = berry::Platform::GetServiceRegistry().GetServiceById(mitk::IDataStorageService::ID); return service->GetDefaultDataStorage()->GetDataStorage(); } void QmitkFunctionality::CreatePartControl(void* parent) { // scrollArea QScrollArea* scrollArea = new QScrollArea; //QVBoxLayout* scrollAreaLayout = new QVBoxLayout(scrollArea); scrollArea->setFrameShadow(QFrame::Plain); scrollArea->setFrameShape(QFrame::NoFrame); scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); // m_Parent m_Parent = new QWidget; //m_Parent->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding)); this->CreateQtPartControl(m_Parent); //scrollAreaLayout->addWidget(m_Parent); //scrollArea->setLayout(scrollAreaLayout); // set the widget now scrollArea->setWidgetResizable(true); scrollArea->setWidget(m_Parent); // add the scroll area to the real parent (the view tabbar) QWidget* parentQWidget = static_cast(parent); QVBoxLayout* parentLayout = new QVBoxLayout(parentQWidget); parentLayout->setMargin(0); parentLayout->setSpacing(0); parentLayout->addWidget(scrollArea); // finally set the layout containing the scroll area to the parent widget (= show it) parentQWidget->setLayout(parentLayout); this->AfterCreateQtPartControl(); } void QmitkFunctionality::AfterCreateQtPartControl() { // REGISTER DATASTORAGE LISTENER this->GetDefaultDataStorage()->AddNodeEvent.AddListener( mitk::MessageDelegate1 ( this, &QmitkFunctionality::NodeAddedProxy ) ); this->GetDefaultDataStorage()->ChangedNodeEvent.AddListener( mitk::MessageDelegate1 ( this, &QmitkFunctionality::NodeChangedProxy ) ); this->GetDefaultDataStorage()->RemoveNodeEvent.AddListener( mitk::MessageDelegate1 ( this, &QmitkFunctionality::NodeRemovedProxy ) ); // REGISTER PREFERENCES LISTENER berry::IBerryPreferences::Pointer prefs = this->GetPreferences().Cast(); if(prefs.IsNotNull()) prefs->OnChanged.AddListener(berry::MessageDelegate1(this, &QmitkFunctionality::OnPreferencesChanged)); // REGISTER FOR WORKBENCH SELECTION EVENTS m_BlueBerrySelectionListener = berry::ISelectionListener::Pointer(new berry::SelectionChangedAdapter(this , &QmitkFunctionality::BlueBerrySelectionChanged)); this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(/*"org.mitk.views.datamanager",*/ m_BlueBerrySelectionListener); // REGISTER A SELECTION PROVIDER QmitkFunctionalitySelectionProvider::Pointer _SelectionProvider = QmitkFunctionalitySelectionProvider::New(this); m_SelectionProvider = _SelectionProvider.GetPointer(); this->GetSite()->SetSelectionProvider(berry::ISelectionProvider::Pointer(m_SelectionProvider)); // EMULATE INITIAL SELECTION EVENTS // by default a a multi widget is always available this->StdMultiWidgetAvailable(*this->GetActiveStdMultiWidget()); // send datamanager selection this->OnSelectionChanged(this->GetDataManagerSelection()); // send preferences changed event this->OnPreferencesChanged(this->GetPreferences().Cast().GetPointer()); } void QmitkFunctionality::ClosePart() { } void QmitkFunctionality::ClosePartProxy() { this->GetDefaultDataStorage()->AddNodeEvent.RemoveListener( mitk::MessageDelegate1 ( this, &QmitkFunctionality::NodeAddedProxy ) ); this->GetDefaultDataStorage()->RemoveNodeEvent.RemoveListener( mitk::MessageDelegate1 ( this, &QmitkFunctionality::NodeRemovedProxy) ); this->GetDefaultDataStorage()->ChangedNodeEvent.RemoveListener( mitk::MessageDelegate1 ( this, &QmitkFunctionality::NodeChangedProxy ) ); berry::IBerryPreferences::Pointer prefs = this->GetPreferences().Cast(); if(prefs.IsNotNull()) { prefs->OnChanged.RemoveListener(berry::MessageDelegate1(this, &QmitkFunctionality::OnPreferencesChanged)); // flush the preferences here (disabled, everyone should flush them by themselves at the right moment) // prefs->Flush(); } // REMOVE SELECTION PROVIDER this->GetSite()->SetSelectionProvider(berry::ISelectionProvider::Pointer(NULL)); berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService(); if(s) { s->RemovePostSelectionListener(m_BlueBerrySelectionListener); } this->ClosePart(); } QmitkFunctionality::~QmitkFunctionality() { this->Register(); this->ClosePartProxy(); this->UnRegister(false); } void QmitkFunctionality::OnPreferencesChanged( const berry::IBerryPreferences* ) { } void QmitkFunctionality::BlueBerrySelectionChanged(berry::IWorkbenchPart::Pointer sourcepart, berry::ISelection::ConstPointer selection) { if(sourcepart.IsNull() || sourcepart->GetSite()->GetId() != "org.mitk.views.datamanager") return; mitk::DataNodeSelection::ConstPointer _DataNodeSelection = selection.Cast(); this->OnSelectionChanged(this->DataNodeSelectionToVector(_DataNodeSelection)); } bool QmitkFunctionality::IsVisible() const { return m_Visible; } void QmitkFunctionality::SetFocus() { } void QmitkFunctionality::Activated() { } void QmitkFunctionality::Deactivated() { } void QmitkFunctionality::StdMultiWidgetAvailable( QmitkStdMultiWidget& /*stdMultiWidget*/ ) { } void QmitkFunctionality::StdMultiWidgetNotAvailable() { } void QmitkFunctionality::DataStorageChanged() { } QmitkStdMultiWidget* QmitkFunctionality::GetActiveStdMultiWidget( bool reCreateWidget ) { QmitkStdMultiWidget* activeStdMultiWidget = 0; berry::IEditorPart::Pointer editor = this->GetSite()->GetPage()->GetActiveEditor(); if (editor.Cast().IsNotNull()) { activeStdMultiWidget = editor.Cast()->GetStdMultiWidget(); } else if (reCreateWidget) { + mitk::IDataStorageService::Pointer service = + berry::Platform::GetServiceRegistry().GetServiceById(mitk::IDataStorageService::ID); + mitk::DataStorageEditorInput::Pointer editorInput; - editorInput = new mitk::DataStorageEditorInput(); + editorInput = new mitk::DataStorageEditorInput( service->GetActiveDataStorage() ); // open a new multi-widget editor, but do not give it the focus berry::IEditorPart::Pointer editor = this->GetSite()->GetPage()->OpenEditor(editorInput, QmitkStdMultiWidgetEditor::EDITOR_ID, false); activeStdMultiWidget = editor.Cast()->GetStdMultiWidget(); } return activeStdMultiWidget; } void QmitkFunctionality::HandleException( const char* str, QWidget* parent, bool showDialog ) const { //itkGenericOutputMacro( << "Exception caught: " << str ); MITK_ERROR << str; if ( showDialog ) { QMessageBox::critical ( parent, "Exception caught!", str ); } } void QmitkFunctionality::HandleException( std::exception& e, QWidget* parent, bool showDialog ) const { HandleException( e.what(), parent, showDialog ); } void QmitkFunctionality::StdMultiWidgetClosed( QmitkStdMultiWidget& /*stdMultiWidget*/ ) { } void QmitkFunctionality::WaitCursorOn() { QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) ); } void QmitkFunctionality::BusyCursorOn() { QApplication::setOverrideCursor( QCursor(Qt::BusyCursor) ); } void QmitkFunctionality::WaitCursorOff() { this->RestoreOverrideCursor(); } void QmitkFunctionality::BusyCursorOff() { this->RestoreOverrideCursor(); } void QmitkFunctionality::RestoreOverrideCursor() { QApplication::restoreOverrideCursor(); } berry::IPreferences::Pointer QmitkFunctionality::GetPreferences() const { berry::IPreferencesService::Pointer prefService = m_PreferencesService.Lock(); // const_cast workaround for bad programming: const uncorrectness this->GetViewSite() should be const std::string id = "/" + (const_cast(this))->GetViewSite()->GetId(); return prefService.IsNotNull() ? prefService->GetSystemPreferences()->Node(id): berry::IPreferences::Pointer(0); } void QmitkFunctionality::Visible() { } void QmitkFunctionality::Hidden() { } bool QmitkFunctionality::IsExclusiveFunctionality() const { return true; } void QmitkFunctionality::SetVisible( bool visible ) { m_Visible = visible; } void QmitkFunctionality::SetActivated( bool activated ) { m_Active = activated; } bool QmitkFunctionality::IsActivated() const { return m_Active; } diff --git a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp index 114a5262ee..b034b9e5cd 100644 --- a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp +++ b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp @@ -1,942 +1,936 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 18127 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkDataManagerView.h" #include //# Own Includes //## mitk #include "mitkDataStorageEditorInput.h" #include "mitkIDataStorageReference.h" #include "mitkNodePredicateDataType.h" #include "mitkCoreObjectFactory.h" #include "mitkPACSPlugin.h" #include "mitkDataNodeFactory.h" #include "mitkColorProperty.h" #include "mitkCommon.h" #include "mitkDelegateManager.h" #include "mitkNodePredicateData.h" #include "mitkNodePredicateNot.h" #include "mitkNodePredicateProperty.h" #include "mitkEnumerationProperty.h" #include "mitkProperties.h" #include #include #include #include //## Qmitk #include #include #include #include #include #include #include "src/internal/QmitkNodeTableViewKeyFilter.h" #include "src/internal/QmitkInfoDialog.h" //## Berry #include #include #include #include #include #include //# Toolkit Includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkDataNodeObject.h" #include "mitkIContextMenuAction.h" #include "berryIExtensionPointService.h" const std::string QmitkDataManagerView::VIEW_ID = "org.mitk.views.datamanager"; QmitkDataManagerView::QmitkDataManagerView() { } QmitkDataManagerView::~QmitkDataManagerView() { //Remove all registered actions from each descriptor for (std::vector< std::pair< QmitkNodeDescriptor*, QAction* > >::iterator it = m_DescriptorActionList.begin();it != m_DescriptorActionList.end(); it++) { // first== the NodeDescriptor; second== the registered QAction (it->first)->RemoveAction(it->second); } } void QmitkDataManagerView::CreateQtPartControl(QWidget* parent) { m_CurrentRowCount = 0; m_Parent = parent; //# Preferences berry::IPreferencesService::Pointer prefService = berry::Platform::GetServiceRegistry() .GetServiceById(berry::IPreferencesService::ID); berry::IBerryPreferences::Pointer prefs = (prefService->GetSystemPreferences()->Node(VIEW_ID)) .Cast(); assert( prefs ); prefs->OnChanged.AddListener( berry::MessageDelegate1( this , &QmitkDataManagerView::OnPreferencesChanged ) ); //# GUI m_NodeTreeModel = new QmitkDataStorageTreeModel(this->GetDataStorage()); m_NodeTreeModel->setParent( parent ); m_NodeTreeModel->SetPlaceNewNodesOnTop( prefs->GetBool("Place new nodes on top", true) ); m_NodeTreeModel->SetShowHelperObjects( prefs->GetBool("Show helper objects", false) ); m_NodeTreeModel->SetShowNodesContainingNoData( prefs->GetBool("Show nodes containing no data", false) ); m_SurfaceDecimation = prefs->GetBool("Use surface decimation", false); //# Tree View (experimental) m_NodeTreeView = new QTreeView; m_NodeTreeView->setSelectionMode( QAbstractItemView::ExtendedSelection ); m_NodeTreeView->setSelectionBehavior( QAbstractItemView::SelectRows ); m_NodeTreeView->setAlternatingRowColors(true); m_NodeTreeView->setDragEnabled(true); m_NodeTreeView->setDropIndicatorShown(true); m_NodeTreeView->setAcceptDrops(true); m_NodeTreeView->setContextMenuPolicy(Qt::CustomContextMenu); m_NodeTreeView->setModel(m_NodeTreeModel); m_NodeTreeView->installEventFilter(new QmitkNodeTableViewKeyFilter(this)); QObject::connect( m_NodeTreeView, SIGNAL(customContextMenuRequested(const QPoint&)) , this, SLOT(NodeTableViewContextMenuRequested(const QPoint&)) ); QObject::connect( m_NodeTreeModel, SIGNAL(rowsInserted (const QModelIndex&, int, int)) , this, SLOT(NodeTreeViewRowsInserted ( const QModelIndex&, int, int )) ); QObject::connect( m_NodeTreeModel, SIGNAL(rowsRemoved (const QModelIndex&, int, int)) , this, SLOT(NodeTreeViewRowsRemoved( const QModelIndex&, int, int )) ); QObject::connect( m_NodeTreeView->selectionModel() , SIGNAL( selectionChanged ( const QItemSelection &, const QItemSelection & ) ) , this , SLOT( NodeSelectionChanged ( const QItemSelection &, const QItemSelection & ) ) ); //# m_NodeMenu m_NodeMenu = new QMenu(m_NodeTreeView); // # Actions berry::IEditorRegistry* editorRegistry = berry::PlatformUI::GetWorkbench()->GetEditorRegistry(); std::list editors = editorRegistry->GetEditors("*.mitk"); if (editors.size() > 1) { m_ShowInMapper = new QSignalMapper(this); foreach(berry::IEditorDescriptor::Pointer descriptor, editors) { QAction* action = new QAction(QString::fromStdString(descriptor->GetLabel()), this); m_ShowInActions << action; m_ShowInMapper->connect(action, SIGNAL(triggered()), m_ShowInMapper, SLOT(map())); m_ShowInMapper->setMapping(action, QString::fromStdString(descriptor->GetId())); } connect(m_ShowInMapper, SIGNAL(mapped(QString)), this, SLOT(ShowIn(QString))); } QmitkNodeDescriptor* unknownDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetUnknownDataNodeDescriptor(); QmitkNodeDescriptor* imageDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("Image"); QmitkNodeDescriptor* surfaceDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("Surface"); QAction* globalReinitAction = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/Refresh_48.png"), "Global Reinit", this); QObject::connect( globalReinitAction, SIGNAL( triggered(bool) ) , this, SLOT( GlobalReinit(bool) ) ); unknownDataNodeDescriptor->AddAction(globalReinitAction); m_DescriptorActionList.push_back(std::pair(unknownDataNodeDescriptor, globalReinitAction)); QAction* saveAction = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/Save_48.png"), "Save...", this); QObject::connect( saveAction, SIGNAL( triggered(bool) ) , this, SLOT( SaveSelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(saveAction); m_DescriptorActionList.push_back(std::pair(unknownDataNodeDescriptor,saveAction)); QAction* removeAction = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/Remove_48.png"), "Remove", this); QObject::connect( removeAction, SIGNAL( triggered(bool) ) , this, SLOT( RemoveSelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(removeAction); m_DescriptorActionList.push_back(std::pair(unknownDataNodeDescriptor,removeAction)); QAction* reinitAction = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/Refresh_48.png"), "Reinit", this); QObject::connect( reinitAction, SIGNAL( triggered(bool) ) , this, SLOT( ReinitSelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(reinitAction); m_DescriptorActionList.push_back(std::pair(unknownDataNodeDescriptor,reinitAction)); // find contextMenuAction extension points and add them to the node descriptor berry::IExtensionPointService::Pointer extensionPointService = berry::Platform::GetExtensionPointService(); berry::IConfigurationElement::vector cmActions( extensionPointService->GetConfigurationElementsFor("org.mitk.gui.qt.datamanager.contextMenuActions") ); berry::IConfigurationElement::vector::iterator cmActionsIt; std::string cmNodeDescriptorName; std::string cmLabel; std::string cmIcon; std::string cmClass; QmitkNodeDescriptor* tmpDescriptor; QAction* contextMenuAction; QVariant cmActionDataIt; m_ConfElements.clear(); int i=1; for (cmActionsIt = cmActions.begin() ; cmActionsIt != cmActions.end() ; ++cmActionsIt) { cmIcon.erase(); if((*cmActionsIt)->GetAttribute("nodeDescriptorName", cmNodeDescriptorName) && (*cmActionsIt)->GetAttribute("label", cmLabel) && (*cmActionsIt)->GetAttribute("class", cmClass)) { (*cmActionsIt)->GetAttribute("icon", cmIcon); // create context menu entry here tmpDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor(QString::fromStdString(cmNodeDescriptorName)); if(!tmpDescriptor) { MITK_WARN << "cannot add action \"" << cmLabel << "\" because descriptor " << cmNodeDescriptorName << " does not exist"; continue; } contextMenuAction = new QAction( QString::fromStdString(cmLabel), parent); tmpDescriptor->AddAction(contextMenuAction); m_DescriptorActionList.push_back(std::pair(tmpDescriptor,contextMenuAction)); m_ConfElements[contextMenuAction] = *cmActionsIt; cmActionDataIt.setValue(i); contextMenuAction->setData( cmActionDataIt ); connect( contextMenuAction, SIGNAL( triggered(bool) ) , this, SLOT( ContextMenuActionTriggered(bool) ) ); ++i; } } m_OpacitySlider = new QSlider; m_OpacitySlider->setMinimum(0); m_OpacitySlider->setMaximum(100); m_OpacitySlider->setOrientation(Qt::Horizontal); QObject::connect( m_OpacitySlider, SIGNAL( valueChanged(int) ) , this, SLOT( OpacityChanged(int) ) ); QLabel* _OpacityLabel = new QLabel("Opacity: "); QHBoxLayout* _OpacityWidgetLayout = new QHBoxLayout; _OpacityWidgetLayout->setContentsMargins(4,4,4,4); _OpacityWidgetLayout->addWidget(_OpacityLabel); _OpacityWidgetLayout->addWidget(m_OpacitySlider); QWidget* _OpacityWidget = new QWidget; _OpacityWidget->setLayout(_OpacityWidgetLayout); QWidgetAction* opacityAction = new QWidgetAction(this); opacityAction ->setDefaultWidget(_OpacityWidget); QObject::connect( opacityAction , SIGNAL( changed() ) , this, SLOT( OpacityActionChanged() ) ); unknownDataNodeDescriptor->AddAction(opacityAction , false); m_DescriptorActionList.push_back(std::pair(unknownDataNodeDescriptor,opacityAction)); m_ColorButton = new QPushButton; m_ColorButton->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum); //m_ColorButton->setText("Change color"); QObject::connect( m_ColorButton, SIGNAL( clicked() ) , this, SLOT( ColorChanged() ) ); QLabel* _ColorLabel = new QLabel("Color: "); _ColorLabel->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); QHBoxLayout* _ColorWidgetLayout = new QHBoxLayout; _ColorWidgetLayout->setContentsMargins(4,4,4,4); _ColorWidgetLayout->addWidget(_ColorLabel); _ColorWidgetLayout->addWidget(m_ColorButton); QWidget* _ColorWidget = new QWidget; _ColorWidget->setLayout(_ColorWidgetLayout); QWidgetAction* colorAction = new QWidgetAction(this); colorAction->setDefaultWidget(_ColorWidget); QObject::connect( colorAction, SIGNAL( changed() ) , this, SLOT( ColorActionChanged() ) ); unknownDataNodeDescriptor->AddAction(colorAction, false); m_DescriptorActionList.push_back(std::pair(unknownDataNodeDescriptor,colorAction)); m_TextureInterpolation = new QAction("Texture Interpolation", this); m_TextureInterpolation->setCheckable ( true ); QObject::connect( m_TextureInterpolation, SIGNAL( changed() ) , this, SLOT( TextureInterpolationChanged() ) ); QObject::connect( m_TextureInterpolation, SIGNAL( toggled(bool) ) , this, SLOT( TextureInterpolationToggled(bool) ) ); imageDataNodeDescriptor->AddAction(m_TextureInterpolation, false); m_DescriptorActionList.push_back(std::pair(imageDataNodeDescriptor,m_TextureInterpolation)); m_SurfaceRepresentation = new QAction("Surface Representation", this); m_SurfaceRepresentation->setMenu(new QMenu); QObject::connect( m_SurfaceRepresentation->menu(), SIGNAL( aboutToShow() ) , this, SLOT( SurfaceRepresentationMenuAboutToShow() ) ); surfaceDataNodeDescriptor->AddAction(m_SurfaceRepresentation, false); m_DescriptorActionList.push_back(std::pair(surfaceDataNodeDescriptor, m_SurfaceRepresentation)); QAction* showOnlySelectedNodes = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/ShowSelectedNode_48.png") , "Show only selected nodes", this); QObject::connect( showOnlySelectedNodes, SIGNAL( triggered(bool) ) , this, SLOT( ShowOnlySelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(showOnlySelectedNodes); m_DescriptorActionList.push_back(std::pair(unknownDataNodeDescriptor, showOnlySelectedNodes)); QAction* toggleSelectedVisibility = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/InvertShowSelectedNode_48.png") , "Toggle visibility", this); QObject::connect( toggleSelectedVisibility, SIGNAL( triggered(bool) ) , this, SLOT( ToggleVisibilityOfSelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(toggleSelectedVisibility); m_DescriptorActionList.push_back(std::pair(unknownDataNodeDescriptor,toggleSelectedVisibility)); QAction* actionShowInfoDialog = new QAction(QIcon(":/org.mitk.gui.qt.datamanager/ShowDataInfo_48.png") , "Details...", this); QObject::connect( actionShowInfoDialog, SIGNAL( triggered(bool) ) , this, SLOT( ShowInfoDialogForSelectedNodes(bool) ) ); unknownDataNodeDescriptor->AddAction(actionShowInfoDialog); m_DescriptorActionList.push_back(std::pair(unknownDataNodeDescriptor,actionShowInfoDialog)); QAction* otsuFilterAction = new QAction("Apply Otsu Filter", this); QObject::connect( otsuFilterAction, SIGNAL( triggered(bool) ) , this, SLOT( OtsuFilter(bool) ) ); // Otsu filter does not work properly, remove it temporarily // imageDataNodeDescriptor->AddAction(otsuFilterAction); // m_DescriptorActionList.push_back(std::pair(imageDataNodeDescriptor,otsuFilterAction)); QGridLayout* _DndFrameWidgetLayout = new QGridLayout; _DndFrameWidgetLayout->addWidget(m_NodeTreeView, 0, 0); _DndFrameWidgetLayout->setContentsMargins(0,0,0,0); m_DndFrameWidget = new QmitkDnDFrameWidget(m_Parent); m_DndFrameWidget->setLayout(_DndFrameWidgetLayout); QVBoxLayout* layout = new QVBoxLayout(parent); layout->addWidget(m_DndFrameWidget); layout->setContentsMargins(0,0,0,0); m_Parent->setLayout(layout); } void QmitkDataManagerView::SetFocus() { } void QmitkDataManagerView::ContextMenuActionTriggered( bool ) { QAction* action = qobject_cast ( sender() ); - + std::map::iterator it = m_ConfElements.find( action ); if( it == m_ConfElements.end() ) { MITK_WARN << "associated conf element for action " << action->text().toStdString() << " not found"; return; } berry::IConfigurationElement::Pointer confElem = it->second; mitk::IContextMenuAction* contextMenuAction = confElem->CreateExecutableExtension("class"); std::string className; std::string smoothed; confElem->GetAttribute("class", className); confElem->GetAttribute("smoothed", smoothed); if(className == "QmitkThresholdAction") { contextMenuAction->SetDataStorage(this->GetDataStorage()); } else if(className == "QmitkCreatePolygonModelAction") { contextMenuAction->SetDataStorage(this->GetDataStorage()); if(smoothed == "false") { contextMenuAction->SetSmoothed(false); } else { contextMenuAction->SetSmoothed(true); } contextMenuAction->SetDecimated(m_SurfaceDecimation); } else if(className == "QmitkStatisticsAction") { contextMenuAction->SetFunctionality(this); } contextMenuAction->Run( this->GetCurrentSelection() ); // run the action } void QmitkDataManagerView::OnPreferencesChanged(const berry::IBerryPreferences* prefs) { if( m_NodeTreeModel->GetPlaceNewNodesOnTopFlag() != prefs->GetBool("Place new nodes on top", true) ) m_NodeTreeModel->SetPlaceNewNodesOnTop( !m_NodeTreeModel->GetPlaceNewNodesOnTopFlag() ); - + if( m_NodeTreeModel->GetShowHelperObjectsFlag()!= prefs->GetBool("Show helper objects", false) ) m_NodeTreeModel->SetShowHelperObjects( !m_NodeTreeModel->GetShowHelperObjectsFlag() ); if( m_NodeTreeModel->GetShowNodesContainingNoDataFlag()!= prefs->GetBool("Show nodes containing no data", false) ) m_NodeTreeModel->SetShowNodesContainingNoData( !m_NodeTreeModel->GetShowNodesContainingNoDataFlag() ); m_NodeTreeView->expandAll(); m_SurfaceDecimation = prefs->GetBool("Use surface decimation", false); this->GlobalReinit(); } void QmitkDataManagerView::NodeTableViewContextMenuRequested( const QPoint & pos ) { QModelIndex selected = m_NodeTreeView->indexAt ( pos ); mitk::DataNode::Pointer node = m_NodeTreeModel->GetNode(selected); QList selectedNodes = this->GetCurrentSelection(); if(!selectedNodes.isEmpty()) { m_NodeMenu->clear(); QList actions; if(selectedNodes.size() == 1 ) { actions = QmitkNodeDescriptorManager::GetInstance()->GetActions(node); for(QList::iterator it = actions.begin(); it != actions.end(); ++it) { (*it)->setData(QVariant::fromValue(node.GetPointer())); } } else actions = QmitkNodeDescriptorManager::GetInstance()->GetActions(selectedNodes); if (!m_ShowInActions.isEmpty()) { QMenu* showInMenu = m_NodeMenu->addMenu("Show In"); showInMenu->addActions(m_ShowInActions); } m_NodeMenu->addActions(actions); m_NodeMenu->popup(QCursor::pos()); } } void QmitkDataManagerView::OpacityChanged(int value) { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex()); if(node) { float opacity = static_cast(value)/100.0f; node->SetFloatProperty("opacity", opacity); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } - - MITK_INFO << "slider changed"; } void QmitkDataManagerView::OpacityActionChanged() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex()); if(node) { float opacity = 0.0; if(node->GetFloatProperty("opacity", opacity)) { m_OpacitySlider->setValue(static_cast(opacity*100)); } } - MITK_INFO << "changed"; } void QmitkDataManagerView::ColorChanged() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex()); if(node) { QColor color = QColorDialog::getColor(); m_ColorButton->setAutoFillBackground(true); node->SetProperty("color",mitk::ColorProperty::New(color.red()/255.0,color.green()/255.0,color.blue()/255.0)); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } - - MITK_INFO << "slider changed"; } void QmitkDataManagerView::ColorActionChanged() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex()); if(node) { mitk::Color color; mitk::ColorProperty::Pointer colorProp; node->GetProperty(colorProp,"color"); if(colorProp.IsNull()) return; color = colorProp->GetValue(); QString styleSheet = "background-color:rgb("; styleSheet.append(QString::number(color[0]*255)); styleSheet.append(","); styleSheet.append(QString::number(color[1]*255)); styleSheet.append(","); styleSheet.append(QString::number(color[2]*255)); styleSheet.append(")"); m_ColorButton->setStyleSheet(styleSheet); } - MITK_INFO << "changed"; } void QmitkDataManagerView::TextureInterpolationChanged() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex()); if(node) { bool textureInterpolation = false; node->GetBoolProperty("texture interpolation", textureInterpolation); m_TextureInterpolation->setChecked(textureInterpolation); } } void QmitkDataManagerView::TextureInterpolationToggled( bool checked ) { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex()); if(node) { node->SetBoolProperty("texture interpolation", checked); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkDataManagerView::SurfaceRepresentationMenuAboutToShow() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex()); if(!node) return; mitk::EnumerationProperty* representationProp = dynamic_cast (node->GetProperty("material.representation")); if(!representationProp) return; // clear menu m_SurfaceRepresentation->menu()->clear(); QAction* tmp; // create menu entries for(mitk::EnumerationProperty::EnumConstIterator it=representationProp->Begin(); it!=representationProp->End() ; it++) { tmp = m_SurfaceRepresentation->menu()->addAction(QString::fromStdString(it->second)); tmp->setCheckable(true); if(it->second == representationProp->GetValueAsString()) { tmp->setChecked(true); } QObject::connect( tmp, SIGNAL( triggered(bool) ) , this, SLOT( SurfaceRepresentationActionToggled(bool) ) ); } } void QmitkDataManagerView::SurfaceRepresentationActionToggled( bool /*checked*/ ) { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_NodeTreeView->selectionModel()->currentIndex()); if(!node) return; mitk::EnumerationProperty* representationProp = dynamic_cast (node->GetProperty("material.representation")); if(!representationProp) return; QAction* senderAction = qobject_cast ( QObject::sender() ); if(!senderAction) return; std::string activatedItem = senderAction->text().toStdString(); if ( activatedItem != representationProp->GetValueAsString() ) { if ( representationProp->IsValidEnumerationValue( activatedItem ) ) { representationProp->SetValue( activatedItem ); representationProp->InvokeEvent( itk::ModifiedEvent() ); representationProp->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } } void QmitkDataManagerView::SaveSelectedNodes( bool ) { QModelIndexList indexesOfSelectedRows = m_NodeTreeView->selectionModel()->selectedRows(); mitk::DataNode* node = 0; unsigned int indexesOfSelectedRowsSize = indexesOfSelectedRows.size(); for (unsigned int i = 0; iGetNode(indexesOfSelectedRows.at(i)); // if node is not defined or if the node contains geometry data do not remove it if ( node != 0 ) { mitk::BaseData::Pointer data = node->GetData(); if (data.IsNotNull()) { QString error; try { CommonFunctionality::SaveBaseData( data.GetPointer(), node->GetName().c_str() ); } catch(std::exception& e) { error = e.what(); } catch(...) { error = "Unknown error occured"; } if( !error.isEmpty() ) QMessageBox::critical( m_Parent, "Error saving...", error ); } } } } void QmitkDataManagerView::ReinitSelectedNodes( bool ) { mitk::IRenderWindowPart* renderWindow = this->OpenRenderWindowPart(); QList selectedNodes = this->GetCurrentSelection(); foreach(mitk::DataNode::Pointer node, selectedNodes) { mitk::BaseData::Pointer basedata = node->GetData(); if (basedata.IsNotNull()) { renderWindow->GetRenderingManager()->InitializeViews( basedata->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); renderWindow->GetRenderingManager()->RequestUpdateAll(); } } } void QmitkDataManagerView::RemoveSelectedNodes( bool ) { QModelIndexList indexesOfSelectedRows = m_NodeTreeView->selectionModel()->selectedRows(); if(indexesOfSelectedRows.size() < 1) { return; } std::vector selectedNodes; mitk::DataNode* node = 0; QString question = tr("Do you really want to remove "); for (QModelIndexList::iterator it = indexesOfSelectedRows.begin() ; it != indexesOfSelectedRows.end(); it++) { node = m_NodeTreeModel->GetNode(*it); // if node is not defined or if the node contains geometry data do not remove it if ( node != 0 /*& strcmp(node->GetData()->GetNameOfClass(), "Geometry2DData") != 0*/ ) { selectedNodes.push_back(node); question.append(QString::fromStdString(node->GetName())); question.append(", "); } } // remove the last two characters = ", " question = question.remove(question.size()-2, 2); question.append(" from data storage?"); QMessageBox::StandardButton answerButton = QMessageBox::question( m_Parent , tr("DataManager") , question , QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); if(answerButton == QMessageBox::Yes) { for (std::vector::iterator it = selectedNodes.begin() ; it != selectedNodes.end(); it++) { node = *it; this->GetDataStorage()->Remove(node); this->GlobalReinit(false); } } } void QmitkDataManagerView::MakeAllNodesInvisible( bool ) { QList nodes = m_NodeTreeModel->GetNodeSet(); foreach(mitk::DataNode::Pointer node, nodes) { node->SetVisibility(false); } //mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataManagerView::ShowOnlySelectedNodes( bool ) { QList selectedNodes = this->GetCurrentSelection(); QList allNodes = m_NodeTreeModel->GetNodeSet(); foreach(mitk::DataNode::Pointer node, allNodes) { node->SetVisibility(selectedNodes.contains(node)); } //mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataManagerView::ToggleVisibilityOfSelectedNodes( bool ) { QList selectedNodes = this->GetCurrentSelection(); bool isVisible = false; foreach(mitk::DataNode::Pointer node, selectedNodes) { isVisible = false; node->GetBoolProperty("visible", isVisible); node->SetVisibility(!isVisible); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataManagerView::ShowInfoDialogForSelectedNodes( bool ) { QList selectedNodes = this->GetCurrentSelection(); QmitkInfoDialog _QmitkInfoDialog(selectedNodes, this->m_Parent); _QmitkInfoDialog.exec(); } void QmitkDataManagerView::Load( bool ) { QStringList fileNames = QFileDialog::getOpenFileNames(NULL, "Load data", "", mitk::CoreObjectFactory::GetInstance()->GetFileExtensions()); for ( QStringList::Iterator it = fileNames.begin(); it != fileNames.end(); ++it ) { FileOpen((*it).toAscii(), 0); } } void QmitkDataManagerView::FileOpen( const char * fileName, mitk::DataNode* parentNode ) { mitk::DataNodeFactory::Pointer factory = mitk::DataNodeFactory::New(); try { factory->SetFileName( fileName ); QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) ); factory->Update(); for ( unsigned int i = 0 ; i < factory->GetNumberOfOutputs( ); ++i ) { mitk::DataNode::Pointer node = factory->GetOutput( i ); if ( ( node.IsNotNull() ) && ( node->GetData() != NULL ) ) { this->GetDataStorage()->Add(node, parentNode); mitk::BaseData::Pointer basedata = node->GetData(); mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); //mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } } catch ( itk::ExceptionObject & ex ) { itkGenericOutputMacro( << "Exception during file open: " << ex ); } QApplication::restoreOverrideCursor(); } QItemSelectionModel *QmitkDataManagerView::GetDataNodeSelectionModel() const { return m_NodeTreeView->selectionModel(); } void QmitkDataManagerView::GlobalReinit( bool ) { mitk::IRenderWindowPart* renderWindow = this->OpenRenderWindowPart(); // get all nodes that have not set "includeInBoundingBox" to false mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox" , mitk::BoolProperty::New(false))); mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetSubset(pred); // calculate bounding geometry of these nodes mitk::TimeSlicedGeometry::Pointer bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs, "visible"); // initialize the views to the bounding geometry renderWindow->GetRenderingManager()->InitializeViews(bounds); } void QmitkDataManagerView::OnSelectionChanged( berry::IWorkbenchPart::Pointer part , const QList& selection ) { if(part.GetPointer() == this) return; QItemSelection newSelection; m_NodeTreeView->selectionModel()->reset(); foreach(mitk::DataNode::Pointer node, selection) { QModelIndex treeIndex = m_NodeTreeModel->GetIndex(node); if(treeIndex.isValid()) newSelection.select(treeIndex, treeIndex); } m_NodeTreeView->selectionModel()->select(newSelection, QItemSelectionModel::SelectCurrent); } void QmitkDataManagerView::OtsuFilter( bool ) { QList selectedNodes = this->GetCurrentSelection(); mitk::Image::Pointer mitkImage = 0; foreach(mitk::DataNode::Pointer node, selectedNodes) { mitkImage = dynamic_cast( node->GetData() ); if(mitkImage.IsNull()) continue; try { // get selected mitk image const unsigned short dim = 3; typedef short InputPixelType; typedef unsigned char OutputPixelType; typedef itk::Image< InputPixelType, dim > InputImageType; typedef itk::Image< OutputPixelType, dim > OutputImageType; typedef itk::OtsuThresholdImageFilter< InputImageType, OutputImageType > FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetOutsideValue( 1 ); filter->SetInsideValue( 0 ); InputImageType::Pointer itkImage; mitk::CastToItkImage(mitkImage, itkImage); filter->SetInput( itkImage ); filter->Update(); mitk::DataNode::Pointer resultNode = mitk::DataNode::New(); std::string nameOfResultImage = node->GetName(); nameOfResultImage.append("Otsu"); resultNode->SetProperty("name", mitk::StringProperty::New(nameOfResultImage) ); resultNode->SetProperty("binary", mitk::BoolProperty::New(true) ); resultNode->SetData( mitk::ImportItkImage ( filter->GetOutput() ) ); this->GetDataStorage()->Add(resultNode, node); } catch( std::exception& err ) { MITK_ERROR(this->GetClassName()) << err.what(); } } } -void QmitkDataManagerView::NodeTreeViewRowsRemoved ( +void QmitkDataManagerView::NodeTreeViewRowsRemoved ( const QModelIndex & /*parent*/, int /*start*/, int /*end*/ ) { m_CurrentRowCount = m_NodeTreeModel->rowCount(); } void QmitkDataManagerView::NodeTreeViewRowsInserted( const QModelIndex & parent, int, int ) { m_NodeTreeView->setExpanded(parent, true); // a new row was inserted if( m_CurrentRowCount == 0 && m_NodeTreeModel->rowCount() == 1 ) { this->OpenRenderWindowPart(); m_CurrentRowCount = m_NodeTreeModel->rowCount(); /* std::vector nodes = m_NodeTreeModel->GetNodeSet(); if(nodes.size() == 1) { QModelIndex treeIndex = m_NodeTreeModel->GetIndex(nodes.front()); m_NodeTreeView->selectionModel()->setCurrentIndex( treeIndex, QItemSelectionModel::ClearAndSelect ); } */ } } void QmitkDataManagerView::NodeSelectionChanged( const QItemSelection & /*selected*/, const QItemSelection & /*deselected*/ ) { QList nodes = m_NodeTreeModel->GetNodeSet(); foreach(mitk::DataNode::Pointer node, nodes) { if ( node.IsNotNull() ) node->SetBoolProperty("selected", false); } nodes.clear(); nodes = this->GetCurrentSelection(); foreach(mitk::DataNode::Pointer node, nodes) { if ( node.IsNotNull() ) node->SetBoolProperty("selected", true); } //changing the selection does NOT require any rendering processes! //mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataManagerView::ShowIn(const QString &editorId) { berry::IWorkbenchPage::Pointer page = this->GetSite()->GetPage(); berry::IEditorInput::Pointer input(new mitk::DataStorageEditorInput(this->GetDataStorageReference())); page->OpenEditor(input, editorId.toStdString(), false, berry::IWorkbenchPage::MATCH_ID); } mitk::IRenderWindowPart* QmitkDataManagerView::OpenRenderWindowPart() { return this->GetRenderWindowPart(QmitkAbstractView::ACTIVATE | QmitkAbstractView::OPEN); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/files.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging/files.cmake index 6d734cf9ed..68930fafcd 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/files.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/files.cmake @@ -1,120 +1,121 @@ set(SRC_CPP_FILES QmitkODFDetailsWidget.cpp QmitkODFRenderWidget.cpp QmitkPartialVolumeAnalysisWidget.cpp QmitkIVIMWidget.cpp QmitkTbssRoiAnalysisWidget.cpp QmitkResidualAnalysisWidget.cpp QmitkResidualViewWidget.cpp ) set(INTERNAL_CPP_FILES mitkPluginActivator.cpp QmitkQBallReconstructionView.cpp QmitkPreprocessingView.cpp QmitkDiffusionDicomImportView.cpp QmitkDiffusionQuantificationView.cpp QmitkTensorReconstructionView.cpp QmitkDiffusionImagingPublicPerspective.cpp QmitkControlVisualizationPropertiesView.cpp QmitkODFDetailsView.cpp QmitkGibbsTrackingView.cpp QmitkStochasticFiberTrackingView.cpp QmitkFiberProcessingView.cpp QmitkFiberBundleDeveloperView.cpp QmitkPartialVolumeAnalysisView.cpp QmitkIVIMView.cpp QmitkTractbasedSpatialStatisticsView.cpp QmitkTbssTableModel.cpp QmitkTbssMetaTableModel.cpp QmitkTbssSkeletonizationView.cpp Connectomics/QmitkBrainNetworkAnalysisView.cpp Connectomics/QmitkNetworkHistogramCanvas.cpp ) set(UI_FILES src/internal/QmitkQBallReconstructionViewControls.ui src/internal/QmitkPreprocessingViewControls.ui src/internal/QmitkDiffusionDicomImportViewControls.ui src/internal/QmitkDiffusionQuantificationViewControls.ui src/internal/QmitkTensorReconstructionViewControls.ui src/internal/QmitkControlVisualizationPropertiesViewControls.ui src/internal/QmitkODFDetailsViewControls.ui src/internal/QmitkGibbsTrackingViewControls.ui src/internal/QmitkStochasticFiberTrackingViewControls.ui src/internal/QmitkFiberProcessingViewControls.ui src/internal/QmitkFiberBundleDeveloperViewControls.ui src/internal/QmitkPartialVolumeAnalysisViewControls.ui src/internal/QmitkIVIMViewControls.ui src/internal/QmitkTractbasedSpatialStatisticsViewControls.ui src/internal/QmitkTbssSkeletonizationViewControls.ui src/internal/Connectomics/QmitkBrainNetworkAnalysisViewControls.ui ) set(MOC_H_FILES src/internal/mitkPluginActivator.h src/internal/QmitkQBallReconstructionView.h src/internal/QmitkPreprocessingView.h src/internal/QmitkDiffusionDicomImportView.h src/internal/QmitkDiffusionImagingPublicPerspective.h src/internal/QmitkDiffusionQuantificationView.h src/internal/QmitkTensorReconstructionView.h src/internal/QmitkControlVisualizationPropertiesView.h src/internal/QmitkODFDetailsView.h src/QmitkODFRenderWidget.h src/QmitkODFDetailsWidget.h src/internal/QmitkGibbsTrackingView.h src/internal/QmitkStochasticFiberTrackingView.h src/internal/QmitkFiberProcessingView.h src/internal/QmitkFiberBundleDeveloperView.h src/internal/QmitkPartialVolumeAnalysisView.h src/QmitkPartialVolumeAnalysisWidget.h src/internal/QmitkIVIMView.h src/internal/QmitkTractbasedSpatialStatisticsView.h src/internal/QmitkTbssSkeletonizationView.h src/QmitkTbssRoiAnalysisWidget.h src/QmitkResidualAnalysisWidget.h src/QmitkResidualViewWidget.h src/internal/Connectomics/QmitkBrainNetworkAnalysisView.h src/internal/Connectomics/QmitkNetworkHistogramCanvas.h ) set(CACHED_RESOURCE_FILES # list of resource files which can be used by the plug-in # system without loading the plug-ins shared library, # for example the icon used in the menu and tabs for the # plug-in views in the workbench plugin.xml resources/preprocessing.png resources/dwiimport.png resources/quantification.png resources/reconodf.png resources/recontensor.png resources/vizControls.png resources/OdfDetails.png resources/GibbsTracking.png resources/FiberBundleOperations.png resources/PartialVolumeAnalysis_24.png resources/IVIM_48.png resources/stochFB.png resources/tbss.png resources/QmitkBrainNetworkAnalysisViewIcon_48.png + resources/arrow.png ) set(QRC_FILES # uncomment the following line if you want to use Qt resources resources/QmitkDiffusionImaging.qrc #resources/QmitkTractbasedSpatialStatisticsView.qrc ) 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/resources/ConnectomicsNetwork.png b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/ConnectomicsNetwork.png new file mode 100644 index 0000000000..2c3c896bb8 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/ConnectomicsNetwork.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkDiffusionImaging.qrc b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkDiffusionImaging.qrc index 1a2a557966..87088bac16 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkDiffusionImaging.qrc +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkDiffusionImaging.qrc @@ -1,36 +1,37 @@ qball.png tensor.png dwi.png dwiimport.png quantification.png reconodf.png recontensor.png texIntONIcon.png texIntOFFIcon.png vizControls.png Refresh_48.png QBallData24.png glyphsoff_C.png glyphsoff_S.png glyphsoff_T.png glyphson_C.png glyphson_S.png glyphson_T.png FiberBundle.png FiberBundleX.png + ConnectomicsNetwork.png rectangle.png circle.png polygon.png color24.gif color48.gif color64.gif crosshair.png paint2.png IVIM_48.png reset.png MapperEfx2D.png diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/resources/arrow.png b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/arrow.png new file mode 100644 index 0000000000..ab5d3e805f Binary files /dev/null and b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/arrow.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkODFRenderWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkODFRenderWidget.cpp index 2e0d524f66..2fff514fea 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkODFRenderWidget.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkODFRenderWidget.cpp @@ -1,131 +1,124 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkODFRenderWidget.h" #include #include #include #include #include QmitkODFRenderWidget::QmitkODFRenderWidget(QWidget* parent, Qt::WindowFlags f): QWidget(parent, f) { //create Layouts QmitkODFRenderWidgetLayout = new QHBoxLayout( this ); //Set Layout to widget this->setLayout(QmitkODFRenderWidgetLayout); //Create RenderWindow m_RenderWindow = new QmitkRenderWindow(this, "odf render widget"); m_RenderWindow->setMaximumSize(300,300); m_RenderWindow->GetRenderer()->SetMapperID( mitk::BaseRenderer::Standard3D ); + //m_RenderWindow->SetLayoutIndex( 3 ); QmitkODFRenderWidgetLayout->addWidget( m_RenderWindow ); } QmitkODFRenderWidget::~QmitkODFRenderWidget() { } void QmitkODFRenderWidget::GenerateODF( itk::OrientationDistributionFunction odf ) { + try + { m_Surface = mitk::Surface::New(); m_ds = mitk::StandaloneDataStorage::New(); m_Node = mitk::DataNode::New(); vtkPolyData* m_TemplateOdf = itk::OrientationDistributionFunction::GetBaseMesh(); vtkPolyData *polyData = vtkPolyData::New(); vtkPoints *points = vtkPoints::New(); vtkFloatArray *scalars = vtkFloatArray::New(); - double max = -10000; - double min = 10000; - for (int i=0; imax) - max = odf[i]; - - if (std::fabs(max)GetPoints()->GetPoint(i,p); double val = odf[i]; p[0] *= val; p[1] *= val; p[2] *= val; points->InsertPoint(i,p); -// scalars->InsertTuple1(i, 1-val/max); - scalars->InsertTuple1(i, 1-val/max); + + scalars->InsertTuple1(i, 1-val); } polyData->SetPoints(points); vtkCellArray* polys = m_TemplateOdf->GetPolys(); polyData->SetPolys(polys); polyData->GetPointData()->SetScalars(scalars); polys->Delete(); scalars->Delete(); points->Delete(); m_Surface->SetVtkPolyData(polyData); m_Node->SetData(m_Surface); mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); vtkLookupTable* vtkLut = mitkLut->GetVtkLookupTable(); vtkLut->SetTableRange(0, 1); vtkLut->Build(); mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); mitkLutProp->SetLookupTable(mitkLut); m_Node->SetProperty( "LookupTable", mitkLutProp ); m_Node->SetProperty("scalar visibility", mitk::BoolProperty::New(true)); m_Node->SetProperty("color mode", mitk::BoolProperty::New(true)); m_Node->SetProperty("material.specularCoefficient", mitk::FloatProperty::New(0.5)); m_ds->Add(m_Node); m_RenderWindow->GetRenderer()->SetDataStorage( m_ds ); // adjust camera to current plane rotation mitk::Geometry2D::ConstPointer worldGeometry = mitk::GlobalInteraction::GetInstance()->GetFocus()->GetCurrentWorldGeometry2D(); mitk::PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast( worldGeometry.GetPointer() ); mitk::Vector3D normal = worldPlaneGeometry->GetNormal(); mitk::Vector3D up = worldPlaneGeometry->GetAxisVector(1); normal.Normalize(); up.Normalize(); vtkSmartPointer cam = vtkSmartPointer::New(); const double camPos[3] = {normal[0],normal[1],normal[2]}; const double camUp[3] = {up[0],up[1],up[2]}; cam->SetPosition(camPos); cam->SetViewUp(camUp); cam->SetParallelProjection(1); m_RenderWindow->GetRenderer()->GetVtkRenderer()->SetActiveCamera(cam); + m_RenderWindow->update(); + } + catch (...) + { + + } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkPartialVolumeAnalysisWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkPartialVolumeAnalysisWidget.cpp index 137b295c9f..ee1fc5c8ac 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkPartialVolumeAnalysisWidget.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkPartialVolumeAnalysisWidget.cpp @@ -1,156 +1,156 @@ /*========================================================================= Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkPartialVolumeAnalysisWidget.h" #include "mitkHistogramGenerator.h" #include "mitkPartialVolumeAnalysisClusteringCalculator.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include QmitkPartialVolumeAnalysisWidget::QmitkPartialVolumeAnalysisWidget( QWidget * parent ) : QmitkPlotWidget(parent) { // this->SetAxisTitle( QwtPlot::xBottom, "Grayvalue" ); // this->SetAxisTitle( QwtPlot::yLeft, "Probability" ); // this->Replot(); m_Plot->setCanvasLineWidth(0); m_Plot->setMargin(0); } QmitkPartialVolumeAnalysisWidget::~QmitkPartialVolumeAnalysisWidget() { } void QmitkPartialVolumeAnalysisWidget::DrawGauss() { } void QmitkPartialVolumeAnalysisWidget::ClearItemModel() { } void QmitkPartialVolumeAnalysisWidget::SetParameters( ParamsType *params, ResultsType *results, HistType *hist ) { this->Clear(); if(params != 0 && results != 0) { hist->Print(); params->Print(); results->Print(); for(unsigned int i=0; iGetXVals()); m_Vals.push_back(hist->GetHVals()); std::vector *xVals = hist->GetXVals(); std::vector *yVals = hist->GetHVals(); std::vector *fiberVals = new std::vector(results->GetFiberVals()); std::vector *nonFiberVals = new std::vector(results->GetNonFiberVals()); std::vector *mixedVals = new std::vector(results->GetMixedVals()); std::vector *combiVals = new std::vector(results->GetCombiVals()); double fiberFA = 0.0; double weights = 0.0; std::cout << "x, y, fiber, nonFiber, mixed, combi" << std::endl; for(int i=0; isize(); ++i) { fiberFA += xVals->at(i) * fiberVals->at(i); weights += fiberVals->at(i); std::cout << xVals->at(i) << " " << yVals->at(i) << " " << fiberVals->at(i) << " " << nonFiberVals->at(i) << " " << mixedVals->at(i) << " " << combiVals->at(i) << std::endl; } fiberFA = fiberFA / weights; QPen pen( Qt::SolidLine ); pen.setWidth(2); pen.setColor(Qt::black); int curveId = this->InsertCurve( "histogram" ); this->SetCurveData( curveId, (*m_Vals[0]), (*m_Vals[1]) ); this->SetCurvePen( curveId, pen ); // this->SetCurveTitle( curveId, "Image Histogram" ); curveId = this->InsertCurve( "fiber" ); this->SetCurveData(curveId, (*hist->GetXVals()), (*fiberVals)); this->SetCurvePen( curveId, QPen( Qt::NoPen ) ); - this->SetCurveBrush(curveId, QBrush(QColor::fromRgbF(0,1,0,.5), Qt::SolidPattern)); + this->SetCurveBrush(curveId, QBrush(QColor::fromRgbF(1,0,0,.5), Qt::SolidPattern)); m_Vals.push_back(fiberVals); curveId = this->InsertCurve( "nonfiber" ); this->SetCurveData( curveId, (*hist->GetXVals()), (*nonFiberVals) ); this->SetCurvePen( curveId, QPen( Qt::NoPen ) ); - this->SetCurveBrush(curveId, QBrush(QColor::fromRgbF(1,0,0,.5), Qt::SolidPattern)); + this->SetCurveBrush(curveId, QBrush(QColor::fromRgbF(0,1,0,.5), Qt::SolidPattern)); m_Vals.push_back(nonFiberVals); curveId = this->InsertCurve( "mixed" ); this->SetCurveData( curveId, (*hist->GetXVals()), (*mixedVals) ); this->SetCurvePen( curveId, QPen( Qt::NoPen ) ); this->SetCurveBrush(curveId, QBrush(QColor::fromRgbF(.7,.7,.7,.5), Qt::SolidPattern)); m_Vals.push_back(mixedVals); pen.setColor(Qt::blue); curveId = this->InsertCurve( "combi" ); this->SetCurveData( curveId, (*hist->GetXVals()), (*combiVals) ); this->SetCurvePen( curveId, pen ); m_Vals.push_back(combiVals); } this->Replot(); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkBrainNetworkAnalysisView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkBrainNetworkAnalysisView.cpp index 10a3a57089..e8e6630bcb 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkBrainNetworkAnalysisView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkBrainNetworkAnalysisView.cpp @@ -1,537 +1,549 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ // ####### Blueberry includes ####### #include #include // ####### Qmitk includes ####### #include "QmitkBrainNetworkAnalysisView.h" #include "QmitkStdMultiWidget.h" // ####### Qt includes ####### #include // ####### ITK includes ####### #include // ####### MITK includes ####### #include #include "mitkConnectomicsSyntheticNetworkGenerator.h" #include "mitkConnectomicsSimulatedAnnealingManager.h" #include "mitkConnectomicsSimulatedAnnealingPermutationModularity.h" #include "mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h" // Includes for image casting between ITK and MITK #include "mitkImageCast.h" #include "mitkITKImageImport.h" #include "mitkImageAccessByItk.h" const std::string QmitkBrainNetworkAnalysisView::VIEW_ID = "org.mitk.views.brainnetworkanalysis"; QmitkBrainNetworkAnalysisView::QmitkBrainNetworkAnalysisView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) , m_ConnectomicsNetworkCreator( mitk::ConnectomicsNetworkCreator::New() ) , m_demomode( false ) , m_currentIndex( 0 ) { } QmitkBrainNetworkAnalysisView::~QmitkBrainNetworkAnalysisView() { } void QmitkBrainNetworkAnalysisView::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::QmitkBrainNetworkAnalysisViewControls; m_Controls->setupUi( parent ); QObject::connect( m_Controls->convertToRGBAImagePushButton, SIGNAL(clicked()), this, SLOT(OnConvertToRGBAImagePushButtonClicked()) ); QObject::connect( m_Controls->networkifyPushButton, SIGNAL(clicked()), this, SLOT(OnNetworkifyPushButtonClicked()) ); QObject::connect( m_Controls->syntheticNetworkCreationPushButton, SIGNAL(clicked()), this, SLOT(OnSyntheticNetworkCreationPushButtonClicked()) ); QObject::connect( (QObject*)( m_Controls->syntheticNetworkComboBox ), SIGNAL(currentIndexChanged (int)), this, SLOT(OnSyntheticNetworkComboBoxCurrentIndexChanged(int)) ); QObject::connect( (QObject*)( m_Controls->modularizePushButton ), SIGNAL(clicked()), this, SLOT(OnModularizePushButtonClicked()) ); } // GUI is different for developer and demo mode m_demomode = false; if( m_demomode ) { this->m_Controls->convertToRGBAImagePushButton->hide(); this->m_Controls->networkifyPushButton->show(); this->m_Controls->networkifyPushButton->setText( "Create Network" ); - this->m_Controls->modularizePushButton->show(); + this->m_Controls->modularizePushButton->hide(); - this->m_Controls->syntheticNetworkOptionsGroupBox->hide(); + this->m_Controls->syntheticNetworkOptionsGroupBox->show(); + //--------------------------- fill comboBox--------------------------- + this->m_Controls->syntheticNetworkComboBox->insertItem(0,"Regular lattice"); + this->m_Controls->syntheticNetworkComboBox->insertItem(1,"Heterogenic sphere"); + this->m_Controls->syntheticNetworkComboBox->insertItem(2,"Random network"); } else { this->m_Controls->convertToRGBAImagePushButton->show(); this->m_Controls->networkifyPushButton->show(); this->m_Controls->networkifyPushButton->setText( "Networkify" ); this->m_Controls->modularizePushButton->show(); this->m_Controls->syntheticNetworkOptionsGroupBox->show(); //--------------------------- fill comboBox--------------------------- this->m_Controls->syntheticNetworkComboBox->insertItem(0,"Regular lattice"); this->m_Controls->syntheticNetworkComboBox->insertItem(1,"Heterogenic sphere"); this->m_Controls->syntheticNetworkComboBox->insertItem(2,"Random network"); this->m_Controls->syntheticNetworkComboBox->insertItem(3,"Scale free network"); this->m_Controls->syntheticNetworkComboBox->insertItem(4,"Small world network"); } } void QmitkBrainNetworkAnalysisView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkBrainNetworkAnalysisView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkBrainNetworkAnalysisView::WipeDisplay() { m_Controls->numberOfVerticesLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH ); m_Controls->numberOfEdgesLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH ); m_Controls->numberOfSelfLoopsLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH ); m_Controls->averageDegreeLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH ); m_Controls->connectionDensityLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH ); m_Controls->efficiencyLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH ); m_Controls->globalClusteringLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH ); m_Controls->betweennessNetworkHistogramCanvas->SetHistogram( NULL ); m_Controls->degreeNetworkHistogramCanvas->SetHistogram( NULL ); m_Controls->shortestPathNetworkHistogramCanvas->SetHistogram( NULL ); m_Controls->betweennessNetworkHistogramCanvas->update(); m_Controls->degreeNetworkHistogramCanvas->update(); m_Controls->shortestPathNetworkHistogramCanvas->update(); } void QmitkBrainNetworkAnalysisView::OnSelectionChanged( std::vector nodes ) { this->WipeDisplay(); // iterate all selected objects, adjust warning visibility for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_Controls->lblWarning->setVisible( false ); return; } { mitk::ConnectomicsNetwork* network = dynamic_cast( node->GetData() ); if( node.IsNotNull() && network ) { m_Controls->lblWarning->setVisible( false ); int noVertices = network->GetNumberOfVertices(); int noEdges = network->GetNumberOfEdges(); int noSelfLoops = network->GetNumberOfSelfLoops(); double averageDegree = network->GetAverageDegree(); double connectionDensity = network->GetConnectionDensity(); double globalClustering = network->GetGlobalClusteringCoefficient(); m_Controls->numberOfVerticesLabel->setText( QString::number( noVertices ) ); m_Controls->numberOfEdgesLabel->setText( QString::number( noEdges ) ); m_Controls->numberOfSelfLoopsLabel->setText( QString::number( noSelfLoops ) ); m_Controls->averageDegreeLabel->setText( QString::number( averageDegree ) ); m_Controls->connectionDensityLabel->setText( QString::number( connectionDensity ) ); m_Controls->globalClusteringLabel->setText( QString::number( globalClustering ) ); mitk::ConnectomicsNetwork::Pointer connectomicsNetwork( network ); mitk::ConnectomicsHistogramsContainer *histogramContainer = histogramCache[ connectomicsNetwork ]; m_Controls->betweennessNetworkHistogramCanvas->SetHistogram( histogramContainer->GetBetweennessHistogram() ); m_Controls->degreeNetworkHistogramCanvas->SetHistogram( histogramContainer->GetDegreeHistogram() ); m_Controls->shortestPathNetworkHistogramCanvas->SetHistogram( histogramContainer->GetShortestPathHistogram() ); m_Controls->betweennessNetworkHistogramCanvas->DrawProfiles(); m_Controls->degreeNetworkHistogramCanvas->DrawProfiles(); m_Controls->shortestPathNetworkHistogramCanvas->DrawProfiles(); double efficiency = histogramContainer->GetShortestPathHistogram()->GetEfficiency(); m_Controls->efficiencyLabel->setText( QString::number( efficiency ) ); return; } } } m_Controls->lblWarning->setVisible( true ); } void QmitkBrainNetworkAnalysisView::OnSyntheticNetworkComboBoxCurrentIndexChanged(int currentIndex) { m_currentIndex = currentIndex; switch (m_currentIndex) { case 0: this->m_Controls->parameterOneLabel->setText( "Nodes per side" ); this->m_Controls->parameterTwoLabel->setText( "Internode distance" ); this->m_Controls->parameterOneSpinBox->setEnabled( true ); this->m_Controls->parameterOneSpinBox->setValue( 5 ); this->m_Controls->parameterTwoDoubleSpinBox->setEnabled( true ); this->m_Controls->parameterTwoDoubleSpinBox->setMaximum( 999.999 ); this->m_Controls->parameterTwoDoubleSpinBox->setValue( 10.0 ); break; case 1: this->m_Controls->parameterOneLabel->setText( "Number of nodes" ); this->m_Controls->parameterTwoLabel->setText( "Radius" ); this->m_Controls->parameterOneSpinBox->setEnabled( true ); this->m_Controls->parameterOneSpinBox->setValue( 1000 ); this->m_Controls->parameterTwoDoubleSpinBox->setEnabled( true ); this->m_Controls->parameterTwoDoubleSpinBox->setMaximum( 999.999 ); this->m_Controls->parameterTwoDoubleSpinBox->setValue( 50.0 ); break; case 2: this->m_Controls->parameterOneLabel->setText( "Number of nodes" ); this->m_Controls->parameterTwoLabel->setText( "Edge percentage" ); this->m_Controls->parameterOneSpinBox->setEnabled( true ); this->m_Controls->parameterOneSpinBox->setValue( 100 ); this->m_Controls->parameterTwoDoubleSpinBox->setEnabled( true ); this->m_Controls->parameterTwoDoubleSpinBox->setMaximum( 1.0 ); this->m_Controls->parameterTwoDoubleSpinBox->setValue( 0.5 ); break; case 3: //GenerateSyntheticScaleFreeNetwork( network, 1000 ); break; case 4: //GenerateSyntheticSmallWorldNetwork( network, 1000 ); break; default: this->m_Controls->parameterOneLabel->setText( "Parameter 1" ); this->m_Controls->parameterTwoLabel->setText( "Paramater 2" ); this->m_Controls->parameterOneSpinBox->setEnabled( false ); this->m_Controls->parameterOneSpinBox->setValue( 0 ); this->m_Controls->parameterTwoDoubleSpinBox->setEnabled( false ); this->m_Controls->parameterTwoDoubleSpinBox->setValue( 0.0 ); } } void QmitkBrainNetworkAnalysisView::OnSyntheticNetworkCreationPushButtonClicked() { mitk::ConnectomicsSyntheticNetworkGenerator::Pointer generator = mitk::ConnectomicsSyntheticNetworkGenerator::New(); mitk::DataNode::Pointer networkNode = mitk::DataNode::New(); int parameterOne = this->m_Controls->parameterOneSpinBox->value(); double parameterTwo = this->m_Controls->parameterTwoDoubleSpinBox->value(); ////add network to datastorage networkNode->SetData( generator->CreateSyntheticNetwork( m_currentIndex, parameterOne, parameterTwo ) ); networkNode->SetName( mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_DEFAULT_CNF_NAME ); this->GetDefaultDataStorage()->Add( networkNode ); return; } void QmitkBrainNetworkAnalysisView::OnConvertToRGBAImagePushButtonClicked() { std::vector nodes = this->GetDataManagerSelection(); if (nodes.empty()) return; mitk::DataNode* node = nodes.front(); if (!node) { // Nothing selected. Inform the user and return QMessageBox::information( NULL, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS_CREATION, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_SELECTION_WARNING); return; } // here we have a valid mitk::DataNode // a node itself is not very useful, we need its data item (the image) mitk::BaseData* data = node->GetData(); if (data) { // test if this data item is an image or not (could also be a surface or something totally different) mitk::Image* image = dynamic_cast( data ); if (image) { std::stringstream message; std::string name; message << mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_PERFORMING_IMAGE_PROCESSING_FOR_IMAGE; if (node->GetName(name)) { // a property called "name" was found for this DataNode message << "'" << name << "'"; } message << "."; MITK_INFO << message.str(); // Convert to RGBA AccessByItk( image, TurnIntoRGBA ); this->GetDefaultDataStorage()->GetNamedNode( mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_DEFAULT_RGBA_NAME )->GetData()->SetGeometry( node->GetData()->GetGeometry() ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } } template < typename TPixel, unsigned int VImageDimension > void QmitkBrainNetworkAnalysisView::TurnIntoRGBA( itk::Image* inputImage) { typedef itk::RGBAPixel< unsigned char > RGBAPixelType; typedef itk::Image< TPixel, VImageDimension > TemplateImageType; typedef itk::Image< RGBAPixelType, VImageDimension > RGBAImageType; itk::ImageRegionIterator it_inputImage(inputImage, inputImage->GetLargestPossibleRegion()); TPixel minimumValue, maximumValue; it_inputImage.GoToBegin(); maximumValue = minimumValue = it_inputImage.Value(); for(it_inputImage.GoToBegin(); !it_inputImage.IsAtEnd(); ++it_inputImage) { if ( it_inputImage.Value() < minimumValue ) { minimumValue = it_inputImage.Value(); } else { if ( it_inputImage.Value() > maximumValue ) { maximumValue = it_inputImage.Value(); } } } int range = int ( maximumValue - minimumValue ); //needs to be castable to int int offset = int ( minimumValue ); if ( range < 0 ) //error { return; } std::vector< unsigned int > histogram; histogram.resize( range + 1, 0 ); for(it_inputImage.GoToBegin(); !it_inputImage.IsAtEnd(); ++it_inputImage) { histogram[ int ( it_inputImage.Value() ) - offset ] += 1; } int gapCounter = 0; //this variable will be used to count the empty labels //stores how much has to be subtracted from the image to remove gaps std::vector< TPixel > subtractionStorage; subtractionStorage.resize( range + 1, 0 ); for( int index = 0; index <= range; index++ ) { if( histogram[ index ] == 0 ) { gapCounter++; //if the label is empty, increase gapCounter } else { subtractionStorage[ index ] = TPixel ( gapCounter ); } } //remove gaps from label image for(it_inputImage.GoToBegin(); !it_inputImage.IsAtEnd(); ++it_inputImage) { it_inputImage.Value() = it_inputImage.Value() - subtractionStorage[ int ( it_inputImage.Value() ) ]; } // create colour vector std::vector< RGBAPixelType > lookupTable; { RGBAPixelType backgroundColour; for( int elementIndex = 0; elementIndex < 4; ++elementIndex ) { backgroundColour.SetElement( elementIndex, 0 ); } lookupTable.push_back( backgroundColour ); for(int colourNumber = 0; colourNumber < range ; ++colourNumber) { RGBAPixelType colour; for( int elementIndex = 0; elementIndex < 3; ++elementIndex ) { colour.SetElement( elementIndex, rand() % 256 ); } colour.SetAlpha( 255 ); lookupTable.push_back( colour ); } } // create RGBA image typename RGBAImageType::Pointer rgbaImage = RGBAImageType::New(); rgbaImage->SetRegions(inputImage->GetLargestPossibleRegion().GetSize()); rgbaImage->SetSpacing(inputImage->GetSpacing()); rgbaImage->SetOrigin(inputImage->GetOrigin()); rgbaImage->Allocate(); //fill with appropriate colours itk::ImageRegionIterator it_rgbaImage(rgbaImage, rgbaImage->GetLargestPossibleRegion()); for(it_inputImage.GoToBegin(), it_rgbaImage.GoToBegin(); !it_inputImage.IsAtEnd(); ++it_inputImage, ++it_rgbaImage) { it_rgbaImage.Value() = lookupTable[ int ( it_inputImage.Value() ) ]; } mitk::Image::Pointer mitkRGBAImage = mitk::ImportItkImage( rgbaImage ); mitk::DataNode::Pointer rgbaImageNode = mitk::DataNode::New(); rgbaImageNode->SetData(mitkRGBAImage); rgbaImageNode->SetProperty(mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_NAME, mitk::StringProperty::New(mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_DEFAULT_RGBA_NAME)); rgbaImageNode->SetBoolProperty( mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_VOLUMERENDERING, true); this->GetDefaultDataStorage()->Add( rgbaImageNode ); } void QmitkBrainNetworkAnalysisView::OnNetworkifyPushButtonClicked() { std::vector nodes = this->GetDataManagerSelection(); if ( nodes.empty() ) { QMessageBox::information( NULL, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS_CREATION, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_SELECTION_WARNING); return; } if (! ( nodes.size() == 2 ) ) { QMessageBox::information( NULL, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS_CREATION, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_SELECTION_WARNING); return; } - mitk::DataNode* node = nodes.front(); - mitk::DataNode* fiberNode = nodes.at(1); + mitk::DataNode* firstNode = nodes.front(); + mitk::DataNode* secondNode = nodes.at(1); - if (!node) + if (!firstNode) { // Nothing selected. Inform the user and return QMessageBox::information( NULL, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS_CREATION, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_SELECTION_WARNING); return; } // here we have a valid mitk::DataNode // a node itself is not very useful, we need its data item (the image) - mitk::BaseData* data = node->GetData(); - mitk::BaseData* fiberData = fiberNode->GetData(); - if (data && fiberData) + mitk::BaseData* firstData = firstNode->GetData(); + mitk::BaseData* secondData = secondNode->GetData(); + if (firstData && secondData) { // test if this data item is an image or not (could also be a surface or something totally different) - mitk::Image* image = dynamic_cast( data ); - mitk::FiberBundleX* fiberBundle = dynamic_cast( fiberData ); + mitk::Image* image = dynamic_cast( firstData ); + mitk::FiberBundleX* fiberBundle = dynamic_cast( secondData ); + + // check whether order was switched + if (! (image && fiberBundle) ) + { + image = dynamic_cast( secondData ); + fiberBundle = dynamic_cast( firstData ); + } + if (image && fiberBundle) { m_ConnectomicsNetworkCreator->SetSegmentation( image ); m_ConnectomicsNetworkCreator->SetFiberBundle( fiberBundle ); m_ConnectomicsNetworkCreator->CreateNetworkFromFibersAndSegmentation(); mitk::DataNode::Pointer networkNode = mitk::DataNode::New(); ////add network to datastorage networkNode->SetData( m_ConnectomicsNetworkCreator->GetNetwork() ); networkNode->SetName( mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_DEFAULT_CNF_NAME ); this->GetDefaultDataStorage()->Add( networkNode ); } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkBrainNetworkAnalysisView::OnModularizePushButtonClicked() { std::vector nodes = this->GetDataManagerSelection(); if ( nodes.empty() ) { QMessageBox::information( NULL, "Modularization calculation", "Please select exactly one network."); return; } for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { return; } { mitk::ConnectomicsNetwork* network = dynamic_cast( node->GetData() ); if( node.IsNotNull() && network ) { typedef mitk::ConnectomicsSimulatedAnnealingPermutationModularity::ToModuleMapType MappingType; int depthOfModuleRecursive( 2 ); double startTemperature( 2.0 ); double stepSize( 4.0 ); mitk::ConnectomicsNetwork::Pointer connectomicsNetwork( network ); mitk::ConnectomicsSimulatedAnnealingManager::Pointer manager = mitk::ConnectomicsSimulatedAnnealingManager::New(); mitk::ConnectomicsSimulatedAnnealingPermutationModularity::Pointer permutation = mitk::ConnectomicsSimulatedAnnealingPermutationModularity::New(); mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::Pointer costFunction = mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::New(); permutation->SetCostFunction( costFunction.GetPointer() ); permutation->SetNetwork( connectomicsNetwork ); permutation->SetDepth( depthOfModuleRecursive ); permutation->SetStepSize( stepSize ); manager->SetPermutation( permutation.GetPointer() ); manager->RunSimulatedAnnealing( startTemperature, stepSize ); MappingType mapping = permutation->GetMapping(); MappingType::iterator iter = mapping.begin(); MappingType::iterator end = mapping.end(); int loop( 0 ); while( iter != end ) { MBI_DEBUG << "Vertex " << iter->first << " belongs to module " << iter->second ; MBI_INFO << "Vertex " << iter->first << " belongs to module " << iter->second ; iter++; } MBI_DEBUG << "Overall number of modules is " << permutation->getNumberOfModules( &mapping ) ; MBI_DEBUG << "Cost is " << costFunction->Evaluate( network, &mapping ) ; MBI_INFO << "Overall number of modules is " << permutation->getNumberOfModules( &mapping ) ; MBI_INFO << "Cost is " << costFunction->Evaluate( network, &mapping ) ; return; } } } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp index c479449fa7..b7d2674574 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp @@ -1,1640 +1,1768 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date: 2009-05-28 17:19:30 +0200 (Do, 28 Mai 2009) $ Version: $Revision: 17495 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkControlVisualizationPropertiesView.h" #include "mitkNodePredicateDataType.h" #include "mitkDataNodeObject.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include "mitkResliceMethodProperty.h" #include "mitkRenderingManager.h" #include "mitkTbssImage.h" #include "mitkPlanarFigure.h" #include "mitkFiberBundleX.h" #include "QmitkDataStorageComboBox.h" #include "QmitkStdMultiWidget.h" #include "mitkFiberBundleInteractor.h" #include "mitkPlanarFigureInteractor.h" #include #include #include #include "mitkGlobalInteraction.h" #include "mitkGeometry2D.h" +#include "mitkSegTool2D.h" #include "berryIWorkbenchWindow.h" #include "berryIWorkbenchPage.h" #include "berryISelectionService.h" #include "berryConstants.h" #include "berryPlatformUI.h" #include "itkRGBAPixel.h" #include #include "qwidgetaction.h" #include "qcolordialog.h" const std::string QmitkControlVisualizationPropertiesView::VIEW_ID = "org.mitk.views.controlvisualizationpropertiesview"; using namespace berry; struct CvpSelListener : ISelectionListener { berryObjectMacro(CvpSelListener); CvpSelListener(QmitkControlVisualizationPropertiesView* view) { m_View = view; } void ApplySettings(mitk::DataNode::Pointer node) { bool tex_int; node->GetBoolProperty("texture interpolation", tex_int); if(tex_int) { m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexON); m_View->m_Controls->m_TextureIntON->setChecked(true); m_View->m_TexIsOn = true; } else { m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexOFF); m_View->m_Controls->m_TextureIntON->setChecked(false); m_View->m_TexIsOn = false; } int val; node->GetIntProperty("ShowMaxNumber", val); m_View->m_Controls->m_ShowMaxNumber->setValue(val); m_View->m_Controls->m_NormalizationDropdown->setCurrentIndex(dynamic_cast(node->GetProperty("Normalization"))->GetValueAsId()); float fval; node->GetFloatProperty("Scaling",fval); m_View->m_Controls->m_ScalingFactor->setValue(fval); m_View->m_Controls->m_AdditionalScaling->setCurrentIndex(dynamic_cast(node->GetProperty("ScaleBy"))->GetValueAsId()); node->GetFloatProperty("IndexParam1",fval); m_View->m_Controls->m_IndexParam1->setValue(fval); node->GetFloatProperty("IndexParam2",fval); m_View->m_Controls->m_IndexParam2->setValue(fval); } void DoSelectionChanged(ISelection::ConstPointer selection) { // save current selection in member variable m_View->m_CurrentSelection = selection.Cast(); m_View->m_Controls->m_VisibleOdfsON_T->setVisible(false); m_View->m_Controls->m_VisibleOdfsON_S->setVisible(false); m_View->m_Controls->m_VisibleOdfsON_C->setVisible(false); m_View->m_Controls->m_TextureIntON->setVisible(false); m_View->m_Controls->m_ImageControlsFrame->setVisible(false); m_View->m_Controls->m_PlanarFigureControlsFrame->setVisible(false); m_View->m_Controls->m_BundleControlsFrame->setVisible(false); m_View->m_SelectedNode = 0; if(m_View->m_CurrentSelection.IsNull()) return; if(m_View->m_CurrentSelection->Size() == 1) { mitk::DataNodeObject::Pointer nodeObj = m_View->m_CurrentSelection->Begin()->Cast(); if(nodeObj.IsNotNull()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); - if(dynamic_cast(node->GetData()) != 0) - { - m_View->m_Controls->m_PlanarFigureControlsFrame->setVisible(true); - m_View->m_SelectedNode = node; - - float val; - node->GetFloatProperty("planarfigure.line.width", val); - m_View->m_Controls->m_PFWidth->setValue((int)(val*10.0)); - - QString label = "Width %1"; - label = label.arg(val); - m_View->m_Controls->label_pfwidth->setText(label); - - float color[3]; - node->GetColor( color, NULL, "planarfigure.default.line.color"); - QString styleSheet = "background-color:rgb("; - styleSheet.append(QString::number(color[0]*255.0)); - styleSheet.append(","); - styleSheet.append(QString::number(color[1]*255.0)); - styleSheet.append(","); - styleSheet.append(QString::number(color[2]*255.0)); - styleSheet.append(")"); - m_View->m_Controls->m_PFColor->setAutoFillBackground(true); - m_View->m_Controls->m_PFColor->setStyleSheet(styleSheet); - - node->GetColor( color, NULL, "color"); - styleSheet = "background-color:rgb("; - styleSheet.append(QString::number(color[0]*255.0)); - styleSheet.append(","); - styleSheet.append(QString::number(color[1]*255.0)); - styleSheet.append(","); - styleSheet.append(QString::number(color[2]*255.0)); - styleSheet.append(")"); - - m_View->PlanarFigureFocus(); - } + // check if node has data, + // if some helper nodes are shown in the DataManager, the GetData() returns 0x0 which would lead to SIGSEV + mitk::BaseData* nodeData = node->GetData(); - if(dynamic_cast(node->GetData()) != 0) + if(nodeData != NULL ) { - m_View->m_Controls->m_BundleControlsFrame->setVisible(true); - m_View->m_SelectedNode = node; - - if(m_View->m_CurrentPickingNode != 0 && node.GetPointer() != m_View->m_CurrentPickingNode) + if(dynamic_cast(nodeData) != 0) { - m_View->m_Controls->m_Crosshair->setEnabled(false); + m_View->m_Controls->m_PlanarFigureControlsFrame->setVisible(true); + m_View->m_SelectedNode = node; + + float val; + node->GetFloatProperty("planarfigure.line.width", val); + m_View->m_Controls->m_PFWidth->setValue((int)(val*10.0)); + + QString label = "Width %1"; + label = label.arg(val); + m_View->m_Controls->label_pfwidth->setText(label); + + float color[3]; + node->GetColor( color, NULL, "planarfigure.default.line.color"); + QString styleSheet = "background-color:rgb("; + styleSheet.append(QString::number(color[0]*255.0)); + styleSheet.append(","); + styleSheet.append(QString::number(color[1]*255.0)); + styleSheet.append(","); + styleSheet.append(QString::number(color[2]*255.0)); + styleSheet.append(")"); + m_View->m_Controls->m_PFColor->setAutoFillBackground(true); + m_View->m_Controls->m_PFColor->setStyleSheet(styleSheet); + + node->GetColor( color, NULL, "color"); + styleSheet = "background-color:rgb("; + styleSheet.append(QString::number(color[0]*255.0)); + styleSheet.append(","); + styleSheet.append(QString::number(color[1]*255.0)); + styleSheet.append(","); + styleSheet.append(QString::number(color[2]*255.0)); + styleSheet.append(")"); + + m_View->PlanarFigureFocus(); } - else + + if(dynamic_cast(nodeData) != 0) { - m_View->m_Controls->m_Crosshair->setEnabled(true); - } + m_View->m_Controls->m_BundleControlsFrame->setVisible(true); + m_View->m_SelectedNode = node; - float val; - node->GetFloatProperty("TubeRadius", val); - m_View->m_Controls->m_TubeRadius->setValue((int)(val * 100.0)); - - QString label = "Radius %1"; - label = label.arg(val); - m_View->m_Controls->label_tuberadius->setText(label); - - int width; - node->GetIntProperty("LineWidth", width); - m_View->m_Controls->m_LineWidth->setValue(width); - - label = "Width %1"; - label = label.arg(width); - m_View->m_Controls->label_linewidth->setText(label); - - float range; - node->GetFloatProperty("Fiber2DSliceThickness",range); - label = "Range %1"; - label = label.arg(range*0.1); - m_View->m_Controls->label_range->setText(label); - -// mitk::ColorProperty* nodecolor= mitk::ColorProperty::New(); -// node->GetProperty(nodecolor,"color"); -// m_View->m_Controls->m_Color->setAutoFillBackground(true); -// QString styleSheet = "background-color:rgb("; -// styleSheet.append(QString::number(nodecolor->GetColor().GetRed()*255.0)); -// styleSheet.append(","); -// styleSheet.append(QString::number(nodecolor->GetColor().GetGreen()*255.0)); -// styleSheet.append(","); -// styleSheet.append(QString::number(nodecolor->GetColor().GetBlue()*255.0)); -// styleSheet.append(")"); -// m_View->m_Controls->m_Color->setStyleSheet(styleSheet); + if(m_View->m_CurrentPickingNode != 0 && node.GetPointer() != m_View->m_CurrentPickingNode) + { + m_View->m_Controls->m_Crosshair->setEnabled(false); + } + else + { + m_View->m_Controls->m_Crosshair->setEnabled(true); + } + float val; + node->GetFloatProperty("TubeRadius", val); + m_View->m_Controls->m_TubeRadius->setValue((int)(val * 100.0)); - } + QString label = "Radius %1"; + label = label.arg(val); + m_View->m_Controls->label_tuberadius->setText(label); + + int width; + node->GetIntProperty("LineWidth", width); + m_View->m_Controls->m_LineWidth->setValue(width); + + label = "Width %1"; + label = label.arg(width); + m_View->m_Controls->label_linewidth->setText(label); + + float range; + node->GetFloatProperty("Fiber2DSliceThickness",range); + label = "Range %1"; + label = label.arg(range*0.1); + m_View->m_Controls->label_range->setText(label); + + } + + } // check node data != NULL } } if(m_View->m_CurrentSelection->Size() > 0 && m_View->m_SelectedNode == 0) { m_View->m_Controls->m_ImageControlsFrame->setVisible(true); bool foundDiffusionImage = false; bool foundQBIVolume = false; bool foundTensorVolume = false; bool foundImage = false; bool foundMultipleOdfImages = false; bool foundRGBAImage = false; bool foundTbssImage = false; // do something with the selected items if(m_View->m_CurrentSelection) { // iterate selection for (IStructuredSelection::iterator i = m_View->m_CurrentSelection->Begin(); i != m_View->m_CurrentSelection->End(); ++i) { // extract datatree node if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); - // only look at interesting types - if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0) - { - foundDiffusionImage = true; - bool tex_int; - node->GetBoolProperty("texture interpolation", tex_int); - if(tex_int) - { - m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexON); - m_View->m_Controls->m_TextureIntON->setChecked(true); - m_View->m_TexIsOn = true; - } - else - { - m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexOFF); - m_View->m_Controls->m_TextureIntON->setChecked(false); - m_View->m_TexIsOn = false; - } - int val; - node->GetIntProperty("DisplayChannel", val); - m_View->m_Controls->m_DisplayIndex->setValue(val); - - QString label = "Channel %1"; - label = label.arg(val); - m_View->m_Controls->label_channel->setText(label); + mitk::BaseData* nodeData = node->GetData(); - int maxVal = (dynamic_cast* >(node->GetData()))->GetVectorImage()->GetVectorLength(); - m_View->m_Controls->m_DisplayIndex->setMaximum(maxVal-1); - } - - if(QString("TbssImage").compare(node->GetData()->GetNameOfClass())==0) + if(nodeData != NULL ) { - foundTbssImage = true; - bool tex_int; - node->GetBoolProperty("texture interpolation", tex_int); - if(tex_int) + // only look at interesting types + if(QString("DiffusionImage").compare(nodeData->GetNameOfClass())==0) { - m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexON); - m_View->m_Controls->m_TextureIntON->setChecked(true); - m_View->m_TexIsOn = true; + foundDiffusionImage = true; + bool tex_int; + node->GetBoolProperty("texture interpolation", tex_int); + if(tex_int) + { + m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexON); + m_View->m_Controls->m_TextureIntON->setChecked(true); + m_View->m_TexIsOn = true; + } + else + { + m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexOFF); + m_View->m_Controls->m_TextureIntON->setChecked(false); + m_View->m_TexIsOn = false; + } + int val; + node->GetIntProperty("DisplayChannel", val); + m_View->m_Controls->m_DisplayIndex->setValue(val); + + QString label = "Channel %1"; + label = label.arg(val); + m_View->m_Controls->label_channel->setText(label); + + int maxVal = (dynamic_cast* >(nodeData))->GetVectorImage()->GetVectorLength(); + m_View->m_Controls->m_DisplayIndex->setMaximum(maxVal-1); } - else + + if(QString("TbssImage").compare(nodeData->GetNameOfClass())==0) { - m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexOFF); - m_View->m_Controls->m_TextureIntON->setChecked(false); - m_View->m_TexIsOn = false; + foundTbssImage = true; + bool tex_int; + node->GetBoolProperty("texture interpolation", tex_int); + if(tex_int) + { + m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexON); + m_View->m_Controls->m_TextureIntON->setChecked(true); + m_View->m_TexIsOn = true; + } + else + { + m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexOFF); + m_View->m_Controls->m_TextureIntON->setChecked(false); + m_View->m_TexIsOn = false; + } + int val; + node->GetIntProperty("DisplayChannel", val); + m_View->m_Controls->m_DisplayIndex->setValue(val); + + QString label = "Channel %1"; + label = label.arg(val); + m_View->m_Controls->label_channel->setText(label); + + int maxVal = (dynamic_cast(nodeData))->GetImage()->GetVectorLength(); + m_View->m_Controls->m_DisplayIndex->setMaximum(maxVal-1); } - int val; - node->GetIntProperty("DisplayChannel", val); - m_View->m_Controls->m_DisplayIndex->setValue(val); - QString label = "Channel %1"; - label = label.arg(val); - m_View->m_Controls->label_channel->setText(label); - int maxVal = (dynamic_cast(node->GetData()))->GetImage()->GetVectorLength(); - m_View->m_Controls->m_DisplayIndex->setMaximum(maxVal-1); - } - - - else if(QString("QBallImage").compare(node->GetData()->GetNameOfClass())==0) - { - foundMultipleOdfImages = foundQBIVolume || foundTensorVolume; - foundQBIVolume = true; - ApplySettings(node); - } - - else if(QString("TensorImage").compare(node->GetData()->GetNameOfClass())==0) - { - foundMultipleOdfImages = foundQBIVolume || foundTensorVolume; - foundTensorVolume = true; - ApplySettings(node); - } - - else if(QString("Image").compare(node->GetData()->GetNameOfClass())==0) - { - foundImage = true; - mitk::Image::Pointer img = dynamic_cast(node->GetData()); - if(img.IsNotNull() && img->GetPixelType().GetPixelTypeId() == typeid(itk::RGBAPixel) ) + else if(QString("QBallImage").compare(nodeData->GetNameOfClass())==0) { - foundRGBAImage = true; + foundMultipleOdfImages = foundQBIVolume || foundTensorVolume; + foundQBIVolume = true; + ApplySettings(node); } - bool tex_int; - node->GetBoolProperty("texture interpolation", tex_int); - if(tex_int) + else if(QString("TensorImage").compare(nodeData->GetNameOfClass())==0) { - m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexON); - m_View->m_Controls->m_TextureIntON->setChecked(true); - m_View->m_TexIsOn = true; + foundMultipleOdfImages = foundQBIVolume || foundTensorVolume; + foundTensorVolume = true; + ApplySettings(node); } - else + + else if(QString("Image").compare(nodeData->GetNameOfClass())==0) { - m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexOFF); - m_View->m_Controls->m_TextureIntON->setChecked(false); - m_View->m_TexIsOn = false; + foundImage = true; + mitk::Image::Pointer img = dynamic_cast(nodeData); + if(img.IsNotNull() && img->GetPixelType().GetPixelTypeId() == typeid(itk::RGBAPixel) ) + { + foundRGBAImage = true; + } + + bool tex_int; + node->GetBoolProperty("texture interpolation", tex_int); + if(tex_int) + { + m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexON); + m_View->m_Controls->m_TextureIntON->setChecked(true); + m_View->m_TexIsOn = true; + } + else + { + m_View->m_Controls->m_TextureIntON->setIcon(*m_View->m_IconTexOFF); + m_View->m_Controls->m_TextureIntON->setChecked(false); + m_View->m_TexIsOn = false; + } } - } + + } // END CHECK node != NULL } } } m_View->m_FoundSingleOdfImage = (foundQBIVolume || foundTensorVolume) && !foundMultipleOdfImages; m_View->m_Controls->m_NumberGlyphsFrame->setVisible(m_View->m_FoundSingleOdfImage); m_View->m_Controls->m_NormalizationDropdown->setVisible(m_View->m_FoundSingleOdfImage); m_View->m_Controls->label->setVisible(m_View->m_FoundSingleOdfImage); m_View->m_Controls->m_ScalingFactor->setVisible(m_View->m_FoundSingleOdfImage); m_View->m_Controls->m_AdditionalScaling->setVisible(m_View->m_FoundSingleOdfImage); m_View->m_Controls->m_NormalizationScalingFrame->setVisible(m_View->m_FoundSingleOdfImage); m_View->m_Controls->OpacMinFrame->setVisible(foundRGBAImage || m_View->m_FoundSingleOdfImage); // changed for SPIE paper, Principle curvature scaling //m_View->m_Controls->params_frame->setVisible(m_View->m_FoundSingleOdfImage); m_View->m_Controls->params_frame->setVisible(false); m_View->m_Controls->m_VisibleOdfsON_T->setVisible(m_View->m_FoundSingleOdfImage); m_View->m_Controls->m_VisibleOdfsON_S->setVisible(m_View->m_FoundSingleOdfImage); m_View->m_Controls->m_VisibleOdfsON_C->setVisible(m_View->m_FoundSingleOdfImage); bool foundAnyImage = foundDiffusionImage || foundQBIVolume || foundTensorVolume || foundImage || foundTbssImage; m_View->m_Controls->m_Reinit->setVisible(foundAnyImage); m_View->m_Controls->m_TextureIntON->setVisible(foundAnyImage); m_View->m_Controls->m_TSMenu->setVisible(foundAnyImage); - if(m_View->m_IsInitialized) - { - //m_View->GetSite()->GetWorkbenchWindow()->GetActivePage() - // ->HideView(IViewPart::Pointer(m_View)); - - //berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->GetActivePage() - // ->ShowView(QmitkControlVisualizationPropertiesView::VIEW_ID, - // "", berry::IWorkbenchPage::VIEW_VISIBLE); - - } } } void SelectionChanged(IWorkbenchPart::Pointer part, ISelection::ConstPointer selection) { // check, if selection comes from datamanager if (part) { QString partname(part->GetPartName().c_str()); if(partname.compare("Datamanager")==0) { // apply selection DoSelectionChanged(selection); } } } QmitkControlVisualizationPropertiesView* m_View; }; QmitkControlVisualizationPropertiesView::QmitkControlVisualizationPropertiesView() : QmitkFunctionality(), m_Controls(NULL), m_MultiWidget(NULL), m_NodeUsedForOdfVisualization(NULL), m_IconTexOFF(new QIcon(":/QmitkDiffusionImaging/texIntOFFIcon.png")), m_IconTexON(new QIcon(":/QmitkDiffusionImaging/texIntONIcon.png")), m_IconGlyOFF_T(new QIcon(":/QmitkDiffusionImaging/glyphsoff_T.png")), m_IconGlyON_T(new QIcon(":/QmitkDiffusionImaging/glyphson_T.png")), m_IconGlyOFF_C(new QIcon(":/QmitkDiffusionImaging/glyphsoff_C.png")), m_IconGlyON_C(new QIcon(":/QmitkDiffusionImaging/glyphson_C.png")), m_IconGlyOFF_S(new QIcon(":/QmitkDiffusionImaging/glyphsoff_S.png")), m_IconGlyON_S(new QIcon(":/QmitkDiffusionImaging/glyphson_S.png")), m_CurrentSelection(0), m_CurrentPickingNode(0), m_GlyIsOn_S(false), m_GlyIsOn_C(false), - m_GlyIsOn_T(false) + m_GlyIsOn_T(false), + m_FiberBundleObserverTag(0), + m_Color(NULL) { currentThickSlicesMode = 1; m_MyMenu = NULL; } QmitkControlVisualizationPropertiesView::QmitkControlVisualizationPropertiesView(const QmitkControlVisualizationPropertiesView& other) { Q_UNUSED(other) throw std::runtime_error("Copy constructor not implemented"); } QmitkControlVisualizationPropertiesView::~QmitkControlVisualizationPropertiesView() { + if(m_SlicesRotationObserverTag1 ) + { + mitk::SlicesCoordinator* coordinator = m_MultiWidget->GetSlicesRotator(); + if( coordinator) + coordinator->RemoveObserver(m_SlicesRotationObserverTag1); + } + if( m_SlicesRotationObserverTag2) + { + mitk::SlicesCoordinator* coordinator = m_MultiWidget->GetSlicesRotator(); + if( coordinator ) + coordinator->RemoveObserver(m_SlicesRotationObserverTag1); + } + this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->RemovePostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener); } void QmitkControlVisualizationPropertiesView::OnThickSlicesModeSelected( QAction* action ) { currentThickSlicesMode = action->data().toInt(); switch(currentThickSlicesMode) { default: case 1: this->m_Controls->m_TSMenu->setText("MIP"); break; case 2: this->m_Controls->m_TSMenu->setText("SUM"); break; case 3: this->m_Controls->m_TSMenu->setText("WEIGH"); break; } mitk::DataNode* n; n = this->m_MultiWidget->GetWidgetPlane1(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) ); n = this->m_MultiWidget->GetWidgetPlane2(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) ); n = this->m_MultiWidget->GetWidgetPlane3(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) ); mitk::BaseRenderer::Pointer renderer = this->GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer(); if(renderer.IsNotNull()) { renderer->SendUpdateSlice(); } renderer = this->GetActiveStdMultiWidget()->GetRenderWindow2()->GetRenderer(); if(renderer.IsNotNull()) { renderer->SendUpdateSlice(); } renderer = this->GetActiveStdMultiWidget()->GetRenderWindow3()->GetRenderer(); if(renderer.IsNotNull()) { renderer->SendUpdateSlice(); } renderer->GetRenderingManager()->RequestUpdateAll(); } void QmitkControlVisualizationPropertiesView::OnTSNumChanged(int num) { if(num==0) { mitk::DataNode* n; n = this->m_MultiWidget->GetWidgetPlane1(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 0 ) ); n = this->m_MultiWidget->GetWidgetPlane2(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 0 ) ); n = this->m_MultiWidget->GetWidgetPlane3(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 0 ) ); } else { mitk::DataNode* n; n = this->m_MultiWidget->GetWidgetPlane1(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) ); n = this->m_MultiWidget->GetWidgetPlane2(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) ); n = this->m_MultiWidget->GetWidgetPlane3(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) ); n = this->m_MultiWidget->GetWidgetPlane1(); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) ); n = this->m_MultiWidget->GetWidgetPlane2(); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) ); n = this->m_MultiWidget->GetWidgetPlane3(); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) ); } m_TSLabel->setText(QString::number(num*2+1)); mitk::BaseRenderer::Pointer renderer = this->GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer(); if(renderer.IsNotNull()) { renderer->SendUpdateSlice(); } renderer = this->GetActiveStdMultiWidget()->GetRenderWindow2()->GetRenderer(); if(renderer.IsNotNull()) { renderer->SendUpdateSlice(); } renderer = this->GetActiveStdMultiWidget()->GetRenderWindow3()->GetRenderer(); if(renderer.IsNotNull()) { renderer->SendUpdateSlice(); } renderer->GetRenderingManager()->RequestUpdateAll(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS); } void QmitkControlVisualizationPropertiesView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkControlVisualizationPropertiesViewControls; m_Controls->setupUi(parent); this->CreateConnections(); + // hide warning (ODFs in rotated planes) + m_Controls->m_lblRotatedPlanesWarning->hide(); + m_MyMenu = new QMenu(parent); connect( m_MyMenu, SIGNAL( aboutToShow() ), this, SLOT(OnMenuAboutToShow()) ); // button for changing rotation mode m_Controls->m_TSMenu->setMenu( m_MyMenu ); //m_CrosshairModeButton->setIcon( QIcon( iconCrosshairMode_xpm ) ); m_Controls->params_frame->setVisible(false); QIcon icon5(":/QmitkDiffusionImaging/Refresh_48.png"); m_Controls->m_Reinit->setIcon(icon5); m_Controls->m_Focus->setIcon(icon5); QIcon iconColor(":/QmitkDiffusionImaging/color24.gif"); m_Controls->m_PFColor->setIcon(iconColor); m_Controls->m_Color->setIcon(iconColor); QIcon iconReset(":/QmitkDiffusionImaging/reset.png"); m_Controls->m_ResetColoring->setIcon(iconReset); m_Controls->m_PFColor->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); QIcon iconCrosshair(":/QmitkDiffusionImaging/crosshair.png"); m_Controls->m_Crosshair->setIcon(iconCrosshair); // was is los QIcon iconPaint(":/QmitkDiffusionImaging/paint2.png"); m_Controls->m_TDI->setIcon(iconPaint); QIcon iconFiberFade(":/QmitkDiffusionImaging/MapperEfx2D.png"); m_Controls->m_FiberFading2D->setIcon(iconFiberFade); m_Controls->m_TextureIntON->setCheckable(true); #ifndef DIFFUSION_IMAGING_EXTENDED int size = m_Controls->m_AdditionalScaling->count(); for(int t=0; tm_AdditionalScaling->itemText(t).toStdString() == "Scale by ASR") { m_Controls->m_AdditionalScaling->removeItem(t); } } #endif m_Controls->m_OpacitySlider->setRange(0.0,1.0); m_Controls->m_OpacitySlider->setLowerValue(0.0); m_Controls->m_OpacitySlider->setUpperValue(0.0); m_Controls->m_ScalingFrame->setVisible(false); m_Controls->m_NormalizationFrame->setVisible(false); - + m_Controls->frame_tube->setVisible(false); + m_Controls->frame_wire->setVisible(false); } m_IsInitialized = false; m_SelListener = berry::ISelectionListener::Pointer(new CvpSelListener(this)); this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener); berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); m_IsInitialized = true; } void QmitkControlVisualizationPropertiesView::OnMenuAboutToShow () { // THICK SLICE SUPPORT QMenu *myMenu = m_MyMenu; myMenu->clear(); QActionGroup* thickSlicesActionGroup = new QActionGroup(myMenu); thickSlicesActionGroup->setExclusive(true); mitk::BaseRenderer::Pointer renderer = this->GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer(); int currentTSMode = 0; { mitk::ResliceMethodProperty::Pointer m = dynamic_cast(renderer->GetCurrentWorldGeometry2DNode()->GetProperty( "reslice.thickslices" )); if( m.IsNotNull() ) currentTSMode = m->GetValueAsId(); } const int maxTS = 30; int currentNum = 0; { mitk::IntProperty::Pointer m = dynamic_cast(renderer->GetCurrentWorldGeometry2DNode()->GetProperty( "reslice.thickslices.num" )); if( m.IsNotNull() ) { currentNum = m->GetValue(); if(currentNum < 0) currentNum = 0; if(currentNum > maxTS) currentNum = maxTS; } } if(currentTSMode==0) currentNum=0; QSlider *m_TSSlider = new QSlider(myMenu); m_TSSlider->setMinimum(0); m_TSSlider->setMaximum(maxTS-1); m_TSSlider->setValue(currentNum); m_TSSlider->setOrientation(Qt::Horizontal); connect( m_TSSlider, SIGNAL( valueChanged(int) ), this, SLOT( OnTSNumChanged(int) ) ); QHBoxLayout* _TSLayout = new QHBoxLayout; _TSLayout->setContentsMargins(4,4,4,4); _TSLayout->addWidget(m_TSSlider); _TSLayout->addWidget(m_TSLabel=new QLabel(QString::number(currentNum*2+1),myMenu)); QWidget* _TSWidget = new QWidget; _TSWidget->setLayout(_TSLayout); QActionGroup* thickSliceModeActionGroup = new QActionGroup(myMenu); thickSliceModeActionGroup->setExclusive(true); QWidgetAction *m_TSSliderAction = new QWidgetAction(myMenu); m_TSSliderAction->setDefaultWidget(_TSWidget); myMenu->addAction(m_TSSliderAction); QAction* mipThickSlicesAction = new QAction(myMenu); mipThickSlicesAction->setActionGroup(thickSliceModeActionGroup); mipThickSlicesAction->setText("MIP (max. intensity proj.)"); mipThickSlicesAction->setCheckable(true); mipThickSlicesAction->setChecked(currentThickSlicesMode==1); mipThickSlicesAction->setData(1); myMenu->addAction( mipThickSlicesAction ); QAction* sumThickSlicesAction = new QAction(myMenu); sumThickSlicesAction->setActionGroup(thickSliceModeActionGroup); sumThickSlicesAction->setText("SUM (sum intensity proj.)"); sumThickSlicesAction->setCheckable(true); sumThickSlicesAction->setChecked(currentThickSlicesMode==2); sumThickSlicesAction->setData(2); myMenu->addAction( sumThickSlicesAction ); QAction* weightedThickSlicesAction = new QAction(myMenu); weightedThickSlicesAction->setActionGroup(thickSliceModeActionGroup); weightedThickSlicesAction->setText("WEIGHTED (gaussian proj.)"); weightedThickSlicesAction->setCheckable(true); weightedThickSlicesAction->setChecked(currentThickSlicesMode==3); weightedThickSlicesAction->setData(3); myMenu->addAction( weightedThickSlicesAction ); connect( thickSliceModeActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(OnThickSlicesModeSelected(QAction*)) ); } void QmitkControlVisualizationPropertiesView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; + + if (m_MultiWidget) + { + mitk::SlicesCoordinator* coordinator = m_MultiWidget->GetSlicesRotator(); + if (coordinator) + { + itk::ReceptorMemberCommand::Pointer command2 = itk::ReceptorMemberCommand::New(); + command2->SetCallbackFunction( this, &QmitkControlVisualizationPropertiesView::SliceRotation ); + m_SlicesRotationObserverTag1 = coordinator->AddObserver( mitk::SliceRotationEvent(), command2 ); + } + + coordinator = m_MultiWidget->GetSlicesSwiveller(); + if (coordinator) + { + itk::ReceptorMemberCommand::Pointer command2 = itk::ReceptorMemberCommand::New(); + command2->SetCallbackFunction( this, &QmitkControlVisualizationPropertiesView::SliceRotation ); + m_SlicesRotationObserverTag2 = coordinator->AddObserver( mitk::SliceRotationEvent(), command2 ); + } + } } +void QmitkControlVisualizationPropertiesView::SliceRotation(const itk::EventObject&) +{ + // test if plane rotated + if( m_GlyIsOn_T || m_GlyIsOn_C || m_GlyIsOn_S ) + { + if( this->IsPlaneRotated() ) + { + // show label + m_Controls->m_lblRotatedPlanesWarning->show(); + } + else + { + //hide label + m_Controls->m_lblRotatedPlanesWarning->hide(); + } + } +} + + void QmitkControlVisualizationPropertiesView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkControlVisualizationPropertiesView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_DisplayIndex), SIGNAL(valueChanged(int)), this, SLOT(DisplayIndexChanged(int)) ); connect( (QObject*)(m_Controls->m_TextureIntON), SIGNAL(clicked()), this, SLOT(TextIntON()) ); connect( (QObject*)(m_Controls->m_Reinit), SIGNAL(clicked()), this, SLOT(Reinit()) ); connect( (QObject*)(m_Controls->m_VisibleOdfsON_T), SIGNAL(clicked()), this, SLOT(VisibleOdfsON_T()) ); connect( (QObject*)(m_Controls->m_VisibleOdfsON_S), SIGNAL(clicked()), this, SLOT(VisibleOdfsON_S()) ); connect( (QObject*)(m_Controls->m_VisibleOdfsON_C), SIGNAL(clicked()), this, SLOT(VisibleOdfsON_C()) ); connect( (QObject*)(m_Controls->m_ShowMaxNumber), SIGNAL(editingFinished()), this, SLOT(ShowMaxNumberChanged()) ); connect( (QObject*)(m_Controls->m_NormalizationDropdown), SIGNAL(currentIndexChanged(int)), this, SLOT(NormalizationDropdownChanged(int)) ); connect( (QObject*)(m_Controls->m_ScalingFactor), SIGNAL(valueChanged(double)), this, SLOT(ScalingFactorChanged(double)) ); connect( (QObject*)(m_Controls->m_AdditionalScaling), SIGNAL(currentIndexChanged(int)), this, SLOT(AdditionalScaling(int)) ); connect( (QObject*)(m_Controls->m_IndexParam1), SIGNAL(valueChanged(double)), this, SLOT(IndexParam1Changed(double)) ); connect( (QObject*)(m_Controls->m_IndexParam2), SIGNAL(valueChanged(double)), this, SLOT(IndexParam2Changed(double)) ); connect( (QObject*)(m_Controls->m_ScalingCheckbox), SIGNAL(clicked()), this, SLOT(ScalingCheckbox()) ); connect( (QObject*)(m_Controls->m_OpacitySlider), SIGNAL(spanChanged(double,double)), this, SLOT(OpacityChanged(double,double)) ); connect((QObject*) m_Controls->m_Wire, SIGNAL(clicked()), (QObject*) this, SLOT(BundleRepresentationWire())); connect((QObject*) m_Controls->m_Tube, SIGNAL(clicked()), (QObject*) this, SLOT(BundleRepresentationTube())); connect((QObject*) m_Controls->m_Color, SIGNAL(clicked()), (QObject*) this, SLOT(BundleRepresentationColor())); connect((QObject*) m_Controls->m_ResetColoring, SIGNAL(clicked()), (QObject*) this, SLOT(BundleRepresentationResetColoring())); connect((QObject*) m_Controls->m_Focus, SIGNAL(clicked()), (QObject*) this, SLOT(PlanarFigureFocus())); connect((QObject*) m_Controls->m_FiberFading2D, SIGNAL(clicked()), (QObject*) this, SLOT( Fiber2DfadingEFX() ) ); connect((QObject*) m_Controls->m_FiberThicknessSlider, SIGNAL(sliderReleased()), (QObject*) this, SLOT( FiberSlicingThickness2D() ) ); connect((QObject*) m_Controls->m_FiberThicknessSlider, SIGNAL(valueChanged(int)), (QObject*) this, SLOT( FiberSlicingUpdateLabel(int) )); connect((QObject*) m_Controls->m_Crosshair, SIGNAL(clicked()), (QObject*) this, SLOT(SetInteractor())); connect((QObject*) m_Controls->m_PFWidth, SIGNAL(valueChanged(int)), (QObject*) this, SLOT(PFWidth(int))); connect((QObject*) m_Controls->m_PFColor, SIGNAL(clicked()), (QObject*) this, SLOT(PFColor())); connect((QObject*) m_Controls->m_TDI, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateTdi())); connect((QObject*) m_Controls->m_LineWidth, SIGNAL(valueChanged(int)), (QObject*) this, SLOT(LineWidthChanged(int))); connect((QObject*) m_Controls->m_TubeRadius, SIGNAL(valueChanged(int)), (QObject*) this, SLOT(TubeRadiusChanged(int))); connect((QObject*) m_Controls->m_Welcome, SIGNAL(clicked()), (QObject*) this, SLOT(Welcome())); } } void QmitkControlVisualizationPropertiesView::Activated() { berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); QmitkFunctionality::Activated(); } void QmitkControlVisualizationPropertiesView::Deactivated() { QmitkFunctionality::Deactivated(); } int QmitkControlVisualizationPropertiesView::GetSizeFlags(bool width) { if(!width) { return berry::Constants::MIN | berry::Constants::MAX | berry::Constants::FILL; } else { return 0; } } int QmitkControlVisualizationPropertiesView::ComputePreferredSize(bool width, int /*availableParallel*/, int /*availablePerpendicular*/, int preferredResult) { if(width==false) { return m_FoundSingleOdfImage ? 120 : 80; } else { return preferredResult; } } // set diffusion image channel to b0 volume void QmitkControlVisualizationPropertiesView::NodeAdded(const mitk::DataNode *node) { mitk::DataNode* notConst = const_cast(node); if (dynamic_cast*>(notConst->GetData())) { mitk::DiffusionImage::Pointer dimg = dynamic_cast*>(notConst->GetData()); notConst->SetIntProperty("DisplayChannel", dimg->GetB0Indices().front()); } } /* OnSelectionChanged is registered to SelectionService, therefore no need to implement SelectionService Listener explicitly */ void QmitkControlVisualizationPropertiesView::OnSelectionChanged( std::vector nodes ) { if ( !this->IsVisible() ) { // do nothing if nobody wants to see me :-( return; } // deactivate channel slider if no diffusion weighted image or tbss image is selected m_Controls->m_DisplayIndex->setVisible(false); m_Controls->label_channel->setVisible(false); + for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; - if (node.IsNotNull() && (dynamic_cast(node->GetData()) || - dynamic_cast*>(node->GetData()))) + + // check if node has data, + // if some helper nodes are shown in the DataManager, the GetData() returns 0x0 which would lead to SIGSEV + mitk::BaseData* nodeData = node->GetData(); + if(nodeData == NULL) + continue; + + if (node.IsNotNull() && (dynamic_cast(nodeData) || + dynamic_cast*>(nodeData))) { m_Controls->m_DisplayIndex->setVisible(true); m_Controls->label_channel->setVisible(true); } + else if (node.IsNotNull() && dynamic_cast(node->GetData())) + { + if (m_Color.IsNotNull()) + m_Color->RemoveObserver(m_FiberBundleObserverTag); + + itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); + command->SetCallbackFunction( this, &QmitkControlVisualizationPropertiesView::SetFiberBundleCustomColor ); + m_Color = dynamic_cast(node->GetProperty("color", NULL)); + if (m_Color.IsNotNull()) + m_FiberBundleObserverTag = m_Color->AddObserver( itk::ModifiedEvent(), command ); + } } for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; - if( node.IsNotNull() && (dynamic_cast(node->GetData()) || dynamic_cast(node->GetData())) ) + + // check if node has data, + // if some helper nodes are shown in the DataManager, the GetData() returns 0x0 which would lead to SIGSEV + mitk::BaseData* nodeData = node->GetData(); + if(nodeData == NULL) + continue; + + if( node.IsNotNull() && (dynamic_cast(nodeData) || dynamic_cast(nodeData)) ) { if(m_NodeUsedForOdfVisualization.IsNotNull()) { m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_S", false); m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_C", false); m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_T", false); } m_NodeUsedForOdfVisualization = node; m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_S", m_GlyIsOn_S); m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_C", m_GlyIsOn_C); m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_T", m_GlyIsOn_T); if(m_MultiWidget) m_MultiWidget->RequestUpdate(); m_Controls->m_TSMenu->setVisible(false); // deactivate mip etc. for tensor and q-ball images break; } else m_Controls->m_TSMenu->setVisible(true); } } mitk::DataStorage::SetOfObjects::Pointer QmitkControlVisualizationPropertiesView::ActiveSet(std::string classname) { if (m_CurrentSelection) { mitk::DataStorage::SetOfObjects::Pointer set = mitk::DataStorage::SetOfObjects::New(); int at = 0; for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i) { if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); - if(QString(classname.c_str()).compare(node->GetData()->GetNameOfClass())==0) + + // check if node has data, + // if some helper nodes are shown in the DataManager, the GetData() returns 0x0 which would lead to SIGSEV + const mitk::BaseData* nodeData = node->GetData(); + if(nodeData == NULL) + continue; + + if(QString(classname.c_str()).compare(nodeData->GetNameOfClass())==0) { set->InsertElement(at++, node); } } } return set; } return 0; } void QmitkControlVisualizationPropertiesView::SetBoolProp( mitk::DataStorage::SetOfObjects::Pointer set, std::string name, bool value) { if(set.IsNotNull()) { mitk::DataStorage::SetOfObjects::const_iterator itemiter( set->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( set->end() ); while ( itemiter != itemiterend ) { (*itemiter)->SetBoolProperty(name.c_str(), value); ++itemiter; } } } void QmitkControlVisualizationPropertiesView::SetIntProp( mitk::DataStorage::SetOfObjects::Pointer set, std::string name, int value) { if(set.IsNotNull()) { mitk::DataStorage::SetOfObjects::const_iterator itemiter( set->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( set->end() ); while ( itemiter != itemiterend ) { (*itemiter)->SetIntProperty(name.c_str(), value); ++itemiter; } } } void QmitkControlVisualizationPropertiesView::SetFloatProp( mitk::DataStorage::SetOfObjects::Pointer set, std::string name, float value) { if(set.IsNotNull()) { mitk::DataStorage::SetOfObjects::const_iterator itemiter( set->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( set->end() ); while ( itemiter != itemiterend ) { (*itemiter)->SetFloatProperty(name.c_str(), value); ++itemiter; } } } void QmitkControlVisualizationPropertiesView::SetLevelWindowProp( mitk::DataStorage::SetOfObjects::Pointer set, std::string name, mitk::LevelWindow value) { if(set.IsNotNull()) { mitk::LevelWindowProperty::Pointer prop = mitk::LevelWindowProperty::New(value); mitk::DataStorage::SetOfObjects::const_iterator itemiter( set->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( set->end() ); while ( itemiter != itemiterend ) { (*itemiter)->SetProperty(name.c_str(), prop); ++itemiter; } } } void QmitkControlVisualizationPropertiesView::SetEnumProp( mitk::DataStorage::SetOfObjects::Pointer set, std::string name, mitk::EnumerationProperty::Pointer value) { if(set.IsNotNull()) { mitk::DataStorage::SetOfObjects::const_iterator itemiter( set->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( set->end() ); while ( itemiter != itemiterend ) { (*itemiter)->SetProperty(name.c_str(), value); ++itemiter; } } } void QmitkControlVisualizationPropertiesView::DisplayIndexChanged(int dispIndex) { QString label = "Channel %1"; label = label.arg(dispIndex); m_Controls->label_channel->setText(label); std::vector sets; sets.push_back("DiffusionImage"); sets.push_back("TbssImage"); std::vector::iterator it = sets.begin(); while(it != sets.end()) { std::string s = *it; mitk::DataStorage::SetOfObjects::Pointer set = ActiveSet(s); if(set.IsNotNull()) { mitk::DataStorage::SetOfObjects::const_iterator itemiter( set->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( set->end() ); while ( itemiter != itemiterend ) { (*itemiter)->SetIntProperty("DisplayChannel", dispIndex); ++itemiter; } //m_MultiWidget->RequestUpdate(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } it++; } } void QmitkControlVisualizationPropertiesView::Reinit() { if (m_CurrentSelection) { mitk::DataNodeObject::Pointer nodeObj = m_CurrentSelection->Begin()->Cast(); mitk::DataNode::Pointer node = nodeObj->GetDataNode(); mitk::BaseData::Pointer basedata = node->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } } void QmitkControlVisualizationPropertiesView::TextIntON() { if(m_TexIsOn) { m_Controls->m_TextureIntON->setIcon(*m_IconTexOFF); } else { m_Controls->m_TextureIntON->setIcon(*m_IconTexON); } mitk::DataStorage::SetOfObjects::Pointer set = ActiveSet("DiffusionImage"); SetBoolProp(set,"texture interpolation", !m_TexIsOn); set = ActiveSet("TensorImage"); SetBoolProp(set,"texture interpolation", !m_TexIsOn); set = ActiveSet("QBallImage"); SetBoolProp(set,"texture interpolation", !m_TexIsOn); set = ActiveSet("Image"); SetBoolProp(set,"texture interpolation", !m_TexIsOn); m_TexIsOn = !m_TexIsOn; if(m_MultiWidget) m_MultiWidget->RequestUpdate(); } void QmitkControlVisualizationPropertiesView::VisibleOdfsON_S() { m_GlyIsOn_S = m_Controls->m_VisibleOdfsON_S->isChecked(); if (m_NodeUsedForOdfVisualization.IsNull()) { MITK_WARN << "ODF visualization activated but m_NodeUsedForOdfVisualization is NULL"; return; } m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_S", m_GlyIsOn_S); VisibleOdfsON(0); } void QmitkControlVisualizationPropertiesView::VisibleOdfsON_T() { m_GlyIsOn_T = m_Controls->m_VisibleOdfsON_T->isChecked(); if (m_NodeUsedForOdfVisualization.IsNull()) { MITK_WARN << "ODF visualization activated but m_NodeUsedForOdfVisualization is NULL"; return; } m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_T", m_GlyIsOn_T); VisibleOdfsON(1); } void QmitkControlVisualizationPropertiesView::VisibleOdfsON_C() { m_GlyIsOn_C = m_Controls->m_VisibleOdfsON_C->isChecked(); if (m_NodeUsedForOdfVisualization.IsNull()) { MITK_WARN << "ODF visualization activated but m_NodeUsedForOdfVisualization is NULL"; return; } m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_C", m_GlyIsOn_C); VisibleOdfsON(2); } +bool QmitkControlVisualizationPropertiesView::IsPlaneRotated() +{ + + // for all 2D renderwindows of m_MultiWidget check alignment + mitk::PlaneGeometry::ConstPointer displayPlane = dynamic_cast( m_MultiWidget->GetRenderWindow1()->GetRenderer()->GetCurrentWorldGeometry2D() ); + if (displayPlane.IsNull()) return false; + + mitk::Image* currentImage = dynamic_cast( m_NodeUsedForOdfVisualization->GetData() ); + if( currentImage == NULL ) + { + MITK_ERROR << " Casting problems. Returning false"; + return false; + } + + int affectedDimension(-1); + int affectedSlice(-1); + return !(mitk::SegTool2D::DetermineAffectedImageSlice( currentImage, displayPlane, affectedDimension, affectedSlice )); + +} + void QmitkControlVisualizationPropertiesView::VisibleOdfsON(int view) { if(m_MultiWidget) m_MultiWidget->RequestUpdate(); } void QmitkControlVisualizationPropertiesView::ShowMaxNumberChanged() { int maxNr = m_Controls->m_ShowMaxNumber->value(); if ( maxNr < 1 ) { m_Controls->m_ShowMaxNumber->setValue( 1 ); maxNr = 1; } mitk::DataStorage::SetOfObjects::Pointer set = ActiveSet("QBallImage"); SetIntProp(set,"ShowMaxNumber", maxNr); set = ActiveSet("TensorImage"); SetIntProp(set,"ShowMaxNumber", maxNr); if(m_MultiWidget) m_MultiWidget->RequestUpdate(); } void QmitkControlVisualizationPropertiesView::NormalizationDropdownChanged(int normDropdown) { typedef mitk::OdfNormalizationMethodProperty PropType; PropType::Pointer normMeth = PropType::New(); switch(normDropdown) { case 0: normMeth->SetNormalizationToMinMax(); break; case 1: normMeth->SetNormalizationToMax(); break; case 2: normMeth->SetNormalizationToNone(); break; case 3: normMeth->SetNormalizationToGlobalMax(); break; default: normMeth->SetNormalizationToMinMax(); } mitk::DataStorage::SetOfObjects::Pointer set = ActiveSet("QBallImage"); SetEnumProp(set,"Normalization", normMeth.GetPointer()); set = ActiveSet("TensorImage"); SetEnumProp(set,"Normalization", normMeth.GetPointer()); - if(m_MultiWidget) - m_MultiWidget->RequestUpdate(); - +// if(m_MultiWidget) +// m_MultiWidget->RequestUpdate(); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkControlVisualizationPropertiesView::ScalingFactorChanged(double scalingFactor) { mitk::DataStorage::SetOfObjects::Pointer set = ActiveSet("QBallImage"); SetFloatProp(set,"Scaling", scalingFactor); set = ActiveSet("TensorImage"); SetFloatProp(set,"Scaling", scalingFactor); if(m_MultiWidget) m_MultiWidget->RequestUpdate(); } void QmitkControlVisualizationPropertiesView::AdditionalScaling(int additionalScaling) { typedef mitk::OdfScaleByProperty PropType; PropType::Pointer scaleBy = PropType::New(); switch(additionalScaling) { case 0: scaleBy->SetScaleByNothing(); break; case 1: scaleBy->SetScaleByGFA(); //m_Controls->params_frame->setVisible(true); break; #ifdef DIFFUSION_IMAGING_EXTENDED case 2: scaleBy->SetScaleByPrincipalCurvature(); // commented in for SPIE paper, Principle curvature scaling //m_Controls->params_frame->setVisible(true); break; #endif default: scaleBy->SetScaleByNothing(); } mitk::DataStorage::SetOfObjects::Pointer set = ActiveSet("QBallImage"); SetEnumProp(set,"ScaleBy", scaleBy.GetPointer()); set = ActiveSet("TensorImage"); SetEnumProp(set,"ScaleBy", scaleBy.GetPointer()); if(m_MultiWidget) m_MultiWidget->RequestUpdate(); } void QmitkControlVisualizationPropertiesView::IndexParam1Changed(double param1) { mitk::DataStorage::SetOfObjects::Pointer set = ActiveSet("QBallImage"); SetFloatProp(set,"IndexParam1", param1); set = ActiveSet("TensorImage"); SetFloatProp(set,"IndexParam1", param1); if(m_MultiWidget) m_MultiWidget->RequestUpdate(); } void QmitkControlVisualizationPropertiesView::IndexParam2Changed(double param2) { mitk::DataStorage::SetOfObjects::Pointer set = ActiveSet("QBallImage"); SetFloatProp(set,"IndexParam2", param2); set = ActiveSet("TensorImage"); SetFloatProp(set,"IndexParam2", param2); if(m_MultiWidget) m_MultiWidget->RequestUpdate(); } void QmitkControlVisualizationPropertiesView::OpacityChanged(double l, double u) { mitk::LevelWindow olw; olw.SetRangeMinMax(l*255, u*255); mitk::DataStorage::SetOfObjects::Pointer set = ActiveSet("QBallImage"); SetLevelWindowProp(set,"opaclevelwindow", olw); set = ActiveSet("TensorImage"); SetLevelWindowProp(set,"opaclevelwindow", olw); set = ActiveSet("Image"); SetLevelWindowProp(set,"opaclevelwindow", olw); m_Controls->m_OpacityMinFaLabel->setText(QString::number(l,'f',2) + " : " + QString::number(u,'f',2)); if(m_MultiWidget) m_MultiWidget->RequestUpdate(); } void QmitkControlVisualizationPropertiesView::ScalingCheckbox() { m_Controls->m_ScalingFrame->setVisible( m_Controls->m_ScalingCheckbox->isChecked()); if(!m_Controls->m_ScalingCheckbox->isChecked()) { m_Controls->m_AdditionalScaling->setCurrentIndex(0); m_Controls->m_ScalingFactor->setValue(1.0); } } void QmitkControlVisualizationPropertiesView::Fiber2DfadingEFX() { if (m_SelectedNode) { bool currentMode; m_SelectedNode->GetBoolProperty("Fiber2DfadeEFX", currentMode); m_SelectedNode->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(!currentMode)); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); } } void QmitkControlVisualizationPropertiesView::FiberSlicingThickness2D() { if (m_SelectedNode) { float fibThickness = m_Controls->m_FiberThicknessSlider->value() * 0.1; m_SelectedNode->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(fibThickness)); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); } } void QmitkControlVisualizationPropertiesView::FiberSlicingUpdateLabel(int value) { QString label = "Range %1"; label = label.arg(value * 0.1); m_Controls->label_range->setText(label); } void QmitkControlVisualizationPropertiesView::BundleRepresentationWire() { if(m_SelectedNode) { int width = m_Controls->m_LineWidth->value(); m_SelectedNode->SetProperty("LineWidth",mitk::IntProperty::New(width)); m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(15)); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(18)); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(1)); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(2)); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(3)); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(4)); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(0)); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); } } void QmitkControlVisualizationPropertiesView::BundleRepresentationTube() { if(m_SelectedNode) { float radius = m_Controls->m_TubeRadius->value() / 100.0; m_SelectedNode->SetProperty("TubeRadius",mitk::FloatProperty::New(radius)); m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(17)); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(13)); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(16)); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); m_SelectedNode->SetProperty("ColorCoding",mitk::IntProperty::New(0)); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); } } +void QmitkControlVisualizationPropertiesView::SetFiberBundleCustomColor(const itk::EventObject& /*e*/) +{ + float color[3]; + m_SelectedNode->GetColor(color); + m_Controls->m_Color->setAutoFillBackground(true); + QString styleSheet = "background-color:rgb("; + styleSheet.append(QString::number(color[0]*255.0)); + styleSheet.append(","); + styleSheet.append(QString::number(color[1]*255.0)); + styleSheet.append(","); + styleSheet.append(QString::number(color[2]*255.0)); + styleSheet.append(")"); + m_Controls->m_Color->setStyleSheet(styleSheet); + + m_SelectedNode->SetProperty("color",mitk::ColorProperty::New(color[0], color[1], color[2])); + mitk::FiberBundleX::Pointer fib = dynamic_cast(m_SelectedNode->GetData()); + fib->SetColorCoding(mitk::FiberBundleX::COLORCODING_CUSTOM); + m_SelectedNode->Modified(); + mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); +} + void QmitkControlVisualizationPropertiesView::BundleRepresentationColor() { if(m_SelectedNode) { QColor color = QColorDialog::getColor(); if (!color.isValid()) return; m_Controls->m_Color->setAutoFillBackground(true); QString styleSheet = "background-color:rgb("; styleSheet.append(QString::number(color.red())); styleSheet.append(","); styleSheet.append(QString::number(color.green())); styleSheet.append(","); styleSheet.append(QString::number(color.blue())); styleSheet.append(")"); m_Controls->m_Color->setStyleSheet(styleSheet); m_SelectedNode->SetProperty("color",mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0)); mitk::FiberBundleX::Pointer fib = dynamic_cast(m_SelectedNode->GetData()); fib->SetColorCoding(mitk::FiberBundleX::COLORCODING_CUSTOM); + m_SelectedNode->Modified(); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); } } void QmitkControlVisualizationPropertiesView::BundleRepresentationResetColoring() { if(m_SelectedNode) { + MITK_INFO << "reset colorcoding to oBased"; m_Controls->m_Color->setAutoFillBackground(true); QString styleSheet = "background-color:rgb(255,255,255)"; m_Controls->m_Color->setStyleSheet(styleSheet); +// m_SelectedNode->SetProperty("color",NULL); m_SelectedNode->SetProperty("color",mitk::ColorProperty::New(1.0, 1.0, 1.0)); mitk::FiberBundleX::Pointer fib = dynamic_cast(m_SelectedNode->GetData()); fib->SetColorCoding(mitk::FiberBundleX::COLORCODING_ORIENTATION_BASED); + fib->DoColorCodingOrientationBased(); + m_SelectedNode->Modified(); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); } } void QmitkControlVisualizationPropertiesView::PlanarFigureFocus() { if(m_SelectedNode) { mitk::PlanarFigure* _PlanarFigure = 0; _PlanarFigure = dynamic_cast (m_SelectedNode->GetData()); if (_PlanarFigure) { QmitkRenderWindow* selectedRenderWindow = 0; bool PlanarFigureInitializedWindow = false; QmitkRenderWindow* RenderWindow1 = this->GetActiveStdMultiWidget()->GetRenderWindow1(); if (m_SelectedNode->GetBoolProperty("PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow1->GetRenderer())) { selectedRenderWindow = RenderWindow1; } QmitkRenderWindow* RenderWindow2 = this->GetActiveStdMultiWidget()->GetRenderWindow2(); if (!selectedRenderWindow && m_SelectedNode->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow2->GetRenderer())) { selectedRenderWindow = RenderWindow2; } QmitkRenderWindow* RenderWindow3 = this->GetActiveStdMultiWidget()->GetRenderWindow3(); if (!selectedRenderWindow && m_SelectedNode->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow3->GetRenderer())) { selectedRenderWindow = RenderWindow3; } QmitkRenderWindow* RenderWindow4 = this->GetActiveStdMultiWidget()->GetRenderWindow4(); if (!selectedRenderWindow && m_SelectedNode->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow4->GetRenderer())) { selectedRenderWindow = RenderWindow4; } const mitk::PlaneGeometry * _PlaneGeometry = dynamic_cast (_PlanarFigure->GetGeometry2D()); mitk::VnlVector normal = _PlaneGeometry->GetNormalVnl(); mitk::Geometry2D::ConstPointer worldGeometry1 = RenderWindow1->GetRenderer()->GetCurrentWorldGeometry2D(); mitk::PlaneGeometry::ConstPointer _Plane1 = dynamic_cast( worldGeometry1.GetPointer() ); mitk::VnlVector normal1 = _Plane1->GetNormalVnl(); mitk::Geometry2D::ConstPointer worldGeometry2 = RenderWindow2->GetRenderer()->GetCurrentWorldGeometry2D(); mitk::PlaneGeometry::ConstPointer _Plane2 = dynamic_cast( worldGeometry2.GetPointer() ); mitk::VnlVector normal2 = _Plane2->GetNormalVnl(); mitk::Geometry2D::ConstPointer worldGeometry3 = RenderWindow3->GetRenderer()->GetCurrentWorldGeometry2D(); mitk::PlaneGeometry::ConstPointer _Plane3 = dynamic_cast( worldGeometry3.GetPointer() ); mitk::VnlVector normal3 = _Plane3->GetNormalVnl(); normal[0] = fabs(normal[0]); normal[1] = fabs(normal[1]); normal[2] = fabs(normal[2]); normal1[0] = fabs(normal1[0]); normal1[1] = fabs(normal1[1]); normal1[2] = fabs(normal1[2]); normal2[0] = fabs(normal2[0]); normal2[1] = fabs(normal2[1]); normal2[2] = fabs(normal2[2]); normal3[0] = fabs(normal3[0]); normal3[1] = fabs(normal3[1]); normal3[2] = fabs(normal3[2]); double ang1 = angle(normal, normal1); double ang2 = angle(normal, normal2); double ang3 = angle(normal, normal3); if(ang1 < ang2 && ang1 < ang3) { selectedRenderWindow = RenderWindow1; } else { if(ang2 < ang3) { selectedRenderWindow = RenderWindow2; } else { selectedRenderWindow = RenderWindow3; } } // make node visible if (selectedRenderWindow) { mitk::Point3D centerP = _PlaneGeometry->GetOrigin(); selectedRenderWindow->GetSliceNavigationController()->ReorientSlices( centerP, _PlaneGeometry->GetNormal()); selectedRenderWindow->GetSliceNavigationController()->SelectSliceByPoint( centerP); } } // set interactor for new node (if not already set) mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(m_SelectedNode->GetInteractor()); if(figureInteractor.IsNull()) figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", m_SelectedNode); mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor); m_SelectedNode->SetProperty("planarfigure.iseditable",mitk::BoolProperty::New(true)); } } void QmitkControlVisualizationPropertiesView::SetInteractor() { typedef std::vector Container; Container _NodeSet = this->GetDataManagerSelection(); mitk::DataNode* node = 0; mitk::FiberBundleX* bundle = 0; mitk::FiberBundleInteractor::Pointer bundleInteractor = 0; // finally add all nodes to the model for(Container::const_iterator it=_NodeSet.begin(); it!=_NodeSet.end() ; it++) { node = const_cast(*it); bundle = dynamic_cast(node->GetData()); if(bundle) { bundleInteractor = dynamic_cast(node->GetInteractor()); if(bundleInteractor.IsNotNull()) mitk::GlobalInteraction::GetInstance()->RemoveInteractor(bundleInteractor); if(!m_Controls->m_Crosshair->isChecked()) { m_Controls->m_Crosshair->setChecked(false); this->GetActiveStdMultiWidget()->GetRenderWindow4()->setCursor(Qt::ArrowCursor); m_CurrentPickingNode = 0; } else { m_Controls->m_Crosshair->setChecked(true); bundleInteractor = mitk::FiberBundleInteractor::New("FiberBundleInteractor", node); mitk::GlobalInteraction::GetInstance()->AddInteractor(bundleInteractor); this->GetActiveStdMultiWidget()->GetRenderWindow4()->setCursor(Qt::CrossCursor); m_CurrentPickingNode = node; } } } } void QmitkControlVisualizationPropertiesView::PFWidth(int w) { double width = w/10.0; m_SelectedNode->SetProperty("planarfigure.line.width", mitk::FloatProperty::New(width) ); m_SelectedNode->SetProperty("planarfigure.shadow.widthmodifier", mitk::FloatProperty::New(width) ); m_SelectedNode->SetProperty("planarfigure.outline.width", mitk::FloatProperty::New(width) ); m_SelectedNode->SetProperty("planarfigure.helperline.width", mitk::FloatProperty::New(width) ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); QString label = "Width %1"; label = label.arg(width); m_Controls->label_pfwidth->setText(label); } void QmitkControlVisualizationPropertiesView::PFColor() { QColor color = QColorDialog::getColor(); if (!color.isValid()) return; m_Controls->m_PFColor->setAutoFillBackground(true); QString styleSheet = "background-color:rgb("; styleSheet.append(QString::number(color.red())); styleSheet.append(","); styleSheet.append(QString::number(color.green())); styleSheet.append(","); styleSheet.append(QString::number(color.blue())); styleSheet.append(")"); m_Controls->m_PFColor->setStyleSheet(styleSheet); m_SelectedNode->SetProperty( "planarfigure.default.line.color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0)); m_SelectedNode->SetProperty( "planarfigure.default.outline.color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0)); m_SelectedNode->SetProperty( "planarfigure.default.helperline.color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0)); m_SelectedNode->SetProperty( "planarfigure.default.markerline.color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0)); m_SelectedNode->SetProperty( "planarfigure.default.marker.color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0)); m_SelectedNode->SetProperty( "planarfigure.hover.line.color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0) ); m_SelectedNode->SetProperty( "planarfigure.hover.outline.color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0) ); m_SelectedNode->SetProperty( "planarfigure.hover.helperline.color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0) ); m_SelectedNode->SetProperty( "color", mitk::ColorProperty::New(color.red()/255.0, color.green()/255.0, color.blue()/255.0)); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkControlVisualizationPropertiesView::GenerateTdi() { if(m_SelectedNode) { mitk::FiberBundleX* bundle = dynamic_cast(m_SelectedNode->GetData()); if(!bundle) return; typedef float OutPixType; typedef itk::Image OutImageType; // run generator itk::TractDensityImageFilter< OutImageType >::Pointer generator = itk::TractDensityImageFilter< OutImageType >::New(); generator->SetFiberBundle(bundle); generator->SetUpsamplingFactor(2); generator->Update(); // get result OutImageType::Pointer outImg = generator->GetOutput(); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk(outImg.GetPointer()); img->SetVolume(outImg->GetBufferPointer()); // to datastorage mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(img); QString name(m_SelectedNode->GetName().c_str()); name += "_TDI"; node->SetName(name.toStdString()); node->SetVisibility(true); GetDataStorage()->Add(node); } } void QmitkControlVisualizationPropertiesView::LineWidthChanged(int w) { QString label = "Width %1"; label = label.arg(w); m_Controls->label_linewidth->setText(label); BundleRepresentationWire(); } void QmitkControlVisualizationPropertiesView::TubeRadiusChanged(int r) { QString label = "Radius %1"; label = label.arg(r / 100.0); m_Controls->label_tuberadius->setText(label); this->BundleRepresentationTube(); } void QmitkControlVisualizationPropertiesView::Welcome() { berry::PlatformUI::GetWorkbench()->GetIntroManager()->ShowIntro( GetSite()->GetWorkbenchWindow(), false); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.h index 61646264eb..e1b7620944 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.h @@ -1,172 +1,181 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date: 2009-05-28 17:19:30 +0200 (Do, 28 Mai 2009) $ Version: $Revision: 17495 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _QMITKControlVisualizationPropertiesView_H_INCLUDED #define _QMITKControlVisualizationPropertiesView_H_INCLUDED #include #include #include "berryISelectionListener.h" #include "berryIStructuredSelection.h" #include "berryISizeProvider.h" #include "ui_QmitkControlVisualizationPropertiesViewControls.h" #include "mitkEnumerationProperty.h" /*! * \ingroup org_mitk_gui_qt_diffusionquantification_internal * * \brief QmitkControlVisualizationPropertiesView * * Document your class here. * * \sa QmitkFunctionality */ class QmitkControlVisualizationPropertiesView : public QmitkFunctionality//, public berry::ISizeProvider { friend struct CvpSelListener; // this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkControlVisualizationPropertiesView(); QmitkControlVisualizationPropertiesView(const QmitkControlVisualizationPropertiesView& other); virtual ~QmitkControlVisualizationPropertiesView(); virtual void CreateQtPartControl(QWidget *parent); /// \brief Creation of the connections of main and control widget virtual void CreateConnections(); /// \brief Called when the functionality is activated virtual void Activated(); virtual void Deactivated(); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); mitk::DataStorage::SetOfObjects::Pointer ActiveSet(std::string); void SetBoolProp (mitk::DataStorage::SetOfObjects::Pointer,std::string,bool); void SetIntProp (mitk::DataStorage::SetOfObjects::Pointer,std::string,int); void SetFloatProp(mitk::DataStorage::SetOfObjects::Pointer,std::string,float); void SetLevelWindowProp(mitk::DataStorage::SetOfObjects::Pointer,std::string,mitk::LevelWindow); void SetEnumProp (mitk::DataStorage::SetOfObjects::Pointer,std::string,mitk::EnumerationProperty::Pointer); virtual int GetSizeFlags(bool width); virtual int ComputePreferredSize(bool width, int availableParallel, int availablePerpendicular, int preferredResult); protected slots: void DisplayIndexChanged(int); void TextIntON(); void Reinit(); void VisibleOdfsON(int view); void VisibleOdfsON_S(); void VisibleOdfsON_T(); void VisibleOdfsON_C(); void ShowMaxNumberChanged(); void NormalizationDropdownChanged(int); void ScalingFactorChanged(double); void AdditionalScaling(int); void IndexParam1Changed(double); void IndexParam2Changed(double); void OpacityChanged(double,double); void ScalingCheckbox(); void OnThickSlicesModeSelected( QAction* action ); void OnTSNumChanged(int num); void OnMenuAboutToShow (); void BundleRepresentationWire(); void BundleRepresentationTube(); void BundleRepresentationColor(); void BundleRepresentationResetColoring(); void PlanarFigureFocus(); void Fiber2DfadingEFX(); void FiberSlicingThickness2D(); void FiberSlicingUpdateLabel(int); void SetInteractor(); void PFWidth(int); void PFColor(); void LineWidthChanged(int); void TubeRadiusChanged(int); void GenerateTdi(); void Welcome(); protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); virtual void NodeAdded(const mitk::DataNode *node); + void SetFiberBundleCustomColor(const itk::EventObject& /*e*/); + bool IsPlaneRotated(); + + void SliceRotation(const itk::EventObject&); Ui::QmitkControlVisualizationPropertiesViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; berry::ISelectionListener::Pointer m_SelListener; berry::IStructuredSelection::ConstPointer m_CurrentSelection; bool m_FoundSingleOdfImage; bool m_IsInitialized; mitk::DataNode::Pointer m_NodeUsedForOdfVisualization; QIcon* m_IconTexOFF; QIcon* m_IconTexON; QIcon* m_IconGlyOFF_T; QIcon* m_IconGlyON_T; QIcon* m_IconGlyOFF_C; QIcon* m_IconGlyON_C; QIcon* m_IconGlyOFF_S; QIcon* m_IconGlyON_S; bool m_TexIsOn; bool m_GlyIsOn_T; bool m_GlyIsOn_C; bool m_GlyIsOn_S; int currentThickSlicesMode; QLabel* m_TSLabel; QMenu* m_MyMenu; // for planarfigure and bundle handling: mitk::DataNode* m_SelectedNode; mitk::DataNode* m_CurrentPickingNode; + + unsigned long m_SlicesRotationObserverTag1; + unsigned long m_SlicesRotationObserverTag2; + unsigned long m_FiberBundleObserverTag; + mitk::ColorProperty::Pointer m_Color; }; #endif // _QMITKControlVisualizationPropertiesView_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesViewControls.ui index 0f706d78c1..47e5b8ea1b 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesViewControls.ui @@ -1,911 +1,933 @@ QmitkControlVisualizationPropertiesViewControls 0 0 499 652 0 100 0 0 QmitkTemplate 0 QFrame::NoFrame QFrame::Raised 0 0 0 QFrame::NoFrame QFrame::Raised 0 Reinit view Reinit view Reinit view false false Texture interpolation ON Texture interpolation ON Texture interpolation ON true false Toggle visibility of ODF glyphs Toggle visibility of ODF glyphs Toggle visibility of ODF glyphs :/QmitkDiffusionImaging/glyphsoff_T.png :/QmitkDiffusionImaging/glyphson_T.png:/QmitkDiffusionImaging/glyphsoff_T.png true false Toggle visibility of ODF glyphs Toggle visibility of ODF glyphs Toggle visibility of ODF glyphs :/QmitkDiffusionImaging/glyphsoff_S.png :/QmitkDiffusionImaging/glyphson_S.png:/QmitkDiffusionImaging/glyphsoff_S.png true false Toggle visibility of ODF glyphs Toggle visibility of ODF glyphs Toggle visibility of ODF glyphs :/QmitkDiffusionImaging/glyphsoff_C.png :/QmitkDiffusionImaging/glyphson_C.png:/QmitkDiffusionImaging/glyphsoff_C.png true false Multislice Projection Multislice Projection Multislice Projection MIP QToolButton::MenuButtonPopup Qt::NoArrow Channel 300 Qt::Horizontal QFrame::NoFrame QFrame::Plain 0 Qt::Horizontal 20 20 #Glyphs 9999 QFrame::NoFrame QFrame::Plain 0 Opacity 100 Qt::Horizontal 80 0 0.0 : 0.0 QFrame::NoFrame QFrame::Raised 0 0 QFrame::NoFrame QFrame::Raised 6 0 0 QFrame::NoFrame QFrame::Plain 0 false None By GFA By ASR * Scaling QFrame::NoFrame QFrame::Plain 0 0 false Min-Max Max None QFrame::NoFrame QFrame::Raised 0 Param1 9999.989999999999782 Param2 9999.989999999999782 QFrame::NoFrame QFrame::Raised 0 QFrame::NoFrame QFrame::Raised 0 Uniform Color for Bundle Reset to Default Coloring Position Crosshair by 3D-Click true false Generate Tract Density Image 2D Fiberfading on/off Qt::Horizontal 40 20 QFrame::NoFrame QFrame::Raised 0 2D Clipping 100 10 10 10 Qt::Horizontal 90 0 10000 16777215 Range QFrame::NoFrame QFrame::Raised 0 0 QFrame::NoFrame QFrame::Raised 0 50 16777215 Tube 15 Qt::Horizontal 90 0 10000 16777215 Radius QFrame::NoFrame QFrame::Raised 0 50 16777215 Wire 1 9 1 Qt::Horizontal 90 0 43 16777215 Width QFrame::NoFrame QFrame::Raised 0 Focus Planar Figure 0 0 Select ROI color. Adjust 2D line width. 1 100 20 Qt::Horizontal 80 0 Width Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + 50 + false + false + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#ff0000;"> ODF Visualisation not possible in rotated planes. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#ff0000;"> Use 'Reinit' on the image node to reset. </span></p></body></html> + + + Qt::AutoText + + + Qt::Vertical 20 40 Show Welcome Screen QmitkFloatingPointSpanSlider QSlider
QmitkFloatingPointSpanSlider.h
QmitkDataStorageComboBox.h
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDiffusionQuantificationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDiffusionQuantificationView.cpp index fa451ebff4..0030b57e25 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDiffusionQuantificationView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDiffusionQuantificationView.cpp @@ -1,655 +1,665 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date: 2009-05-28 17:19:30 +0200 (Do, 28 Mai 2009) $ Version: $Revision: 17495 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkDiffusionQuantificationView.h" #include "mitkDiffusionImagingConfigure.h" #include "itkTimeProbe.h" #include "itkImage.h" #include "mitkNodePredicateDataType.h" #include "mitkDataNodeObject.h" #include "mitkQBallImage.h" #include "mitkImageCast.h" #include "mitkStatusBar.h" #include "itkDiffusionQballGeneralizedFaImageFilter.h" #include "itkShiftScaleImageFilter.h" #include "itkTensorFractionalAnisotropyImageFilter.h" #include "itkTensorRelativeAnisotropyImageFilter.h" #include "itkTensorDerivedMeasurementsFilter.h" #include "QmitkDataStorageComboBox.h" #include "QmitkStdMultiWidget.h" #include #include "berryIWorkbenchWindow.h" #include "berryISelectionService.h" const std::string QmitkDiffusionQuantificationView::VIEW_ID = "org.mitk.views.diffusionquantification"; using namespace berry; struct DqSelListener : ISelectionListener { berryObjectMacro(DqSelListener); DqSelListener(QmitkDiffusionQuantificationView* view) { m_View = view; } void DoSelectionChanged(ISelection::ConstPointer selection) { // save current selection in member variable m_View->m_CurrentSelection = selection.Cast(); // do something with the selected items if(m_View->m_CurrentSelection) { bool foundQBIVolume = false; bool foundTensorVolume = false; // iterate selection for (IStructuredSelection::iterator i = m_View->m_CurrentSelection->Begin(); i != m_View->m_CurrentSelection->End(); ++i) { // extract datatree node if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); // only look at interesting types - if(QString("QBallImage").compare(node->GetData()->GetNameOfClass())==0) + // process only on valid nodes + const mitk::BaseData* nodeData = node->GetData(); + if(nodeData) { - foundQBIVolume = true; - } - - if(QString("TensorImage").compare(node->GetData()->GetNameOfClass())==0) - { - foundTensorVolume = true; + if(QString("QBallImage").compare(nodeData->GetNameOfClass())==0) + { + foundQBIVolume = true; + } + + if(QString("TensorImage").compare(nodeData->GetNameOfClass())==0) + { + foundTensorVolume = true; + } } } } m_View->m_Controls->m_GFAButton->setEnabled(foundQBIVolume); m_View->m_Controls->m_CurvatureButton->setEnabled(foundQBIVolume); m_View->m_Controls->m_FAButton->setEnabled(foundTensorVolume); m_View->m_Controls->m_RAButton->setEnabled(foundTensorVolume); m_View->m_Controls->m_ADButton->setEnabled(foundTensorVolume); m_View->m_Controls->m_RDButton->setEnabled(foundTensorVolume); m_View->m_Controls->m_MDButton->setEnabled(foundTensorVolume); m_View->m_Controls->m_ClusteringAnisotropy->setEnabled(foundTensorVolume); } } void SelectionChanged(IWorkbenchPart::Pointer part, ISelection::ConstPointer selection) { // check, if selection comes from datamanager if (part) { QString partname(part->GetPartName().c_str()); if(partname.compare("Datamanager")==0) { // apply selection DoSelectionChanged(selection); } } } QmitkDiffusionQuantificationView* m_View; }; QmitkDiffusionQuantificationView::QmitkDiffusionQuantificationView() : QmitkFunctionality(), m_Controls(NULL), m_MultiWidget(NULL) { } QmitkDiffusionQuantificationView::QmitkDiffusionQuantificationView(const QmitkDiffusionQuantificationView& other) { Q_UNUSED(other) throw std::runtime_error("Copy constructor not implemented"); } QmitkDiffusionQuantificationView::~QmitkDiffusionQuantificationView() { this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->RemovePostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener); } void QmitkDiffusionQuantificationView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkDiffusionQuantificationViewControls; m_Controls->setupUi(parent); this->CreateConnections(); GFACheckboxClicked(); #ifndef DIFFUSION_IMAGING_EXTENDED m_Controls->m_StandardGFACheckbox->setVisible(false); m_Controls->frame_3->setVisible(false); m_Controls->m_CurvatureButton->setVisible(false); #endif } m_SelListener = berry::ISelectionListener::Pointer(new DqSelListener(this)); this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener); berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); } void QmitkDiffusionQuantificationView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkDiffusionQuantificationView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkDiffusionQuantificationView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_StandardGFACheckbox), SIGNAL(clicked()), this, SLOT(GFACheckboxClicked()) ); connect( (QObject*)(m_Controls->m_GFAButton), SIGNAL(clicked()), this, SLOT(GFA()) ); connect( (QObject*)(m_Controls->m_CurvatureButton), SIGNAL(clicked()), this, SLOT(Curvature()) ); connect( (QObject*)(m_Controls->m_FAButton), SIGNAL(clicked()), this, SLOT(FA()) ); connect( (QObject*)(m_Controls->m_RAButton), SIGNAL(clicked()), this, SLOT(RA()) ); connect( (QObject*)(m_Controls->m_ADButton), SIGNAL(clicked()), this, SLOT(AD()) ); connect( (QObject*)(m_Controls->m_RDButton), SIGNAL(clicked()), this, SLOT(RD()) ); connect( (QObject*)(m_Controls->m_MDButton), SIGNAL(clicked()), this, SLOT(MD()) ); connect( (QObject*)(m_Controls->m_ClusteringAnisotropy), SIGNAL(clicked()), this, SLOT(ClusterAnisotropy()) ); } } void QmitkDiffusionQuantificationView::Activated() { berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); QmitkFunctionality::Activated(); } void QmitkDiffusionQuantificationView::Deactivated() { QmitkFunctionality::Deactivated(); } void QmitkDiffusionQuantificationView::GFACheckboxClicked() { m_Controls->frame_2->setVisible(m_Controls-> m_StandardGFACheckbox->isChecked()); } void QmitkDiffusionQuantificationView::GFA() { if(m_Controls->m_StandardGFACheckbox->isChecked()) { QBIQuantify(13); } else { QBIQuantify(0); } } void QmitkDiffusionQuantificationView::Curvature() { QBIQuantify(12); } void QmitkDiffusionQuantificationView::FA() { TensorQuantify(0); } void QmitkDiffusionQuantificationView::RA() { TensorQuantify(1); } void QmitkDiffusionQuantificationView::AD() { TensorQuantify(2); } void QmitkDiffusionQuantificationView::RD() { TensorQuantify(3); } void QmitkDiffusionQuantificationView::ClusterAnisotropy() { TensorQuantify(4); } void QmitkDiffusionQuantificationView::MD() { TensorQuantify(5); } void QmitkDiffusionQuantificationView::QBIQuantify(int method) { if (m_CurrentSelection) { mitk::DataStorage::SetOfObjects::Pointer set = mitk::DataStorage::SetOfObjects::New(); int at = 0; for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i) { if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); if(QString("QBallImage").compare(node->GetData()->GetNameOfClass())==0) { set->InsertElement(at++, node); } } } QBIQuantification(set, method); } } void QmitkDiffusionQuantificationView::TensorQuantify(int method) { if (m_CurrentSelection) { mitk::DataStorage::SetOfObjects::Pointer set = mitk::DataStorage::SetOfObjects::New(); int at = 0; for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i) { if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); - if(QString("TensorImage").compare(node->GetData()->GetNameOfClass())==0) + // process only on valid nodes + mitk::BaseData* nodeData = node->GetData(); + if(nodeData) { - set->InsertElement(at++, node); + if(QString("TensorImage").compare(nodeData->GetNameOfClass())==0) + { + set->InsertElement(at++, node); + } } } } TensorQuantification(set, method); } } void QmitkDiffusionQuantificationView::QBIQuantification( mitk::DataStorage::SetOfObjects::Pointer inImages, int method) { itk::TimeProbe clock; QString status; int nrFiles = inImages->size(); if (!nrFiles) return; mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { typedef float TOdfPixelType; const int odfsize = QBALL_ODFSIZE; typedef itk::Vector OdfVectorType; typedef itk::Image OdfVectorImgType; mitk::Image* vol = static_cast((*itemiter)->GetData()); OdfVectorImgType::Pointer itkvol = OdfVectorImgType::New(); mitk::CastToItkImage(vol, itkvol); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); ++itemiter; float p1 = m_Controls->m_ParamKEdit->text().toFloat(); float p2 = m_Controls->m_ParamPEdit->text().toFloat(); // COMPUTE RA clock.Start(); MBI_INFO << "Computing GFA "; mitk::StatusBar::GetInstance()->DisplayText(status.sprintf( "Computing GFA for %s", nodename.c_str()).toAscii()); typedef OdfVectorType::ValueType RealValueType; typedef itk::Image< RealValueType, 3 > RAImageType; typedef itk::DiffusionQballGeneralizedFaImageFilter GfaFilterType; GfaFilterType::Pointer gfaFilter = GfaFilterType::New(); gfaFilter->SetInput(itkvol); gfaFilter->SetNumberOfThreads(8); double scale = 1; std::string newname; newname.append(nodename); switch(method) { case 0: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_STANDARD); newname.append("GFA"); break; } case 1: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_QUANTILES_HIGH_LOW); newname.append("01"); break; } case 2: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_QUANTILE_HIGH); newname.append("02"); break; } case 3: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_MAX_ODF_VALUE); newname.append("03"); break; } case 4: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_DECONVOLUTION_COEFFS); newname.append("04"); break; } case 5: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_MIN_MAX_NORMALIZED_STANDARD); newname.append("05"); break; } case 6: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_NORMALIZED_ENTROPY); newname.append("06"); break; } case 7: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_NEMATIC_ORDER_PARAMETER); newname.append("07"); break; } case 8: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_QUANTILES_LOW_HIGH); newname.append("08"); break; } case 9: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_QUANTILE_LOW); newname.append("09"); break; } case 10: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_MIN_ODF_VALUE); newname.append("10"); break; } case 11: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_STD_BY_MAX); newname.append("11"); break; } case 12: { p1 = m_Controls->MinAngle->text().toFloat(); p2 = m_Controls->MaxAngle->text().toFloat(); gfaFilter->SetComputationMethod(GfaFilterType::GFA_PRINCIPLE_CURVATURE); QString paramString; paramString = paramString.append("PC%1-%2").arg(p1).arg(p2); newname.append(paramString.toAscii()); gfaFilter->SetParam1(p1); gfaFilter->SetParam2(p2); break; } case 13: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_GENERALIZED_GFA); QString paramString; paramString = paramString.append("GFAK%1P%2").arg(p1).arg(p2); newname.append(paramString.toAscii()); gfaFilter->SetParam1(p1); gfaFilter->SetParam2(p2); break; } default: { newname.append("0"); gfaFilter->SetComputationMethod(GfaFilterType::GFA_STANDARD); } } gfaFilter->Update(); clock.Stop(); MBI_DEBUG << "took " << clock.GetMeanTime() << "s."; typedef itk::Image ImgType; ImgType::Pointer img = ImgType::New(); img->SetSpacing( gfaFilter->GetOutput()->GetSpacing() ); // Set the image spacing img->SetOrigin( gfaFilter->GetOutput()->GetOrigin() ); // Set the image origin img->SetDirection( gfaFilter->GetOutput()->GetDirection() ); // Set the image direction img->SetLargestPossibleRegion( gfaFilter->GetOutput()->GetLargestPossibleRegion()); img->SetBufferedRegion( gfaFilter->GetOutput()->GetLargestPossibleRegion() ); img->Allocate(); itk::ImageRegionIterator ot (img, img->GetLargestPossibleRegion() ); ot = ot.Begin(); itk::ImageRegionConstIterator it (gfaFilter->GetOutput(), gfaFilter->GetOutput()->GetLargestPossibleRegion() ); it = it.Begin(); for (it = it.Begin(); !it.IsAtEnd(); ++it) { GfaFilterType::OutputImageType::PixelType val = it.Get(); ot.Set(val * m_Controls->m_ScaleImageValuesBox->value()); ++ot; } // GFA TO DATATREE mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk( img.GetPointer() ); image->SetVolume( img->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( image ); node->SetProperty( "name", mitk::StringProperty::New(newname) ); nodes.push_back(node); mitk::StatusBar::GetInstance()->DisplayText("Computation complete."); } std::vector::iterator nodeIt; for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt) GetDefaultDataStorage()->Add(*nodeIt); m_MultiWidget->RequestUpdate(); } void QmitkDiffusionQuantificationView::TensorQuantification( mitk::DataStorage::SetOfObjects::Pointer inImages, int method) { itk::TimeProbe clock; QString status; int nrFiles = inImages->size(); if (!nrFiles) return; mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { typedef float TTensorPixelType; typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType; typedef itk::Image< TensorPixelType, 3 > TensorImageType; mitk::Image* vol = static_cast((*itemiter)->GetData()); TensorImageType::Pointer itkvol = TensorImageType::New(); mitk::CastToItkImage(vol, itkvol); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); ++itemiter; // COMPUTE FA clock.Start(); MBI_INFO << "Computing FA "; mitk::StatusBar::GetInstance()->DisplayText(status.sprintf( "Computing FA for %s", nodename.c_str()).toAscii()); typedef itk::Image< TTensorPixelType, 3 > FAImageType; typedef itk::ShiftScaleImageFilter ShiftScaleFilterType; ShiftScaleFilterType::Pointer multi = ShiftScaleFilterType::New(); multi->SetShift(0.0); multi->SetScale(m_Controls->m_ScaleImageValuesBox->value());//itk::NumericTraits::max() typedef itk::TensorDerivedMeasurementsFilter MeasurementsType; if(method == 0) //FA { /* typedef itk::TensorFractionalAnisotropyImageFilter< TensorImageType, FAImageType > FilterType; FilterType::Pointer anisotropyFilter = FilterType::New(); anisotropyFilter->SetInput( itkvol.GetPointer() ); anisotropyFilter->Update(); multi->SetInput(anisotropyFilter->GetOutput()); nodename = QString(nodename.c_str()).append("_FA").toStdString();*/ MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itkvol.GetPointer() ); measurementsCalculator->SetMeasure(MeasurementsType::FA); measurementsCalculator->Update(); multi->SetInput(measurementsCalculator->GetOutput()); nodename = QString(nodename.c_str()).append("_FA").toStdString(); } else if(method == 1) //RA { /*typedef itk::TensorRelativeAnisotropyImageFilter< TensorImageType, FAImageType > FilterType; FilterType::Pointer anisotropyFilter = FilterType::New(); anisotropyFilter->SetInput( itkvol.GetPointer() ); anisotropyFilter->Update(); multi->SetInput(anisotropyFilter->GetOutput()); nodename = QString(nodename.c_str()).append("_RA").toStdString();*/ MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itkvol.GetPointer() ); measurementsCalculator->SetMeasure(MeasurementsType::RA); measurementsCalculator->Update(); multi->SetInput(measurementsCalculator->GetOutput()); nodename = QString(nodename.c_str()).append("_RA").toStdString(); } else if(method == 2) // AD (Axial diffusivity) { MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itkvol.GetPointer() ); measurementsCalculator->SetMeasure(MeasurementsType::AD); measurementsCalculator->Update(); multi->SetInput(measurementsCalculator->GetOutput()); nodename = QString(nodename.c_str()).append("_AD").toStdString(); } else if(method == 3) // RD (Radial diffusivity, (Lambda2+Lambda3)/2 { MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itkvol.GetPointer() ); measurementsCalculator->SetMeasure(MeasurementsType::RD); measurementsCalculator->Update(); multi->SetInput(measurementsCalculator->GetOutput()); nodename = QString(nodename.c_str()).append("_RD").toStdString(); } else if(method == 4) // 1-(Lambda2+Lambda3)/(2*Lambda1) { MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itkvol.GetPointer() ); measurementsCalculator->SetMeasure(MeasurementsType::CA); measurementsCalculator->Update(); multi->SetInput(measurementsCalculator->GetOutput()); nodename = QString(nodename.c_str()).append("_CA").toStdString(); } else if(method == 5) // MD (Mean Diffusivity, (Lambda1+Lambda2+Lambda3)/3 ) { MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itkvol.GetPointer() ); measurementsCalculator->SetMeasure(MeasurementsType::MD); measurementsCalculator->Update(); multi->SetInput(measurementsCalculator->GetOutput()); nodename = QString(nodename.c_str()).append("_MD").toStdString(); } multi->Update(); clock.Stop(); MBI_DEBUG << "took " << clock.GetMeanTime() << "s."; // FA TO DATATREE mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk( multi->GetOutput() ); image->SetVolume( multi->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( image ); node->SetProperty( "name", mitk::StringProperty::New(nodename) ); nodes.push_back(node); mitk::StatusBar::GetInstance()->DisplayText("Computation complete."); } std::vector::iterator nodeIt; for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt) GetDefaultDataStorage()->Add(*nodeIt); m_MultiWidget->RequestUpdate(); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.cpp index a39cde0604..2dde0a992c 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.cpp @@ -1,1710 +1,1759 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $ Version: $Revision: 21975 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkFiberProcessingView.h" #include // Qt #include // MITK #include #include #include #include #include #include #include #include #include #include #include // ITK #include #include #include #include #include #include #include #include const std::string QmitkFiberProcessingView::VIEW_ID = "org.mitk.views.fiberprocessing"; const std::string id_DataManager = "org.mitk.views.datamanager"; using namespace mitk; QmitkFiberProcessingView::QmitkFiberProcessingView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) , m_EllipseCounter(0) , m_PolygonCounter(0) , m_UpsamplingFactor(5) { } // Destructor QmitkFiberProcessingView::~QmitkFiberProcessingView() { } void QmitkFiberProcessingView::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::QmitkFiberProcessingViewControls; m_Controls->setupUi( parent ); m_Controls->doExtractFibersButton->setDisabled(true); m_Controls->PFCompoANDButton->setDisabled(true); m_Controls->PFCompoORButton->setDisabled(true); m_Controls->PFCompoNOTButton->setDisabled(true); m_Controls->m_PlanarFigureButtonsFrame->setEnabled(false); m_Controls->m_RectangleButton->setVisible(false); connect( m_Controls->doExtractFibersButton, SIGNAL(clicked()), this, SLOT(DoFiberExtraction()) ); connect( m_Controls->m_CircleButton, SIGNAL( clicked() ), this, SLOT( OnDrawCircle() ) ); connect( m_Controls->m_PolygonButton, SIGNAL( clicked() ), this, SLOT( OnDrawPolygon() ) ); connect(m_Controls->PFCompoANDButton, SIGNAL(clicked()), this, SLOT(GenerateAndComposite()) ); connect(m_Controls->PFCompoORButton, SIGNAL(clicked()), this, SLOT(GenerateOrComposite()) ); connect(m_Controls->PFCompoNOTButton, SIGNAL(clicked()), this, SLOT(GenerateNotComposite()) ); connect(m_Controls->m_JoinBundles, SIGNAL(clicked()), this, SLOT(JoinBundles()) ); connect(m_Controls->m_SubstractBundles, SIGNAL(clicked()), this, SLOT(SubstractBundles()) ); connect(m_Controls->m_GenerateRoiImage, SIGNAL(clicked()), this, SLOT(GenerateRoiImage()) ); connect(m_Controls->m_Extract3dButton, SIGNAL(clicked()), this, SLOT(Extract3d())); connect( m_Controls->m_ProcessFiberBundleButton, SIGNAL(clicked()), this, SLOT(ProcessSelectedBundles()) ); connect( m_Controls->m_ResampleFibersButton, SIGNAL(clicked()), this, SLOT(ResampleSelectedBundles()) ); + connect(m_Controls->m_FaColorFibersButton, SIGNAL(clicked()), this, SLOT(DoFaColorCoding())); } } void QmitkFiberProcessingView::Extract3d() { std::vector nodes = this->GetDataManagerSelection(); if (nodes.empty()) return; mitk::FiberBundleX::Pointer fib = mitk::FiberBundleX::New(); mitk::Surface::Pointer roi = mitk::Surface::New(); bool fibB = false; bool roiB = false; for (int i=0; i(nodes.at(i)->GetData())) { fib = dynamic_cast(nodes.at(i)->GetData()); fibB = true; } else if (dynamic_cast(nodes.at(i)->GetData())) { roi = dynamic_cast(nodes.at(i)->GetData()); roiB = true; } } if (!fibB) return; if (!roiB) return; vtkSmartPointer polyRoi = roi->GetVtkPolyData(); vtkSmartPointer polyFib = fib->GetFiberPolyData(); vtkSmartPointer selectEnclosedPoints = vtkSmartPointer::New(); selectEnclosedPoints->SetInput(polyFib); selectEnclosedPoints->SetSurface(polyRoi); selectEnclosedPoints->Update(); vtkSmartPointer newPoly = vtkSmartPointer::New(); vtkSmartPointer newCellArray = vtkSmartPointer::New(); vtkSmartPointer newPoints = vtkSmartPointer::New(); vtkSmartPointer newPolyComplement = vtkSmartPointer::New(); vtkSmartPointer newCellArrayComplement = vtkSmartPointer::New(); vtkSmartPointer newPointsComplement = vtkSmartPointer::New(); vtkSmartPointer vLines = polyFib->GetLines(); vLines->InitTraversal(); int numberOfLines = vLines->GetNumberOfCells(); // each line for (int j=0; jGetNextCell ( numPoints, points ); bool isPassing = false; // each point of this line for (int k=0; kIsInside(points[k])) { isPassing = true; // fill new polydata vtkSmartPointer container = vtkSmartPointer::New(); for (int k=0; kGetPoint(points[k]); vtkIdType pointId = newPoints->InsertNextPoint(point); container->GetPointIds()->InsertNextId(pointId); } newCellArray->InsertNextCell(container); break; } } if (!isPassing) { vtkSmartPointer container = vtkSmartPointer::New(); for (int k=0; kGetPoint(points[k]); vtkIdType pointId = newPointsComplement->InsertNextPoint(point); container->GetPointIds()->InsertNextId(pointId); } newCellArrayComplement->InsertNextCell(container); } } newPoly->SetPoints(newPoints); newPoly->SetLines(newCellArray); mitk::FiberBundleX::Pointer fb = mitk::FiberBundleX::New(newPoly); DataNode::Pointer newNode = DataNode::New(); newNode->SetData(fb); newNode->SetName("passing surface"); GetDefaultDataStorage()->Add(newNode); newPolyComplement->SetPoints(newPointsComplement); newPolyComplement->SetLines(newCellArrayComplement); mitk::FiberBundleX::Pointer fbComplement = mitk::FiberBundleX::New(newPolyComplement); DataNode::Pointer newNodeComplement = DataNode::New(); newNodeComplement->SetData(fbComplement); newNodeComplement->SetName("not passing surface"); GetDefaultDataStorage()->Add(newNodeComplement); } void QmitkFiberProcessingView::GenerateRoiImage(){ - if (m_SelectedImage.IsNull() || m_SelectedPF.empty()) + if (m_SelectedPF.empty()) return; - mitk::Image* image = const_cast(m_SelectedImage.GetPointer()); - - UCharImageType::Pointer temp = UCharImageType::New(); - mitk::CastToItkImage(m_SelectedImage, temp); + mitk::Geometry3D::Pointer geometry; + if (m_SelectedImage.IsNotNull()) + geometry = m_SelectedImage->GetGeometry(); + else if (!m_SelectedFB.empty()) + { + mitk::FiberBundleX::Pointer fib = dynamic_cast(m_SelectedFB.front()->GetData()); + geometry = fib->GetGeometry(); + } + else + return; - m_PlanarFigureImage = UCharImageType::New(); - m_PlanarFigureImage->SetSpacing( temp->GetSpacing() ); // Set the image spacing - m_PlanarFigureImage->SetOrigin( temp->GetOrigin() ); // Set the image origin - m_PlanarFigureImage->SetDirection( temp->GetDirection() ); // Set the image direction - m_PlanarFigureImage->SetRegions( temp->GetLargestPossibleRegion() ); + itk::Matrix direction; + itk::ImageRegion<3> imageRegion; + for (int i=0; i<3; i++) + for (int j=0; j<3; j++) + direction[j][i] = geometry->GetMatrixColumn(i)[j]; + imageRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor); + imageRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor); + imageRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor); + + m_PlanarFigureImage = itkUCharImageType::New(); + m_PlanarFigureImage->SetSpacing( geometry->GetSpacing() ); // Set the image spacing + m_PlanarFigureImage->SetOrigin( geometry->GetOrigin() ); // Set the image origin + m_PlanarFigureImage->SetDirection( direction ); // Set the image direction + m_PlanarFigureImage->SetRegions( imageRegion ); m_PlanarFigureImage->Allocate(); m_PlanarFigureImage->FillBuffer( 0 ); + Image::Pointer tmpImage = Image::New(); + tmpImage->InitializeByItk(m_PlanarFigureImage.GetPointer()); + tmpImage->SetVolume(m_PlanarFigureImage->GetBufferPointer()); + for (int i=0; iInitializeByItk(m_PlanarFigureImage.GetPointer()); tmpImage->SetVolume(m_PlanarFigureImage->GetBufferPointer()); node->SetData(tmpImage); node->SetName("ROI Image"); this->GetDefaultDataStorage()->Add(node); } void QmitkFiberProcessingView::CompositeExtraction(mitk::DataNode::Pointer node, mitk::Image* image) { if (dynamic_cast(node.GetPointer()->GetData()) && !dynamic_cast(node.GetPointer()->GetData())) { m_PlanarFigure = dynamic_cast(node.GetPointer()->GetData()); AccessFixedDimensionByItk_2( image, InternalReorientImagePlane, 3, m_PlanarFigure->GetGeometry(), -1); // itk::Image< unsigned char, 3 >::Pointer outimage = itk::Image< unsigned char, 3 >::New(); // outimage->SetSpacing( m_PlanarFigure->GetGeometry()->GetSpacing()/m_UpsamplingFactor ); // Set the image spacing // mitk::Point3D origin = m_PlanarFigure->GetGeometry()->GetOrigin(); // mitk::Point3D indexOrigin; // m_PlanarFigure->GetGeometry()->WorldToIndex(origin, indexOrigin); // indexOrigin[0] = indexOrigin[0] - .5 * (1.0-1.0/m_UpsamplingFactor); // indexOrigin[1] = indexOrigin[1] - .5 * (1.0-1.0/m_UpsamplingFactor); // indexOrigin[2] = indexOrigin[2] - .5 * (1.0-1.0/m_UpsamplingFactor); // mitk::Point3D newOrigin; // m_PlanarFigure->GetGeometry()->IndexToWorld(indexOrigin, newOrigin); // outimage->SetOrigin( newOrigin ); // Set the image origin // itk::Matrix matrix; // for (int i=0; i<3; i++) // for (int j=0; j<3; j++) // matrix[j][i] = m_PlanarFigure->GetGeometry()->GetMatrixColumn(i)[j]/m_PlanarFigure->GetGeometry()->GetSpacing().GetElement(i); // outimage->SetDirection( matrix ); // Set the image direction // itk::ImageRegion<3> upsampledRegion; // upsampledRegion.SetSize(0, m_PlanarFigure->GetGeometry()->GetParametricExtentInMM(0)/m_PlanarFigure->GetGeometry()->GetSpacing()[0]); // upsampledRegion.SetSize(1, m_PlanarFigure->GetGeometry()->GetParametricExtentInMM(1)/m_PlanarFigure->GetGeometry()->GetSpacing()[1]); // upsampledRegion.SetSize(2, 1); // typename itk::Image< unsigned char, 3 >::RegionType::SizeType upsampledSize = upsampledRegion.GetSize(); // for (unsigned int n = 0; n < 2; n++) // { // upsampledSize[n] = upsampledSize[n] * m_UpsamplingFactor; // } // upsampledRegion.SetSize( upsampledSize ); // outimage->SetRegions( upsampledRegion ); // outimage->Allocate(); // this->m_InternalImage = mitk::Image::New(); // this->m_InternalImage->InitializeByItk( outimage.GetPointer() ); // this->m_InternalImage->SetVolume( outimage->GetBufferPointer() ); AccessFixedDimensionByItk_2( m_InternalImage, InternalCalculateMaskFromPlanarFigure, 3, 2, node->GetName() ); } } template < typename TPixel, unsigned int VImageDimension > void QmitkFiberProcessingView::InternalReorientImagePlane( const itk::Image< TPixel, VImageDimension > *image, mitk::Geometry3D* planegeo3D, int additionalIndex ) { MITK_INFO << "InternalReorientImagePlane() start"; typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::Image< float, VImageDimension > FloatImageType; typedef itk::ResampleImageFilter ResamplerType; typename ResamplerType::Pointer resampler = ResamplerType::New(); mitk::PlaneGeometry* planegeo = dynamic_cast(planegeo3D); float upsamp = m_UpsamplingFactor; float gausssigma = 0.5; // Spacing typename ResamplerType::SpacingType spacing = planegeo->GetSpacing(); spacing[0] = image->GetSpacing()[0] / upsamp; spacing[1] = image->GetSpacing()[1] / upsamp; spacing[2] = image->GetSpacing()[2]; resampler->SetOutputSpacing( spacing ); // Size typename ResamplerType::SizeType size; size[0] = planegeo->GetParametricExtentInMM(0) / spacing[0]; size[1] = planegeo->GetParametricExtentInMM(1) / spacing[1]; size[2] = 1; resampler->SetSize( size ); // Origin typename mitk::Point3D orig = planegeo->GetOrigin(); typename mitk::Point3D corrorig; planegeo3D->WorldToIndex(orig,corrorig); corrorig[0] += 0.5/upsamp; corrorig[1] += 0.5/upsamp; corrorig[2] += 0; planegeo3D->IndexToWorld(corrorig,corrorig); resampler->SetOutputOrigin(corrorig ); // Direction typename ResamplerType::DirectionType direction; typename mitk::AffineTransform3D::MatrixType matrix = planegeo->GetIndexToWorldTransform()->GetMatrix(); for(int c=0; cSetOutputDirection( direction ); // Gaussian interpolation if(gausssigma != 0) { double sigma[3]; for( unsigned int d = 0; d < 3; d++ ) { sigma[d] = gausssigma * image->GetSpacing()[d]; } double alpha = 2.0; typedef itk::GaussianInterpolateImageFunction GaussianInterpolatorType; typename GaussianInterpolatorType::Pointer interpolator = GaussianInterpolatorType::New(); interpolator->SetInputImage( image ); interpolator->SetParameters( sigma, alpha ); resampler->SetInterpolator( interpolator ); } else { // typedef typename itk::BSplineInterpolateImageFunction // InterpolatorType; typedef typename itk::LinearInterpolateImageFunction InterpolatorType; typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); interpolator->SetInputImage( image ); resampler->SetInterpolator( interpolator ); } // Other resampling options resampler->SetInput( image ); resampler->SetDefaultPixelValue(0); MITK_INFO << "Resampling requested image plane ... "; resampler->Update(); MITK_INFO << " ... done"; if(additionalIndex < 0) { this->m_InternalImage = mitk::Image::New(); this->m_InternalImage->InitializeByItk( resampler->GetOutput() ); this->m_InternalImage->SetVolume( resampler->GetOutput()->GetBufferPointer() ); } } template < typename TPixel, unsigned int VImageDimension > void QmitkFiberProcessingView::InternalCalculateMaskFromPlanarFigure( itk::Image< TPixel, VImageDimension > *image, unsigned int axis, std::string nodeName ) { MITK_INFO << "InternalCalculateMaskFromPlanarFigure() start"; typedef itk::Image< TPixel, VImageDimension > ImageType; - typedef itk::CastImageFilter< ImageType, UCharImageType > CastFilterType; + typedef itk::CastImageFilter< ImageType, itkUCharImageType > CastFilterType; // Generate mask image as new image with same header as input image and // initialize with "1". - UCharImageType::Pointer newMaskImage = UCharImageType::New(); + itkUCharImageType::Pointer newMaskImage = itkUCharImageType::New(); newMaskImage->SetSpacing( image->GetSpacing() ); // Set the image spacing newMaskImage->SetOrigin( image->GetOrigin() ); // Set the image origin newMaskImage->SetDirection( image->GetDirection() ); // Set the image direction newMaskImage->SetRegions( image->GetLargestPossibleRegion() ); newMaskImage->Allocate(); newMaskImage->FillBuffer( 1 ); // Generate VTK polygon from (closed) PlanarFigure polyline // (The polyline points are shifted by -0.5 in z-direction to make sure // that the extrusion filter, which afterwards elevates all points by +0.5 // in z-direction, creates a 3D object which is cut by the the plane z=0) const Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D(); const PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 ); const Geometry3D *imageGeometry3D = m_InternalImage->GetGeometry( 0 ); vtkPolyData *polyline = vtkPolyData::New(); polyline->Allocate( 1, 1 ); // Determine x- and y-dimensions depending on principal axis int i0, i1; switch ( axis ) { case 0: i0 = 1; i1 = 2; break; case 1: i0 = 0; i1 = 2; break; case 2: default: i0 = 0; i1 = 1; break; } // Create VTK polydata object of polyline contour vtkPoints *points = vtkPoints::New(); PlanarFigure::PolyLineType::const_iterator it; std::vector indices; unsigned int numberOfPoints = 0; for ( it = planarFigurePolyline.begin(); it != planarFigurePolyline.end(); ++it ) { Point3D point3D; // Convert 2D point back to the local index coordinates of the selected // image Point2D point2D = it->Point; planarFigureGeometry2D->WorldToIndex(point2D, point2D); point2D[0] -= 0.5/m_UpsamplingFactor; point2D[1] -= 0.5/m_UpsamplingFactor; planarFigureGeometry2D->IndexToWorld(point2D, point2D); planarFigureGeometry2D->Map( point2D, point3D ); // Polygons (partially) outside of the image bounds can not be processed // further due to a bug in vtkPolyDataToImageStencil if ( !imageGeometry3D->IsInside( point3D ) ) { float bounds[2] = {0,0}; bounds[0] = this->m_InternalImage->GetLargestPossibleRegion().GetSize().GetElement(i0); bounds[1] = this->m_InternalImage->GetLargestPossibleRegion().GetSize().GetElement(i1); imageGeometry3D->WorldToIndex( point3D, point3D ); // if (point3D[i0]<0) // point3D[i0] = 0.5; // else if (point3D[i0]>bounds[0]) // point3D[i0] = bounds[0]-0.5; // if (point3D[i1]<0) // point3D[i1] = 0.5; // else if (point3D[i1]>bounds[1]) // point3D[i1] = bounds[1]-0.5; if (point3D[i0]<0) point3D[i0] = 0.0; else if (point3D[i0]>bounds[0]) point3D[i0] = bounds[0]-0.001; if (point3D[i1]<0) point3D[i1] = 0.0; else if (point3D[i1]>bounds[1]) point3D[i1] = bounds[1]-0.001; points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 ); numberOfPoints++; } else { imageGeometry3D->WorldToIndex( point3D, point3D ); // Add point to polyline array points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 ); numberOfPoints++; } } polyline->SetPoints( points ); points->Delete(); vtkIdType *ptIds = new vtkIdType[numberOfPoints]; for ( vtkIdType i = 0; i < numberOfPoints; ++i ) { ptIds[i] = i; } polyline->InsertNextCell( VTK_POLY_LINE, numberOfPoints, ptIds ); // Extrude the generated contour polygon vtkLinearExtrusionFilter *extrudeFilter = vtkLinearExtrusionFilter::New(); extrudeFilter->SetInput( polyline ); extrudeFilter->SetScaleFactor( 1 ); extrudeFilter->SetExtrusionTypeToNormalExtrusion(); extrudeFilter->SetVector( 0.0, 0.0, 1.0 ); // Make a stencil from the extruded polygon vtkPolyDataToImageStencil *polyDataToImageStencil = vtkPolyDataToImageStencil::New(); polyDataToImageStencil->SetInput( extrudeFilter->GetOutput() ); // Export from ITK to VTK (to use a VTK filter) - typedef itk::VTKImageImport< UCharImageType > ImageImportType; - typedef itk::VTKImageExport< UCharImageType > ImageExportType; + typedef itk::VTKImageImport< itkUCharImageType > ImageImportType; + typedef itk::VTKImageExport< itkUCharImageType > ImageExportType; typename ImageExportType::Pointer itkExporter = ImageExportType::New(); itkExporter->SetInput( newMaskImage ); vtkImageImport *vtkImporter = vtkImageImport::New(); this->ConnectPipelines( itkExporter, vtkImporter ); vtkImporter->Update(); // Apply the generated image stencil to the input image vtkImageStencil *imageStencilFilter = vtkImageStencil::New(); imageStencilFilter->SetInputConnection( vtkImporter->GetOutputPort() ); imageStencilFilter->SetStencil( polyDataToImageStencil->GetOutput() ); imageStencilFilter->ReverseStencilOff(); imageStencilFilter->SetBackgroundValue( 0 ); imageStencilFilter->Update(); // Export from VTK back to ITK vtkImageExport *vtkExporter = vtkImageExport::New(); vtkExporter->SetInputConnection( imageStencilFilter->GetOutputPort() ); vtkExporter->Update(); typename ImageImportType::Pointer itkImporter = ImageImportType::New(); this->ConnectPipelines( vtkExporter, itkImporter ); itkImporter->Update(); // calculate cropping bounding box m_InternalImageMask3D = itkImporter->GetOutput(); m_InternalImageMask3D->SetDirection(image->GetDirection()); - itk::ImageRegionConstIterator + itk::ImageRegionConstIterator itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion()); itk::ImageRegionIterator itimage(image, image->GetLargestPossibleRegion()); itmask = itmask.Begin(); itimage = itimage.Begin(); typename ImageType::SizeType lowersize = {{9999999999,9999999999,9999999999}}; typename ImageType::SizeType uppersize = {{0,0,0}}; while( !itmask.IsAtEnd() ) { if(itmask.Get() == 0) { itimage.Set(0); } else { typename ImageType::IndexType index = itimage.GetIndex(); typename ImageType::SizeType signedindex; signedindex[0] = index[0]; signedindex[1] = index[1]; signedindex[2] = index[2]; lowersize[0] = signedindex[0] < lowersize[0] ? signedindex[0] : lowersize[0]; lowersize[1] = signedindex[1] < lowersize[1] ? signedindex[1] : lowersize[1]; lowersize[2] = signedindex[2] < lowersize[2] ? signedindex[2] : lowersize[2]; uppersize[0] = signedindex[0] > uppersize[0] ? signedindex[0] : uppersize[0]; uppersize[1] = signedindex[1] > uppersize[1] ? signedindex[1] : uppersize[1]; uppersize[2] = signedindex[2] > uppersize[2] ? signedindex[2] : uppersize[2]; } ++itmask; ++itimage; } typename ImageType::IndexType index; index[0] = lowersize[0]; index[1] = lowersize[1]; index[2] = lowersize[2]; typename ImageType::SizeType size; size[0] = uppersize[0] - lowersize[0] + 1; size[1] = uppersize[1] - lowersize[1] + 1; size[2] = uppersize[2] - lowersize[2] + 1; itk::ImageRegion<3> cropRegion = itk::ImageRegion<3>(index, size); // crop internal mask - typedef itk::RegionOfInterestImageFilter< UCharImageType, UCharImageType > ROIMaskFilterType; + typedef itk::RegionOfInterestImageFilter< itkUCharImageType, itkUCharImageType > ROIMaskFilterType; typename ROIMaskFilterType::Pointer roi2 = ROIMaskFilterType::New(); roi2->SetRegionOfInterest(cropRegion); roi2->SetInput(m_InternalImageMask3D); roi2->Update(); m_InternalImageMask3D = roi2->GetOutput(); Image::Pointer tmpImage = Image::New(); tmpImage->InitializeByItk(m_InternalImageMask3D.GetPointer()); tmpImage->SetVolume(m_InternalImageMask3D->GetBufferPointer()); Image::Pointer tmpImage2 = Image::New(); tmpImage2->InitializeByItk(m_PlanarFigureImage.GetPointer()); const Geometry3D *pfImageGeometry3D = tmpImage2->GetGeometry( 0 ); const Geometry3D *intImageGeometry3D = tmpImage->GetGeometry( 0 ); - typedef itk::ImageRegionIteratorWithIndex IteratorType; + typedef itk::ImageRegionIteratorWithIndex IteratorType; IteratorType imageIterator (m_InternalImageMask3D, m_InternalImageMask3D->GetRequestedRegion()); imageIterator.GoToBegin(); while ( !imageIterator.IsAtEnd() ) { unsigned char val = imageIterator.Value(); if (val>0) { itk::Index<3> index = imageIterator.GetIndex(); Point3D point; point[0] = index[0]; point[1] = index[1]; point[2] = index[2]; intImageGeometry3D->IndexToWorld(point, point); pfImageGeometry3D->WorldToIndex(point, point); point[i0] += 0.5; point[i1] += 0.5; index[0] = point[0]; index[1] = point[1]; index[2] = point[2]; m_PlanarFigureImage->SetPixel(index, 1); } ++imageIterator; } // Clean up VTK objects polyline->Delete(); extrudeFilter->Delete(); polyDataToImageStencil->Delete(); vtkImporter->Delete(); imageStencilFilter->Delete(); //vtkExporter->Delete(); // TODO: crashes when outcommented; memory leak?? delete[] ptIds; } void QmitkFiberProcessingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkFiberProcessingView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } /* OnSelectionChanged is registered to SelectionService, therefore no need to implement SelectionService Listener explicitly */ void QmitkFiberProcessingView::UpdateGui() { // are fiber bundles selected? if ( m_SelectedFB.empty() ) { m_Controls->m_JoinBundles->setEnabled(false); m_Controls->m_SubstractBundles->setEnabled(false); m_Controls->m_ProcessFiberBundleButton->setEnabled(false); m_Controls->doExtractFibersButton->setEnabled(false); m_Controls->m_Extract3dButton->setEnabled(false); m_Controls->m_ResampleFibersButton->setEnabled(false); + m_Controls->m_PlanarFigureButtonsFrame->setEnabled(false); + m_Controls->m_FaColorFibersButton->setEnabled(false); } else { m_Controls->m_PlanarFigureButtonsFrame->setEnabled(true); m_Controls->m_ProcessFiberBundleButton->setEnabled(true); m_Controls->m_ResampleFibersButton->setEnabled(true); if (m_Surfaces.size()>0) m_Controls->m_Extract3dButton->setEnabled(true); // one bundle and one planar figure needed to extract fibers if (!m_SelectedPF.empty()) m_Controls->doExtractFibersButton->setEnabled(true); // more than two bundles needed to join/subtract if (m_SelectedFB.size() > 1) { m_Controls->m_JoinBundles->setEnabled(true); m_Controls->m_SubstractBundles->setEnabled(true); } else { m_Controls->m_JoinBundles->setEnabled(false); m_Controls->m_SubstractBundles->setEnabled(false); } + + if (m_SelectedImage.IsNotNull()) + m_Controls->m_FaColorFibersButton->setEnabled(true); } // are planar figures selected? if ( m_SelectedPF.empty() ) { m_Controls->doExtractFibersButton->setEnabled(false); m_Controls->PFCompoANDButton->setEnabled(false); m_Controls->PFCompoORButton->setEnabled(false); m_Controls->PFCompoNOTButton->setEnabled(false); m_Controls->m_GenerateRoiImage->setEnabled(false); } else { - if ( m_SelectedImage.IsNotNull() ) + if ( m_SelectedImage.IsNotNull() || !m_SelectedFB.empty() ) m_Controls->m_GenerateRoiImage->setEnabled(true); else m_Controls->m_GenerateRoiImage->setEnabled(false); if (m_SelectedPF.size() > 1) { m_Controls->PFCompoANDButton->setEnabled(true); m_Controls->PFCompoORButton->setEnabled(true); m_Controls->PFCompoNOTButton->setEnabled(false); } else { m_Controls->PFCompoANDButton->setEnabled(false); m_Controls->PFCompoORButton->setEnabled(false); m_Controls->PFCompoNOTButton->setEnabled(true); } } } void QmitkFiberProcessingView::OnSelectionChanged( std::vector nodes ) { if ( !this->IsVisible() ) return; //reset existing Vectors containing FiberBundles and PlanarFigures from a previous selection m_SelectedFB.clear(); m_SelectedPF.clear(); m_Surfaces.clear(); m_SelectedImage = NULL; for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if ( dynamic_cast(node->GetData()) ) m_SelectedFB.push_back(node); else if (dynamic_cast(node->GetData())) m_SelectedPF.push_back(node); else if (dynamic_cast(node->GetData())) m_SelectedImage = dynamic_cast(node->GetData()); else if (dynamic_cast(node->GetData())) m_Surfaces.push_back(dynamic_cast(node->GetData())); } UpdateGui(); GenerateStats(); } void QmitkFiberProcessingView::OnDrawPolygon() { // bool checked = m_Controls->m_PolygonButton->isChecked(); // if(!this->AssertDrawingIsPossible(checked)) // return; mitk::PlanarPolygon::Pointer figure = mitk::PlanarPolygon::New(); figure->ClosedOn(); this->AddFigureToDataStorage(figure, QString("Polygon%1").arg(++m_PolygonCounter)); MITK_INFO << "PlanarPolygon created ..."; mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDefaultDataStorage()->GetAll(); mitk::DataNode* node = 0; mitk::PlanarFigureInteractor::Pointer figureInteractor = 0; mitk::PlanarFigure* figureP = 0; for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End() ; it++) { node = const_cast(it->Value().GetPointer()); figureP = dynamic_cast(node->GetData()); if(figureP) { figureInteractor = dynamic_cast(node->GetInteractor()); if(figureInteractor.IsNull()) figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", node); mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor); } } } void QmitkFiberProcessingView::OnDrawCircle() { //bool checked = m_Controls->m_CircleButton->isChecked(); //if(!this->AssertDrawingIsPossible(checked)) // return; mitk::PlanarCircle::Pointer figure = mitk::PlanarCircle::New(); this->AddFigureToDataStorage(figure, QString("Circle%1").arg(++m_EllipseCounter)); this->GetDataStorage()->Modified(); MITK_INFO << "PlanarCircle created ..."; //call mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDefaultDataStorage()->GetAll(); mitk::DataNode* node = 0; mitk::PlanarFigureInteractor::Pointer figureInteractor = 0; mitk::PlanarFigure* figureP = 0; for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End() ; it++) { node = const_cast(it->Value().GetPointer()); figureP = dynamic_cast(node->GetData()); if(figureP) { figureInteractor = dynamic_cast(node->GetInteractor()); if(figureInteractor.IsNull()) figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", node); mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor); } } } void QmitkFiberProcessingView::Activated() { MITK_INFO << "FB OPerations ACTIVATED()"; /* mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDefaultDataStorage()->GetAll(); mitk::DataNode* node = 0; mitk::PlanarFigureInteractor::Pointer figureInteractor = 0; mitk::PlanarFigure* figure = 0; for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End() ; it++) { node = const_cast(it->Value().GetPointer()); figure = dynamic_cast(node->GetData()); if(figure) { figureInteractor = dynamic_cast(node->GetInteractor()); if(figureInteractor.IsNull()) figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", node); mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor); } } */ } void QmitkFiberProcessingView::AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, const char *propertyKey, mitk::BaseProperty *property ) { // initialize figure's geometry with empty geometry mitk::PlaneGeometry::Pointer emptygeometry = mitk::PlaneGeometry::New(); figure->SetGeometry2D( emptygeometry ); //set desired data to DataNode where Planarfigure is stored mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetName(name.toStdString()); newNode->SetData(figure); newNode->AddProperty( "planarfigure.default.line.color", mitk::ColorProperty::New(1.0,0.0,0.0)); newNode->AddProperty( "planarfigure.line.width", mitk::FloatProperty::New(2.0)); newNode->AddProperty( "planarfigure.drawshadow", mitk::BoolProperty::New(true)); - newNode->AddProperty( "selected", mitk::BoolProperty::New(true) ); newNode->AddProperty( "planarfigure.ishovering", mitk::BoolProperty::New(true) ); newNode->AddProperty( "planarfigure.drawoutline", mitk::BoolProperty::New(true) ); newNode->AddProperty( "planarfigure.drawquantities", mitk::BoolProperty::New(false) ); newNode->AddProperty( "planarfigure.drawshadow", mitk::BoolProperty::New(true) ); newNode->AddProperty( "planarfigure.line.width", mitk::FloatProperty::New(3.0) ); newNode->AddProperty( "planarfigure.shadow.widthmodifier", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.outline.width", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.helperline.width", mitk::FloatProperty::New(2.0) ); -// PlanarFigureControlPointStyleProperty::Pointer styleProperty = -// dynamic_cast< PlanarFigureControlPointStyleProperty* >( node->GetProperty( "planarfigure.controlpointshape" ) ); -// if ( styleProperty.IsNotNull() ) -// { -// m_ControlPointShape = styleProperty->GetShape(); -// } - newNode->AddProperty( "planarfigure.default.line.color", mitk::ColorProperty::New(1.0,1.0,1.0) ); newNode->AddProperty( "planarfigure.default.line.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.default.outline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.default.outline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.default.helperline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.default.helperline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.default.markerline.color", mitk::ColorProperty::New(0.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.default.markerline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.default.marker.color", mitk::ColorProperty::New(1.0,1.0,1.0) ); newNode->AddProperty( "planarfigure.default.marker.opacity",mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.hover.line.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.hover.line.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.hover.outline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.hover.outline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.hover.helperline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.hover.helperline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.hover.markerline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.hover.markerline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.hover.marker.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.hover.marker.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.selected.line.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.selected.line.opacity",mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.selected.outline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.selected.outline.opacity", mitk::FloatProperty::New(2.0)); newNode->AddProperty( "planarfigure.selected.helperline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.selected.helperline.opacity",mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.selected.markerline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.selected.markerline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.selected.marker.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.selected.marker.opacity",mitk::FloatProperty::New(2.0)); // figure drawn on the topmost layer / image newNode->SetColor(1.0,1.0,1.0); newNode->SetOpacity(0.8); GetDataStorage()->Add(newNode ); std::vector selectedNodes = GetDataManagerSelection(); for(unsigned int i = 0; i < selectedNodes.size(); i++) { selectedNodes[i]->SetSelected(false); } newNode->SetSelected(true); } void QmitkFiberProcessingView::DoFiberExtraction() { if ( m_SelectedFB.empty() ){ QMessageBox::information( NULL, "Warning", "No fibe bundle selected!"); MITK_WARN("QmitkFiberProcessingView") << "no fibe bundle selected"; return; } for (int i=0; i(m_SelectedFB.at(i)->GetData()); mitk::PlanarFigure::Pointer roi = dynamic_cast (m_SelectedPF.at(0)->GetData()); mitk::FiberBundleX::Pointer extFB = fib->ExtractFiberSubset(roi); if (extFB->GetNumFibers()<=0) continue; mitk::DataNode::Pointer node; node = mitk::DataNode::New(); node->SetData(extFB); QString name(m_SelectedFB.at(i)->GetName().c_str()); name += "_"; name += m_SelectedPF.at(0)->GetName().c_str(); node->SetName(name.toStdString()); GetDataStorage()->Add(node); m_SelectedFB.at(i)->SetVisibility(false); } } void QmitkFiberProcessingView::GenerateAndComposite() { mitk::PlanarFigureComposite::Pointer PFCAnd = mitk::PlanarFigureComposite::New(); mitk::PlaneGeometry* currentGeometry2D = dynamic_cast( const_cast(GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer()->GetCurrentWorldGeometry2D())); PFCAnd->SetGeometry2D(currentGeometry2D); PFCAnd->setOperationType(mitk::PFCOMPOSITION_AND_OPERATION); for( std::vector::iterator it = m_SelectedPF.begin(); it != m_SelectedPF.end(); ++it ) { mitk::DataNode::Pointer nodePF = *it; mitk::PlanarFigure::Pointer tmpPF = dynamic_cast( nodePF->GetData() ); PFCAnd->addPlanarFigure( tmpPF ); PFCAnd->addDataNode( nodePF ); PFCAnd->setDisplayName("AND_COMPO"); } AddCompositeToDatastorage(PFCAnd, NULL); } void QmitkFiberProcessingView::GenerateOrComposite() { mitk::PlanarFigureComposite::Pointer PFCOr = mitk::PlanarFigureComposite::New(); mitk::PlaneGeometry* currentGeometry2D = dynamic_cast( const_cast(GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer()->GetCurrentWorldGeometry2D())); PFCOr->SetGeometry2D(currentGeometry2D); PFCOr->setOperationType(mitk::PFCOMPOSITION_OR_OPERATION); for( std::vector::iterator it = m_SelectedPF.begin(); it != m_SelectedPF.end(); ++it ) { mitk::DataNode::Pointer nodePF = *it; mitk::PlanarFigure::Pointer tmpPF = dynamic_cast( nodePF->GetData() ); PFCOr->addPlanarFigure( tmpPF ); PFCOr->addDataNode( nodePF ); PFCOr->setDisplayName("OR_COMPO"); } AddCompositeToDatastorage(PFCOr, NULL); } void QmitkFiberProcessingView::GenerateNotComposite() { mitk::PlanarFigureComposite::Pointer PFCNot = mitk::PlanarFigureComposite::New(); mitk::PlaneGeometry* currentGeometry2D = dynamic_cast( const_cast(GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer()->GetCurrentWorldGeometry2D())); PFCNot->SetGeometry2D(currentGeometry2D); PFCNot->setOperationType(mitk::PFCOMPOSITION_NOT_OPERATION); for( std::vector::iterator it = m_SelectedPF.begin(); it != m_SelectedPF.end(); ++it ) { mitk::DataNode::Pointer nodePF = *it; mitk::PlanarFigure::Pointer tmpPF = dynamic_cast( nodePF->GetData() ); PFCNot->addPlanarFigure( tmpPF ); PFCNot->addDataNode( nodePF ); PFCNot->setDisplayName("NOT_COMPO"); } AddCompositeToDatastorage(PFCNot, NULL); } /* CLEANUP NEEDED */ void QmitkFiberProcessingView::AddCompositeToDatastorage(mitk::PlanarFigureComposite::Pointer pfcomp, mitk::DataNode::Pointer parentDataNode ) { mitk::DataNode::Pointer newPFCNode; newPFCNode = mitk::DataNode::New(); newPFCNode->SetName( pfcomp->getDisplayName() ); newPFCNode->SetData(pfcomp); newPFCNode->SetVisibility(true); switch (pfcomp->getOperationType()) { case 0: { if (!parentDataNode.IsNull()) { GetDataStorage()->Add(newPFCNode, parentDataNode); } else { GetDataStorage()->Add(newPFCNode); } //iterate through its childs for(int i=0; igetNumberOfChildren(); ++i) { mitk::PlanarFigure::Pointer tmpPFchild = pfcomp->getChildAt(i); mitk::DataNode::Pointer savedPFchildNode = pfcomp->getDataNodeAt(i); mitk::PlanarFigureComposite::Pointer pfcompcast= dynamic_cast(tmpPFchild.GetPointer()); if ( !pfcompcast.IsNull() ) { // child is of type planar Figure composite // make new node of the child, cuz later the child has to be removed of its old position in datamanager // feed new dataNode with information of the savedDataNode, which is gonna be removed soon mitk::DataNode::Pointer newChildPFCNode; newChildPFCNode = mitk::DataNode::New(); newChildPFCNode->SetData(tmpPFchild); newChildPFCNode->SetName( savedPFchildNode->GetName() ); pfcompcast->setDisplayName( savedPFchildNode->GetName() ); //name might be changed in DataManager by user //update inside vector the dataNodePointer pfcomp->replaceDataNodeAt(i, newChildPFCNode); AddCompositeToDatastorage(pfcompcast, newPFCNode); //the current PFCNode becomes the childs parent // remove savedNode here, cuz otherwise its children will change their position in the dataNodeManager // without having its parent anymore //GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; }else{ MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName(); } // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " still exists"; } } else { // child is not of type PlanarFigureComposite, so its one of the planarFigures // create new dataNode containing the data of the old dataNode, but position in dataManager will be // modified cuz we re setting a (new) parent. mitk::DataNode::Pointer newPFchildNode = mitk::DataNode::New(); newPFchildNode->SetName(savedPFchildNode->GetName() ); newPFchildNode->SetData(tmpPFchild); newPFchildNode->SetVisibility(true); // replace the dataNode in PFComp DataNodeVector pfcomp->replaceDataNodeAt(i, newPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; } else { MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName(); } // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " still exists"; } MITK_INFO << "adding " << newPFchildNode->GetName() << " to " << newPFCNode->GetName(); //add new child to datamanager with its new position as child of newPFCNode parent GetDataStorage()->Add(newPFchildNode, newPFCNode); } } GetDataStorage()->Modified(); break; } case 1: { if (!parentDataNode.IsNull()) { MITK_INFO << "adding " << newPFCNode->GetName() << " to " << parentDataNode->GetName() ; GetDataStorage()->Add(newPFCNode, parentDataNode); } else { MITK_INFO << "adding " << newPFCNode->GetName(); GetDataStorage()->Add(newPFCNode); } for(int i=0; igetNumberOfChildren(); ++i) { mitk::PlanarFigure::Pointer tmpPFchild = pfcomp->getChildAt(i); mitk::DataNode::Pointer savedPFchildNode = pfcomp->getDataNodeAt(i); mitk::PlanarFigureComposite::Pointer pfcompcast= dynamic_cast(tmpPFchild.GetPointer()); if ( !pfcompcast.IsNull() ) { // child is of type planar Figure composite // make new node of the child, cuz later the child has to be removed of its old position in datamanager // feed new dataNode with information of the savedDataNode, which is gonna be removed soon mitk::DataNode::Pointer newChildPFCNode; newChildPFCNode = mitk::DataNode::New(); newChildPFCNode->SetData(tmpPFchild); newChildPFCNode->SetName( savedPFchildNode->GetName() ); pfcompcast->setDisplayName( savedPFchildNode->GetName() ); //name might be changed in DataManager by user //update inside vector the dataNodePointer pfcomp->replaceDataNodeAt(i, newChildPFCNode); AddCompositeToDatastorage(pfcompcast, newPFCNode); //the current PFCNode becomes the childs parent // remove savedNode here, cuz otherwise its children will change their position in the dataNodeManager // without having its parent anymore //GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; }else{ MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName(); } // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " still exists"; } } else { // child is not of type PlanarFigureComposite, so its one of the planarFigures // create new dataNode containing the data of the old dataNode, but position in dataManager will be // modified cuz we re setting a (new) parent. mitk::DataNode::Pointer newPFchildNode = mitk::DataNode::New(); newPFchildNode->SetName(savedPFchildNode->GetName() ); newPFchildNode->SetData(tmpPFchild); newPFchildNode->SetVisibility(true); // replace the dataNode in PFComp DataNodeVector pfcomp->replaceDataNodeAt(i, newPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; }else{ MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName(); } // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " still exists"; } MITK_INFO << "adding " << newPFchildNode->GetName() << " to " << newPFCNode->GetName(); //add new child to datamanager with its new position as child of newPFCNode parent GetDataStorage()->Add(newPFchildNode, newPFCNode); } } GetDataStorage()->Modified(); break; } case 2: { if (!parentDataNode.IsNull()) { MITK_INFO << "adding " << newPFCNode->GetName() << " to " << parentDataNode->GetName() ; GetDataStorage()->Add(newPFCNode, parentDataNode); } else { MITK_INFO << "adding " << newPFCNode->GetName(); GetDataStorage()->Add(newPFCNode); } //iterate through its childs for(int i=0; igetNumberOfChildren(); ++i) { mitk::PlanarFigure::Pointer tmpPFchild = pfcomp->getChildAt(i); mitk::DataNode::Pointer savedPFchildNode = pfcomp->getDataNodeAt(i); mitk::PlanarFigureComposite::Pointer pfcompcast= dynamic_cast(tmpPFchild.GetPointer()); if ( !pfcompcast.IsNull() ) { // child is of type planar Figure composite // makeRemoveBundle new node of the child, cuz later the child has to be removed of its old position in datamanager // feed new dataNode with information of the savedDataNode, which is gonna be removed soon mitk::DataNode::Pointer newChildPFCNode; newChildPFCNode = mitk::DataNode::New(); newChildPFCNode->SetData(tmpPFchild); newChildPFCNode->SetName( savedPFchildNode->GetName() ); pfcompcast->setDisplayName( savedPFchildNode->GetName() ); //name might be changed in DataManager by user //update inside vector the dataNodePointer pfcomp->replaceDataNodeAt(i, newChildPFCNode); AddCompositeToDatastorage(pfcompcast, newPFCNode); //the current PFCNode becomes the childs parent // remove savedNode here, cuz otherwise its children will change their position in the dataNodeManager // without having its parent anymore //GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; }else{ MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName(); } // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " still exists"; } } else { // child is not of type PlanarFigureComposite, so its one of the planarFigures // create new dataNode containing the data of the old dataNode, but position in dataManager will be // modified cuz we re setting a (new) parent. mitk::DataNode::Pointer newPFchildNode = mitk::DataNode::New(); newPFchildNode->SetName(savedPFchildNode->GetName() ); newPFchildNode->SetData(tmpPFchild); newPFchildNode->SetVisibility(true); // replace the dataNode in PFComp DataNodeVector pfcomp->replaceDataNodeAt(i, newPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; }else{ MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName(); } // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " still exists"; } MITK_INFO << "adding " << newPFchildNode->GetName() << " to " << newPFCNode->GetName(); //add new child to datamanager with its new position as child of newPFCNode parent GetDataStorage()->Add(newPFchildNode, newPFCNode); } } GetDataStorage()->Modified(); break; } default: MITK_INFO << "we have an UNDEFINED composition... ERROR" ; break; } } void QmitkFiberProcessingView::JoinBundles() { if ( m_SelectedFB.size()<2 ){ QMessageBox::information( NULL, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberProcessingView") << "Select at least two fiber bundles!"; return; } std::vector::const_iterator it = m_SelectedFB.begin(); mitk::FiberBundleX::Pointer newBundle = dynamic_cast((*it)->GetData()); QString name(""); name += QString((*it)->GetName().c_str()); ++it; for (it; it!=m_SelectedFB.end(); ++it) { newBundle = newBundle->AddBundle(dynamic_cast((*it)->GetData())); name += "+"+QString((*it)->GetName().c_str()); } mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); } void QmitkFiberProcessingView::SubstractBundles() { if ( m_SelectedFB.size()<2 ){ QMessageBox::information( NULL, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberProcessingView") << "Select at least two fiber bundles!"; return; } std::vector::const_iterator it = m_SelectedFB.begin(); mitk::FiberBundleX::Pointer newBundle = dynamic_cast((*it)->GetData()); QString name(""); name += QString((*it)->GetName().c_str()); ++it; for (it; it!=m_SelectedFB.end(); ++it) { newBundle = newBundle->SubtractBundle(dynamic_cast((*it)->GetData())); + if (newBundle.IsNull()) + break; name += "-"+QString((*it)->GetName().c_str()); } + if (newBundle.IsNull()) + { + QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers. Did you select the fiber bundles in the correct order? X-Y is not equal to Y-X!"); + return; + } mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); } void QmitkFiberProcessingView::GenerateStats() { if ( m_SelectedFB.empty() ) return; QString stats(""); for( int i=0; i(node->GetData())) { if (i>0) stats += "\n-----------------------------\n"; stats += QString(node->GetName().c_str()) + "\n"; mitk::FiberBundleX::Pointer fib = dynamic_cast(node->GetData()); vtkSmartPointer fiberPolyData = fib->GetFiberPolyData(); vtkSmartPointer vLines = fiberPolyData->GetLines(); vLines->InitTraversal(); int numberOfLines = vLines->GetNumberOfCells(); stats += "Number of fibers: "+ QString::number(numberOfLines) + "\n"; float length = 0; std::vector lengths; for (int i=0; iGetNextCell ( numPoints, points ); float l=0; for (unsigned int j=0; j p1; itk::Point p2; fiberPolyData->GetPoint(points[j], p1.GetDataPointer()); fiberPolyData->GetPoint(points[j+1], p2.GetDataPointer()); float dist = p1.EuclideanDistanceTo(p2); length += dist; l += dist; } itk::Point p2; fiberPolyData->GetPoint(points[numPoints-1], p2.GetDataPointer()); lengths.push_back(l); } std::sort(lengths.begin(), lengths.end()); if (numberOfLines>0) length /= numberOfLines; float dev=0; int count = 0; vLines->InitTraversal(); for (int i=0; iGetNextCell ( numPoints, points ); float l=0; for (unsigned int j=0; j p1; itk::Point p2; fiberPolyData->GetPoint(points[j], p1.GetDataPointer()); fiberPolyData->GetPoint(points[j+1], p2.GetDataPointer()); float dist = p1.EuclideanDistanceTo(p2); l += dist; } dev += (length-l)*(length-l); count++; } if (numberOfLines>1) dev /= (numberOfLines-1); else dev = 0; stats += "Min. length: "+ QString::number(lengths.front(),'f',1) + " mm\n"; stats += "Max. length: "+ QString::number(lengths.back(),'f',1) + " mm\n"; stats += "Mean length: "+ QString::number(length,'f',1) + " mm\n"; stats += "Median length: "+ QString::number(lengths.at(lengths.size()/2),'f',1) + " mm\n"; stats += "Standard deviation: "+ QString::number(sqrt(dev),'f',1) + " mm\n"; } } this->m_Controls->m_StatsTextEdit->setText(stats); } void QmitkFiberProcessingView::ProcessSelectedBundles() { if ( m_SelectedFB.empty() ){ QMessageBox::information( NULL, "Warning", "No fibe bundle selected!"); MITK_WARN("QmitkFiberProcessingView") << "no fibe bundle selected"; return; } int generationMethod = m_Controls->m_GenerationBox->currentIndex(); for( int i=0; i(node->GetData())) { mitk::FiberBundleX::Pointer fib = dynamic_cast(node->GetData()); QString name(node->GetName().c_str()); DataNode::Pointer newNode = NULL; switch(generationMethod){ case 0: newNode = GenerateTractDensityImage(fib, false); name += "_TDI"; break; case 1: newNode = GenerateTractDensityImage(fib, true); name += "_envelope"; break; case 2: newNode = GenerateColorHeatmap(fib); break; case 3: newNode = GenerateFiberEndingsImage(fib); name += "_fiber_endings"; break; case 4: newNode = GenerateFiberEndingsPointSet(fib); name += "_fiber_endings"; break; } if (newNode.IsNotNull()) { newNode->SetName(name.toStdString()); GetDataStorage()->Add(newNode); } } } } // generate pointset displaying the fiber endings mitk::DataNode::Pointer QmitkFiberProcessingView::GenerateFiberEndingsPointSet(mitk::FiberBundleX::Pointer fib) { mitk::PointSet::Pointer pointSet = mitk::PointSet::New(); vtkSmartPointer fiberPolyData = fib->GetFiberPolyData(); vtkSmartPointer vLines = fiberPolyData->GetLines(); vLines->InitTraversal(); int count = 0; int numFibers = fib->GetNumFibers(); for( int i=0; iGetNextCell ( numPoints, points ); if (numPoints>0) { double* point = fiberPolyData->GetPoint(points[0]); itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; pointSet->InsertPoint(count, itkPoint); count++; } if (numPoints>2) { double* point = fiberPolyData->GetPoint(points[numPoints-1]); itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; pointSet->InsertPoint(count, itkPoint); count++; } } mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( pointSet ); return node; } // generate image displaying the fiber endings mitk::DataNode::Pointer QmitkFiberProcessingView::GenerateFiberEndingsImage(mitk::FiberBundleX::Pointer fib) { typedef unsigned char OutPixType; typedef itk::Image OutImageType; typedef itk::TractsToFiberEndingsImageFilter< OutImageType > ImageGeneratorType; ImageGeneratorType::Pointer generator = ImageGeneratorType::New(); generator->SetFiberBundle(fib); generator->SetInvertImage(m_Controls->m_InvertCheckbox->isChecked()); generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value()); if (m_SelectedImage.IsNotNull()) { OutImageType::Pointer itkImage = OutImageType::New(); CastToItkImage(m_SelectedImage, itkImage); generator->SetInputImage(itkImage); generator->SetUseImageGeometry(true); } generator->Update(); // get output image OutImageType::Pointer outImg = generator->GetOutput(); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk(outImg.GetPointer()); img->SetVolume(outImg->GetBufferPointer()); // init data node mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(img); return node; } // generate rgba heatmap from fiber bundle mitk::DataNode::Pointer QmitkFiberProcessingView::GenerateColorHeatmap(mitk::FiberBundleX::Pointer fib) { typedef itk::RGBAPixel OutPixType; typedef itk::Image OutImageType; typedef itk::TractsToRgbaImageFilter< OutImageType > ImageGeneratorType; ImageGeneratorType::Pointer generator = ImageGeneratorType::New(); generator->SetFiberBundle(fib); generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value()); if (m_SelectedImage.IsNotNull()) { itk::Image::Pointer itkImage = itk::Image::New(); CastToItkImage(m_SelectedImage, itkImage); generator->SetInputImage(itkImage); generator->SetUseImageGeometry(true); } generator->Update(); // get output image typedef itk::Image OutType; OutType::Pointer outImg = generator->GetOutput(); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk(outImg.GetPointer()); img->SetVolume(outImg->GetBufferPointer()); // init data node mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(img); return node; } // generate tract density image from fiber bundle mitk::DataNode::Pointer QmitkFiberProcessingView::GenerateTractDensityImage(mitk::FiberBundleX::Pointer fib, bool binary) { typedef float OutPixType; typedef itk::Image OutImageType; itk::TractDensityImageFilter< OutImageType >::Pointer generator = itk::TractDensityImageFilter< OutImageType >::New(); generator->SetFiberBundle(fib); generator->SetBinaryOutput(binary); generator->SetInvertImage(m_Controls->m_InvertCheckbox->isChecked()); generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value()); if (m_SelectedImage.IsNotNull()) { OutImageType::Pointer itkImage = OutImageType::New(); CastToItkImage(m_SelectedImage, itkImage); generator->SetInputImage(itkImage); generator->SetUseImageGeometry(true); } generator->Update(); // get output image typedef itk::Image OutType; OutType::Pointer outImg = generator->GetOutput(); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk(outImg.GetPointer()); img->SetVolume(outImg->GetBufferPointer()); // init data node mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(img); return node; } void QmitkFiberProcessingView::ResampleSelectedBundles() { int factor = this->m_Controls->m_ResampleFibersSpinBox->value(); for (int i=0; i(m_SelectedFB.at(i)->GetData()); fib->DoFiberSmoothing(factor); } } +void QmitkFiberProcessingView::DoFaColorCoding() +{ + if (m_SelectedImage.IsNull()) + return; +// mitk::PixelType pType = mitk::MakeScalarPixelType(); +// if (m_SelectedImage->GetPixelType()!=pType) +// { +// //mitk::Image bla; bla.GetPixelType().GetNameOfClass() +// MITK_INFO << m_SelectedImage->GetPixelType().GetNameOfClass(); +// QMessageBox::warning(NULL, "Wrong Image Type", "FA/GFA image should be of type float"); +//// return; +// } + + for( int i=0; i(m_SelectedFB.at(i)->GetData()); + fib->SetFAMap(m_SelectedImage); + fib->SetColorCoding(mitk::FiberBundleX::COLORCODING_FA_BASED); + fib->DoColorCodingFaBased(); + } + + if(m_MultiWidget) + m_MultiWidget->RequestUpdate(); +} + diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.h index e36abfddd1..0216663e73 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.h @@ -1,198 +1,198 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $ Version: $Revision: 21975 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef QmitkFiberProcessingView_h #define QmitkFiberProcessingView_h #include #include "ui_QmitkFiberProcessingViewControls.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*! \brief QmitkFiberProcessingView \warning View to process fiber bundles. Supplies methods to extract fibers from the bundle, join and subtract bundles, generate images from the selected bundle and much more. \sa QmitkFunctionality \ingroup Functionalities */ class QmitkFiberProcessingView : public QmitkFunctionality { // 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< unsigned char, 3 > UCharImageType; - typedef itk::Image< float, 3 > FloatImageType; + typedef itk::Image< unsigned char, 3 > itkUCharImageType; + typedef itk::Image< float, 3 > itkFloatImageType; static const std::string VIEW_ID; QmitkFiberProcessingView(); virtual ~QmitkFiberProcessingView(); virtual void CreateQtPartControl(QWidget *parent); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); virtual void Activated(); protected slots: void OnDrawCircle(); void OnDrawPolygon(); void DoFiberExtraction(); void GenerateAndComposite(); void GenerateOrComposite(); void GenerateNotComposite(); void JoinBundles(); void SubstractBundles(); void GenerateRoiImage(); void ProcessSelectedBundles(); void ResampleSelectedBundles(); - + void DoFaColorCoding(); void Extract3d(); virtual void AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, const char *propertyKey = NULL, mitk::BaseProperty *property = NULL ); protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); Ui::QmitkFiberProcessingViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; /** Connection from VTK to ITK */ template void ConnectPipelines(VTK_Exporter* exporter, ITK_Importer importer) { importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback()); importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback()); importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback()); importer->SetSpacingCallback(exporter->GetSpacingCallback()); importer->SetOriginCallback(exporter->GetOriginCallback()); importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback()); importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback()); importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback()); importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback()); importer->SetDataExtentCallback(exporter->GetDataExtentCallback()); importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback()); importer->SetCallbackUserData(exporter->GetCallbackUserData()); } template void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer) { importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback()); importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback()); importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback()); importer->SetSpacingCallback(exporter->GetSpacingCallback()); importer->SetOriginCallback(exporter->GetOriginCallback()); importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback()); importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback()); importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback()); importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback()); importer->SetDataExtentCallback(exporter->GetDataExtentCallback()); importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback()); importer->SetCallbackUserData(exporter->GetCallbackUserData()); } template < typename TPixel, unsigned int VImageDimension > void InternalCalculateMaskFromPlanarFigure( itk::Image< TPixel, VImageDimension > *image, unsigned int axis, std::string nodeName ); template < typename TPixel, unsigned int VImageDimension > void InternalReorientImagePlane( const itk::Image< TPixel, VImageDimension > *image, mitk::Geometry3D* planegeo3D, int additionalIndex ); void GenerateStats(); void UpdateGui(); berry::ISelectionListener::Pointer m_SelListener; berry::IStructuredSelection::ConstPointer m_CurrentSelection; private: int m_EllipseCounter; int m_PolygonCounter; //contains the selected FiberBundles std::vector m_SelectedFB; //contains the selected PlanarFigures std::vector m_SelectedPF; - mitk::Image::ConstPointer m_SelectedImage; + mitk::Image::Pointer m_SelectedImage; mitk::Image::Pointer m_InternalImage; mitk::PlanarFigure::Pointer m_PlanarFigure; float m_UpsamplingFactor; - UCharImageType::Pointer m_InternalImageMask3D; - UCharImageType::Pointer m_PlanarFigureImage; + itkUCharImageType::Pointer m_InternalImageMask3D; + itkUCharImageType::Pointer m_PlanarFigureImage; std::vector m_Surfaces; void AddCompositeToDatastorage(mitk::PlanarFigureComposite::Pointer, mitk::DataNode::Pointer); void debugPFComposition(mitk::PlanarFigureComposite::Pointer , int ); void CompositeExtraction(mitk::DataNode::Pointer node, mitk::Image* image); mitk::DataNode::Pointer GenerateTractDensityImage(mitk::FiberBundleX::Pointer fib, bool binary); mitk::DataNode::Pointer GenerateColorHeatmap(mitk::FiberBundleX::Pointer fib); mitk::DataNode::Pointer GenerateFiberEndingsImage(mitk::FiberBundleX::Pointer fib); mitk::DataNode::Pointer GenerateFiberEndingsPointSet(mitk::FiberBundleX::Pointer fib); }; #endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingViewControls.ui index 40c46f33cc..c1cf883f2d 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingViewControls.ui @@ -1,650 +1,683 @@ QmitkFiberProcessingViewControls 0 0 665 587 Form + + 0 + - 5 + 9 - 0 + 3 - 5 + 9 - 0 + 3 Fiber Bundle Modification 0 0 200 0 16777215 60 QFrame::NoFrame QFrame::Raised 0 30 30 - Draw circular ROI + Draw circular ROI. Select reference fiber bundle to execute. :/QmitkDiffusionImaging/circle.png:/QmitkDiffusionImaging/circle.png 32 32 false true 30 30 - Draw rectangular ROI + Draw rectangular ROI. Select reference fiber bundle to execute. :/QmitkDiffusionImaging/rectangle.png:/QmitkDiffusionImaging/rectangle.png 32 32 true true 30 30 - Draw polygonal ROI + Draw polygonal ROI. Select reference fiber bundle to execute. :/QmitkDiffusionImaging/polygon.png:/QmitkDiffusionImaging/polygon.png 32 32 true true Qt::Horizontal 40 20 QFrame::NoFrame QFrame::Raised 0 false 0 0 200 16777215 11 - Extract fibers passing through selected ROI or composite ROI + Extract fibers passing through selected ROI or composite ROI. Select ROI and fiber bundle to execute. Extract false 0 0 200 16777215 11 - Returns fiber bundle containing all fibers the two selected bundles dont't have in common + Returns all fibers contained in bundle X that are not contained in bundle Y (not commutative!). Select at least two fiber bundles to execute. Substract - - + + false 0 0 - 16777215 + 200 16777215 11 - Generate a binary image containing all selected ROIs + Merge selected fiber bundles. Select at least two fiber bundles to execute. - ROI Image + Join - - + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + false 0 0 200 16777215 11 - Merge selected fiber bundles + Extract fibers passing through selected surface mesh. Select surface mesh and fiber bundle to execute. - Join + Extract 3D - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + false 0 0 - 200 + 16777215 16777215 11 - Extract fibers passing through selected surface mesh + Generate a binary image containing all selected ROIs. Select at least one ROI (planar figure) and a reference fiber bundle or image. - Extract 3D + ROI Image 0 0 200 0 16777215 60 QFrame::NoFrame QFrame::Raised 0 Qt::Horizontal 40 20 false 60 16777215 - Create AND composition with selected ROIs + Create AND composition with selected ROIs. AND false 60 16777215 - Create OR composition with selected ROIs + Create OR composition with selected ROIs. OR false 60 16777215 - Create NOT composition from selected ROI + Create NOT composition from selected ROI. NOT Fiber Bundle Processing 0 0 Tract Density Image (TDI) Binary Envelope Fiber Bundle Image Fiber Endings Image Fiber Endings Pointset - Upsampling Factor + Upsampling factor 1 10 2 false 0 0 200 16777215 11 - Perform selected operation on fiber bundle + Perform selected operation on all selected fiber bundles. Generate - If selected operation generates an image, the inverse image is returned + If selected operation generates an image, the inverse image is returned. Invert false 0 0 200 16777215 11 - Resample fibers using a Kochanek spline interpolation + Resample fibers using a Kochanek spline interpolation. Smooth Fibers Points per cm 1 50 10 + + + + false + + + + 0 + 0 + + + + + 200 + 16777215 + + + + + 11 + + + + Resample fibers using a Kochanek spline interpolation. + + + FA Color Coding + + + Fiber Bundle Statistics Courier 10 Pitch false true Qt::Vertical 20 40 diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.cpp index 9b84a43183..269b2de3aa 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.cpp @@ -1,767 +1,765 @@ /*========================================================================= Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkGibbsTrackingView.h" #include // Qt #include #include #include // MITK #include #include #include #include #include // ITK #include #include #include // MISC #include QmitkTrackingWorker::QmitkTrackingWorker(QmitkGibbsTrackingView* view) : m_View(view) { } void QmitkTrackingWorker::run() { m_View->m_GlobalTracker = QmitkGibbsTrackingView::GibbsTrackingFilterType::New(); MITK_INFO << "Resampling mask images"; // setup resampler typedef itk::ResampleImageFilter ResamplerType; ResamplerType::Pointer resampler = ResamplerType::New(); resampler->SetOutputSpacing( m_View->m_ItkQBallImage->GetSpacing() ); resampler->SetOutputOrigin( m_View->m_ItkQBallImage->GetOrigin() ); resampler->SetOutputDirection( m_View->m_ItkQBallImage->GetDirection() ); resampler->SetSize( m_View->m_ItkQBallImage->GetLargestPossibleRegion().GetSize() ); // resample mask image resampler->SetInput( m_View->m_MaskImage ); resampler->SetDefaultPixelValue(0); resampler->Update(); m_View->m_MaskImage = resampler->GetOutput(); m_View->m_GlobalTracker->SetInput0(m_View->m_ItkQBallImage.GetPointer()); m_View->m_GlobalTracker->SetMaskImage(m_View->m_MaskImage); m_View->m_GlobalTracker->SetTempStart((float)m_View->m_Controls->m_StartTempSlider->value()/100); m_View->m_GlobalTracker->SetTempEnd((float)m_View->m_Controls->m_EndTempSlider->value()/10000); m_View->m_GlobalTracker->SetNumIt(m_View->m_Iterations); m_View->m_GlobalTracker->SetParticleWeight((float)m_View->m_Controls->m_ParticleWeightSlider->value()/10000); m_View->m_GlobalTracker->SetSubtractMean(m_View->m_Controls->m_MeanSubtractionCheckbox->isChecked()); m_View->m_GlobalTracker->SetParticleWidth((float)(m_View->m_Controls->m_ParticleWidthSlider->value())/10); m_View->m_GlobalTracker->SetParticleLength((float)(m_View->m_Controls->m_ParticleLengthSlider->value())/10); m_View->m_GlobalTracker->SetInexBalance((float)m_View->m_Controls->m_InExBalanceSlider->value()/10); m_View->m_GlobalTracker->SetFiberLength(m_View->m_Controls->m_FiberLengthSlider->value()); m_View->m_GlobalTracker->SetCurvatureHardThreshold(cos((float)m_View->m_Controls->m_CurvatureThresholdSlider->value()*3.14159265/180)); m_View->m_GlobalTracker->Update(); m_View->m_TrackingThread.quit(); } const std::string QmitkGibbsTrackingView::VIEW_ID = "org.mitk.views.gibbstracking"; QmitkGibbsTrackingView::QmitkGibbsTrackingView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) , m_ThreadIsRunning(false) , m_GlobalTracker(NULL) , m_QBallImage(NULL) , m_MaskImage(NULL) , m_QBallImageNode(NULL) , m_ItkQBallImage(NULL) , m_FiberBundleNode(NULL) + , m_MaskImageNode(NULL) , m_TrackingWorker(this) - , m_QBallSelected(false) , m_Iterations(10000000) , m_LastStep(0) - , m_SaveCounter(0) { m_TrackingWorker.moveToThread(&m_TrackingThread); connect(&m_TrackingThread, SIGNAL(started()), this, SLOT(BeforeThread())); connect(&m_TrackingThread, SIGNAL(started()), &m_TrackingWorker, SLOT(run())); connect(&m_TrackingThread, SIGNAL(finished()), this, SLOT(AfterThread())); connect(&m_TrackingThread, SIGNAL(terminated()), this, SLOT(AfterThread())); m_TrackingTimer = new QTimer(this); } QmitkGibbsTrackingView::~QmitkGibbsTrackingView() { delete m_TrackingTimer; } // update tracking status and generate fiber bundle void QmitkGibbsTrackingView::TimerUpdate() { int currentStep = m_GlobalTracker->GetCurrentStep(); mitk::ProgressBar::GetInstance()->Progress(currentStep-m_LastStep); UpdateTrackingStatus(); GenerateFiberBundle(false); m_LastStep = currentStep; } // tell global tractography filter to stop after current step void QmitkGibbsTrackingView::StopGibbsTracking() { if (m_GlobalTracker.IsNull()) return; //mitk::ProgressBar::GetInstance()->Progress(m_GlobalTracker->GetSteps()-m_LastStep+1); m_GlobalTracker->SetAbortTracking(true); m_Controls->m_TrackingStop->setEnabled(false); m_Controls->m_TrackingStop->setText("Stopping Tractography ..."); } // update gui elements and generate fiber bundle after tracking is finished void QmitkGibbsTrackingView::AfterThread() { m_ThreadIsRunning = false; m_TrackingTimer->stop(); mitk::ProgressBar::GetInstance()->Progress(m_GlobalTracker->GetSteps()-m_LastStep+1); UpdateGUI(); UpdateTrackingStatus(); - GenerateFiberBundle(true); - QString paramMessage; + if(m_Controls->m_ParticleWeightSlider->value()==0) { m_Controls->m_ParticleWeightLabel->setText(QString::number(m_GlobalTracker->GetParticleWeight())); m_Controls->m_ParticleWeightSlider->setValue(m_GlobalTracker->GetParticleWeight()*10000); - paramMessage += "Particle weight was set to " + QString::number(m_GlobalTracker->GetParticleWeight()) + "\n"; } if(m_Controls->m_ParticleWidthSlider->value()==0) { m_Controls->m_ParticleWidthLabel->setText(QString::number(m_GlobalTracker->GetParticleWidth())); m_Controls->m_ParticleWidthSlider->setValue(m_GlobalTracker->GetParticleWidth()*10); - paramMessage += "Particle width was set to " + QString::number(m_GlobalTracker->GetParticleWidth()) + " mm\n"; } if(m_Controls->m_ParticleLengthSlider->value()==0) { m_Controls->m_ParticleLengthLabel->setText(QString::number(m_GlobalTracker->GetParticleLength())); m_Controls->m_ParticleLengthSlider->setValue(m_GlobalTracker->GetParticleLength()*10); - paramMessage += "Particle length was set to " + QString::number(m_GlobalTracker->GetParticleLength()) + " mm\n"; } + GenerateFiberBundle(true); m_FiberBundleNode = NULL; - - if (paramMessage.length()>0) - QMessageBox::information(NULL, "Automatically selected parameters", paramMessage); } // start tracking timer and update gui elements before tracking is started void QmitkGibbsTrackingView::BeforeThread() { m_ThreadIsRunning = true; m_TrackingTime = QTime::currentTime(); m_ElapsedTime = 0; m_TrackingTimer->start(1000); m_LastStep = 0; UpdateGUI(); } // setup gui elements and signal/slot connections void QmitkGibbsTrackingView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkGibbsTrackingViewControls; m_Controls->setupUi( parent ); AdvancedSettings(); connect( m_TrackingTimer, SIGNAL(timeout()), this, SLOT(TimerUpdate()) ); connect( m_Controls->m_TrackingStop, SIGNAL(clicked()), this, SLOT(StopGibbsTracking()) ); connect( m_Controls->m_TrackingStart, SIGNAL(clicked()), this, SLOT(StartGibbsTracking()) ); - connect( m_Controls->m_SetMaskButton, SIGNAL(clicked()), this, SLOT(SetMask()) ); connect( m_Controls->m_AdvancedSettingsCheckbox, SIGNAL(clicked()), this, SLOT(AdvancedSettings()) ); connect( m_Controls->m_SaveTrackingParameters, SIGNAL(clicked()), this, SLOT(SaveTrackingParameters()) ); connect( m_Controls->m_LoadTrackingParameters, SIGNAL(clicked()), this, SLOT(LoadTrackingParameters()) ); connect( m_Controls->m_IterationsSlider, SIGNAL(valueChanged(int)), this, SLOT(SetIterations(int)) ); connect( m_Controls->m_ParticleWidthSlider, SIGNAL(valueChanged(int)), this, SLOT(SetParticleWidth(int)) ); connect( m_Controls->m_ParticleLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(SetParticleLength(int)) ); connect( m_Controls->m_InExBalanceSlider, SIGNAL(valueChanged(int)), this, SLOT(SetInExBalance(int)) ); connect( m_Controls->m_FiberLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(SetFiberLength(int)) ); connect( m_Controls->m_ParticleWeightSlider, SIGNAL(valueChanged(int)), this, SLOT(SetParticleWeight(int)) ); connect( m_Controls->m_StartTempSlider, SIGNAL(valueChanged(int)), this, SLOT(SetStartTemp(int)) ); connect( m_Controls->m_EndTempSlider, SIGNAL(valueChanged(int)), this, SLOT(SetEndTemp(int)) ); connect( m_Controls->m_CurvatureThresholdSlider, SIGNAL(valueChanged(int)), this, SLOT(SetCurvatureThreshold(int)) ); connect( m_Controls->m_OutputFileButton, SIGNAL(clicked()), this, SLOT(SetOutputFile()) ); } } void QmitkGibbsTrackingView::SetInExBalance(int value) { m_Controls->m_InExBalanceLabel->setText(QString::number((float)value/10)); } void QmitkGibbsTrackingView::SetFiberLength(int value) { m_Controls->m_FiberLengthLabel->setText(QString::number(value)+"mm"); } void QmitkGibbsTrackingView::SetParticleWeight(int value) { if (value>0) m_Controls->m_ParticleWeightLabel->setText(QString::number((float)value/10000)); else m_Controls->m_ParticleWeightLabel->setText("auto"); } void QmitkGibbsTrackingView::SetStartTemp(int value) { m_Controls->m_StartTempLabel->setText(QString::number((float)value/100)); } void QmitkGibbsTrackingView::SetEndTemp(int value) { m_Controls->m_EndTempLabel->setText(QString::number((float)value/10000)); } void QmitkGibbsTrackingView::SetParticleWidth(int value) { if (value>0) m_Controls->m_ParticleWidthLabel->setText(QString::number((float)value/10)+" mm"); else m_Controls->m_ParticleWidthLabel->setText("auto"); } void QmitkGibbsTrackingView::SetParticleLength(int value) { if (value>0) m_Controls->m_ParticleLengthLabel->setText(QString::number((float)value/10)+" mm"); else m_Controls->m_ParticleLengthLabel->setText("auto"); } void QmitkGibbsTrackingView::SetCurvatureThreshold(int value) { m_Controls->m_CurvatureThresholdLabel->setText(QString::number(value)+"°"); } void QmitkGibbsTrackingView::SetIterations(int value) { switch(value) { case 0: m_Controls->m_IterationsLabel->setText("Iterations: 1x10^4"); m_Iterations = 10000; break; case 1: m_Controls->m_IterationsLabel->setText("Iterations: 5x10^4"); m_Iterations = 50000; break; case 2: m_Controls->m_IterationsLabel->setText("Iterations: 1x10^5"); m_Iterations = 100000; break; case 3: m_Controls->m_IterationsLabel->setText("Iterations: 5x10^5"); m_Iterations = 500000; break; case 4: m_Controls->m_IterationsLabel->setText("Iterations: 1x10^6"); m_Iterations = 1000000; break; case 5: m_Controls->m_IterationsLabel->setText("Iterations: 5x10^6"); m_Iterations = 5000000; break; case 6: m_Controls->m_IterationsLabel->setText("Iterations: 1x10^7"); m_Iterations = 10000000; break; case 7: m_Controls->m_IterationsLabel->setText("Iterations: 5x10^7"); m_Iterations = 50000000; break; case 8: m_Controls->m_IterationsLabel->setText("Iterations: 1x10^8"); m_Iterations = 100000000; break; case 9: m_Controls->m_IterationsLabel->setText("Iterations: 5x10^8"); m_Iterations = 500000000; break; case 10: m_Controls->m_IterationsLabel->setText("Iterations: 1x10^9"); m_Iterations = 1000000000; break; } } void QmitkGibbsTrackingView::StdMultiWidgetAvailable(QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkGibbsTrackingView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } // called if datamanager selection changes void QmitkGibbsTrackingView::OnSelectionChanged( std::vector nodes ) { - m_QBallSelected = false; + if (m_ThreadIsRunning) + return; + + m_QBallImageNode = NULL; + m_MaskImageNode = NULL; // iterate all selected objects for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if( node.IsNotNull() && dynamic_cast(node->GetData()) ) - { - m_QBallSelected = true; m_QBallImageNode = node; + else if( node.IsNotNull() && dynamic_cast(node->GetData()) ) + { + bool isBinary = false; + node->GetPropertyValue("binary", isBinary); + if (isBinary) + m_MaskImageNode = node; } } UpdateGUI(); } // update gui elements displaying trackings status void QmitkGibbsTrackingView::UpdateTrackingStatus() { if (m_GlobalTracker.IsNull()) return; m_ElapsedTime += m_TrackingTime.elapsed()/1000; m_TrackingTime.restart(); unsigned long hours = m_ElapsedTime/3600; unsigned long minutes = (m_ElapsedTime%3600)/60; unsigned long seconds = m_ElapsedTime%60; m_Controls->m_ProposalAcceptance->setText(QString::number(m_GlobalTracker->GetProposalAcceptance()*100)+"%"); m_Controls->m_TrackingTimeLabel->setText( QString::number(hours)+QString("h ")+QString::number(minutes)+QString("m ")+QString::number(seconds)+QString("s") ); m_Controls->m_NumConnectionsLabel->setText( QString::number(m_GlobalTracker->GetNumConnections()) ); m_Controls->m_NumParticlesLabel->setText( QString::number(m_GlobalTracker->GetNumParticles()) ); m_Controls->m_CurrentStepLabel->setText( QString::number(100*(float)m_GlobalTracker->GetCurrentStep()/m_GlobalTracker->GetSteps())+"%" ); m_Controls->m_AcceptedFibersLabel->setText( QString::number(m_GlobalTracker->GetNumAcceptedFibers()) ); } // update gui elements (enable/disable elements and set tooltips) void QmitkGibbsTrackingView::UpdateGUI() { - if (!m_ThreadIsRunning && m_QBallSelected) + if (m_QBallImageNode.IsNotNull()) + m_Controls->m_QballImageLabel->setText(m_QBallImageNode->GetName().c_str()); + else + m_Controls->m_QballImageLabel->setText("-"); + if (m_MaskImageNode.IsNotNull()) + m_Controls->m_MaskImageLabel->setText(m_MaskImageNode->GetName().c_str()); + else + m_Controls->m_MaskImageLabel->setText("-"); + + if (!m_ThreadIsRunning && m_QBallImageNode.IsNotNull()) { m_Controls->m_TrackingStop->setEnabled(false); m_Controls->m_TrackingStart->setEnabled(true); m_Controls->m_LoadTrackingParameters->setEnabled(true); - m_Controls->m_MaskFrame->setEnabled(true); m_Controls->m_IterationsSlider->setEnabled(true); m_Controls->m_AdvancedFrame->setEnabled(true); m_Controls->m_TrackingStop->setText("Stop Tractography"); m_Controls->m_TrackingStart->setToolTip("Start tractography. No further change of parameters possible."); m_Controls->m_TrackingStop->setToolTip(""); } else if (!m_ThreadIsRunning) { m_Controls->m_TrackingStop->setEnabled(false); m_Controls->m_TrackingStart->setEnabled(false); m_Controls->m_LoadTrackingParameters->setEnabled(true); - m_Controls->m_MaskFrame->setEnabled(true); m_Controls->m_IterationsSlider->setEnabled(true); m_Controls->m_AdvancedFrame->setEnabled(true); m_Controls->m_TrackingStop->setText("Stop Tractography"); m_Controls->m_TrackingStart->setToolTip("No Q-Ball image selected."); m_Controls->m_TrackingStop->setToolTip(""); } else { m_Controls->m_TrackingStop->setEnabled(true); m_Controls->m_TrackingStart->setEnabled(false); m_Controls->m_LoadTrackingParameters->setEnabled(false); - m_Controls->m_MaskFrame->setEnabled(false); m_Controls->m_IterationsSlider->setEnabled(false); m_Controls->m_AdvancedFrame->setEnabled(false); m_Controls->m_AdvancedFrame->setVisible(false); m_Controls->m_AdvancedSettingsCheckbox->setChecked(false); m_Controls->m_TrackingStart->setToolTip("Tracking in progress."); m_Controls->m_TrackingStop->setToolTip("Stop tracking and display results."); } } // show/hide advanced settings frame void QmitkGibbsTrackingView::AdvancedSettings() { m_Controls->m_AdvancedFrame->setVisible(m_Controls->m_AdvancedSettingsCheckbox->isChecked()); } // set mask image data node void QmitkGibbsTrackingView::SetMask() { std::vector nodes = GetDataManagerSelection(); if (nodes.empty()) { m_MaskImageNode = NULL; - m_Controls->m_MaskImageEdit->setText("N/A"); + m_Controls->m_MaskImageLabel->setText("-"); return; } for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if (node.IsNotNull() && dynamic_cast(node->GetData())) { m_MaskImageNode = node; - m_Controls->m_MaskImageEdit->setText(node->GetName().c_str()); + m_Controls->m_MaskImageLabel->setText(node->GetName().c_str()); return; } } } // cast image to float template void QmitkGibbsTrackingView::CastToFloat(InputImageType* image, mitk::Image::Pointer outImage) { typedef itk::CastImageFilter ItkCastFilter; typename ItkCastFilter::Pointer itkCaster = ItkCastFilter::New(); itkCaster->SetInput(image); itkCaster->Update(); outImage->InitializeByItk(itkCaster->GetOutput()); outImage->SetVolume(itkCaster->GetOutput()->GetBufferPointer()); } // check for mask and qbi and start tracking thread void QmitkGibbsTrackingView::StartGibbsTracking() { if(m_ThreadIsRunning) { MITK_WARN("QmitkGibbsTrackingView")<<"Thread already running!"; return; } - if (!m_QBallSelected) + if (m_QBallImageNode.IsNull()) { // Nothing selected. Inform the user and return QMessageBox::information( NULL, "Warning", "Please load and select a qball image before starting image processing."); return; } // a node itself is not very useful, we need its data item (the image) mitk::BaseData* data = m_QBallImageNode->GetData(); if (!data) return; // test if this data item is an image or not (could also be a surface or something totally different) m_QBallImage = dynamic_cast( data ); if (m_QBallImage.IsNull()) return; // cast qbi to itk m_ItkQBallImage = ItkQBallImgType::New(); mitk::CastToItkImage(m_QBallImage, m_ItkQBallImage); // mask image found? // catch exceptions thrown by the itkAccess macros try{ - if(m_Controls->m_MaskImageEdit->text().compare("N/A") != 0) + if(m_MaskImageNode.IsNotNull()) { m_MaskImage = 0; if (dynamic_cast(m_MaskImageNode->GetData())) mitk::CastToItkImage(dynamic_cast(m_MaskImageNode->GetData()), m_MaskImage); } } catch(...) { QMessageBox::warning(NULL, "Warning", "Incompatible mask image chosen. Processing without masking."); //reset mask image m_MaskImage = NULL; } // if no mask image is selected generate it if( m_MaskImage.IsNull() ) { m_MaskImage = MaskImgType::New(); m_MaskImage->SetSpacing( m_ItkQBallImage->GetSpacing() ); // Set the image spacing m_MaskImage->SetOrigin( m_ItkQBallImage->GetOrigin() ); // Set the image origin m_MaskImage->SetDirection( m_ItkQBallImage->GetDirection() ); // Set the image direction m_MaskImage->SetLargestPossibleRegion( m_ItkQBallImage->GetLargestPossibleRegion()); m_MaskImage->SetBufferedRegion( m_ItkQBallImage->GetLargestPossibleRegion() ); m_MaskImage->Allocate(); itk::ImageRegionIterator it (m_MaskImage, m_MaskImage->GetLargestPossibleRegion() ); for (it = it.Begin(); !it.IsAtEnd(); ++it) { it.Set(1); } } unsigned int steps = m_Iterations/10000; if (steps<10) steps = 10; m_LastStep = 1; mitk::ProgressBar::GetInstance()->AddStepsToDo(steps); - m_SaveCounter = 0; - // start worker thread m_TrackingThread.start(QThread::LowestPriority); } // generate mitkFiberBundle from tracking filter output void QmitkGibbsTrackingView::GenerateFiberBundle(bool smoothFibers) { if (m_GlobalTracker.IsNull() || (!(m_Controls->m_VisualizationCheckbox->isChecked() || m_Controls->m_VisualizeOnceButton->isChecked()) && m_ThreadIsRunning)) return; if (m_Controls->m_VisualizeOnceButton->isChecked()) m_Controls->m_VisualizeOnceButton->setChecked(false); vtkSmartPointer fiberBundle = m_GlobalTracker->GetFiberBundle(); if ( fiberBundle->GetNumberOfLines()==0 ) return; m_FiberBundle = mitk::FiberBundleX::New(fiberBundle); if (smoothFibers) m_FiberBundle->DoFiberSmoothing(10); if (m_FiberBundleNode.IsNotNull()){ GetDefaultDataStorage()->Remove(m_FiberBundleNode); m_FiberBundleNode = 0; } m_FiberBundleNode = mitk::DataNode::New(); m_FiberBundleNode->SetData(m_FiberBundle); QString name(m_QBallImageNode->GetName().c_str()); name += "_FiberBundle"; m_FiberBundleNode->SetName(name.toStdString()); m_FiberBundleNode->SetVisibility(true); if (!m_OutputFileName.isEmpty()) { QString filename = m_OutputFileName; - if (m_SaveCounter>0 && m_Controls->m_SaveIntermediateCheckbox->isChecked()) - { - filename = QString(itksys::SystemTools::GetFilenamePath(filename.toStdString()).c_str())+"/"+QString(itksys::SystemTools::GetFilenameWithoutExtension(filename.toStdString()).c_str()); - filename += "_"+QString::number(m_SaveCounter)+".fib"; - } mitk::FiberBundleXWriter::Pointer writer = mitk::FiberBundleXWriter::New(); writer->SetFileName(filename.toStdString()); writer->SetInputFiberBundleX(m_FiberBundle.GetPointer()); try { - MITK_INFO << "Saving " << filename.toStdString(); writer->Update(); - m_SaveCounter++; + QMessageBox::information(NULL, "Fiber bundle saved to", filename); } catch (itk::ExceptionObject &ex) { - MITK_ERROR << QString("%1\n%2\n%3\n%4\n%5\n%6").arg(ex.GetNameOfClass()).arg(ex.GetFile()).arg(ex.GetLine()).arg(ex.GetLocation()).arg(ex.what()).arg(ex.GetDescription()).toStdString(); + QMessageBox::information(NULL, "Fiber bundle could not be saved", QString("%1\n%2\n%3\n%4\n%5\n%6").arg(ex.GetNameOfClass()).arg(ex.GetFile()).arg(ex.GetLine()).arg(ex.GetLocation()).arg(ex.what()).arg(ex.GetDescription())); + if(m_QBallImageNode.IsNull()) GetDataStorage()->Add(m_FiberBundleNode); else GetDataStorage()->Add(m_FiberBundleNode, m_QBallImageNode); } } else { if(m_QBallImageNode.IsNull()) GetDataStorage()->Add(m_FiberBundleNode); else GetDataStorage()->Add(m_FiberBundleNode, m_QBallImageNode); } } void QmitkGibbsTrackingView::SetOutputFile() { // SELECT FOLDER DIALOG m_OutputFileName = QFileDialog::getSaveFileName(0, tr("Set file name"), QDir::currentPath()+"/FiberBundle.fib", tr("Fiber Bundle (*.fib)") ); if (m_OutputFileName.isEmpty()) m_Controls->m_OutputFileLabel->setText("N/A"); else m_Controls->m_OutputFileLabel->setText(m_OutputFileName); - m_SaveCounter = 0; } // save current tracking paramters as xml file (.gtp) void QmitkGibbsTrackingView::SaveTrackingParameters() { TiXmlDocument documentXML; TiXmlDeclaration* declXML = new TiXmlDeclaration( "1.0", "", "" ); documentXML.LinkEndChild( declXML ); TiXmlElement* mainXML = new TiXmlElement("global_tracking_parameter_file"); mainXML->SetAttribute("file_version", "0.1"); documentXML.LinkEndChild(mainXML); TiXmlElement* paramXML = new TiXmlElement("parameter_set"); paramXML->SetAttribute("iterations", QString::number(m_Iterations).toStdString()); paramXML->SetAttribute("particle_length", QString::number((float)m_Controls->m_ParticleLengthSlider->value()/10).toStdString()); paramXML->SetAttribute("particle_width", QString::number((float)m_Controls->m_ParticleWidthSlider->value()/10).toStdString()); paramXML->SetAttribute("particle_weight", QString::number((float)m_Controls->m_ParticleWeightSlider->value()/10000).toStdString()); paramXML->SetAttribute("temp_start", QString::number((float)m_Controls->m_StartTempSlider->value()/100).toStdString()); paramXML->SetAttribute("temp_end", QString::number((float)m_Controls->m_EndTempSlider->value()/10000).toStdString()); paramXML->SetAttribute("inexbalance", QString::number((float)m_Controls->m_InExBalanceSlider->value()/10).toStdString()); paramXML->SetAttribute("fiber_length", QString::number(m_Controls->m_FiberLengthSlider->value()).toStdString()); paramXML->SetAttribute("curvature_threshold", QString::number(m_Controls->m_CurvatureThresholdSlider->value()).toStdString()); mainXML->LinkEndChild(paramXML); QString filename = QFileDialog::getSaveFileName( 0, tr("Save Parameters"), QDir::currentPath()+"/param.gtp", tr("Global Tracking Parameters (*.gtp)") ); if(filename.isEmpty() || filename.isNull()) return; if(!filename.endsWith(".gtp")) filename += ".gtp"; documentXML.SaveFile( filename.toStdString() ); } void QmitkGibbsTrackingView::UpdateIteraionsGUI(unsigned long iterations) { switch(iterations) { case 10000: m_Controls->m_IterationsSlider->setValue(0); m_Controls->m_IterationsLabel->setText("Iterations: 10^4"); break; case 50000: m_Controls->m_IterationsSlider->setValue(1); m_Controls->m_IterationsLabel->setText("Iterations: 5x10^4"); break; case 100000: m_Controls->m_IterationsSlider->setValue(2); m_Controls->m_IterationsLabel->setText("Iterations: 10^5"); break; case 500000: m_Controls->m_IterationsSlider->setValue(3); m_Controls->m_IterationsLabel->setText("Iterations: 5x10^5"); break; case 1000000: m_Controls->m_IterationsSlider->setValue(4); m_Controls->m_IterationsLabel->setText("Iterations: 10^6"); break; case 5000000: m_Controls->m_IterationsSlider->setValue(5); m_Controls->m_IterationsLabel->setText("Iterations: 5x10^6"); break; case 10000000: m_Controls->m_IterationsSlider->setValue(6); m_Controls->m_IterationsLabel->setText("Iterations: 10^7"); break; case 50000000: m_Controls->m_IterationsSlider->setValue(7); m_Controls->m_IterationsLabel->setText("Iterations: 5x10^7"); break; case 100000000: m_Controls->m_IterationsSlider->setValue(8); m_Controls->m_IterationsLabel->setText("Iterations: 10^8"); break; case 500000000: m_Controls->m_IterationsSlider->setValue(9); m_Controls->m_IterationsLabel->setText("Iterations: 5x10^8"); break; case 1000000000: m_Controls->m_IterationsSlider->setValue(10); m_Controls->m_IterationsLabel->setText("Iterations: 10^9"); break; case 5000000000: m_Controls->m_IterationsSlider->setValue(11); m_Controls->m_IterationsLabel->setText("Iterations: 5x10^9"); break; } } // load current tracking paramters from xml file (.gtp) void QmitkGibbsTrackingView::LoadTrackingParameters() { QString filename = QFileDialog::getOpenFileName(0, tr("Load Parameters"), QDir::currentPath(), tr("Global Tracking Parameters (*.gtp)") ); if(filename.isEmpty() || filename.isNull()) return; TiXmlDocument doc( filename.toStdString() ); doc.LoadFile(); TiXmlHandle hDoc(&doc); TiXmlElement* pElem; TiXmlHandle hRoot(0); pElem = hDoc.FirstChildElement().Element(); hRoot = TiXmlHandle(pElem); pElem = hRoot.FirstChildElement("parameter_set").Element(); QString iterations(pElem->Attribute("iterations")); m_Iterations = iterations.toULong(); UpdateIteraionsGUI(m_Iterations); QString particleLength(pElem->Attribute("particle_length")); float pLength = particleLength.toFloat(); QString particleWidth(pElem->Attribute("particle_width")); float pWidth = particleWidth.toFloat(); if (pLength==0) m_Controls->m_ParticleLengthLabel->setText("auto"); else m_Controls->m_ParticleLengthLabel->setText(particleLength+" mm"); if (pWidth==0) m_Controls->m_ParticleWidthLabel->setText("auto"); else m_Controls->m_ParticleWidthLabel->setText(particleWidth+" mm"); m_Controls->m_ParticleWidthSlider->setValue(pWidth*10); m_Controls->m_ParticleLengthSlider->setValue(pLength*10); QString partWeight(pElem->Attribute("particle_weight")); m_Controls->m_ParticleWeightSlider->setValue(partWeight.toFloat()*10000); m_Controls->m_ParticleWeightLabel->setText(partWeight); QString startTemp(pElem->Attribute("temp_start")); m_Controls->m_StartTempSlider->setValue(startTemp.toFloat()*100); m_Controls->m_StartTempLabel->setText(startTemp); QString endTemp(pElem->Attribute("temp_end")); m_Controls->m_EndTempSlider->setValue(endTemp.toFloat()*10000); m_Controls->m_EndTempLabel->setText(endTemp); QString inExBalance(pElem->Attribute("inexbalance")); m_Controls->m_InExBalanceSlider->setValue(inExBalance.toFloat()*10); m_Controls->m_InExBalanceLabel->setText(inExBalance); QString fiberLength(pElem->Attribute("fiber_length")); m_Controls->m_FiberLengthSlider->setValue(fiberLength.toInt()); m_Controls->m_FiberLengthLabel->setText(fiberLength+"mm"); QString curvThres(pElem->Attribute("curvature_threshold")); m_Controls->m_CurvatureThresholdSlider->setValue(curvThres.toInt()); m_Controls->m_CurvatureThresholdLabel->setText(curvThres+"°"); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.h index 6d85a900da..0285ee11ec 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.h @@ -1,168 +1,165 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $ Version: $Revision: 21975 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef QmitkGibbsTrackingView_h #define QmitkGibbsTrackingView_h #include #include #include "ui_QmitkGibbsTrackingViewControls.h" #include #include #include #include #include #include #include class QmitkGibbsTrackingView; class QmitkTrackingWorker : public QObject { Q_OBJECT public: QmitkTrackingWorker(QmitkGibbsTrackingView* view); public slots: void run(); private: QmitkGibbsTrackingView* m_View; }; /*! \brief QmitkGibbsTrackingView \warning This application module is not yet documented. Use "svn blame/praise/annotate" and ask the author to provide basic documentation. \sa QmitkFunctionality \ingroup Functionalities */ typedef itk::Image< float, 3 > FloatImageType; namespace itk { template class GibbsTrackingFilter; } class QmitkGibbsTrackingView : public QmitkFunctionality { // 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 MaskImgType; typedef itk::Vector OdfVectorType; typedef itk::Image ItkQBallImgType; typedef itk::GibbsTrackingFilter GibbsTrackingFilterType; static const std::string VIEW_ID; QmitkGibbsTrackingView(); virtual ~QmitkGibbsTrackingView(); virtual void CreateQtPartControl(QWidget *parent); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); signals: protected slots: void StartGibbsTracking(); void StopGibbsTracking(); void AfterThread(); void BeforeThread(); void TimerUpdate(); void SetMask(); void AdvancedSettings(); void SaveTrackingParameters(); void LoadTrackingParameters(); void SetIterations(int value); void SetParticleWidth(int value); void SetParticleLength(int value); void SetInExBalance(int value); void SetFiberLength(int value); void SetParticleWeight(int value); void SetStartTemp(int value); void SetEndTemp(int value); void SetCurvatureThreshold(int value); void SetOutputFile(); private: // Visualization & GUI void GenerateFiberBundle(bool smoothFibers); void UpdateGUI(); void UpdateTrackingStatus(); /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); template void CastToFloat(InputImageType* image, typename mitk::Image::Pointer outImage); void UpdateIteraionsGUI(unsigned long iterations); Ui::QmitkGibbsTrackingViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; // data objects mitk::FiberBundleX::Pointer m_FiberBundle; MaskImgType::Pointer m_MaskImage; mitk::QBallImage::Pointer m_QBallImage; ItkQBallImgType::Pointer m_ItkQBallImage; // data nodes mitk::DataNode::Pointer m_QBallImageNode; mitk::DataNode::Pointer m_MaskImageNode; mitk::DataNode::Pointer m_FiberBundleNode; // flags etc. bool m_ThreadIsRunning; QTimer* m_TrackingTimer; QTime m_TrackingTime; unsigned long m_ElapsedTime; - bool m_QBallSelected; - bool m_FibSelected; unsigned long m_Iterations; int m_LastStep; QString m_OutputFileName; - int m_SaveCounter; // global tracker and friends itk::SmartPointer m_GlobalTracker; QmitkTrackingWorker m_TrackingWorker; QThread m_TrackingThread; friend class QmitkTrackingWorker; }; #endif // _QMITKGibbsTrackingVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingViewControls.ui index 8b8172f6a9..b99d3213ef 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingViewControls.ui @@ -1,1111 +1,1045 @@ QmitkGibbsTrackingViewControls 0 0 463 1011 0 0 0 0 QmitkTemplate 0 - 3 + 9 - 0 + 3 - 3 + 9 - 0 + 3 - + - + Data - - false + + + + + Q-Ball Image: + + + + + + + Mandatory input + + + - + + + + + + + Mask Image: + + + + + + + Optional input to limit the algorithms search space. + + + - + + + + + + + + + + Parameters - - - 0 - - + + 0 - - + + + + + + + + + + + + + Iterations: 10^7 + + + + + + + Specify number of iterations for the tracking algorithm. + + + 10 + + + 6 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + + + true - - false + + Activate continuous visualization of intermediate results. + + + Visualize Tractography + + + true + + + + + + + Visualize intermediate result. + + + + + + + :/QmitkDiffusionImaging/Refresh_48.png:/QmitkDiffusionImaging/Refresh_48.png + + + true + + + + + + + Advanced Settings + + + + + + + + + + + + + + + Output File: + + + + + QFrame::NoFrame - QFrame::Raised + QFrame::Plain - - - QFormLayout::AllNonFixedFieldsGrow - - + + 0 + + + 0 - - 4 - - + 0 - - - - Mask Image - - - - - - Binary mask image to reduce the algorithms search space. - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 0 - - - - - true - - - => - - - - - - - true - - - N/A - - - true - - - - - - - - - - - - - - - - - - - Iterations: 10^7 - - - - - - - Specify number of iterations for the tracking algorithm. - - - 10 - - - 6 - - - Qt::Horizontal - - - QSlider::TicksBelow - - - - - - - true - - - Activate continuous visualization of intermediate results. - - - Visualize Tractography - - - true - - - - - - - Advanced Settings - - - - - - - true - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 0 - - - 4 - - - 0 - - - - - - - - - - - - - - auto - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - auto = 1.5 * min. spacing; l - - - 100 - - - 1 - - - Qt::Horizontal - - - QSlider::NoTicks - - - - - - - - - - - - - - - - auto - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - auto = 0.5 * min. spacing; sigma - - - 100 - - - 1 - - - Qt::Horizontal - - - QSlider::NoTicks - - - - - - - - - - - - - - - - auto - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - automatic estimation from gfa map and q-ball data. - - - 0 - - - 1000 - - - 1 - - - 0 - - - Qt::Horizontal - - - true - - - QSlider::NoTicks - - - - - - - 0.1 - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - 1 - - - 100 - - - 1 - - - 10 - - - Qt::Horizontal - - - false - - - false - - - QSlider::NoTicks - - - - - - - 0.001 - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - 1 - - - 99 - - - 1 - - - 10 - - - Qt::Horizontal - - - QSlider::NoTicks - - - - - - - - - - - - - - - - 0 - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - IE Bias < 0 < EE Bias - - - -50 - - - 50 - - - 1 - - - Qt::Horizontal - - - QSlider::NoTicks - - - - - - - - - - - - - - - - 40mm - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - Only fibers longer than specified are accepted. - - - 100 - - - 1 - - - 40 - - - Qt::Horizontal - - - QSlider::NoTicks - - - - - - - - - - - - - - - - Particle Length: - - - - - - - - - - - - - - - - Particle Width: - - - - - - - - - - - - - - - - Particle Weight: - - - - - - - Start Temperature: - - - - - - - End Temperature: - - - - - - - - - - - - - - - - Balance In/Ex Energy: - - - - - - - - - - - - - - - - Min. Fiber Length: - - - - - - - true - - - Use mean subtracted ODFs (recommended). - - - Subtract ODF Mean - - - true - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 60 - 20 - - - - - - - - - - - - - - - - - Curvature Threshold: - - - - - - - - - - - - - - - - 45° - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - Allow only fiber curvature values smaller than the selected threshold. - - - 180 - - - 1 - - - 45 - - - Qt::Horizontal - - - QSlider::NoTicks - - - - - - - - - - true - - - Save current parameters as xml (.gtp) - - - Qt::LeftToRight - - - Save Parameters - - - - :/qmitk/btnMoveDown.png:/qmitk/btnMoveDown.png - - - - - - - true - - - Load parameters from xml file (.gtp) - - - Qt::LeftToRight - - - Load Parameters - - - - :/qmitk/btnMoveUp.png:/qmitk/btnMoveUp.png - - - - - - - false - - - No Q-Ball image selected. - - - Qt::LeftToRight - - - Start Tractography - - - - :/qmitk/play.xpm:/qmitk/play.xpm - - - - - - - false - + - - - - Qt::LeftToRight + Select output file name and folder. - Stop Tractography - - - - :/qmitk/stop.xpm:/qmitk/stop.xpm + ... - - - - Visualize intermediate result. - + + - - - - - :/QmitkDiffusionImaging/Refresh_48.png:/QmitkDiffusionImaging/Refresh_48.png + N/A - + true - - - - - 0 - 0 - - - - - 0 - 0 - + + + + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 9 + + + 0 + + + 9 + + + 0 + + + 4 + + + + + - - QFrame::StyledPanel + + - - QFrame::Raised + + + + + auto + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - 0 - - - 7 - - - 0 - - - - - Will only be updated if tracking is visualized - - - Will only be updated if tracking is visualized - - - - - - Accepted Fibers: - - - - - - - Will only be updated if tracking is visualized - - - - - - - - - - - - - - - - - - - - - - - - - - Progress: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Connections: - - - - - - - - - - - - - - - - Particles: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Tracking Time: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Proposal Acceptance Rate: - - - - - - - - - - - - - - - - - - - - - - - - - QFrame::NoFrame + + + + - - QFrame::Plain + + + + + + + + auto + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + auto = 0.5 * min. spacing; sigma + + + 100 + + + 1 + + + Qt::Horizontal + + + QSlider::NoTicks + + + + + + + + + + + + + + + + auto + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + automatic estimation from gfa map and q-ball data. + + + 0 + + + 1000 + + + 1 + + + 0 + + + Qt::Horizontal + + + true + + + QSlider::NoTicks + + + + + + + 0.1 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + 1 + + + 100 + + + 1 + + + 10 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + 0.001 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + 1 + + + 99 + + + 1 + + + 10 + + + Qt::Horizontal + + + QSlider::NoTicks + + + + + + + + + + + + + + + + 0 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + IE Bias < 0 < EE Bias + + + -50 + + + 50 + + + 1 + + + Qt::Horizontal + + + QSlider::NoTicks + + + + + + + + + + + + + + + + 40mm + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + Only fibers longer than specified are accepted. + + + 100 + + + 1 + + + 40 + + + Qt::Horizontal + + + QSlider::NoTicks + + + + + + + + + + + + + + + + Particle Length: + + + + + + + + + + + + + + + + Particle Width: + + + + + + + + + + + + + + + + Particle Weight: + + + + + + + Start Temperature: + + + + + + + End Temperature: + + + + + + + + + + + + + + + + Balance In/Ex Energy: + + + + + + + + + + + + + + + + Min. Fiber Length: + + + + + + + true + + + Use mean subtracted ODFs (recommended). + + + Subtract ODF Mean + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 60 + 20 + + + + + + + + + + + + + + + + + Curvature Threshold: + + + + + + + + + + + + + + + + 45° + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + Allow only fiber curvature values smaller than the selected threshold. + + + 180 + + + 1 + + + 45 + + + Qt::Horizontal + + + QSlider::NoTicks + + + + + + + auto = 1.5 * min. spacing; l + + + 100 + + + 1 + + + Qt::Horizontal + + + QSlider::NoTicks + + + + + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + 0 + + + + 0 + + + 0 + + + + + true + + + Save current parameters as xml (.gtp) + + + Qt::LeftToRight + + + Save Parameters + + + + :/qmitk/btnMoveDown.png:/qmitk/btnMoveDown.png + + + + + + + true + + + Load parameters from xml file (.gtp) + + + Qt::LeftToRight + + + Load Parameters + + + + :/qmitk/btnMoveUp.png:/qmitk/btnMoveUp.png + + + + + + + false + + + No Q-Ball image selected. + + + Qt::LeftToRight + + + Start Tractography + + + + :/qmitk/play.xpm:/qmitk/play.xpm + + + + + + + false + + + + + + Qt::LeftToRight + + + Stop Tractography + + + + :/qmitk/stop.xpm:/qmitk/stop.xpm + + + + + + + + + + Monitor + + + + + + + + + + + + + + + Progress: + + + + + + + + + + + + + + + + - + + + + + + + Will only be updated if tracking is visualized + + + Will only be updated if tracking is visualized + + + + + + Accepted Fibers: + + + + + + + + + + + + + + + + Connections: + + + + + + + + + + + + + + + + Particles: + + + + + + + + + + + + + + + + Proposal Acceptance Rate: + + + + + + + + + + + + + + + + Tracking Time: + + + + + + + Will only be updated if tracking is visualized + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - 0 - - - 10 - - - 0 - - - 0 - - - 0 - - - - - - - - - - - - - - Output File: - - - - - - - - - - - - - - - - N/A - - - - - - - Select output file name and folder. - - - ... - - - - - - - true - - - Results are enumerated and saved separately. - - - save intermediate results - - - false - - - - Qt::Vertical QSizePolicy::Expanding 0 0 + - diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkODFDetailsView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkODFDetailsView.cpp index 6b6fd83070..8cda17993f 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkODFDetailsView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkODFDetailsView.cpp @@ -1,282 +1,308 @@ /*========================================================================= Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkODFDetailsView.h" #include #include #include #include #include #include #include #include #include #include +#include const std::string QmitkODFDetailsView::VIEW_ID = "org.mitk.views.odfdetails"; QmitkODFDetailsView::QmitkODFDetailsView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) , m_OdfNormalization(0) + , m_SelectedNode(NULL) { m_VtkActor = vtkActor::New(); m_VtkMapper = vtkPolyDataMapper::New(); m_Renderer = vtkRenderer::New(); m_VtkRenderWindow = vtkRenderWindow::New(); m_RenderWindowInteractor = vtkRenderWindowInteractor::New(); m_Camera = vtkCamera::New(); m_VtkRenderWindow->SetSize(300,300); } QmitkODFDetailsView::~QmitkODFDetailsView() { QmitkStdMultiWidget* MultiWidget = this->GetActiveStdMultiWidget(false); if(MultiWidget) { //unregister observers when view is destroyed if( MultiWidget->mitkWidget1 != NULL && m_SliceObserverTag1 != 0) { mitk::SliceNavigationController* slicer = MultiWidget->mitkWidget1->GetSliceNavigationController(); slicer->RemoveObserver( m_SliceObserverTag1 ); } if( MultiWidget->mitkWidget2 != NULL && m_SliceObserverTag2 != 0) { mitk::SliceNavigationController* slicer = MultiWidget->mitkWidget2->GetSliceNavigationController(); slicer->RemoveObserver( m_SliceObserverTag2 ); } if( MultiWidget->mitkWidget3!= NULL && m_SliceObserverTag3 != 0) { mitk::SliceNavigationController* slicer = MultiWidget->mitkWidget3->GetSliceNavigationController(); slicer->RemoveObserver( m_SliceObserverTag3 ); } } } void QmitkODFDetailsView::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::QmitkODFDetailsViewControls; m_Controls->setupUi( parent ); m_Controls->m_OdfBox->setVisible(false); + m_Controls->m_ODFRenderWidget->setVisible(false); } } void QmitkODFDetailsView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; { mitk::SliceNavigationController* slicer = m_MultiWidget->mitkWidget1->GetSliceNavigationController(); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkODFDetailsView::OnSliceChanged ); m_SliceObserverTag1 = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(NULL, 0), command ); } { mitk::SliceNavigationController* slicer = m_MultiWidget->mitkWidget2->GetSliceNavigationController(); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkODFDetailsView::OnSliceChanged ); m_SliceObserverTag2 = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(NULL, 0), command ); } { mitk::SliceNavigationController* slicer = m_MultiWidget->mitkWidget3->GetSliceNavigationController(); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkODFDetailsView::OnSliceChanged ); m_SliceObserverTag3 = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(NULL, 0), command ); } } void QmitkODFDetailsView::StdMultiWidgetNotAvailable() { { mitk::SliceNavigationController* slicer = m_MultiWidget->mitkWidget1->GetSliceNavigationController(); slicer->RemoveObserver( m_SliceObserverTag1 ); } { mitk::SliceNavigationController* slicer = m_MultiWidget->mitkWidget2->GetSliceNavigationController(); slicer->RemoveObserver( m_SliceObserverTag2 ); } { mitk::SliceNavigationController* slicer = m_MultiWidget->mitkWidget3->GetSliceNavigationController(); slicer->RemoveObserver( m_SliceObserverTag3 ); } m_MultiWidget = NULL; } -void QmitkODFDetailsView::OnSliceChanged(const itk::EventObject& /*e*/) +void QmitkODFDetailsView::OnSelectionChanged( std::vector nodes ) +{ + if (m_SelectedNode.IsNotNull()) + m_SelectedNode->RemoveObserver( m_PropertyObserverTag ); + UpdateOdf(); + if (m_SelectedNode.IsNotNull()) + { + itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); + command->SetCallbackFunction( this, &QmitkODFDetailsView::OnSliceChanged ); + m_PropertyObserverTag = m_SelectedNode->AddObserver( itk::ModifiedEvent(), command ); + } +} + +void QmitkODFDetailsView::UpdateOdf() { try { m_Values.clear(); std::vector nodes = this->GetDataManagerSelection(); if (nodes.empty()) return; if (!nodes.front()) return; + m_SelectedNode = nodes.front(); mitk::Image::Pointer img = dynamic_cast(nodes.front()->GetData()); if (!img) return; if (!m_MultiWidget) return; // ODF Normalization Property mitk::OdfNormalizationMethodProperty* nmp = dynamic_cast(nodes.front()->GetProperty( "Normalization" )); if(nmp) m_OdfNormalization = nmp->GetNormalization(); m_TemplateOdf = itk::OrientationDistributionFunction::GetBaseMesh(); m_OdfTransform = vtkSmartPointer::New(); m_OdfTransform->Identity(); m_OdfVals = vtkSmartPointer::New(); m_OdfSource = vtkSmartPointer::New(); itk::OrientationDistributionFunction odf; - itk::OrientationDistributionFunction originalOdf; mitk::Point3D world = m_MultiWidget->GetCrossPosition(); mitk::Point3D index; img->GetTimeSlicedGeometry()->WorldToIndex(world, index); float sum = 0; float max = itk::NumericTraits::min(); float min = itk::NumericTraits::max(); QString values; QString overviewText; // check if dynamic_cast successfull and if the crosshair position is inside of the geometry of the ODF data // otherwise possible crash for a scenario with multiple nodes if (dynamic_cast(nodes.front()->GetData()) && ( nodes.front()->GetData()->GetGeometry()->IsInside(world) ) ) { + m_Controls->m_ODFRenderWidget->setVisible(true); m_Controls->m_OdfBox->setVisible(true); OdfVectorImgType::Pointer itkQBallImage = OdfVectorImgType::New(); mitk::CastToItkImage(dynamic_cast(nodes.front()->GetData()), itkQBallImage); OdfVectorImgType::IndexType ind; ind[0] = (int)(index[0]+0.5); ind[1] = (int)(index[1]+0.5); ind[2] = (int)(index[2]+0.5); OdfVectorImgType::PixelType pixel = itkQBallImage->GetPixel(ind); for (int i=0; imax) max = val; if (val pd = odf.GetDirection(odf.GetPrincipleDiffusionDirection()); overviewText += "Main Diffusion:\n "+QString::number(pd[0])+"\n "+QString::number(pd[1])+"\n "+QString::number(pd[2])+"\n"; m_Controls->m_OdfValuesTextEdit->setText(values); } else if (dynamic_cast(nodes.front()->GetData())) { + m_Controls->m_ODFRenderWidget->setVisible(true); m_Controls->m_OdfBox->setVisible(false); TensorImageType::Pointer itkQBallImage = TensorImageType::New(); mitk::CastToItkImage(dynamic_cast(nodes.front()->GetData()), itkQBallImage); TensorImageType::IndexType ind; ind[0] = (int)(index[0]+0.5); ind[1] = (int)(index[1]+0.5); ind[2] = (int)(index[2]+0.5); TensorImageType::PixelType pixel = itkQBallImage->GetPixel(ind); float tensorelems[6] = { (float)pixel[0], (float)pixel[1], (float)pixel[2], (float)pixel[3], (float)pixel[4], (float)pixel[5], }; itk::DiffusionTensor3D tensor(tensorelems); odf.InitFromTensor(tensor); /** Array of eigen-values. */ typedef itk::FixedArray EigenValuesArrayType; /** Matrix of eigen-vectors. */ typedef itk::Matrix MatrixType; typedef itk::Matrix EigenVectorsMatrixType; EigenValuesArrayType eigenValues; EigenVectorsMatrixType eigenVectors; QString pos = QString::number(ind[0])+", "+QString::number(ind[1])+", "+QString::number(ind[2]); overviewText += "Coordinates: "+pos+"\n"; overviewText += "FA: "+QString::number(tensor.GetFractionalAnisotropy())+"\n"; overviewText += "RA: "+QString::number(tensor.GetRelativeAnisotropy())+"\n"; overviewText += "Trace: "+QString::number(tensor.GetTrace())+"\n"; tensor.ComputeEigenAnalysis(eigenValues,eigenVectors); overviewText += "Eigenvalues:\n "+QString::number(eigenValues[2])+"\n "+QString::number(eigenValues[1])+"\n "+QString::number(eigenValues[0])+"\n"; overviewText += "Main Diffusion:\n "+QString::number(eigenVectors[0][0])+"\n "+QString::number(eigenVectors[1][0])+"\n "+QString::number(eigenVectors[2][0])+"\n"; overviewText += "Values:\n "+QString::number(tensorelems[0])+"\n "+QString::number(tensorelems[1])+"\n "+QString::number(tensorelems[2])+"\n "+QString::number(tensorelems[3])+"\n "+QString::number(tensorelems[4])+"\n "+QString::number(tensorelems[5])+"\n "+"\n"; } + else + { + m_Controls->m_ODFRenderWidget->setVisible(false); + m_Controls->m_OdfBox->setVisible(false); + overviewText += "Please select a Q-Ball or tensor image\n"; + } - - originalOdf = odf; + m_Controls->m_ODFDetailsWidget->SetParameters(odf); switch(m_OdfNormalization) { case 0: odf = odf.MinMaxNormalize(); break; case 1: odf = odf.MaxNormalize(); break; case 2: - // nothing + odf = odf.MaxNormalize(); break; default: odf = odf.MinMaxNormalize(); } - m_Controls->m_ODFDetailsWidget->SetParameters(originalOdf); m_Controls->m_ODFRenderWidget->GenerateODF(odf); - m_Controls->m_OverviewTextEdit->setText(overviewText.toStdString().c_str()); } catch(...) { QMessageBox::critical(0, "Error", "Data could not be analyzed. The image might be corrupted."); } } + +void QmitkODFDetailsView::OnSliceChanged(const itk::EventObject& /*e*/) +{ + UpdateOdf(); +} diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkODFDetailsView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkODFDetailsView.h index 36738c934b..a935492329 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkODFDetailsView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkODFDetailsView.h @@ -1,109 +1,114 @@ /*========================================================================= Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _QMITKQmitkODFDetailsView_H_INCLUDED #define _QMITKQmitkODFDetailsView_H_INCLUDED #include #include #include "ui_QmitkODFDetailsViewControls.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*! \brief QmitkODFDetailsView \warning This application module is not yet documented. Use "svn blame/praise/annotate" and ask the author to provide basic documentation. \sa QmitkFunctionality \ingroup Functionalities */ class QmitkODFDetailsView : public QmitkFunctionality { // 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; QmitkODFDetailsView(); QmitkODFDetailsView(const QmitkODFDetailsView& other) { Q_UNUSED(other) throw std::runtime_error("Copy constructor not implemented"); } virtual ~QmitkODFDetailsView(); typedef float TOdfPixelType; typedef itk::Vector OdfVectorType; typedef itk::Image OdfVectorImgType; typedef itk::DiffusionTensor3D< TOdfPixelType > TensorPixelType; typedef itk::Image< TensorPixelType, 3 > TensorImageType; virtual void CreateQtPartControl(QWidget *parent); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); void OnSliceChanged(const itk::EventObject& e); protected slots: protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed + virtual void OnSelectionChanged( std::vector nodes ); + + void UpdateOdf(); Ui::QmitkODFDetailsViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; int m_SliceObserverTag1; int m_SliceObserverTag2; int m_SliceObserverTag3; + int m_PropertyObserverTag; vtkPolyData* m_TemplateOdf; vtkSmartPointer m_OdfTransform; vtkSmartPointer m_OdfVals; vtkSmartPointer m_OdfSource; vtkActor* m_VtkActor; vtkPolyDataMapper* m_VtkMapper; vtkRenderer* m_Renderer; vtkRenderWindow* m_VtkRenderWindow; vtkRenderWindowInteractor* m_RenderWindowInteractor; vtkCamera* m_Camera; + mitk::DataNode::Pointer m_SelectedNode; std::vector m_Values; int m_OdfNormalization; }; #endif // _QmitkODFDetailsView_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisView.cpp index 23516def66..52ea734ec8 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisView.cpp @@ -1,2084 +1,2169 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-05-22 11:00:35 +0200 (Fr, 22 Mai 2009) $ Version: $Revision: 10185 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkPartialVolumeAnalysisView.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "QmitkStdMultiWidget.h" #include "QmitkSliderNavigatorWidget.h" #include "mitkNodePredicateDataType.h" #include "mitkNodePredicateOr.h" #include "mitkImageTimeSelector.h" #include "mitkProperties.h" #include "mitkProgressBar.h" - -// Includes for image processing #include "mitkImageCast.h" #include "mitkImageToItk.h" #include "mitkITKImageImport.h" #include "mitkDataNodeObject.h" #include "mitkNodePredicateData.h" - #include "mitkPlanarFigureInteractor.h" #include "mitkGlobalInteraction.h" #include "mitkTensorImage.h" - #include "mitkPlanarCircle.h" #include "mitkPlanarRectangle.h" #include "mitkPlanarPolygon.h" - #include "mitkPartialVolumeAnalysisClusteringCalculator.h" +#include "mitkDiffusionImage.h" #include #include "itkTensorDerivedMeasurementsFilter.h" #include "itkDiffusionTensor3D.h" #include "itkCartesianToPolarVectorImageFilter.h" #include "itkPolarToCartesianVectorImageFilter.h" #include "itkBinaryThresholdImageFilter.h" #include "itkMaskImageFilter.h" #include "itkCastImageFilter.h" - #include "itkImageMomentsCalculator.h" +#include +#include +#include #include #define _USE_MATH_DEFINES #include #define PVA_PI M_PI const std::string QmitkPartialVolumeAnalysisView::VIEW_ID = "org.mitk.views.partialvolumeanalysisview"; class QmitkRequestStatisticsUpdateEvent : public QEvent { public: enum Type { StatisticsUpdateRequest = QEvent::MaxUser - 1025 }; QmitkRequestStatisticsUpdateEvent() : QEvent( (QEvent::Type) StatisticsUpdateRequest ) {}; }; typedef itk::Image ImageType; typedef itk::Image FloatImageType; typedef itk::Image, 3> VectorImageType; inline bool my_isnan(float x) { volatile float d = x; if(d!=d) return true; if(d==d) return false; return d != d; } QmitkPartialVolumeAnalysisView::QmitkPartialVolumeAnalysisView(QObject * /*parent*/, const char * /*name*/) : QmitkFunctionality(), m_Controls( NULL ), m_TimeStepperAdapter( NULL ), m_MeasurementInfoRenderer(0), m_MeasurementInfoAnnotation(0), m_SelectedImageNodes( ), m_SelectedImage( NULL ), m_SelectedMaskNode( NULL ), m_SelectedImageMask( NULL ), m_SelectedPlanarFigureNodes(0), m_SelectedPlanarFigure( NULL ), m_IsTensorImage(false), m_FAImage(0), m_RDImage(0), m_ADImage(0), m_MDImage(0), m_CAImage(0), // m_DirectionImage(0), m_DirectionComp1Image(0), m_DirectionComp2Image(0), m_AngularErrorImage(0), m_SelectedRenderWindow(NULL), m_LastRenderWindow(NULL), m_ImageObserverTag( -1 ), m_ImageMaskObserverTag( -1 ), m_PlanarFigureObserverTag( -1 ), m_CurrentStatisticsValid( false ), m_StatisticsUpdatePending( false ), m_GaussianSigmaChangedSliding(false), m_NumberBinsSliding(false), m_UpsamplingChangedSliding(false), m_ClusteringResult(NULL), m_EllipseCounter(0), m_RectangleCounter(0), m_PolygonCounter(0), m_CurrentFigureNodeInitialized(false), m_QuantifyClass(2), m_IconTexOFF(new QIcon(":/QmitkPartialVolumeAnalysisView/texIntOFFIcon.png")), m_IconTexON(new QIcon(":/QmitkPartialVolumeAnalysisView/texIntONIcon.png")), m_TexIsOn(true) { } QmitkPartialVolumeAnalysisView::~QmitkPartialVolumeAnalysisView() { if ( m_SelectedImage.IsNotNull() ) m_SelectedImage->RemoveObserver( m_ImageObserverTag ); if ( m_SelectedImageMask.IsNotNull() ) m_SelectedImageMask->RemoveObserver( m_ImageMaskObserverTag ); if ( m_SelectedPlanarFigure.IsNotNull() ) { m_SelectedPlanarFigure->RemoveObserver( m_PlanarFigureObserverTag ); m_SelectedPlanarFigure->RemoveObserver( m_InitializedObserverTag ); } this->GetDefaultDataStorage()->AddNodeEvent -= mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeAddedInDataStorage ); m_SelectedPlanarFigureNodes->NodeChanged.RemoveListener( mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) ); m_SelectedPlanarFigureNodes->NodeRemoved.RemoveListener( mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) ); m_SelectedPlanarFigureNodes->PropertyChanged.RemoveListener( mitk::MessageDelegate2( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) ); m_SelectedImageNodes->NodeChanged.RemoveListener( mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) ); m_SelectedImageNodes->NodeRemoved.RemoveListener( mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) ); m_SelectedImageNodes->PropertyChanged.RemoveListener( mitk::MessageDelegate2( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) ); } void QmitkPartialVolumeAnalysisView::CreateQtPartControl(QWidget *parent) { if (m_Controls == NULL) { m_Controls = new Ui::QmitkPartialVolumeAnalysisViewControls; m_Controls->setupUi(parent); this->CreateConnections(); m_Controls->m_ErrorMessageLabel->hide(); } SetHistogramVisibility(); m_Controls->m_TextureIntON->setIcon(*m_IconTexON); m_Controls->m_SimilarAnglesFrame->setVisible(false); m_Controls->m_SimilarAnglesLabel->setVisible(false); vtkTextProperty *textProp = vtkTextProperty::New(); textProp->SetColor(1.0, 1.0, 1.0); m_MeasurementInfoAnnotation = vtkCornerAnnotation::New(); m_MeasurementInfoAnnotation->SetMaximumFontSize(12); m_MeasurementInfoAnnotation->SetTextProperty(textProp); m_MeasurementInfoRenderer = vtkRenderer::New(); m_MeasurementInfoRenderer->AddActor(m_MeasurementInfoAnnotation); m_SelectedPlanarFigureNodes = mitk::DataStorageSelection::New(this->GetDefaultDataStorage(), false); m_SelectedPlanarFigureNodes->NodeChanged.AddListener( mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) ); m_SelectedPlanarFigureNodes->NodeRemoved.AddListener( mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) ); m_SelectedPlanarFigureNodes->PropertyChanged.AddListener( mitk::MessageDelegate2( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) ); m_SelectedImageNodes = mitk::DataStorageSelection::New(this->GetDefaultDataStorage(), false); m_SelectedImageNodes->PropertyChanged.AddListener( mitk::MessageDelegate2( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) ); m_SelectedImageNodes->NodeChanged.AddListener( mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) ); m_SelectedImageNodes->NodeRemoved.AddListener( mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) ); this->GetDefaultDataStorage()->AddNodeEvent.AddListener( mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeAddedInDataStorage ) ); Select(NULL,true,true); SetAdvancedVisibility(); } void QmitkPartialVolumeAnalysisView::SetHistogramVisibility() { m_Controls->m_HistogramWidget->setVisible(m_Controls->m_DisplayHistogramCheckbox->isChecked()); } void QmitkPartialVolumeAnalysisView::SetAdvancedVisibility() { m_Controls->frame_7->setVisible(m_Controls->m_AdvancedCheckbox->isChecked()); } void QmitkPartialVolumeAnalysisView::CreateConnections() { if ( m_Controls ) { connect( m_Controls->m_DisplayHistogramCheckbox, SIGNAL( clicked() ) , this, SLOT( SetHistogramVisibility() ) ); connect( m_Controls->m_AdvancedCheckbox, SIGNAL( clicked() ) , this, SLOT( SetAdvancedVisibility() ) ); connect( m_Controls->m_NumberBinsSlider, SIGNAL( sliderReleased () ), this, SLOT( NumberBinsReleasedSlider( ) ) ); connect( m_Controls->m_UpsamplingSlider, SIGNAL( sliderReleased( ) ), this, SLOT( UpsamplingReleasedSlider( ) ) ); connect( m_Controls->m_GaussianSigmaSlider, SIGNAL( sliderReleased( ) ), this, SLOT( GaussianSigmaReleasedSlider( ) ) ); connect( m_Controls->m_SimilarAnglesSlider, SIGNAL( sliderReleased( ) ), this, SLOT( SimilarAnglesReleasedSlider( ) ) ); connect( m_Controls->m_NumberBinsSlider, SIGNAL( valueChanged (int) ), this, SLOT( NumberBinsChangedSlider( int ) ) ); connect( m_Controls->m_UpsamplingSlider, SIGNAL( valueChanged( int ) ), this, SLOT( UpsamplingChangedSlider( int ) ) ); connect( m_Controls->m_GaussianSigmaSlider, SIGNAL( valueChanged( int ) ), this, SLOT( GaussianSigmaChangedSlider( int ) ) ); connect( m_Controls->m_SimilarAnglesSlider, SIGNAL( valueChanged( int ) ), this, SLOT( SimilarAnglesChangedSlider(int) ) ); connect( m_Controls->m_OpacitySlider, SIGNAL( valueChanged( int ) ), this, SLOT( OpacityChangedSlider(int) ) ); connect( (QObject*)(m_Controls->m_ButtonCopyHistogramToClipboard), SIGNAL(clicked()),(QObject*) this, SLOT(ToClipBoard())); connect( m_Controls->m_CircleButton, SIGNAL( clicked() ) , this, SLOT( ActionDrawEllipseTriggered() ) ); connect( m_Controls->m_RectangleButton, SIGNAL( clicked() ) , this, SLOT( ActionDrawRectangleTriggered() ) ); connect( m_Controls->m_PolygonButton, SIGNAL( clicked() ) , this, SLOT( ActionDrawPolygonTriggered() ) ); connect( m_Controls->m_GreenRadio, SIGNAL( clicked(bool) ) , this, SLOT( GreenRadio(bool) ) ); connect( m_Controls->m_PartialVolumeRadio, SIGNAL( clicked(bool) ) , this, SLOT( PartialVolumeRadio(bool) ) ); connect( m_Controls->m_BlueRadio, SIGNAL( clicked(bool) ) , this, SLOT( BlueRadio(bool) ) ); connect( m_Controls->m_AllRadio, SIGNAL( clicked(bool) ) , this, SLOT( AllRadio(bool) ) ); connect( m_Controls->m_EstimateCircle, SIGNAL( clicked() ) , this, SLOT( EstimateCircle() ) ); connect( (QObject*)(m_Controls->m_TextureIntON), SIGNAL(clicked()), this, SLOT(TextIntON()) ); + connect( m_Controls->m_ExportClusteringResultsButton, SIGNAL(clicked()), this, SLOT(ExportClusteringResults())); } } +void QmitkPartialVolumeAnalysisView::ExportClusteringResults() +{ + if (m_ClusteringResult.IsNull() || m_SelectedImage.IsNull()) + return; + + mitk::DiffusionImage::Pointer diffusionImage = NULL; + if (dynamic_cast*>(m_SelectedImage.GetPointer())) + diffusionImage = dynamic_cast*>(m_SelectedImage.GetPointer()); + else + return; + + typedef itk::Image< float, 3 > OutType; + mitk::Image::Pointer mitkInImage = dynamic_cast(m_ClusteringResult->GetData()); + typedef itk::ExtractChannelFromRgbaImageFilter< OutType > ExtractionFilterType; + + typedef itk::Image< itk::RGBAPixel, 3 > ItkRgbaImageType; + typedef mitk::ImageToItk< ItkRgbaImageType > CasterType; + + CasterType::Pointer caster = CasterType::New(); + caster->SetInput(mitkInImage); + caster->Update(); + ItkRgbaImageType::Pointer itkInImage = caster->GetOutput(); + + ExtractionFilterType::Pointer filter = ExtractionFilterType::New(); + filter->SetInput(itkInImage); + filter->SetChannel(ExtractionFilterType::ALPHA); + filter->SetReferenceImage(diffusionImage->GetVectorImage()); + filter->Update(); + + OutType::Pointer outImg = filter->GetOutput(); + +// mitk::Geometry3D* geometry = m_SelectedImage->GetGeometry(); +// itk::Matrix direction; +// itk::ImageRegion<3> imageRegion; +// for (int i=0; i<3; i++) +// for (int j=0; j<3; j++) +// direction[j][i] = geometry->GetMatrixColumn(i)[j]; +// imageRegion.SetSize(0, geometry->GetExtent(0)); +// imageRegion.SetSize(1, geometry->GetExtent(1)); +// imageRegion.SetSize(2, geometry->GetExtent(2)); +// typedef itk::ResampleImageFilter ResamplerType; +// ResamplerType::Pointer resampler = ResamplerType::New(); +// resampler->SetOutputSpacing( geometry->GetSpacing() ); +// resampler->SetOutputOrigin( geometry->GetOrigin() ); +// resampler->SetOutputDirection( direction ); +// resampler->SetSize( imageRegion.GetSize() ); +// resampler->SetInput( outImg ); +// const itk::Transform* trafo = geometry->GetParametricTransform(); +// itk::Transform::InverseTransformBasePointer t = trafo->GetInverseTransform(); +// itk::Transform* invTrafo = dynamic_cast*>(t.GetPointer()); +// resampler->SetTransform(invTrafo); + +//// double gausssigma = 10; +//// double sigma[3]; +//// for( unsigned int d = 0; d < 3; d++ ) +//// sigma[d] = gausssigma * geometry->GetSpacing()[d]; +//// double alpha = 2.0; +//// typedef itk::GaussianInterpolateImageFunction InterpolatorType; +//// typedef itk::NearestNeighborInterpolateImageFunction InterpolatorType; +//// typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); +//// interpolator->SetInputImage( outImg ); +//// interpolator->SetParameters( sigma, alpha ); +//// resampler->SetInterpolator( interpolator ); + +// resampler->Update(); +// outImg = resampler->GetOutput(); + + mitk::Image::Pointer img = mitk::Image::New(); + img->InitializeByItk(outImg.GetPointer()); + img->SetVolume(outImg->GetBufferPointer()); + + // init data node + mitk::DataNode::Pointer node = mitk::DataNode::New(); + node->SetData(img); + node->SetName("Clustering Result"); + GetDataStorage()->Add(node); +} + void QmitkPartialVolumeAnalysisView::EstimateCircle() { typedef itk::Image SegImageType; SegImageType::Pointer mask_itk = SegImageType::New(); typedef mitk::ImageToItk CastType; CastType::Pointer caster = CastType::New(); caster->SetInput(m_SelectedImageMask); caster->Update(); typedef itk::ImageMomentsCalculator< SegImageType > MomentsType; MomentsType::Pointer momentsCalc = MomentsType::New(); momentsCalc->SetImage(caster->GetOutput()); momentsCalc->Compute(); MomentsType::VectorType cog = momentsCalc->GetCenterOfGravity(); MomentsType::MatrixType axes = momentsCalc->GetPrincipalAxes(); MomentsType::VectorType moments = momentsCalc->GetPrincipalMoments(); // moments-coord conversion // third coordinate min oder max? // max-min = extent MomentsType::AffineTransformPointer trafo = momentsCalc->GetPhysicalAxesToPrincipalAxesTransform(); itk::ImageRegionIterator itimage(caster->GetOutput(), caster->GetOutput()->GetLargestPossibleRegion()); itimage = itimage.Begin(); double max = -9999999999.0; double min = 9999999999.0; while( !itimage.IsAtEnd() ) { if(itimage.Get()) { ImageType::IndexType index = itimage.GetIndex(); itk::Point point; caster->GetOutput()->TransformIndexToPhysicalPoint(index,point); itk::Point newPoint; newPoint = trafo->TransformPoint(point); if(newPoint[2]max) max = newPoint[2]; } ++itimage; } double extent = max - min; MITK_INFO << "EXTENT = " << extent; mitk::Point3D origin; mitk::Vector3D right, bottom, normal; double factor = 1000.0; mitk::FillVector3D(origin, cog[0]-factor*axes[1][0]-factor*axes[2][0], cog[1]-factor*axes[1][1]-factor*axes[2][1], cog[2]-factor*axes[1][2]-factor*axes[2][2]); // mitk::FillVector3D(normal, axis[0][0],axis[0][1],axis[0][2]); mitk::FillVector3D(bottom, 2*factor*axes[1][0], 2*factor*axes[1][1], 2*factor*axes[1][2]); mitk::FillVector3D(right, 2*factor*axes[2][0], 2*factor*axes[2][1], 2*factor*axes[2][2]); mitk::PlaneGeometry::Pointer planegeometry = mitk::PlaneGeometry::New(); planegeometry->InitializeStandardPlane(right.Get_vnl_vector(), bottom.Get_vnl_vector()); planegeometry->SetOrigin(origin); double len1 = sqrt(axes[1][0]*axes[1][0] + axes[1][1]*axes[1][1] + axes[1][2]*axes[1][2]); double len2 = sqrt(axes[2][0]*axes[2][0] + axes[2][1]*axes[2][1] + axes[2][2]*axes[2][2]); mitk::Point2D point1; point1[0] = factor*len1; point1[1] = factor*len2; mitk::Point2D point2; point2[0] = factor*len1+extent*.5; point2[1] = factor*len2; mitk::PlanarCircle::Pointer circle = mitk::PlanarCircle::New(); circle->SetGeometry2D(planegeometry); circle->PlaceFigure( point1 ); circle->SetControlPoint(0,point1); circle->SetControlPoint(1,point2); //circle->SetCurrentControlPoint( point2 ); mitk::PlanarFigure::PolyLineType polyline = circle->GetPolyLine( 0 ); MITK_INFO << "SIZE of planar figure polyline: " << polyline.size(); AddFigureToDataStorage(circle, "Circle"); } void QmitkPartialVolumeAnalysisView::StdMultiWidgetAvailable( QmitkStdMultiWidget& stdMultiWidget ) { QmitkFunctionality::StdMultiWidgetAvailable(stdMultiWidget); } bool QmitkPartialVolumeAnalysisView::AssertDrawingIsPossible(bool checked) { if (m_SelectedImageNodes->GetNode().IsNull()) { checked = false; this->HandleException("Please select an image!", this->m_Parent, true); return false; } //this->GetActiveStdMultiWidget()->SetWidgetPlanesVisibility(false); return checked; } void QmitkPartialVolumeAnalysisView::ActionDrawEllipseTriggered() { bool checked = m_Controls->m_CircleButton->isChecked(); if(!this->AssertDrawingIsPossible(checked)) return; mitk::PlanarCircle::Pointer figure = mitk::PlanarCircle::New(); this->AddFigureToDataStorage(figure, QString("Circle%1").arg(++m_EllipseCounter)); MITK_INFO << "PlanarCircle created ..."; } void QmitkPartialVolumeAnalysisView::ActionDrawRectangleTriggered() { bool checked = m_Controls->m_RectangleButton->isChecked(); if(!this->AssertDrawingIsPossible(checked)) return; mitk::PlanarRectangle::Pointer figure = mitk::PlanarRectangle::New(); this->AddFigureToDataStorage(figure, QString("Rectangle%1").arg(++m_RectangleCounter)); MITK_INFO << "PlanarRectangle created ..."; } void QmitkPartialVolumeAnalysisView::ActionDrawPolygonTriggered() { bool checked = m_Controls->m_PolygonButton->isChecked(); if(!this->AssertDrawingIsPossible(checked)) return; mitk::PlanarPolygon::Pointer figure = mitk::PlanarPolygon::New(); figure->ClosedOn(); this->AddFigureToDataStorage(figure, QString("Polygon%1").arg(++m_PolygonCounter)); MITK_INFO << "PlanarPolygon created ..."; } void QmitkPartialVolumeAnalysisView::AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, const char *propertyKey, mitk::BaseProperty *property ) { mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetName(name.toStdString()); newNode->SetData(figure); // Add custom property, if available if ( (propertyKey != NULL) && (property != NULL) ) { newNode->AddProperty( propertyKey, property ); } // figure drawn on the topmost layer / image this->GetDataStorage()->Add(newNode, m_SelectedImageNodes->GetNode() ); std::vector selectedNodes = GetDataManagerSelection(); for(unsigned int i = 0; i < selectedNodes.size(); i++) { selectedNodes[i]->SetSelected(false); } selectedNodes = m_SelectedPlanarFigureNodes->GetNodes(); for(unsigned int i = 0; i < selectedNodes.size(); i++) { selectedNodes[i]->SetSelected(false); } newNode->SetSelected(true); Select(newNode); } void QmitkPartialVolumeAnalysisView::PlanarFigureInitialized() { if(m_SelectedPlanarFigureNodes->GetNode().IsNull()) return; m_CurrentFigureNodeInitialized = true; this->Select(m_SelectedPlanarFigureNodes->GetNode()); m_Controls->m_CircleButton->setChecked(false); m_Controls->m_RectangleButton->setChecked(false); m_Controls->m_PolygonButton->setChecked(false); //this->GetActiveStdMultiWidget()->SetWidgetPlanesVisibility(true); this->RequestStatisticsUpdate(); } void QmitkPartialVolumeAnalysisView::PlanarFigureFocus(mitk::DataNode* node) { mitk::PlanarFigure* _PlanarFigure = 0; _PlanarFigure = dynamic_cast (node->GetData()); if (_PlanarFigure) { FindRenderWindow(node); const mitk::PlaneGeometry * _PlaneGeometry = dynamic_cast (_PlanarFigure->GetGeometry2D()); // make node visible if (m_SelectedRenderWindow) { mitk::Point3D centerP = _PlaneGeometry->GetOrigin(); m_SelectedRenderWindow->GetSliceNavigationController()->ReorientSlices( centerP, _PlaneGeometry->GetNormal()); m_SelectedRenderWindow->GetSliceNavigationController()->SelectSliceByPoint( centerP); } } } void QmitkPartialVolumeAnalysisView::FindRenderWindow(mitk::DataNode* node) { if(node) { mitk::PlanarFigure* _PlanarFigure = 0; _PlanarFigure = dynamic_cast (node->GetData()); if (_PlanarFigure) { m_SelectedRenderWindow = 0; QmitkRenderWindow* RenderWindow1 = this->GetActiveStdMultiWidget()->GetRenderWindow1(); QmitkRenderWindow* RenderWindow2 = this->GetActiveStdMultiWidget()->GetRenderWindow2(); QmitkRenderWindow* RenderWindow3 = this->GetActiveStdMultiWidget()->GetRenderWindow3(); QmitkRenderWindow* RenderWindow4 = this->GetActiveStdMultiWidget()->GetRenderWindow4(); bool PlanarFigureInitializedWindow = false; // find initialized renderwindow if (node->GetBoolProperty("PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow1->GetRenderer())) { m_SelectedRenderWindow = RenderWindow1; } if (!m_SelectedRenderWindow && node->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow2->GetRenderer())) { m_SelectedRenderWindow = RenderWindow2; } if (!m_SelectedRenderWindow && node->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow3->GetRenderer())) { m_SelectedRenderWindow = RenderWindow3; } if (!m_SelectedRenderWindow && node->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow4->GetRenderer())) { m_SelectedRenderWindow = RenderWindow4; } } } } void QmitkPartialVolumeAnalysisView::OnSelectionChanged( std::vector nodes ) { if ( !this->IsVisible() ) { return; } if ( nodes.empty() || nodes.size() > 1 ) { // Nothing to do: invalidate image, clear statistics, histogram, and GUI return; } Select(nodes.front()); } void QmitkPartialVolumeAnalysisView::Select( mitk::DataNode::Pointer node, bool clearMaskOnFirstArgNULL, bool clearImageOnFirstArgNULL ) { // Clear any unreferenced images this->RemoveOrphanImages(); bool somethingChanged = false; if(node.IsNull()) { somethingChanged = true; if(clearMaskOnFirstArgNULL) { if ( (m_SelectedImageMask.IsNotNull()) && (m_ImageMaskObserverTag >= 0) ) { m_SelectedImageMask->RemoveObserver( m_ImageMaskObserverTag ); m_ImageMaskObserverTag = -1; } if ( (m_SelectedPlanarFigure.IsNotNull()) && (m_PlanarFigureObserverTag >= 0) ) { m_SelectedPlanarFigure->RemoveObserver( m_PlanarFigureObserverTag ); m_PlanarFigureObserverTag = -1; } if ( (m_SelectedPlanarFigure.IsNotNull()) && (m_InitializedObserverTag >= 0) ) { m_SelectedPlanarFigure->RemoveObserver( m_InitializedObserverTag ); m_InitializedObserverTag = -1; } m_SelectedPlanarFigure = NULL; m_SelectedPlanarFigureNodes->RemoveAllNodes(); m_CurrentFigureNodeInitialized = false; m_SelectedRenderWindow = 0; m_SelectedMaskNode = NULL; m_SelectedImageMask = NULL; } if(clearImageOnFirstArgNULL) { if ( (m_SelectedImage.IsNotNull()) && (m_ImageObserverTag >= 0) ) { m_SelectedImage->RemoveObserver( m_ImageObserverTag ); m_ImageObserverTag = -1; } m_SelectedImageNodes->RemoveAllNodes(); m_SelectedImage = NULL; m_IsTensorImage = false; m_FAImage = NULL; m_RDImage = NULL; m_ADImage = NULL; m_MDImage = NULL; m_CAImage = NULL; m_DirectionComp1Image = NULL; m_DirectionComp2Image = NULL; m_AngularErrorImage = NULL; m_Controls->m_SimilarAnglesFrame->setVisible(false); m_Controls->m_SimilarAnglesLabel->setVisible(false); } } else { typedef itk::SimpleMemberCommand< QmitkPartialVolumeAnalysisView > ITKCommandType; ITKCommandType::Pointer changeListener; changeListener = ITKCommandType::New(); changeListener->SetCallbackFunction( this, &QmitkPartialVolumeAnalysisView::RequestStatisticsUpdate ); // Get selected element mitk::TensorImage *selectedTensorImage = dynamic_cast< mitk::TensorImage * >( node->GetData() ); mitk::Image *selectedImage = dynamic_cast< mitk::Image * >( node->GetData() ); mitk::PlanarFigure *selectedPlanar = dynamic_cast< mitk::PlanarFigure * >( node->GetData() ); bool isMask = false; bool isImage = false; bool isPlanar = false; bool isTensorImage = false; if (selectedTensorImage != NULL) { isTensorImage = true; } else if(selectedImage != NULL) { node->GetPropertyValue("binary", isMask); isImage = !isMask; } else if ( (selectedPlanar != NULL) ) { isPlanar = true; } // image if(isImage && selectedImage->GetDimension()==3) { if(selectedImage != m_SelectedImage.GetPointer()) { somethingChanged = true; if ( (m_SelectedImage.IsNotNull()) && (m_ImageObserverTag >= 0) ) { m_SelectedImage->RemoveObserver( m_ImageObserverTag ); m_ImageObserverTag = -1; } *m_SelectedImageNodes = node; m_SelectedImage = selectedImage; m_IsTensorImage = false; m_FAImage = NULL; m_RDImage = NULL; m_ADImage = NULL; m_MDImage = NULL; m_CAImage = NULL; m_DirectionComp1Image = NULL; m_DirectionComp2Image = NULL; m_AngularErrorImage = NULL; // Add change listeners to selected objects m_ImageObserverTag = m_SelectedImage->AddObserver( itk::ModifiedEvent(), changeListener ); m_Controls->m_SimilarAnglesFrame->setVisible(false); m_Controls->m_SimilarAnglesLabel->setVisible(false); m_Controls->m_SelectedImageLabel->setText( m_SelectedImageNodes->GetNode()->GetName().c_str() ); } } //planar if(isPlanar) { if(selectedPlanar != m_SelectedPlanarFigure.GetPointer()) { MITK_INFO << "Planar selection changed"; somethingChanged = true; // Possibly previous change listeners if ( (m_SelectedPlanarFigure.IsNotNull()) && (m_PlanarFigureObserverTag >= 0) ) { m_SelectedPlanarFigure->RemoveObserver( m_PlanarFigureObserverTag ); m_PlanarFigureObserverTag = -1; } if ( (m_SelectedPlanarFigure.IsNotNull()) && (m_InitializedObserverTag >= 0) ) { m_SelectedPlanarFigure->RemoveObserver( m_InitializedObserverTag ); m_InitializedObserverTag = -1; } m_SelectedPlanarFigure = selectedPlanar; *m_SelectedPlanarFigureNodes = node; m_CurrentFigureNodeInitialized = selectedPlanar->IsPlaced(); m_SelectedMaskNode = NULL; m_SelectedImageMask = NULL; m_PlanarFigureObserverTag = m_SelectedPlanarFigure->AddObserver( mitk::EndInteractionPlanarFigureEvent(), changeListener ); if(!m_CurrentFigureNodeInitialized) { typedef itk::SimpleMemberCommand< QmitkPartialVolumeAnalysisView > ITKCommandType; ITKCommandType::Pointer initializationCommand; initializationCommand = ITKCommandType::New(); // set the callback function of the member command initializationCommand->SetCallbackFunction( this, &QmitkPartialVolumeAnalysisView::PlanarFigureInitialized ); // add an observer m_InitializedObserverTag = selectedPlanar->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand ); } m_Controls->m_SelectedMaskLabel->setText( m_SelectedPlanarFigureNodes->GetNode()->GetName().c_str() ); PlanarFigureFocus(node); } } //mask if(isMask && selectedImage->GetDimension()==3) { if(selectedImage != m_SelectedImage.GetPointer()) { somethingChanged = true; if ( (m_SelectedImageMask.IsNotNull()) && (m_ImageMaskObserverTag >= 0) ) { m_SelectedImageMask->RemoveObserver( m_ImageMaskObserverTag ); m_ImageMaskObserverTag = -1; } m_SelectedMaskNode = node; m_SelectedImageMask = selectedImage; m_SelectedPlanarFigure = NULL; m_SelectedPlanarFigureNodes->RemoveAllNodes(); m_ImageMaskObserverTag = m_SelectedImageMask->AddObserver( itk::ModifiedEvent(), changeListener ); m_Controls->m_SelectedMaskLabel->setText( m_SelectedMaskNode->GetName().c_str() ); } } //tensor image if(isTensorImage && selectedTensorImage->GetDimension()==3) { if(selectedImage != m_SelectedImage.GetPointer()) { somethingChanged = true; if ( (m_SelectedImage.IsNotNull()) && (m_ImageObserverTag >= 0) ) { m_SelectedImage->RemoveObserver( m_ImageObserverTag ); m_ImageObserverTag = -1; } *m_SelectedImageNodes = node; m_SelectedImage = selectedImage; m_IsTensorImage = true; ExtractTensorImages(selectedImage); // Add change listeners to selected objects m_ImageObserverTag = m_SelectedImage->AddObserver( itk::ModifiedEvent(), changeListener ); m_Controls->m_SimilarAnglesFrame->setVisible(true); m_Controls->m_SimilarAnglesLabel->setVisible(true); m_Controls->m_SelectedImageLabel->setText( m_SelectedImageNodes->GetNode()->GetName().c_str() ); } } } if(somethingChanged) { this->SetMeasurementInfoToRenderWindow(""); if(m_SelectedPlanarFigure.IsNull() && m_SelectedImageMask.IsNull() ) { m_Controls->m_SelectedMaskLabel->setText( "None" ); m_Controls->m_ResampleOptionsFrame->setEnabled(false); m_Controls->m_HistogramWidget->setEnabled(false); m_Controls->m_ClassSelector->setEnabled(false); m_Controls->m_DisplayHistogramCheckbox->setEnabled(false); m_Controls->m_AdvancedCheckbox->setEnabled(false); m_Controls->frame_7->setEnabled(false); } else { m_Controls->m_ResampleOptionsFrame->setEnabled(true); m_Controls->m_HistogramWidget->setEnabled(true); m_Controls->m_ClassSelector->setEnabled(true); m_Controls->m_DisplayHistogramCheckbox->setEnabled(true); m_Controls->m_AdvancedCheckbox->setEnabled(true); m_Controls->frame_7->setEnabled(true); } // Clear statistics / histogram GUI if nothing is selected if ( m_SelectedImage.IsNull() ) { m_Controls->m_PlanarFigureButtonsFrame->setEnabled(false); m_Controls->m_OpacityFrame->setEnabled(false); m_Controls->m_SelectedImageLabel->setText( "None" ); } else { m_Controls->m_PlanarFigureButtonsFrame->setEnabled(true); m_Controls->m_OpacityFrame->setEnabled(true); } if( m_SelectedImage.IsNull() || (m_SelectedPlanarFigure.IsNull() && m_SelectedImageMask.IsNull()) ) { m_Controls->m_HistogramWidget->ClearItemModel(); m_CurrentStatisticsValid = false; m_Controls->m_ErrorMessageLabel->hide(); } else { this->RequestStatisticsUpdate(); } } } void QmitkPartialVolumeAnalysisView::ShowClusteringResults() { typedef itk::Image MaskImageType; mitk::Image::Pointer mask = 0; MaskImageType::Pointer itkmask = 0; if(m_IsTensorImage && m_Controls->m_SimilarAnglesSlider->value() != 0) { typedef itk::Image AngularErrorImageType; typedef mitk::ImageToItk CastType; CastType::Pointer caster = CastType::New(); caster->SetInput(m_AngularErrorImage); caster->Update(); typedef itk::BinaryThresholdImageFilter< AngularErrorImageType, MaskImageType > ThreshType; ThreshType::Pointer thresh = ThreshType::New(); thresh->SetUpperThreshold((90-m_Controls->m_SimilarAnglesSlider->value())*(PVA_PI/180.0)); thresh->SetInsideValue(1.0); thresh->SetInput(caster->GetOutput()); thresh->Update(); itkmask = thresh->GetOutput(); mask = mitk::Image::New(); mask->InitializeByItk(itkmask.GetPointer()); mask->SetVolume(itkmask->GetBufferPointer()); // GetDefaultDataStorage()->Remove(m_newnode); // m_newnode = mitk::DataNode::New(); // m_newnode->SetData(mask); // m_newnode->SetName("masking node"); // m_newnode->SetIntProperty( "layer", 1002 ); // GetDefaultDataStorage()->Add(m_newnode, m_SelectedImageNodes->GetNode()); } mitk::Image::Pointer clusteredImage; ClusteringType::Pointer clusterer = ClusteringType::New(); if(m_QuantifyClass==3) { if(m_IsTensorImage) { double *green_fa, *green_rd, *green_ad, *green_md; //double *greengray_fa, *greengray_rd, *greengray_ad, *greengray_md; double *gray_fa, *gray_rd, *gray_ad, *gray_md; //double *redgray_fa, *redgray_rd, *redgray_ad, *redgray_md; double *red_fa, *red_rd, *red_ad, *red_md; mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(0); mitk::Image::ConstPointer imgToCluster = tmpImg; red_fa = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->r, mask); green_fa = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->g, mask); gray_fa = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->b, mask); tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(3); mitk::Image::ConstPointer imgToCluster3 = tmpImg; red_rd = clusterer->PerformQuantification(imgToCluster3, m_CurrentRGBClusteringResults->rgbChannels->r, mask); green_rd = clusterer->PerformQuantification(imgToCluster3, m_CurrentRGBClusteringResults->rgbChannels->g, mask); gray_rd = clusterer->PerformQuantification(imgToCluster3, m_CurrentRGBClusteringResults->rgbChannels->b, mask); tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(4); mitk::Image::ConstPointer imgToCluster4 = tmpImg; red_ad = clusterer->PerformQuantification(imgToCluster4, m_CurrentRGBClusteringResults->rgbChannels->r, mask); green_ad = clusterer->PerformQuantification(imgToCluster4, m_CurrentRGBClusteringResults->rgbChannels->g, mask); gray_ad = clusterer->PerformQuantification(imgToCluster4, m_CurrentRGBClusteringResults->rgbChannels->b, mask); tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(5); mitk::Image::ConstPointer imgToCluster5 = tmpImg; red_md = clusterer->PerformQuantification(imgToCluster5, m_CurrentRGBClusteringResults->rgbChannels->r, mask); green_md = clusterer->PerformQuantification(imgToCluster5, m_CurrentRGBClusteringResults->rgbChannels->g, mask); gray_md = clusterer->PerformQuantification(imgToCluster5, m_CurrentRGBClusteringResults->rgbChannels->b, mask); // clipboard QString clipboardText("FA\t%1\t%2\t\t%3\t%4\t\t%5\t%6\t"); clipboardText = clipboardText .arg(red_fa[0]).arg(red_fa[1]) .arg(gray_fa[0]).arg(gray_fa[1]) .arg(green_fa[0]).arg(green_fa[1]); QString clipboardText3("RD\t%1\t%2\t\t%3\t%4\t\t%5\t%6\t"); clipboardText3 = clipboardText3 .arg(red_rd[0]).arg(red_rd[1]) .arg(gray_rd[0]).arg(gray_rd[1]) .arg(green_rd[0]).arg(green_rd[1]); QString clipboardText4("AD\t%1\t%2\t\t%3\t%4\t\t%5\t%6\t"); clipboardText4 = clipboardText4 .arg(red_ad[0]).arg(red_ad[1]) .arg(gray_ad[0]).arg(gray_ad[1]) .arg(green_ad[0]).arg(green_ad[1]); QString clipboardText5("MD\t%1\t%2\t\t%3\t%4\t\t%5\t%6"); clipboardText5 = clipboardText5 .arg(red_md[0]).arg(red_md[1]) .arg(gray_md[0]).arg(gray_md[1]) .arg(green_md[0]).arg(green_md[1]); QApplication::clipboard()->setText(clipboardText+clipboardText3+clipboardText4+clipboardText5, QClipboard::Clipboard); // now paint infos also on renderwindow QString plainInfoText("%1 %2 %3 \n"); plainInfoText = plainInfoText .arg("Red ", 20) .arg("Gray ", 20) .arg("Green", 20); QString plainInfoText0("FA:%1 ± %2%3 ± %4%5 ± %6\n"); plainInfoText0 = plainInfoText0 .arg(red_fa[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(red_fa[1], -10, 'g', 2, QLatin1Char( ' ' )) .arg(gray_fa[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(gray_fa[1], -10, 'g', 2, QLatin1Char( ' ' )) .arg(green_fa[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(green_fa[1], -10, 'g', 2, QLatin1Char( ' ' )); QString plainInfoText3("RDx10³:%1 ± %2%3 ± %4%5 ± %6\n"); plainInfoText3 = plainInfoText3 .arg(1000.0 * red_rd[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_rd[1], -10, 'g', 2, QLatin1Char( ' ' )) .arg(1000.0 * gray_rd[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * gray_rd[1], -10, 'g', 2, QLatin1Char( ' ' )) .arg(1000.0 * green_rd[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * green_rd[1], -10, 'g', 2, QLatin1Char( ' ' )); QString plainInfoText4("ADx10³:%1 ± %2%3 ± %4%5 ± %6\n"); plainInfoText4 = plainInfoText4 .arg(1000.0 * red_ad[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_ad[1], -10, 'g', 2, QLatin1Char( ' ' )) .arg(1000.0 * gray_ad[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * gray_ad[1], -10, 'g', 2, QLatin1Char( ' ' )) .arg(1000.0 * green_ad[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * green_ad[1], -10, 'g', 2, QLatin1Char( ' ' )); QString plainInfoText5("MDx10³:%1 ± %2%3 ± %4%5 ± %6"); plainInfoText5 = plainInfoText5 .arg(1000.0 * red_md[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_md[1], -10, 'g', 2, QLatin1Char( ' ' )) .arg(1000.0 * gray_md[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * gray_md[1], -10, 'g', 2, QLatin1Char( ' ' )) .arg(1000.0 * green_md[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * green_md[1], -10, 'g', 2, QLatin1Char( ' ' )); this->SetMeasurementInfoToRenderWindow(plainInfoText+plainInfoText0+plainInfoText3+plainInfoText4+plainInfoText5); } else { double* green; double* gray; double* red; mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalImage(); mitk::Image::ConstPointer imgToCluster = tmpImg; red = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->r); green = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->g); gray = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->b); // clipboard QString clipboardText("%1\t%2\t\t%3\t%4\t\t%5\t%6"); clipboardText = clipboardText.arg(red[0]).arg(red[1]) .arg(gray[0]).arg(gray[1]) .arg(green[0]).arg(green[1]); QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard); // now paint infos also on renderwindow QString plainInfoText("Red: %1 ± %2\nGray: %3 ± %4\nGreen: %5 ± %6"); plainInfoText = plainInfoText.arg(red[0]).arg(red[1]) .arg(gray[0]).arg(gray[1]) .arg(green[0]).arg(green[1]); this->SetMeasurementInfoToRenderWindow(plainInfoText); } clusteredImage = m_CurrentRGBClusteringResults->rgb; } else { if(m_IsTensorImage) { double *red_fa, *red_rd, *red_ad, *red_md; mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(0); mitk::Image::ConstPointer imgToCluster = tmpImg; red_fa = clusterer->PerformQuantification(imgToCluster, m_CurrentPerformClusteringResults->clusteredImage, mask); tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(3); mitk::Image::ConstPointer imgToCluster3 = tmpImg; red_rd = clusterer->PerformQuantification(imgToCluster3, m_CurrentPerformClusteringResults->clusteredImage, mask); tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(4); mitk::Image::ConstPointer imgToCluster4 = tmpImg; red_ad = clusterer->PerformQuantification(imgToCluster4, m_CurrentPerformClusteringResults->clusteredImage, mask); tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(5); mitk::Image::ConstPointer imgToCluster5 = tmpImg; red_md = clusterer->PerformQuantification(imgToCluster5, m_CurrentPerformClusteringResults->clusteredImage, mask); // clipboard QString clipboardText("FA\t%1\t%2\t"); clipboardText = clipboardText .arg(red_fa[0]).arg(red_fa[1]); QString clipboardText3("RD\t%1\t%2\t"); clipboardText3 = clipboardText3 .arg(red_rd[0]).arg(red_rd[1]); QString clipboardText4("AD\t%1\t%2\t"); clipboardText4 = clipboardText4 .arg(red_ad[0]).arg(red_ad[1]); QString clipboardText5("MD\t%1\t%2\t"); clipboardText5 = clipboardText5 .arg(red_md[0]).arg(red_md[1]); QApplication::clipboard()->setText(clipboardText+clipboardText3+clipboardText4+clipboardText5, QClipboard::Clipboard); // now paint infos also on renderwindow QString plainInfoText("%1 \n"); plainInfoText = plainInfoText .arg("Red ", 20); QString plainInfoText0("FA:%1 ± %2\n"); plainInfoText0 = plainInfoText0 .arg(red_fa[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(red_fa[1], -10, 'g', 2, QLatin1Char( ' ' )); QString plainInfoText3("RDx10³:%1 ± %2\n"); plainInfoText3 = plainInfoText3 .arg(1000.0 * red_rd[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_rd[1], -10, 'g', 2, QLatin1Char( ' ' )); QString plainInfoText4("ADx10³:%1 ± %2\n"); plainInfoText4 = plainInfoText4 .arg(1000.0 * red_ad[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_ad[1], -10, 'g', 2, QLatin1Char( ' ' )); QString plainInfoText5("MDx10³:%1 ± %2"); plainInfoText5 = plainInfoText5 .arg(1000.0 * red_md[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_md[1], -10, 'g', 2, QLatin1Char( ' ' )); this->SetMeasurementInfoToRenderWindow(plainInfoText+plainInfoText0+plainInfoText3+plainInfoText4+plainInfoText5); } else { double* quant; mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalImage(); mitk::Image::ConstPointer imgToCluster = tmpImg; quant = clusterer->PerformQuantification(imgToCluster, m_CurrentPerformClusteringResults->clusteredImage); // clipboard QString clipboardText("%1\t%2"); clipboardText = clipboardText.arg(quant[0]).arg(quant[1]); QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard); // now paint infos also on renderwindow QString plainInfoText("Measurement: %1 ± %2"); plainInfoText = plainInfoText.arg(quant[0]).arg(quant[1]); this->SetMeasurementInfoToRenderWindow(plainInfoText); } clusteredImage = m_CurrentPerformClusteringResults->displayImage; } if(mask.IsNotNull()) { typedef itk::Image,3> RGBImageType; typedef mitk::ImageToItk ClusterCasterType; ClusterCasterType::Pointer clCaster = ClusterCasterType::New(); clCaster->SetInput(clusteredImage); clCaster->Update(); clCaster->GetOutput(); typedef itk::MaskImageFilter< RGBImageType, MaskImageType, RGBImageType > MaskType; MaskType::Pointer masker = MaskType::New(); masker->SetInput1(clCaster->GetOutput()); masker->SetInput2(itkmask); masker->Update(); clusteredImage = mitk::Image::New(); clusteredImage->InitializeByItk(masker->GetOutput()); clusteredImage->SetVolume(masker->GetOutput()->GetBufferPointer()); } if(m_ClusteringResult.IsNotNull()) { GetDefaultDataStorage()->Remove(m_ClusteringResult); } m_ClusteringResult = mitk::DataNode::New(); m_ClusteringResult->SetBoolProperty("helper object", true); m_ClusteringResult->SetIntProperty( "layer", 1000 ); m_ClusteringResult->SetBoolProperty("texture interpolation", m_TexIsOn); m_ClusteringResult->SetData(clusteredImage); m_ClusteringResult->SetName("Clusterprobs"); GetDefaultDataStorage()->Add(m_ClusteringResult, m_SelectedImageNodes->GetNode()); if(m_SelectedPlanarFigure.IsNotNull() && m_SelectedPlanarFigureNodes->GetNode().IsNotNull()) { m_SelectedPlanarFigureNodes->GetNode()->SetIntProperty( "layer", 1001 ); } GetActiveStdMultiWidget()->RequestUpdate(); } void QmitkPartialVolumeAnalysisView::UpdateStatistics() { MITK_INFO << "UpdateStatistics()"; if(!m_CurrentFigureNodeInitialized && m_SelectedPlanarFigure.IsNotNull()) { MITK_INFO << "Selected planar figure not initialized. No stats calculation performed."; return; } // Remove any cached images that are no longer referenced elsewhere this->RemoveOrphanImages(); QmitkStdMultiWidget *multiWidget = this->GetActiveStdMultiWidget(); if ( multiWidget == NULL ) { return; } if ( m_SelectedImage.IsNotNull() ) { // Check if a the selected image is a multi-channel image. If yes, statistics // cannot be calculated currently. if ( !m_IsTensorImage && m_SelectedImage->GetPixelType().GetNumberOfComponents() > 1 ) { std::stringstream message; message << "Non-tensor multi-component images not supported."; m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() ); m_Controls->m_ErrorMessageLabel->show(); m_Controls->m_HistogramWidget->ClearItemModel(); m_CurrentStatisticsValid = false; return; } // Retrieve HistogramStatisticsCalculator from has map (or create a new one // for this image if non-existant) PartialVolumeAnalysisMapType::iterator it = m_PartialVolumeAnalysisMap.find( m_SelectedImage ); if ( it != m_PartialVolumeAnalysisMap.end() ) { m_CurrentStatisticsCalculator = it->second; MITK_INFO << "Retrieving StatisticsCalculator"; } else { m_CurrentStatisticsCalculator = mitk::PartialVolumeAnalysisHistogramCalculator::New(); m_CurrentStatisticsCalculator->SetPlanarFigureThickness(m_Controls->m_PlanarFiguresThickness->value()); if(m_IsTensorImage) { m_CurrentStatisticsCalculator->SetImage( m_CAImage ); m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_FAImage ); m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_DirectionComp1Image ); m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_DirectionComp2Image ); m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_RDImage ); m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_ADImage ); m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_MDImage ); } else { m_CurrentStatisticsCalculator->SetImage( m_SelectedImage ); } m_PartialVolumeAnalysisMap[m_SelectedImage] = m_CurrentStatisticsCalculator; MITK_INFO << "Creating StatisticsCalculator"; } std::string maskName; std::string maskType; unsigned int maskDimension; if ( m_SelectedImageMask.IsNotNull() ) { mitk::PixelType pixelType = m_SelectedImageMask->GetPixelType(); std::cout << pixelType.GetItkTypeAsString() << std::endl; if(pixelType.GetBitsPerComponent() == 16) { //convert from short to uchar typedef itk::Image ShortImageType; typedef itk::Image CharImageType; CharImageType::Pointer charImage; ShortImageType::Pointer shortImage; mitk::CastToItkImage(m_SelectedImageMask, shortImage); typedef itk::CastImageFilter ImageCasterType; ImageCasterType::Pointer caster = ImageCasterType::New(); caster->SetInput( shortImage ); caster->Update(); charImage = caster->GetOutput(); mitk::CastToMitkImage(charImage, m_SelectedImageMask); } m_CurrentStatisticsCalculator->SetImageMask( m_SelectedImageMask ); m_CurrentStatisticsCalculator->SetMaskingModeToImage(); maskName = m_SelectedMaskNode->GetName(); maskType = m_SelectedImageMask->GetNameOfClass(); maskDimension = 3; std::stringstream maskLabel; maskLabel << maskName; if ( maskDimension > 0 ) { maskLabel << " [" << maskDimension << "D " << maskType << "]"; } m_Controls->m_SelectedMaskLabel->setText( maskLabel.str().c_str() ); } else if ( m_SelectedPlanarFigure.IsNotNull() && m_SelectedPlanarFigureNodes->GetNode().IsNotNull()) { m_CurrentStatisticsCalculator->SetPlanarFigure( m_SelectedPlanarFigure ); m_CurrentStatisticsCalculator->SetMaskingModeToPlanarFigure(); maskName = m_SelectedPlanarFigureNodes->GetNode()->GetName(); maskType = m_SelectedPlanarFigure->GetNameOfClass(); maskDimension = 2; } else { m_CurrentStatisticsCalculator->SetMaskingModeToNone(); maskName = "None"; maskType = ""; maskDimension = 0; } bool statisticsChanged = false; bool statisticsCalculationSuccessful = false; // Initialize progress bar mitk::ProgressBar::GetInstance()->AddStepsToDo( 100 ); // Install listener for progress events and initialize progress bar typedef itk::SimpleMemberCommand< QmitkPartialVolumeAnalysisView > ITKCommandType; ITKCommandType::Pointer progressListener; progressListener = ITKCommandType::New(); progressListener->SetCallbackFunction( this, &QmitkPartialVolumeAnalysisView::UpdateProgressBar ); unsigned long progressObserverTag = m_CurrentStatisticsCalculator ->AddObserver( itk::ProgressEvent(), progressListener ); ClusteringType::ParamsType *cparams = 0; ClusteringType::ClusterResultType *cresult = 0; ClusteringType::HistType *chist = 0; try { m_CurrentStatisticsCalculator->SetNumberOfBins(m_Controls->m_NumberBins->text().toInt()); m_CurrentStatisticsCalculator->SetUpsamplingFactor(m_Controls->m_Upsampling->text().toDouble()); m_CurrentStatisticsCalculator->SetGaussianSigma(m_Controls->m_GaussianSigma->text().toDouble()); // Compute statistics statisticsChanged = m_CurrentStatisticsCalculator->ComputeStatistics( ); mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalImage(); mitk::Image::ConstPointer imgToCluster = tmpImg; if(imgToCluster.IsNotNull()) { // perform clustering const HistogramType *histogram = m_CurrentStatisticsCalculator->GetHistogram( ); if(histogram != NULL) { ClusteringType::Pointer clusterer = ClusteringType::New(); clusterer->SetStepsNumIntegration(200); clusterer->SetMaxIt(1000); mitk::Image::Pointer pFiberImg; if(m_QuantifyClass==3) { if(m_Controls->m_Quantiles->isChecked()) { m_CurrentRGBClusteringResults = clusterer->PerformRGBQuantiles(imgToCluster, histogram, m_Controls->m_q1->value(),m_Controls->m_q2->value()); } else { m_CurrentRGBClusteringResults = clusterer->PerformRGBClustering(imgToCluster, histogram); } pFiberImg = m_CurrentRGBClusteringResults->rgbChannels->r; cparams = m_CurrentRGBClusteringResults->params; cresult = m_CurrentRGBClusteringResults->result; chist = m_CurrentRGBClusteringResults->hist; } else { if(m_Controls->m_Quantiles->isChecked()) { m_CurrentPerformClusteringResults = clusterer->PerformQuantiles(imgToCluster, histogram, m_Controls->m_q1->value(),m_Controls->m_q2->value()); } else { m_CurrentPerformClusteringResults = clusterer->PerformClustering(imgToCluster, histogram, m_QuantifyClass); } pFiberImg = m_CurrentPerformClusteringResults->clusteredImage; cparams = m_CurrentPerformClusteringResults->params; cresult = m_CurrentPerformClusteringResults->result; chist = m_CurrentPerformClusteringResults->hist; } if(m_IsTensorImage) { m_AngularErrorImage = clusterer->CaculateAngularErrorImage( m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(1), m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(2), pFiberImg); // GetDefaultDataStorage()->Remove(m_newnode2); // m_newnode2 = mitk::DataNode::New(); // m_newnode2->SetData(m_AngularErrorImage); // m_newnode2->SetName(("AngularError")); // m_newnode2->SetIntProperty( "layer", 1003 ); // GetDefaultDataStorage()->Add(m_newnode2, m_SelectedImageNodes->GetNode()); // newnode = mitk::DataNode::New(); // newnode->SetData(m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(1)); // newnode->SetName(("Comp1")); // GetDefaultDataStorage()->Add(newnode, m_SelectedImageNodes->GetNode()); // newnode = mitk::DataNode::New(); // newnode->SetData(m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(2)); // newnode->SetName(("Comp2")); // GetDefaultDataStorage()->Add(newnode, m_SelectedImageNodes->GetNode()); } ShowClusteringResults(); } } statisticsCalculationSuccessful = true; } catch ( const std::runtime_error &e ) { // In case of exception, print error message on GUI std::stringstream message; message << e.what(); m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() ); m_Controls->m_ErrorMessageLabel->show(); } catch ( const std::exception &e ) { MITK_ERROR << "Caught exception: " << e.what(); // In case of exception, print error message on GUI std::stringstream message; message << "Error in calculating histogram: " << e.what(); m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() ); m_Controls->m_ErrorMessageLabel->show(); } m_CurrentStatisticsCalculator->RemoveObserver( progressObserverTag ); // Make sure that progress bar closes mitk::ProgressBar::GetInstance()->Progress( 100 ); if ( statisticsCalculationSuccessful ) { if ( statisticsChanged ) { // Do not show any error messages m_Controls->m_ErrorMessageLabel->hide(); m_CurrentStatisticsValid = true; } // m_Controls->m_HistogramWidget->SetHistogramModeToDirectHistogram(); m_Controls->m_HistogramWidget->SetParameters( cparams, cresult, chist ); // m_Controls->m_HistogramWidget->UpdateItemModelFromHistogram(); } else { m_Controls->m_SelectedMaskLabel->setText( "None" ); // Clear statistics and histogram m_Controls->m_HistogramWidget->ClearItemModel(); m_CurrentStatisticsValid = false; // If a (non-closed) PlanarFigure is selected, display a line profile widget if ( m_SelectedPlanarFigure.IsNotNull() ) { // TODO: enable line profile widget //m_Controls->m_StatisticsWidgetStack->setCurrentIndex( 1 ); //m_Controls->m_LineProfileWidget->SetImage( m_SelectedImage ); //m_Controls->m_LineProfileWidget->SetPlanarFigure( m_SelectedPlanarFigure ); //m_Controls->m_LineProfileWidget->UpdateItemModelFromPath(); } } } } void QmitkPartialVolumeAnalysisView::SetMeasurementInfoToRenderWindow(const QString& text) { FindRenderWindow(m_SelectedPlanarFigureNodes->GetNode()); if(m_LastRenderWindow != m_SelectedRenderWindow) { if(m_LastRenderWindow) { QObject::disconnect( m_LastRenderWindow, SIGNAL( destroyed(QObject*) ) , this, SLOT( OnRenderWindowDelete(QObject*) ) ); } m_LastRenderWindow = m_SelectedRenderWindow; if(m_LastRenderWindow) { QObject::connect( m_LastRenderWindow, SIGNAL( destroyed(QObject*) ) , this, SLOT( OnRenderWindowDelete(QObject*) ) ); } } if(m_LastRenderWindow && m_SelectedPlanarFigureNodes->GetNode().IsNotNull()) { if (!text.isEmpty()) { m_MeasurementInfoAnnotation->SetText(1, text.toLatin1().data()); mitk::VtkLayerController::GetInstance(m_LastRenderWindow->GetRenderWindow())->InsertForegroundRenderer( m_MeasurementInfoRenderer, true); } else { if (mitk::VtkLayerController::GetInstance( m_LastRenderWindow->GetRenderWindow()) ->IsRendererInserted( m_MeasurementInfoRenderer)) mitk::VtkLayerController::GetInstance(m_LastRenderWindow->GetRenderWindow())->RemoveRenderer( m_MeasurementInfoRenderer); } } else { if (!text.isEmpty()) { m_MeasurementInfoAnnotation->SetText(1, text.toLatin1().data()); mitk::VtkLayerController::GetInstance(this->GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderWindow())->InsertForegroundRenderer( m_MeasurementInfoRenderer, true); } else { if (mitk::VtkLayerController::GetInstance( this->GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderWindow()) ->IsRendererInserted( m_MeasurementInfoRenderer)) mitk::VtkLayerController::GetInstance(this->GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderWindow())->RemoveRenderer( m_MeasurementInfoRenderer); } } } void QmitkPartialVolumeAnalysisView::UpdateProgressBar() { mitk::ProgressBar::GetInstance()->Progress(); } void QmitkPartialVolumeAnalysisView::RequestStatisticsUpdate() { if ( !m_StatisticsUpdatePending ) { QApplication::postEvent( this, new QmitkRequestStatisticsUpdateEvent ); m_StatisticsUpdatePending = true; } } void QmitkPartialVolumeAnalysisView::RemoveOrphanImages() { PartialVolumeAnalysisMapType::iterator it = m_PartialVolumeAnalysisMap.begin(); while ( it != m_PartialVolumeAnalysisMap.end() ) { mitk::Image *image = it->first; mitk::PartialVolumeAnalysisHistogramCalculator *calculator = it->second; ++it; mitk::NodePredicateData::Pointer hasImage = mitk::NodePredicateData::New( image ); if ( this->GetDefaultDataStorage()->GetNode( hasImage ) == NULL ) { if ( m_SelectedImage == image ) { m_SelectedImage = NULL; m_SelectedImageNodes->RemoveAllNodes(); } if ( m_CurrentStatisticsCalculator == calculator ) { m_CurrentStatisticsCalculator = NULL; } m_PartialVolumeAnalysisMap.erase( image ); it = m_PartialVolumeAnalysisMap.begin(); } } } void QmitkPartialVolumeAnalysisView::ExtractTensorImages( mitk::Image::ConstPointer tensorimage) { typedef itk::Image< itk::DiffusionTensor3D, 3> TensorImageType; typedef mitk::ImageToItk CastType; CastType::Pointer caster = CastType::New(); caster->SetInput(tensorimage); caster->Update(); TensorImageType::Pointer image = caster->GetOutput(); typedef itk::TensorDerivedMeasurementsFilter MeasurementsType; MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(image ); measurementsCalculator->SetMeasure(MeasurementsType::FA); measurementsCalculator->Update(); MeasurementsType::OutputImageType::Pointer fa = measurementsCalculator->GetOutput(); m_FAImage = mitk::Image::New(); m_FAImage->InitializeByItk(fa.GetPointer()); m_FAImage->SetVolume(fa->GetBufferPointer()); // mitk::DataNode::Pointer node = mitk::DataNode::New(); // node->SetData(m_FAImage); // GetDefaultDataStorage()->Add(node); measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(image ); measurementsCalculator->SetMeasure(MeasurementsType::CA); measurementsCalculator->Update(); MeasurementsType::OutputImageType::Pointer ca = measurementsCalculator->GetOutput(); m_CAImage = mitk::Image::New(); m_CAImage->InitializeByItk(ca.GetPointer()); m_CAImage->SetVolume(ca->GetBufferPointer()); // node = mitk::DataNode::New(); // node->SetData(m_CAImage); // GetDefaultDataStorage()->Add(node); measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(image ); measurementsCalculator->SetMeasure(MeasurementsType::RD); measurementsCalculator->Update(); MeasurementsType::OutputImageType::Pointer rd = measurementsCalculator->GetOutput(); m_RDImage = mitk::Image::New(); m_RDImage->InitializeByItk(rd.GetPointer()); m_RDImage->SetVolume(rd->GetBufferPointer()); // node = mitk::DataNode::New(); // node->SetData(m_CAImage); // GetDefaultDataStorage()->Add(node); measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(image ); measurementsCalculator->SetMeasure(MeasurementsType::AD); measurementsCalculator->Update(); MeasurementsType::OutputImageType::Pointer ad = measurementsCalculator->GetOutput(); m_ADImage = mitk::Image::New(); m_ADImage->InitializeByItk(ad.GetPointer()); m_ADImage->SetVolume(ad->GetBufferPointer()); // node = mitk::DataNode::New(); // node->SetData(m_CAImage); // GetDefaultDataStorage()->Add(node); measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(image ); measurementsCalculator->SetMeasure(MeasurementsType::RA); measurementsCalculator->Update(); MeasurementsType::OutputImageType::Pointer md = measurementsCalculator->GetOutput(); m_MDImage = mitk::Image::New(); m_MDImage->InitializeByItk(md.GetPointer()); m_MDImage->SetVolume(md->GetBufferPointer()); // node = mitk::DataNode::New(); // node->SetData(m_CAImage); // GetDefaultDataStorage()->Add(node); typedef DirectionsFilterType::OutputImageType DirImageType; DirectionsFilterType::Pointer dirFilter = DirectionsFilterType::New(); dirFilter->SetInput(image ); dirFilter->Update(); itk::ImageRegionIterator itd(dirFilter->GetOutput(), dirFilter->GetOutput()->GetLargestPossibleRegion()); itd = itd.Begin(); while( !itd.IsAtEnd() ) { DirImageType::PixelType direction = itd.Get(); direction[0] = fabs(direction[0]); direction[1] = fabs(direction[1]); direction[2] = fabs(direction[2]); itd.Set(direction); ++itd; } typedef itk::CartesianToPolarVectorImageFilter< DirImageType, DirImageType, true> C2PFilterType; C2PFilterType::Pointer cpFilter = C2PFilterType::New(); cpFilter->SetInput(dirFilter->GetOutput()); cpFilter->Update(); DirImageType::Pointer dir = cpFilter->GetOutput(); typedef itk::Image CompImageType; CompImageType::Pointer comp1 = CompImageType::New(); comp1->SetSpacing( dir->GetSpacing() ); // Set the image spacing comp1->SetOrigin( dir->GetOrigin() ); // Set the image origin comp1->SetDirection( dir->GetDirection() ); // Set the image direction comp1->SetRegions( dir->GetLargestPossibleRegion() ); comp1->Allocate(); CompImageType::Pointer comp2 = CompImageType::New(); comp2->SetSpacing( dir->GetSpacing() ); // Set the image spacing comp2->SetOrigin( dir->GetOrigin() ); // Set the image origin comp2->SetDirection( dir->GetDirection() ); // Set the image direction comp2->SetRegions( dir->GetLargestPossibleRegion() ); comp2->Allocate(); itk::ImageRegionConstIterator it(dir, dir->GetLargestPossibleRegion()); itk::ImageRegionIterator it1(comp1, comp1->GetLargestPossibleRegion()); itk::ImageRegionIterator it2(comp2, comp2->GetLargestPossibleRegion()); it = it.Begin(); it1 = it1.Begin(); it2 = it2.Begin(); while( !it.IsAtEnd() ) { it1.Set(it.Get()[1]); it2.Set(it.Get()[2]); ++it; ++it1; ++it2; } m_DirectionComp1Image = mitk::Image::New(); m_DirectionComp1Image->InitializeByItk(comp1.GetPointer()); m_DirectionComp1Image->SetVolume(comp1->GetBufferPointer()); m_DirectionComp2Image = mitk::Image::New(); m_DirectionComp2Image->InitializeByItk(comp2.GetPointer()); m_DirectionComp2Image->SetVolume(comp2->GetBufferPointer()); } void QmitkPartialVolumeAnalysisView::OnRenderWindowDelete(QObject * obj) { if(obj == m_LastRenderWindow) m_LastRenderWindow = 0; + if(obj == m_SelectedRenderWindow) + m_SelectedRenderWindow = 0; } bool QmitkPartialVolumeAnalysisView::event( QEvent *event ) { if ( event->type() == (QEvent::Type) QmitkRequestStatisticsUpdateEvent::StatisticsUpdateRequest ) { // Update statistics m_StatisticsUpdatePending = false; this->UpdateStatistics(); return true; } return false; } void QmitkPartialVolumeAnalysisView::Visible() { this->OnSelectionChanged( this->GetDataManagerSelection() ); } bool QmitkPartialVolumeAnalysisView::IsExclusiveFunctionality() const { return true; } void QmitkPartialVolumeAnalysisView::Activated() { this->GetActiveStdMultiWidget()->SetWidgetPlanesVisibility(false); //this->GetActiveStdMultiWidget()->GetRenderWindow1()->FullScreenMode(true); mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDefaultDataStorage()->GetAll(); mitk::DataNode* node = 0; mitk::PlanarFigure* figure = 0; mitk::PlanarFigureInteractor::Pointer figureInteractor = 0; // finally add all nodes to the model for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End() ; it++) { node = const_cast(it->Value().GetPointer()); figure = dynamic_cast(node->GetData()); if(figure) { figureInteractor = dynamic_cast(node->GetInteractor()); if(figureInteractor.IsNull()) figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", node); mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor); } } m_Visible = true; } void QmitkPartialVolumeAnalysisView::Deactivated() { this->GetActiveStdMultiWidget()->SetWidgetPlanesVisibility(true); //this->GetActiveStdMultiWidget()->GetRenderWindow1()->FullScreenMode(false); this->SetMeasurementInfoToRenderWindow(""); mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDefaultDataStorage()->GetAll(); mitk::DataNode* node = 0; mitk::PlanarFigure* figure = 0; mitk::PlanarFigureInteractor::Pointer figureInteractor = 0; // finally add all nodes to the model for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End() ; it++) { node = const_cast(it->Value().GetPointer()); figure = dynamic_cast(node->GetData()); if(figure) { figureInteractor = dynamic_cast(node->GetInteractor()); if(figureInteractor) mitk::GlobalInteraction::GetInstance()->RemoveInteractor(figureInteractor); } } m_Visible = false; } void QmitkPartialVolumeAnalysisView::GreenRadio(bool checked) { if(checked) { m_Controls->m_PartialVolumeRadio->setChecked(false); m_Controls->m_BlueRadio->setChecked(false); m_Controls->m_AllRadio->setChecked(false); + m_Controls->m_ExportClusteringResultsButton->setEnabled(true); } m_QuantifyClass = 0; RequestStatisticsUpdate(); } void QmitkPartialVolumeAnalysisView::PartialVolumeRadio(bool checked) { if(checked) { m_Controls->m_GreenRadio->setChecked(false); m_Controls->m_BlueRadio->setChecked(false); m_Controls->m_AllRadio->setChecked(false); + m_Controls->m_ExportClusteringResultsButton->setEnabled(true); } m_QuantifyClass = 1; RequestStatisticsUpdate(); } void QmitkPartialVolumeAnalysisView::BlueRadio(bool checked) { if(checked) { m_Controls->m_PartialVolumeRadio->setChecked(false); m_Controls->m_GreenRadio->setChecked(false); m_Controls->m_AllRadio->setChecked(false); + m_Controls->m_ExportClusteringResultsButton->setEnabled(true); } m_QuantifyClass = 2; RequestStatisticsUpdate(); } void QmitkPartialVolumeAnalysisView::AllRadio(bool checked) { if(checked) { m_Controls->m_BlueRadio->setChecked(false); m_Controls->m_PartialVolumeRadio->setChecked(false); m_Controls->m_GreenRadio->setChecked(false); + m_Controls->m_ExportClusteringResultsButton->setEnabled(false); } m_QuantifyClass = 3; RequestStatisticsUpdate(); } void QmitkPartialVolumeAnalysisView::NumberBinsChangedSlider(int v ) { m_Controls->m_NumberBins->setText(QString("%1").arg(m_Controls->m_NumberBinsSlider->value()*5.0)); } void QmitkPartialVolumeAnalysisView::UpsamplingChangedSlider( int v) { m_Controls->m_Upsampling->setText(QString("%1").arg(m_Controls->m_UpsamplingSlider->value()/10.0)); } void QmitkPartialVolumeAnalysisView::GaussianSigmaChangedSlider(int v ) { m_Controls->m_GaussianSigma->setText(QString("%1").arg(m_Controls->m_GaussianSigmaSlider->value()/100.0)); } void QmitkPartialVolumeAnalysisView::SimilarAnglesChangedSlider(int v ) { m_Controls->m_SimilarAngles->setText(QString("%1°").arg(90-m_Controls->m_SimilarAnglesSlider->value())); ShowClusteringResults(); } void QmitkPartialVolumeAnalysisView::OpacityChangedSlider(int v ) { if(m_SelectedImageNodes->GetNode().IsNotNull()) { float opacImag = 1.0f-(v-5)/5.0f; opacImag = opacImag < 0 ? 0 : opacImag; m_SelectedImageNodes->GetNode()->SetFloatProperty("opacity", opacImag); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } if(m_ClusteringResult.IsNotNull()) { float opacClust = v/5.0f; opacClust = opacClust > 1 ? 1 : opacClust; m_ClusteringResult->SetFloatProperty("opacity", opacClust); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkPartialVolumeAnalysisView::NumberBinsReleasedSlider( ) { RequestStatisticsUpdate(); } void QmitkPartialVolumeAnalysisView::UpsamplingReleasedSlider( ) { RequestStatisticsUpdate(); } void QmitkPartialVolumeAnalysisView::GaussianSigmaReleasedSlider( ) { RequestStatisticsUpdate(); } void QmitkPartialVolumeAnalysisView::SimilarAnglesReleasedSlider( ) { } void QmitkPartialVolumeAnalysisView::ToClipBoard() { std::vector* > vals = m_Controls->m_HistogramWidget->m_Vals; QString clipboardText; for (std::vector* >::iterator it = vals.begin(); it != vals.end(); ++it) { for (std::vector::iterator it2 = (**it).begin(); it2 != (**it).end(); ++it2) { clipboardText.append(QString("%1 \t").arg(*it2)); } clipboardText.append(QString("\n")); } QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard); } void QmitkPartialVolumeAnalysisView::PropertyChanged(const mitk::DataNode* /*node*/, const mitk::BaseProperty* /*prop*/) { } void QmitkPartialVolumeAnalysisView::NodeChanged(const mitk::DataNode* /*node*/) { } void QmitkPartialVolumeAnalysisView::NodeRemoved(const mitk::DataNode* node) { + if (dynamic_cast(node->GetData())) + GetDefaultDataStorage()->Remove(m_ClusteringResult); if( node == m_SelectedPlanarFigureNodes->GetNode().GetPointer() || node == m_SelectedMaskNode.GetPointer() ) { this->Select(NULL,true,false); SetMeasurementInfoToRenderWindow(""); } if( node == m_SelectedImageNodes->GetNode().GetPointer() ) { this->Select(NULL,false,true); SetMeasurementInfoToRenderWindow(""); } } void QmitkPartialVolumeAnalysisView::NodeAddedInDataStorage(const mitk::DataNode* node) { if(!m_Visible) return; mitk::DataNode* nonConstNode = const_cast(node); mitk::PlanarFigure* figure = dynamic_cast(nonConstNode->GetData()); if(figure) { // set interactor for new node (if not already set) mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetInteractor()); if(figureInteractor.IsNull()) figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", nonConstNode); mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor); // remove uninitialized old planars if( m_SelectedPlanarFigureNodes->GetNode().IsNotNull() && m_CurrentFigureNodeInitialized == false ) { mitk::Interactor::Pointer oldInteractor = m_SelectedPlanarFigureNodes->GetNode()->GetInteractor(); if(oldInteractor.IsNotNull()) mitk::GlobalInteraction::GetInstance()->RemoveInteractor(oldInteractor); this->GetDefaultDataStorage()->Remove(m_SelectedPlanarFigureNodes->GetNode()); } } } void QmitkPartialVolumeAnalysisView::TextIntON() { if(m_ClusteringResult.IsNotNull()) { if(m_TexIsOn) { m_Controls->m_TextureIntON->setIcon(*m_IconTexOFF); } else { m_Controls->m_TextureIntON->setIcon(*m_IconTexON); } m_ClusteringResult->SetBoolProperty("texture interpolation", !m_TexIsOn); m_TexIsOn = !m_TexIsOn; GetActiveStdMultiWidget()->RequestUpdate(); } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisView.h index 6383dc7300..bbae16184c 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisView.h @@ -1,268 +1,270 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-05-28 20:08:26 +0200 (Do, 28 Mai 2009) $ Version: $Revision: 10185 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #if !defined(QmitkPartialVolumeAnalysisView_H__INCLUDED) #define QmitkPartialVolumeAnalysisView_H__INCLUDED #include "QmitkFunctionality.h" #include "ui_QmitkPartialVolumeAnalysisViewControls.h" // berry #include #include // itk #include #include "itkDiffusionTensorPrincipleDirectionImageFilter.h" +#include // qmitk #include "QmitkStepperAdapter.h" #include "QmitkRenderWindow.h" // mitk #include "mitkPartialVolumeAnalysisHistogramCalculator.h" #include "mitkPlanarLine.h" #include #include "mitkDataStorageSelection.h" #include // vtk #include #include #include //#include "itkProcessObject.h" /*! \brief QmitkPartialVolumeAnalysis \sa QmitkFunctionality \ingroup Functionalities */ class QmitkPartialVolumeAnalysisView : public QmitkFunctionality//, public itk::ProcessObject { Q_OBJECT public: /*! \ Convenient typedefs */ typedef mitk::DataStorage::SetOfObjects ConstVector; typedef ConstVector::ConstPointer ConstVectorPointer; typedef ConstVector::ConstIterator ConstVectorIterator; typedef mitk::PartialVolumeAnalysisHistogramCalculator HistogramCalculatorType; typedef HistogramCalculatorType::HistogramType HistogramType; typedef mitk::PartialVolumeAnalysisClusteringCalculator ClusteringType; typedef itk::DiffusionTensorPrincipleDirectionImageFilter DirectionsFilterType; /*! \brief default constructor */ QmitkPartialVolumeAnalysisView(QObject *parent=0, const char *name=0); /*! \brief default destructor */ virtual ~QmitkPartialVolumeAnalysisView(); /*! \brief method for creating the widget containing the application controls, like sliders, buttons etc. */ virtual void CreateQtPartControl(QWidget *parent); /*! \brief method for creating the connections of main and control widget */ virtual void CreateConnections(); bool IsExclusiveFunctionality() const; virtual bool event( QEvent *event ); void OnSelectionChanged( std::vector nodes ); virtual void Activated(); virtual void Deactivated(); bool AssertDrawingIsPossible(bool checked); virtual void NodeChanged(const mitk::DataNode* node); virtual void PropertyChanged(const mitk::DataNode* node, const mitk::BaseProperty* prop); virtual void NodeRemoved(const mitk::DataNode* node); virtual void NodeAddedInDataStorage(const mitk::DataNode* node); virtual void AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, const char *propertyKey = NULL, mitk::BaseProperty *property = NULL ); void PlanarFigureInitialized(); void PlanarFigureFocus(mitk::DataNode* node); void ShowClusteringResults(); static const std::string VIEW_ID; protected slots: void EstimateCircle(); void SetHistogramVisibility(); void SetAdvancedVisibility(); void NumberBinsChangedSlider(int v ); void UpsamplingChangedSlider( int v ); void GaussianSigmaChangedSlider( int v ); void SimilarAnglesChangedSlider(int v ); void OpacityChangedSlider(int v ); void NumberBinsReleasedSlider( ); void UpsamplingReleasedSlider( ); void GaussianSigmaReleasedSlider( ); void SimilarAnglesReleasedSlider( ); void ActionDrawEllipseTriggered(); void ActionDrawRectangleTriggered(); void ActionDrawPolygonTriggered(); void ToClipBoard(); void GreenRadio(bool checked); void PartialVolumeRadio(bool checked); void BlueRadio(bool checked); void AllRadio(bool checked); void OnRenderWindowDelete(QObject * obj); void TextIntON(); + void ExportClusteringResults(); protected: void StdMultiWidgetAvailable( QmitkStdMultiWidget& stdMultiWidget ); /** \brief Issues a request to update statistics by sending an event to the * Qt event processing queue. * * Statistics update should only be executed after program execution returns * to the Qt main loop. This mechanism also prevents multiple execution of * updates where only one is required.*/ void RequestStatisticsUpdate(); /** \brief Recalculate statistics for currently selected image and mask and * update the GUI. */ void UpdateStatistics(); /** \brief Listener for progress events to update progress bar. */ void UpdateProgressBar(); /** \brief Removes any cached images which are no longer referenced elsewhere. */ void RemoveOrphanImages(); void Select( mitk::DataNode::Pointer node, bool clearMaskOnFirstArgNULL=false, bool clearImageOnFirstArgNULL=false ); void Visible( ); void SetMeasurementInfoToRenderWindow(const QString& text); void FindRenderWindow(mitk::DataNode* node); void ExtractTensorImages( mitk::Image::ConstPointer tensorimage); typedef std::map< mitk::Image *, mitk::PartialVolumeAnalysisHistogramCalculator::Pointer > PartialVolumeAnalysisMapType; /*! * controls containing sliders for scrolling through the slices */ Ui::QmitkPartialVolumeAnalysisViewControls *m_Controls; QmitkStepperAdapter* m_TimeStepperAdapter; unsigned int m_CurrentTime; QString m_Clipboard; // result text rendering vtkRenderer * m_MeasurementInfoRenderer; vtkCornerAnnotation *m_MeasurementInfoAnnotation; // Image and mask data mitk::DataStorageSelection::Pointer m_SelectedImageNodes; mitk::Image::Pointer m_SelectedImage; mitk::DataNode::Pointer m_SelectedMaskNode; mitk::Image::Pointer m_SelectedImageMask; mitk::DataStorageSelection::Pointer m_SelectedPlanarFigureNodes; mitk::PlanarFigure::Pointer m_SelectedPlanarFigure; bool m_IsTensorImage; mitk::Image::Pointer m_FAImage; mitk::Image::Pointer m_CAImage; mitk::Image::Pointer m_RDImage; mitk::Image::Pointer m_ADImage; mitk::Image::Pointer m_MDImage; // mitk::Image::Pointer m_DirectionImage; mitk::Image::Pointer m_DirectionComp1Image; mitk::Image::Pointer m_DirectionComp2Image; mitk::Image::Pointer m_AngularErrorImage; QmitkRenderWindow* m_SelectedRenderWindow; QmitkRenderWindow* m_LastRenderWindow; long m_ImageObserverTag; long m_ImageMaskObserverTag; long m_PlanarFigureObserverTag; // Hash map for associating one image statistics calculator with each iamge // (so that previously calculated histograms / statistics can be recovered // if a recalculation is not required) PartialVolumeAnalysisMapType m_PartialVolumeAnalysisMap; HistogramCalculatorType::Pointer m_CurrentStatisticsCalculator; bool m_CurrentStatisticsValid; bool m_StatisticsUpdatePending; bool m_GaussianSigmaChangedSliding; bool m_NumberBinsSliding; bool m_UpsamplingChangedSliding; mitk::DataNode::Pointer m_ClusteringResult; int m_EllipseCounter; int m_RectangleCounter; int m_PolygonCounter; unsigned int m_InitializedObserverTag; bool m_CurrentFigureNodeInitialized; int m_QuantifyClass; ClusteringType::HelperStructPerformRGBClusteringRetval* m_CurrentRGBClusteringResults; ClusteringType::HelperStructPerformClusteringRetval *m_CurrentPerformClusteringResults; // mitk::DataNode::Pointer m_newnode; // mitk::DataNode::Pointer m_newnode2; QIcon* m_IconTexOFF; QIcon* m_IconTexON; bool m_TexIsOn; }; #endif // !defined(QmitkPartialVolumeAnalysis_H__INCLUDED) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisViewControls.ui index 44adb4bbcc..ef60ffb5a4 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisViewControls.ui @@ -1,772 +1,793 @@ QmitkPartialVolumeAnalysisViewControls true 0 0 343 - 467 + 470 Form 0 0 false true QFrame::NoFrame QFrame::Raised 0 QFrame::NoFrame QFrame::Raised 0 0 QFrame::NoFrame QFrame::Raised 6 0 0 0 9 0 0 0 Image: false true 0 0 Mask: false true QFrame::NoFrame QFrame::Raised 0 30 30 :/QmitkDiffusionImaging/circle.png:/QmitkDiffusionImaging/circle.png 32 32 true true 30 30 :/QmitkDiffusionImaging/rectangle.png:/QmitkDiffusionImaging/rectangle.png 32 32 true true 30 30 :/QmitkDiffusionImaging/polygon.png:/QmitkDiffusionImaging/polygon.png 32 32 true true true QFrame::NoFrame QFrame::Raised 0 Upsampling QFrame::NoFrame QFrame::Raised 0 + + 1 + 50 1 25 Qt::Horizontal 50 0 2.5 Similar angles QFrame::NoFrame 0 90 0 Qt::Horizontal QSlider::NoTicks 50 0 90° QFrame::NoFrame QFrame::Raised 0 0 display histogram true 0 0 QFrame::NoFrame QFrame::Raised 0 QFrame::NoFrame QFrame::Raised 0 20 20 true true Green Partial Volume Partial Volume Partial Volume Partial Volume PV Red true All + + + + Export clustering result as float image. + + + ... + + + + :/org.mitk.gui.qt.diffusionimaging/resources/arrow.png:/org.mitk.gui.qt.diffusionimaging/resources/arrow.png + + + QFrame::NoFrame 0 Opacity 10 5 Qt::Horizontal QSlider::TicksBelow Histogram to Clipboard Advanced Qt::Vertical QSizePolicy::Preferred 10 1 QFrame::NoFrame QFrame::Raised QFormLayout::AllNonFixedFieldsGrow 0 Blurring QFrame::NoFrame QFrame::Raised 0 200 1 0 Qt::Horizontal 50 0 0.0 # Bins QFrame::NoFrame 0 + + 1 + 100 10 Qt::Horizontal QSlider::NoTicks 50 0 50 quantiles QFrame::StyledPanel QFrame::Raised 0 1.000000000000000 0.010000000000000 0.250000000000000 1.000000000000000 0.010000000000000 0.750000000000000 Estimate circle from binary image "Thick" PFs Qt::Vertical 20 40 QmitkPartialVolumeAnalysisWidget QWidget
QmitkPartialVolumeAnalysisWidget.h
1
+
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp index 7ec76cd33d..c6302d1b44 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp @@ -1,538 +1,561 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date: 2009-05-28 17:19:30 +0200 (Do, 28 Mai 2009) $ Version: $Revision: 17495 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ //#define MBILOG_ENABLE_DEBUG #include "QmitkPreprocessingView.h" #include "mitkDiffusionImagingConfigure.h" // qt includes #include // itk includes #include "itkTimeProbe.h" #include "itkB0ImageExtractionImageFilter.h" #include "itkBrainMaskExtractionImageFilter.h" #include "itkCastImageFilter.h" #include "itkVectorContainer.h" #include // mitk includes #include "QmitkDataStorageComboBox.h" #include "QmitkStdMultiWidget.h" #include "mitkProgressBar.h" #include "mitkStatusBar.h" #include "mitkNodePredicateDataType.h" #include "mitkProperties.h" #include "mitkVtkResliceInterpolationProperty.h" #include "mitkLookupTable.h" #include "mitkLookupTableProperty.h" #include "mitkTransferFunction.h" #include "mitkTransferFunctionProperty.h" #include "mitkDataNodeObject.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include #include "berryIStructuredSelection.h" #include "berryIWorkbenchWindow.h" #include "berryISelectionService.h" #include #include const std::string QmitkPreprocessingView::VIEW_ID = "org.mitk.views.preprocessing"; #define DI_INFO MITK_INFO("DiffusionImaging") typedef float TTensorPixelType; using namespace berry; struct PrpSelListener : ISelectionListener { berryObjectMacro(PrpSelListener); PrpSelListener(QmitkPreprocessingView* view) { m_View = view; } void DoSelectionChanged(ISelection::ConstPointer selection) { // save current selection in member variable m_View->m_CurrentSelection = selection.Cast(); // do something with the selected items if(m_View->m_CurrentSelection) { bool foundDwiVolume = false; m_View->m_DiffusionImage = NULL; // iterate selection for (IStructuredSelection::iterator i = m_View->m_CurrentSelection->Begin(); i != m_View->m_CurrentSelection->End(); ++i) { // extract datatree node if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); + // process only on valid nodes + mitk::BaseData* nodeData = node->GetData(); + if(nodeData) + { // only look at interesting types - if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0) + if(QString("DiffusionImage").compare(nodeData->GetNameOfClass())==0) { foundDwiVolume = true; - m_View->m_DiffusionImage = dynamic_cast*>(node->GetData()); + m_View->m_DiffusionImage = dynamic_cast*>(nodeData); + } } } } m_View->m_Controls->m_ButtonBrainMask->setEnabled(foundDwiVolume); m_View->m_Controls->m_ButtonAverageGradients->setEnabled(foundDwiVolume); m_View->m_Controls->m_ButtonExtractB0->setEnabled(foundDwiVolume); m_View->m_Controls->m_ModifyMeasurementFrame->setEnabled(foundDwiVolume); m_View->m_Controls->m_MeasurementFrameTable->setEnabled(foundDwiVolume); m_View->m_Controls->m_ReduceGradientsButton->setEnabled(foundDwiVolume); m_View->m_Controls->m_ShowGradientsButton->setEnabled(foundDwiVolume); m_View->m_Controls->m_MirrorGradientToHalfSphereButton->setEnabled(foundDwiVolume); if (foundDwiVolume) { vnl_matrix_fixed< double, 3, 3 > mf = m_View->m_DiffusionImage->GetMeasurementFrame(); for (int r=0; r<3; r++) for (int c=0; c<3; c++) { QTableWidgetItem* item = m_View->m_Controls->m_MeasurementFrameTable->item(r,c); delete item; item = new QTableWidgetItem(); item->setTextAlignment(Qt::AlignCenter | Qt::AlignVCenter); item->setText(QString::number(mf.get(r,c))); m_View->m_Controls->m_MeasurementFrameTable->setItem(r,c,item); } m_View->m_Controls->m_GradientsLabel->setText(QString::number(m_View->m_DiffusionImage->GetNumDirections())); if (m_View->m_DiffusionImage->IsMultiBval()) m_View->m_Controls->m_BvalLabel->setText("Acquisition with multiple b-values!"); else m_View->m_Controls->m_BvalLabel->setText(QString::number(m_View->m_DiffusionImage->GetB_Value())); } else { for (int r=0; r<3; r++) for (int c=0; c<3; c++) { QTableWidgetItem* item = m_View->m_Controls->m_MeasurementFrameTable->item(r,c); delete item; item = new QTableWidgetItem(); m_View->m_Controls->m_MeasurementFrameTable->setItem(r,c,item); } m_View->m_Controls->m_GradientsLabel->setText("-"); m_View->m_Controls->m_BvalLabel->setText("-"); } } } void SelectionChanged(IWorkbenchPart::Pointer part, ISelection::ConstPointer selection) { // check, if selection comes from datamanager if (part) { QString partname(part->GetPartName().c_str()); if(partname.compare("Datamanager")==0) { // apply selection DoSelectionChanged(selection); } } } QmitkPreprocessingView* m_View; }; QmitkPreprocessingView::QmitkPreprocessingView() : QmitkFunctionality(), m_Controls(NULL), m_MultiWidget(NULL), m_DiffusionImage(NULL) { } QmitkPreprocessingView::QmitkPreprocessingView(const QmitkPreprocessingView& other) { Q_UNUSED(other) throw std::runtime_error("Copy constructor not implemented"); } QmitkPreprocessingView::~QmitkPreprocessingView() { this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->RemovePostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener); } void QmitkPreprocessingView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkPreprocessingViewControls; m_Controls->setupUi(parent); this->CreateConnections(); m_Controls->m_MeasurementFrameTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch); m_Controls->m_MeasurementFrameTable->verticalHeader()->setResizeMode(QHeaderView::Stretch); } m_SelListener = berry::ISelectionListener::Pointer(new PrpSelListener(this)); this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener); berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); } void QmitkPreprocessingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkPreprocessingView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkPreprocessingView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_ButtonAverageGradients), SIGNAL(clicked()), this, SLOT(AverageGradients()) ); connect( (QObject*)(m_Controls->m_ButtonExtractB0), SIGNAL(clicked()), this, SLOT(ExtractB0()) ); connect( (QObject*)(m_Controls->m_ButtonBrainMask), SIGNAL(clicked()), this, SLOT(BrainMask()) ); connect( (QObject*)(m_Controls->m_ModifyMeasurementFrame), SIGNAL(clicked()), this, SLOT(DoApplyMesurementFrame()) ); connect( (QObject*)(m_Controls->m_ReduceGradientsButton), SIGNAL(clicked()), this, SLOT(DoReduceGradientDirections()) ); connect( (QObject*)(m_Controls->m_ShowGradientsButton), SIGNAL(clicked()), this, SLOT(DoShowGradientDirections()) ); connect( (QObject*)(m_Controls->m_MirrorGradientToHalfSphereButton), SIGNAL(clicked()), this, SLOT(DoHalfSphereGradientDirections()) ); } } void QmitkPreprocessingView::Activated() { QmitkFunctionality::Activated(); berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); } void QmitkPreprocessingView::Deactivated() { QmitkFunctionality::Deactivated(); } void QmitkPreprocessingView::DoHalfSphereGradientDirections() { if (m_DiffusionImage.IsNull()) return; GradientDirectionContainerType::Pointer gradientContainer = m_DiffusionImage->GetOriginalDirections(); for (int j=0; jSize(); j++) if (gradientContainer->at(j)[0]<0) gradientContainer->at(j) = -gradientContainer->at(j); } void QmitkPreprocessingView::DoApplyMesurementFrame() { if (m_DiffusionImage.IsNull()) return; vnl_matrix_fixed< double, 3, 3 > mf; for (int r=0; r<3; r++) for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c); if (!item) return; mf[r][c] = item->text().toDouble(); } m_DiffusionImage->SetMeasurementFrame(mf); } void QmitkPreprocessingView::DoShowGradientDirections() { if (m_DiffusionImage.IsNull()) return; GradientDirectionContainerType::Pointer gradientContainer = m_DiffusionImage->GetOriginalDirections(); mitk::PointSet::Pointer pointset = mitk::PointSet::New(); for (int j=0; jSize(); j++) { mitk::Point3D p; vnl_vector_fixed< double, 3 > v = gradientContainer->at(j); if (fabs(v[0])>0.001 || fabs(v[1])>0.001 || fabs(v[2])>0.001) { p[0] = v[0]; p[1] = v[1]; p[2] = v[2]; pointset->InsertPoint(j, p); } } mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(pointset); node->SetName("gradient directions"); node->SetProperty("pointsize", mitk::FloatProperty::New(0.05)); node->SetProperty("color", mitk::ColorProperty::New(1,0,0)); GetDefaultDataStorage()->Add(node); } void QmitkPreprocessingView::DoReduceGradientDirections() { if (m_DiffusionImage.IsNull()) return; typedef mitk::DiffusionImage DiffusionImageType; typedef itk::ReduceDirectionGradientsFilter FilterType; GradientDirectionContainerType::Pointer gradientContainer = m_DiffusionImage->GetOriginalDirections(); FilterType::Pointer filter = FilterType::New(); filter->SetInput(m_DiffusionImage->GetVectorImage()); filter->SetOriginalGradientDirections(gradientContainer); filter->SetNumGradientDirections(m_Controls->m_ReduceGradientsBox->value()); filter->Update(); DiffusionImageType::Pointer image = DiffusionImageType::New(); image->SetVectorImage( filter->GetOutput() ); image->SetB_Value(m_DiffusionImage->GetB_Value()); image->SetDirections(filter->GetGradientDirections()); image->SetOriginalDirections(filter->GetGradientDirections()); image->SetMeasurementFrame(m_DiffusionImage->GetMeasurementFrame()); image->InitializeFromVectorImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( image ); imageNode->SetName("reduced_image"); GetDefaultDataStorage()->Add(imageNode); } void QmitkPreprocessingView::ExtractB0() { if (m_CurrentSelection) { mitk::DataStorage::SetOfObjects::Pointer set = mitk::DataStorage::SetOfObjects::New(); int at = 0; for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); - i != m_CurrentSelection->End(); - ++i) + i != m_CurrentSelection->End(); + ++i) { if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); - if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0) + + // process only on valid nodes + const mitk::BaseData* nodeData = node->GetData(); + if(nodeData) { - set->InsertElement(at++, node); + if(QString("DiffusionImage").compare(nodeData->GetNameOfClass())==0) + { + set->InsertElement(at++, node); + } } } } DoExtractB0(set); } } void QmitkPreprocessingView::DoExtractB0 (mitk::DataStorage::SetOfObjects::Pointer inImages) { typedef mitk::DiffusionImage DiffusionImageType; typedef DiffusionImageType::GradientDirectionContainerType GradientContainerType; int nrFiles = inImages->size(); if (!nrFiles) return; mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { DiffusionImageType* vols = static_cast( (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); // Extract image using found index typedef itk::B0ImageExtractionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput(vols->GetVectorImage()); filter->SetDirections(vols->GetDirections()); filter->Update(); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( filter->GetOutput() ); mitkImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( mitkImage ); node->SetProperty( "name", mitk::StringProperty::New(nodename + "_B0")); GetDefaultDataStorage()->Add(node); ++itemiter; } } void QmitkPreprocessingView::AverageGradients() { if (m_CurrentSelection) { mitk::DataStorage::SetOfObjects::Pointer set = mitk::DataStorage::SetOfObjects::New(); int at = 0; for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i) { if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); - if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0) + // process only on valid nodes + const mitk::BaseData* nodeData = node->GetData(); + + if(nodeData) { - set->InsertElement(at++, node); + if(QString("DiffusionImage").compare(nodeData->GetNameOfClass())==0) + { + set->InsertElement(at++, node); + } } } } DoAverageGradients(set); } } void QmitkPreprocessingView::DoAverageGradients (mitk::DataStorage::SetOfObjects::Pointer inImages) { int nrFiles = inImages->size(); if (!nrFiles) return; mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { mitk::DiffusionImage* vols = static_cast*>( (*itemiter)->GetData()); vols->AverageRedundantGradients(m_Controls->m_Blur->value()); ++itemiter; } } void QmitkPreprocessingView::BrainMask() { if (m_CurrentSelection) { mitk::DataStorage::SetOfObjects::Pointer set = mitk::DataStorage::SetOfObjects::New(); int at = 0; for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i) { if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); - if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0) + // process only on valid nodes + const mitk::BaseData* nodeData = node->GetData(); + + if(nodeData) { - set->InsertElement(at++, node); + if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0) + { + set->InsertElement(at++, node); + } } } } DoBrainMask(set); } } void QmitkPreprocessingView::DoBrainMask (mitk::DataStorage::SetOfObjects::Pointer inImages) { int nrFiles = inImages->size(); if (!nrFiles) return; mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); while ( itemiter != itemiterend ) // for all items { mitk::DiffusionImage* vols = static_cast*>( (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); // Extract image using found index typedef itk::B0ImageExtractionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput(vols->GetVectorImage()); filter->SetDirections(vols->GetDirections()); typedef itk::CastImageFilter, itk::Image > CastFilterType; CastFilterType::Pointer castfilter = CastFilterType::New(); castfilter->SetInput(filter->GetOutput()); typedef itk::BrainMaskExtractionImageFilter MaskFilterType; MaskFilterType::Pointer maskfilter = MaskFilterType::New(); maskfilter->SetInput(castfilter->GetOutput()); maskfilter->Update(); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( maskfilter->GetOutput() ); mitkImage->SetVolume( maskfilter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( mitkImage ); node->SetProperty( "name", mitk::StringProperty::New(nodename + "_Mask")); GetDefaultDataStorage()->Add(node); ++itemiter; } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkQBallReconstructionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkQBallReconstructionView.cpp index ff27406a8d..331a9f2616 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkQBallReconstructionView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkQBallReconstructionView.cpp @@ -1,789 +1,801 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date: 2009-05-28 17:19:30 +0200 (Do, 28 Mai 2009) $ Version: $Revision: 17495 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ //#define MBILOG_ENABLE_DEBUG #include "QmitkQBallReconstructionView.h" #include "mitkDiffusionImagingConfigure.h" // qt includes #include // itk includes #include "itkTimeProbe.h" // mitk includes #include "mitkProgressBar.h" #include "mitkStatusBar.h" #include "mitkNodePredicateDataType.h" #include "QmitkDataStorageComboBox.h" #include "QmitkStdMultiWidget.h" #include "itkDiffusionQballReconstructionImageFilter.h" #include "itkAnalyticalDiffusionQballReconstructionImageFilter.h" #include "itkVectorContainer.h" #include "mitkQBallImage.h" #include "mitkProperties.h" #include "mitkVtkResliceInterpolationProperty.h" #include "mitkLookupTable.h" #include "mitkLookupTableProperty.h" #include "mitkTransferFunction.h" #include "mitkTransferFunctionProperty.h" #include "mitkDataNodeObject.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include "berryIStructuredSelection.h" #include "berryIWorkbenchWindow.h" #include "berryISelectionService.h" #include const std::string QmitkQBallReconstructionView::VIEW_ID = "org.mitk.views.qballreconstruction"; #define DI_INFO MITK_INFO("DiffusionImaging") typedef float TTensorPixelType; const int QmitkQBallReconstructionView::nrconvkernels = 252; using namespace berry; struct QbrSelListener : ISelectionListener { berryObjectMacro(QbrSelListener); QbrSelListener(QmitkQBallReconstructionView* view) { m_View = view; } void DoSelectionChanged(ISelection::ConstPointer selection) { // save current selection in member variable m_View->m_CurrentSelection = selection.Cast(); // do something with the selected items if(m_View->m_CurrentSelection) { bool foundDwiVolume = false; // iterate selection for (IStructuredSelection::iterator i = m_View->m_CurrentSelection->Begin(); i != m_View->m_CurrentSelection->End(); ++i) { // extract datatree node if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); - // only look at interesting types - if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0) + // check if node valid + const mitk::BaseData* nodeData = node->GetData(); + + if(nodeData) { - foundDwiVolume = true; + // only look at interesting types + if(QString("DiffusionImage").compare(nodeData->GetNameOfClass())==0) + { + foundDwiVolume = true; + } } } } m_View->m_Controls->m_ButtonStandard->setEnabled(foundDwiVolume); } } void SelectionChanged(IWorkbenchPart::Pointer part, ISelection::ConstPointer selection) { // check, if selection comes from datamanager if (part) { QString partname(part->GetPartName().c_str()); if(partname.compare("Datamanager")==0) { // apply selection DoSelectionChanged(selection); } } } QmitkQBallReconstructionView* m_View; }; QmitkQBallReconstructionView::QmitkQBallReconstructionView() : QmitkFunctionality(), m_Controls(NULL), m_MultiWidget(NULL) { } QmitkQBallReconstructionView::QmitkQBallReconstructionView(const QmitkQBallReconstructionView& other) { Q_UNUSED(other); throw std::runtime_error("Copy constructor not implemented"); } //void QmitkQBallReconstructionView::OpactiyChanged(int value) //{ // if (m_CurrentSelection) // { // if (mitk::DataNodeObject::Pointer nodeObj = m_CurrentSelection->Begin()->Cast()) // { // mitk::DataNode::Pointer node = nodeObj->GetDataNode(); // if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0) // { // node->SetIntProperty("DisplayChannel", value); // mitk::RenderingManager::GetInstance()->RequestUpdateAll(); // } // } // } //} // //void QmitkQBallReconstructionView::OpactiyActionChanged() //{ // if (m_CurrentSelection) // { // if (mitk::DataNodeObject::Pointer nodeObj = m_CurrentSelection->Begin()->Cast()) // { // mitk::DataNode::Pointer node = nodeObj->GetDataNode(); // if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0) // { // int displayChannel = 0.0; // if(node->GetIntProperty("DisplayChannel", displayChannel)) // { // m_OpacitySlider->setValue(displayChannel); // } // } // } // } // // MITK_INFO << "changed"; //} QmitkQBallReconstructionView::~QmitkQBallReconstructionView() { this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->RemovePostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener); } void QmitkQBallReconstructionView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkQBallReconstructionViewControls; m_Controls->setupUi(parent); this->CreateConnections(); QStringList items; items << "2" << "4" << "6" << "8" << "10" << "12"; m_Controls->m_QBallReconstructionMaxLLevelComboBox->addItems(items); m_Controls->m_QBallReconstructionMaxLLevelComboBox->setCurrentIndex(1); MethodChoosen(m_Controls->m_QBallReconstructionMethodComboBox->currentIndex()); #ifndef DIFFUSION_IMAGING_EXTENDED m_Controls->m_QBallReconstructionMethodComboBox->removeItem(3); #endif AdvancedCheckboxClicked(); // define data type for combobox //m_Controls->m_ImageSelector->SetDataStorage( this->GetDefaultDataStorage() ); //m_Controls->m_ImageSelector->SetPredicate( mitk::NodePredicateDataType::New("DiffusionImage") ); } m_SelListener = berry::ISelectionListener::Pointer(new QbrSelListener(this)); this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener); berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); } void QmitkQBallReconstructionView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkQBallReconstructionView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkQBallReconstructionView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_ButtonStandard), SIGNAL(clicked()), this, SLOT(ReconstructStandard()) ); connect( (QObject*)(m_Controls->m_AdvancedCheckbox), SIGNAL(clicked()), this, SLOT(AdvancedCheckboxClicked()) ); connect( (QObject*)(m_Controls->m_QBallReconstructionMethodComboBox), SIGNAL(currentIndexChanged(int)), this, SLOT(MethodChoosen(int)) ); } } void QmitkQBallReconstructionView::Activated() { QmitkFunctionality::Activated(); berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); } void QmitkQBallReconstructionView::Deactivated() { QmitkFunctionality::Deactivated(); } void QmitkQBallReconstructionView::ReconstructStandard() { int index = m_Controls->m_QBallReconstructionMethodComboBox->currentIndex(); #ifndef DIFFUSION_IMAGING_EXTENDED if(index>=3) { index = index + 1; } #endif switch(index) { case 0: { // Numerical Reconstruct(0,0); break; } case 1: { // Standard Reconstruct(1,0); break; } case 2: { // Solid Angle Reconstruct(1,6); break; } case 3: { // Constrained Solid Angle Reconstruct(1,7); break; } case 4: { // ADC Reconstruct(1,4); break; } case 5: { // Raw Signal Reconstruct(1,5); break; } } } void QmitkQBallReconstructionView::MethodChoosen(int method) { switch(method) { case 0: m_Controls->m_Description->setText("Numerical recon. (Tuch2004)"); break; case 1: m_Controls->m_Description->setText("Spherical harmonics recon. (Descoteaux2007)"); break; case 2: m_Controls->m_Description->setText("SH recon. with solid angle consideration (Aganj2009)"); break; case 3: m_Controls->m_Description->setText("SH solid angle with non-neg. constraint (Goh2009)"); break; case 4: m_Controls->m_Description->setText("SH recon. of the plain ADC-profiles"); break; case 5: m_Controls->m_Description->setText("SH recon. of the raw diffusion signal"); break; } } void QmitkQBallReconstructionView::AdvancedCheckboxClicked() { bool check = m_Controls-> m_AdvancedCheckbox->isChecked(); m_Controls->m_QBallReconstructionMaxLLevelTextLabel_2->setVisible(check); m_Controls->m_QBallReconstructionMaxLLevelComboBox->setVisible(check); m_Controls->m_QBallReconstructionLambdaTextLabel_2->setVisible(check); m_Controls->m_QBallReconstructionLambdaLineEdit->setVisible(check); m_Controls->m_QBallReconstructionThresholdLabel_2->setVisible(check); m_Controls->m_QBallReconstructionThreasholdEdit->setVisible(check); m_Controls->m_OutputB0Image->setVisible(check); m_Controls->label_2->setVisible(check); //m_Controls->textLabel1_2->setVisible(check); //m_Controls->m_QBallReconstructionLambdaStepLineEdit->setVisible(check); //m_Controls->textLabel1_3->setVisible(check); m_Controls->frame_2->setVisible(check); } void QmitkQBallReconstructionView::Reconstruct(int method, int normalization) { if (m_CurrentSelection) { mitk::DataStorage::SetOfObjects::Pointer set = mitk::DataStorage::SetOfObjects::New(); int at = 0; for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i) { if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); - if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0) + + // check if node's data valid + const mitk::BaseData* nodeData = node->GetData(); + if(nodeData) + { + if(QString("DiffusionImage").compare(nodeData->GetNameOfClass())==0) { set->InsertElement(at++, node); } + } } } if(method == 0) { NumericalQBallReconstruction(set, normalization); } else { #if BOOST_VERSION / 100000 > 0 #if BOOST_VERSION / 100 % 1000 > 34 if(method == 1) { AnalyticalQBallReconstruction(set, normalization); } #else std::cout << "ERROR: Boost 1.35 minimum required" << std::endl; QMessageBox::warning(NULL,"ERROR","Boost 1.35 minimum required"); #endif #else std::cout << "ERROR: Boost 1.35 minimum required" << std::endl; QMessageBox::warning(NULL,"ERROR","Boost 1.35 minimum required"); #endif } } } void QmitkQBallReconstructionView::NumericalQBallReconstruction (mitk::DataStorage::SetOfObjects::Pointer inImages, int normalization) { try { itk::TimeProbe clock; int nrFiles = inImages->size(); if (!nrFiles) return; QString status; mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles); mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { mitk::DiffusionImage* vols = static_cast*>( (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); ++itemiter; // QBALL RECONSTRUCTION clock.Start(); MBI_INFO << "QBall reconstruction "; mitk::StatusBar::GetInstance()->DisplayText(status.sprintf( "QBall reconstruction for %s", nodename.c_str()).toAscii()); typedef itk::DiffusionQballReconstructionImageFilter QballReconstructionImageFilterType; QballReconstructionImageFilterType::Pointer filter = QballReconstructionImageFilterType::New(); filter->SetGradientImage( vols->GetDirections(), vols->GetVectorImage() ); filter->SetBValue(vols->GetB_Value()); filter->SetThreshold( m_Controls->m_QBallReconstructionThreasholdEdit->text().toFloat() ); switch(normalization) { case 0: { filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_STANDARD); break; } case 1: { filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_B_ZERO_B_VALUE); break; } case 2: { filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_B_ZERO); break; } case 3: { filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_NONE); break; } default: { filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_STANDARD); } } filter->Update(); clock.Stop(); MBI_DEBUG << "took " << clock.GetMeanTime() << "s." ; // ODFs TO DATATREE mitk::QBallImage::Pointer image = mitk::QBallImage::New(); image->InitializeByItk( filter->GetOutput() ); //image->SetImportVolume( filter->GetOutput()->GetBufferPointer(), 0, 0, mitk::Image::ImportMemoryManagementType::ManageMemory ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( image ); QString newname; newname = newname.append(nodename.c_str()); newname = newname.append("_QN%1").arg(normalization); SetDefaultNodeProperties(node, newname.toStdString()); nodes.push_back(node); // B-Zero TO DATATREE if(m_Controls->m_OutputB0Image->isChecked()) { mitk::Image::Pointer image4 = mitk::Image::New(); image4->InitializeByItk( filter->GetBZeroImage().GetPointer() ); image4->SetVolume( filter->GetBZeroImage()->GetBufferPointer() ); mitk::DataNode::Pointer node4=mitk::DataNode::New(); node4->SetData( image4 ); node4->SetProperty( "name", mitk::StringProperty::New( QString(nodename.c_str()).append("_b0").toStdString()) ); nodes.push_back(node4); } mitk::ProgressBar::GetInstance()->Progress(); } std::vector::iterator nodeIt; for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt) GetDefaultDataStorage()->Add(*nodeIt); mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toAscii()); m_MultiWidget->RequestUpdate(); } catch (itk::ExceptionObject &ex) { MBI_INFO << ex ; return ; } } void QmitkQBallReconstructionView::AnalyticalQBallReconstruction( mitk::DataStorage::SetOfObjects::Pointer inImages, int normalization) { try { itk::TimeProbe clock; int nrFiles = inImages->size(); if (!nrFiles) return; std::vector lambdas; float minLambda = m_Controls->m_QBallReconstructionLambdaLineEdit->text().toFloat(); lambdas.push_back(minLambda); int nLambdas = lambdas.size(); QString status; mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles*nLambdas); mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); std::vector* nodes = new std::vector(); while ( itemiter != itemiterend ) // for all items { mitk::DiffusionImage* vols = static_cast*>( (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name",nodename); itemiter++; // QBALL RECONSTRUCTION clock.Start(); MBI_INFO << "QBall reconstruction "; mitk::StatusBar::GetInstance()->DisplayText(status.sprintf( "QBall reconstruction for %s", nodename.c_str()).toAscii()); for(int i=0; im_QBallReconstructionMaxLLevelComboBox->currentIndex()) { case 0: { TemplatedAnalyticalQBallReconstruction<2>(vols, currentLambda, nodename, nodes, normalization); break; } case 1: { TemplatedAnalyticalQBallReconstruction<4>(vols, currentLambda, nodename, nodes, normalization); break; } case 2: { TemplatedAnalyticalQBallReconstruction<6>(vols, currentLambda, nodename, nodes, normalization); break; } case 3: { TemplatedAnalyticalQBallReconstruction<8>(vols, currentLambda, nodename, nodes, normalization); break; } case 4: { TemplatedAnalyticalQBallReconstruction<10>(vols, currentLambda, nodename, nodes, normalization); break; } case 5: { TemplatedAnalyticalQBallReconstruction<12>(vols, currentLambda, nodename, nodes, normalization); break; } } clock.Stop(); MBI_DEBUG << "took " << clock.GetMeanTime() << "s." ; mitk::ProgressBar::GetInstance()->Progress(); } } std::vector::iterator nodeIt; for(nodeIt = nodes->begin(); nodeIt != nodes->end(); ++nodeIt) GetDefaultDataStorage()->Add(*nodeIt); m_MultiWidget->RequestUpdate(); mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toAscii()); } catch (itk::ExceptionObject &ex) { MBI_INFO << ex ; return ; } } template void QmitkQBallReconstructionView::TemplatedAnalyticalQBallReconstruction( mitk::DiffusionImage* vols, float lambda, std::string nodename, std::vector* nodes, int normalization) { typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; typename FilterType::Pointer filter = FilterType::New(); filter->SetGradientImage( vols->GetDirections(), vols->GetVectorImage() ); filter->SetBValue(vols->GetB_Value()); filter->SetThreshold( m_Controls->m_QBallReconstructionThreasholdEdit->text().toFloat() ); filter->SetLambda(lambda); switch(normalization) { case 0: { filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); break; } case 1: { filter->SetNormalizationMethod(FilterType::QBAR_B_ZERO_B_VALUE); break; } case 2: { filter->SetNormalizationMethod(FilterType::QBAR_B_ZERO); break; } case 3: { filter->SetNormalizationMethod(FilterType::QBAR_NONE); break; } case 4: { filter->SetNormalizationMethod(FilterType::QBAR_ADC_ONLY); break; } case 5: { filter->SetNormalizationMethod(FilterType::QBAR_RAW_SIGNAL); break; } case 6: { filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); break; } case 7: { filter->SetNormalizationMethod(FilterType::QBAR_NONNEG_SOLID_ANGLE); break; } default: { filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); } } filter->Update(); // ODFs TO DATATREE mitk::QBallImage::Pointer image = mitk::QBallImage::New(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( image ); QString newname; newname = newname.append(nodename.c_str()); newname = newname.append("_QA%1").arg(normalization); SetDefaultNodeProperties(node, newname.toStdString()); nodes->push_back(node); // mitk::Image::Pointer image5 = mitk::Image::New(); // image5->InitializeByItk( filter->GetODFSumImage().GetPointer() ); // image5->SetVolume( filter->GetODFSumImage()->GetBufferPointer() ); // mitk::DataNode::Pointer node5=mitk::DataNode::New(); // node5->SetData( image5 ); // node5->SetProperty( "name", mitk::StringProperty::New( // QString(nodename.c_str()).append("_ODF").toStdString()) ); // nodes->push_back(node5); // B-Zero TO DATATREE if(m_Controls->m_OutputB0Image->isChecked()) { mitk::Image::Pointer image4 = mitk::Image::New(); image4->InitializeByItk( filter->GetBZeroImage().GetPointer() ); image4->SetVolume( filter->GetBZeroImage()->GetBufferPointer() ); mitk::DataNode::Pointer node4=mitk::DataNode::New(); node4->SetData( image4 ); node4->SetProperty( "name", mitk::StringProperty::New( QString(nodename.c_str()).append("_b0").toStdString()) ); nodes->push_back(node4); } } void QmitkQBallReconstructionView::SetDefaultNodeProperties(mitk::DataNode::Pointer node, std::string name) { node->SetProperty( "ShowMaxNumber", mitk::IntProperty::New( 500 ) ); node->SetProperty( "Scaling", mitk::FloatProperty::New( 1.0 ) ); node->SetProperty( "Normalization", mitk::OdfNormalizationMethodProperty::New()); node->SetProperty( "ScaleBy", mitk::OdfScaleByProperty::New()); node->SetProperty( "IndexParam1", mitk::FloatProperty::New(2)); node->SetProperty( "IndexParam2", mitk::FloatProperty::New(1)); node->SetProperty( "visible", mitk::BoolProperty::New( true ) ); node->SetProperty( "VisibleOdfs", mitk::BoolProperty::New( false ) ); node->SetProperty ("layer", mitk::IntProperty::New(100)); node->SetProperty( "DoRefresh", mitk::BoolProperty::New( true ) ); //node->SetProperty( "opacity", mitk::FloatProperty::New(1.0f) ); node->SetProperty( "name", mitk::StringProperty::New(name) ); } //node->SetProperty( "volumerendering", mitk::BoolProperty::New( false ) ); //node->SetProperty( "use color", mitk::BoolProperty::New( true ) ); //node->SetProperty( "texture interpolation", mitk::BoolProperty::New( true ) ); //node->SetProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ); //node->SetProperty( "layer", mitk::IntProperty::New(0)); //node->SetProperty( "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ); //node->SetOpacity(1.0f); //node->SetColor(1.0,1.0,1.0); //node->SetVisibility(true); //node->SetProperty( "IsQBallVolume", mitk::BoolProperty::New( true ) ); //mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); //mitk::LevelWindow levelwindow; //// levelwindow.SetAuto( image ); //levWinProp->SetLevelWindow( levelwindow ); //node->GetPropertyList()->SetProperty( "levelwindow", levWinProp ); //// add a default rainbow lookup table for color mapping //if(!node->GetProperty("LookupTable")) //{ // mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); // vtkLookupTable* vtkLut = mitkLut->GetVtkLookupTable(); // vtkLut->SetHueRange(0.6667, 0.0); // vtkLut->SetTableRange(0.0, 20.0); // vtkLut->Build(); // mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); // mitkLutProp->SetLookupTable(mitkLut); // node->SetProperty( "LookupTable", mitkLutProp ); //} //if(!node->GetProperty("binary")) // node->SetProperty( "binary", mitk::BoolProperty::New( false ) ); //// add a default transfer function //mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New(); //node->SetProperty ( "TransferFunction", mitk::TransferFunctionProperty::New ( tf.GetPointer() ) ); //// set foldername as string property //mitk::StringProperty::Pointer nameProp = mitk::StringProperty::New( name ); //node->SetProperty( "name", nameProp ); diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingViewControls.ui index 7d32869673..2a821e9378 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingViewControls.ui @@ -1,200 +1,212 @@ QmitkStochasticFiberTrackingViewControls 0 0 480 553 0 0 QmitkTemplate + + 3 + + + 3 + + + 0 + Data Diffusion Image: - - ROI Image: + Seed ROI Image: - Parameters - Maximum tract length in voxel + Maximum tract length in #voxel. 1 500 100 Qt::Horizontal - Length of single tracts + Maximum tract length in #voxel. Max. Tract Length: 100 - Number of tracts for each seedpoint + Number of tracts started in each voxel of the seed ROI. Seeds per Voxel: 1 - Likelihood cache in Megabytes + Likelihood cache in Megabytes. Max. Chache Size: 1GB - Number of tracts started in each voxel of the seed ROI + Number of tracts started in each voxel of the seed ROI. 1 10 Qt::Horizontal + + Likelihood cache in Megabytes. + 1 10 1 Qt::Horizontal Qt::Horizontal QSizePolicy::Fixed 200 0 false Start Tracking Qt::Vertical QSizePolicy::Expanding 20 220 commandLinkButton diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTbssSkeletonizationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTbssSkeletonizationView.cpp index 2fe792b588..afd7fca2c8 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTbssSkeletonizationView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTbssSkeletonizationView.cpp @@ -1,504 +1,521 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $ Version: $Revision: 21975 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ // Blueberry #include #include #include #include #include // Qmitk #include "QmitkTbssSkeletonizationView.h" #include #include #include #include #include #include #include #include // Qt #include #include //vtk #include #include // Boost #include const std::string QmitkTbssSkeletonizationView::VIEW_ID = "org.mitk.views.tbssskeletonization"; using namespace berry; struct TbssSkeletonizationSelListener : ISelectionListener { berryObjectMacro(TbssSkeletonizationSelListener) TbssSkeletonizationSelListener(QmitkTbssSkeletonizationView* view) { m_View = view; } void DoSelectionChanged(ISelection::ConstPointer selection) { // save current selection in member variable m_View->m_CurrentSelection = selection.Cast(); // do something with the selected items if(m_View->m_CurrentSelection) { bool found3dImage = false; bool found4dImage = false; // iterate selection for (IStructuredSelection::iterator i = m_View->m_CurrentSelection->Begin(); i != m_View->m_CurrentSelection->End(); ++i) { // extract datatree node if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); // only look at interesting types + // from valid nodes + mitk::BaseData* nodeData = node->GetData(); - if(QString("Image").compare(node->GetData()->GetNameOfClass())==0) + if(nodeData) { - mitk::Image* img = static_cast(node->GetData()); - if(img->GetDimension() == 3) + if(QString("Image").compare(nodeData->GetNameOfClass())==0) { - found3dImage = true; - } - else if(img->GetDimension() == 4) - { - found4dImage = true; + mitk::Image* img = static_cast(nodeData); + if(img->GetDimension() == 3) + { + found3dImage = true; + } + else if(img->GetDimension() == 4) + { + found4dImage = true; + } } } } } m_View->m_Controls->m_Skeletonize->setEnabled(found3dImage); m_View->m_Controls->m_Project->setEnabled(found3dImage && found4dImage); m_View->m_Controls->m_OutputMask->setEnabled(found3dImage && found4dImage); m_View->m_Controls->m_OutputDistanceMap->setEnabled(found3dImage && found4dImage); } } void SelectionChanged(IWorkbenchPart::Pointer part, ISelection::ConstPointer selection) { // check, if selection comes from datamanager if (part) { QString partname(part->GetPartName().c_str()); if(partname.compare("Datamanager")==0) { // apply selection DoSelectionChanged(selection); } } } QmitkTbssSkeletonizationView* m_View; }; QmitkTbssSkeletonizationView::QmitkTbssSkeletonizationView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) { } QmitkTbssSkeletonizationView::~QmitkTbssSkeletonizationView() { } void QmitkTbssSkeletonizationView::OnSelectionChanged(std::vector nodes) { //datamanager selection changed if (!this->IsActivated()) return; } void QmitkTbssSkeletonizationView::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::QmitkTbssSkeletonizationViewControls; m_Controls->setupUi( parent ); this->CreateConnections(); } m_SelListener = berry::ISelectionListener::Pointer(new TbssSkeletonizationSelListener(this)); this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener); berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); m_IsInitialized = false; } void QmitkTbssSkeletonizationView::Activated() { QmitkFunctionality::Activated(); berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); } void QmitkTbssSkeletonizationView::Deactivated() { QmitkFunctionality::Deactivated(); } void QmitkTbssSkeletonizationView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_Skeletonize), SIGNAL(clicked()), this, SLOT(Skeletonize() )); connect( (QObject*)(m_Controls->m_Project), SIGNAL(clicked()), this, SLOT(Project() )); } } void QmitkTbssSkeletonizationView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkTbssSkeletonizationView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkTbssSkeletonizationView::Skeletonize() { typedef itk::SkeletonizationFilter SkeletonisationFilterType; SkeletonisationFilterType::Pointer skeletonizer = SkeletonisationFilterType::New(); if (m_CurrentSelection) { mitk::DataStorage::SetOfObjects::Pointer set = mitk::DataStorage::SetOfObjects::New(); mitk::Image::Pointer meanImage = mitk::Image::New(); for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i) { if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); - if(QString("Image").compare(node->GetData()->GetNameOfClass())==0) + // process only on valid nodes + mitk::BaseData* nodeData = node->GetData(); + + if(nodeData) { - mitk::Image* img = static_cast(node->GetData()); - if(img->GetDimension() == 3) + if(QString("Image").compare(nodeData->GetNameOfClass())==0) { - meanImage = img; + mitk::Image* img = static_cast(nodeData); + if(img->GetDimension() == 3) + { + meanImage = img; + } } } } } // Calculate skeleton FloatImageType::Pointer itkImg = FloatImageType::New(); mitk::CastToItkImage(meanImage, itkImg); skeletonizer->SetInput(itkImg); skeletonizer->Update(); FloatImageType::Pointer output = skeletonizer->GetOutput(); mitk::Image::Pointer mitkOutput = mitk::Image::New(); mitk::CastToMitkImage(output, mitkOutput); AddToDataStorage(mitkOutput, "all_FA_skeletonised"); } } void QmitkTbssSkeletonizationView::Project() { typedef itk::SkeletonizationFilter SkeletonisationFilterType; typedef itk::ProjectionFilter ProjectionFilterType; typedef itk::DistanceMapFilter DistanceMapFilterType; SkeletonisationFilterType::Pointer skeletonizer = SkeletonisationFilterType::New(); if (m_CurrentSelection) { mitk::DataStorage::SetOfObjects::Pointer set = mitk::DataStorage::SetOfObjects::New(); mitk::Image::Pointer meanImage = mitk::Image::New(); mitk::Image::Pointer subjects = mitk::Image::New(); for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i) { if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); - if(QString("Image").compare(node->GetData()->GetNameOfClass())==0) + // process only on valid nodes + mitk::BaseData* nodeData = node->GetData(); + + if(nodeData) { - mitk::Image* img = static_cast(node->GetData()); - if(img->GetDimension() == 3) + if(QString("Image").compare(nodeData->GetNameOfClass())==0) { - meanImage = img; - } - else if(img->GetDimension() == 4) - { - subjects = img; + mitk::Image* img = static_cast(nodeData); + if(img->GetDimension() == 3) + { + meanImage = img; + } + else if(img->GetDimension() == 4) + { + subjects = img; + } } } } } Float4DImageType::Pointer allFA = ConvertToItk(subjects); // Calculate skeleton FloatImageType::Pointer itkImg = FloatImageType::New(); mitk::CastToItkImage(meanImage, itkImg); skeletonizer->SetInput(itkImg); skeletonizer->Update(); FloatImageType::Pointer output = skeletonizer->GetOutput(); mitk::Image::Pointer mitkOutput = mitk::Image::New(); mitk::CastToMitkImage(output, mitkOutput); AddToDataStorage(mitkOutput, "mean_FA_skeletonised"); // Retrieve direction image needed later by the projection filter DirectionImageType::Pointer directionImg = skeletonizer->GetVectorImage(); // Calculate distance image DistanceMapFilterType::Pointer distanceMapFilter = DistanceMapFilterType::New(); distanceMapFilter->SetInput(output); distanceMapFilter->Update(); FloatImageType::Pointer distanceMap = distanceMapFilter->GetOutput(); if(m_Controls->m_OutputDistanceMap->isChecked()) { mitk::Image::Pointer mitkDistance = mitk::Image::New(); mitk::CastToMitkImage(distanceMap, mitkDistance); AddToDataStorage(mitkDistance, "distance map"); } // Do projection // Ask a threshold to create a skeleton mask double threshold = -1.0; while(threshold == -1.0) { threshold = QInputDialog::getDouble(m_Controls->m_Skeletonize, tr("Specify the FA threshold"), tr("Threshold:"), QLineEdit::Normal, 0.2); if(threshold < 0.0 || threshold > 1.0) { QMessageBox msgBox; msgBox.setText("Please choose a value between 0 and 1"); msgBox.exec(); threshold = -1.0; } } typedef itk::BinaryThresholdImageFilter ThresholdFilterType; ThresholdFilterType::Pointer thresholder = ThresholdFilterType::New(); thresholder->SetInput(output); thresholder->SetLowerThreshold(threshold); thresholder->SetUpperThreshold(std::numeric_limits::max()); thresholder->SetOutsideValue(0); thresholder->SetInsideValue(1); thresholder->Update(); CharImageType::Pointer thresholdedImg = thresholder->GetOutput(); if(m_Controls->m_OutputMask->isChecked()) { mitk::Image::Pointer mitkThresholded = mitk::Image::New(); mitk::CastToMitkImage(thresholdedImg, mitkThresholded); std::string maskName = "skeleton_mask_at_" + boost::lexical_cast(threshold); AddToDataStorage(mitkThresholded, maskName); } typedef itk::ImageFileReader< CharImageType > CharReaderType; CharReaderType::Pointer reader = CharReaderType::New(); reader->SetFileName("/local/testing/LowerCingulum_1mm.nii.gz"); reader->Update(); CharImageType::Pointer cingulum = reader->GetOutput(); ProjectionFilterType::Pointer projectionFilter = ProjectionFilterType::New(); projectionFilter->SetDistanceMap(distanceMap); projectionFilter->SetDirections(directionImg); projectionFilter->SetAllFA(allFA); projectionFilter->SetTube(cingulum); projectionFilter->SetSkeleton(thresholdedImg); projectionFilter->Project(); Float4DImageType::Pointer projected = projectionFilter->GetProjections(); mitk::Image::Pointer mitkProjections = mitk::Image::New(); mitk::CastToMitkImage(projected, mitkProjections); AddToDataStorage(mitkProjections, "all_FA_projected"); } } void QmitkTbssSkeletonizationView::AddToDataStorage(mitk::Image* img, std::string name) { mitk::DataNode::Pointer result = mitk::DataNode::New(); result->SetProperty( "name", mitk::StringProperty::New(name) ); result->SetData( img ); // add new image to data storage and set as active to ease further processing GetDefaultDataStorage()->Add( result ); } Float4DImageType::Pointer QmitkTbssSkeletonizationView::ConvertToItk(mitk::Image::Pointer image) { Float4DImageType::Pointer output = Float4DImageType::New(); mitk::Geometry3D* geo = image->GetGeometry(); mitk::Vector3D mitkSpacing = geo->GetSpacing(); mitk::Point3D mitkOrigin = geo->GetOrigin(); Float4DImageType::SpacingType spacing; spacing[0] = mitkSpacing[0]; spacing[1] = mitkSpacing[1]; spacing[2] = mitkSpacing[2]; spacing[3] = 1.0; // todo: check if spacing has length 4 Float4DImageType::PointType origin; origin[0] = mitkOrigin[0]; origin[1] = mitkOrigin[1]; origin[2] = mitkOrigin[2]; origin[3] = 0; Float4DImageType::SizeType size; size[0] = image->GetDimension(0); size[1] = image->GetDimension(1); size[2] = image->GetDimension(2); size[3] = image->GetDimension(3); Float4DImageType::DirectionType dir; vtkLinearTransform* lin = geo->GetVtkTransform(); vtkMatrix4x4 *m = lin->GetMatrix(); dir.Fill(0.0); for(int x=0; x<3; x++) { for(int y=0; y<3; y++) { dir[x][y] = m->GetElement(x,y); } } dir[3][3] = 1; output->SetSpacing(spacing); output->SetOrigin(origin); output->SetRegions(size); output->SetDirection(dir); output->Allocate(); if(image->GetDimension() == 4) { int timesteps = image->GetDimension(3); // iterate through the subjects and copy data to output for(int t=0; tGetDimension(0); x++) { for(int y=0; yGetDimension(1); y++) { for(int z=0; zGetDimension(2); z++) { itk::Index<4> ix4; ix4[0] = x; ix4[1] = y; ix4[2] = z; ix4[3] = t; mitk::Index3D ix; ix[0] = x; ix[1] = y; ix[2] = z; output->SetPixel(ix4, image->GetPixelValueByIndex(ix, t)); } } } } } return output; } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.cpp index 00b21ae1a9..fbe44bf130 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.cpp @@ -1,1351 +1,1377 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date: 2009-05-28 17:19:30 +0200 (Do, 28 Mai 2009) $ Version: $Revision: 17495 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkTensorReconstructionView.h" #include "mitkDiffusionImagingConfigure.h" // qt includes #include #include #include #include #include // itk includes #include "itkTimeProbe.h" //#include "itkTensor.h" // mitk includes #include "mitkProgressBar.h" #include "mitkStatusBar.h" #include "mitkNodePredicateDataType.h" #include "QmitkDataStorageComboBox.h" #include "QmitkStdMultiWidget.h" #include "mitkTeemDiffusionTensor3DReconstructionImageFilter.h" #include "itkDiffusionTensor3DReconstructionImageFilter.h" #include "itkTensorImageToDiffusionImageFilter.h" #include "itkPointShell.h" #include "itkVector.h" #include "itkB0ImageExtractionImageFilter.h" #include "mitkProperties.h" #include "mitkDataNodeObject.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include "mitkDiffusionImageMapper.h" #include "mitkLookupTableProperty.h" #include "mitkLookupTable.h" #include "mitkImageStatisticsHolder.h" #include "berryIStructuredSelection.h" #include "berryIWorkbenchWindow.h" #include "berryISelectionService.h" #include #include const std::string QmitkTensorReconstructionView::VIEW_ID = "org.mitk.views.tensorreconstruction"; #define DI_INFO MITK_INFO("DiffusionImaging") typedef float TTensorPixelType; typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType; typedef itk::Image< TensorPixelType, 3 > TensorImageType; using namespace berry; struct TrSelListener : ISelectionListener { berryObjectMacro(TrSelListener); TrSelListener(QmitkTensorReconstructionView* view) { m_View = view; } void DoSelectionChanged(ISelection::ConstPointer selection) { // if(!m_View->IsVisible()) // return; // save current selection in member variable m_View->m_CurrentSelection = selection.Cast(); // do something with the selected items if(m_View->m_CurrentSelection) { bool foundDwiVolume = false; bool foundTensorVolume = false; // iterate selection for (IStructuredSelection::iterator i = m_View->m_CurrentSelection->Begin(); i != m_View->m_CurrentSelection->End(); ++i) { // extract datatree node if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); - // only look at interesting types - if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0) + mitk::BaseData* nodeData = node->GetData(); + if( nodeData != NULL ) { - foundDwiVolume = true; - } + // only look at interesting types + if(QString("DiffusionImage").compare(nodeData->GetNameOfClass())==0) + { + foundDwiVolume = true; + } - // only look at interesting types - if(QString("TensorImage").compare(node->GetData()->GetNameOfClass())==0) - { - foundTensorVolume = true; + // only look at interesting types + if(QString("TensorImage").compare(nodeData->GetNameOfClass())==0) + { + foundTensorVolume = true; + } } } } m_View->m_Controls->m_ItkReconstruction->setEnabled(foundDwiVolume); m_View->m_Controls->m_TeemReconstruction->setEnabled(foundDwiVolume); m_View->m_Controls->m_TensorsToDWIButton->setEnabled(foundTensorVolume); m_View->m_Controls->m_TensorsToQbiButton->setEnabled(foundTensorVolume); m_View->m_Controls->m_ResidualButton->setEnabled(foundDwiVolume && foundTensorVolume); m_View->m_Controls->m_PercentagesOfOutliers->setEnabled(foundDwiVolume && foundTensorVolume); m_View->m_Controls->m_PerSliceView->setEnabled(foundDwiVolume && foundTensorVolume); } } void SelectionChanged(IWorkbenchPart::Pointer part, ISelection::ConstPointer selection) { // check, if selection comes from datamanager if (part) { QString partname(part->GetPartName().c_str()); if(partname.compare("Datamanager")==0) { // apply selection DoSelectionChanged(selection); } } } QmitkTensorReconstructionView* m_View; }; QmitkTensorReconstructionView::QmitkTensorReconstructionView() : QmitkFunctionality(), m_Controls(NULL), m_MultiWidget(NULL) { if(m_CurrentSelection) { mitk::DataStorage::SetOfObjects::Pointer set = mitk::DataStorage::SetOfObjects::New(); mitk::DiffusionImage::Pointer diffImage = mitk::DiffusionImage::New(); TensorImageType::Pointer tensorImage; std::string nodename; for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i) { if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); - if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0) - { - diffImage = static_cast*>((node)->GetData()); - } - else if((QString("TensorImage").compare(node->GetData()->GetNameOfClass())==0)) + + mitk::BaseData* nodeData = node->GetData(); + if(nodeData) { - mitk::TensorImage* mitkVol; - mitkVol = static_cast((node)->GetData()); - mitk::CastToItkImage(mitkVol, tensorImage); - node->GetStringProperty("name", nodename); + if(QString("DiffusionImage").compare(nodeData->GetNameOfClass())==0) + { + diffImage = static_cast*>((node)->GetData()); + } + else if((QString("TensorImage").compare(nodeData->GetNameOfClass())==0)) + { + mitk::TensorImage* mitkVol; + mitkVol = static_cast((node)->GetData()); + mitk::CastToItkImage(mitkVol, tensorImage); + node->GetStringProperty("name", nodename); + } } } } } } QmitkTensorReconstructionView::QmitkTensorReconstructionView(const QmitkTensorReconstructionView& other) { Q_UNUSED(other) throw std::runtime_error("Copy constructor not implemented"); } QmitkTensorReconstructionView::~QmitkTensorReconstructionView() { this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->RemovePostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener); } void QmitkTensorReconstructionView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkTensorReconstructionViewControls; m_Controls->setupUi(parent); this->CreateConnections(); QStringList items; items << "LLS (Linear Least Squares)" << "MLE (Maximum Likelihood)" << "NLS (Nonlinear Least Squares)" << "WLS (Weighted Least Squares)"; m_Controls->m_TensorEstimationTeemEstimationMethodCombo->addItems(items); m_Controls->m_TensorEstimationTeemEstimationMethodCombo->setCurrentIndex(0); m_Controls->m_TensorEstimationManualThreashold->setChecked(false); m_Controls->m_TensorEstimationTeemSigmaEdit->setText("NaN"); m_Controls->m_TensorEstimationTeemNumItsSpin->setValue(1); m_Controls->m_TensorEstimationTeemFuzzyEdit->setText("0.0"); m_Controls->m_TensorEstimationTeemMinValEdit->setText("1.0"); m_Controls->m_TensorEstimationTeemNumItsLabel_2->setEnabled(true); m_Controls->m_TensorEstimationTeemNumItsSpin->setEnabled(true); m_Controls->m_TensorsToDWIBValueEdit->setText("1000"); Advanced1CheckboxClicked(); Advanced2CheckboxClicked(); TeemCheckboxClicked(); #ifndef DIFFUSION_IMAGING_EXTENDED m_Controls->m_TeemToggle->setVisible(false); #endif // define data type for combobox //m_Controls->m_ImageSelector->SetDataStorage( this->GetDefaultDataStorage() ); //m_Controls->m_ImageSelector->SetPredicate( mitk::NodePredicateDataType::New("DiffusionImage") ); } m_SelListener = berry::ISelectionListener::Pointer(new TrSelListener(this)); this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener); berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); } void QmitkTensorReconstructionView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); m_MultiWidget = &stdMultiWidget; } void QmitkTensorReconstructionView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkTensorReconstructionView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_TeemToggle), SIGNAL(clicked()), this, SLOT(TeemCheckboxClicked()) ); connect( (QObject*)(m_Controls->m_ItkReconstruction), SIGNAL(clicked()), this, SLOT(ItkReconstruction()) ); connect( (QObject*)(m_Controls->m_TeemReconstruction), SIGNAL(clicked()), this, SLOT(TeemReconstruction()) ); connect( (QObject*)(m_Controls->m_TensorEstimationTeemEstimationMethodCombo), SIGNAL(currentIndexChanged(int)), this, SLOT(MethodChoosen(int)) ); connect( (QObject*)(m_Controls->m_Advanced1), SIGNAL(clicked()), this, SLOT(Advanced1CheckboxClicked()) ); connect( (QObject*)(m_Controls->m_Advanced2), SIGNAL(clicked()), this, SLOT(Advanced2CheckboxClicked()) ); connect( (QObject*)(m_Controls->m_TensorEstimationManualThreashold), SIGNAL(clicked()), this, SLOT(ManualThresholdClicked()) ); connect( (QObject*)(m_Controls->m_TensorsToDWIButton), SIGNAL(clicked()), this, SLOT(TensorsToDWI()) ); connect( (QObject*)(m_Controls->m_TensorsToQbiButton), SIGNAL(clicked()), this, SLOT(TensorsToQbi()) ); connect( (QObject*)(m_Controls->m_ResidualButton), SIGNAL(clicked()), this, SLOT(ResidualCalculation()) ); connect( (QObject*)(m_Controls->m_PerSliceView), SIGNAL(pointSelected(int, int)), this, SLOT(ResidualClicked(int, int)) ); } } void QmitkTensorReconstructionView::ResidualClicked(int slice, int volume) { // Use image coord to reset crosshair // Find currently selected diffusion image // Update Label // to do: This position should be modified in order to skip B0 volumes that are not taken into account // when calculating residuals // Find the diffusion image mitk::DiffusionImage* diffImage; mitk::DataNodeObject::Pointer nodeObj; mitk::DataNode::Pointer correctNode; mitk::Geometry3D* geometry; for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i) { if (nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); - if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0) + // process only on valid nodes + mitk::BaseData* nodeData = node->GetData(); + if(nodeData) { - diffImage = static_cast*>((node)->GetData()); + if(QString("DiffusionImage").compare(nodeData->GetNameOfClass())==0) + { + diffImage = static_cast*>(nodeData); - geometry = diffImage->GetGeometry(); + geometry = diffImage->GetGeometry(); - // Remember the node whose display index must be updated - correctNode = mitk::DataNode::New(); - correctNode = node; + // Remember the node whose display index must be updated + correctNode = mitk::DataNode::New(); + correctNode = node; + } } } } if(diffImage != NULL) { typedef vnl_vector_fixed< double, 3 > GradientDirectionType; typedef itk::VectorContainer< unsigned int, GradientDirectionType > GradientDirectionContainerType; GradientDirectionContainerType::Pointer dirs = diffImage->GetDirections(); for(int i=0; iSize() && i<=volume; i++) { GradientDirectionType grad = dirs->ElementAt(i); // check if image is b0 weighted if(fabs(grad[0]) < 0.001 && fabs(grad[1]) < 0.001 && fabs(grad[2]) < 0.001) { volume++; } } QString pos = "Volume: "; pos.append(QString::number(volume)); pos.append(", Slice: "); pos.append(QString::number(slice)); m_Controls->m_PositionLabel->setText(pos); if(correctNode) { int oldDisplayVal; correctNode->GetIntProperty("DisplayChannel", oldDisplayVal); std::string oldVal = QString::number(oldDisplayVal).toStdString(); std::string newVal = QString::number(volume).toStdString(); correctNode->SetIntProperty("DisplayChannel",volume); correctNode->SetSelected(true); this->FirePropertyChanged("DisplayChannel", oldVal, newVal); correctNode->UpdateOutputInformation(); mitk::Point3D p3 = m_MultiWidget->GetCrossPosition(); itk::Index<3> ix; geometry->WorldToIndex(p3, ix); // ix[2] = slice; mitk::Vector3D vec; vec[0] = ix[0]; vec[1] = ix[1]; vec[2] = slice; mitk::Vector3D v3New; geometry->IndexToWorld(vec, v3New); mitk::Point3D origin = geometry->GetOrigin(); mitk::Point3D p3New; p3New[0] = v3New[0] + origin[0]; p3New[1] = v3New[1] + origin[1]; p3New[2] = v3New[2] + origin[2]; m_MultiWidget->MoveCrossToPosition(p3New); m_MultiWidget->RequestUpdate(); } } } void QmitkTensorReconstructionView::TeemCheckboxClicked() { m_Controls->groupBox_3->setVisible(m_Controls-> m_TeemToggle->isChecked()); } void QmitkTensorReconstructionView::Advanced1CheckboxClicked() { bool check = m_Controls-> m_Advanced1->isChecked(); m_Controls->frame->setVisible(check); } void QmitkTensorReconstructionView::Advanced2CheckboxClicked() { bool check = m_Controls-> m_Advanced2->isChecked(); m_Controls->frame_2->setVisible(check); } void QmitkTensorReconstructionView::ManualThresholdClicked() { m_Controls->m_TensorReconstructionThreasholdEdit_2->setEnabled( m_Controls->m_TensorEstimationManualThreashold->isChecked()); } void QmitkTensorReconstructionView::Activated() { QmitkFunctionality::Activated(); } void QmitkTensorReconstructionView::Deactivated() { QmitkFunctionality::Deactivated(); } void QmitkTensorReconstructionView::MethodChoosen(int method) { m_Controls->m_TensorEstimationTeemNumItsLabel_2->setEnabled(method==3); m_Controls->m_TensorEstimationTeemNumItsSpin->setEnabled(method==3); } void QmitkTensorReconstructionView::ResidualCalculation() { // Extract dwi and dti from current selection // In case of multiple selections, take the first one, since taking all combinations is not meaningful if(m_CurrentSelection) { mitk::DataStorage::SetOfObjects::Pointer set = mitk::DataStorage::SetOfObjects::New(); mitk::DiffusionImage::Pointer diffImage = mitk::DiffusionImage::New(); TensorImageType::Pointer tensorImage; std::string nodename; for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); - i != m_CurrentSelection->End(); - ++i) + i != m_CurrentSelection->End(); + ++i) { if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); - if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0) - { - diffImage = static_cast*>((node)->GetData()); - } - else if((QString("TensorImage").compare(node->GetData()->GetNameOfClass())==0)) + + // process only on valid nodes + mitk::BaseData* nodeData = node->GetData(); + if(nodeData) { - mitk::TensorImage* mitkVol; - mitkVol = static_cast((node)->GetData()); - mitk::CastToItkImage(mitkVol, tensorImage); - node->GetStringProperty("name", nodename); + if(QString("DiffusionImage").compare(nodeData->GetNameOfClass())==0) + { + diffImage = static_cast*>((node)->GetData()); + } + else if((QString("TensorImage").compare(nodeData->GetNameOfClass())==0)) + { + mitk::TensorImage* mitkVol; + mitkVol = static_cast(nodeData); + mitk::CastToItkImage(mitkVol, tensorImage); + node->GetStringProperty("name", nodename); + } } } } typedef itk::TensorImageToDiffusionImageFilter< TTensorPixelType, DiffusionPixelType > FilterType; FilterType::GradientListType gradientList; mitk::DiffusionImage::GradientDirectionContainerType* gradients = diffImage->GetDirections(); // Copy gradients vectors from gradients to gradientList for(int i=0; iSize(); i++) { mitk::DiffusionImage::GradientDirectionType vec = gradients->at(i); itk::Vector grad; grad[0] = vec[0]; grad[1] = vec[1]; grad[2] = vec[2]; gradientList.push_back(grad); } // Find the min and the max values from a baseline image mitk::ImageStatisticsHolder *stats = diffImage->GetStatistics(); //Initialize filter that calculates the modeled diffusion weighted signals FilterType::Pointer filter = FilterType::New(); filter->SetInput( tensorImage ); filter->SetBValue(diffImage->GetB_Value()); filter->SetGradientList(gradientList); filter->SetMin(stats->GetScalarValueMin()); filter->SetMax(500); filter->Update(); // TENSORS TO DATATREE mitk::DiffusionImage::Pointer image = mitk::DiffusionImage::New(); image->SetVectorImage( filter->GetOutput() ); image->SetB_Value(diffImage->GetB_Value()); image->SetDirections(gradientList); image->SetOriginalDirections(gradientList); image->InitializeFromVectorImage(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); mitk::DiffusionImageMapper::SetDefaultProperties(node); QString newname; newname = newname.append(nodename.c_str()); newname = newname.append("_dwi"); node->SetName(newname.toAscii()); GetDefaultDataStorage()->Add(node); std::vector b0Indices = image->GetB0Indices(); typedef itk::ResidualImageFilter ResidualImageFilterType; ResidualImageFilterType::Pointer residualFilter = ResidualImageFilterType::New(); residualFilter->SetInput(diffImage->GetVectorImage()); residualFilter->SetSecondDiffusionImage(image->GetVectorImage()); residualFilter->SetGradients(gradients); residualFilter->SetB0Index(b0Indices[0]); residualFilter->SetB0Threshold(30); residualFilter->Update(); itk::Image::Pointer residualImage = itk::Image::New(); residualImage = residualFilter->GetOutput(); mitk::Image::Pointer mitkResImg = mitk::Image::New(); mitk::CastToMitkImage(residualImage, mitkResImg); stats = mitkResImg->GetStatistics(); float min = stats->GetScalarValueMin(); float max = stats->GetScalarValueMax(); mitk::LookupTableProperty::Pointer lutProp = mitk::LookupTableProperty::New(); mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); vtkSmartPointer lookupTable = vtkSmartPointer::New(); lookupTable->SetTableRange(min, max); // If you don't want to use the whole color range, you can use // SetValueRange, SetHueRange, and SetSaturationRange lookupTable->Build(); int size = lookupTable->GetTable()->GetSize(); vtkSmartPointer reversedlookupTable = vtkSmartPointer::New(); reversedlookupTable->SetTableRange(min+1, max); reversedlookupTable->Build(); for(int i=0; i<256; i++) { double* rgba = reversedlookupTable->GetTableValue(255-i); lookupTable->SetTableValue(i, rgba[0], rgba[1], rgba[2], rgba[3]); } lut->SetVtkLookupTable(lookupTable); lutProp->SetLookupTable(lut); // Create lookuptable mitk::DataNode::Pointer resNode=mitk::DataNode::New(); resNode->SetData( mitkResImg ); resNode->SetName("Residual Image"); resNode->SetProperty("LookupTable", lutProp); bool b; resNode->GetBoolProperty("use color", b); resNode->SetBoolProperty("use color", false); GetDefaultDataStorage()->Add(resNode); m_MultiWidget->RequestUpdate(); // Draw Graph std::vector means = residualFilter->GetMeans(); std::vector q1s = residualFilter->GetQ1(); std::vector q3s = residualFilter->GetQ3(); std::vector percentagesOfOUtliers = residualFilter->GetPercentagesOfOutliers(); m_Controls->m_ResidualAnalysis->SetMeans(means); m_Controls->m_ResidualAnalysis->SetQ1(q1s); m_Controls->m_ResidualAnalysis->SetQ3(q3s); m_Controls->m_ResidualAnalysis->SetPercentagesOfOutliers(percentagesOfOUtliers); if(m_Controls->m_PercentagesOfOutliers->isChecked()) { m_Controls->m_ResidualAnalysis->DrawPercentagesOfOutliers(); } else { m_Controls->m_ResidualAnalysis->DrawMeans(); } // Draw Graph for volumes per slice in the QGraphicsView std::vector< std::vector > outliersPerSlice = residualFilter->GetOutliersPerSlice(); int xSize = outliersPerSlice.size(); if(xSize == 0) { return; } int ySize = outliersPerSlice[0].size(); // Find maximum in outliersPerSlice double maxOutlier= 0.0; for(int i=0; imaxOutlier) { maxOutlier = outliersPerSlice[i][j]; } } } // Create some QImage QImage qImage(xSize, ySize, QImage::Format_RGB32); QImage legend(1, 256, QImage::Format_RGB32); QRgb value; vtkSmartPointer lookup = vtkSmartPointer::New(); lookup->SetTableRange(0.0, maxOutlier); lookup->Build(); reversedlookupTable->SetTableRange(0, maxOutlier); reversedlookupTable->Build(); for(int i=0; i<256; i++) { double* rgba = reversedlookupTable->GetTableValue(255-i); lookup->SetTableValue(i, rgba[0], rgba[1], rgba[2], rgba[3]); } // Fill qImage for(int i=0; iMapValue(out); int r, g, b; r = _rgba[0]; g = _rgba[1]; b = _rgba[2]; value = qRgb(r, g, b); qImage.setPixel(i,j,value); } } for(int i=0; i<256; i++) { double* rgba = lookup->GetTableValue(i); int r, g, b; r = rgba[0]*255; g = rgba[1]*255; b = rgba[2]*255; value = qRgb(r, g, b); legend.setPixel(0,255-i,value); } QString upper = QString::number(maxOutlier, 'g', 3); upper.append(" %"); QString lower = QString::number(0.0); lower.append(" %"); m_Controls->m_UpperLabel->setText(upper); m_Controls->m_LowerLabel->setText(lower); QGraphicsScene* scene = new QGraphicsScene; QGraphicsScene* scene2 = new QGraphicsScene; QPixmap pixmap(QPixmap::fromImage(qImage)); QGraphicsPixmapItem *item = new QGraphicsPixmapItem( pixmap, 0, scene); item->scale(10.0, 3.0); QPixmap pixmap2(QPixmap::fromImage(legend)); QGraphicsPixmapItem *item2 = new QGraphicsPixmapItem( pixmap2, 0, scene2); item2->scale(20.0, 1.0); m_Controls->m_PerSliceView->SetResidualPixmapItem(item); m_Controls->m_PerSliceView->setScene(scene); m_Controls->m_LegendView->setScene(scene2); m_Controls->m_PerSliceView->show(); m_Controls->m_PerSliceView->repaint(); m_Controls->m_LegendView->setHorizontalScrollBarPolicy ( Qt::ScrollBarAlwaysOff ); m_Controls->m_LegendView->setVerticalScrollBarPolicy ( Qt::ScrollBarAlwaysOff ); m_Controls->m_LegendView->show(); m_Controls->m_LegendView->repaint(); } } void QmitkTensorReconstructionView::ItkReconstruction() { Reconstruct(0); } void QmitkTensorReconstructionView::TeemReconstruction() { Reconstruct(1); } void QmitkTensorReconstructionView::Reconstruct(int method) { if (m_CurrentSelection) { mitk::DataStorage::SetOfObjects::Pointer set = mitk::DataStorage::SetOfObjects::New(); int at = 0; for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i) { if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0) { set->InsertElement(at++, node); } } } if(method == 0) { ItkTensorReconstruction(set); } if(method == 1) { TeemTensorReconstruction(set); } } } void QmitkTensorReconstructionView::ItkTensorReconstruction (mitk::DataStorage::SetOfObjects::Pointer inImages) { try { itk::TimeProbe clock; int nrFiles = inImages->size(); if (!nrFiles) return; QString status; mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles); mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { mitk::DiffusionImage* vols = static_cast*>( (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); ++itemiter; // TENSOR RECONSTRUCTION clock.Start(); MBI_INFO << "Tensor reconstruction "; mitk::StatusBar::GetInstance()->DisplayText(status.sprintf( "Tensor reconstruction for %s", nodename.c_str()).toAscii()); typedef itk::DiffusionTensor3DReconstructionImageFilter< DiffusionPixelType, DiffusionPixelType, TTensorPixelType > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer tensorReconstructionFilter = TensorReconstructionImageFilterType::New(); + + + mitk::DiffusionImage::GradientDirectionContainerType::Pointer dirs = vols->GetDirections(); + itk::VectorImage::Pointer img = vols->GetVectorImage(); + tensorReconstructionFilter->SetGradientImage( vols->GetDirections(), vols->GetVectorImage() ); tensorReconstructionFilter->SetBValue(vols->GetB_Value()); tensorReconstructionFilter->SetThreshold( m_Controls->m_TensorReconstructionThreasholdEdit->text().toFloat() ); tensorReconstructionFilter->Update(); clock.Stop(); MBI_DEBUG << "took " << clock.GetMeanTime() << "s."; // TENSORS TO DATATREE mitk::TensorImage::Pointer image = mitk::TensorImage::New(); typedef itk::Image, 3> TensorImageType; TensorImageType::Pointer tensorImage; tensorImage = tensorReconstructionFilter->GetOutput(); // Check the tensor for negative eigenvalues if(m_Controls->m_CheckNegativeEigenvalues->isChecked()) { typedef itk::ImageRegionIterator TensorImageIteratorType; TensorImageIteratorType tensorIt(tensorImage, tensorImage->GetRequestedRegion()); tensorIt.GoToBegin(); while(!tensorIt.IsAtEnd()) { typedef itk::DiffusionTensor3D TensorType; //typedef itk::Tensor TensorType2; TensorType tensor = tensorIt.Get(); // TensorType2 tensor2; /* for(int i=0; i SymEigenSystemType; SymEigenSystemType eig (tensor2.GetVnlMatrix()); for(unsigned int i=0; iInitializeByItk( tensorImage.GetPointer() ); image->SetVolume( tensorReconstructionFilter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( image ); QString newname; newname = newname.append(nodename.c_str()); newname = newname.append("_dti"); SetDefaultNodeProperties(node, newname.toStdString()); nodes.push_back(node); mitk::ProgressBar::GetInstance()->Progress(); } std::vector::iterator nodeIt; for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt) GetDefaultDataStorage()->Add(*nodeIt); mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toAscii()); m_MultiWidget->RequestUpdate(); } catch (itk::ExceptionObject &ex) { MBI_INFO << ex ; return ; } } void QmitkTensorReconstructionView::TeemTensorReconstruction (mitk::DataStorage::SetOfObjects::Pointer inImages) { try { itk::TimeProbe clock; int nrFiles = inImages->size(); if (!nrFiles) return; QString status; mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles); mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { mitk::DiffusionImage* vols = static_cast*>( (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); ++itemiter; // TENSOR RECONSTRUCTION clock.Start(); MBI_INFO << "Teem Tensor reconstruction "; mitk::StatusBar::GetInstance()->DisplayText(status.sprintf( "Teem Tensor reconstruction for %s", nodename.c_str()).toAscii()); typedef mitk::TeemDiffusionTensor3DReconstructionImageFilter< DiffusionPixelType, TTensorPixelType > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer tensorReconstructionFilter = TensorReconstructionImageFilterType::New(); tensorReconstructionFilter->SetInput( vols ); if(!m_Controls->m_TensorEstimationTeemSigmaEdit->text().contains(QString("NaN"))) tensorReconstructionFilter->SetSigma( m_Controls->m_TensorEstimationTeemSigmaEdit->text().toFloat() ); switch(m_Controls->m_TensorEstimationTeemEstimationMethodCombo->currentIndex()) { // items << "LLS (Linear Least Squares)" //<< "MLE (Maximum Likelihood)" //<< "NLS (Nonlinear Least Squares)" //<< "WLS (Weighted Least Squares)"; case 0: tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsLLS); break; case 1: tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsMLE); break; case 2: tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsNLS); break; case 3: tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsWLS); break; default: tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsLLS); } tensorReconstructionFilter->SetNumIterations( m_Controls->m_TensorEstimationTeemNumItsSpin->value() ); if(m_Controls->m_TensorEstimationManualThreashold->isChecked()) tensorReconstructionFilter->SetConfidenceThreshold( m_Controls->m_TensorReconstructionThreasholdEdit_2->text().toDouble() ); tensorReconstructionFilter->SetConfidenceFuzzyness( m_Controls->m_TensorEstimationTeemFuzzyEdit->text().toFloat() ); tensorReconstructionFilter->SetMinPlausibleValue( m_Controls->m_TensorEstimationTeemMinValEdit->text().toDouble() ); tensorReconstructionFilter->Update(); clock.Stop(); MBI_DEBUG << "took " << clock.GetMeanTime() << "s." ; // TENSORS TO DATATREE mitk::DataNode::Pointer node2=mitk::DataNode::New(); node2->SetData( tensorReconstructionFilter->GetOutputItk() ); QString newname; newname = newname.append(nodename.c_str()); newname = newname.append("_dtix"); SetDefaultNodeProperties(node2, newname.toStdString()); nodes.push_back(node2); mitk::ProgressBar::GetInstance()->Progress(); } std::vector::iterator nodeIt; for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt) GetDefaultDataStorage()->Add(*nodeIt); mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toAscii()); m_MultiWidget->RequestUpdate(); } catch (itk::ExceptionObject &ex) { MBI_INFO << ex ; return ; } } void QmitkTensorReconstructionView::SetDefaultNodeProperties(mitk::DataNode::Pointer node, std::string name) { node->SetProperty( "ShowMaxNumber", mitk::IntProperty::New( 500 ) ); node->SetProperty( "Scaling", mitk::FloatProperty::New( 1.0 ) ); node->SetProperty( "Normalization", mitk::OdfNormalizationMethodProperty::New()); node->SetProperty( "ScaleBy", mitk::OdfScaleByProperty::New()); node->SetProperty( "IndexParam1", mitk::FloatProperty::New(2)); node->SetProperty( "IndexParam2", mitk::FloatProperty::New(1)); node->SetProperty( "visible", mitk::BoolProperty::New( true ) ); node->SetProperty( "VisibleOdfs", mitk::BoolProperty::New( false ) ); node->SetProperty ("layer", mitk::IntProperty::New(100)); node->SetProperty( "DoRefresh", mitk::BoolProperty::New( true ) ); //node->SetProperty( "opacity", mitk::FloatProperty::New(1.0f) ); node->SetProperty( "name", mitk::StringProperty::New(name) ); } //node->SetProperty( "volumerendering", mitk::BoolProperty::New( false ) ); //node->SetProperty( "use color", mitk::BoolProperty::New( true ) ); //node->SetProperty( "texture interpolation", mitk::BoolProperty::New( true ) ); //node->SetProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ); //node->SetProperty( "layer", mitk::IntProperty::New(0)); //node->SetProperty( "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ); //node->SetOpacity(1.0f); //node->SetColor(1.0,1.0,1.0); //node->SetVisibility(true); //node->SetProperty( "IsTensorVolume", mitk::BoolProperty::New( true ) ); //mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); //mitk::LevelWindow levelwindow; //// levelwindow.SetAuto( image ); //levWinProp->SetLevelWindow( levelwindow ); //node->GetPropertyList()->SetProperty( "levelwindow", levWinProp ); //// add a default rainbow lookup table for color mapping //if(!node->GetProperty("LookupTable")) //{ // mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); // vtkLookupTable* vtkLut = mitkLut->GetVtkLookupTable(); // vtkLut->SetHueRange(0.6667, 0.0); // vtkLut->SetTableRange(0.0, 20.0); // vtkLut->Build(); // mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); // mitkLutProp->SetLookupTable(mitkLut); // node->SetProperty( "LookupTable", mitkLutProp ); //} //if(!node->GetProperty("binary")) // node->SetProperty( "binary", mitk::BoolProperty::New( false ) ); //// add a default transfer function //mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New(); //node->SetProperty ( "TransferFunction", mitk::TransferFunctionProperty::New ( tf.GetPointer() ) ); //// set foldername as string property //mitk::StringProperty::Pointer nameProp = mitk::StringProperty::New( name ); //node->SetProperty( "name", nameProp ); void QmitkTensorReconstructionView::TensorsToDWI() { if (m_CurrentSelection) { mitk::DataStorage::SetOfObjects::Pointer set = mitk::DataStorage::SetOfObjects::New(); int at = 0; for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i) { if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); - if(QString("TensorImage").compare(node->GetData()->GetNameOfClass())==0) + // process only on valid nodes + const mitk::BaseData* nodeData = node->GetData(); + if(nodeData) { - set->InsertElement(at++, node); + if(QString("TensorImage").compare(nodeData->GetNameOfClass())==0) + { + set->InsertElement(at++, node); + } } } } DoTensorsToDWI(set); } } void QmitkTensorReconstructionView::TensorsToQbi() { std::vector nodes = this->GetDataManagerSelection(); for (int i=0; i TensorPixelType; typedef itk::Image< TensorPixelType, 3 > TensorImageType; TensorImageType::Pointer itkvol = TensorImageType::New(); mitk::CastToItkImage(dynamic_cast(tensorImageNode->GetData()), itkvol); typedef itk::TensorImageToQBallImageFilter< TTensorPixelType, TTensorPixelType > FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkvol ); filter->Update(); typedef itk::Vector OutputPixelType; typedef itk::Image OutputImageType; mitk::QBallImage::Pointer image = mitk::QBallImage::New(); OutputImageType::Pointer outimg = filter->GetOutput(); image->InitializeByItk( outimg.GetPointer() ); image->SetVolume( outimg->GetBufferPointer() ); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); QString newname; newname = newname.append(tensorImageNode->GetName().c_str()); newname = newname.append("_qbi"); node->SetName(newname.toAscii()); GetDefaultDataStorage()->Add(node); } } void QmitkTensorReconstructionView::OnSelectionChanged( std::vector nodes ) { if ( !this->IsVisible() ) return; } template std::vector > QmitkTensorReconstructionView::MakeGradientList() { std::vector > retval; vnl_matrix_fixed* U = itk::PointShell >::DistributePointShell(); for(int i=0; i v; v[0] = U->get(0,i); v[1] = U->get(1,i); v[2] = U->get(2,i); retval.push_back(v); } // Add 0 vector for B0 itk::Vector v; v.Fill(0.0); retval.push_back(v); return retval; } void QmitkTensorReconstructionView::DoTensorsToDWI (mitk::DataStorage::SetOfObjects::Pointer inImages) { try { itk::TimeProbe clock; int nrFiles = inImages->size(); if (!nrFiles) return; QString status; mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles); mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { std::string nodename; (*itemiter)->GetStringProperty("name", nodename); mitk::TensorImage* vol = static_cast((*itemiter)->GetData()); ++itemiter; typedef float TTensorPixelType; typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType; typedef itk::Image< TensorPixelType, 3 > TensorImageType; TensorImageType::Pointer itkvol = TensorImageType::New(); mitk::CastToItkImage(vol, itkvol); typedef itk::TensorImageToDiffusionImageFilter< TTensorPixelType, DiffusionPixelType > FilterType; FilterType::GradientListType gradientList; switch(m_Controls->m_TensorsToDWINumDirsSelect->currentIndex()) { case 0: gradientList = MakeGradientList<12>(); break; case 1: gradientList = MakeGradientList<42>(); break; case 2: gradientList = MakeGradientList<92>(); break; case 3: gradientList = MakeGradientList<162>(); break; case 4: gradientList = MakeGradientList<252>(); break; case 5: gradientList = MakeGradientList<362>(); break; case 6: gradientList = MakeGradientList<492>(); break; case 7: gradientList = MakeGradientList<642>(); break; case 8: gradientList = MakeGradientList<812>(); break; case 9: gradientList = MakeGradientList<1002>(); break; default: gradientList = MakeGradientList<92>(); } double bVal = m_Controls->m_TensorsToDWIBValueEdit->text().toDouble(); // DWI ESTIMATION clock.Start(); MBI_INFO << "DWI Estimation "; mitk::StatusBar::GetInstance()->DisplayText(status.sprintf( "DWI Estimation for %s", nodename.c_str()).toAscii()); FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkvol ); filter->SetBValue(bVal); filter->SetGradientList(gradientList); //filter->SetNumberOfThreads(1); filter->Update(); clock.Stop(); MBI_DEBUG << "took " << clock.GetMeanTime() << "s."; - itk::Vector v; - v[0] = 0; v[1] = 0; v[2] = 0; - gradientList.push_back(v); - // TENSORS TO DATATREE mitk::DiffusionImage::Pointer image = mitk::DiffusionImage::New(); image->SetVectorImage( filter->GetOutput() ); image->SetB_Value(bVal); image->SetDirections(gradientList); image->SetOriginalDirections(gradientList); image->InitializeFromVectorImage(); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( image ); mitk::DiffusionImageMapper::SetDefaultProperties(node); QString newname; newname = newname.append(nodename.c_str()); newname = newname.append("_dwi"); node->SetName(newname.toAscii()); nodes.push_back(node); mitk::ProgressBar::GetInstance()->Progress(); } std::vector::iterator nodeIt; for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt) GetDefaultDataStorage()->Add(*nodeIt); mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toAscii()); m_MultiWidget->RequestUpdate(); } catch (itk::ExceptionObject &ex) { MBI_INFO << ex ; return ; } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.cpp index 5f269b8134..4ec33c8f57 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.cpp @@ -1,1767 +1,1498 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $ Version: $Revision: 21975 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ // Blueberry #include "berryIWorkbenchWindow.h" #include "berryIWorkbenchPage.h" #include "berryISelectionService.h" #include "berryConstants.h" #include "berryPlatformUI.h" // Qmitk #include "QmitkTractbasedSpatialStatisticsView.h" #include "QmitkStdMultiWidget.h" #include "mitkDataNodeObject.h" #include // Qt #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vtkFloatArray.h" #include "vtkLinearTransform.h" #include "vtkPoints.h" #include "mitkSurface.h" #include #include "vtkArrowSource.h" #include "vtkUnstructuredGrid.h" #include "vtkPointData.h" #include #include #include #include #include #include "mitkITKImageImport.h" // #include "mitkImageMapperGL2D.h" #include "mitkVolumeDataVtkMapper3D.h" #include "mitkImageAccessByItk.h" #include "mitkTensorImage.h" #include "itkDiffusionTensor3D.h" #define SEARCHSIGMA 10 /* length in linear voxel dimens { // create new ones m_PointSetNode = mitk::PointSet::New();ions */ #define MAXSEARCHLENGTH (3*SEARCHSIGMA) const std::string QmitkTractbasedSpatialStatisticsView::VIEW_ID = "org.mitk.views.tractbasedspatialstatistics"; using namespace berry; struct TbssSelListener : ISelectionListener { berryObjectMacro(TbssSelListener) TbssSelListener(QmitkTractbasedSpatialStatisticsView* view) { m_View = view; } void DoSelectionChanged(ISelection::ConstPointer selection) { // save current selection in member variable m_View->m_CurrentSelection = selection.Cast(); // do something with the selected items if(m_View->m_CurrentSelection) { bool foundTbssRoi = false; bool foundTbss = false; bool found3dImage = false; bool found4dImage = false; bool foundFiberBundle = false; mitk::TbssRoiImage* roiImage; mitk::TbssImage* image; mitk::Image* img; mitk::FiberBundleX* fib; // iterate selection for (IStructuredSelection::iterator i = m_View->m_CurrentSelection->Begin(); i != m_View->m_CurrentSelection->End(); ++i) { // extract datatree node if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); // only look at interesting types - - if(QString("TbssRoiImage").compare(node->GetData()->GetNameOfClass())==0) - { - foundTbssRoi = true; - roiImage = static_cast(node->GetData()); - } - else if (QString("TbssImage").compare(node->GetData()->GetNameOfClass())==0) - { - foundTbss = true; - image = static_cast(node->GetData()); - } - else if(QString("Image").compare(node->GetData()->GetNameOfClass())==0) + // check for valid data + mitk::BaseData* nodeData = node->GetData(); + if( nodeData ) { - img = static_cast(node->GetData()); - if(img->GetDimension() == 3) + if(QString("TbssRoiImage").compare(nodeData->GetNameOfClass())==0) { - found3dImage = true; + foundTbssRoi = true; + roiImage = static_cast(nodeData); } - else if(img->GetDimension() == 4) + else if (QString("TbssImage").compare(nodeData->GetNameOfClass())==0) { - found4dImage = true; + foundTbss = true; + image = static_cast(nodeData); + } + else if(QString("Image").compare(nodeData->GetNameOfClass())==0) + { + img = static_cast(nodeData); + if(img->GetDimension() == 3) + { + found3dImage = true; + } + else if(img->GetDimension() == 4) + { + found4dImage = true; + } } - } - else if (QString("FiberBundleX").compare(node->GetData()->GetNameOfClass())==0) + else if (QString("FiberBundleX").compare(nodeData->GetNameOfClass())==0) { foundFiberBundle = true; - fib = static_cast(node->GetData()); + fib = static_cast(nodeData); } + } // end CHECK nodeData != NULL } } - - m_View->m_Controls->m_Transform->setEnabled(found3dImage); m_View->m_Controls->m_CreateRoi->setEnabled(found3dImage); m_View->m_Controls->m_ImportFsl->setEnabled(found4dImage); + if(found3dImage) { m_View->InitPointsets(); } if(foundTbss && foundTbssRoi) { m_View->Plot(image, roiImage); } if(found3dImage == true && foundFiberBundle) { m_View->PlotFiberBundle(fib, img); } } } void SelectionChanged(IWorkbenchPart::Pointer part, ISelection::ConstPointer selection) { // check, if selection comes from datamanager if (part) { QString partname(part->GetPartName().c_str()); if(partname.compare("Datamanager")==0) { // apply selection DoSelectionChanged(selection); } } } QmitkTractbasedSpatialStatisticsView* m_View; }; QmitkTractbasedSpatialStatisticsView::QmitkTractbasedSpatialStatisticsView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) { } QmitkTractbasedSpatialStatisticsView::~QmitkTractbasedSpatialStatisticsView() { } void QmitkTractbasedSpatialStatisticsView::OnSelectionChanged(std::vector nodes) { //datamanager selection changed if (!this->IsActivated()) return; // Get DataManagerSelection if (!this->GetDataManagerSelection().empty()) { mitk::DataNode::Pointer sourceImageNode = this->GetDataManagerSelection().front(); mitk::Image::Pointer sourceImage = dynamic_cast(sourceImageNode->GetData()); if (!sourceImage) { m_Controls->m_TbssImageLabel->setText( QString( sourceImageNode->GetName().c_str() ) + " is no image" ); return; } // set Text m_Controls->m_TbssImageLabel->setText( QString( sourceImageNode->GetName().c_str() ) + " (" + QString::number(sourceImage->GetDimension()) + "D)" ); } else { m_Controls->m_TbssImageLabel->setText("Please select an image"); } } void QmitkTractbasedSpatialStatisticsView::InitPointsets() { // Check if PointSetStart exsits, if not create it. m_P1 = this->GetDefaultDataStorage()->GetNamedNode("PointSetNode"); if (m_PointSetNode) { //m_PointSetNode = dynamic_cast(m_P1->GetData()); return; } if ((!m_P1) || (!m_PointSetNode)) { // create new ones m_PointSetNode = mitk::PointSet::New(); m_P1 = mitk::DataNode::New(); m_P1->SetData( m_PointSetNode ); m_P1->SetProperty( "name", mitk::StringProperty::New( "PointSet" ) ); m_P1->SetProperty( "opacity", mitk::FloatProperty::New( 1 ) ); m_P1->SetProperty( "helper object", mitk::BoolProperty::New(false) ); // CHANGE if wanted m_P1->SetProperty( "pointsize", mitk::FloatProperty::New( 0.1 ) ); m_P1->SetColor( 1.0, 0.0, 0.0 ); this->GetDefaultDataStorage()->Add(m_P1); m_Controls->m_PointWidget->SetPointSetNode(m_P1); m_Controls->m_PointWidget->SetMultiWidget(GetActiveStdMultiWidget()); } } void QmitkTractbasedSpatialStatisticsView::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::QmitkTractbasedSpatialStatisticsViewControls; m_Controls->setupUi( parent ); this->CreateConnections(); } m_SelListener = berry::ISelectionListener::Pointer(new TbssSelListener(this)); this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener); berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); m_IsInitialized = false; // Table for the FSL TBSS import m_GroupModel = new QmitkTbssTableModel(); m_Controls->m_GroupInfo->setModel(m_GroupModel); } void QmitkTractbasedSpatialStatisticsView::Activated() { QmitkFunctionality::Activated(); berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); } void QmitkTractbasedSpatialStatisticsView::Deactivated() { QmitkFunctionality::Deactivated(); } void QmitkTractbasedSpatialStatisticsView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_CreateRoi), SIGNAL(clicked()), this, SLOT(CreateRoi()) ); connect( (QObject*)(m_Controls->m_ImportFsl), SIGNAL(clicked()), this, SLOT(TbssImport()) ); connect( (QObject*)(m_Controls->m_AddGroup), SIGNAL(clicked()), this, SLOT(AddGroup()) ); connect( (QObject*)(m_Controls->m_RemoveGroup), SIGNAL(clicked()), this, SLOT(RemoveGroup()) ); connect( (QObject*)(m_Controls->m_Clipboard), SIGNAL(clicked()), this, SLOT(CopyToClipboard()) ); connect( m_Controls->m_RoiPlotWidget->m_PlotPicker, SIGNAL(selected(const QwtDoublePoint&)), SLOT(Clicked(const QwtDoublePoint&) ) ); - connect( m_Controls->m_RoiPlotWidget->m_PlotPicker, SIGNAL(moved(const QwtDoublePoint&)), SLOT(Clicked(const QwtDoublePoint&) ) ); - connect( (QObject*)(m_Controls->m_SetDxx), SIGNAL(clicked()), this, SLOT(SetDxx()) ); - connect( (QObject*)(m_Controls->m_SetDxy), SIGNAL(clicked()), this, SLOT(SetDxy()) ); - connect( (QObject*)(m_Controls->m_SetDxz), SIGNAL(clicked()), this, SLOT(SetDxz()) ); - connect( (QObject*)(m_Controls->m_SetDyy), SIGNAL(clicked()), this, SLOT(SetDyy()) ); - connect( (QObject*)(m_Controls->m_SetDyz), SIGNAL(clicked()), this, SLOT(SetDyz()) ); - connect( (QObject*)(m_Controls->m_SetDzz), SIGNAL(clicked()), this, SLOT(SetDzz()) ); - connect( (QObject*)(m_Controls->m_TensorByComps), SIGNAL(clicked()), this, SLOT(ImportTensorByComps()) ); - } -} - -void QmitkTractbasedSpatialStatisticsView::ImportTensorByComps() -{ - if(m_DxxNode.IsNull() || m_DxyNode.IsNull() || m_DxzNode.IsNull() - || m_DyzNode.IsNull() || m_DyyNode.IsNull() || m_DzzNode.IsNull() ) - { - return; - } - - mitk::Image* img = static_cast(m_DxxNode->GetData()); - FloatImageType::Pointer Dxx = FloatImageType::New(); - mitk::CastToItkImage(img, Dxx); - - img = static_cast(m_DxyNode->GetData()); - FloatImageType::Pointer Dxy = FloatImageType::New(); - mitk::CastToItkImage(img, Dxy); - - img = static_cast(m_DxzNode->GetData()); - FloatImageType::Pointer Dxz = FloatImageType::New(); - mitk::CastToItkImage(img, Dxz); - - img = static_cast(m_DyzNode->GetData()); - FloatImageType::Pointer Dyz = FloatImageType::New(); - mitk::CastToItkImage(img, Dyz); - - img = static_cast(m_DyyNode->GetData()); - FloatImageType::Pointer Dyy = FloatImageType::New(); - mitk::CastToItkImage(img, Dyy); - - img = static_cast(m_DzzNode->GetData()); - FloatImageType::Pointer Dzz = FloatImageType::New(); - mitk::CastToItkImage(img, Dzz); - - - - itk::Image, 3>::Pointer tensorImg = itk::Image, 3>::New(); - tensorImg->SetSpacing(Dzz->GetSpacing()); - tensorImg->SetOrigin(Dzz->GetOrigin()); - tensorImg->SetRegions(Dzz->GetLargestPossibleRegion().GetSize()); - tensorImg->Allocate(); - - - mitk::TensorImage::Pointer image = mitk::TensorImage::New(); - - FloatImageType::SizeType size = Dxx->GetLargestPossibleRegion().GetSize(); - - for(int x=0; x ix; - ix[0]=x; - ix[1]=y; - ix[2]=z; - - float dxx = Dxx->GetPixel(ix); - float dxy = Dxy->GetPixel(ix); - float dxz = Dxz->GetPixel(ix); - float dyz = Dyz->GetPixel(ix); - float dyy = Dyy->GetPixel(ix); - float dzz = Dzz->GetPixel(ix); - - - itk::DiffusionTensor3D tensor; - tensor[0] = dxx*1000; - tensor[1] = dxy*1000; - tensor[2] = dxz*1000; - tensor[3] = dyy*1000; - tensor[4] = dyz*1000; - tensor[5] = dzz*1000; - - tensorImg->SetPixel(ix, tensor); - } - } - } - - image->InitializeByItk( tensorImg.GetPointer() ); - image->SetVolume( tensorImg->GetBufferPointer() ); - mitk::DataNode::Pointer node=mitk::DataNode::New(); - node->SetData( image ); - GetDefaultDataStorage()->Add( node ); - - - -} - -void QmitkTractbasedSpatialStatisticsView::SetTensorComponent(QLineEdit* edit, mitk::DataNode::Pointer node) -{ - std::vector nodes = GetDataManagerSelection(); - if (nodes.empty()) - { - node = NULL; - edit->setText("N/A"); - return; - } - - for( std::vector::iterator it = nodes.begin(); - it != nodes.end(); - ++it ) - { - mitk::DataNode::Pointer n = *it; - - if (n.IsNotNull() && dynamic_cast(n->GetData())) - { - node = mitk::DataNode::New(); - node = n; - edit->setText(node->GetName().c_str()); - return; - } - } -} - -void QmitkTractbasedSpatialStatisticsView::SetDxx() -{ - std::vector nodes = GetDataManagerSelection(); - if (nodes.empty()) - { - m_DxxNode = NULL; - m_Controls->m_DxxImageEdit->setText("N/A"); - return; - } - - for( std::vector::iterator it = nodes.begin(); - it != nodes.end(); - ++it ) - { - mitk::DataNode::Pointer n = *it; - - if (n.IsNotNull() && dynamic_cast(n->GetData())) - { - m_DxxNode = n; - m_Controls->m_DxxImageEdit->setText(n->GetName().c_str()); - return; - } + connect( m_Controls->m_RoiPlotWidget->m_PlotPicker, SIGNAL(moved(const QwtDoublePoint&)), SLOT(Clicked(const QwtDoublePoint&) ) ); } } -void QmitkTractbasedSpatialStatisticsView::SetDxy() -{ - std::vector nodes = GetDataManagerSelection(); - if (nodes.empty()) - { - m_DxyNode = NULL; - m_Controls->m_DxyImageEdit->setText("N/A"); - return; - } - - for( std::vector::iterator it = nodes.begin(); - it != nodes.end(); - ++it ) - { - mitk::DataNode::Pointer n = *it; - - if (n.IsNotNull() && dynamic_cast(n->GetData())) - { - m_DxyNode = n; - m_Controls->m_DxyImageEdit->setText(n->GetName().c_str()); - return; - } - } -} - -void QmitkTractbasedSpatialStatisticsView::SetDxz() -{ - std::vector nodes = GetDataManagerSelection(); - if (nodes.empty()) - { - m_DxzNode = NULL; - m_Controls->m_DxzImageEdit->setText("N/A"); - return; - } - - for( std::vector::iterator it = nodes.begin(); - it != nodes.end(); - ++it ) - { - mitk::DataNode::Pointer n = *it; - - if (n.IsNotNull() && dynamic_cast(n->GetData())) - { - m_DxzNode = n; - m_Controls->m_DxzImageEdit->setText(n->GetName().c_str()); - return; - } - } -} - -void QmitkTractbasedSpatialStatisticsView::SetDyy() -{ - std::vector nodes = GetDataManagerSelection(); - if (nodes.empty()) - { - m_DyyNode = NULL; - m_Controls->m_DyyImageEdit->setText("N/A"); - return; - } - - for( std::vector::iterator it = nodes.begin(); - it != nodes.end(); - ++it ) - { - mitk::DataNode::Pointer n = *it; - - if (n.IsNotNull() && dynamic_cast(n->GetData())) - { - m_DyyNode = n; - m_Controls->m_DyyImageEdit->setText(n->GetName().c_str()); - return; - } - } -} - -void QmitkTractbasedSpatialStatisticsView::SetDyz() -{ - std::vector nodes = GetDataManagerSelection(); - if (nodes.empty()) - { - m_DyzNode = NULL; - m_Controls->m_DyzImageEdit->setText("N/A"); - return; - } - - for( std::vector::iterator it = nodes.begin(); - it != nodes.end(); - ++it ) - { - mitk::DataNode::Pointer n = *it; - - if (n.IsNotNull() && dynamic_cast(n->GetData())) - { - m_DyzNode = n; - m_Controls->m_DyzImageEdit->setText(n->GetName().c_str()); - return; - } - } -} - -void QmitkTractbasedSpatialStatisticsView::SetDzz() -{ - std::vector nodes = GetDataManagerSelection(); - if (nodes.empty()) - { - m_DzzNode = NULL; - m_Controls->m_DzzImageEdit->setText("N/A"); - return; - } - - for( std::vector::iterator it = nodes.begin(); - it != nodes.end(); - ++it ) - { - mitk::DataNode::Pointer n = *it; - - if (n.IsNotNull() && dynamic_cast(n->GetData())) - { - m_DzzNode = n; - m_Controls->m_DzzImageEdit->setText(n->GetName().c_str()); - return; - } - } -} - - - void QmitkTractbasedSpatialStatisticsView::CopyToClipboard() { std::vector > vals = m_Controls->m_RoiPlotWidget->GetVals(); QString clipboardText; for (std::vector >::iterator it = vals.begin(); it != vals.end(); ++it) { for (std::vector::iterator it2 = (*it).begin(); it2 != (*it).end(); ++it2) { clipboardText.append(QString("%1 \t").arg(*it2)); double d = *it2; std::cout << d <setText(clipboardText, QClipboard::Clipboard); } void QmitkTractbasedSpatialStatisticsView::RemoveGroup() { QTableView *temp = static_cast(m_Controls->m_GroupInfo); // QSortFilterProxyModel *proxy = static_cast(temp->model()); QItemSelectionModel *selectionModel = temp->selectionModel(); QModelIndexList indices = selectionModel->selectedRows(); QModelIndex index; foreach(index, indices) { int row = index.row(); m_GroupModel->removeRows(row, 1, QModelIndex()); } } std::string QmitkTractbasedSpatialStatisticsView::ReadFile(std::string whatfile) { std::string s = "Select a" + whatfile; QFileDialog* w = new QFileDialog(this->m_Controls->m_ImportFsl, QString(s.c_str()) ); w->setFileMode(QFileDialog::ExistingFiles); w->setDirectory("/home"); if(whatfile == "gradient image") { w->setNameFilter("Tbss gradient images (*.tgi)"); } // RETRIEVE SELECTION if ( w->exec() != QDialog::Accepted ) { return ""; MITK_INFO << "Failed to load"; } QStringList filenames = w->selectedFiles(); if (filenames.size() > 0) { std::string retval = filenames.at(0).toStdString(); return retval; } return ""; } void QmitkTractbasedSpatialStatisticsView::AddGroup() { QString group("Group"); int number = 0; QPair pair(group, number); QList< QPair >list = m_GroupModel->getList(); if(!list.contains(pair)) { m_GroupModel->insertRows(0, 1, QModelIndex()); QModelIndex index = m_GroupModel->index(0, 0, QModelIndex()); m_GroupModel->setData(index, group, Qt::EditRole); index = m_GroupModel->index(0, 1, QModelIndex()); m_GroupModel->setData(index, number, Qt::EditRole); } else { //QMessageBox::information(this, "Duplicate name"); } } void QmitkTractbasedSpatialStatisticsView::TbssImport() { // Read groups from the interface mitk::TbssImporter::Pointer importer = mitk::TbssImporter::New(); QList< QPair >list = m_GroupModel->getList(); if(list.size() == 0) { QMessageBox msgBox; msgBox.setText("No study group information has been set yet."); msgBox.exec(); return; } std::vector < std::pair > groups; for(int i=0; i pair = list.at(i); std::string s = pair.first.toStdString(); int n = pair.second; std::pair p; p.first = s; p.second = n; groups.push_back(p); } importer->SetGroupInfo(groups); std::string minfo = m_Controls->m_MeasurementInfo->text().toStdString(); importer->SetMeasurementInfo(minfo); std::string name = ""; for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i) { // extract datatree node if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); if(QString("Image").compare(node->GetData()->GetNameOfClass())==0) { mitk::Image* img = static_cast(node->GetData()); if(img->GetDimension() == 4) { importer->SetImportVolume(img); name = node->GetName(); } } } } mitk::TbssImage::Pointer tbssImage; tbssImage = importer->Import(); name += "_tbss"; AddTbssToDataStorage(tbssImage, name); } void QmitkTractbasedSpatialStatisticsView::AddTbssToDataStorage(mitk::Image* image, std::string name) { mitk::LevelWindow levelwindow; levelwindow.SetAuto( image ); mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); levWinProp->SetLevelWindow( levelwindow ); mitk::DataNode::Pointer result = mitk::DataNode::New(); result->SetProperty( "name", mitk::StringProperty::New(name) ); result->SetData( image ); result->SetProperty( "levelwindow", levWinProp ); // add new image to data storage and set as active to ease further processing GetDefaultDataStorage()->Add( result ); // show the results mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkTractbasedSpatialStatisticsView::Clicked(const QwtDoublePoint& pos) { if(m_Roi.size() > 0 && m_CurrentGeometry != NULL) { int index = (int)pos.x(); index = std::max(0, index); index = std::min(index, (int)m_Roi.size()); itk::Index<3> ix = m_Roi.at(index); mitk::Vector3D i; i[0] = ix[0]; i[1] = ix[1]; i[2] = ix[2]; mitk::Vector3D w; m_CurrentGeometry->IndexToWorld(i, w); mitk::Point3D origin = m_CurrentGeometry->GetOrigin(); mitk::Point3D p; p[0] = w[0] + origin[0]; p[1] = w[1] + origin[1]; p[2] = w[2] + origin[2]; m_MultiWidget->MoveCrossToPosition(p); m_Controls->m_RoiPlotWidget->drawBar(index); } } void QmitkTractbasedSpatialStatisticsView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkTractbasedSpatialStatisticsView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkTractbasedSpatialStatisticsView::AdjustPlotMeasure(const QString & text) { berry::ISelection::ConstPointer sel( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); m_CurrentSelection = sel.Cast(); m_SelListener.Cast()->DoSelectionChanged(sel); } void QmitkTractbasedSpatialStatisticsView::Clustering() { /* // Create a mask using the distance map typedef itk::ImageFileReader< VectorImageType > DirectionReader; DirectionReader::Pointer directionReader = DirectionReader::New(); directionReader->SetFileName(m_TbssWorkspaceManager.GetInputDir().toStdString() + "/tbss/" + m_TbssWorkspaceManager.GetGradient().toStdString()); directionReader->Update(); VectorImageType::Pointer directions = directionReader->GetOutput(); FloatReaderType::Pointer distMapReader = FloatReaderType::New(); distMapReader->SetFileName(m_TbssWorkspaceManager.GetInputDir().toStdString() + "/stats/" + m_TbssWorkspaceManager.GetDistanceMap().toStdString()); distMapReader->Update(); FloatImageType::Pointer distanceMap = distMapReader->GetOutput(); std::string line; std::string path = "/mnt/E130-Projekte/NeuroDiffusion/BRAM DTI/TBSS/rois/cc.txt"; std::ifstream file(path.c_str()); std::vector< itk::Index< 3 > > roi; if(file.is_open()) { while(getline(file,line)) { std::vector tokens; Tokenize(line, tokens); itk::Index<3> ix; ix[0] = atoi(tokens[0].c_str()); ix[1] = atoi(tokens[1].c_str()); ix[2] = atoi(tokens[2].c_str()); roi.push_back(ix); } } if(roi.size() == 0) { return; } // Some code from the projection algorithm of tbss to create a mask std::vector< std::vector< itk::Index< 3 > > > rois; for(int j=0; j > indices; FloatImageType::SizeType size = distanceMap->GetLargestPossibleRegion().GetSize(); bool roiDone = false; while(!roiDone && j ix = roi[j]; int x=ix[0]; int y=ix[1]; int z=ix[2]; VectorImageType::PixelType dir = directions->GetPixel(ix); indices.push_back(ix); for(int iters=0;iters<2;iters++) { float distance=0; for(int d=1;d=size[0] && dy<=size[1] && dz<=size[2]) { d=MAXSEARCHLENGTH; } else if(distanceMap->GetPixel(ix)>=distance) { distance = distanceMap->GetPixel(ix); indices.push_back(ix); } else{ d=MAXSEARCHLENGTH; } } } j++; } // Create a mask from indices UCharImageType::Pointer maskItk = UCharImageType::New(); maskItk->SetRegions(distanceMap->GetRequestedRegion()); maskItk->SetDirection(distanceMap->GetDirection()); maskItk->SetSpacing(distanceMap->GetSpacing()); maskItk->SetOrigin(distanceMap->GetOrigin()); maskItk->Allocate(); // For every point on the roi create a mask and feed it to the partial voluming algorithm //maskItk->FillBuffer(0); // Create a bounding box from current ROI int xMin = numeric_limits::max(); int yMin = numeric_limits::max(); int zMin = numeric_limits::max(); int xMax = numeric_limits::min(); int yMax = numeric_limits::min(); int zMax = numeriUCharImageType::Pointer newMask = UCharImageType::New();c_limits::min(); for(int i=0; i ix = indices[i]; if(ix[0] < xMin) xMin=ix[0]; if(ix[1] < yMin) yMin=ix[1]; if(ix[2] < zMin) zMin=ix[2]; if(ix[0] > xMax) xMax=ix[0]; if(ix[1] > yMax) yMax=ix[1]; if(ix[2] > zMax) zMax=ix[2]; } FloatImageType::PointType origin = distanceMap->GetOrigin(); CharImageType::PointType originMask; originMask[0] = origin[0] + xMin; originMask[1] = origin[1] + -yMin; originMask[2] = origin[2] + zMin; CharImageType::RegionType region; CharImageType::RegionType::SizeType s; s[0] = xMax-xMin + 1; s[1] = yMax-yMin + 1; s[2] = zMax-zMin + 1; region.SetSize(s); UCharImageType::Pointer newMask = UCharImageType::New(); newMask->SetSpacing( distanceMap->GetSpacing() ); // Set the image spacing newMask->SetOrigin( originMask ); // Set the image origin newMask->SetDirection( distanceMap->GetDirection() ); // Set the image direction newMask->SetRegions( region ); newMask->Allocate(); newMask->FillBuffer(0); for(int i=0; i ix = indices[i]; itk::Point< double, 3 > point; itk::Index< 3 > index; distanceMap->TransformIndexToPhysicalPoint (ix, point); newMask->TransformPhysicalPointToIndex(point, index); newMask->SetPixel(index, 1); } */ /* UCharImageType::Pointer newMask = UCharImageType::New(); UCharReaderType::Pointer cReader = UCharReaderType::New(); cReader->SetFileName("/mnt/E130-Projekte/NeuroDiffusion/BRAM DTI/ClusteringFornix/fornix_central_maxFA_path_Dilated_by_3.nrrd"); cReader->Update(); newMask = cReader->GetOutput(); // mitk::DataNode::Pointer maskNode = readNode("itk image/mnt/E130-Projekte/NeuroDiffusion/BRAM DTI/TBSS/clusterMasks/area2.nii"); // mitk::Image::Pointer mask = dynamic_cast(maskNode->GetData()); mitk::Image::Pointer mask; mitk::CastToMitkImage(newMask, mask); typedef mitk::PartialVolumeAnalysisHistogramCalculator HistorgramCalculator; typedef mitk::PartialVolumeAnalysisClusteringCalculator ClusteringType; typedef HistorgramCalculator::HistogramType HistogramType; HistorgramCalculator::Pointer histogramCalculator = HistorgramCalculator::New(); // Make list of subjects std::vector paths; paths.push_back("/mnt/E130-Projekte/NeuroDiffusion/BRAM DTI/TBSS/FA/SORTEDBYCONDITION/FA/subset"); // paths.push_back("/mnt/E130-Projekte/NeuroDiffusion/BRAM DTI/TBSS/FA/SORTEDBYCONDITION/AXD/"); for(int j=0; j values; for(int i=0; i(node->GetData()); histogramCalculator->SetImage(image); histogramCalculator->SetImageMask( mask ); histogramCalculator->SetMaskingModeToImage(); histogramCalculator->SetNumberOfBins(25); histogramCalculator->SetUpsamplingFactor(5); histogramCalculator->SetGaussianSigma(0.0); histogramCalculator->SetForceUpdate(true); bool statisticsChanged = histogramCalculator->ComputeStatistics( ); ClusteringType::ParamsType *cparams = 0; ClusteringType::ClusterResultType *cresult = 0; ClusteringType::HistType *chist = 0; ClusteringType::HelperStructPerformClusteringRetval *currentPerformClusteringResults; try{ mitk::Image* tmpImg = histogramCalculator->GetInternalImage(); mitk::Image::ConstPointer imgToCluster = tmpImg; if(imgToCluster.IsNotNull()) { // perform clustering const HistogramType *histogram = histogramCalculator->GetHistogram( ); ClusteringType::Pointer clusterer = ClusteringType::New(); clusterer->SetStepsNumIntegration(200); clusterer->SetMaxIt(1000); mitk::Image::Pointer pFiberImg; currentPerformClusteringResults = clusterer->PerformClustering(imgToCluster, histogram, 2); pFiberImg = currentPerformClusteringResults->clusteredImage; cparams = currentPerformClusteringResults->params; cresult = currentPerformClusteringResults->result; chist = currentPerformClusteringResults->hist; // m_Controls->m_HistogramWidget->SetParameters( // cparams, cresult, chist ); std::vector *xVals = chist->GetXVals(); std::vector *fiberVals = new std::vector(cresult->GetFiberVals()); double fiberFA = 0.0; double weights = 0.0; // std::cout << "x, y, fiber, nonFiber, mixed, combi" << std::endl; for(int k=0; ksize(); ++k) { fiberFA += xVals->at(k) * fiberVals->at(k); weights += fiberVals->at(k); } fiberFA = fiberFA / weights; std::cout << "FA: " << fiberFA << std::endl; values.push_back(fiberFA); } } catch ( const std::runtime_error &e ) { std::cout << "noooooooooooooooooooooooooooooooo!"; } //MITK_INFO << "number of voxels: " << indices.size(); } std::vector::iterator it = values.begin(); while(it!=values.end()) { std::cout << *it << std::endl; ++it; } }*/ } void QmitkTractbasedSpatialStatisticsView::CreateRoi() { // It is important to load the MeanFASkeletonMask image in MITK to make sure that point selection and // pathfinding is done on the same image //string filename = m_TbssWorkspaceManager.GetInputDir().toStdString() + "/stats/" + m_TbssWorkspaceManager.GetMeanFASkeletonMask().toStdString(); // Implement a way to obtain skeleton and skeletonFA without sml workspace double threshold = QInputDialog::getDouble(m_Controls->m_CreateRoi, tr("Set an FA threshold"), tr("Threshold:"), QLineEdit::Normal, 0.2); mitk::Image::Pointer image; for (IStructuredSelection::iterator i = m_CurrentSelection->Begin(); i != m_CurrentSelection->End(); ++i) { // extract datatree node if (mitk::DataNodeObject::Pointer nodeObj = i->Cast()) { mitk::DataNode::Pointer node = nodeObj->GetDataNode(); if(QString("Image").compare(node->GetData()->GetNameOfClass())==0) { mitk::Image* img = static_cast(node->GetData()); if(img->GetDimension() == 3) { image = img; } } } } if(image.IsNull()) { return; } mitk::TractAnalyzer analyzer; analyzer.SetInputImage(image); analyzer.SetThreshold(threshold); int n = 0; if(m_PointSetNode.IsNotNull()) { n = m_PointSetNode->GetSize(); if(n==0) { QMessageBox msgBox; msgBox.setText("No points have been set yet."); msgBox.exec(); } } else{ QMessageBox msgBox; msgBox.setText("No points have been set yet."); msgBox.exec(); } std::string pathDescription = ""; std::vector< itk::Index<3> > totalPath; if(n>0) { for(int i=0; iGetPoint(i); mitk::Point3D p2 = m_PointSetNode->GetPoint(i+1); itk::Index<3> StartPoint; mitk::ProgressBar::GetInstance()->Progress(); itk::Index<3> EndPoint; image->GetGeometry()->WorldToIndex(p,StartPoint); image->GetGeometry()->WorldToIndex(p2,EndPoint); MITK_INFO << "create roi"; analyzer.BuildGraph(StartPoint, EndPoint); std::vector< itk::Index<3> > path = analyzer.GetPath(); for(std::vector< itk::Index<3> >::iterator it = path.begin(); it != path.end(); it++) { itk::Index<3> ix = *it; if (!(ix==EndPoint)) { mitk::ProgressBar::GetInstance()->Progress(); totalPath.push_back(ix); std::stringstream ss; ss << ix[0] << " " << ix[1] << " " << ix[2] << "\n"; pathDescription += ss.str(); } else { // Only when dealing with the last segment the last point should be added. This one will not occur // as the first point of the next roi segment. if(i == (n-2)) { totalPath.push_back(EndPoint); std::stringstream ss; ss << EndPoint[0] << " " << EndPoint[1] << " " << EndPoint[2] << "\n"; pathDescription += ss.str(); } } } } m_Controls->m_PathTextEdit->setPlainText(QString(pathDescription.c_str())); FloatImageType::Pointer itkImg = FloatImageType::New(); mitk::CastToItkImage(image, itkImg); CharImageType::Pointer roiImg = CharImageType::New(); roiImg->SetRegions(itkImg->GetLargestPossibleRegion().GetSize()); roiImg->SetOrigin(itkImg->GetOrigin()); roiImg->SetSpacing(itkImg->GetSpacing()); roiImg->SetDirection(itkImg->GetDirection()); roiImg->Allocate(); roiImg->FillBuffer(0); std::vector< itk::Index<3> > roi; std::vector< itk::Index<3> >::iterator it; for(it = totalPath.begin(); it != totalPath.end(); it++) { itk::Index<3> ix = *it; roiImg->SetPixel(ix, 1); roi.push_back(ix); } mitk::TbssRoiImage::Pointer tbssRoi = mitk::TbssRoiImage::New(); //mitk::CastToTbssImage(m_CurrentRoi.GetPointer(), tbssRoi); tbssRoi->SetRoi(roi); tbssRoi->SetImage(roiImg); tbssRoi->SetStructure(m_Controls->m_Structure->text().toStdString()); tbssRoi->InitializeFromImage(); // mitk::Image::Pointer tbssRoi = mitk::Image::New(); //mitk::CastToTbssImage(m_CurrentRoi.GetPointer(), tbssRoi); // mitk::CastToMitkImage(roiImg, tbssRoi); AddTbssToDataStorage(tbssRoi, m_Controls->m_RoiName->text().toStdString()); } } void QmitkTractbasedSpatialStatisticsView::PlotFiberBundle(mitk::FiberBundleX *fib, mitk::Image* img) { int num = fib->GetNumFibers(); std::cout << "number of fibers: " << num << std::endl; vtkSmartPointer fiberPolyData = fib->GetFiberPolyData(); vtkCellArray* lines = fiberPolyData->GetLines(); lines->InitTraversal(); int lineSize = lines->GetSize(); std::cout << "line size: " << lineSize << std::cout; typedef itk::Point PointType; typedef std::vector< PointType> TractType; typedef std::vector< TractType > TractContainerType; TractContainerType tracts; for( int fiberID( 0 ); fiberID < num; fiberID++ ) { vtkIdType numPointsInCell(0); vtkIdType* pointsInCell(NULL); lines->GetNextCell ( numPointsInCell, pointsInCell ); TractType singleTract; for( int pointInCellID( 0 ); pointInCellID < numPointsInCell ; pointInCellID++) { // push back point double *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] ); PointType point; point[0] = p[0]; point[1] = p[1]; point[2] = p[2]; singleTract.push_back( point ); } tracts.push_back(singleTract); } m_Controls->m_RoiPlotWidget->PlotFiberBundles(tracts, img); } void QmitkTractbasedSpatialStatisticsView::Plot(mitk::TbssImage* image, mitk::TbssRoiImage* roiImage) { if(m_Controls->m_TabWidget->currentWidget() == m_Controls->m_MeasureTAB) { std::vector< itk::Index<3> > roi = roiImage->GetRoi(); m_Roi = roi; m_CurrentGeometry = image->GetGeometry(); std::string resultfile = ""; /* if(image->GetPreprocessedFA()) { resultFile = image->GetPreprocessedFAFile(); } */ std::string structure = roiImage->GetStructure(); //m_View->m_CurrentGeometry = image->GetGeometry(); m_Controls->m_RoiPlotWidget->SetGroups(image->GetGroupInfo()); // Check for preprocessed results to save time //if(resultfile == "") // { // Need to calculate the results using the 4D volume // Can save the time this takes if there are results available already //std::string type = m_Controls->m_MeasureType->itemText(m_Controls->m_MeasureType->currentIndex()).toStdString(); m_Controls->m_RoiPlotWidget->SetProjections(image->GetImage()); // } m_Controls->m_RoiPlotWidget->SetRoi(roi); m_Controls->m_RoiPlotWidget->SetStructure(structure); m_Controls->m_RoiPlotWidget->SetMeasure( image->GetMeasurementInfo() ); m_Controls->m_RoiPlotWidget->DrawProfiles(resultfile); } } void QmitkTractbasedSpatialStatisticsView::Masking() { //QString filename = m_Controls->m_WorkingDirectory->text(); QString filename = "E:/Experiments/tbss"; QString faFiles = filename + "/AxD"; QString maskFiles = filename + "/bin_masks"; QDirIterator faDirIt(faFiles, QDir::Files | QDir::NoSymLinks, QDirIterator::Subdirectories); QDirIterator maskDirIt(maskFiles, QDir::Files | QDir::NoSymLinks, QDirIterator::Subdirectories); std::vector faFilenames; std::vector maskFilenames; std::vector outputFilenames; while(faDirIt.hasNext() && maskDirIt.hasNext()) { faDirIt.next(); maskDirIt.next(); if((faDirIt.fileInfo().completeSuffix() == "nii" || faDirIt.fileInfo().completeSuffix() == "mhd" || faDirIt.fileInfo().completeSuffix() == "nii.gz") && (maskDirIt.fileInfo().completeSuffix() == "nii" || maskDirIt.fileInfo().completeSuffix() == "mhd" || maskDirIt.fileInfo().completeSuffix() == "nii.gz")) { faFilenames.push_back(faDirIt.filePath().toStdString()); outputFilenames.push_back(faDirIt.fileName().toStdString()); maskFilenames.push_back(maskDirIt.filePath().toStdString()); } } std::vector::iterator faIt = faFilenames.begin(); std::vector::iterator maskIt = maskFilenames.begin(); std::vector::iterator outputIt = outputFilenames.begin(); // Now multiply all FA images with their corresponding masks QString outputDir = filename; while(faIt != faFilenames.end() && maskIt != maskFilenames.end() && outputIt != outputFilenames.end()) { std::cout << "Mask " << *faIt << " with " << *maskIt << std::endl; typedef itk::MultiplyImageFilter MultiplicationFilterType; FloatReaderType::Pointer floatReader = FloatReaderType::New(); CharReaderType::Pointer charReader = CharReaderType::New(); floatReader->SetFileName(*faIt); //floatReader->Update(); //FloatImageType::Pointer faImage = floatReader->GetOutput(); charReader->SetFileName(*maskIt); //charReader->Update(); // CharImageType::Pointer maskImage = charReader->GetOutput(); MultiplicationFilterType::Pointer multiplicationFilter = MultiplicationFilterType::New(); multiplicationFilter->SetInput1(floatReader->GetOutput()); multiplicationFilter->SetInput2(charReader->GetOutput()); multiplicationFilter->Update(); //FloatImageType::Pointer maskedImage = FloatImageType::New(); //maskedImage = MultiplicationFilter->GetOutput(); FloatWriterType::Pointer floatWriter = FloatWriterType::New(); std::string s = faFiles.toStdString().append("/"+*outputIt); floatWriter->SetFileName(s.c_str()); floatWriter->SetInput(multiplicationFilter->GetOutput()); floatWriter->Update(); ++faIt; ++maskIt; ++outputIt; } } VectorImageType::Pointer QmitkTractbasedSpatialStatisticsView::ConvertToVectorImage(mitk::Image::Pointer mitkImage) { VectorImageType::Pointer vecImg = VectorImageType::New(); mitk::Geometry3D* geo = mitkImage->GetGeometry(); mitk::Vector3D spacing = geo->GetSpacing(); mitk::Point3D origin = geo->GetOrigin(); VectorImageType::SpacingType vecSpacing; vecSpacing[0] = spacing[0]; vecSpacing[1] = spacing[1]; vecSpacing[2] = spacing[2]; VectorImageType::PointType vecOrigin; vecOrigin[0] = origin[0]; vecOrigin[1] = origin[1]; vecOrigin[2] = origin[2]; VectorImageType::SizeType size; size[0] = mitkImage->GetDimension(0); size[1] = mitkImage->GetDimension(1); size[2] = mitkImage->GetDimension(2); vecImg->SetSpacing(vecSpacing); vecImg->SetOrigin(vecOrigin); vecImg->SetRegions(size); vecImg->SetVectorLength(mitkImage->GetDimension(3)); vecImg->Allocate(); for(int x=0; x pixel = vecImg->GetPixel(ix); for (int t=0; tGetPixelValueByIndex(ix, t); pixel.SetElement(t, f); } vecImg->SetPixel(ix, pixel); } } } return vecImg; } /* void QmitkTractbasedSpatialStatisticsView::InitializeGridByVectorImage() { // Read vector image from file typedef itk::ImageFileReader< FloatVectorImageType > VectorReaderType; VectorReaderType::Pointer vectorReader = VectorReaderType::New(); vectorReader->SetFileName("E:\\tbss\\testing\\Gradient.mhd"); vectorReader->Update(); FloatVectorImageType::Pointer directions = vectorReader->GetOutput(); // Read roi from file. CharReaderType::Pointer roiReader = CharReaderType::New(); roiReader->SetFileName("E:\\tbss\\testing\\debugging skeletonization\\segment2.mhd"); roiReader->Update(); CharImageType::Pointer roi = roiReader->GetOutput(); DoInitializeGridByVectorImage(directions, roi, std::string("directions")); } void QmitkTractbasedSpatialStatisticsView::DoInitializeGridByVectorImage(FloatVectorImageType::Pointer vectorpic, CharImageType::Pointer roi, std::string name) { //vtkStructuredGrid* grid = vtkStructuredGrid::New(); itk::Matrix itkdirection = vectorpic->GetDirection(); itk::Matrix itkinversedirection = itk::Matrix(itkdirection.GetInverse()); std::vector GridPoints; vtkPoints *points = vtkPoints::New(); mitk::Geometry3D::Pointer geom = mitk::Geometry3D::New(); vtkLinearTransform *vtktransform; vtkLinearTransform *inverse; mitk::Image::Pointer geomget = mitk::Image::New(); geomget->InitializeByItk(vectorpic.GetPointer()); geom = geomget->GetGeometry(); vtktransform = geom->GetVtkTransform(); inverse = vtktransform->GetLinearInverse(); vtkFloatArray * directions = vtkFloatArray::New(); directions->SetName("Vectors"); directions->SetNumberOfComponents(3); // Iterator for the vector image itk::ImageRegionIterator it_input(vectorpic, vectorpic->GetLargestPossibleRegion()); FloatVectorType nullvector; nullvector.Fill(0); double lengthsum = 0; int id = 0; // Iterator for the roi itk::ImageRegionIterator roiIt(roi, roi->GetLargestPossibleRegion()); roiIt.GoToBegin(); for(it_input.GoToBegin(); !( it_input.IsAtEnd() || roiIt.IsAtEnd() ); ++it_input) { //VectorType val = it_input.Value(); if(it_input.Value() != nullvector && roiIt.Get() != 0) { //itk::Point point; mitk::Point3D mitkpoint, mitkworldpoint; mitk::Point3D mitkendpoint, mitkworldendpoint; mitk::Vector3D mitkvector, mitktransvector; itk::Point direction = it_input.Value().GetDataPointer(); //itk::Index<3> in_input = it_input.GetIndex(); //itk::ContinuousIndex cindirection; FloatVectorType transvec = it_input.Value(); mitkvector[0] = transvec[0]; mitkvector[1] = transvec[1]; mitkvector[2] = transvec[2]; //mitkvector[2] = 0.0; mitkpoint[0] = it_input.GetIndex()[0]; mitkpoint[1] = it_input.GetIndex()[1]; mitkpoint[2] = it_input.GetIndex()[2]; mitkendpoint[0] = mitkpoint[0] + mitkvector[0]; mitkendpoint[1] = mitkpoint[1] + mitkvector[1]; mitkendpoint[2] = mitkpoint[2] + mitkvector[2]; //mitkpoint.setXYZ((ScalarType)point[0],(ScalarType)point[1],(ScalarType)point[2]); geom->IndexToWorld(mitkpoint, mitkworldpoint); geom->IndexToWorld(mitkendpoint, mitkworldendpoint); mitktransvector[0] = mitkworldendpoint[0] - mitkworldpoint[0]; mitktransvector[1] = mitkworldendpoint[1] - mitkworldpoint[1]; mitktransvector[2] = mitkworldendpoint[2] - mitkworldpoint[2]; lengthsum += mitktransvector.GetNorm(); directions->InsertTuple3(id,mitktransvector[0],mitktransvector[1],mitktransvector[2]); points->InsertPoint(id,mitkworldpoint[0],mitkworldpoint[1],mitkworldpoint[2]); id++; //for (unsigned short loop = 0; (loop < 20) && (!it_input.IsAtEnd()); loop++) //{ // ++it_input; //} if(it_input.IsAtEnd()) { break; } } ++roiIt; } double meanlength = lengthsum / id; vtkGlyph3D* glyph = vtkGlyph3D::New(); vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New(); ugrid->SetPoints(points); ugrid->GetPointData()->SetVectors(directions); glyph->SetInput(ugrid); glyph->SetScaleModeToScaleByVector(); glyph->SetScaleFactor(0.5); glyph->SetColorModeToColorByScalar(); //glyph->ClampingOn(); vtkArrowSource* arrow = vtkArrowSource::New(); if(meanlength > 5) {arrow->SetTipLength(0);arrow->SetTipRadius(0);} arrow->SetShaftRadius(0.03/meanlength); //arrow->SetTipRadius(0.05/meanlength); glyph->SetSource(arrow->GetOutput()); glyph->Update(); mitk::Surface::Pointer glyph_surface = mitk::Surface::New(); glyph_surface->SetVtkPolyData(glyph->GetOutput()); glyph_surface->UpdateOutputInformation(); mitk::DataNode::Pointer gridNode = mitk::DataNode::New(); gridNode->SetProperty( "name", mitk::StringProperty::New(name.c_str()) ); //m_GridNode->SetProperty( "color" , m_GridColor); gridNode->SetProperty( "visible", mitk::BoolProperty::New(true) ); gridNode->SetProperty( "segmentation", mitk::BoolProperty::New(true) ); gridNode->SetProperty( "ID-Tag", mitk::StringProperty::New("grid") ); gridNode->SetProperty( "shader", mitk::StringProperty::New("mitkShaderLightning") ); gridNode->SetData( glyph_surface ); GetDefaultDataStorage()->Add(gridNode); } */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.h index 1cde1ffe59..b1fe665ff6 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.h @@ -1,272 +1,260 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $ Version: $Revision: 21975 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef QmitkTractbasedSpatialStatisticsView_h #define QmitkTractbasedSpatialStatisticsView_h #include #include #include #include #include "ui_QmitkTractbasedSpatialStatisticsViewControls.h" #include #include #include #include #include #include #include #include #include #include "QmitkTbssTableModel.h" #include "QmitkTbssMetaTableModel.h" #include typedef short DiffusionPixelType; typedef itk::Image CharImageType; typedef itk::Image UCharImageType; typedef itk::Image Float4DImageType; typedef itk::Image FloatImageType; typedef itk::Vector IntVectorType; //typedef itk::VectorImage DirectionImageType; typedef itk::VectorImage VectorImageType; typedef itk::ImageFileReader< CharImageType > CharReaderType; typedef itk::ImageFileReader< UCharImageType > UCharReaderType; typedef itk::ImageFileWriter< CharImageType > CharWriterType; typedef itk::ImageFileReader< FloatImageType > FloatReaderType; typedef itk::ImageFileWriter< FloatImageType > FloatWriterType; typedef itk::ImageFileReader< Float4DImageType > Float4DReaderType; typedef itk::ImageFileWriter< Float4DImageType > Float4DWriterType; struct TbssSelListener; /*! \brief QmitkTractbasedSpatialStatisticsView \warning This application module is not yet documented. Use "svn blame/praise/annotate" and ask the author to provide basic documentation. \sa QmitkFunctionalitymitkTbssWorkspaceManager \ingroup Functionalities */ class QmitkTractbasedSpatialStatisticsView : public QmitkFunctionality { friend struct TbssSelListener; // this is needed for all Qt objesetupUicts 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; QmitkTractbasedSpatialStatisticsView(); virtual ~QmitkTractbasedSpatialStatisticsView(); virtual void CreateQtPartControl(QWidget *parent); /// \brief Creation of the connections of main and control widget virtual void CreateConnections(); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); /// \brief Called when the functionality is activated virtual void Activated(); virtual void Deactivated(); protected slots: //void OutputValues(); // void InitializeGridByVectorImage(); void Masking(); void CreateRoi(); void Clustering(); void AdjustPlotMeasure(const QString & text); void Clicked(const QwtDoublePoint& pos); void TbssImport(); void AddGroup(); void RemoveGroup(); void CopyToClipboard(); - void SetDxx(); - void SetDyy(); - void SetDzz(); - void SetDxy(); - void SetDxz(); - void SetDyz(); - void ImportTensorByComps(); + protected: - void SetTensorComponent(QLineEdit* edit, mitk::DataNode::Pointer node); /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); void Plot(mitk::TbssImage*, mitk::TbssRoiImage*); void PlotFiberBundle(mitk::FiberBundleX* fib, mitk::Image* img); void InitPointsets(); void SetDefaultNodeProperties(mitk::DataNode::Pointer node, std::string name); berry::ISelectionListener::Pointer m_SelListener; berry::IStructuredSelection::ConstPointer m_CurrentSelection; bool m_IsInitialized; mitk::PointSet::Pointer m_PointSetNode; mitk::DataNode::Pointer m_P1; Ui::QmitkTractbasedSpatialStatisticsViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; std::vector SortPoints(CharImageType::Pointer roi, CharImageType::IndexType currentPoint); bool PointVisited(std::vector points, CharImageType::IndexType point); // Modifies the current point by reference and returns true if no more points need to be visited CharImageType::IndexType FindNextPoint(std::vector pointsVisited, CharImageType::IndexType currentPoint, CharImageType::Pointer roi, bool &ready); //void DoInitializeGridByVectorImage(FloatVectorImageType::Pointer vectorpic, CharImageType::Pointer roi ,std::string name); // Tokenizer needed for the roi files void Tokenize(const std::string& str, std::vector& tokens, const std::string& delimiters = " ") { // Skip delimiters at beginning. std::string::size_type lastPos = str.find_first_not_of(delimiters, 0); // Find first "non-delimiter". std::string::size_type pos = str.find_first_of(delimiters, lastPos); while (std::string::npos != pos || std::string::npos != lastPos) { // Found a token, add it to the vector. tokens.push_back(str.substr(lastPos, pos - lastPos)); // Skip delimiters. Note the "not_of" lastPos = str.find_first_not_of(delimiters, pos); // Find next "non-delimiter" pos = str.find_first_of(delimiters, lastPos); } } mitk::DataNode::Pointer readNode(std::string f) { mitk::DataNode::Pointer node; mitk::DataNodeFactory::Pointer nodeReader = mitk::DataNodeFactory::New(); try { nodeReader->SetFileName(f); nodeReader->Update(); node = nodeReader->GetOutput(); } catch(...) { MITK_ERROR << "Could not read file"; return NULL; } return node; } /*template < typename TPixel, unsigned int VImageDimension > void ToITK4D( itk::Image* inputImage, Float4DImageType::Pointer& outputImage );*/ std::string ReadFile(std::string whatfile); std::vector< itk::Index<3> > m_Roi; std::string m_CurrentStructure; mitk::Geometry3D* m_CurrentGeometry; QmitkTbssTableModel* m_GroupModel; void AddTbssToDataStorage(mitk::Image* image, std::string name); mitk::TbssImage::Pointer m_CurrentTbssMetaImage; VectorImageType::Pointer ConvertToVectorImage(mitk::Image::Pointer mitkImg); - mitk::DataNode::Pointer m_DxxNode; - mitk::DataNode::Pointer m_DxyNode; - mitk::DataNode::Pointer m_DxzNode; - mitk::DataNode::Pointer m_DyzNode; - mitk::DataNode::Pointer m_DyyNode; - mitk::DataNode::Pointer m_DzzNode; + }; #endif // _QMITKTRACTBASEDSPATIALSTATISTICSVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsViewControls.ui index c07a46a0bd..b6d1b75c69 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsViewControls.ui @@ -1,640 +1,318 @@ QmitkTractbasedSpatialStatisticsViewControls 0 0 431 811 0 0 QmitkTemplate FSL import false false Here subject data and tbss meta data can be imported from FSL into the MITK TBSS module 0 Subject data QFrame::StyledPanel QFrame::Raised Group information QAbstractItemView::SelectRows QFrame::StyledPanel QFrame::Raised Add group entry. After that give the group a name and the correct number Add Remove selected entries Remove false Import a 4D image containing group data after group information has been set Import subject data QFrame::StyledPanel QFrame::Raised Diffusion measure Measurement in the to be imported 4D image Fractional Anisotropy Tract-specific analysis true To create a roi first load a tbss meta image into the datamanager - 3 + 0 ROIs QFormLayout::AllNonFixedFieldsGrow current selection mean FA skeleton: Points on Roi 100 100 0 100 Use this widget to create points on the ROI by shift-leftclick on the right positions on the skeleton. Then click Create Roi. The Roi that will be created will pass through the points in the order of occurence in this list false No suitable tbss meta image selected yet. The meta image needs to contain a mean FA skeleton and a skeleton mask Create ROI 0 0 Points on the ROI Name Give a name to the region of interest roiname Structure info On what anatomical structure lies the ROI? Structure Measuring To plot, load a tbss image with subject information and a region of interest corresponding to the study and select them both Copy to clipboard - - - Transform - - - - - - - - - false - - - Transform - - - - - - - - Import Tensor Image - - - - - - Dxx - - - - - - - Binary mask image to reduce the algorithms search space. - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 0 - - - - - true - - - => - - - - - - - true - - - N/A - - - true - - - - - - - - - - Dxy - - - - - - - Binary mask image to reduce the algorithms search space. - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 0 - - - - - true - - - => - - - - - - - true - - - N/A - - - true - - - - - - - - - - Dxz - - - - - - - Binary mask image to reduce the algorithms search space. - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 0 - - - - - true - - - => - - - - - - - true - - - N/A - - - true - - - - - - - - - - Dyy - - - - - - - Binary mask image to reduce the algorithms search space. - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 0 - - - - - true - - - => - - - - - - - true - - - N/A - - - true - - - - - - - - - - Dyz - - - - - - - Binary mask image to reduce the algorithms search space. - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 0 - - - - - true - - - => - - - - - - - true - - - N/A - - - true - - - - - - - - - - Dzz - - - - - - - Binary mask image to reduce the algorithms search space. - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 0 - - - - - true - - - => - - - - - - - true - - - N/A - - - true - - - - - - - - - - Import - - - - - QmitkPointListWidget QWidget
QmitkPointListWidget.h
QmitkTbssRoiAnalysisWidget QWidget
QmitkTbssRoiAnalysisWidget.h
1
diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/files.cmake b/Plugins/org.mitk.gui.qt.diffusionimagingapp/files.cmake index 19fa450822..ceb304b965 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/files.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/files.cmake @@ -1,98 +1,82 @@ set(SRC_CPP_FILES QmitkDiffusionImagingAppApplication.cpp QmitkDiffusionImagingAppWorkbenchAdvisor.cpp ) set(INTERNAL_CPP_FILES - mitkPluginActivator.cpp + QmitkDiffusionApplicationPlugin.cpp QmitkDiffusionImagingAppIntroPart.cpp - QmitkDiffusionImagingAppPerspective.cpp - QmitkWelcomePerspective.cpp - QmitkDIAppConnectomicsPerspective.cpp - QmitkDIAppDicomImportPerspective.cpp - QmitkDIAppFiberTractographyPerspective.cpp - QmitkDIAppIVIMPerspective.cpp - QmitkDIAppPreprocessingReconstructionPerspective.cpp - QmitkDIAppQuantificationPerspective.cpp - QmitkDIAppScreenshotsMoviesPerspective.cpp - QmitkDIAppTBSSPerspective.cpp - QmitkDIAppVolumeVisualizationPerspective.cpp - QmitkDIAppTrackingEvaluationPerspective.cpp + Perspectives/QmitkDiffusionImagingAppPerspective.cpp + Perspectives/QmitkWelcomePerspective.cpp + Perspectives/QmitkDIAppConnectomicsPerspective.cpp + Perspectives/QmitkDIAppDicomImportPerspective.cpp + Perspectives/QmitkDIAppFiberTractographyPerspective.cpp + Perspectives/QmitkDIAppIVIMPerspective.cpp + Perspectives/QmitkDIAppPreprocessingReconstructionPerspective.cpp + Perspectives/QmitkDIAppQuantificationPerspective.cpp + Perspectives/QmitkDIAppScreenshotsMoviesPerspective.cpp + Perspectives/QmitkDIAppTBSSPerspective.cpp + Perspectives/QmitkDIAppVolumeVisualizationPerspective.cpp ) set(UI_FILES src/internal/QmitkWelcomeScreenViewControls.ui ) set(MOC_H_FILES src/internal/QmitkDiffusionImagingAppIntroPart.h - src/internal/mitkPluginActivator.h + src/internal/QmitkDiffusionApplicationPlugin.h src/QmitkDiffusionImagingAppApplication.h - src/internal/QmitkDiffusionImagingAppPerspective.h - src/internal/QmitkWelcomePerspective.h - src/internal/QmitkDIAppConnectomicsPerspective.h - src/internal/QmitkDIAppDicomImportPerspective.h - src/internal/QmitkDIAppFiberTractographyPerspective.h - src/internal/QmitkDIAppIVIMPerspective.h - src/internal/QmitkDIAppPreprocessingReconstructionPerspective.h - src/internal/QmitkDIAppQuantificationPerspective.h - src/internal/QmitkDIAppScreenshotsMoviesPerspective.h - src/internal/QmitkDIAppTBSSPerspective.h - src/internal/QmitkDIAppVolumeVisualizationPerspective.h - src/internal/QmitkDIAppTrackingEvaluationPerspective.h + src/internal/Perspectives/QmitkDiffusionImagingAppPerspective.h + src/internal/Perspectives/QmitkWelcomePerspective.h + src/internal/Perspectives/QmitkDIAppConnectomicsPerspective.h + src/internal/Perspectives/QmitkDIAppDicomImportPerspective.h + src/internal/Perspectives/QmitkDIAppFiberTractographyPerspective.h + src/internal/Perspectives/QmitkDIAppIVIMPerspective.h + src/internal/Perspectives/QmitkDIAppPreprocessingReconstructionPerspective.h + src/internal/Perspectives/QmitkDIAppQuantificationPerspective.h + src/internal/Perspectives/QmitkDIAppScreenshotsMoviesPerspective.h + src/internal/Perspectives/QmitkDIAppTBSSPerspective.h + src/internal/Perspectives/QmitkDIAppVolumeVisualizationPerspective.h ) set(CACHED_RESOURCE_FILES # list of resource files which can be used by the plug-in # system without loading the plug-ins shared library, # for example the icon used in the menu and tabs for the # plug-in views in the workbench plugin.xml resources/icon_dicom.xpm resources/diffusionimaging.png resources/preprocessing.png resources/Measurement_48.png resources/volvis.png resources/perspectives/diffusionimaging.png resources/perspectives/icon_home.png resources/perspectives/connectomics.png resources/perspectives/dicomimport.png resources/perspectives/tractography.png resources/perspectives/ivim.png resources/perspectives/preprocessingreconstruction.png resources/perspectives/quantification.png resources/perspectives/screenshotsmovies.png resources/perspectives/tbss.png resources/perspectives/volumevizualization.png ) set(QRC_FILES # uncomment the following line if you want to use Qt resources resources/welcome/QmitkWelcomeScreenView.qrc resources/org_mitk_gui_qt_diffusionimagingapp.qrc ) # 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}) - -#----------- Qt Help Collection Project -------------# - -if(BLUEBERRY_USE_QT_HELP) - set(_plugin_qhcp_input "${CMAKE_CURRENT_SOURCE_DIR}/documentation/MitkDiffusionImagingAppQtHelpCollectionProject.qhcp") - set(_plugin_qhcp_output "${CMAKE_CURRENT_BINARY_DIR}/MitkDiffusionImagingAppQtHelpCollection.qhc") - add_custom_command(OUTPUT ${_plugin_qhcp_output} - COMMAND ${QT_COLLECTIONGENERATOR_EXECUTABLE} ${_plugin_qhcp_input} -o ${_plugin_qhcp_output} - DEPENDS ${_plugin_qhcp_input} - ) - - list(APPEND CACHED_RESOURCE_FILES ${_plugin_qhcp_output}) - #set(FILE_DEPENDENCIES ${_plugin_qhcp_output}) -endif() diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/plugin.xml b/Plugins/org.mitk.gui.qt.diffusionimagingapp/plugin.xml index d4c20d714a..174abdcf6d 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/plugin.xml +++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/plugin.xml @@ -1,73 +1,69 @@ - diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppWorkbenchAdvisor.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppWorkbenchAdvisor.cpp index fcbb3f4992..0e93f5e6c6 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppWorkbenchAdvisor.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppWorkbenchAdvisor.cpp @@ -1,116 +1,80 @@ /*========================================================================= Program: BlueBerry Platform Language: C++ Date: $Date: 2009-10-23 02:59:36 +0200 (Fri, 23 Oct 2009) $ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkDiffusionImagingAppWorkbenchAdvisor.h" -#include "internal/mitkPluginActivator.h" +#include "internal/QmitkDiffusionApplicationPlugin.h" #include #include #include #include #include #include const std::string QmitkDiffusionImagingAppWorkbenchAdvisor::WELCOME_PERSPECTIVE_ID = "org.mitk.diffusionimagingapp.perspectives.welcome"; void QmitkDiffusionImagingAppWorkbenchAdvisor::Initialize(berry::IWorkbenchConfigurer::Pointer configurer) { berry::QtWorkbenchAdvisor::Initialize(configurer); configurer->SetSaveAndRestore(true); - // TODO This should go into the products plugin_customization.ini file (when - // the product and branding support is finished, see bug 2146). - // This will not work anymore, if bug 2822 is fixed. - berry::IPreferencesService::Pointer prefService = berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); - prefService->GetSystemPreferences()->Put(berry::WorkbenchPreferenceConstants::PREFERRED_SASH_LAYOUT, berry::WorkbenchPreferenceConstants::RIGHT); - - QString collectionFile = mitkPluginActivator::GetDefault()->GetQtHelpCollectionFile(); - if (!collectionFile.isEmpty()) - { - berry::QtAssistantUtil::SetHelpCollectionFile(collectionFile); - berry::QtAssistantUtil::SetDefaultHelpUrl("qthelp://org.mitk.gui.qt.diffusionimagingapp/bundle/index.html"); - - typedef std::vector BundleContainer; - BundleContainer bundles = berry::Platform::GetBundles(); - berry::QtAssistantUtil::RegisterQCHFiles(bundles); - } - } berry::WorkbenchWindowAdvisor* QmitkDiffusionImagingAppWorkbenchAdvisor::CreateWorkbenchWindowAdvisor( berry::IWorkbenchWindowConfigurer::Pointer configurer) { std::vector perspExcludeList; perspExcludeList.push_back( std::string("org.blueberry.uitest.util.EmptyPerspective") ); perspExcludeList.push_back( std::string("org.blueberry.uitest.util.EmptyPerspective2") ); perspExcludeList.push_back( std::string("org.mitk.coreapp.defaultperspective") ); perspExcludeList.push_back( std::string("org.mitk.extapp.defaultperspective") ); perspExcludeList.push_back( std::string("org.mitk.perspectives.publicdiffusionimaging") ); perspExcludeList.push_back( std::string("org.mitk.perspectives.diffusionimaginginternal") ); + // Exclude the help perspective from org.blueberry.ui.qt.help from + // the normal perspective list. + // The perspective gets a dedicated menu entry in the help menu + perspExcludeList.push_back("org.blueberry.perspectives.help"); std::vector viewExcludeList; -// viewExcludeList.push_back( std::string("org.mitk.views.partialvolumeanalysis") ); -// viewExcludeList.push_back( std::string("org.mitk.views.globalfibertracking") ); -// viewExcludeList.push_back( std::string("org.mitk.views.tractbasedspatialstatistics") ); -// viewExcludeList.push_back( std::string("org.mitk.views.fibertracking") ); -// viewExcludeList.push_back( std::string("org.mitk.views.ivim") ); -// viewExcludeList.push_back( std::string("org.mitk.views.qballreconstruction") ); -// viewExcludeList.push_back( std::string("org.mitk.views.diffusiondicomimport") ); -// viewExcludeList.push_back( std::string("org.mitk.views.diffusionpreprocessing") ); -// viewExcludeList.push_back( std::string("org.mitk.views.diffusionquantification") ); -// viewExcludeList.push_back( std::string("org.mitk.views.tensorreconstruction") ); -// viewExcludeList.push_back( std::string("org.mitk.views.perspectiveswitcher") ); -// viewExcludeList.push_back( std::string("org.mitk.views.basicimageprocessing") ); -// viewExcludeList.push_back( std::string("org.mitk.views.fiberprocessing") ); -// viewExcludeList.push_back( std::string("org.mitk.views.measurement") ); -// viewExcludeList.push_back( std::string("org.mitk.views.moviemaker") ); -// viewExcludeList.push_back( std::string("org.mitk.views.odfdetails") ); -// viewExcludeList.push_back( std::string("org.mitk.views.propertylistview") ); -// viewExcludeList.push_back( std::string("org.mitk.views.screenshotmaker") ); -// viewExcludeList.push_back( std::string("org.mitk.views.segmentation") ); -// viewExcludeList.push_back( std::string("org.mitk.views.imagestatistics") ); -// viewExcludeList.push_back( std::string("org.mitk.views.controlvisualizationpropertiesview") ); -// viewExcludeList.push_back( std::string("org.mitk.views.volumevisualization") ); -// viewExcludeList.push_back( std::string("org.mitk.views.simplemeasurement") ); configurer->SetInitialSize(berry::Point(1000,770)); QmitkExtWorkbenchWindowAdvisor* advisor = new QmitkExtWorkbenchWindowAdvisor(this, configurer); advisor->ShowViewMenuItem(false); advisor->ShowNewWindowMenuItem(false); advisor->ShowClosePerspectiveMenuItem(false); advisor->SetPerspectiveExcludeList(perspExcludeList); advisor->SetViewExcludeList(viewExcludeList); advisor->ShowViewToolbar(false); advisor->ShowPerspectiveToolbar(true); advisor->ShowVersionInfo(false); advisor->ShowMitkVersionInfo(false); advisor->SetProductName("MITK Diffusion"); advisor->SetWindowIcon(":/org.mitk.gui.qt.diffusionimagingapp/app-icon.png"); return advisor; } std::string QmitkDiffusionImagingAppWorkbenchAdvisor::GetInitialWindowPerspectiveId() { return WELCOME_PERSPECTIVE_ID; } diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppConnectomicsPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppConnectomicsPerspective.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppConnectomicsPerspective.cpp rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppConnectomicsPerspective.cpp diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppConnectomicsPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppConnectomicsPerspective.h similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppConnectomicsPerspective.h rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppConnectomicsPerspective.h diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppDicomImportPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppDicomImportPerspective.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppDicomImportPerspective.cpp rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppDicomImportPerspective.cpp diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppDicomImportPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppDicomImportPerspective.h similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppDicomImportPerspective.h rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppDicomImportPerspective.h diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppFiberTractographyPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppFiberTractographyPerspective.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppFiberTractographyPerspective.cpp rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppFiberTractographyPerspective.cpp diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppFiberTractographyPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppFiberTractographyPerspective.h similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppFiberTractographyPerspective.h rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppFiberTractographyPerspective.h diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppIVIMPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppIVIMPerspective.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppIVIMPerspective.cpp rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppIVIMPerspective.cpp diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppIVIMPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppIVIMPerspective.h similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppIVIMPerspective.h rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppIVIMPerspective.h diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppPreprocessingReconstructionPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppPreprocessingReconstructionPerspective.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppPreprocessingReconstructionPerspective.cpp rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppPreprocessingReconstructionPerspective.cpp diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppPreprocessingReconstructionPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppPreprocessingReconstructionPerspective.h similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppPreprocessingReconstructionPerspective.h rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppPreprocessingReconstructionPerspective.h diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppQuantificationPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppQuantificationPerspective.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppQuantificationPerspective.cpp rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppQuantificationPerspective.cpp diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppQuantificationPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppQuantificationPerspective.h similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppQuantificationPerspective.h rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppQuantificationPerspective.h diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppScreenshotsMoviesPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppScreenshotsMoviesPerspective.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppScreenshotsMoviesPerspective.cpp rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppScreenshotsMoviesPerspective.cpp diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppScreenshotsMoviesPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppScreenshotsMoviesPerspective.h similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppScreenshotsMoviesPerspective.h rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppScreenshotsMoviesPerspective.h diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppTBSSPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppTBSSPerspective.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppTBSSPerspective.cpp rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppTBSSPerspective.cpp diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppTBSSPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppTBSSPerspective.h similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppTBSSPerspective.h rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppTBSSPerspective.h diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppTrackingEvaluationPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppTrackingEvaluationPerspective.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppTrackingEvaluationPerspective.cpp rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppTrackingEvaluationPerspective.cpp diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppTrackingEvaluationPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppTrackingEvaluationPerspective.h similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppTrackingEvaluationPerspective.h rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppTrackingEvaluationPerspective.h diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppVolumeVisualizationPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppVolumeVisualizationPerspective.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppVolumeVisualizationPerspective.cpp rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppVolumeVisualizationPerspective.cpp diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppVolumeVisualizationPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppVolumeVisualizationPerspective.h similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDIAppVolumeVisualizationPerspective.h rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDIAppVolumeVisualizationPerspective.h diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDiffusionImagingAppPerspective.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppPerspective.cpp rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDiffusionImagingAppPerspective.cpp diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDiffusionImagingAppPerspective.h similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppPerspective.h rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkDiffusionImagingAppPerspective.h diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkWelcomePerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkWelcomePerspective.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkWelcomePerspective.cpp rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkWelcomePerspective.cpp diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkWelcomePerspective.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkWelcomePerspective.h similarity index 100% rename from Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkWelcomePerspective.h rename to Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkWelcomePerspective.h diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionApplicationPlugin.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionApplicationPlugin.cpp new file mode 100644 index 0000000000..3fe48a15dd --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionApplicationPlugin.cpp @@ -0,0 +1,109 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "QmitkDiffusionApplicationPlugin.h" +#include "src/QmitkDiffusionImagingAppApplication.h" + +#include "src/internal/Perspectives/QmitkWelcomePerspective.h" +#include "src/internal/QmitkDiffusionImagingAppIntroPart.h" +#include "src/internal/Perspectives/QmitkDiffusionImagingAppPerspective.h" + +#include "src/internal/Perspectives/QmitkDIAppConnectomicsPerspective.h" +#include "src/internal/Perspectives/QmitkDIAppDicomImportPerspective.h" +#include "src/internal/Perspectives/QmitkDIAppFiberTractographyPerspective.h" +#include "src/internal/Perspectives/QmitkDIAppIVIMPerspective.h" +#include "src/internal/Perspectives/QmitkDIAppPreprocessingReconstructionPerspective.h" +#include "src/internal/Perspectives/QmitkDIAppQuantificationPerspective.h" +#include "src/internal/Perspectives/QmitkDIAppScreenshotsMoviesPerspective.h" +#include "src/internal/Perspectives/QmitkDIAppTBSSPerspective.h" +#include "src/internal/Perspectives/QmitkDIAppVolumeVisualizationPerspective.h" + +#include +#include + +#include +#include + +#include +#include +#include + +QmitkDiffusionApplicationPlugin* QmitkDiffusionApplicationPlugin::inst = 0; + +QmitkDiffusionApplicationPlugin::QmitkDiffusionApplicationPlugin() +{ + inst = this; +} + +QmitkDiffusionApplicationPlugin::~QmitkDiffusionApplicationPlugin() +{ +} + +QmitkDiffusionApplicationPlugin* QmitkDiffusionApplicationPlugin::GetDefault() +{ + return inst; +} + +void QmitkDiffusionApplicationPlugin::start(ctkPluginContext* context) +{ + berry::AbstractUICTKPlugin::start(context); + + this->context = context; + + BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionImagingAppApplication, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionImagingAppIntroPart, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionImagingAppPerspective, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkWelcomePerspective, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppConnectomicsPerspective, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppDicomImportPerspective, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppFiberTractographyPerspective, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppIVIMPerspective, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppPreprocessingReconstructionPerspective, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppQuantificationPerspective, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppScreenshotsMoviesPerspective, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppTBSSPerspective, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppVolumeVisualizationPerspective, context) + + ctkServiceReference cmRef = context->getServiceReference(); + ctkConfigurationAdmin* configAdmin = 0; + if (cmRef) + { + configAdmin = context->getService(cmRef); + } + + // Use the CTK Configuration Admin service to configure the BlueBerry help system + + if (configAdmin) + { + ctkConfigurationPtr conf = configAdmin->getConfiguration("org.blueberry.services.help", QString()); + ctkDictionary helpProps; + helpProps.insert("homePage", "qthelp://org.mitk.gui.qt.diffusionimagingapp/bundle/index.html"); + conf->update(helpProps); + context->ungetService(cmRef); + } + else + { + MITK_WARN << "Configuration Admin service unavailable, cannot set home page url."; + } +} + +ctkPluginContext* QmitkDiffusionApplicationPlugin::GetPluginContext() const +{ + return context; +} + +Q_EXPORT_PLUGIN2(org_mitk_gui_qt_diffusionimagingapp, QmitkDiffusionApplicationPlugin) diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionApplicationPlugin.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionApplicationPlugin.h new file mode 100644 index 0000000000..adf4523b93 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionApplicationPlugin.h @@ -0,0 +1,53 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#ifndef QMITKDIFFUSIONAPPLICATIONPLUGIN_H_ +#define QMITKDIFFUSIONAPPLICATIONPLUGIN_H_ + +#include + +#include + +#include + +class QmitkDiffusionApplicationPlugin : public QObject, public berry::AbstractUICTKPlugin +{ + Q_OBJECT + Q_INTERFACES(ctkPluginActivator) + +public: + + QmitkDiffusionApplicationPlugin(); + ~QmitkDiffusionApplicationPlugin(); + + static QmitkDiffusionApplicationPlugin* GetDefault(); + + ctkPluginContext* GetPluginContext() const; + + void start(ctkPluginContext*); + + QString GetQtHelpCollectionFile() const; + +private: + + static QmitkDiffusionApplicationPlugin* inst; + + ctkPluginContext* context; +}; + +#endif /* QMITKDIFFUSIONAPPLICATIONPLUGIN_H_ */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppApplication.h~bug-8511-DTI-atlas-app b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppApplication.h~bug-8511-DTI-atlas-app deleted file mode 100644 index 8debb63dad..0000000000 --- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppApplication.h~bug-8511-DTI-atlas-app +++ /dev/null @@ -1,41 +0,0 @@ -/*========================================================================= - -Program: Medical Imaging & Interaction Toolkit -Language: C++ -Date: $Date$ -Version: $Revision$ - -Copyright (c) German Cancer Research Center, Division of Medical and -Biological Informatics. All rights reserved. -See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. - -This software is distributed WITHOUT ANY WARRANTY; without even -the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ - -#ifndef QMITKDiffusionImagingAppAPPLICATION_H_ -#define QMITKDiffusionImagingAppAPPLICATION_H_ - -#include - -class QmitkDiffusionImagingAppApplication : public QObject, public berry::IApplication -{ - Q_OBJECT - -public: - - QmitkDiffusionImagingAppApplication() {} - QmitkDiffusionImagingAppApplication(const QmitkDiffusionImagingAppApplication& other) - { - Q_UNUSED(other) - throw std::runtime_error("Copy constructor not implemented"); - } - ~QmitkDiffusionImagingAppApplication() {} - - int Start(); - void Stop(); -}; - -#endif /*QMITKDiffusionImagingAppAPPLICATION_H_*/ diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppIntroPart.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppIntroPart.cpp index 329abe8cc0..f6d2bccbc0 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppIntroPart.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppIntroPart.cpp @@ -1,245 +1,184 @@ /*========================================================================= Program: BlueBerry Platform Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkDiffusionImagingAppIntroPart.h" #include "mitkNodePredicateDataType.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef QT_WEBKIT #include #include #endif #include #include #include #include #include #include #include "QmitkStdMultiWidget.h" #include "QmitkStdMultiWidgetEditor.h" -#include "mitkPluginActivator.h" +#include "QmitkDiffusionApplicationPlugin.h" #include "mitkDataStorageEditorInput.h" #include "mitkBaseDataIOFactory.h" #include "mitkSceneIO.h" #include "mitkProgressBar.h" #include "mitkDataNodeFactory.h" #include "mitkNodePredicateNot.h" #include "mitkNodePredicateProperty.h" QmitkDiffusionImagingAppIntroPart::QmitkDiffusionImagingAppIntroPart() : m_Controls(NULL) { - berry::IPreferences::Pointer workbenchPrefs = mitkPluginActivator::GetDefault()->GetPreferencesService()->GetSystemPreferences(); + berry::IPreferences::Pointer workbenchPrefs = QmitkDiffusionApplicationPlugin::GetDefault()->GetPreferencesService()->GetSystemPreferences(); workbenchPrefs->PutBool(berry::WorkbenchPreferenceConstants::SHOW_INTRO, true); workbenchPrefs->Flush(); } QmitkDiffusionImagingAppIntroPart::~QmitkDiffusionImagingAppIntroPart() { // if the workbench is not closing (that means, welcome screen was closed explicitly), set "Show_intro" false if (!this->GetIntroSite()->GetPage()->GetWorkbenchWindow()->GetWorkbench()->IsClosing()) { - berry::IPreferences::Pointer workbenchPrefs = mitkPluginActivator::GetDefault()->GetPreferencesService()->GetSystemPreferences(); + berry::IPreferences::Pointer workbenchPrefs = QmitkDiffusionApplicationPlugin::GetDefault()->GetPreferencesService()->GetSystemPreferences(); workbenchPrefs->PutBool(berry::WorkbenchPreferenceConstants::SHOW_INTRO, false); workbenchPrefs->Flush(); } else { - berry::IPreferences::Pointer workbenchPrefs = mitkPluginActivator::GetDefault()->GetPreferencesService()->GetSystemPreferences(); + berry::IPreferences::Pointer workbenchPrefs = QmitkDiffusionApplicationPlugin::GetDefault()->GetPreferencesService()->GetSystemPreferences(); workbenchPrefs->PutBool(berry::WorkbenchPreferenceConstants::SHOW_INTRO, true); workbenchPrefs->Flush(); } // if workbench is not closing (Just welcome screen closing), open last used perspective if (this->GetIntroSite()->GetPage()->GetPerspective()->GetId() == "org.mitk.diffusionimagingapp.perspectives.welcome" && !this->GetIntroSite()->GetPage()->GetWorkbenchWindow()->GetWorkbench()->IsClosing()) { berry::IPerspectiveDescriptor::Pointer perspective = this->GetIntroSite()->GetWorkbenchWindow()->GetWorkbench()->GetPerspectiveRegistry()->FindPerspectiveWithId("org.mitk.diffusionimagingapp.perspectives.diffusionimagingapp"); if (perspective) { this->GetIntroSite()->GetPage()->SetPerspective(perspective); } } } void QmitkDiffusionImagingAppIntroPart::CreateQtPartControl(QWidget* parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkWelcomeScreenViewControls; m_Controls->setupUi(parent); #ifdef QT_WEBKIT // create a QWebView as well as a QWebPage and QWebFrame within the QWebview m_view = new QWebView(parent); m_view->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); QUrl urlQtResource(QString("qrc:/org.mitk.gui.qt.welcomescreen/mitkdiffusionimagingappwelcomeview.html"), QUrl::TolerantMode ); m_view->load( urlQtResource ); // adds the webview as a widget parent->layout()->addWidget(m_view); this->CreateConnections(); #else parent->layout()->addWidget(new QLabel("

Please install Qt with the WebKit option to see cool pictures!

")); #endif } } #ifdef QT_WEBKIT void QmitkDiffusionImagingAppIntroPart::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_view->page()), SIGNAL(linkClicked(const QUrl& )), this, SLOT(DelegateMeTo(const QUrl& )) ); } } void QmitkDiffusionImagingAppIntroPart::DelegateMeTo(const QUrl& showMeNext) { QString scheme = showMeNext.scheme(); QByteArray urlHostname = showMeNext.encodedHost(); QByteArray urlPath = showMeNext.encodedPath(); QByteArray dataset = showMeNext.encodedQueryItemValue("dataset"); QByteArray clear = showMeNext.encodedQueryItemValue("clear"); if (scheme.isEmpty()) MITK_INFO << " empty scheme of the to be delegated link" ; // if the scheme is set to mitk, it is to be tested which action should be applied if (scheme.contains(QString("mitk")) ) { if(urlPath.isEmpty() ) MITK_INFO << " mitk path is empty " ; // searching for the perspective keyword within the host name if(urlHostname.contains(QByteArray("perspectives")) ) { // the simplified method removes every whitespace // ( whitespace means any character for which the standard C++ isspace() method returns true) urlPath = urlPath.simplified(); QString tmpPerspectiveId(urlPath.data()); tmpPerspectiveId.replace(QString("/"), QString("") ); std::string perspectiveId = tmpPerspectiveId.toStdString(); // is working fine as long as the perspective id is valid, if not the application crashes GetIntroSite()->GetWorkbenchWindow()->GetWorkbench()->ShowPerspective(perspectiveId, GetIntroSite()->GetWorkbenchWindow() ); - - mitk::DataStorageEditorInput::Pointer editorInput; - editorInput = new mitk::DataStorageEditorInput(); - berry::IEditorPart::Pointer editor = GetIntroSite()->GetPage()->OpenEditor(editorInput, QmitkStdMultiWidgetEditor::EDITOR_ID); - - - QmitkStdMultiWidgetEditor::Pointer multiWidgetEditor; - mitk::DataStorage::Pointer dataStorage; - - if (editor.Cast().IsNull()) - { - editorInput = new mitk::DataStorageEditorInput(); - dataStorage = editorInput->GetDataStorageReference()->GetDataStorage(); - } - else - { - multiWidgetEditor = editor.Cast(); - multiWidgetEditor->GetStdMultiWidget()->RequestUpdate(); - dataStorage = multiWidgetEditor->GetEditorInput().Cast()->GetDataStorageReference()->GetDataStorage(); - } - - bool dsmodified = false; - if(dataStorage.IsNotNull() && dsmodified) - { - // get all nodes that have not set "includeInBoundingBox" to false - mitk::NodePredicateNot::Pointer pred - = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox" - , mitk::BoolProperty::New(false))); - - mitk::DataStorage::SetOfObjects::ConstPointer rs = dataStorage->GetSubset(pred); - - if(rs->Size() > 0) - { - // calculate bounding geometry of these nodes - mitk::TimeSlicedGeometry::Pointer bounds = dataStorage->ComputeBoundingGeometry3D(rs); - // initialize the views to the bounding geometry - mitk::RenderingManager::GetInstance()->InitializeViews(bounds); - } - } - - } - // searching for the load - if(urlHostname.contains(QByteArray("perspectives")) ) - { - // the simplified method removes every whitespace - // ( whitespace means any character for which the standard C++ isspace() method returns true) - urlPath = urlPath.simplified(); - QString tmpPerspectiveId(urlPath.data()); - tmpPerspectiveId.replace(QString("/"), QString("") ); - std::string perspectiveId = tmpPerspectiveId.toStdString(); - - // is working fine as long as the perspective id is valid, if not the application crashes - GetIntroSite()->GetWorkbenchWindow()->GetWorkbench()->ShowPerspective(perspectiveId, GetIntroSite()->GetWorkbenchWindow() ); - - mitk::DataStorageEditorInput::Pointer editorInput; - editorInput = new mitk::DataStorageEditorInput(); - GetIntroSite()->GetPage()->OpenEditor(editorInput, QmitkStdMultiWidgetEditor::EDITOR_ID); - } - else - { - MITK_INFO << "Unkown mitk action keyword (see documentation for mitk links)" ; } } // if the scheme is set to http, by default no action is performed, if an external webpage needs to be // shown it should be implemented below else if (scheme.contains(QString("http")) ) { QDesktopServices::openUrl(showMeNext); // m_view->load( ) ; } else if(scheme.contains("qrc")) { m_view->load(showMeNext); } } #endif void QmitkDiffusionImagingAppIntroPart::StandbyStateChanged(bool standby) { } void QmitkDiffusionImagingAppIntroPart::SetFocus() { } diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/mitkPluginActivator.cpp deleted file mode 100644 index b251a54b97..0000000000 --- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/mitkPluginActivator.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/*========================================================================= - - Program: BlueBerry Platform - Language: C++ - Date: $Date$ - Version: $Revision$ - - Copyright (c) German Cancer Research Center, Division of Medical and - Biological Informatics. All rights reserved. - See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notices for more information. - - =========================================================================*/ - -#include "mitkPluginActivator.h" -#include -#include -#include - -#include "src/QmitkDiffusionImagingAppApplication.h" - -#include "QmitkWelcomePerspective.h" -#include "src/internal/QmitkDiffusionImagingAppIntroPart.h" -#include "src/internal/QmitkDiffusionImagingAppPerspective.h" - -#include "src/internal/QmitkDIAppConnectomicsPerspective.h" -#include "src/internal/QmitkDIAppDicomImportPerspective.h" -#include "src/internal/QmitkDIAppFiberTractographyPerspective.h" -#include "src/internal/QmitkDIAppIVIMPerspective.h" -#include "src/internal/QmitkDIAppPreprocessingReconstructionPerspective.h" -#include "src/internal/QmitkDIAppQuantificationPerspective.h" -#include "src/internal/QmitkDIAppScreenshotsMoviesPerspective.h" -#include "src/internal/QmitkDIAppTBSSPerspective.h" -#include "src/internal/QmitkDIAppVolumeVisualizationPerspective.h" -#include "src/internal/QmitkDIAppTrackingEvaluationPerspective.h" - -#include -#include - -mitkPluginActivator* mitkPluginActivator::inst = 0; - -mitkPluginActivator::mitkPluginActivator() - : pluginListener(0) -{ - inst = this; -} - -mitkPluginActivator::~mitkPluginActivator() -{ - delete pluginListener; -} - -mitkPluginActivator* mitkPluginActivator::GetDefault() -{ - return inst; -} - -void mitkPluginActivator::start(ctkPluginContext* context) -{ - berry::AbstractUICTKPlugin::start(context); - - this->context = context; - - BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionImagingAppApplication, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionImagingAppIntroPart, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionImagingAppPerspective, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkWelcomePerspective, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppConnectomicsPerspective, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppDicomImportPerspective, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppFiberTractographyPerspective, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppIVIMPerspective, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppPreprocessingReconstructionPerspective, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppQuantificationPerspective, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppScreenshotsMoviesPerspective, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppTBSSPerspective, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppVolumeVisualizationPerspective, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppTrackingEvaluationPerspective, context) - - delete pluginListener; - pluginListener = new berry::QCHPluginListener(context); - context->connectPluginListener(pluginListener, SLOT(pluginChanged(ctkPluginEvent)), Qt::DirectConnection); - - // register all QCH files from all the currently installed plugins - pluginListener->processPlugins(); - - -} - -QString mitkPluginActivator::GetQtHelpCollectionFile() const -{ - - if (!helpCollectionFile.isEmpty()) - { - return helpCollectionFile; - } - - QString collectionFilename; - QString na("n/a"); -// if (na != MITK_REVISION) -// collectionFilename = "MitkDiffusionImagingAppQtHelpCollection_" MITK_REVISION ".qhc"; -// else - collectionFilename = "MitkDiffusionImagingAppQtHelpCollection.qhc"; - - QFileInfo collectionFileInfo = context->getDataFile(collectionFilename); - QFileInfo pluginFileInfo = QFileInfo(QUrl(context->getPlugin()->getLocation()).toLocalFile()); - if (!collectionFileInfo.exists() || - pluginFileInfo.lastModified() > collectionFileInfo.lastModified()) - { - // extract the qhc file from the plug-in - QByteArray content = context->getPlugin()->getResource(collectionFilename); - if (content.isEmpty()) - { - BERRY_WARN << "Could not get plug-in resource: " << collectionFilename.toStdString(); - } - else - { - QFile file(collectionFileInfo.absoluteFilePath()); - file.open(QIODevice::WriteOnly); - file.write(content); - file.close(); - } - } - - if (QFile::exists(collectionFileInfo.absoluteFilePath())) - { - helpCollectionFile = collectionFileInfo.absoluteFilePath(); - } - - return helpCollectionFile; - -} - -Q_EXPORT_PLUGIN2(org_mitk_gui_qt_diffusionimagingapp, mitkPluginActivator) - - diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/mitkPluginActivator.h deleted file mode 100644 index a5a0d7ee92..0000000000 --- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/mitkPluginActivator.h +++ /dev/null @@ -1,59 +0,0 @@ -/*========================================================================= - - Program: BlueBerry Platform - Language: C++ - Date: $Date$ - Version: $Revision$ - - Copyright (c) German Cancer Research Center, Division of Medical and - Biological Informatics. All rights reserved. - See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notices for more information. - - =========================================================================*/ - -#ifndef QMITKDIFFUSIONIMAGINGAPPAPPLICATIONPLUGIN_H_ -#define QMITKDIFFUSIONIMAGINGAPPAPPLICATIONPLUGIN_H_ - -#include -#include -#include - -#include -#include - -class MITK_LOCAL mitkPluginActivator : - public QObject, public berry::AbstractUICTKPlugin -{ - Q_OBJECT - Q_INTERFACES(ctkPluginActivator) - -public: - - mitkPluginActivator(); - ~mitkPluginActivator(); - - static mitkPluginActivator* GetDefault(); - - ctkPluginContext* GetPluginContext() const; - - void start(ctkPluginContext*); - - QString GetQtHelpCollectionFile() const; - - private: - - static mitkPluginActivator* inst; - - ctkPluginContext* context; - berry::QCHPluginListener* pluginListener; - - mutable QString helpCollectionFile; - - -}; // QmitkDiffusionImagingAppApplicationPlugin - -#endif // QMITKDIFFUSIONIMAGINGAPPAPPLICATIONPLUGIN_H_ diff --git a/Plugins/org.mitk.gui.qt.toftutorial/src/internal/QmitkToFTutorialView.cpp b/Plugins/org.mitk.gui.qt.toftutorial/src/internal/QmitkToFTutorialView.cpp index 53003d3d27..bd980acdae 100644 --- a/Plugins/org.mitk.gui.qt.toftutorial/src/internal/QmitkToFTutorialView.cpp +++ b/Plugins/org.mitk.gui.qt.toftutorial/src/internal/QmitkToFTutorialView.cpp @@ -1,200 +1,196 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkToFTutorialView.h" #include "QmitkStdMultiWidget.h" // Qt #include // mitk includes #include // class holding the intrinsic parameters of the according camera #include // MITK-ToF related includes +#include #include // configuration file holding e.g. plugin paths or path to test file directory #include // filter from module ToFProcessing that calculates a surface from the given range image -#include // creator class that provides pre-configured ToFCameraDevices #include // allows access to images provided by the ToF camera - - const std::string QmitkToFTutorialView::VIEW_ID = "org.mitk.views.toftutorial"; QmitkToFTutorialView::QmitkToFTutorialView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) { } QmitkToFTutorialView::~QmitkToFTutorialView() { } - void QmitkToFTutorialView::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::QmitkToFTutorialViewControls; m_Controls->setupUi( parent ); connect( m_Controls->step1Button, SIGNAL(clicked()), this, SLOT(OnStep1()) ); connect( m_Controls->step2Button, SIGNAL(clicked()), this, SLOT(OnStep2()) ); } } void QmitkToFTutorialView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } - void QmitkToFTutorialView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } - void QmitkToFTutorialView::OnStep1() { // clean up data storage RemoveAllNodesFromDataStorage(); - // use ToFImageGrabber to create instance of ToFImageGrabber that holds a ToFCameraMITKPlayerDevice for playing ToF data - mitk::ToFImageGrabber::Pointer tofImageGrabber = mitk::ToFImageGrabberCreator::GetInstance()->GetMITKPlayerImageGrabber(); + // Create an instance of ToFImageGrabber that holds a ToFCameraMITKPlayerDevice for playing ToF data + mitk::ToFImageGrabber::Pointer tofImageGrabber = mitk::ToFImageGrabber::New(); + tofImageGrabber->SetCameraDevice(mitk::ToFCameraMITKPlayerDevice::New()); // set paths to test data std::string distanceFileName = MITK_TOF_DATA_DIR; distanceFileName.append("/PMDCamCube2_MF0_IT0_20Images_DistanceImage.pic"); std::string amplitudeFileName = MITK_TOF_DATA_DIR; amplitudeFileName.append("/PMDCamCube2_MF0_IT0_20Images_AmplitudeImage.pic"); std::string intensityFileName = MITK_TOF_DATA_DIR; intensityFileName.append("/PMDCamCube2_MF0_IT0_20Images_IntensityImage.pic"); // set file name property in image grabber. This will be propagated to the corresponding device and controller class tofImageGrabber->SetProperty("DistanceImageFileName",mitk::StringProperty::New(distanceFileName)); tofImageGrabber->SetProperty("AmplitudeImageFileName",mitk::StringProperty::New(amplitudeFileName)); tofImageGrabber->SetProperty("IntensityImageFileName",mitk::StringProperty::New(intensityFileName)); // connect to device if (tofImageGrabber->ConnectCamera()) { //// start camera (internally starts thread that continuously grabs images from the camera) tofImageGrabber->StartCamera(); // update image grabber which itself represents the source of a MITK filter pipeline tofImageGrabber->Update(); // grab distance image mitk::Image::Pointer distanceImage = tofImageGrabber->GetOutput(0); // grab amplitude image mitk::Image::Pointer amplitudeImage = tofImageGrabber->GetOutput(1); // grab intensity image mitk::Image::Pointer intensityImage = tofImageGrabber->GetOutput(2); //add distance image to data storage mitk::DataNode::Pointer distanceNode = mitk::DataNode::New(); distanceNode->SetName("Distance Image"); distanceNode->SetData(distanceImage); this->GetDefaultDataStorage()->Add(distanceNode); //add amplitude image to data storage mitk::DataNode::Pointer amplitudeNode = mitk::DataNode::New(); amplitudeNode->SetName("Amplitude Image"); amplitudeNode->SetData(amplitudeImage); this->GetDefaultDataStorage()->Add(amplitudeNode); //add intensity image to data storage mitk::DataNode::Pointer intensityNode = mitk::DataNode::New(); intensityNode->SetName("Intensity Image"); intensityNode->SetData(intensityImage); this->GetDefaultDataStorage()->Add(intensityNode); // stop camera (terminate internally used thread) tofImageGrabber->StopCamera(); //// disconnect from camera tofImageGrabber->DisconnectCamera(); // adjust views to new data in DataStorage mitk::RenderingManager::GetInstance()->InitializeViews(distanceImage->GetGeometry()); } else { MITK_ERROR<<"Connection to ToF camera could not be established"; } } void QmitkToFTutorialView::OnStep2() { // Check if distance image is available mitk::DataNode::Pointer distanceNode = this->GetDefaultDataStorage()->GetNamedNode("Distance Image"); if (distanceNode.IsNotNull()) { // get distance image from node and check if node contains image mitk::Image::Pointer distanceImage = dynamic_cast(distanceNode->GetData()); if (distanceImage.IsNotNull()) { // create object of CameraIntrinsics that holds intrinsic parameters of the ToF camera mitk::CameraIntrinsics::Pointer cameraIntrinsics = mitk::CameraIntrinsics::New(); // set focal length in pixel cameraIntrinsics->SetFocalLength(295.8,296.1); // set principal point in pixel cameraIntrinsics->SetPrincipalPoint(113.2,97.1); // set up filter for surface calculation mitk::ToFDistanceImageToSurfaceFilter::Pointer surfaceFilter = mitk::ToFDistanceImageToSurfaceFilter::New(); // apply intrinsic parameters to filter surfaceFilter->SetCameraIntrinsics(cameraIntrinsics); // set distance between pixels on chip in mm (in this example squared pixel) mitk::ToFProcessingCommon::ToFPoint2D interPixelDistance; interPixelDistance[0] = 0.045; interPixelDistance[1] = 0.045; surfaceFilter->SetInterPixelDistance(interPixelDistance); // set distance image as input surfaceFilter->SetInput(distanceImage); // update the filter surfaceFilter->Update(); // get surface from filter mitk::Surface::Pointer surface = surfaceFilter->GetOutput(); // add surface to data storage mitk::DataNode::Pointer surfaceNode = mitk::DataNode::New(); surfaceNode->SetName("ToF surface"); surfaceNode->SetData(surface); this->GetDefaultDataStorage()->Add(surfaceNode); // adjust views to new data in DataStorage mitk::RenderingManager::GetInstance()->InitializeViews(surface->GetGeometry()); mitk::RenderingManager::GetInstance()->InitializeViews(surface->GetGeometry()); } else { QMessageBox::warning(NULL,"ToF Tutorial","Node 'Distance Image' contains no image"); } } else { QMessageBox::warning(NULL,"ToF Tutorial","Perform Step 1 first to acquire a distance image"); } } void QmitkToFTutorialView::RemoveAllNodesFromDataStorage() { mitk::DataStorage::SetOfObjects::ConstPointer allNodes = this->GetDefaultDataStorage()->GetAll(); this->GetDefaultDataStorage()->Remove(allNodes); } diff --git a/Utilities/CMakeLists.txt b/Utilities/CMakeLists.txt index b7db4ff132..327554976f 100644 --- a/Utilities/CMakeLists.txt +++ b/Utilities/CMakeLists.txt @@ -1,49 +1,49 @@ SUPPRESS_ALL_WARNINGS() # most stuff of these uses itk_zlib.h (via mitkIpPic.h) find_package(ITK) include(${ITK_USE_FILE}) # some legacy util files include in the old style with prefixed directory, # like #include include_directories(.) subdirs( ann ipSegmentation - IIL4MITK + #IIL4MITK pic2vtk tinyxml Poco qwt qxt mbilog glew vecmath qtsingleapplication ) # mbilog is independent of mitk, and cant use mitk macros # configuring happens through mbilog/mbilogConfig.cmake.in set(mbilog_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/mbilog" "${CMAKE_CURRENT_BINARY_DIR}/mbilog") set(mbilog_CONFIG_FILE "${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME}/mbilogConfig.cmake" CACHE INTERNAL "Path to module config" FORCE) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/mbilog/mbilogConfig.cmake.in" "${mbilog_CONFIG_FILE}") # if(NOT MITK_CHILI_PLUGIN) subdirs(ipPic ipFunc) add_subdirectory(KWStyle) # endif(NOT MITK_CHILI_PLUGIN) set(Poco_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Poco CACHE PATH "top-level directory containing the poco include directories. E.g /usr/local/include/ or c:\\poco\\include\\poco-1.3.2" ) set(Poco_LIBRARY_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} CACHE PATH "top-level directory containing the poco libraries." )