diff --git a/Applications/PluginGenerator/CMakeLists.txt b/Applications/PluginGenerator/CMakeLists.txt index 66dded2398..4e56205ee9 100644 --- a/Applications/PluginGenerator/CMakeLists.txt +++ b/Applications/PluginGenerator/CMakeLists.txt @@ -1,92 +1,92 @@ if (${CMAKE_SOURCE_DIR} EQUAL ${PROJECT_SOURCE_DIR}) cmake_minimum_required(VERSION 3.1 FATAL_ERROR) endif() project(MitkPluginGenerator) set(VERSION_MAJOR 1) set(VERSION_MINOR 5) set(VERSION_PATCH 0) set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) set(standalone_build 1) else() set(standalone_build 0) endif() #----------------------------------------------------------------------------- # Prerequisites #----------------------------------------------------------------------------- set(QT_DONT_USE_QTGUI 1) set(QT_USE_QTNETWORK 1) if(MITK_USE_Qt4) find_package(Qt 4.7 REQUIRED) include(${QT_USE_FILE}) else() find_package(Qt5Network REQUIRED) endif() configure_file("${CMAKE_CURRENT_SOURCE_DIR}/PluginGeneratorConfig.h.in" "${CMAKE_CURRENT_BINARY_DIR}/PluginGeneratorConfig.h" @ONLY) include_directories("${CMAKE_CURRENT_BINARY_DIR}") #----------------------------------------------------------------------------- # Executable #----------------------------------------------------------------------------- set(src_files PluginGenerator.cpp ctkCommandLineParser.cpp ) if(MITK_USE_Qt4) qt4_wrap_cpp(src_files ctkCommandLineParser.h OPTIONS -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) qt4_add_resources(src_files plugin_template.qrc project_template.qrc) else() qt5_wrap_cpp(src_files ctkCommandLineParser.h OPTIONS -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) qt5_add_resources(src_files plugin_template.qrc project_template.qrc) endif() set(exec_target ${PROJECT_NAME}) add_executable(${exec_target} ${src_files}) if(MITK_USE_Qt4) target_link_libraries(${exec_target} ${QT_LIBRARIES}) else() target_link_libraries(${exec_target} Qt5::Network) endif() if(NOT standalone_build) # subproject support add_dependencies(MITK-CoreUI ${exec_target}) endif() #----------------------------------------------------------------------------- # Win32 Convenience #----------------------------------------------------------------------------- if(WIN32 AND NOT standalone_build) file(TO_NATIVE_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}" native_runtime_dir) add_custom_target(NewPlugin start "MITK PluginGenerator" /D "${native_runtime_dir}" cmd /K ${exec_target}.exe -h DEPENDS ${exec_target}) endif() #----------------------------------------------------------------------------- # Testing #----------------------------------------------------------------------------- if(NOT standalone_build) # Test the plugin generator - include(mitkTestPluginGenerator) + # include(mitkTestPluginGenerator) endif() #----------------------------------------------------------------------------- # Packaging support #----------------------------------------------------------------------------- if(standalone_build) include(SetupPackaging.cmake) endif() diff --git a/Applications/PluginGenerator/PluginTemplate/CMakeLists.txt b/Applications/PluginGenerator/PluginTemplate/CMakeLists.txt index 7839a577ed..78f3b80eff 100644 --- a/Applications/PluginGenerator/PluginTemplate/CMakeLists.txt +++ b/Applications/PluginGenerator/PluginTemplate/CMakeLists.txt @@ -1,7 +1,14 @@ project($(plugin-target)) +if(MITK_USE_Qt5) + find_package(Qt5OpenGL REQUIRED) + find_package(Qt5Sql REQUIRED) + find_package(Qt5Widgets REQUIRED) + find_package(Qt5Xml REQUIRED) +endif() + MACRO_CREATE_MITK_CTK_PLUGIN( EXPORT_DIRECTIVE $(plugin-export-directive) EXPORTED_INCLUDE_SUFFIXES src MODULE_DEPENDS MitkQtWidgetsExt ) diff --git a/Applications/PluginGenerator/ProjectTemplate/Apps/TemplateApp/CMakeLists.txt b/Applications/PluginGenerator/ProjectTemplate/Apps/TemplateApp/CMakeLists.txt index 3e992f0312..0ceaaca758 100644 --- a/Applications/PluginGenerator/ProjectTemplate/Apps/TemplateApp/CMakeLists.txt +++ b/Applications/PluginGenerator/ProjectTemplate/Apps/TemplateApp/CMakeLists.txt @@ -1,22 +1,22 @@ set(_app_options) if(${MY_PROJECT_NAME}_SHOW_CONSOLE_WINDOW) list(APPEND _app_options SHOW_CONSOLE) endif() # Plug-ins listed below will not be # - added as a build-time dependency to the executable # - listed in the provisioning file for the executable # - installed if they are external plug-ins set(_exclude_plugins ) FunctionCreateBlueBerryApplication( NAME ${MY_APP_NAME} DESCRIPTION "MITK - ${MY_APP_NAME} Application" EXCLUDE_PLUGINS ${_exclude_plugins} ${_app_options} ) -mitk_use_modules(TARGET ${MY_APP_NAME} PACKAGES Qt4|QtGui) +mitk_use_modules(TARGET ${MY_APP_NAME} PACKAGES Qt4|QtGui Qt5|Widgets) diff --git a/Applications/PluginGenerator/ProjectTemplate/CMakeExternals/MITK.cmake b/Applications/PluginGenerator/ProjectTemplate/CMakeExternals/MITK.cmake index 3a73aa3e16..33b32e5b89 100644 --- a/Applications/PluginGenerator/ProjectTemplate/CMakeExternals/MITK.cmake +++ b/Applications/PluginGenerator/ProjectTemplate/CMakeExternals/MITK.cmake @@ -1,213 +1,227 @@ #----------------------------------------------------------------------------- # MITK #----------------------------------------------------------------------------- set(MITK_DEPENDS) set(proj_DEPENDENCIES) set(proj MITK) if(NOT MITK_DIR) #----------------------------------------------------------------------------- # Create CMake options to customize the MITK build #----------------------------------------------------------------------------- option(MITK_USE_SUPERBUILD "Use superbuild for MITK" ON) option(MITK_USE_BLUEBERRY "Build the BlueBerry platform in MITK" ON) option(MITK_BUILD_EXAMPLES "Build the MITK examples" OFF) option(MITK_BUILD_ALL_PLUGINS "Build all MITK plugins" OFF) option(MITK_BUILD_TESTING "Build the MITK unit tests" OFF) option(MITK_USE_ACVD "Use Approximated Centroidal Voronoi Diagrams" OFF) option(MITK_USE_CTK "Use CTK in MITK" ${MITK_USE_BLUEBERRY}) option(MITK_USE_DCMTK "Use DCMTK in MITK" ON) option(MITK_USE_QT "Use Nokia's Qt library in MITK" ON) option(MITK_USE_Boost "Use the Boost library in MITK" OFF) option(MITK_USE_OpenCV "Use Intel's OpenCV library" OFF) option(MITK_USE_SOFA "Use Simulation Open Framework Architecture" OFF) option(MITK_USE_Python "Enable Python wrapping in MITK" OFF) if(MITK_USE_BLUEBERRY AND 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() 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() set(MITK_USE_CableSwig ${MITK_USE_Python}) set(MITK_USE_GDCM 1) set(MITK_USE_ITK 1) set(MITK_USE_VTK 1) mark_as_advanced(MITK_USE_SUPERBUILD MITK_BUILD_ALL_PLUGINS MITK_BUILD_TESTING ) set(mitk_cmake_boolean_args MITK_USE_SUPERBUILD MITK_USE_BLUEBERRY MITK_BUILD_EXAMPLES MITK_BUILD_ALL_PLUGINS MITK_USE_ACVD MITK_USE_CTK MITK_USE_DCMTK MITK_USE_QT MITK_USE_Boost MITK_USE_OpenCV MITK_USE_SOFA MITK_USE_Python ) - if(MITK_USE_QT) + if(MITK_USE_Qt4) # Look for Qt at the superbuild level, to catch missing Qt libs early find_package(Qt4 4.7 REQUIRED) + elseif(MITK_USE_Qt5) + find_package(Qt5Widgets REQUIRED) endif() set(additional_mitk_cmakevars ) # Configure the set of default 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") 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") foreach(_arg MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES MITK_ACCESSBYITK_DIMENSIONS) mark_as_advanced(${_arg}) list(APPEND additional_mitk_cmakevars "-D${_arg}:STRING=${${_arg}}") endforeach() #----------------------------------------------------------------------------- # Create options to inject pre-build dependencies #----------------------------------------------------------------------------- foreach(proj CTK DCMTK GDCM VTK ACVD ITK OpenCV SOFA CableSwig) if(MITK_USE_${proj}) set(MITK_${proj}_DIR "${${proj}_DIR}" CACHE PATH "Path to ${proj} build directory") mark_as_advanced(MITK_${proj}_DIR) if(MITK_${proj}_DIR) list(APPEND additional_mitk_cmakevars "-D${proj}_DIR:PATH=${MITK_${proj}_DIR}") endif() endif() endforeach() if(MITK_USE_Boost) set(MITK_BOOST_ROOT "${BOOST_ROOT}" CACHE PATH "Path to Boost directory") mark_as_advanced(MITK_BOOST_ROOT) if(MITK_BOOST_ROOT) list(APPEND additional_mitk_cmakevars "-DBOOST_ROOT:PATH=${MITK_BOOST_ROOT}") endif() endif() set(MITK_SOURCE_DIR "" CACHE PATH "MITK source code location. If empty, MITK will be cloned from MITK_GIT_REPOSITORY") set(MITK_GIT_REPOSITORY "http://git.mitk.org/MITK.git" CACHE STRING "The git repository for cloning MITK") set(MITK_GIT_TAG "releases/master" CACHE STRING "The git tag/hash to be used when cloning from MITK_GIT_REPOSITORY") mark_as_advanced(MITK_SOURCE_DIR MITK_GIT_REPOSITORY MITK_GIT_TAG) #----------------------------------------------------------------------------- # Create the final variable containing superbuild boolean args #----------------------------------------------------------------------------- set(mitk_boolean_args) foreach(mitk_cmake_arg ${mitk_cmake_boolean_args}) list(APPEND mitk_boolean_args -D${mitk_cmake_arg}:BOOL=${${mitk_cmake_arg}}) endforeach() #----------------------------------------------------------------------------- # Additional MITK CMake variables #----------------------------------------------------------------------------- - if(MITK_USE_QT AND QT_QMAKE_EXECUTABLE) + if(MITK_USE_Qt4 AND QT_QMAKE_EXECUTABLE) list(APPEND additional_mitk_cmakevars "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}") + elseif(MITK_USE_Qt5) + list(APPEND additional_mitk_cmakevars "-DDESIRED_QT_VERSION:STRING=5") + list(APPEND additional_mitk_cmakevars "-DCMAKE_PREFIX_PATH:PATH=${CMAKE_PREFIX_PATH}") endif() if(MITK_USE_CTK) list(APPEND additional_mitk_cmakevars "-DGIT_EXECUTABLE:FILEPATH=${GIT_EXECUTABLE}") endif() if(MITK_INITIAL_CACHE_FILE) list(APPEND additional_mitk_cmakevars "-DMITK_INITIAL_CACHE_FILE:INTERNAL=${MITK_INITIAL_CACHE_FILE}") endif() if(MITK_USE_SUPERBUILD) set(MITK_BINARY_DIR ${proj}-superbuild) else() set(MITK_BINARY_DIR ${proj}-build) endif() set(proj_DEPENDENCIES) set(MITK_DEPENDS ${proj}) # Configure the MITK souce code location if(NOT MITK_SOURCE_DIR) set(mitk_source_location SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj} GIT_REPOSITORY ${MITK_GIT_REPOSITORY} GIT_TAG ${MITK_GIT_TAG} ) else() set(mitk_source_location SOURCE_DIR ${MITK_SOURCE_DIR} ) endif() ExternalProject_Add(${proj} ${mitk_source_location} BINARY_DIR ${MITK_BINARY_DIR} PREFIX ${proj}${ep_suffix} INSTALL_COMMAND "" CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} ${mitk_boolean_args} ${additional_mitk_cmakevars} -DBUILD_SHARED_LIBS:BOOL=ON -DBUILD_TESTING:BOOL=${MITK_BUILD_TESTING} DEPENDS ${proj_DEPENDENCIES} ) if(MITK_USE_SUPERBUILD) set(MITK_DIR "${CMAKE_CURRENT_BINARY_DIR}/${MITK_BINARY_DIR}/MITK-build") else() set(MITK_DIR "${CMAKE_CURRENT_BINARY_DIR}/${MITK_BINARY_DIR}") endif() else() # The project is provided using MITK_DIR, nevertheless since other # projects may depend on MITK, let's add an 'empty' one MacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") # Further, do some sanity checks in the case of a pre-built MITK set(my_itk_dir ${ITK_DIR}) set(my_vtk_dir ${VTK_DIR}) - set(my_qmake_executable ${QT_QMAKE_EXECUTABLE}) find_package(MITK REQUIRED) if(my_itk_dir AND NOT my_itk_dir STREQUAL ${ITK_DIR}) message(FATAL_ERROR "ITK packages do not match:\n ${MY_PROJECT_NAME}: ${my_itk_dir}\n MITK: ${ITK_DIR}") endif() if(my_vtk_dir AND NOT my_vtk_dir STREQUAL ${VTK_DIR}) message(FATAL_ERROR "VTK packages do not match:\n ${MY_PROJECT_NAME}: ${my_vtk_dir}\n MITK: ${VTK_DIR}") endif() + if(MITK_USE_Qt4) + set(my_qmake_executable ${QT_QMAKE_EXECUTABLE}) + + if(my_qmake_executable AND MITK_QMAKE_EXECUTABLE) + if(NOT my_qmake_executable STREQUAL ${MITK_QMAKE_EXECUTABLE}) + message(FATAL_ERROR "Qt qmake does not match:\n ${MY_PROJECT_NAME}: ${my_qmake_executable}\n MITK: ${MITK_QMAKE_EXECUTABLE}") + endif() + endif() + endif() + endif() diff --git a/Applications/PluginGenerator/ProjectTemplate/CMakeLists.txt b/Applications/PluginGenerator/ProjectTemplate/CMakeLists.txt index 2519ec21db..38d5b43a45 100644 --- a/Applications/PluginGenerator/ProjectTemplate/CMakeLists.txt +++ b/Applications/PluginGenerator/ProjectTemplate/CMakeLists.txt @@ -1,361 +1,361 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR) # Change project and application name to your own set(MY_PROJECT_NAME $(project-name)) set(MY_APP_NAME $(project-app-name)) #----------------------------------------------------------------------------- # Set the language standard (MITK requires C++11) #----------------------------------------------------------------------------- set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED 1) set(CMAKE_CXX_EXTENSIONS 0) #----------------------------------------------------------------------------- # 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(${MY_PROJECT_NAME}_USE_SUPERBUILD "Build ${MY_PROJECT_NAME} and the projects it depends on via SuperBuild.cmake." ON) if(${MY_PROJECT_NAME}_USE_SUPERBUILD) project(${MY_PROJECT_NAME}-superbuild) set(${MY_PROJECT_NAME}_SOURCE_DIR ${PROJECT_SOURCE_DIR}) set(${MY_PROJECT_NAME}_BINARY_DIR ${PROJECT_BINARY_DIR}) else() project(${MY_PROJECT_NAME}) 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 CMP0020 # NEW: Automatically link Qt executables to qtmain target on Windows. CMP0028 # NEW: Double colon in target name means ALIAS or IMPORTED target. ) foreach(policy ${project_policies}) if(POLICY ${policy}) cmake_policy(SET ${policy} NEW) endif() endforeach() #----------------------------------------------------------------------------- # Update CMake module path #------------------------------------------------------------------------------ set(CMAKE_MODULE_PATH ${${MY_PROJECT_NAME}_SOURCE_DIR}/CMake ${CMAKE_MODULE_PATH} ) #----------------------------------------------------------------------------- # CMake Function(s) and Macro(s) #----------------------------------------------------------------------------- include(MacroEmptyExternalProject) #----------------------------------------------------------------------------- # Output directories. #----------------------------------------------------------------------------- foreach(type LIBRARY RUNTIME ARCHIVE) set(output_dir ${${MY_PROJECT_NAME}_BINARY_DIR}/bin) 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 Options (also shown during superbuild) #----------------------------------------------------------------------------- option(BUILD_SHARED_LIBS "Build ${MY_PROJECT_NAME} with shared libraries" ON) option(WITH_COVERAGE "Enable/Disable coverage" OFF) option(BUILD_TESTING "Test the project" ON) option(${MY_PROJECT_NAME}_BUILD_ALL_PLUGINS "Build all ${MY_PROJECT_NAME} plugins" OFF) mark_as_advanced(${MY_PROJECT_NAME}_INSTALL_RPATH_RELATIVE ${MY_PROJECT_NAME}_BUILD_ALL_PLUGINS ) #----------------------------------------------------------------------------- # Superbuild script #----------------------------------------------------------------------------- if(${MY_PROJECT_NAME}_USE_SUPERBUILD) include("${CMAKE_CURRENT_SOURCE_DIR}/SuperBuild.cmake") return() endif() #***************************************************************************** #**************************** END OF SUPERBUILD **************************** #***************************************************************************** #----------------------------------------------------------------------------- # Prerequesites #----------------------------------------------------------------------------- set(${PROJECT_NAME}_MODULES_PACKAGE_DEPENDS_DIR "${PROJECT_SOURCE_DIR}/CMake/PackageDepends") set(MODULES_PACKAGE_DEPENDS_DIRS ${${PROJECT_NAME}_MODULES_PACKAGE_DEPENDS_DIR}) find_package(MITK 2014.10.99 REQUIRED) if(COMMAND mitkFunctionCheckMitkCompatibility) mitkFunctionCheckMitkCompatibility(VERSIONS MITK_VERSION_PLUGIN_SYSTEM 1 REQUIRED) else() message(SEND_ERROR "Your MITK version is too old. Please use Git hash b86bf28 or newer") endif() link_directories(${MITK_LINK_DIRECTORIES}) #----------------------------------------------------------------------------- # CMake Function(s) and Macro(s) #----------------------------------------------------------------------------- set(CMAKE_MODULE_PATH ${MITK_SOURCE_DIR}/CMake ${CMAKE_MODULE_PATH} ) include(mitkFunctionCheckCompilerFlags) include(mitkFunctionGetGccVersion) include(mitkFunctionGetVersion) #----------------------------------------------------------------------------- # Set project specific options and variables (NOT available during superbuild) #----------------------------------------------------------------------------- set(${PROJECT_NAME}_VERSION_MAJOR "0") set(${PROJECT_NAME}_VERSION_MINOR "1") set(${PROJECT_NAME}_VERSION_PATCH "1") set(${PROJECT_NAME}_VERSION_STRING "${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH}") # Ask the user if a console window should be shown with the applications option(${PROJECT_NAME}_SHOW_CONSOLE_WINDOW "Use this to enable or disable the console window when starting GUI Applications" ON) mark_as_advanced(${PROJECT_NAME}_SHOW_CONSOLE_WINDOW) if(NOT UNIX AND NOT MINGW) set(MITK_WIN32_FORCE_STATIC "STATIC") endif() #----------------------------------------------------------------------------- # Get project version info #----------------------------------------------------------------------------- mitkFunctionGetVersion(${PROJECT_SOURCE_DIR} ${PROJECT_NAME}) #----------------------------------------------------------------------------- # Installation preparation # # These should be set before any MITK install macros are used #----------------------------------------------------------------------------- # on Mac OSX all CTK plugins get copied into every # application bundle (.app directory) specified here set(MACOSX_BUNDLE_NAMES) if(APPLE) list(APPEND MACOSX_BUNDLE_NAMES ${MY_APP_NAME}) 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) # The MITK module build system does not yet support default hidden visibility set(VISIBILITY_CXX_FLAGS ) # "-fvisibility=hidden -fvisibility-inlines-hidden") endif() #----------------------------------------------------------------------------- # Set coverage Flags #----------------------------------------------------------------------------- if(WITH_COVERAGE) if(CMAKE_COMPILER_IS_GNUCXX) set(coverage_flags "-g -fprofile-arcs -ftest-coverage -O0 -DNDEBUG") set(COVERAGE_CXX_FLAGS ${coverage_flags}) set(COVERAGE_C_FLAGS ${coverage_flags}) endif() endif() #----------------------------------------------------------------------------- # Project C/CXX Flags #----------------------------------------------------------------------------- set(${PROJECT_NAME}_C_FLAGS "${MITK_C_FLAGS} ${COVERAGE_C_FLAGS}") set(${PROJECT_NAME}_C_FLAGS_DEBUG ${MITK_C_FLAGS_DEBUG}) set(${PROJECT_NAME}_C_FLAGS_RELEASE ${MITK_C_FLAGS_RELEASE}) set(${PROJECT_NAME}_CXX_FLAGS "${MITK_CXX_FLAGS} ${VISIBILITY_CXX_FLAGS} ${COVERAGE_CXX_FLAGS}") set(${PROJECT_NAME}_CXX_FLAGS_DEBUG ${MITK_CXX_FLAGS_DEBUG}) set(${PROJECT_NAME}_CXX_FLAGS_RELEASE ${MITK_CXX_FLAGS_RELEASE}) set(${PROJECT_NAME}_EXE_LINKER_FLAGS ${MITK_EXE_LINKER_FLAGS}) set(${PROJECT_NAME}_SHARED_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS}) set(${PROJECT_NAME}_MODULE_LINKER_FLAGS ${MITK_MODULE_LINKER_FLAGS}) #----------------------------------------------------------------------------- # Set C/CXX Flags #----------------------------------------------------------------------------- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${${PROJECT_NAME}_C_FLAGS}") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${${PROJECT_NAME}_C_FLAGS_DEBUG}") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${${PROJECT_NAME}_C_FLAGS_RELEASE}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${${PROJECT_NAME}_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${${PROJECT_NAME}_CXX_FLAGS_DEBUG}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${${PROJECT_NAME}_CXX_FLAGS_RELEASE}") set(CMAKE_EXE_LINKER_FLAGS ${${PROJECT_NAME}_EXE_LINKER_FLAGS}) set(CMAKE_SHARED_LINKER_FLAGS ${${PROJECT_NAME}_SHARED_LINKER_FLAGS}) set(CMAKE_MODULE_LINKER_FLAGS ${${PROJECT_NAME}_MODULE_LINKER_FLAGS}) #----------------------------------------------------------------------------- # Testing #----------------------------------------------------------------------------- if(BUILD_TESTING) enable_testing() include(CTest) mark_as_advanced(TCL_TCLSH DART_ROOT) # Setup file for setting custom ctest vars configure_file( CMake/CTestCustom.cmake.in ${CMAKE_CURRENT_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; } ") endif() #----------------------------------------------------------------------------- # ${MY_PROJECT_NAME}_SUPERBUILD_BINARY_DIR #----------------------------------------------------------------------------- # If ${MY_PROJECT_NAME}_SUPERBUILD_BINARY_DIR isn't defined, it means this project is # *NOT* build using Superbuild. In that specific case, ${MY_PROJECT_NAME}_SUPERBUILD_BINARY_DIR # should default to PROJECT_BINARY_DIR if(NOT DEFINED ${PROJECT_NAME}_SUPERBUILD_BINARY_DIR) set(${PROJECT_NAME}_SUPERBUILD_BINARY_DIR ${PROJECT_BINARY_DIR}) endif() #----------------------------------------------------------------------------- # Qt support #----------------------------------------------------------------------------- -if(MITK_USE_QT) +if(MITK_USE_Qt4) set(QT_QMAKE_EXECUTABLE ${MITK_QMAKE_EXECUTABLE}) endif() #----------------------------------------------------------------------------- # MITK modules #----------------------------------------------------------------------------- #add_subdirectory(Modules) #----------------------------------------------------------------------------- # CTK plugins #----------------------------------------------------------------------------- # The CMake code in this section *must* be in the top-level CMakeLists.txt file macro(GetMyTargetLibraries all_target_libraries varname) set(re_ctkplugin "^$(project-plugin-base)_[a-zA-Z0-9_]+$") set(_tmp_list) list(APPEND _tmp_list ${all_target_libraries}) ctkMacroListFilter(_tmp_list re_ctkplugin OUTPUT_VARIABLE ${varname}) endmacro() include(${CMAKE_CURRENT_SOURCE_DIR}/Plugins/Plugins.cmake) ctkMacroSetupPlugins(${PROJECT_PLUGINS} BUILD_OPTION_PREFIX ${MY_PROJECT_NAME}_ BUILD_ALL ${${MY_PROJECT_NAME}_BUILD_ALL_PLUGINS}) #----------------------------------------------------------------------------- # Add subdirectories #----------------------------------------------------------------------------- add_subdirectory(Apps/$(project-app-name)) #----------------------------------------------------------------------------- # Installation #----------------------------------------------------------------------------- # set MITK cpack variables include(mitkSetupCPack) # Customize CPack variables for this project include(CPackSetup) list(APPEND CPACK_CREATE_DESKTOP_LINKS "${MY_APP_NAME}") configure_file(${MITK_SOURCE_DIR}/MITKCPackOptions.cmake.in ${PROJECT_BINARY_DIR}/${PROJECT_NAME}CPackOptions.cmake @ONLY) set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}CPackOptions.cmake") # include CPack model once all variables are set include(CPack) # Additional installation rules include(mitkInstallRules) #----------------------------------------------------------------------------- # Last configuration steps #----------------------------------------------------------------------------- # 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("${PROJECT_SOURCE_DIR}/CMake/StartVS.bat.in" ${PROJECT_BINARY_DIR}/StartVS_${VS_BUILD_TYPE}.bat ${VS_BUILD_TYPE}) endforeach() endif(WIN32) diff --git a/Applications/PluginGenerator/ProjectTemplate/SuperBuild.cmake b/Applications/PluginGenerator/ProjectTemplate/SuperBuild.cmake index 4d051a380a..b899e23bd3 100644 --- a/Applications/PluginGenerator/ProjectTemplate/SuperBuild.cmake +++ b/Applications/PluginGenerator/ProjectTemplate/SuperBuild.cmake @@ -1,221 +1,224 @@ #----------------------------------------------------------------------------- # ExternalProjects #----------------------------------------------------------------------------- set(external_projects MITK ) set(EXTERNAL_MITK_DIR "${MITK_DIR}" CACHE PATH "Path to MITK build directory") mark_as_advanced(EXTERNAL_MITK_DIR) if(EXTERNAL_MITK_DIR) set(MITK_DIR ${EXTERNAL_MITK_DIR}) endif() # Look for git early on, if needed if(NOT MITK_DIR AND MITK_USE_CTK AND NOT CTK_DIR) find_package(Git REQUIRED) endif() #----------------------------------------------------------------------------- # External project settings #----------------------------------------------------------------------------- include(ExternalProject) set(ep_base "${CMAKE_BINARY_DIR}/CMakeExternals") set_property(DIRECTORY PROPERTY EP_BASE ${ep_base}) set(ep_install_dir "${CMAKE_BINARY_DIR}/CMakeExternals/Install") set(ep_suffix "-cmake") set(ep_build_shared_libs ON) set(ep_build_testing OFF) # Compute -G arg for configuring external projects with the same CMake generator: if(CMAKE_EXTRA_GENERATOR) set(gen "${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}") else() set(gen "${CMAKE_GENERATOR}") endif() # Use this value where semi-colons are needed in ep_add args: set(sep "^^") ## if(MSVC_VERSION) set(ep_common_C_FLAGS "${CMAKE_C_FLAGS} /bigobj /MP") set(ep_common_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj /MP") endif() set(ep_common_args -DBUILD_TESTING:BOOL=${ep_build_testing} -DCMAKE_INSTALL_PREFIX:PATH=${ep_install_dir} + -DCMAKE_PREFIX_PATH:PATH=${CMAKE_PREFIX_PATH} + -DCMAKE_INCLUDE_PATH:PATH=${CMAKE_INCLUDE_PATH} + -DCMAKE_LIBRARY_PATH:PATH=${CMAKE_LIBRARY_PATH} -DBUILD_SHARED_LIBS:BOOL=${ep_build_shared_libs} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} -DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS} -DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS} # debug flags -DCMAKE_CXX_FLAGS_DEBUG:STRING=${CMAKE_CXX_FLAGS_DEBUG} -DCMAKE_C_FLAGS_DEBUG:STRING=${CMAKE_C_FLAGS_DEBUG} # release flags -DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE} -DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE} # relwithdebinfo -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DCMAKE_C_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_C_FLAGS_RELWITHDEBINFO} # link flags -DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_SHARED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_MODULE_LINKER_FLAGS} ) # Include external projects foreach(p ${external_projects}) include(CMakeExternals/${p}.cmake) endforeach() #----------------------------------------------------------------------------- # Set superbuild boolean args #----------------------------------------------------------------------------- set(my_cmake_boolean_args WITH_COVERAGE BUILD_TESTING ${MY_PROJECT_NAME}_BUILD_ALL_PLUGINS ) #----------------------------------------------------------------------------- # Create the final variable containing superbuild boolean args #----------------------------------------------------------------------------- set(my_superbuild_boolean_args) foreach(my_cmake_arg ${my_cmake_boolean_args}) list(APPEND my_superbuild_boolean_args -D${my_cmake_arg}:BOOL=${${my_cmake_arg}}) endforeach() #----------------------------------------------------------------------------- # Project Utilities #----------------------------------------------------------------------------- set(proj ${MY_PROJECT_NAME}-Utilities) ExternalProject_Add(${proj} DOWNLOAD_COMMAND "" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" DEPENDS # Mandatory dependencies ${MITK_DEPENDS} # Optional dependencies ) #----------------------------------------------------------------------------- # Additional Project CXX/C Flags #----------------------------------------------------------------------------- set(${MY_PROJECT_NAME}_ADDITIONAL_C_FLAGS "" CACHE STRING "Additional C Flags for ${MY_PROJECT_NAME}") set(${MY_PROJECT_NAME}_ADDITIONAL_C_FLAGS_RELEASE "" CACHE STRING "Additional Release C Flags for ${MY_PROJECT_NAME}") set(${MY_PROJECT_NAME}_ADDITIONAL_C_FLAGS_DEBUG "" CACHE STRING "Additional Debug C Flags for ${MY_PROJECT_NAME}") mark_as_advanced(${MY_PROJECT_NAME}_ADDITIONAL_C_FLAGS ${MY_PROJECT_NAME}_ADDITIONAL_C_FLAGS_DEBUG ${MY_PROJECT_NAME}_ADDITIONAL_C_FLAGS_RELEASE) set(${MY_PROJECT_NAME}_ADDITIONAL_CXX_FLAGS "" CACHE STRING "Additional CXX Flags for ${MY_PROJECT_NAME}") set(${MY_PROJECT_NAME}_ADDITIONAL_CXX_FLAGS_RELEASE "" CACHE STRING "Additional Release CXX Flags for ${MY_PROJECT_NAME}") set(${MY_PROJECT_NAME}_ADDITIONAL_CXX_FLAGS_DEBUG "" CACHE STRING "Additional Debug CXX Flags for ${MY_PROJECT_NAME}") mark_as_advanced(${MY_PROJECT_NAME}_ADDITIONAL_CXX_FLAGS ${MY_PROJECT_NAME}_ADDITIONAL_CXX_FLAGS_DEBUG ${MY_PROJECT_NAME}_ADDITIONAL_CXX_FLAGS_RELEASE) set(${MY_PROJECT_NAME}_ADDITIONAL_EXE_LINKER_FLAGS "" CACHE STRING "Additional exe linker flags for ${MY_PROJECT_NAME}") set(${MY_PROJECT_NAME}_ADDITIONAL_SHARED_LINKER_FLAGS "" CACHE STRING "Additional shared linker flags for ${MY_PROJECT_NAME}") set(${MY_PROJECT_NAME}_ADDITIONAL_MODULE_LINKER_FLAGS "" CACHE STRING "Additional module linker flags for ${MY_PROJECT_NAME}") mark_as_advanced(${MY_PROJECT_NAME}_ADDITIONAL_EXE_LINKER_FLAGS ${MY_PROJECT_NAME}_ADDITIONAL_SHARED_LINKER_FLAGS ${MY_PROJECT_NAME}_ADDITIONAL_MODULE_LINKER_FLAGS) #----------------------------------------------------------------------------- # Project Configure #----------------------------------------------------------------------------- set(proj ${MY_PROJECT_NAME}-Configure) ExternalProject_Add(${proj} DOWNLOAD_COMMAND "" CMAKE_GENERATOR ${gen} CMAKE_CACHE_ARGS # --------------- Build options ---------------- -DBUILD_TESTING:BOOL=${ep_build_testing} -DCMAKE_INSTALL_PREFIX:PATH=${ep_install_dir} -DBUILD_SHARED_LIBS:BOOL=${ep_build_shared_libs} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} # --------------- Compile options ---------------- -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS} ${${MY_PROJECT_NAME}_ADDITIONAL_C_FLAGS}" "-DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS} ${${MY_PROJECT_NAME}_ADDITIONAL_CXX_FLAGS}" # debug flags "-DCMAKE_CXX_FLAGS_DEBUG:STRING=${CMAKE_CXX_FLAGS_DEBUG} ${${MY_PROJECT_NAME}_ADDITIONAL_CXX_FLAGS_DEBUG}" "-DCMAKE_C_FLAGS_DEBUG:STRING=${CMAKE_C_FLAGS_DEBUG} ${${MY_PROJECT_NAME}_ADDITIONAL_C_FLAGS_DEBUG}" # release flags "-DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE} ${${MY_PROJECT_NAME}_ADDITIONAL_CXX_FLAGS_RELEASE}" "-DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE} ${${MY_PROJECT_NAME}_ADDITIONAL_C_FLAGS_RELEASE}" # relwithdebinfo -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DCMAKE_C_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_C_FLAGS_RELWITHDEBINFO} # link flags "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS} ${${MY_PROJECT_NAME}_ADDITIONAL_EXE_LINKER_FLAGS}" "-DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_SHARED_LINKER_FLAGS} ${${MY_PROJECT_NAME}_ADDITIONAL_SHARED_LINKER_FLAGS}" "-DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_MODULE_LINKER_FLAGS} ${${MY_PROJECT_NAME}_ADDITIONAL_MODULE_LINKER_FLAGS}" # ------------- Boolean build options -------------- ${my_superbuild_boolean_args} -D${MY_PROJECT_NAME}_USE_SUPERBUILD:BOOL=OFF -D${MY_PROJECT_NAME}_CONFIGURED_VIA_SUPERBUILD:BOOL=ON -DCTEST_USE_LAUNCHERS:BOOL=${CTEST_USE_LAUNCHERS} # ----------------- Miscellaneous --------------- -D${MY_PROJECT_NAME}_SUPERBUILD_BINARY_DIR:PATH=${PROJECT_BINARY_DIR} -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} -DCMAKE_PREFIX_PATH:PATH=${CMAKE_PREFIX_PATH} -DMITK_DIR:PATH=${MITK_DIR} -DITK_DIR:PATH=${ITK_DIR} -DVTK_DIR:PATH=${VTK_DIR} SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} BINARY_DIR ${CMAKE_BINARY_DIR}/${MY_PROJECT_NAME}-build BUILD_COMMAND "" INSTALL_COMMAND "" DEPENDS ${MY_PROJECT_NAME}-Utilities ) #----------------------------------------------------------------------------- # Project #----------------------------------------------------------------------------- if(CMAKE_GENERATOR MATCHES ".*Makefiles.*") set(_build_cmd "$(MAKE)") else() set(_build_cmd ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/${MY_PROJECT_NAME}-build --config ${CMAKE_CFG_INTDIR}) endif() # The variable SUPERBUILD_EXCLUDE_${MY_PROJECT_NAME}BUILD_TARGET should be set when submitting to a dashboard if(NOT DEFINED SUPERBUILD_EXCLUDE_${MY_PROJECT_NAME}BUILD_TARGET OR NOT SUPERBUILD_EXCLUDE_${MY_PROJECT_NAME}BUILD_TARGET) set(_target_all_option "ALL") else() set(_target_all_option "") endif() add_custom_target(${MY_PROJECT_NAME}-build ${_target_all_option} COMMAND ${_build_cmd} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${MY_PROJECT_NAME}-build DEPENDS ${MY_PROJECT_NAME}-Configure ) #----------------------------------------------------------------------------- # Custom target allowing to drive the build of the project itself #----------------------------------------------------------------------------- add_custom_target(${MY_PROJECT_NAME} COMMAND ${_build_cmd} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${MY_PROJECT_NAME}-build ) diff --git a/BlueBerry/Bundles/org.blueberry.ui.qt.help/src/internal/berryHelpContentView.cpp b/BlueBerry/Bundles/org.blueberry.ui.qt.help/src/internal/berryHelpContentView.cpp index a99decf635..e994b41c17 100644 --- a/BlueBerry/Bundles/org.blueberry.ui.qt.help/src/internal/berryHelpContentView.cpp +++ b/BlueBerry/Bundles/org.blueberry.ui.qt.help/src/internal/berryHelpContentView.cpp @@ -1,224 +1,226 @@ /*=================================================================== BlueBerry Platform Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifdef __MINGW32__ // We need to inlclude winbase.h here in order to declare // atomic intrinsics like InterlockedIncrement correctly. // Otherwhise, they would be declared wrong within qatomic_windows.h . #include #endif #include "berryHelpContentView.h" #include "berryHelpPluginActivator.h" #include "berryHelpEditor.h" #include "berryHelpEditorInput.h" #include "berryHelpWebView.h" #include "berryQHelpEngineWrapper.h" #include #include #include #include #include #include #include namespace berry { HelpContentWidget::HelpContentWidget() : QTreeView(0) , m_SortModel(new QSortFilterProxyModel(this)) , m_SourceModel(0) { header()->hide(); setUniformRowHeights(true); connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(showLink(QModelIndex))); + connect(this, SIGNAL(clicked(QModelIndex)), + this, SLOT(showLink(QModelIndex))); m_SortModel->setDynamicSortFilter(true); QTreeView::setModel(m_SortModel); } QModelIndex HelpContentWidget::indexOf(const QUrl &link) { QHelpContentModel *contentModel = qobject_cast(m_SourceModel); if (!contentModel || link.scheme() != QLatin1String("qthelp")) return QModelIndex(); m_syncIndex = QModelIndex(); for (int i=0; irowCount(); ++i) { QHelpContentItem *itm = contentModel->contentItemAt(contentModel->index(i, 0)); if (itm && itm->url().host() == link.host()) { QString path = link.path(); if (path.startsWith(QLatin1Char('/'))) path = path.mid(1); if (searchContentItem(contentModel, contentModel->index(i, 0), path)) { return m_syncIndex; } } } return QModelIndex(); } void HelpContentWidget::setModel(QAbstractItemModel *model) { m_SourceModel = model; m_SortModel->setSourceModel(model); } bool HelpContentWidget::searchContentItem(QHelpContentModel *model, const QModelIndex &parent, const QString &path) { QHelpContentItem *parentItem = model->contentItemAt(parent); if (!parentItem) return false; if (QDir::cleanPath(parentItem->url().path()) == path) { m_syncIndex = m_SortModel->mapFromSource(parent); return true; } for (int i=0; ichildCount(); ++i) { if (searchContentItem(model, model->index(i, 0, parent), path)) return true; } return false; } QUrl HelpContentWidget::GetUrl(const QModelIndex &index) { QHelpContentModel *contentModel = qobject_cast(m_SourceModel); if (!contentModel) return QUrl(); QHelpContentItem *item = contentModel->contentItemAt(m_SortModel->mapToSource(index)); if (!item) return QUrl(); QUrl url = item->url(); if (url.isValid()) return url; return QUrl(); } void HelpContentWidget::showLink(const QModelIndex &index) { QHelpContentModel *contentModel = qobject_cast(m_SourceModel); if (!contentModel) return; QHelpContentItem *item = contentModel->contentItemAt(m_SortModel->mapToSource(index)); if (!item) return; QUrl url = item->url(); if (url.isValid()) emit linkActivated(url); } HelpContentView::HelpContentView() : m_ContentWidget(0) { } HelpContentView::~HelpContentView() { } void HelpContentView::CreateQtPartControl(QWidget* parent) { if (m_ContentWidget == 0) { QVBoxLayout* verticalLayout = new QVBoxLayout(parent); verticalLayout->setSpacing(0); verticalLayout->setContentsMargins(0, 0, 0, 0); QHelpEngineWrapper& helpEngine = HelpPluginActivator::getInstance()->getQHelpEngine(); m_ContentWidget = new HelpContentWidget(); m_ContentWidget->setModel(helpEngine.contentModel()); m_ContentWidget->sortByColumn(0, Qt::AscendingOrder); connect(helpEngine.contentModel(), SIGNAL(contentsCreationStarted()), this, SLOT(setContentsWidgetBusy())); connect(helpEngine.contentModel(), SIGNAL(contentsCreated()), this, SLOT(unsetContentsWidgetBusy())); verticalLayout->addWidget(m_ContentWidget); m_ContentWidget->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_ContentWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); connect(m_ContentWidget, SIGNAL(linkActivated(QUrl)), this, SLOT(linkActivated(QUrl))); } } void HelpContentView::linkActivated(const QUrl &link) { IWorkbenchPage::Pointer page = this->GetSite()->GetPage(); HelpPluginActivator::linkActivated(page, link); } void HelpContentView::showContextMenu(const QPoint &pos) { if (!m_ContentWidget->indexAt(pos).isValid()) return; QModelIndex index = m_ContentWidget->indexAt(pos); QUrl url = m_ContentWidget->GetUrl(index); QMenu menu; QAction *curTab = menu.addAction(tr("Open Link")); QAction *newTab = menu.addAction(tr("Open Link in New Tab")); if (!HelpWebView::canOpenPage(url.path())) newTab->setEnabled(false); menu.move(m_ContentWidget->mapToGlobal(pos)); QAction *action = menu.exec(); if (curTab == action) { linkActivated(url); } else if (newTab == action) { IEditorInput::Pointer input(new HelpEditorInput(url)); this->GetSite()->GetPage()->OpenEditor(input, HelpEditor::EDITOR_ID); } } void HelpContentView::SetFocus() { m_ContentWidget->setFocus(); } void HelpContentView::setContentsWidgetBusy() { m_ContentWidget->setCursor(Qt::WaitCursor); } void HelpContentView::unsetContentsWidgetBusy() { m_ContentWidget->unsetCursor(); } } diff --git a/CMake/BuildConfigurations/mitkNavigationModules.cmake b/CMake/BuildConfigurations/mitkNavigationModules.cmake new file mode 100644 index 0000000000..33a1e44067 --- /dev/null +++ b/CMake/BuildConfigurations/mitkNavigationModules.cmake @@ -0,0 +1,37 @@ +message(STATUS "Configuring MITK Navigation Modules Build") + +set(MITK_CONFIG_PACKAGES + ACVD + QT + BLUEBERRY +) + +# Enable open cv and open igt link, which is a necessary configuration +set(MITK_USE_OpenCV ON CACHE BOOL "MITK Use OpenCV Library" FORCE) +set(MITK_USE_OpenIGTLink ON CACHE BOOL "MITK Use OpenIGTLink Library" FORCE) + +# Enable default plugins and the navigation modules +set(MITK_CONFIG_PLUGINS + org.mitk.gui.qt.datamanager + org.mitk.gui.qt.stdmultiwidgeteditor + org.mitk.gui.qt.dicom + org.mitk.gui.qt.imagenavigator + org.mitk.gui.qt.measurementtoolbox + org.mitk.gui.qt.properties + org.mitk.gui.qt.segmentation + org.mitk.gui.qt.volumevisualization + org.mitk.planarfigure + org.mitk.gui.qt.moviemaker + org.mitk.gui.qt.pointsetinteraction + org.mitk.gui.qt.registration + org.mitk.gui.qt.remeshing + org.mitk.gui.qt.viewnavigator + org.mitk.gui.qt.imagecropper + org.mitk.gui.qt.igtexamples + org.mitk.gui.qt.igttracking + org.mitk.gui.qt.igtlplugin + org.mitk.gui.qt.ultrasound + org.mitk.gui.qt.toftutorial + org.mitk.gui.qt.tofutil +) + diff --git a/CMake/MITKDashboardScript.TEMPLATE.cmake b/CMake/MITKDashboardScript.TEMPLATE.cmake index 41b6f78fe2..7b4f05bf7a 100644 --- a/CMake/MITKDashboardScript.TEMPLATE.cmake +++ b/CMake/MITKDashboardScript.TEMPLATE.cmake @@ -1,145 +1,148 @@ # # OS: Ubuntu 9.04 2.6.28-18-generic # Hardware: x86_64 GNU/Linux # GPU: NA # # Note: The specific version and processor type of this machine should be reported in the # header above. Indeed, this file will be send to the dashboard as a NOTE file. cmake_minimum_required(VERSION 3.1 FATAL_ERROR) # # Dashboard properties # -set(MY_COMPILER "gcc-4.4.5") +set(MY_COMPILER "gcc-4.8.x") # For Windows, e.g. #set(MY_COMPILER "VC9.0") set(CTEST_CMAKE_COMMAND "/usr/bin/cmake") set(CTEST_CMAKE_GENERATOR "Unix Makefiles") set(CTEST_DASHBOARD_ROOT "/opt/dartclients") # For Windows, e.g. #set(CTEST_CMAKE_COMMAND "cmake") -#set(CTEST_CMAKE_GENERATOR "Visual Studio 9 2008 Win64") +#set(CTEST_CMAKE_GENERATOR "Visual Studio 12 2013 Win64") #set(CTEST_DASHBOARD_ROOT "C:/dartclients") # The directory containing the Qt binaries -set(QT_BINARY_DIR "/usr/bin/") +set(QT5_INSTALL_PREFIX "/home/user/Qt/5.4/gcc_64") +set(QT_BINARY_DIR "${QT5_INSTALL_PREFIX}/bin") # For Windows, e.g. -#set(QT_BINARY_DIR "V:/windows/x64/QT-4.7.0_VC9.0_Bin/bin") +#set(QT_BINARY_DIR "C:/Qt/5.4/msvc2013_64_opengl/bin") # # Dashboard options # set(WITH_KWSTYLE FALSE) set(WITH_MEMCHECK FALSE) set(WITH_COVERAGE FALSE) set(WITH_DOCUMENTATION FALSE) #set(DOCUMENTATION_ARCHIVES_OUTPUT_DIRECTORY ) # for example: $ENV{HOME}/Projects/Doxygen set(CTEST_BUILD_CONFIGURATION "Release") set(CTEST_TEST_TIMEOUT 500) if(UNIX OR MINGW) set(CTEST_BUILD_FLAGS "-j4") # Use multiple CPU cores to build else() set(CTEST_BUILD_FLAGS "") endif() # experimental: # - run_ctest() macro will be called *ONE* time # - binary directory will *NOT* be cleaned # continuous: # - run_ctest() macro will be called EVERY 5 minutes ... # - binary directory will *NOT* be cleaned # - configure/build will be executed *ONLY* if the repository has been updated # nightly: # - run_ctest() macro will be called *ONE* time # - binary directory *WILL BE* cleaned set(SCRIPT_MODE "experimental") # "experimental", "continuous", "nightly" # # Project specific properties # # In order to shorten the global path length, the build directory for each DartClient # uses the following abrevation sceme: # For build configuration: # Debug -> d # Release -> r # For scripte mode: # continuous -> c # nightly -> n # experimental -> e # Example directory: /MITK-sb-d-n/ for a nightly MITK superbuild in debug mode. set(short_of_ctest_build_configuration "") set(short_of_script_mode "") string(SUBSTRING ${CTEST_BUILD_CONFIGURATION} 0 1 short_of_ctest_build_configuration) string(SUBSTRING ${SCRIPT_MODE} 0 1 short_of_script_mode) set(CTEST_SOURCE_DIRECTORY "${CTEST_DASHBOARD_ROOT}/MITK") set(CTEST_BINARY_DIRECTORY "${CTEST_DASHBOARD_ROOT}/MITK-sb-${short_of_ctest_build_configuration}-${short_of_script_mode}") # Create an initial cache file for MITK. This file is used to configure the MITK-Build. Use ADDITIONAL_CMAKECACHE_OPTION # to configure the MITK-Superbuild. The set(MITK_INITIAL_CACHE " # Example how to set a boolean variable in the MITK-Build via this script: #SET(MITK_ENABLE_TOF_HARDWARE \"TRUE\" CACHE INTERNAL \"Enable ToF Hardware\") # Example how to set a path variable in the MITK-Build via this script: #SET(MITK_PMD_LIB \"/home/kilgus/thomas/PMDSDK2/Linux_x86_64/bin/libpmdaccess2.so\" CACHE INTERNAL \"PMD lib\") ") set(ADDITIONAL_CMAKECACHE_OPTION " # Superbuild variables are not passed through to the MITK-Build (or any other build like ITK, VTK, ...) # Use the MITK_INITIAL_CACHE the pass variables to the MITK-Build. # add entries like this #MITK_USE_OpenCV:BOOL=OFF +CMAKE_PREFIX_PATH:PATH=${QT5_INSTALL_PREFIX} +DESIRED_QT_VERSION:STRING=5 ") # List of test that should be explicitly disabled on this machine set(TEST_TO_EXCLUDE_REGEX "") # set any extra environment variables here set(ENV{DISPLAY} ":0") find_program(CTEST_COVERAGE_COMMAND NAMES gcov) find_program(CTEST_MEMORYCHECK_COMMAND NAMES valgrind) find_program(CTEST_GIT_COMMAND NAMES git) # # Git repository - Overwrite the default value provided by the driver script # # The git repository containing MITK code #set(GIT_REPOSITORY "/home/username/MITK") # The branch of the MITK git repository to check out #set(GIT_BRANCH "bug-xxx-label") ########################################## # WARNING: DO NOT EDIT BEYOND THIS POINT # ########################################## # # Convenient macro allowing to download a file # macro(downloadFile url dest) file(DOWNLOAD "${url}" "${dest}" STATUS status) list(GET status 0 error_code) list(GET status 1 error_msg) if(error_code) message(FATAL_ERROR "error: Failed to download ${url} - ${error_msg}") endif() endmacro() # # Download and include setup script # if(NOT DEFINED GIT_BRANCH OR GIT_BRANCH STREQUAL "") set(hb "HEAD") else() string(REGEX REPLACE "^origin/(.*)$" "\\1" _branch_name ${GIT_BRANCH}) set(hb "refs/heads/${_branch_name}") endif() set(url "http://mitk.org/git/?p=MITK.git;a=blob_plain;f=CMake/MITKDashboardSetup.cmake;hb=${hb}") set(dest ${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}.setup) downloadFile("${url}" "${dest}") include(${dest}) diff --git a/CMake/MITKDashboardSetup.cmake b/CMake/MITKDashboardSetup.cmake index 9bd8dca8b8..730833cfe8 100644 --- a/CMake/MITKDashboardSetup.cmake +++ b/CMake/MITKDashboardSetup.cmake @@ -1,155 +1,156 @@ # This file is intended to be included at the end of a custom MITKDashboardScript.TEMPLATE.cmake file list(APPEND CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") # # Automatically determined properties # set(MY_OPERATING_SYSTEM ) if(UNIX) # Download a utility script set(url "http://mitk.org/git/?p=MITK.git;a=blob_plain;f=CMake/mitkDetectOS.sh;hb=${hb}") set(dest "${CTEST_SCRIPT_DIRECTORY}/mitkDetectOS.sh") downloadFile("${url}" "${dest}") execute_process(COMMAND sh "${dest}" RESULT_VARIABLE _result OUTPUT_VARIABLE _out OUTPUT_STRIP_TRAILING_WHITESPACE) if(NOT _result) set(MY_OPERATING_SYSTEM "${_out}") endif() endif() if(NOT MY_OPERATING_SYSTEM) set(MY_OPERATING_SYSTEM "${CMAKE_HOST_SYSTEM}") # Windows 7, Linux-2.6.32, Darwin... endif() site_name(CTEST_SITE) if(NOT DEFINED MITK_USE_QT) set(MITK_USE_QT 1) endif() if(MITK_USE_QT) if(NOT QT_QMAKE_EXECUTABLE) find_program(QT_QMAKE_EXECUTABLE NAMES qmake qmake-qt4 HINTS ${QT_BINARY_DIR}) endif() execute_process(COMMAND ${QT_QMAKE_EXECUTABLE} --version OUTPUT_VARIABLE MY_QT_VERSION RESULT_VARIABLE qmake_error) if(qmake_error) message(FATAL_ERROR "Error when executing ${QT_QMAKE_EXECUTABLE} --version\n${qmake_error}") endif() string(REGEX REPLACE ".*Qt version ([0-9.]+) .*" "\\1" MY_QT_VERSION ${MY_QT_VERSION}) endif() # # Project specific properties # if(NOT CTEST_BUILD_NAME) if(MITK_USE_QT) set(CTEST_BUILD_NAME "${MY_OPERATING_SYSTEM} ${MY_COMPILER} Qt${MY_QT_VERSION} ${CTEST_BUILD_CONFIGURATION}") else() set(CTEST_BUILD_NAME "${MY_OPERATING_SYSTEM} ${MY_COMPILER} ${CTEST_BUILD_CONFIGURATION}") endif() set(CTEST_BUILD_NAME "${CTEST_BUILD_NAME}${CTEST_BUILD_NAME_SUFFIX}") endif() set(PROJECT_BUILD_DIR "MITK-build") set(CTEST_PATH "$ENV{PATH}") if(WIN32) set(ANN_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/ANN-build/${CTEST_BUILD_CONFIGURATION}") set(CPPUNIT_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/CppUnit-build/${CTEST_BUILD_CONFIGURATION}") set(GLUT_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/GLUT-build/${CTEST_BUILD_CONFIGURATION}") set(GLEW_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/GLEW-build/${CTEST_BUILD_CONFIGURATION}") set(TINYXML_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/tinyxml-build/${CTEST_BUILD_CONFIGURATION}") set(QWT_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/Qwt-build/${CTEST_BUILD_CONFIGURATION}") set(VTK_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/VTK-build/bin/${CTEST_BUILD_CONFIGURATION}") set(ACVD_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/ACVD-build/bin/${CTEST_BUILD_CONFIGURATION}") set(ITK_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/ITK-build/bin/${CTEST_BUILD_CONFIGURATION}") set(BOOST_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/Boost-install/lib") set(GDCM_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/GDCM-build/bin/${CTEST_BUILD_CONFIGURATION}") set(DCMTK_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/DCMTK-install/bin/${CTEST_BUILD_CONFIGURATION}") set(OPENCV_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/OpenCV-build/bin/${CTEST_BUILD_CONFIGURATION}") set(POCO_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/Poco-install/bin") set(SOFA_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/SOFA-build/bin/${CTEST_BUILD_CONFIGURATION}") set(REDLAND_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/Redland-install/bin") set(BLUEBERRY_OSGI_DIR "${CTEST_BINARY_DIRECTORY}/MITK-build/bin/BlueBerry/org.blueberry.osgi/bin/${CTEST_BUILD_CONFIGURATION}") - set(CTEST_PATH "${CTEST_PATH};${CPPUNIT_BINARY_DIR};${QT_BINARY_DIR};${VTK_BINARY_DIR};${ANN_BINARY_DIR};${GLUT_BINARY_DIR};${GLEW_BINARY_DIR};${TINYXML_BINARY_DIR};${QWT_BINARY_DIR};${ACVD_BINARY_DIR};${ITK_BINARY_DIR};${BOOST_BINARY_DIR};${GDCM_BINARY_DIR};${DCMTK_BINARY_DIR};${OPENCV_BINARY_DIR};${POCO_BINARY_DIR};${SOFA_BINARY_DIR};${REDLAND_BINARY_DIR};${BLUEBERRY_OSGI_DIR}") + set(OpenIGTLink_DIR "${CTEST_BINARY_DIRECTORY}/OpenIGTLink-build/bin") + set(CTEST_PATH "${CTEST_PATH};${CPPUNIT_BINARY_DIR};${QT_BINARY_DIR};${VTK_BINARY_DIR};${ANN_BINARY_DIR};${GLUT_BINARY_DIR};${GLEW_BINARY_DIR};${TINYXML_BINARY_DIR};${QWT_BINARY_DIR};${ACVD_BINARY_DIR};${ITK_BINARY_DIR};${BOOST_BINARY_DIR};${GDCM_BINARY_DIR};${DCMTK_BINARY_DIR};${OPENCV_BINARY_DIR};${POCO_BINARY_DIR};${SOFA_BINARY_DIR};${REDLAND_BINARY_DIR};${BLUEBERRY_OSGI_DIR};${OpenIGTLink_DIR}") endif() set(ENV{PATH} "${CTEST_PATH}") set(SUPERBUILD_TARGETS "") # If the dashscript doesn't define a GIT_REPOSITORY variable, let's define it here. if(NOT DEFINED GIT_REPOSITORY OR GIT_REPOSITORY STREQUAL "") set(GIT_REPOSITORY "http://git.mitk.org/MITK.git") endif() # # Display build info # message("Site name: ${CTEST_SITE}") message("Build name: ${CTEST_BUILD_NAME}") message("Script Mode: ${SCRIPT_MODE}") message("Coverage: ${WITH_COVERAGE}, MemCheck: ${WITH_MEMCHECK}") # # Set initial cache options # if(${CMAKE_VERSION} VERSION_GREATER "2.8.9") set(CTEST_USE_LAUNCHERS 1) set(ENV{CTEST_USE_LAUNCHERS_DEFAULT} 1) endif() # Remove this if block after all dartclients work if(DEFINED ADDITIONNAL_CMAKECACHE_OPTION) message(WARNING "Rename ADDITIONNAL to ADDITIONAL in your dartlclient script: ${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") set(ADDITIONAL_CMAKECACHE_OPTION ${ADDITIONNAL_CMAKECACHE_OPTION}) endif() if(NOT DEFINED MITK_BUILD_CONFIGURATION) set(MITK_BUILD_CONFIGURATION "All") endif() if(NOT DEFINED MITK_VTK_DEBUG_LEAKS) set(MITK_VTK_DEBUG_LEAKS 1) endif() set(INITIAL_CMAKECACHE_OPTIONS " SUPERBUILD_EXCLUDE_MITKBUILD_TARGET:BOOL=TRUE MITK_BUILD_CONFIGURATION:STRING=${MITK_BUILD_CONFIGURATION} MITK_VTK_DEBUG_LEAKS:BOOL=${MITK_VTK_DEBUG_LEAKS} ${ADDITIONAL_CMAKECACHE_OPTION} ") if(MITK_USE_QT) set(INITIAL_CMAKECACHE_OPTIONS "${INITIAL_CMAKECACHE_OPTIONS} QT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}") endif() # Write a cache file for populating the MITK initial cache (not the superbuild cache). # This can be used to provide variables which are not passed through the # superbuild process to the MITK configure step) if(MITK_INITIAL_CACHE) set(mitk_cache_file "${CTEST_SCRIPT_DIRECTORY}/mitk_initial_cache.txt") file(WRITE "${mitk_cache_file}" "${MITK_INITIAL_CACHE}") set(INITIAL_CMAKECACHE_OPTIONS "${INITIAL_CMAKECACHE_OPTIONS} MITK_INITIAL_CACHE_FILE:INTERNAL=${mitk_cache_file} ") endif() # # Download and include dashboard driver script # set(url "http://mitk.org/git/?p=MITK.git;a=blob_plain;f=CMake/MITKDashboardDriverScript.cmake;hb=${hb}") set(dest ${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}.driver) downloadFile("${url}" "${dest}") include(${dest}) diff --git a/CMake/PackageDepends/MITK_OpenIGTLink_Config.cmake b/CMake/PackageDepends/MITK_OpenIGTLink_Config.cmake new file mode 100644 index 0000000000..3aafcb0b1d --- /dev/null +++ b/CMake/PackageDepends/MITK_OpenIGTLink_Config.cmake @@ -0,0 +1,7 @@ + +find_package(OpenIGTLink REQUIRED) + +include(${OpenIGTLink_USE_FILE}) + +list(APPEND ALL_LIBRARIES ${OpenIGTLink_LIBRARIES}) +#list(APPEND ALL_INCLUDE_DIRECTORIES ${OpenIGTLink_INCLUDE_DIRS}) diff --git a/CMake/mitkFunctionGetLibrarySearchPaths.cmake b/CMake/mitkFunctionGetLibrarySearchPaths.cmake index 672a2d5509..576f58f593 100644 --- a/CMake/mitkFunctionGetLibrarySearchPaths.cmake +++ b/CMake/mitkFunctionGetLibrarySearchPaths.cmake @@ -1,121 +1,127 @@ function(mitkFunctionGetLibrarySearchPaths search_path intermediate_dir) set(_dir_candidates "${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}" "${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}/plugins" "${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY}" "${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugins" ) if(MITK_EXTERNAL_PROJECT_PREFIX) list(APPEND _dir_candidates "${MITK_EXTERNAL_PROJECT_PREFIX}/bin" "${MITK_EXTERNAL_PROJECT_PREFIX}/lib" ) endif() # Determine the Qt4/5 library installation prefix set(_qmake_location ) if(MITK_USE_Qt4) set(_qmake_location ${QT_QMAKE_EXECUTABLE}) elseif(MITK_USE_Qt5 AND TARGET ${Qt5Core_QMAKE_EXECUTABLE}) get_property(_qmake_location TARGET ${Qt5Core_QMAKE_EXECUTABLE} PROPERTY IMPORT_LOCATION) endif() if(_qmake_location) if(NOT _qt_install_libs) if(WIN32) execute_process(COMMAND ${_qmake_location} -query QT_INSTALL_BINS OUTPUT_VARIABLE _qt_install_libs OUTPUT_STRIP_TRAILING_WHITESPACE) else() execute_process(COMMAND ${_qmake_location} -query QT_INSTALL_LIBS OUTPUT_VARIABLE _qt_install_libs OUTPUT_STRIP_TRAILING_WHITESPACE) endif() file(TO_CMAKE_PATH "${_qt_install_libs}" _qt_install_libs) set(_qt_install_libs ${_qt_install_libs} CACHE INTERNAL "Qt library installation prefix" FORCE) endif() if(_qt_install_libs) list(APPEND _dir_candidates ${_qt_install_libs}) endif() elseif(MITK_USE_QT) message(WARNING "The qmake executable could not be found.") endif() get_property(_additional_paths GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS) if(_additional_paths) list(APPEND _dir_candidates ${_additional_paths}) endif() # The code below is sub-optimal. It makes assumptions about # the structure of the build directories, pointed to by # the *_DIR variables. Instead, we should rely on package # specific "LIBRARY_DIRS" variables, if they exist. if(WIN32) if(SOFA_DIR) list(APPEND _dir_candidates "${SOFA_DIR}/bin") endif() + if(OpenIGTLink_DIR) + list(APPEND _dir_candidates "${OpenIGTLink_DIR}/bin") + endif() else() if(SOFA_DIR) list(APPEND _dir_candidates "${SOFA_DIR}/lib") endif() + if(OpenIGTLink_DIR) + list(APPEND _dir_candidates "${OpenIGTLink_DIR}/lib") + endif() endif() if(MITK_USE_Python AND CTK_PYTHONQT_INSTALL_DIR) list(APPEND _dir_candidates "${CTK_PYTHONQT_INSTALL_DIR}/bin") endif() if(MITK_USE_TOF_PMDO3 OR MITK_USE_TOF_PMDCAMCUBE OR MITK_USE_TOF_PMDCAMBOARD) list(APPEND _dir_candidates "${MITK_PMD_SDK_DIR}/plugins" "${MITK_PMD_SDK_DIR}/bin") endif() if(MITK_USE_CTK) list(APPEND _dir_candidates "${CTK_LIBRARY_DIRS}") foreach(_ctk_library ${CTK_LIBRARIES}) if(${_ctk_library}_LIBRARY_DIRS) list(APPEND _dir_candidates "${${_ctk_library}_LIBRARY_DIRS}") endif() endforeach() endif() if(MITK_USE_BLUEBERRY) if(DEFINED CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY) if(IS_ABSOLUTE "${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") list(APPEND _dir_candidates "${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") else() list(APPEND _dir_candidates "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") endif() endif() endif() if(MITK_LIBRARY_DIRS) list(APPEND _dir_candidates ${MITK_LIBRARY_DIRS}) endif() list(REMOVE_DUPLICATES _dir_candidates) set(_search_dirs ) foreach(_dir ${_dir_candidates}) if(EXISTS "${_dir}/${intermediate_dir}") list(APPEND _search_dirs "${_dir}/${intermediate_dir}") else() list(APPEND _search_dirs "${_dir}") endif() endforeach() # Special handling for "internal" search dirs. The intermediate directory # might not have been created yet, so we can't check for its existence. # Hence we just add it for Windows without checking. set(_internal_search_dirs "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/plugins") if(WIN32) foreach(_dir ${_internal_search_dirs}) set(_search_dirs "${_dir}/${intermediate_dir}" ${_search_dirs}) endforeach() else() set(_search_dirs ${_internal_search_dirs} ${_search_dirs}) endif() list(REMOVE_DUPLICATES _search_dirs) set(${search_path} ${_search_dirs} PARENT_SCOPE) endfunction() diff --git a/CMakeExternals/MITKData.cmake b/CMakeExternals/MITKData.cmake index fc6fe88212..6f2c3f96d8 100644 --- a/CMakeExternals/MITKData.cmake +++ b/CMakeExternals/MITKData.cmake @@ -1,37 +1,37 @@ #----------------------------------------------------------------------------- # MITK Data #----------------------------------------------------------------------------- # Sanity checks if(DEFINED MITK_DATA_DIR AND NOT EXISTS ${MITK_DATA_DIR}) message(FATAL_ERROR "MITK_DATA_DIR variable is defined but corresponds to non-existing directory") endif() set(proj MITK-Data) set(proj_DEPENDENCIES) set(MITK-Data_DEPENDS ${proj}) if(BUILD_TESTING) - set(revision_tag 7a7d873f) # first 8 characters of hash-tag + set(revision_tag 569c8296) # first 8 characters of hash-tag # ^^^^^^^^ these are just to check correct length of hash part ExternalProject_Add(${proj} SOURCE_DIR ${proj} URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/MITK-Data_${revision_tag}.tar.gz UPDATE_COMMAND "" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" DEPENDS ${proj_DEPENDENCIES} ) set(MITK_DATA_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif(BUILD_TESTING) diff --git a/CMakeExternals/OpenIGTLink.cmake b/CMakeExternals/OpenIGTLink.cmake new file mode 100644 index 0000000000..5cd98c290d --- /dev/null +++ b/CMakeExternals/OpenIGTLink.cmake @@ -0,0 +1,50 @@ +#----------------------------------------------------------------------------- +# OpenIGTLink +#----------------------------------------------------------------------------- +if(MITK_USE_OpenIGTLink) + + # Sanity checks + if(DEFINED OpenIGTLink_DIR AND NOT EXISTS ${OpenIGTLink_DIR}) + message(FATAL_ERROR "OpenIGTLink_DIR variable is defined but corresponds to non-existing directory") + endif() + + set(proj OpenIGTLink) + set(proj_DEPENDENCIES ) + set(${proj}_DEPENDS ${proj}) + + if(NOT DEFINED OpenIGTLink_DIR) + + set(additional_cmake_args ) + if(MINGW) + set(additional_cmake_args + -DCMAKE_USE_WIN32_THREADS:BOOL=ON + -DCMAKE_USE_PTHREADS:BOOL=OFF) + endif() + + ExternalProject_Add(${proj} + SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src + BINARY_DIR ${proj}-build + PREFIX ${proj}-cmake + URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/OpenIGTLink-54df50de.tar.gz + URL_MD5 b9fd8351b059f4ec615f2dfd74ab2458 + INSTALL_COMMAND "" + CMAKE_GENERATOR ${gen} + CMAKE_ARGS + ${ep_common_args} + ${additional_cmake_args} + -DBUILD_TESTING:BOOL=OFF + -DBUILD_EXAMPLES:BOOL=OFF + -DOpenIGTLink_PROTOCOL_VERSION_2:BOOL=ON + -DCMAKE_CXX_FLAGS:STRING=${ep_common_cxx_flags} + -DCMAKE_C_FLAGS:STRING=${ep_common_c_flags} + DEPENDS ${proj_DEPENDENCIES} + ) + + set(OpenIGTLink_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-build) + + else() + + mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") + + endif() +endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index 8831d14ec1..a16d604796 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,1266 +1,1267 @@ set(MITK_CMAKE_MINIMUM_REQUIRED_VERSION 3.1) cmake_minimum_required(VERSION ${MITK_CMAKE_MINIMUM_REQUIRED_VERSION}) #----------------------------------------------------------------------------- # 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 VERSION 2014.10.99) endif() #----------------------------------------------------------------------------- # Check miminum compiler versions #----------------------------------------------------------------------------- if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # require at least gcc 4.6 as provided by Ubuntu 12.04 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6) message(FATAL_ERROR "GCC version must be at least 4.6") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # require at least clang 3.2 for correct RTTI handling and C++11 support if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.2) message(FATAL_ERROR "Clang version must be at least 3.2") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") # require at least clang 5.0 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) message(FATAL_ERROR "Apple Clang version must be at least 5.0") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # require at least Visual Studio 2010 (msvc ...) if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16) message(FATAL_ERROR "Micorsoft Visual Studio 2010 or newer required (MSVC 16.0)") endif() else() message(WARNING "You are using an unsupported compiler! Compilation has only been tested with Clang (Linux or Apple), GCC and MSVC.") 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 ) foreach(policy ${project_policies}) if(POLICY ${policy}) cmake_policy(SET ${policy} NEW) endif() endforeach() #----------------------------------------------------------------------------- # Update CMake module path #------------------------------------------------------------------------------ set(MITK_CMAKE_DIR ${MITK_SOURCE_DIR}/CMake) set(CMAKE_MODULE_PATH ${MITK_CMAKE_DIR} ${CMAKE_MODULE_PATH} ) #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- # Standard CMake macros include(FeatureSummary) include(CTestUseLaunchers) include(CMakeParseArguments) include(FindPackageHandleStandardArgs) # MITK macros include(mitkMacroEmptyExternalProject) include(mitkFunctionGenerateProjectXml) include(mitkFunctionSuppressWarnings) include(mitkFunctionEnableBuildConfiguration) include(mitkFunctionWhitelists) include(mitkFunctionAddExternalProject) SUPPRESS_VC_DEPRECATED_WARNINGS() #----------------------------------------------------------------------------- # Additional MITK Options (also shown during superbuild) #----------------------------------------------------------------------------- macro(env_option name doc value) set(_value $ENV{${name}}) if("${_value}" STREQUAL "") set(_value ${value}) endif() option(${name} "${doc}" ${_value}) endmacro() # ----------------------------------------- # General build options option(BUILD_SHARED_LIBS "Build MITK with shared libraries" ON) option(WITH_COVERAGE "Enable/Disable coverage" OFF) option(BUILD_TESTING "Test the project" ON) env_option(MITK_BUILD_ALL_APPS "Build all MITK applications" OFF) env_option(MITK_BUILD_EXAMPLES "Build the MITK Examples" OFF) option(MITK_ENABLE_PIC_READER "Enable support for reading the DKFZ pic file format." ON) mark_as_advanced(MITK_BUILD_ALL_APPS MITK_ENABLE_PIC_READER ) # ----------------------------------------- # Qt version related variables set(DESIRED_QT_VERSION 4 CACHE STRING "Pick a version of Qt to use: 4 or 5") env_option(MITK_USE_QT "Use Nokia's Qt library" ON) set(MITK_DESIRED_QT_VERSION ${DESIRED_QT_VERSION}) if(MITK_USE_QT) # find the package at the very beginning, so that QT4_FOUND is available if(DESIRED_QT_VERSION MATCHES 4) set(MITK_QT4_MINIMUM_VERSION 4.7) find_package(Qt4 ${MITK_QT4_MINIMUM_VERSION} REQUIRED) set(MITK_USE_Qt4 TRUE) set(MITK_USE_Qt5 FALSE) endif() if(DESIRED_QT_VERSION MATCHES 5) set(MITK_QT5_MINIMUM_VERSION 5.0.0) set(MITK_USE_Qt4 FALSE) set(MITK_USE_Qt5 TRUE) set(QT5_INSTALL_PREFIX "" CACHE PATH "The install location of Qt5") set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QT5_INSTALL_PREFIX}) set(MITK_QT5_COMPONENTS Concurrent OpenGL PrintSupport Script Sql Svg WebKitWidgets Xml XmlPatterns UiTools) find_package(Qt5 ${MITK_QT5_MINIMUM_VERSION} COMPONENTS ${MITK_QT5_COMPONENTS} REQUIRED) endif() else() set(MITK_USE_Qt4 FALSE) set(MITK_USE_Qt5 FALSE) endif() # ------------------------------------------------------------------------ # Register external projects which can be build with the MITK superbuild # system. Each mitkFunctionAddExternalProject() call registers an external # project for which a CMakeExternals/.cmake file must exist. The # call also creates a MITK_USE_ variable (appearing in the CMake # UI if the NO_CACHE option is *not* given). # ----------------------------------------- # Optional external projects with no # inter-dependencies set_property(GLOBAL PROPERTY MITK_EXTERNAL_PROJECTS "") -mitkFunctionAddExternalProject(NAME Poco ON COMPONENTS Foundation Util XML) -mitkFunctionAddExternalProject(NAME Boost OFF DOC "Use the Boost C++ library") -mitkFunctionAddExternalProject(NAME DCMTK ON DOC "EXPERIMENTAL, superbuild only: Use DCMTK in MITK") - -mitkFunctionAddExternalProject(NAME tinyxml ON ADVANCED) -mitkFunctionAddExternalProject(NAME GDCM ON ADVANCED) -mitkFunctionAddExternalProject(NAME GLUT OFF ADVANCED) -mitkFunctionAddExternalProject(NAME Raptor2 OFF ADVANCED) -mitkFunctionAddExternalProject(NAME Eigen ON ADVANCED DOC "Use the Eigen library") -mitkFunctionAddExternalProject(NAME GLEW ON ADVANCED DOC "Use the GLEW library") -mitkFunctionAddExternalProject(NAME ANN ON ADVANCED DOC "Use Approximate Nearest Neighbor Library") -mitkFunctionAddExternalProject(NAME CppUnit ON ADVANCED DOC "Use CppUnit for unit tests") - -mitkFunctionAddExternalProject(NAME PCRE OFF ADVANCED NO_PACKAGE) -mitkFunctionAddExternalProject(NAME ZLIB OFF ADVANCED NO_PACKAGE NO_CACHE) +mitkFunctionAddExternalProject(NAME Poco ON COMPONENTS Foundation Util XML) +mitkFunctionAddExternalProject(NAME Boost OFF DOC "Use the Boost C++ library") +mitkFunctionAddExternalProject(NAME DCMTK ON DOC "EXPERIMENTAL, superbuild only: Use DCMTK in MITK") +mitkFunctionAddExternalProject(NAME OpenIGTLink OFF) + +mitkFunctionAddExternalProject(NAME tinyxml ON ADVANCED) +mitkFunctionAddExternalProject(NAME GDCM ON ADVANCED) +mitkFunctionAddExternalProject(NAME GLUT OFF ADVANCED) +mitkFunctionAddExternalProject(NAME Raptor2 OFF ADVANCED) +mitkFunctionAddExternalProject(NAME Eigen ON ADVANCED DOC "Use the Eigen library") +mitkFunctionAddExternalProject(NAME GLEW ON ADVANCED DOC "Use the GLEW library") +mitkFunctionAddExternalProject(NAME ANN ON ADVANCED DOC "Use Approximate Nearest Neighbor Library") +mitkFunctionAddExternalProject(NAME CppUnit ON ADVANCED DOC "Use CppUnit for unit tests") + +mitkFunctionAddExternalProject(NAME PCRE OFF ADVANCED NO_PACKAGE) +mitkFunctionAddExternalProject(NAME ZLIB OFF ADVANCED NO_PACKAGE NO_CACHE) # ----------------------------------------- # The following external projects must be # ordered according to their # inter-dependencies if(MITK_USE_QT) mitkFunctionAddExternalProject(NAME Qwt ON ADVANCED) endif() mitkFunctionAddExternalProject(NAME SWIG OFF ADVANCED NO_PACKAGE DEPENDS PCRE) mitkFunctionAddExternalProject(NAME Python OFF NO_PACKAGE DEPENDS SWIG DOC "Use Python wrapping in MITK") mitkFunctionAddExternalProject(NAME Numpy OFF ADVANCED NO_PACKAGE) mitkFunctionAddExternalProject(NAME OpenCV OFF) # These are "hard" dependencies and always set to ON mitkFunctionAddExternalProject(NAME ITK ON NO_CACHE) mitkFunctionAddExternalProject(NAME VTK ON NO_CACHE) mitkFunctionAddExternalProject(NAME SimpleITK OFF DEPENDS ITK GDCM SWIG) mitkFunctionAddExternalProject(NAME ACVD OFF DOC "Use Approximated Centroidal Voronoi Diagrams") mitkFunctionAddExternalProject(NAME CTK ON DEPENDS DCMTK DOC "Use CTK in MITK") mitkFunctionAddExternalProject(NAME Rasqal OFF DEPENDS Raptor2 PCRE ADVANCED) mitkFunctionAddExternalProject(NAME Redland OFF DEPENDS Rasqal DOC "Use the Redland RDF library") mitkFunctionAddExternalProject(NAME SOFA OFF DEPENDS GLUT Boost DOC "Use Simulation Open Framework Architecture") # ----------------------------------------- # Custom dependency logic 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_SOFA) # SOFA requires at least CMake 2.8.8 set(SOFA_CMAKE_VERSION 2.8.8) if(${CMAKE_VERSION} VERSION_LESS ${SOFA_CMAKE_VERSION}) set(MITK_USE_SOFA OFF CACHE BOOL "" FORCE) message(WARNING "Switched off MITK_USE_SOFA\n Minimum required CMake version: ${SOFA_CMAKE_VERSION}\n Installed CMake version: ${CMAKE_VERSION}") endif() # SOFA/ITK combination requires at least MSVC 2010 if(MSVC_VERSION AND MSVC_VERSION LESS 1600) set(MITK_USE_SOFA OFF CACHE BOOL "" FORCE) message(WARNING "Switched off MITK_USE_SOFA\n MSVC versions less than 2010 are not supported.") endif() # SOFA requires boost library if(MITK_USE_SOFA AND NOT MITK_USE_Boost) message("> Forcing MITK_USE_Boost to ON because of MITK_USE_SOFA") set(MITK_USE_Boost ON CACHE BOOL "" FORCE) endif() # SOFA requires boost system library list(FIND MITK_USE_Boost_LIBRARIES system _result) if(_result LESS 0) message("> Adding 'system' to MITK_USE_Boost_LIBRARIES.") list(APPEND MITK_USE_Boost_LIBRARIES system) endif() # SOFA requires boost thread library list(FIND MITK_USE_Boost_LIBRARIES thread _result) if(_result LESS 0) message("> Adding 'thread' to MITK_USE_Boost_LIBRARIES.") list(APPEND MITK_USE_Boost_LIBRARIES thread) endif() # Simulation plugin requires boost chrono library list(FIND MITK_USE_Boost_LIBRARIES chrono _result) if(_result LESS 0) message("> Adding 'chrono' to MITK_USE_Boost_LIBRARIES.") list(APPEND MITK_USE_Boost_LIBRARIES chrono) endif() set(MITK_USE_Boost_LIBRARIES ${MITK_USE_Boost_LIBRARIES} CACHE STRING "" FORCE) # Allow setting external SOFA plugins directory and SOFA plugins set(MITK_USE_SOFA_PLUGINS_DIR ${MITK_USE_SOFA_PLUGINS_DIR} CACHE PATH "External SOFA plugins directory" FORCE) set(MITK_USE_SOFA_PLUGINS ${MITK_USE_SOFA_PLUGINS} CACHE PATH "List of semicolon-separated plugin names" FORCE) endif() if(MITK_USE_Python AND NOT MITK_USE_SYSTEM_PYTHON) set(MITK_USE_ZLIB ON) if(NOT MITK_USE_Numpy) message("> Forcing MITK_USE_Numpy to ON because of MITK_USE_Python") set(MITK_USE_Numpy ON CACHE BOOL "Use Numpy" FORCE) endif() if(NOT MITK_USE_SimpleITK) message("> Forcing MITK_USE_SimpleITK to ON because of MITK_USE_Python") set(MITK_USE_Numpy ON CACHE BOOL "Use Numpy" FORCE) endif() if(APPLE) message(WARNING "Python wrapping is unsuported on mac OSX!") set(MITK_USE_Python OFF CACHE BOOL "Use Python wrapping in MITK" FORCE) else() option(MITK_USE_SYSTEM_PYTHON "Use the system python runtime" OFF) if(MITK_USE_SYSTEM_PYTHON) find_package(PythonLibs REQUIRED) find_package(PythonInterp REQUIRED) endif() endif() endif() if(BUILD_TESTING AND NOT MITK_USE_CppUnit) message("> Forcing MITK_USE_CppUnit to ON because BUILD_TESTING=ON") set(MITK_USE_CppUnit ON CACHE BOOL "Use CppUnit for unit tests" FORCE) endif() # ----------------------------------------- # Other MITK_USE_* options not related to # external projects build via the # MITK superbuild env_option(MITK_USE_BLUEBERRY "Build the BlueBerry platform" ON) env_option(MITK_USE_OpenCL "Use OpenCL GPU-Computing library" OFF) 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() #----------------------------------------------------------------------------- # Build configurations #----------------------------------------------------------------------------- set(_buildConfigs "Custom") file(GLOB _buildConfigFiles CMake/BuildConfigurations/*.cmake) foreach(_buildConfigFile ${_buildConfigFiles}) get_filename_component(_buildConfigFile ${_buildConfigFile} NAME_WE) list(APPEND _buildConfigs ${_buildConfigFile}) endforeach() set(MITK_BUILD_CONFIGURATION "Custom" CACHE STRING "Use pre-defined MITK configurations") mark_as_advanced(MITK_BUILD_CONFIGURATION) set_property(CACHE MITK_BUILD_CONFIGURATION PROPERTY STRINGS ${_buildConfigs}) mitkFunctionEnableBuildConfiguration() mitkFunctionCreateWhitelistPaths(MITK) mitkFunctionFindWhitelists(MITK) #----------------------------------------------------------------------------- # Pixel type multiplexing #----------------------------------------------------------------------------- # 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 "itk::RGBPixel, itk::RGBAPixel" 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_COMPOSITE_PIXEL_TYPES) set(MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES "itk::RGBPixel, itk::RGBAPixel" CACHE STRING "List of composite pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES) string(REPLACE "," ";" _integral_types ${MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES}) string(REPLACE "," ";" _floating_types ${MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES}) foreach(_scalar_type ${_integral_types} ${_floating_types}) set(MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}itk::VariableLengthVector<${_scalar_type}>,") endforeach() string(LENGTH "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}" _length) math(EXPR _length "${_length} - 1") string(SUBSTRING "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}" 0 ${_length} MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES) set(MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES ${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES} CACHE STRING "List of vector pixel types used in AccessByItk and InstantiateAccessFunction macros for itk::VectorImage types" 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() #----------------------------------------------------------------------------- # 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 MITK-Examples 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") # Print configuration summary message("\n\n") feature_summary( DESCRIPTION "------- FEATURE SUMMARY FOR ${PROJECT_NAME} -------" WHAT ALL) return() endif() #***************************************************************************** #**************************** END OF SUPERBUILD **************************** #***************************************************************************** #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- include(WriteBasicConfigVersionFile) include(CheckCXXSourceCompiles) include(GenerateExportHeader) include(mitkFunctionCheckCompilerFlags) include(mitkFunctionGetGccVersion) include(mitkFunctionSuppressWarnings) # includes several functions include(mitkFunctionOrganizeSources) include(mitkFunctionGetVersion) include(mitkFunctionGetVersionDescription) include(mitkFunctionCreateWindowsBatchScript) include(mitkFunctionInstallProvisioningFiles) include(mitkFunctionInstallAutoLoadModules) include(mitkFunctionGetLibrarySearchPaths) include(mitkFunctionCompileSnippets) include(mitkFunctionUseModules) include(mitkFunctionCheckModuleDependencies) include(mitkFunctionCreateModule) include(mitkMacroCreateExecutable) include(mitkMacroCreateModuleTests) include(mitkFunctionAddCustomModuleTest) include(mitkMacroMultiplexPicType) include(mitkMacroInstall) include(mitkMacroInstallHelperApp) include(mitkMacroInstallTargets) include(mitkMacroGenerateToolsLibrary) include(mitkMacroGetLinuxDistribution) include(mitkMacroGetPMDPlatformString) include(mitkMacroConfigureItkPixelTypes) #----------------------------------------------------------------------------- # Global CMake variables #----------------------------------------------------------------------------- set(MITK_CXX_STANDARD 11) # help keeping cross-platform compatibility # CMake 3.1 does not yet know how to handle AppleClang... # See http://public.kitware.com/Bug/view.php?id=15355 if(NOT MSVC AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") set(CMAKE_CXX_EXTENSIONS 0) set(CMAKE_CXX_STANDARD ${MITK_CXX_STANDARD}) set(CMAKE_CXX_STANDARD_REQUIRED 1) endif() # Required and enabled C++11 features for all MITK code. # These are added as PUBLIC compile features to all MITK modules. set(MITK_CXX_FEATURES cxx_auto_type cxx_nullptr cxx_override) if(NOT DEFINED CMAKE_DEBUG_POSTFIX) # We can't do this yet because the CTK Plugin Framework # cannot cope with a postfix yet. #set(CMAKE_DEBUG_POSTFIX d) endif() #----------------------------------------------------------------------------- # Output directories. #----------------------------------------------------------------------------- set(_default_LIBRARY_output_dir lib) set(_default_RUNTIME_output_dir bin) set(_default_ARCHIVE_output_dir lib) foreach(type LIBRARY RUNTIME ARCHIVE) # Make sure the directory exists if(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_CMAKE_${type}_OUTPUT_DIRECTORY) set(CMAKE_${type}_OUTPUT_DIRECTORY ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}) else() set(CMAKE_${type}_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${_default_${type}_output_dir}) set(MITK_CMAKE_${type}_OUTPUT_DIRECTORY ${CMAKE_${type}_OUTPUT_DIRECTORY}) endif() set(CMAKE_${type}_OUTPUT_DIRECTORY ${CMAKE_${type}_OUTPUT_DIRECTORY} CACHE INTERNAL "Output directory for ${type} files.") mark_as_advanced(CMAKE_${type}_OUTPUT_DIRECTORY) endforeach() #----------------------------------------------------------------------------- # Set MITK specific options and variables (NOT available during superbuild) #----------------------------------------------------------------------------- # ASK THE USER TO SHOW THE CONSOLE WINDOW FOR CoreApp and mitkWorkbench 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() # MITK_VERSION 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() # Needed early on for redirecting the BlueBerry documentation output dir set(MITK_DOXYGEN_OUTPUT_DIR ${PROJECT_BINARY_DIR}/Documentation/Doxygen CACHE PATH "Output directory for doxygen generated documentation." ) 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() if(MITK_BUILD_ALL_PLUGINS) set(MITK_BUILD_ALL_PLUGINS_OPTION "FORCE_BUILD_ALL") endif() # Configure pixel types used for ITK image access multiplexing mitkMacroConfigureItkPixelTypes() # Configure module naming conventions set(MITK_MODULE_NAME_REGEX_MATCH "^[A-Z].*$") set(MITK_MODULE_NAME_REGEX_NOT_MATCH "^[Mm][Ii][Tt][Kk].*$") set(MITK_MODULE_NAME_PREFIX "Mitk") set(MITK_MODULE_NAME_DEFAULTS_TO_DIRECTORY_NAME 1) #----------------------------------------------------------------------------- # Get MITK version info #----------------------------------------------------------------------------- mitkFunctionGetVersion(${MITK_SOURCE_DIR} MITK) mitkFunctionGetVersionDescription(${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(MITK_USE_BLUEBERRY AND APPLE) include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") 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) list(GET target_info_list 0 app_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) set(MACOSX_BUNDLE_NAMES ${MACOSX_BUNDLE_NAMES} Mitk${app_name}) endif() endforeach() 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}") set(MITK_C_FLAGS_DEBUG ) set(MITK_C_FLAGS_RELEASE ) set(MITK_CXX_FLAGS "${COVERAGE_CXX_FLAGS}") set(MITK_CXX_FLAGS_DEBUG ) set(MITK_CXX_FLAGS_RELEASE ) set(MITK_EXE_LINKER_FLAGS ) set(MITK_SHARED_LINKER_FLAGS ) mitkFunctionCheckCompilerFlags("-std=c++11" MITK_CXX_FLAGS) if(WIN32) set(MITK_CXX_FLAGS "${MITK_CXX_FLAGS} -D_WIN32_WINNT=0x0501 -DPOCO_NO_UNWINDOWS -DWIN32_LEAN_AND_MEAN -DNOMINMAX") mitkFunctionCheckCompilerFlags("/wd4005" MITK_CXX_FLAGS) # warning C4005: macro redefinition mitkFunctionCheckCompilerFlags("/wd4231" MITK_CXX_FLAGS) # warning C4231: nonstandard extension used : 'extern' before template explicit instantiation # the following line should be removed after fixing bug 17637 mitkFunctionCheckCompilerFlags("/wd4316" MITK_CXX_FLAGS) # warning C4316: object alignment on heap endif() if(NOT MSVC_VERSION) foreach(_flag -Wall -Wextra -Wpointer-arith -Winvalid-pch -Wcast-align -Wwrite-strings -Wno-error=gnu -Wno-error=unknown-pragmas # The strict-overflow warning is generated by ITK template code -Wno-error=strict-overflow -Woverloaded-virtual -Wstrict-null-sentinel #-Wold-style-cast #-Wsign-promo # the following two lines should be removed after ITK-3097 has # been resolved, see also MITK bug 15279 -Wno-unused-local-typedefs -Wno-array-bounds -fdiagnostics-show-option ) mitkFunctionCheckCAndCXXCompilerFlags(${_flag} MITK_C_FLAGS MITK_CXX_FLAGS) endforeach() endif() if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE) mitkFunctionCheckCompilerFlags("-Wl,--no-undefined" MITK_SHARED_LINKER_FLAGS) mitkFunctionCheckCompilerFlags("-Wl,--as-needed" MITK_SHARED_LINKER_FLAGS) endif() if(CMAKE_COMPILER_IS_GNUCXX) 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")) mitkFunctionCheckCAndCXXCompilerFlags("-fstack-protector-all" MITK_C_FLAGS MITK_CXX_FLAGS) endif() if(MINGW) # suppress warnings about auto imported symbols set(MITK_SHARED_LINKER_FLAGS "-Wl,--enable-auto-import ${MITK_SHARED_LINKER_FLAGS}") endif() set(MITK_CXX_FLAGS_RELEASE "-D_FORTIFY_SOURCE=2 ${MITK_CXX_FLAGS_RELEASE}") endif() set(MITK_MODULE_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS}) set(MITK_EXE_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS}) #----------------------------------------------------------------------------- # MITK Packages #----------------------------------------------------------------------------- set(MITK_MODULES_PACKAGE_DEPENDS_DIR ${MITK_SOURCE_DIR}/CMake/PackageDepends) set(MODULES_PACKAGE_DEPENDS_DIRS ${MITK_MODULES_PACKAGE_DEPENDS_DIR}) # This property is populated at the top half of this file get_property(MITK_EXTERNAL_PROJECTS GLOBAL PROPERTY MITK_EXTERNAL_PROJECTS) foreach(ep ${MITK_EXTERNAL_PROJECTS}) get_property(_package GLOBAL PROPERTY MITK_${ep}_PACKAGE) get_property(_components GLOBAL PROPERTY MITK_${ep}_COMPONENTS) if(MITK_USE_${ep} AND _package) if(_components) find_package(${_package} COMPONENTS ${_components} REQUIRED CONFIG) else() # Prefer config mode first because it finds external # Config.cmake files pointed at by _DIR variables. # Otherwise, existing Find.cmake files could file # (e.g. in the case of GLEW and the FindGLEW.cmake file shipped # with CMake). find_package(${_package} QUIET CONFIG) string(TOUPPER "${_package}" _package_uc) if(NOT (${_package}_FOUND OR ${_package_uc}_FOUND)) find_package(${_package} REQUIRED) endif() endif() endif() endforeach() if(MITK_USE_Python) find_package(PythonLibs REQUIRED) find_package(PythonInterp REQUIRED) endif() if(MITK_USE_SOFA) # The SOFAConfig.cmake file does not provide exported targets or # libraries with absolute paths, hence we need to make the link # directories globally available until the SOFAConfig.cmake file # supports a proper mechanism for handling targets. # The same code is needed in MITKConfig.cmake. link_directories(${SOFA_LIBRARY_DIRS}) endif() # Qt support if(MITK_USE_QT) if(DESIRED_QT_VERSION MATCHES 4) find_package(Qt4 ${MITK_QT4_MINIMUM_VERSION} REQUIRED) elseif(DESIRED_QT_VERSION MATCHES 5) find_package(Qt5Core ${MITK_QT5_MINIMUM_VERSION} REQUIRED) # at least Core required endif() endif() # Ensure that the MITK CMake module path comes first set(CMAKE_MODULE_PATH ${MITK_CMAKE_DIR} ${CMAKE_MODULE_PATH} ) #----------------------------------------------------------------------------- # Testing #----------------------------------------------------------------------------- if(BUILD_TESTING) enable_testing() include(CTest) mark_as_advanced(TCL_TCLSH DART_ROOT) option(MITK_ENABLE_RENDERING_TESTING OFF "Enable the MITK rendering tests. Requires x-server in Linux.") #Rendering testing does not work for Linux nightlies, thus it is disabled per default #and activated for Mac and Windows. if(WIN32 OR APPLE) set(MITK_ENABLE_RENDERING_TESTING ON) endif() mark_as_advanced( MITK_ENABLE_RENDERING_TESTING ) # 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) + #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() #----------------------------------------------------------------------------- # Set C/CXX and linker flags for MITK code #----------------------------------------------------------------------------- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MITK_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${MITK_CXX_FLAGS_DEBUG}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${MITK_CXX_FLAGS_RELEASE}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MITK_C_FLAGS}") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${MITK_C_FLAGS_DEBUG}") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${MITK_C_FLAGS_RELEASE}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MITK_EXE_LINKER_FLAGS}") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${MITK_SHARED_LINKER_FLAGS}") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${MITK_MODULE_LINKER_FLAGS}") #----------------------------------------------------------------------------- # Compile Utilities and set-up MITK variables #----------------------------------------------------------------------------- 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} OR MITK_BUILD_ALL_APPS) 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() set(BLUEBERRY_XPDOC_OUTPUT_DIR ${MITK_DOXYGEN_OUTPUT_DIR}/html/extension-points/html/) 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() #----------------------------------------------------------------------------- # 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 #----------------------------------------------------------------------------- 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") if(TARGET 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() endif() set(BLUEBERRY_TEST_APP_ID "org.mitk.qt.coreapplication") endif() include("${CMAKE_CURRENT_SOURCE_DIR}/Plugins/PluginList.cmake") mitkFunctionWhitelistPlugins(MITK MITK_EXT_PLUGINS) 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() if(MITK_BUILD_EXAMPLES) include("${CMAKE_CURRENT_SOURCE_DIR}/Examples/Plugins/PluginList.cmake") set(mitk_example_plugins_fullpath ) foreach(mitk_example_plugin ${MITK_EXAMPLE_PLUGINS}) list(APPEND mitk_example_plugins_fullpath Examples/Plugins/${mitk_example_plugin}) list(APPEND mitk_plugins_fullpath Examples/Plugins/${mitk_example_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}) string(FIND ${mitk_app} "MITK_BUILD_APP_" _index) string(SUBSTRING ${mitk_app} ${_index} -1 _var) if(${_var}) list(APPEND mitk_apps_fullpath "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${mitk_app}") endif() endforeach() if (mitk_plugins_fullpath) ctkMacroSetupPlugins(${mitk_plugins_fullpath} BUILD_OPTION_PREFIX MITK_BUILD_ APPS ${mitk_apps_fullpath} BUILD_ALL ${MITK_BUILD_ALL_PLUGINS} COMPACT_OPTIONS) endif() 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() #----------------------------------------------------------------------------- # Documentation #----------------------------------------------------------------------------- add_subdirectory(Documentation) #----------------------------------------------------------------------------- # Installation #----------------------------------------------------------------------------- # set MITK cpack variables # These are the default variables, which can be overwritten ( see below ) include(mitkSetupCPack) set(use_default_config ON) # 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} OR MITK_BUILD_ALL_APPS) 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} OR MITK_BUILD_ALL_APPS) # 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() 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 #----------------------------------------------------------------------------- # ---------------- Export targets ----------------- set(MITK_EXPORTS_FILE "${MITK_BINARY_DIR}/MitkExports.cmake") file(REMOVE ${MITK_EXPORTS_FILE}) set(targets_to_export) get_property(module_targets GLOBAL PROPERTY MITK_MODULE_TARGETS) if(module_targets) list(APPEND targets_to_export ${module_targets}) endif() if(MITK_USE_BLUEBERRY) if(MITK_PLUGIN_LIBRARIES) list(APPEND targets_to_export ${MITK_PLUGIN_LIBRARIES}) endif() endif() export(TARGETS ${targets_to_export} APPEND FILE ${MITK_EXPORTS_FILE}) set(MITK_EXPORTED_TARGET_PROPERTIES ) foreach(target_to_export ${targets_to_export}) get_target_property(autoload_targets ${target_to_export} MITK_AUTOLOAD_TARGETS) if(autoload_targets) set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES} set_target_properties(${target_to_export} PROPERTIES MITK_AUTOLOAD_TARGETS \"${autoload_targets}\")") endif() get_target_property(autoload_dir ${target_to_export} MITK_AUTOLOAD_DIRECTORY) if(autoload_dir) set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES} set_target_properties(${target_to_export} PROPERTIES MITK_AUTOLOAD_DIRECTORY \"${autoload_dir}\")") endif() get_target_property(deprecated_module ${target_to_export} MITK_MODULE_DEPRECATED_SINCE) if(deprecated_module) set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES} set_target_properties(${target_to_export} PROPERTIES MITK_MODULE_DEPRECATED_SINCE \"${deprecated_module}\")") endif() endforeach() # ---------------- External projects ----------------- get_property(MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS_CONFIG GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS) set(MITK_CONFIG_EXTERNAL_PROJECTS ) #string(REPLACE "^^" ";" _mitk_external_projects ${MITK_EXTERNAL_PROJECTS}) foreach(ep ${MITK_EXTERNAL_PROJECTS}) get_property(_components GLOBAL PROPERTY MITK_${ep}_COMPONENTS) set(MITK_CONFIG_EXTERNAL_PROJECTS "${MITK_CONFIG_EXTERNAL_PROJECTS} set(MITK_USE_${ep} ${MITK_USE_${ep}}) set(MITK_${ep}_DIR \"${${ep}_DIR}\") set(MITK_${ep}_COMPONENTS ${_components}) ") endforeach() foreach(ep ${MITK_EXTERNAL_PROJECTS}) get_property(_package GLOBAL PROPERTY MITK_${ep}_PACKAGE) get_property(_components GLOBAL PROPERTY MITK_${ep}_COMPONENTS) if(_components) set(_components_arg COMPONENTS \${_components}) else() set(_components_arg) endif() if(_package) set(MITK_CONFIG_EXTERNAL_PROJECTS "${MITK_CONFIG_EXTERNAL_PROJECTS} if(MITK_USE_${ep}) set(${ep}_DIR \${MITK_${ep}_DIR}) if(MITK_${ep}_COMPONENTS) mitkMacroFindDependency(${_package} COMPONENTS \${MITK_${ep}_COMPONENTS}) else() mitkMacroFindDependency(${_package}) endif() endif()") endif() endforeach() # ---------------- Tools ----------------- 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 files ----------------- configure_file(mitkVersion.h.in ${MITK_BINARY_DIR}/mitkVersion.h) configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h) set(IPFUNC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ipFunc) set(UTILITIES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities) configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h) configure_file(MITKConfig.cmake.in ${MITK_BINARY_DIR}/MITKConfig.cmake @ONLY) write_basic_config_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake VERSION ${MITK_VERSION_STRING} COMPATIBILITY AnyNewerVersion) # 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) #----------------------------------------------------------------------------- # MITK Examples #----------------------------------------------------------------------------- if(MITK_BUILD_EXAMPLES) # This must come after MITKConfig.h was generated, since applications # might do a find_package(MITK REQUIRED). add_subdirectory(Examples) endif() #----------------------------------------------------------------------------- # Print configuration summary #----------------------------------------------------------------------------- message("\n\n") feature_summary( DESCRIPTION "------- FEATURE SUMMARY FOR ${PROJECT_NAME} -------" WHAT ALL ) diff --git a/Examples/QtAppExample/Step1.cpp b/Examples/QtAppExample/Step1.cpp index 4172a82295..e4dd93383b 100644 --- a/Examples/QtAppExample/Step1.cpp +++ b/Examples/QtAppExample/Step1.cpp @@ -1,107 +1,96 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkRegisterClasses.h" #include "QmitkRenderWindow.h" -#include #include +#include #include #include // Load image (nrrd 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 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(...) + // Load a DataNode using the mitkIOUtil + // (supports many image formats, surface formats, etc.) + mitk::StandaloneDataStorage::SetOfObjects::Pointer dataNodes = mitk::IOUtil::Load(argv[1],*ds); + + if(dataNodes->empty()) { - fprintf( stderr, "Could not open file %s \n\n", filename ); + fprintf( stderr, "Could not open file %s \n\n", argv[1] ); exit(2); } //************************************************************************* // 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::TimeGeometry::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 ); qtapplication.exec(); // cleanup: Remove References to DataStorage. This will delete the object ds = NULL; } diff --git a/Examples/Tutorial/Step1/Step1.cpp b/Examples/Tutorial/Step1/Step1.cpp index 140bd8a6f5..925dd2aec7 100644 --- a/Examples/Tutorial/Step1/Step1.cpp +++ b/Examples/Tutorial/Step1/Step1.cpp @@ -1,115 +1,98 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkRegisterClasses.h" #include "QmitkRenderWindow.h" -#include #include #include #include +#include + //##Documentation //## @brief Load image (nrrd 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 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); - } + // Load datanode (eg. many image formats, surface formats, etc.) + mitk::IOUtil::Load(argv[1],*ds); //************************************************************************* // 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::TimeGeometry::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 DataStorage. This will delete the object ds = NULL; } /** \example Step1.cpp */ diff --git a/Examples/Tutorial/Step2/Step2.cpp b/Examples/Tutorial/Step2/Step2.cpp index 94dc282bb5..d5bedc9dd8 100644 --- a/Examples/Tutorial/Step2/Step2.cpp +++ b/Examples/Tutorial/Step2/Step2.cpp @@ -1,118 +1,102 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkRegisterClasses.h" #include "QmitkRenderWindow.h" -#include #include #include #include +#include //##Documentation //## @brief Load one or more data sets (many image, surface //## and other formats) and display it in a 2D view int main(int argc, char* argv[]) { QApplication qtapplication( argc, argv ); if(argc<2) { fprintf( stderr, "Usage: %s [filename1] [filename2] ...\n\n", itksys::SystemTools::GetFilenameName(argv[0]).c_str() ); return 1; } // Register Qmitk-dependent global instances QmitkRegisterClasses(); //************************************************************************* // Part I: Basic initialization //************************************************************************* // Create a data storage object. We will use it as a singleton mitk::StandaloneDataStorage::Pointer storage = mitk::StandaloneDataStorage::New(); //************************************************************************* // Part II: Create some data by reading files //************************************************************************* int i; for(i=1; iSetFileName(filename); - nodeReader->Update(); - //********************************************************************* - // Part III: Put the data into the datastorage - //********************************************************************* - - // Since the DataNodeFactory directly creates a node, - // use the datastorage to add the read node - storage->Add(nodeReader->GetOutput()); - } - catch(...) - { - fprintf( stderr, "Could not open file %s \n\n", filename ); - exit(2); - } + //********************************************************************* + // Part III: Put the data into the datastorage + //********************************************************************* + // Add the node to the DataStorage + mitk::IOUtil::Load(argv[i],*storage); } //************************************************************************* // 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(storage); // Initialize the RenderWindow mitk::TimeGeometry::Pointer geo = storage->ComputeBoundingGeometry3D(storage->GetAll()); mitk::RenderingManager::GetInstance()->InitializeViews( geo ); // Select a slice mitk::SliceNavigationController::Pointer sliceNaviController = renderWindow.GetSliceNavigationController(); if (sliceNaviController) sliceNaviController->GetSlice()->SetPos( 2 ); //************************************************************************* // 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(); } /** \example Step2.cpp */ diff --git a/Examples/Tutorial/Step3/Step3.cpp b/Examples/Tutorial/Step3/Step3.cpp index 98aedaa4d1..8e8fc8c4b9 100644 --- a/Examples/Tutorial/Step3/Step3.cpp +++ b/Examples/Tutorial/Step3/Step3.cpp @@ -1,171 +1,160 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkRegisterClasses.h" #include "QmitkRenderWindow.h" -#include #include #include #include #include #include +#include #include #include //##Documentation //## @brief Change the type of display to 3D //## //## As in Step2, load one or more data sets (many image, surface //## and other formats), but display it in a 3D view. //## The QmitkRenderWindow is now used for displaying a 3D view, by //## setting the used mapper-slot to Standard3D. //## Since volume-rendering is a (rather) slow procedure, the default //## is that images are not displayed in the 3D view. For this example, //## we want volume-rendering, thus we switch it on by setting //## the Boolean-property "volumerendering" to "true". int main(int argc, char* argv[]) { QApplication qtapplication( argc, argv ); if(argc<2) { fprintf( stderr, "Usage: %s [filename1] [filename2] ...\n\n", itksys::SystemTools::GetFilenameName(argv[0]).c_str() ); return 1; } // Register Qmitk-dependent global instances QmitkRegisterClasses(); //************************************************************************* // Part I: Basic initialization //************************************************************************* // Create a DataStorage mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); //************************************************************************* // Part II: Create some data by reading files //************************************************************************* int i; for(i=1; iSetFileName(filename); - nodeReader->Update(); - //********************************************************************* // Part III: Put the data into the datastorage //********************************************************************* + // Load datanode (eg. many image formats, surface formats, etc.) + mitk::StandaloneDataStorage::SetOfObjects* dataNodes = mitk::IOUtil::Load(argv[i],*ds); - // Since the DataNodeFactory directly creates a node, - // use the datastorage to add the read node - mitk::DataNode::Pointer node = nodeReader->GetOutput(); - ds->Add(node); + if(dataNodes->empty()) + { + fprintf( stderr, "Could not open file %s \n\n", argv[i] ); + exit(2); + } + mitk::DataNode::Pointer node = dataNodes->at(0); // ********************************************************* // ****************** START OF NEW PART 1 ****************** // ********************************************************* //********************************************************************* // Part IV: We want all images to be volume-rendered //********************************************************************* // Check if the data is an image by dynamic_cast-ing the data // contained in the node. Warning: dynamic_cast's are rather slow, // do not use it too often! mitk::Image::Pointer image = dynamic_cast(node->GetData()); if(image.IsNotNull()) { // Set the property "volumerendering" to the Boolean value "true" node->SetProperty("volumerendering", mitk::BoolProperty::New(true)); // Create a transfer function to assign optical properties (color and opacity) to grey-values of the data mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New(); tf->InitializeByMitkImage ( image ); // Set the color transfer function AddRGBPoint(double x, double r, double g, double b) tf->GetColorTransferFunction()->AddRGBPoint ( tf->GetColorTransferFunction()->GetRange() [0], 1.0, 0.0, 0.0 ); tf->GetColorTransferFunction()->AddRGBPoint ( tf->GetColorTransferFunction()->GetRange() [1], 1.0, 1.0, 0.0 ); // Set the piecewise opacity transfer function AddPoint(double x, double y) tf->GetScalarOpacityFunction()->AddPoint ( 0, 0 ); tf->GetScalarOpacityFunction()->AddPoint ( tf->GetColorTransferFunction()->GetRange() [1], 1 ); node->SetProperty ( "TransferFunction", mitk::TransferFunctionProperty::New ( tf.GetPointer() ) ); } // ********************************************************* // ******************* END OF NEW PART 1 ******************* // ********************************************************* - } - catch(...) - { - fprintf( stderr, "Could not open file %s \n\n", filename ); - exit(2); - } } //************************************************************************* // Part V: Create window and pass the tree to it //************************************************************************* // Create a renderwindow QmitkRenderWindow renderWindow; // Tell the renderwindow which (part of) the datastorage to render renderWindow.GetRenderer()->SetDataStorage(ds); // ********************************************************* // ****************** START OF NEW PART 2 ****************** // ********************************************************* // Use it as a 3D view! renderWindow.GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard3D); // ********************************************************* // ******************* END OF NEW PART 2 ******************* // ********************************************************* //************************************************************************* // Part VI: Qt-specific initialization //************************************************************************* renderWindow.show(); renderWindow.resize( 256, 256 ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); // for testing #include "QtTesting.h" if(strcmp(argv[argc-1], "-testing")!=0) return qtapplication.exec(); else return QtTesting(); } /** \example Step3.cpp */ diff --git a/Examples/Tutorial/Step4/Step4.cpp b/Examples/Tutorial/Step4/Step4.cpp index 8460245239..6b2c0f1700 100644 --- a/Examples/Tutorial/Step4/Step4.cpp +++ b/Examples/Tutorial/Step4/Step4.cpp @@ -1,187 +1,170 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkRegisterClasses.h" #include "QmitkRenderWindow.h" #include "QmitkSliceWidget.h" -#include "mitkDataNodeFactory.h" #include "mitkProperties.h" #include "mitkRenderingManager.h" #include "mitkStandaloneDataStorage.h" #include "mitkNodePredicateDataType.h" +#include #include #include #include #include //##Documentation //## @brief Use several views to explore data //## //## As in Step2 and Step3, load one or more data sets (many image, //## surface and other formats), but create 3 views on the data. //## The QmitkRenderWindow is used for displaying a 3D view as in Step3, //## but without volume-rendering. //## Furthermore, we create two 2D views for slicing through the data. //## We use the class QmitkSliceWidget, which is based on the class //## QmitkRenderWindow, but additionally provides sliders //## to slice through the data. We create two instances of //## QmitkSliceWidget, one for axial and one for sagittal slicing. //## The two slices are also shown at their correct position in 3D as //## well as intersection-line, each in the other 2D view. int main(int argc, char* argv[]) { QApplication qtapplication( argc, argv ); if(argc<2) { fprintf( stderr, "Usage: %s [filename1] [filename2] ...\n\n", itksys::SystemTools::GetFilenameName(argv[0]).c_str() ); return 1; } // Register Qmitk-dependent global instances QmitkRegisterClasses(); //************************************************************************* // Part I: Basic initialization //************************************************************************* // Create a DataStorage mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); //************************************************************************* // Part II: Create some data by reading files //************************************************************************* int i; for(i=1; iSetFileName(filename); - nodeReader->Update(); - //********************************************************************* - //Part III: Put the data into the datastorage - //********************************************************************* - - // Since the DataNodeFactory directly creates a node, - // use the datastorage to add the read node - mitk::DataNode::Pointer node = nodeReader->GetOutput(); - ds->Add(node); - } - catch(...) - { - fprintf( stderr, "Could not open file %s \n\n", filename ); - exit(2); - } + //********************************************************************* + // Part III: Put the data into the datastorage + //********************************************************************* + // Load datanode (eg. many image formats, surface formats, etc.) + mitk::IOUtil::Load(argv[i],*ds); } //************************************************************************* // Part IV: Create windows and pass the tree to it //************************************************************************* // Create toplevel widget with horizontal layout QWidget toplevelWidget; QHBoxLayout layout; layout.setSpacing(2); layout.setMargin(0); toplevelWidget.setLayout(&layout); //************************************************************************* // Part IVa: 3D view //************************************************************************* // Create a renderwindow QmitkRenderWindow renderWindow(&toplevelWidget); layout.addWidget(&renderWindow); // Tell the renderwindow which (part of) the datastorage to render renderWindow.GetRenderer()->SetDataStorage(ds); // Use it as a 3D view renderWindow.GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard3D); // ******************************************************* // ****************** START OF NEW PART ****************** // ******************************************************* //************************************************************************* // Part IVb: 2D view for slicing axially //************************************************************************* // Create QmitkSliceWidget, which is based on the class // QmitkRenderWindow, but additionally provides sliders QmitkSliceWidget view2(&toplevelWidget); layout.addWidget(&view2); view2.SetLevelWindowEnabled(true); // Tell the QmitkSliceWidget which (part of) the tree to render. // By default, it slices the data axially view2.SetDataStorage(ds); // Get the image from the data storage. A predicate (mitk::NodePredicateBase) // is used to get only nodes of the type mitk::Image. mitk::DataStorage::SetOfObjects::ConstPointer rs = ds->GetSubset(mitk::TNodePredicateDataType::New()); view2.SetData(rs->Begin(),mitk::SliceNavigationController::Axial); // We want to see the position of the slice in 2D and the // slice itself in 3D: add it to the datastorage! ds->Add(view2.GetRenderer()->GetCurrentWorldGeometry2DNode()); //************************************************************************* // Part IVc: 2D view for slicing sagitally //************************************************************************* // Create QmitkSliceWidget, which is based on the class // QmitkRenderWindow, but additionally provides sliders QmitkSliceWidget view3(&toplevelWidget); layout.addWidget(&view3); view3.SetDataStorage(ds); // Tell the QmitkSliceWidget which (part of) the datastorage to render // and to slice sagitally view3.SetData(rs->Begin(), mitk::SliceNavigationController::Sagittal); // We want to see the position of the slice in 2D and the // slice itself in 3D: add it to the datastorage! ds->Add(view3.GetRenderer()->GetCurrentWorldGeometry2DNode()); // ******************************************************* // ******************* END OF NEW PART ******************* // ******************************************************* //************************************************************************* // Part V: Qt-specific initialization //************************************************************************* toplevelWidget.show(); // for testing #include "QtTesting.h" if(strcmp(argv[argc-1], "-testing")!=0) return qtapplication.exec(); else return QtTesting(); } /** \example Step4.cpp */ diff --git a/Examples/Tutorial/Step5/Step5.cpp b/Examples/Tutorial/Step5/Step5.cpp index 9d0fd14e36..d873d7672a 100644 --- a/Examples/Tutorial/Step5/Step5.cpp +++ b/Examples/Tutorial/Step5/Step5.cpp @@ -1,219 +1,209 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkRegisterClasses.h" #include "QmitkRenderWindow.h" #include "QmitkSliceWidget.h" -#include "mitkDataNodeFactory.h" #include "mitkProperties.h" #include "mitkRenderingManager.h" #include "mitkStandaloneDataStorage.h" #include "mitkPointSet.h" // NEW INCLUDE #include "mitkPointSetDataInteractor.h" #include #include #include +#include //##Documentation //## @brief Interactively add points //## //## As in Step4, load one or more data sets (many image, //## surface and other formats) and create 3 views on the data. //## Additionally, we want to interactively add points. A node containing //## a PointSet as data is added to the data tree and a PointSetDataInteractor //## is associated with the node, which handles the interaction. The //## @em interaction @em pattern is defined in a state-machine, stored in an //## external XML file. Thus, we need to load a state-machine //## The interaction patterns defines the @em events, //## on which the interactor reacts (e.g., which mouse buttons are used to //## set a point), the @em transition to the next state (e.g., the initial //## may be "empty point set") and associated @a actions (e.g., add a point //## at the position where the mouse-click occured). int main(int argc, char* argv[]) { QApplication qtapplication( argc, argv ); if(argc<2) { fprintf( stderr, "Usage: %s [filename1] [filename2] ...\n\n", itksys::SystemTools::GetFilenameName(argv[0]).c_str() ); return 1; } // Register Qmitk-dependent global instances QmitkRegisterClasses(); //************************************************************************* // Part I: Basic initialization //************************************************************************* // Create a DataStorage mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); //************************************************************************* // Part II: Create some data by reading files //************************************************************************* int i; for(i=1; iSetFileName(filename); - nodeReader->Update(); - //********************************************************************* - // Part III: Put the data into the datastorage - //********************************************************************* - - // Since the DataNodeFactory directly creates a node, - // use the iterator to add the read node to the tree - mitk::DataNode::Pointer node = nodeReader->GetOutput(); - ds->Add(node); - } - catch(...) + // Load datanode (eg. many image formats, surface formats, etc.) + mitk::StandaloneDataStorage::SetOfObjects* dataNodes = mitk::IOUtil::Load(argv[i],*ds); + + //********************************************************************* + // Part III: Put the data into the datastorage + //********************************************************************* + // Add the node to the DataStorage + if(dataNodes->empty()) { - fprintf( stderr, "Could not open file %s \n\n", filename ); + fprintf( stderr, "Could not open file %s \n\n", argv[i] ); exit(2); } } //************************************************************************* // Part V: Create windows and pass the tree to it //************************************************************************* // Create toplevel widget with horizontal layout QWidget toplevelWidget; QHBoxLayout layout; layout.setSpacing(2); layout.setMargin(0); toplevelWidget.setLayout(&layout); //************************************************************************* // Part Va: 3D view //************************************************************************* // Create a renderwindow QmitkRenderWindow renderWindow(&toplevelWidget); layout.addWidget(&renderWindow); // Tell the renderwindow which (part of) the tree to render renderWindow.GetRenderer()->SetDataStorage(ds); // Use it as a 3D view renderWindow.GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard3D); //************************************************************************* // Part Vb: 2D view for slicing axially //************************************************************************* // Create QmitkSliceWidget, which is based on the class // QmitkRenderWindow, but additionally provides sliders QmitkSliceWidget view2(&toplevelWidget); layout.addWidget(&view2); // Tell the QmitkSliceWidget which (part of) the tree to render. // By default, it slices the data axially view2.SetDataStorage(ds); mitk::DataStorage::SetOfObjects::ConstPointer rs = ds->GetAll(); view2.SetData(rs->Begin(), mitk::SliceNavigationController::Axial); // We want to see the position of the slice in 2D and the // slice itself in 3D: add it to the tree! ds->Add(view2.GetRenderer()->GetCurrentWorldGeometry2DNode()); //************************************************************************* // Part Vc: 2D view for slicing sagitally //************************************************************************* // Create QmitkSliceWidget, which is based on the class // QmitkRenderWindow, but additionally provides sliders QmitkSliceWidget view3(&toplevelWidget); layout.addWidget(&view3); // Tell the QmitkSliceWidget which (part of) the tree to render // and to slice sagitall view3.SetDataStorage(ds); view3.SetData(rs->Begin(), mitk::SliceNavigationController::Sagittal); // We want to see the position of the slice in 2D and the // slice itself in 3D: add it to the tree! ds->Add(view3.GetRenderer()->GetCurrentWorldGeometry2DNode()); // ******************************************************* // ****************** START OF NEW PART ****************** // ******************************************************* //************************************************************************* // Part VI: For allowing to interactively add points ... //************************************************************************* // ATTENTION: It is very important that the renderer already know their DataStorage, // because registerig DataInteractors with the render windows is done automatically // and only works if the BaseRenderer and the DataStorage know each other. // Create PointSet and a node for it mitk::PointSet::Pointer pointSet = mitk::PointSet::New(); mitk::DataNode::Pointer pointSetNode = mitk::DataNode::New(); // Store the point set in the DataNode pointSetNode->SetData(pointSet); // Add the node to the tree ds->Add(pointSetNode); // Create PointSetDataInteractor mitk::PointSetDataInteractor::Pointer interactor = mitk::PointSetDataInteractor::New(); // Set the StateMachine pattern that describes the flow of the interactions interactor->LoadStateMachine("PointSet.xml"); // Set the configuration file, which describes the user interactions that trigger actions // in this file SHIFT + LeftClick triggers add Point, but by modifying this file, // it could as well be changes to any other user interaction. interactor->SetEventConfig("PointSetConfig.xml"); // Assign the pointSetNode to the interactor, // alternatively one could also add the DataInteractor to the pointSetNode using the SetDataInteractor() method. interactor->SetDataNode(pointSetNode); // ******************************************************* // ******************* END OF NEW PART ******************* // ******************************************************* //************************************************************************* //Part VII: Qt-specific initialization //************************************************************************* toplevelWidget.show(); // For testing #include "QtTesting.h" if(strcmp(argv[argc-1], "-testing")!=0) return qtapplication.exec(); else return QtTesting(); } /** \example Step5.cpp */ diff --git a/Examples/Tutorial/Step6/Step6.cpp b/Examples/Tutorial/Step6/Step6.cpp index 0e8c17ea86..a89d418c73 100644 --- a/Examples/Tutorial/Step6/Step6.cpp +++ b/Examples/Tutorial/Step6/Step6.cpp @@ -1,251 +1,236 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "Step6.h" #include "QmitkRenderWindow.h" #include "QmitkSliceWidget.h" -#include "mitkDataNodeFactory.h" #include "mitkProperties.h" #include "mitkRenderingManager.h" #include "mitkPointSet.h" #include "mitkPointSetDataInteractor.h" #include "mitkImageAccessByItk.h" #include "mitkRenderingManager.h" +#include #include #include #include #include #include #include //##Documentation //## @brief Start region-grower at interactively added points Step6::Step6(int argc, char* argv[], QWidget *parent) : QWidget(parent) { // load data as in the previous steps; a reference to the first loaded // image is kept in the member m_FirstImage and used as input for the // region growing Load(argc, argv); } void Step6::Initialize() { // setup the widgets as in the previous steps, but with an additional // QVBox for a button to start the segmentation this->SetupWidgets(); // Create controlsParent widget with horizontal layout QWidget *controlsParent = new QWidget(this); this->layout()->addWidget(controlsParent); QHBoxLayout* hlayout = new QHBoxLayout(controlsParent); hlayout->setSpacing(2); QLabel *labelThresholdMin = new QLabel("Lower Threshold:", controlsParent); hlayout->addWidget(labelThresholdMin); m_LineEditThresholdMin = new QLineEdit("-1000", controlsParent); hlayout->addWidget(m_LineEditThresholdMin); QLabel *labelThresholdMax = new QLabel("Upper Threshold:", controlsParent); hlayout->addWidget(labelThresholdMax); m_LineEditThresholdMax = new QLineEdit("-400", controlsParent); hlayout->addWidget(m_LineEditThresholdMax); // create button to start the segmentation and connect its clicked() // signal to method StartRegionGrowing QPushButton* startButton = new QPushButton("start region growing", controlsParent); hlayout->addWidget(startButton); connect(startButton, SIGNAL(clicked()), this, SLOT(StartRegionGrowing())); if (m_FirstImage.IsNull()) startButton->setEnabled(false); // as in Step5, create PointSet (now as a member m_Seeds) and // associate a interactor to it m_Seeds = mitk::PointSet::New(); mitk::DataNode::Pointer pointSetNode = mitk::DataNode::New(); pointSetNode->SetData(m_Seeds); pointSetNode->SetProperty("layer", mitk::IntProperty::New(2)); m_DataStorage->Add(pointSetNode); // Create PointSetDataInteractor mitk::PointSetDataInteractor::Pointer interactor = mitk::PointSetDataInteractor::New(); interactor->LoadStateMachine("PointSet.xml"); interactor->SetEventConfig("PointSetConfig.xml"); interactor->SetDataNode(pointSetNode); } int Step6::GetThresholdMin() { return m_LineEditThresholdMin->text().toInt(); } int Step6::GetThresholdMax() { return m_LineEditThresholdMax->text().toInt(); } void Step6::StartRegionGrowing() { AccessByItk_1(m_FirstImage, RegionGrowing, this); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void Step6::Load(int argc, char* argv[]) { //************************************************************************* // Part I: Basic initialization //************************************************************************* m_DataStorage = mitk::StandaloneDataStorage::New(); //************************************************************************* // Part II: Create some data by reading files //************************************************************************* int i; for (i = 1; i < argc; ++i) { // For testing if (strcmp(argv[i], "-testing") == 0) continue; - // Create a DataNodeFactory to read a data format supported - // by the DataNodeFactory (many image formats, surface formats, etc.) - mitk::DataNodeFactory::Pointer nodeReader = - mitk::DataNodeFactory::New(); - const char * filename = argv[i]; - try - { - nodeReader->SetFileName(filename); - nodeReader->Update(); - //********************************************************************* - // Part III: Put the data into the datastorage - //********************************************************************* - - // Since the DataNodeFactory directly creates a node, - // use the iterator to add the read node to the tree - mitk::DataNode::Pointer node = nodeReader->GetOutput(); - m_DataStorage->Add(node); - - mitk::Image::Pointer image = - dynamic_cast (node->GetData()); - if ((m_FirstImage.IsNull()) && (image.IsNotNull())) - m_FirstImage = image; - } catch (...) + // Load datanode (eg. many image formats, surface formats, etc.) + mitk::StandaloneDataStorage::SetOfObjects* dataNodes = mitk::IOUtil::Load(argv[i],*m_DataStorage); + + if(dataNodes->empty()) { - fprintf(stderr, "Could not open file %s \n\n", filename); + fprintf( stderr, "Could not open file %s \n\n", argv[i] ); exit(2); } + + mitk::Image::Pointer image = dynamic_cast (dataNodes->at(0)->GetData()); + if ((m_FirstImage.IsNull()) && (image.IsNotNull())) + m_FirstImage = image; } } void Step6::SetupWidgets() { //************************************************************************* // Part I: Create windows and pass the datastorage to it //************************************************************************* // Create toplevel widget with vertical layout QVBoxLayout* vlayout = new QVBoxLayout(this); vlayout->setMargin(0); vlayout->setSpacing(2); // Create viewParent widget with horizontal layout QWidget* viewParent = new QWidget(this); vlayout->addWidget(viewParent); QHBoxLayout* hlayout = new QHBoxLayout(viewParent); hlayout->setMargin(0); hlayout->setSpacing(2); //************************************************************************* // Part Ia: 3D view //************************************************************************* // Create a renderwindow QmitkRenderWindow* renderWindow = new QmitkRenderWindow(viewParent); hlayout->addWidget(renderWindow); // Tell the renderwindow which (part of) the tree to render renderWindow->GetRenderer()->SetDataStorage(m_DataStorage); // Use it as a 3D view renderWindow->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard3D); //************************************************************************* // Part Ib: 2D view for slicing axially //************************************************************************* // Create QmitkSliceWidget, which is based on the class // QmitkRenderWindow, but additionally provides sliders QmitkSliceWidget *view2 = new QmitkSliceWidget(viewParent); hlayout->addWidget(view2); // Tell the QmitkSliceWidget which (part of) the tree to render. // By default, it slices the data axially view2->SetDataStorage(m_DataStorage); mitk::DataStorage::SetOfObjects::ConstPointer rs = m_DataStorage->GetAll(); view2->SetData(rs->Begin(), mitk::SliceNavigationController::Axial); // We want to see the position of the slice in 2D and the // slice itself in 3D: add it to the tree! m_DataStorage->Add(view2->GetRenderer()->GetCurrentWorldGeometry2DNode()); //************************************************************************* // Part Ic: 2D view for slicing sagitally //************************************************************************* // Create QmitkSliceWidget, which is based on the class // QmitkRenderWindow, but additionally provides sliders QmitkSliceWidget *view3 = new QmitkSliceWidget(viewParent); hlayout->addWidget(view3); // Tell the QmitkSliceWidget which (part of) the tree to render // and to slice sagitally view3->SetDataStorage(m_DataStorage); view3->SetData(rs->Begin(), mitk::SliceNavigationController::Sagittal); // We want to see the position of the slice in 2D and the // slice itself in 3D: add it to the tree! m_DataStorage->Add(view3->GetRenderer()->GetCurrentWorldGeometry2DNode()); //************************************************************************* // Part II: handle updates: To avoid unnecessary updates, we have to //************************************************************************* // define when to update. The RenderingManager serves this purpose, and // each RenderWindow has to be registered to it. /*mitk::RenderingManager *renderingManager = mitk::RenderingManager::GetInstance(); renderingManager->AddRenderWindow( renderWindow ); renderingManager->AddRenderWindow( view2->GetRenderWindow() ); renderingManager->AddRenderWindow( view3->GetRenderWindow() );*/ } /** \example Step6.cpp */ diff --git a/Modules/AlgorithmsExt/src/mitkUnstructuredGridToUnstructuredGridFilter.cpp b/Modules/AlgorithmsExt/src/mitkUnstructuredGridToUnstructuredGridFilter.cpp index d842c90524..f8f7ab0df9 100644 --- a/Modules/AlgorithmsExt/src/mitkUnstructuredGridToUnstructuredGridFilter.cpp +++ b/Modules/AlgorithmsExt/src/mitkUnstructuredGridToUnstructuredGridFilter.cpp @@ -1,90 +1,89 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include mitk::UnstructuredGridToUnstructuredGridFilter::UnstructuredGridToUnstructuredGridFilter() { this->m_UnstructGrid = mitk::UnstructuredGrid::New(); } mitk::UnstructuredGridToUnstructuredGridFilter::~UnstructuredGridToUnstructuredGridFilter(){} void mitk::UnstructuredGridToUnstructuredGridFilter::SetInput(const mitk::UnstructuredGrid* grid) { this->ProcessObject::SetNthInput(0, const_cast< mitk::UnstructuredGrid* >( grid ) ); } void mitk::UnstructuredGridToUnstructuredGridFilter::CreateOutputsForAllInputs(unsigned int /*idx*/) { this->SetNumberOfIndexedOutputs( this->GetNumberOfIndexedInputs() ); for (unsigned int idx = 0; idx < this->GetNumberOfIndexedInputs(); ++idx) { if (this->GetOutput(idx) == NULL) { - DataObjectPointer newOutput = this->MakeOutput(idx); - this->SetNthOutput(idx, newOutput); + mitk::UnstructuredGrid::Pointer newOutputX = mitk::UnstructuredGrid::New(); + this->SetNthOutput(idx, newOutputX); } - this->GetOutput( idx )->Graft( this->GetInput( idx) ); } this->Modified(); } void mitk::UnstructuredGridToUnstructuredGridFilter::SetInput(unsigned int idx, const mitk::UnstructuredGrid* grid ) { if ( this->GetInput(idx) != grid ) { this->SetNthInput( idx, const_cast( grid ) ); this->CreateOutputsForAllInputs(idx); this->Modified(); } } const mitk::UnstructuredGrid* mitk::UnstructuredGridToUnstructuredGridFilter::GetInput(void) { if (this->GetNumberOfInputs() < 1) return NULL; return static_cast( this->ProcessObject::GetInput(0) ); } const mitk::UnstructuredGrid* mitk::UnstructuredGridToUnstructuredGridFilter::GetInput( unsigned int idx) { if (this->GetNumberOfInputs() < 1) return NULL; return static_cast(this->ProcessObject::GetInput(idx)); } void mitk::UnstructuredGridToUnstructuredGridFilter::GenerateOutputInformation() { mitk::UnstructuredGrid::ConstPointer inputImage = this->GetInput(); m_UnstructGrid = this->GetOutput(); itkDebugMacro(<<"GenerateOutputInformation()"); if(inputImage.IsNull()) return; } diff --git a/Modules/Core/include/mitkAbstractFileIO.h b/Modules/Core/include/mitkAbstractFileIO.h index bf6efd20a0..4484124ddc 100644 --- a/Modules/Core/include/mitkAbstractFileIO.h +++ b/Modules/Core/include/mitkAbstractFileIO.h @@ -1,197 +1,184 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKABSTRACTFILEIO_H #define MITKABSTRACTFILEIO_H #include "mitkAbstractFileReader.h" #include "mitkAbstractFileWriter.h" namespace mitk { #ifndef DOXYGEN_SKIP // Skip this code during Doxygen processing, because it only // exists to resolve name clashes when inheriting from both // AbstractFileReader and AbstractFileWriter. class AbstractFileIOReader : public AbstractFileReader { public: virtual ConfidenceLevel GetReaderConfidenceLevel() const { return AbstractFileReader::GetConfidenceLevel(); } virtual ConfidenceLevel GetConfidenceLevel() const { return this->GetReaderConfidenceLevel(); } protected: AbstractFileIOReader() {} AbstractFileIOReader(const CustomMimeType& mimeType, const std::string& description) : AbstractFileReader(mimeType, description) {} private: virtual IFileReader* ReaderClone() const = 0; IFileReader* Clone() const { return ReaderClone(); } }; struct AbstractFileIOWriter : public AbstractFileWriter { virtual ConfidenceLevel GetWriterConfidenceLevel() const { return AbstractFileWriter::GetConfidenceLevel(); } virtual ConfidenceLevel GetConfidenceLevel() const { return this->GetWriterConfidenceLevel(); } protected: AbstractFileIOWriter(const std::string& baseDataType) : AbstractFileWriter(baseDataType) {} AbstractFileIOWriter(const std::string& baseDataType, const CustomMimeType& mimeType, const std::string& description) : AbstractFileWriter(baseDataType, mimeType, description) {} private: virtual IFileWriter* WriterClone() const = 0; IFileWriter* Clone() const { return WriterClone(); } }; #endif // DOXYGEN_SKIP /** * @ingroup IO * * @brief Abstract class for implementing a reader and writer. */ class MITKCORE_EXPORT AbstractFileIO : public AbstractFileIOReader, public AbstractFileIOWriter { public: Options GetReaderOptions() const; us::Any GetReaderOption(const std::string &name) const; void SetReaderOptions(const Options& options); void SetReaderOption(const std::string& name, const us::Any& value); Options GetWriterOptions() const; us::Any GetWriterOption(const std::string &name) const; void SetWriterOptions(const Options& options); void SetWriterOption(const std::string& name, const us::Any& value); virtual ConfidenceLevel GetReaderConfidenceLevel() const; virtual ConfidenceLevel GetWriterConfidenceLevel() const; - std::pair, us::ServiceRegistration > + std::pair, us::ServiceRegistration > RegisterService(us::ModuleContext* context = us::GetModuleContext()); protected: AbstractFileIO(const AbstractFileIO& other); AbstractFileIO(const std::string& baseDataType); /** * Associate this reader instance with the given MIME type. * - * @param mimeType The mime type this reader can read. + * If the given MIME type has nothing but its name set, the according MIME type + * is looked up in the service registry. + * + * @param mimeType The MIME type this reader can read. * @param description A human readable description of this reader. * * @throws std::invalid_argument if \c mimeType is empty. * * @see RegisterService */ explicit AbstractFileIO(const std::string& baseDataType, const CustomMimeType& mimeType, const std::string& description); - /** - * Associate this reader with the given file extension. - * - * Additonal file extensions can be added by sub-classes by calling AddExtension - * or SetExtensions on the CustomMimeType object returned by GetMimeType() and - * setting the modified object again via SetMimeType(). - * - * @param extension The file extension (without a leading period) for which a registered - * mime-type object is looked up and associated with this instance. - * @param description A human readable description of this reader. - * - * @see RegisterService - */ - explicit AbstractFileIO(const std::string& baseDataType, const std::string& extension, - const std::string& description); - void SetMimeType(const CustomMimeType& mimeType); /** * @return The mime-type this reader can handle. */ const CustomMimeType* GetMimeType() const; void SetReaderDescription(const std::string& description); std::string GetReaderDescription() const; void SetWriterDescription(const std::string& description); std::string GetWriterDescription() const; void SetDefaultReaderOptions(const Options& defaultOptions); Options GetDefaultReaderOptions() const; void SetDefaultWriterOptions(const Options& defaultOptions); Options GetDefaultWriterOptions() const; /** * \brief Set the service ranking for this file reader. * * Default is zero and should only be chosen differently for a reason. * The ranking is used to determine which reader to use if several * equivalent readers have been found. * It may be used to replace a default reader from MITK in your own project. * E.g. if you want to use your own reader for nrrd files instead of the default, * implement it and give it a higher ranking than zero. */ void SetReaderRanking(int ranking); int GetReaderRanking() const; void SetWriterRanking(int ranking); int GetWriterRanking() const; private: AbstractFileIO& operator=(const AbstractFileIO& other); virtual AbstractFileIO* IOClone() const = 0; virtual IFileReader* ReaderClone() const; virtual IFileWriter* WriterClone() const; }; } #endif // MITKABSTRACTFILEIO_H diff --git a/Modules/Core/include/mitkIOUtil.h b/Modules/Core/include/mitkIOUtil.h index 3632727dc3..3d2af44cee 100644 --- a/Modules/Core/include/mitkIOUtil.h +++ b/Modules/Core/include/mitkIOUtil.h @@ -1,450 +1,462 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKIOUTIL_H #define MITKIOUTIL_H #include #include #include #include #include #include #include #include #include #include +namespace us{class ModuleResource;} + namespace mitk { + /** * \ingroup IO * * \brief A utility class to load and save data from/to the local file system. * * The methods LoadImage, LoadSurface, and LoadPointSet are convenience methods for general loading of * the three main data types in MITK. They all use the more generic method Load(). * * \see QmitkIOUtil */ class MITKCORE_EXPORT IOUtil { public: struct MITKCORE_EXPORT LoadInfo { LoadInfo(const std::string& path); std::string m_Path; std::vector m_Output; FileReaderSelector m_ReaderSelector; bool m_Cancel; }; struct MITKCORE_EXPORT SaveInfo { SaveInfo(const BaseData* baseData, const MimeType& mimeType, const std::string& path); bool operator<(const SaveInfo& other) const; /// The BaseData object to save. const BaseData* m_BaseData; /// Contains a set of IFileWriter objects. FileWriterSelector m_WriterSelector; /// The selected mime-type, used to restrict results from FileWriterSelector. MimeType m_MimeType; /// The path to write the BaseData object to. std::string m_Path; /// Flag indicating if sub-sequent save operations are to be canceled. bool m_Cancel; }; /** * Get the file system path where the running executable is located. * * @return The location of the currently running executable, without the filename. */ static std::string GetProgramPath(); /** * Get the default temporary path. * * @return The default path for temporary data. */ static std::string GetTempPath(); /** * Returns the Directory Seperator for the current OS. * * @return the Directory Seperator for the current OS, i.e. "\\" for Windows and "/" otherwise. */ static char GetDirectorySeparator(); /** * Create and open a temporary file. * * This method generates a unique temporary filename from \c templateName, creates * and opens the file using the output stream \c tmpStream and returns the name of * the newly create file. * * The \c templateName argument must contain six consective 'X' characters ("XXXXXX") * and these are replaced with a string that makes the filename unique. * * The file is created with read and write permissions for owner only. * * @param tmpStream The output stream for writing to the temporary file. * @param templateName An optional template for the filename. * @param path An optional path where the temporary file should be created. Defaults * to the default temp path as returned by GetTempPath(). * @return The filename of the created temporary file. * * @throw mitk::Exception if the temporary file could not be created. */ static std::string CreateTemporaryFile(std::ofstream& tmpStream, const std::string& templateName = "XXXXXX", std::string path = std::string()); /** * Create and open a temporary file. * * This method generates a unique temporary filename from \c templateName, creates * and opens the file using the output stream \c tmpStream and the specified open * mode \c mode and returns the name of the newly create file. The open mode is always * OR'd with \begin{code}std::ios_base::out | std::ios_base::trunc\end{code}. * * The \c templateName argument must contain six consective 'X' characters ("XXXXXX") * and these are replaced with a string that makes the filename unique. * * The file is created with read and write permissions for owner only. * * @param tmpStream The output stream for writing to the temporary file. * @param mode The open mode for the temporary file stream. * @param templateName An optional template for the filename. * @param path An optional path where the temporary file should be created. Defaults * to the default temp path as returned by GetTempPath(). * @return The filename of the created temporary file. * * @throw mitk::Exception if the temporary file could not be created. */ static std::string CreateTemporaryFile(std::ofstream& tmpStream, std::ios_base::openmode mode, const std::string& templateName = "XXXXXX", std::string path = std::string()); /** * Creates an empty temporary file. * * This method generates a unique temporary filename from \c templateName and creates * this file. * * The file is created with read and write permissions for owner only. * * --- * This version is potentially unsafe because the created temporary file is not kept open * and could be used by another process between calling this method and opening the returned * file path for reading or writing. * --- * * @return The filename of the created temporary file. * @param templateName An optional template for the filename. * @param path An optional path where the temporary file should be created. Defaults * to the default temp path as returned by GetTempPath(). * @throw mitk::Exception if the temporary file could not be created. */ static std::string CreateTemporaryFile(const std::string& templateName = "XXXXXX", std::string path = std::string()); /** * Create a temporary directory. * * This method generates a uniquely named temporary directory from \c templateName. * The last set of six consecutive 'X' characters in \c templateName is replaced * with a string that makes the directory name unique. * * The directory is created with read, write and executable permissions for owner only. * * @param templateName An optional template for the directory name. * @param path An optional path where the temporary directory should be created. Defaults * to the default temp path as returned by GetTempPath(). * @return The filename of the created temporary file. * * @throw mitk::Exception if the temporary directory could not be created. */ static std::string CreateTemporaryDirectory(const std::string& templateName = "XXXXXX", std::string path = std::string()); /** * @brief Load a file into the given DataStorage. * * This method calls Load(const std::vector&, DataStorage&) with a * one-element vector. * * @param path The absolute file name including the file extension. * @param storage A DataStorage object to which the loaded data will be added. * @return The set of added DataNode objects. * @throws mitk::Exception if \c path could not be loaded. * * @sa Load(const std::vector&, DataStorage&) */ static DataStorage::SetOfObjects::Pointer Load(const std::string& path, DataStorage& storage); static DataStorage::SetOfObjects::Pointer Load(const std::string& path, const IFileReader::Options& options, DataStorage& storage); static std::vector Load(const std::string& path); static std::vector Load(const std::string& path, const IFileReader::Options& options); /** * @brief Loads a list of file paths into the given DataStorage. * * If an entry in \c paths cannot be loaded, this method will continue to load * the remaining entries into \c storage and throw an exception afterwards. * * @param paths A list of absolute file names including the file extension. * @param storage A DataStorage object to which the loaded data will be added. * @return The set of added DataNode objects. * @throws mitk::Exception if an entry in \c paths could not be loaded. */ static DataStorage::SetOfObjects::Pointer Load(const std::vector& paths, DataStorage& storage); static std::vector Load(const std::vector& paths); /** * Load files in fileNames and add the constructed mitk::DataNode instances * to the mitk::DataStorage storage * * @param fileNames A list (vector) of absolute file name paths. * @param storage The data storage to which the constructed data nodes are added. * @return The number of added mitk::DataNode instances. * * @deprecatedSince{2014_10} Use Load() instead */ DEPRECATED(static int LoadFiles(const std::vector&fileNames, DataStorage& storage)); /** * This method will create a new mitk::DataStorage instance and pass it to * LoadFiles(std::vector,DataStorage). * * @param fileNames A list (vector) of absolute file name paths. * @return The new mitk::DataStorage containing the constructed data nodes. * * @see LoadFiles(std::vector,DataStorage) * * @deprecatedSince{2014_10} Use Load() instead */ DEPRECATED(static DataStorage::Pointer LoadFiles(const std::vector& fileNames)); /** * @brief Create a BaseData object from the given file. * @param path The path to the file including file name and file extension. * @throws mitk::Exception In case of an error when reading the file. * @return Returns the created BaseData object. * * @deprecatedSince{2014_10} Use Load() or FileReaderRegistry::Read() instead. */ DEPRECATED(static mitk::BaseData::Pointer LoadBaseData(const std::string& path)); /** * @brief LoadDataNode Method to load an arbitrary DataNode. * @param path The path to the file including file name and file extension. * @throws mitk::Exception This exception is thrown when the DataNodeFactory is not able to read/find the file * or the DataNode is NULL. * @return Returns the DataNode. * * @deprecatedSince{2014_10} Use Load() instead. */ DEPRECATED(static mitk::DataNode::Pointer LoadDataNode(const std::string& path)); /** * @brief LoadImage Convenience method to load an arbitrary mitkImage. * @param path The path to the image including file name and file extension. * @throws mitk::Exception This exception is thrown when the Image is NULL. * @return Returns the mitkImage. */ static mitk::Image::Pointer LoadImage(const std::string& path); /** * @brief LoadSurface Convenience method to load an arbitrary mitkSurface. * @param path The path to the surface including file name and file extension. * @throws mitk::Exception This exception is thrown when the Surface is NULL. * @return Returns the mitkSurface. */ static mitk::Surface::Pointer LoadSurface(const std::string& path); /** * @brief LoadPointSet Convenience method to load an arbitrary mitkPointSet. * @param path The path to the pointset including file name and file extension (currently, only .mps is supported). * @throws mitk::Exception This exception is thrown when the PointSet is NULL. * @return Returns the mitkPointSet. */ static mitk::PointSet::Pointer LoadPointSet(const std::string& path); + /** + * @brief Loads the contents of a us::ModuleResource and returns the corresponding mitk::BaseData + * @param usResource a ModuleResource, representing a BaseData object + * @param mode Optional parameter to set the openmode of the stream + * @return The set of loaded BaseData objects. \c Should contain either one or zero elements, since a resource stream + * respresents one object. + * @throws mitk::Exception if no reader was found for the stream. + */ + static std::vector Load(const us::ModuleResource& usResource, std::ios_base::openmode mode = std::ios_base::in); /** * @brief Save a mitk::BaseData instance. * @param data The data to save. * @param path The path to the image including file name and and optional file extension. * If no extension is set, the default extension and mime-type for the * BaseData type of \c data is used. * @throws mitk::Exception if no writer for \c data is available or the writer * is not able to write the image. */ static void Save(const mitk::BaseData* data, const std::string& path); /** * @brief Save a mitk::BaseData instance. * @param data The data to save. * @param path The path to the image including file name and an optional file extension. * If no extension is set, the default extension and mime-type for the * BaseData type of \c data is used. * @param options The IFileWriter options to use for the selected writer. * @throws mitk::Exception if no writer for \c data is available or the writer * is not able to write the image. */ static void Save(const mitk::BaseData* data, const std::string& path, const IFileWriter::Options& options); /** * @brief Save a mitk::BaseData instance. * @param data The data to save. * @param mimeType The mime-type to use for writing \c data. * @param path The path to the image including file name and an optional file extension. * @param addExtension If \c true, an extension according to the given \c mimeType * is added to \c path if it does not contain one. If \c path already contains * a file name extension, it is not checked for compatibility with \c mimeType. * * @throws mitk::Exception if no writer for the combination of \c data and \c mimeType is * available or the writer is not able to write the image. */ static void Save(const mitk::BaseData* data, const std::string& mimeType, const std::string& path, bool addExtension = true); /** * @brief Save a mitk::BaseData instance. * @param data The data to save. * @param mimeType The mime-type to use for writing \c data. * @param path The path to the image including file name and an optional file extension. * @param options Configuration data for the used IFileWriter instance. * @param addExtension If \c true, an extension according to the given \c mimeType * is added to \c path if it does not contain one. If \c path already contains * a file name extension, it is not checked for compatibility with \c mimeType. * * @throws mitk::Exception if no writer for the combination of \c data and \c mimeType is * available or the writer is not able to write the image. */ static void Save(const mitk::BaseData* data, const std::string& mimeType, const std::string& path, const mitk::IFileWriter::Options& options, bool addExtension = true); /** * @brief Use SaveInfo objects to save BaseData instances. * * This is a low-level method for directly working with SaveInfo objects. Usually, * the Save() methods taking a BaseData object as an argument are more appropriate. * * @param saveInfos A list of SaveInfo objects for saving contained BaseData objects. * * @see Save(const mitk::BaseData*, const std::string&) */ static void Save(std::vector& saveInfos); /** * @brief SaveImage Convenience method to save an arbitrary mitkImage. * @param path The path to the image including file name and file extension. * If no extention is set, the default value (defined in DEFAULTIMAGEEXTENSION) is used. * @param image The image to save. * @throws mitk::Exception This exception is thrown when the writer is not able to write the image. * @return Returns true for success else false. * * @deprecatedSince{2014_10} Use Save() instead. */ DEPRECATED(static bool SaveImage(mitk::Image::Pointer image, const std::string& path)); /** * @brief SaveBaseData Convenience method to save arbitrary baseData. * @param path The path to the image including file name and file extension. * If no extention is set, the default extension is used. * @param data The data to save. * @throws mitk::Exception This exception is thrown when the writer is not able to write the image. * @return Returns true for success else false. * * @deprecatedSince{2014_10} Use Save() instead. */ DEPRECATED(static bool SaveBaseData(mitk::BaseData* data, const std::string& path)); /** * @brief SaveSurface Convenience method to save an arbitrary mitkSurface. * @param path The path to the surface including file name and file extension. * If no extention is set, the default extension is used. * @throws mitk::Exception This exception is thrown when the writer is not able to write the surface. * or if the fileextension is not suitable for writing. * @return Returns true for success else false. * * @deprecatedSince{2014_10} Use Save() instead. */ DEPRECATED(static bool SaveSurface(mitk::Surface::Pointer surface, const std::string& path)); /** * @brief SavePointSet Convenience method to save an mitkPointSet. * @param path The path to the pointset including file name and file extension. * If no extention is set, the default extension is used. * @throws mitk::Exception This exception is thrown when the writer is not able to write the pointset. * @return Returns true for success else false. * * @deprecatedSince{2014_10} Use Save() instead. */ DEPRECATED(static bool SavePointSet(mitk::PointSet::Pointer pointset, const std::string& path)); /** @deprecatedSince{2014_10} */ DEPRECATED(static const std::string DEFAULTIMAGEEXTENSION); /** @deprecatedSince{2014_10} */ DEPRECATED(static const std::string DEFAULTSURFACEEXTENSION); /** @deprecatedSince{2014_10} */ DEPRECATED(static const std::string DEFAULTPOINTSETEXTENSION); protected: struct ReaderOptionsFunctorBase { virtual bool operator()(LoadInfo& loadInfo) = 0; }; struct WriterOptionsFunctorBase { virtual bool operator()(SaveInfo& saveInfo) = 0; }; static std::string Load(std::vector& loadInfos, DataStorage::SetOfObjects* nodeResult, DataStorage* ds, ReaderOptionsFunctorBase* optionsCallback); static std::string Save(const BaseData* data, const std::string& mimeType, const std::string& path, WriterOptionsFunctorBase* optionsCallback, bool addExtension); static std::string Save(std::vector& saveInfos, WriterOptionsFunctorBase* optionsCallback); private: struct Impl; }; } #endif // MITKIOUTIL_H diff --git a/Modules/Core/src/IO/mitkItkImageIO.h b/Modules/Core/include/mitkItkImageIO.h similarity index 75% rename from Modules/Core/src/IO/mitkItkImageIO.h rename to Modules/Core/include/mitkItkImageIO.h index ef49973990..1fa0fe293f 100644 --- a/Modules/Core/src/IO/mitkItkImageIO.h +++ b/Modules/Core/include/mitkItkImageIO.h @@ -1,62 +1,70 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKITKFILEIO_H #define MITKITKFILEIO_H #include "mitkAbstractFileIO.h" #include namespace mitk { -// This class wraps ITK image IO objects registered via the -// ITK object factory system -class ItkImageIO : public AbstractFileIO +/** + * This class wraps ITK image IO objects as mitk::IFileReader and + * mitk::IFileWriter objects. + * + * Instantiating this class with a given itk::ImageIOBase instance + * will register corresponding MITK reader/writer services for that + * ITK ImageIO object. + */ +class MITKCORE_EXPORT ItkImageIO : public AbstractFileIO { public: ItkImageIO(itk::ImageIOBase::Pointer imageIO); ItkImageIO(const CustomMimeType& mimeType, itk::ImageIOBase::Pointer imageIO, int rank); // -------------- AbstractFileReader ------------- using AbstractFileReader::Read; virtual std::vector > Read(); virtual ConfidenceLevel GetReaderConfidenceLevel() const; // -------------- AbstractFileWriter ------------- virtual void Write(); virtual ConfidenceLevel GetWriterConfidenceLevel() const; +protected: + + virtual std::vector FixUpImageIOExtensions(const std::string& imageIOName); + private: ItkImageIO(const ItkImageIO& other); ItkImageIO* IOClone() const; - std::vector FixUpImageIOExtensions(const std::string& imageIOName); - itk::ImageIOBase::Pointer m_ImageIO; }; } // namespace mitk #endif /* MITKITKFILEIO_H */ diff --git a/Modules/Core/include/mitkMimeType.h b/Modules/Core/include/mitkMimeType.h index 592d04a44a..e7613139de 100644 --- a/Modules/Core/include/mitkMimeType.h +++ b/Modules/Core/include/mitkMimeType.h @@ -1,88 +1,90 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKMIMETYPE_H #define MITKMIMETYPE_H #include #include #include #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4251) #endif namespace mitk { class CustomMimeType; /** * @ingroup IO * * @brief The MimeType class represens a registered mime-type. * * MimeType instances support the MITK I/O system and represent mime-types * for data formats. */ class MITKCORE_EXPORT MimeType { public: MimeType(); MimeType(const MimeType& other); MimeType(const CustomMimeType& x, int rank, long id); ~MimeType(); MimeType& operator=(const MimeType& other); bool operator==(const MimeType& other) const; bool operator<(const MimeType& other) const; std::string GetName() const; std::string GetCategory() const; std::vector GetExtensions() const; std::string GetComment() const; + std::string GetFilenameWithoutExtension(const std::string& path) const; + bool AppliesTo(const std::string& path) const; bool IsValid() const; void Swap(MimeType& m); private: struct Impl; // Use C++11 shared_ptr instead us::SharedDataPointer m_Data; }; void swap(MimeType& m1, MimeType& m2); std::ostream& operator<<(std::ostream& os, const MimeType& mimeType); } #ifdef _MSC_VER #pragma warning(pop) #endif #endif // MITKMIMETYPE_H diff --git a/Modules/Core/include/mitkSurface.h b/Modules/Core/include/mitkSurface.h index 154440be80..b91d7a0a06 100644 --- a/Modules/Core/include/mitkSurface.h +++ b/Modules/Core/include/mitkSurface.h @@ -1,136 +1,137 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkSurface_h #define mitkSurface_h #include "mitkBaseData.h" #include "itkImageRegion.h" +#include class vtkPolyData; namespace mitk { /** * \brief Class for storing surfaces (vtkPolyData). * \ingroup Data */ class MITKCORE_EXPORT Surface : public BaseData { public: typedef itk::ImageRegion<5> RegionType; mitkClassMacro(Surface, BaseData); itkFactorylessNewMacro(Self) itkCloneMacro(Self) void CalculateBoundingBox(); virtual void CopyInformation(const itk::DataObject *data); virtual void ExecuteOperation(Operation *operation); virtual void Expand( unsigned int timeSteps = 1 ); const RegionType& GetLargestPossibleRegion() const; virtual const RegionType& GetRequestedRegion() const; unsigned int GetSizeOfPolyDataSeries() const; virtual vtkPolyData* GetVtkPolyData(unsigned int t = 0) const; virtual void Graft( const DataObject* data ); virtual bool IsEmptyTimeStep(unsigned int t) const; virtual void PrintSelf( std::ostream& os, itk::Indent indent ) const; virtual bool RequestedRegionIsOutsideOfTheBufferedRegion(); virtual void SetRequestedRegion(const itk::DataObject *data); virtual void SetRequestedRegion(Surface::RegionType *region); virtual void SetRequestedRegionToLargestPossibleRegion(); virtual void SetVtkPolyData(vtkPolyData* polydata, unsigned int t = 0); virtual void Swap(Surface& other); virtual void Update(); virtual void UpdateOutputInformation(); virtual bool VerifyRequestedRegion(); protected: mitkCloneMacro(Self); Surface(); virtual ~Surface(); Surface(const Surface& other); Surface& operator=(Surface other); virtual void ClearData(); virtual void InitializeEmpty(); private: - std::vector m_PolyDatas; + std::vector< vtkSmartPointer > m_PolyDatas; mutable RegionType m_LargestPossibleRegion; mutable RegionType m_RequestedRegion; bool m_CalculateBoundingBox; }; /** * @brief Equal Compare two surfaces for equality, returns true if found equal. * @warning This method is deprecated and will not be available in the future. Use the \a bool mitk::Equal(const mitk::Surface& s1, const mitk::Surface& s2) instead * @ingroup MITKTestingAPI * @param rightHandSide Surface to compare. * @param leftHandSide Surface to compare. * @param eps Epsilon to use for floating point comparison. Most of the time mitk::eps will be sufficient. * @param verbose Flag indicating if the method should give a detailed console output. * @return True if every comparison is true, false in any other case. */ DEPRECATED( MITKCORE_EXPORT bool Equal( mitk::Surface* leftHandSide, mitk::Surface* rightHandSide, mitk::ScalarType eps, bool verbose)); /** * @brief Equal Compare two surfaces for equality, returns true if found equal. * @ingroup MITKTestingAPI * @param rightHandSide Surface to compare. * @param leftHandSide Surface to compare. * @param eps Epsilon to use for floating point comparison. Most of the time mitk::eps will be sufficient. * @param verbose Flag indicating if the method should give a detailed console output. * @return True if every comparison is true, false in any other case. */ MITKCORE_EXPORT bool Equal( mitk::Surface& leftHandSide, mitk::Surface& rightHandSide, mitk::ScalarType eps, bool verbose); /** * @brief Equal Compare two vtk PolyDatas for equality, returns true if found equal. * @warning This method is deprecated and will not be available in the future. Use the \a bool mitk::Equal(const vtkPolyData& p1, const vtkPolyData& p2) instead * @ingroup MITKTestingAPI * @param rightHandSide Surface to compare. * @param leftHandSide Surface to compare. * @param eps Epsilon to use for floating point comparison. Most of the time mitk::eps will be sufficient. * @param verbose Flag indicating if the method should give a detailed console output. * @return True if every comparison is true, false in any other case. * * This will only check if the number of cells, vertices, polygons, stripes and lines is the same and whether * all the two poly datas have the same number of points with the same coordinates. It is not checked whether * all points are correctly connected. */ DEPRECATED( MITKCORE_EXPORT bool Equal( vtkPolyData* leftHandSide, vtkPolyData* rightHandSide, mitk::ScalarType eps, bool verbose)); /** * @brief Equal Compare two vtk PolyDatas for equality, returns true if found equal. * @ingroup MITKTestingAPI * @param rightHandSide Surface to compare. * @param leftHandSide Surface to compare. * @param eps Epsilon to use for floating point comparison. Most of the time mitk::eps will be sufficient. * @param verbose Flag indicating if the method should give a detailed console output. * @return True if every comparison is true, false in any other case. * * This will only check if the number of cells, vertices, polygons, stripes and lines is the same and whether * all the two poly datas have the same number of points with the same coordinates. It is not checked whether * all points are correctly connected. */ MITKCORE_EXPORT bool Equal( vtkPolyData& leftHandSide, vtkPolyData& rightHandSide, mitk::ScalarType eps, bool verbose); } #endif diff --git a/Modules/Core/include/mitkSurfaceToSurfaceFilter.h b/Modules/Core/include/mitkSurfaceToSurfaceFilter.h index 32a8ef2a94..612d2fabb6 100644 --- a/Modules/Core/include/mitkSurfaceToSurfaceFilter.h +++ b/Modules/Core/include/mitkSurfaceToSurfaceFilter.h @@ -1,68 +1,85 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKSURFACETOSURFACEFILTER_H_HEADER_INCLUDED_C10B4740 #define MITKSURFACETOSURFACEFILTER_H_HEADER_INCLUDED_C10B4740 #include "mitkSurfaceSource.h" namespace mitk { class Surface; //##Documentation //## @brief Superclass of all classes getting surfaces (instances of class //## Surface) as input and generating surfaces as output. //## //## In itk and vtk the generated result of a ProcessObject is only guaranteed //## to be up-to-date, when Update() of the ProcessObject or the generated //## DataObject is called immediately before access of the data stored in the //## DataObject. This is also true for subclasses of mitk::BaseProcess and thus //## for mitk::mitkSurfaceToSurfaceFilter. //## @ingroup Process class MITKCORE_EXPORT SurfaceToSurfaceFilter : public mitk::SurfaceSource { public: mitkClassMacro(SurfaceToSurfaceFilter, mitk::SurfaceSource); itkFactorylessNewMacro(Self) itkCloneMacro(Self) typedef itk::DataObject::Pointer DataObjectPointer; using itk::ProcessObject::SetInput; virtual void SetInput( const mitk::Surface* surface ); + /** + * @brief Add a new input at the given index (idx) + * Calls mitk::Surface::CreateOutputForInput(idx) + * @note The inputs must be added sequentially + * @param idx the index of the input, which must be incremental + * @param surface the input which should be added + */ virtual void SetInput( unsigned int idx, const mitk::Surface* surface ); virtual const mitk::Surface* GetInput(); virtual const mitk::Surface* GetInput( unsigned int idx ); - virtual void CreateOutputsForAllInputs(unsigned int idx); + /** + * @brief Create a new output for the input at idx + * @param idx the index of the input for which the output should be created + */ + virtual void CreateOutputForInput(unsigned int idx); + + /** + * @brief Creates outputs for all existing inputs + * @note For each existing input a new output will be allocated + */ + virtual void CreateOutputsForAllInputs(); virtual void RemoveInputs( mitk::Surface* surface ); protected: SurfaceToSurfaceFilter(); virtual ~SurfaceToSurfaceFilter(); }; } // namespace mitk #endif /* MITKSURFACETOSURFACEFILTER_H_HEADER_INCLUDED_C10B4740 */ diff --git a/Modules/Core/src/Algorithms/mitkSurfaceToSurfaceFilter.cpp b/Modules/Core/src/Algorithms/mitkSurfaceToSurfaceFilter.cpp index bb3b59670a..5c8ec14b9d 100644 --- a/Modules/Core/src/Algorithms/mitkSurfaceToSurfaceFilter.cpp +++ b/Modules/Core/src/Algorithms/mitkSurfaceToSurfaceFilter.cpp @@ -1,90 +1,108 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSurfaceToSurfaceFilter.h" #include "mitkSurface.h" mitk::SurfaceToSurfaceFilter::SurfaceToSurfaceFilter() : SurfaceSource() { } mitk::SurfaceToSurfaceFilter::~SurfaceToSurfaceFilter() { } void mitk::SurfaceToSurfaceFilter::SetInput( const mitk::Surface* surface ) { this->SetInput( 0, const_cast( surface ) ); } void mitk::SurfaceToSurfaceFilter::SetInput( unsigned int idx, const mitk::Surface* surface ) { if ( this->GetInput(idx) != surface ) { this->SetNthInput( idx, const_cast( surface ) ); - this->CreateOutputsForAllInputs(idx); + this->CreateOutputForInput(idx); this->Modified(); } } const mitk::Surface* mitk::SurfaceToSurfaceFilter::GetInput() { if (this->GetNumberOfInputs() < 1) return NULL; return static_cast(this->ProcessObject::GetInput(0)); } const mitk::Surface* mitk::SurfaceToSurfaceFilter::GetInput( unsigned int idx) { if (this->GetNumberOfInputs() < 1) return NULL; return static_cast(this->ProcessObject::GetInput(idx)); } +void mitk::SurfaceToSurfaceFilter::CreateOutputForInput(unsigned int idx) +{ + if (this->GetNumberOfIndexedInputs() < idx || this->GetInput(idx) == NULL) + { + mitkThrow() << "Error creating output for input [" <GetNumberOfIndexedOutputs() <= idx) + this->SetNumberOfIndexedOutputs( idx+1 ); + + if (this->GetOutput(idx) == NULL) + { + DataObjectPointer newOutput = this->MakeOutput(idx); + this->SetNthOutput(idx, newOutput); + } + this->GetOutput( idx )->Graft( this->GetInput( idx) ); + this->Modified(); +} -void mitk::SurfaceToSurfaceFilter::CreateOutputsForAllInputs(unsigned int /*idx*/) +void mitk::SurfaceToSurfaceFilter::CreateOutputsForAllInputs() { this->SetNumberOfIndexedOutputs( this->GetNumberOfIndexedInputs() ); for (unsigned int idx = 0; idx < this->GetNumberOfIndexedInputs(); ++idx) { if (this->GetOutput(idx) == NULL) { DataObjectPointer newOutput = this->MakeOutput(idx); this->SetNthOutput(idx, newOutput); } this->GetOutput( idx )->Graft( this->GetInput( idx) ); } this->Modified(); } void mitk::SurfaceToSurfaceFilter::RemoveInputs( mitk::Surface* surface ) { for (unsigned int idx = 0; idx < this->GetNumberOfIndexedInputs(); ++idx) { if ( this->GetInput(idx) == surface ) { this->RemoveOutput(idx); } } } diff --git a/Modules/Core/src/DataManagement/mitkSurface.cpp b/Modules/Core/src/DataManagement/mitkSurface.cpp index 843c587744..c4144396ef 100644 --- a/Modules/Core/src/DataManagement/mitkSurface.cpp +++ b/Modules/Core/src/DataManagement/mitkSurface.cpp @@ -1,529 +1,518 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSurface.h" #include "mitkInteractionConst.h" #include "mitkSurfaceOperation.h" #include #include -static vtkPolyData* DeepCopy(vtkPolyData* other) +static vtkSmartPointer DeepCopy(vtkPolyData* other) { if (other == NULL) return NULL; - vtkPolyData* copy = vtkPolyData::New(); + vtkSmartPointer copy = vtkSmartPointer::New(); copy->DeepCopy(other); return copy; } -static void Delete(vtkPolyData* polyData) -{ - if (polyData != NULL) - polyData->Delete(); -} - static void Update(vtkPolyData* /*polyData*/) { // if (polyData != NULL) // polyData->Update(); //VTK6_TODO vtk pipeline } mitk::Surface::Surface() : m_CalculateBoundingBox(false) { this->InitializeEmpty(); } mitk::Surface::Surface(const mitk::Surface& other) : BaseData(other), m_LargestPossibleRegion(other.m_LargestPossibleRegion), m_RequestedRegion(other.m_RequestedRegion), m_CalculateBoundingBox(other.m_CalculateBoundingBox) { if(!other.m_PolyDatas.empty()) { m_PolyDatas.resize(other.m_PolyDatas.size()); std::transform(other.m_PolyDatas.begin(), other.m_PolyDatas.end(), m_PolyDatas.begin(), DeepCopy); } else { this->InitializeEmpty(); } } void mitk::Surface::Swap(mitk::Surface& other) { std::swap(m_PolyDatas, other.m_PolyDatas); std::swap(m_LargestPossibleRegion, other.m_LargestPossibleRegion); std::swap(m_RequestedRegion, other.m_RequestedRegion); std::swap(m_CalculateBoundingBox, other.m_CalculateBoundingBox); } mitk::Surface& mitk::Surface::operator=(Surface other) { this->Swap(other); return *this; } mitk::Surface::~Surface() { this->ClearData(); } void mitk::Surface::ClearData() { - using ::Delete; - - std::for_each(m_PolyDatas.begin(), m_PolyDatas.end(), Delete); m_PolyDatas.clear(); Superclass::ClearData(); } const mitk::Surface::RegionType& mitk::Surface::GetLargestPossibleRegion() const { m_LargestPossibleRegion.SetIndex(3, 0); m_LargestPossibleRegion.SetSize(3, GetTimeGeometry()->CountTimeSteps()); return m_LargestPossibleRegion; } const mitk::Surface::RegionType& mitk::Surface::GetRequestedRegion() const { return m_RequestedRegion; } void mitk::Surface::InitializeEmpty() { if (!m_PolyDatas.empty()) this->ClearData(); Superclass::InitializeTimeGeometry(); m_PolyDatas.push_back(NULL); m_Initialized = true; } void mitk::Surface::SetVtkPolyData(vtkPolyData* polyData, unsigned int t) { this->Expand(t + 1); if (m_PolyDatas[t] != NULL) { - if (m_PolyDatas[t] == polyData) + if (m_PolyDatas[t].GetPointer() == polyData) return; - - m_PolyDatas[t]->Delete(); } - m_PolyDatas[t] = polyData; + m_PolyDatas[t].TakeReference(polyData); if(polyData != NULL) polyData->Register(NULL); m_CalculateBoundingBox = true; this->Modified(); this->UpdateOutputInformation(); } bool mitk::Surface::IsEmptyTimeStep(unsigned int t) const { if(!IsInitialized()) return false; vtkPolyData* polyData = const_cast(this)->GetVtkPolyData(t); return polyData == NULL || ( polyData->GetNumberOfLines() == 0 && polyData->GetNumberOfPolys() == 0 && polyData->GetNumberOfStrips() == 0 && polyData->GetNumberOfVerts() == 0 ); } vtkPolyData* mitk::Surface::GetVtkPolyData(unsigned int t) const { if (t < m_PolyDatas.size()) { if(m_PolyDatas[t] == NULL && this->GetSource().IsNotNull()) { RegionType requestedRegion; requestedRegion.SetIndex(3, t); requestedRegion.SetSize(3, 1); this->m_RequestedRegion = requestedRegion; this->GetSource()->Update(); } - return m_PolyDatas[t]; + return m_PolyDatas[t].GetPointer(); } return NULL; } void mitk::Surface::UpdateOutputInformation() { if (this->GetSource().IsNotNull()) this->GetSource()->UpdateOutputInformation(); if (m_CalculateBoundingBox == true && !m_PolyDatas.empty()) this->CalculateBoundingBox(); else this->GetTimeGeometry()->Update(); } void mitk::Surface::CalculateBoundingBox() { TimeGeometry* timeGeometry = this->GetTimeGeometry(); if (timeGeometry->CountTimeSteps() != m_PolyDatas.size()) mitkThrow() << "Number of geometry time steps is inconsistent with number of poly data pointers."; for (unsigned int i = 0; i < m_PolyDatas.size(); ++i) { - vtkPolyData* polyData = m_PolyDatas[i]; + vtkPolyData* polyData = m_PolyDatas[i].GetPointer(); double bounds[6] = {0}; if (polyData != NULL && polyData->GetNumberOfPoints() > 0) { // polyData->Update(); //VTK6_TODO vtk pipeline polyData->ComputeBounds(); polyData->GetBounds(bounds); } BaseGeometry::Pointer geometry = timeGeometry->GetGeometryForTimeStep(i); if (geometry.IsNull()) mitkThrow() << "Time-sliced geometry is invalid (equals NULL)."; geometry->SetFloatBounds(bounds); } timeGeometry->Update(); m_CalculateBoundingBox = false; } void mitk::Surface::SetRequestedRegionToLargestPossibleRegion() { m_RequestedRegion = GetLargestPossibleRegion(); } bool mitk::Surface::RequestedRegionIsOutsideOfTheBufferedRegion() { RegionType::IndexValueType end = m_RequestedRegion.GetIndex(3) + m_RequestedRegion.GetSize(3); if(static_cast(m_PolyDatas.size()) < end) return true; for(RegionType::IndexValueType t = m_RequestedRegion.GetIndex(3); t < end; ++t) { if(m_PolyDatas[t] == NULL) return true; } return false; } bool mitk::Surface::VerifyRequestedRegion() { if(m_RequestedRegion.GetIndex(3) >= 0 && m_RequestedRegion.GetIndex(3) + m_RequestedRegion.GetSize(3) <= m_PolyDatas.size()) return true; return false; } void mitk::Surface::SetRequestedRegion(const itk::DataObject* data ) { const mitk::Surface *surface = dynamic_cast(data); if (surface != NULL) m_RequestedRegion = surface->GetRequestedRegion(); else mitkThrow() << "Data object used to get requested region is not a mitk::Surface."; } void mitk::Surface::SetRequestedRegion(Surface::RegionType* region) { if (region == NULL) mitkThrow() << "Requested region is invalid (equals NULL)"; m_RequestedRegion = *region; } void mitk::Surface::CopyInformation(const itk::DataObject* data) { Superclass::CopyInformation(data); const mitk::Surface* surface = dynamic_cast(data); if (surface == NULL) mitkThrow() << "Data object used to get largest possible region is not a mitk::Surface."; m_LargestPossibleRegion = surface->GetLargestPossibleRegion(); } void mitk::Surface::Update() { using ::Update; if (this->GetSource().IsNull()) std::for_each(m_PolyDatas.begin(), m_PolyDatas.end(), Update); Superclass::Update(); } void mitk::Surface::Expand(unsigned int timeSteps) { if (timeSteps > m_PolyDatas.size()) { Superclass::Expand(timeSteps); m_PolyDatas.resize(timeSteps); m_CalculateBoundingBox = true; } } void mitk::Surface::ExecuteOperation(Operation* operation) { switch (operation->GetOperationType()) { case OpSURFACECHANGED: { mitk::SurfaceOperation* surfaceOperation = dynamic_cast(operation); if(surfaceOperation == NULL) break; unsigned int timeStep = surfaceOperation->GetTimeStep(); if(m_PolyDatas[timeStep] != NULL) { vtkPolyData* updatedPolyData = surfaceOperation->GetVtkPolyData(); if(updatedPolyData != NULL) { this->SetVtkPolyData(updatedPolyData, timeStep); this->CalculateBoundingBox(); this->Modified(); } } break; } default: return; } } unsigned int mitk::Surface::GetSizeOfPolyDataSeries() const { return m_PolyDatas.size(); } void mitk::Surface::Graft(const DataObject* data) { const Surface* surface = dynamic_cast(data); if(surface == NULL) mitkThrow() << "Data object used to graft surface is not a mitk::Surface."; this->CopyInformation(data); m_PolyDatas.clear(); for (unsigned int i = 0; i < surface->GetSizeOfPolyDataSeries(); ++i) { - m_PolyDatas.push_back(vtkPolyData::New()); + m_PolyDatas.push_back(vtkSmartPointer::New()); m_PolyDatas.back()->DeepCopy(const_cast(surface)->GetVtkPolyData(i)); } } void mitk::Surface::PrintSelf(std::ostream& os, itk::Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "\nNumber PolyDatas: " << m_PolyDatas.size() << "\n"; unsigned int count = 0; - for (std::vector::const_iterator it = m_PolyDatas.begin(); it != m_PolyDatas.end(); ++it) + for (std::vector >::const_iterator it = m_PolyDatas.begin(); it != m_PolyDatas.end(); ++it) { os << "\n"; if(*it != NULL) { os << indent << "PolyData at time step " << count << ":\n"; os << indent << "Number of cells: " << (*it)->GetNumberOfCells() << "\n"; os << indent << "Number of points: " << (*it)->GetNumberOfPoints() << "\n\n"; os << indent << "VTKPolyData:\n"; (*it)->Print(os); } else { os << indent << "Empty PolyData at time step " << count << "\n"; } ++count; } } bool mitk::Equal( vtkPolyData* leftHandSide, vtkPolyData* rightHandSide, mitk::ScalarType eps, bool verbose ) { if(( leftHandSide == NULL ) || ( rightHandSide == NULL )) { MITK_ERROR << "mitk::Equal( vtkPolyData* leftHandSide, vtkPolyData* rightHandSide, mitk::ScalarType eps, bool verbose ) does not work for NULL pointer input."; return false; } return Equal( *leftHandSide, *rightHandSide, eps, verbose); } bool mitk::Equal( vtkPolyData& leftHandSide, vtkPolyData& rightHandSide, mitk::ScalarType eps, bool verbose ) { bool noDifferenceFound = true; if( ! mitk::Equal( leftHandSide.GetNumberOfCells(), rightHandSide.GetNumberOfCells(), eps, verbose ) ) { if(verbose) MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of cells not equal"; noDifferenceFound = false; } if( ! mitk::Equal( leftHandSide.GetNumberOfVerts(), rightHandSide.GetNumberOfVerts(), eps, verbose )) { if(verbose) MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of vertices not equal"; noDifferenceFound = false; } if( ! mitk::Equal( leftHandSide.GetNumberOfLines(), rightHandSide.GetNumberOfLines(), eps, verbose ) ) { if(verbose) MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of lines not equal"; noDifferenceFound = false; } if( ! mitk::Equal( leftHandSide.GetNumberOfPolys(), rightHandSide.GetNumberOfPolys(), eps, verbose ) ) { if(verbose) MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of polys not equal"; noDifferenceFound = false; } if( ! mitk::Equal( leftHandSide.GetNumberOfStrips(), rightHandSide.GetNumberOfStrips(), eps, verbose ) ) { if(verbose) MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of strips not equal"; noDifferenceFound = false; } { unsigned int numberOfPointsRight = rightHandSide.GetPoints()->GetNumberOfPoints(); unsigned int numberOfPointsLeft = leftHandSide.GetPoints()->GetNumberOfPoints(); if(! mitk::Equal( numberOfPointsLeft, numberOfPointsRight, eps, verbose )) { if(verbose) MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of points not equal"; noDifferenceFound = false; } else { for( unsigned int i( 0 ); i < numberOfPointsRight; i++ ) { bool pointFound = false; double pointOne[3]; rightHandSide.GetPoints()->GetPoint(i, pointOne); for( unsigned int j( 0 ); j < numberOfPointsLeft; j++ ) { double pointTwo[3]; leftHandSide.GetPoints()->GetPoint(j, pointTwo); double x = pointOne[0] - pointTwo[0]; double y = pointOne[1] - pointTwo[1]; double z = pointOne[2] - pointTwo[2]; double distance = x*x + y*y + z*z; if( distance < eps ) { pointFound = true; break; } } if( !pointFound ) { if(verbose) { MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Right hand side point with id " << i << " and coordinates ( " << std::setprecision(12) << pointOne[0] << " ; " << pointOne[1] << " ; " << pointOne[2] << " ) could not be found in left hand side with epsilon " << eps << "."; } noDifferenceFound = false; break; } } } } return noDifferenceFound; } bool mitk::Equal( mitk::Surface* leftHandSide, mitk::Surface* rightHandSide, mitk::ScalarType eps, bool verbose ) { if(( leftHandSide == NULL ) || ( rightHandSide == NULL )) { MITK_ERROR << "mitk::Equal( mitk::Surface* leftHandSide, mitk::Surface* rightHandSide, mitk::ScalarType eps, bool verbose ) does not work with NULL pointer input."; return false; } return Equal( *leftHandSide, *rightHandSide, eps, verbose); } bool mitk::Equal( mitk::Surface& leftHandSide, mitk::Surface& rightHandSide, mitk::ScalarType eps, bool verbose ) { bool noDifferenceFound = true; if( ! mitk::Equal( leftHandSide.GetSizeOfPolyDataSeries(), rightHandSide.GetSizeOfPolyDataSeries(), eps, verbose ) ) { if(verbose) MITK_INFO << "[Equal( mitk::surface&, mitk::surface& )] Size of PolyData series not equal."; return false; } // No mitk::Equal for TimeGeometry implemented. //if( ! mitk::Equal( leftHandSide->GetTimeGeometry(), rightHandSide->GetTimeGeometry(), eps, verbose ) ) //{ // if(verbose) // MITK_INFO << "[Equal( mitk::surface&, mitk::surface& )] Time sliced geometries not equal"; // noDifferenceFound = false; //} for( unsigned int i( 0 ); i < rightHandSide.GetSizeOfPolyDataSeries(); i++ ) { if( ! mitk::Equal( *leftHandSide.GetVtkPolyData( i ), *rightHandSide.GetVtkPolyData( i ), eps, verbose ) ) { if(verbose) MITK_INFO << "[Equal( mitk::surface&, mitk::surface& )] Poly datas not equal."; noDifferenceFound = false; } } return noDifferenceFound; } diff --git a/Modules/Core/src/IO/mitkAbstractFileIO.cpp b/Modules/Core/src/IO/mitkAbstractFileIO.cpp index 4fd52a6613..ef205ea960 100644 --- a/Modules/Core/src/IO/mitkAbstractFileIO.cpp +++ b/Modules/Core/src/IO/mitkAbstractFileIO.cpp @@ -1,194 +1,194 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkAbstractFileIO.h" #include "mitkCustomMimeType.h" namespace mitk { AbstractFileIO::Options AbstractFileIO::GetReaderOptions() const { return AbstractFileReader::GetOptions(); } us::Any AbstractFileIO::GetReaderOption(const std::string& name) const { return AbstractFileReader::GetOption(name); } void AbstractFileIO::SetReaderOptions(const AbstractFileIO::Options& options) { AbstractFileReader::SetOptions(options); } void AbstractFileIO::SetReaderOption(const std::string& name, const us::Any& value) { AbstractFileReader::SetOption(name, value); } AbstractFileIO::Options AbstractFileIO::GetWriterOptions() const { return AbstractFileWriter::GetOptions(); } us::Any AbstractFileIO::GetWriterOption(const std::string& name) const { return AbstractFileWriter::GetOption(name); } void AbstractFileIO::SetWriterOptions(const AbstractFileIO::Options& options) { AbstractFileWriter::SetOptions(options); } void AbstractFileIO::SetWriterOption(const std::string& name, const us::Any& value) { AbstractFileWriter::SetOption(name, value); } IFileIO::ConfidenceLevel AbstractFileIO::GetReaderConfidenceLevel() const { return AbstractFileIOReader::GetReaderConfidenceLevel(); } IFileIO::ConfidenceLevel AbstractFileIO::GetWriterConfidenceLevel() const { return AbstractFileIOWriter::GetWriterConfidenceLevel(); } -std::pair, us::ServiceRegistration > +std::pair, us::ServiceRegistration > AbstractFileIO::RegisterService(us::ModuleContext* context) { - std::pair, us::ServiceRegistration > result; + std::pair, us::ServiceRegistration > result; result.first = this->AbstractFileReader::RegisterService(context); const CustomMimeType* writerMimeType = this->AbstractFileWriter::GetMimeType(); if (writerMimeType == NULL || (writerMimeType->GetName().empty() && writerMimeType->GetExtensions().empty())) { this->AbstractFileWriter::SetMimeType(CustomMimeType(this->AbstractFileReader::GetRegisteredMimeType().GetName())); } result.second = this->AbstractFileWriter::RegisterService(context); return result; } AbstractFileIO::AbstractFileIO(const AbstractFileIO& other) : AbstractFileIOReader(other) , AbstractFileIOWriter(other) { } AbstractFileIO::AbstractFileIO(const std::string& baseDataType) : AbstractFileIOReader() , AbstractFileIOWriter(baseDataType) { } AbstractFileIO::AbstractFileIO(const std::string& baseDataType, const CustomMimeType& mimeType, const std::string& description) : AbstractFileIOReader(mimeType, description) , AbstractFileIOWriter(baseDataType, CustomMimeType(mimeType.GetName()), description) { } void AbstractFileIO::SetMimeType(const CustomMimeType& mimeType) { this->AbstractFileReader::SetMimeType(mimeType); this->AbstractFileWriter::SetMimeType(CustomMimeType(mimeType.GetName())); } const CustomMimeType* AbstractFileIO::GetMimeType() const { const CustomMimeType* mimeType = this->AbstractFileReader::GetMimeType(); if (mimeType->GetName() != this->AbstractFileWriter::GetMimeType()->GetName()) { MITK_WARN << "Reader and writer mime-tpyes are different, using the mime-type from IFileReader"; } return mimeType; } void AbstractFileIO::SetReaderDescription(const std::string& description) { this->AbstractFileReader::SetDescription(description); } std::string AbstractFileIO::GetReaderDescription() const { return this->AbstractFileReader::GetDescription(); } void AbstractFileIO::SetWriterDescription(const std::string& description) { this->AbstractFileWriter::SetDescription(description); } std::string AbstractFileIO::GetWriterDescription() const { return this->AbstractFileWriter::GetDescription(); } void AbstractFileIO::SetDefaultReaderOptions(const AbstractFileIO::Options& defaultOptions) { this->AbstractFileReader::SetDefaultOptions(defaultOptions); } AbstractFileIO::Options AbstractFileIO::GetDefaultReaderOptions() const { return this->AbstractFileReader::GetDefaultOptions(); } void AbstractFileIO::SetDefaultWriterOptions(const AbstractFileIO::Options& defaultOptions) { this->AbstractFileWriter::SetDefaultOptions(defaultOptions); } AbstractFileIO::Options AbstractFileIO::GetDefaultWriterOptions() const { return this->AbstractFileWriter::GetDefaultOptions(); } void AbstractFileIO::SetReaderRanking(int ranking) { this->AbstractFileReader::SetRanking(ranking); } int AbstractFileIO::GetReaderRanking() const { return this->AbstractFileReader::GetRanking(); } void AbstractFileIO::SetWriterRanking(int ranking) { this->AbstractFileWriter::SetRanking(ranking); } int AbstractFileIO::GetWriterRanking() const { return this->AbstractFileWriter::GetRanking(); } IFileReader* AbstractFileIO::ReaderClone() const { return this->IOClone(); } IFileWriter* AbstractFileIO::WriterClone() const { return this->IOClone(); } } diff --git a/Modules/Core/src/IO/mitkAbstractFileReader.cpp b/Modules/Core/src/IO/mitkAbstractFileReader.cpp index 31cc02d446..5bedb1b4d0 100644 --- a/Modules/Core/src/IO/mitkAbstractFileReader.cpp +++ b/Modules/Core/src/IO/mitkAbstractFileReader.cpp @@ -1,414 +1,414 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include namespace mitk { AbstractFileReader::InputStream::InputStream(IFileReader* reader, std::ios_base::openmode mode) : std::istream(NULL) , m_Stream(NULL) { std::istream* stream = reader->GetInputStream(); if (stream) { this->init(stream->rdbuf()); } else { m_Stream = new std::ifstream(reader->GetInputLocation().c_str(), mode); this->init(m_Stream->rdbuf()); } } AbstractFileReader::InputStream::~InputStream() { delete m_Stream; } class AbstractFileReader::Impl : public FileReaderWriterBase { public: Impl() : FileReaderWriterBase() , m_Stream(NULL) , m_PrototypeFactory(NULL) {} Impl(const Impl& other) : FileReaderWriterBase(other) , m_Stream(NULL) , m_PrototypeFactory(NULL) {} std::string m_Location; std::string m_TmpFile; std::istream* m_Stream; us::PrototypeServiceFactory* m_PrototypeFactory; us::ServiceRegistration m_Reg; }; AbstractFileReader::AbstractFileReader() : d(new Impl) { } AbstractFileReader::~AbstractFileReader() { UnregisterService(); delete d->m_PrototypeFactory; if (!d->m_TmpFile.empty()) { std::remove(d->m_TmpFile.c_str()); } } AbstractFileReader::AbstractFileReader(const AbstractFileReader& other) : IFileReader(), d(new Impl(*other.d.get())) { } AbstractFileReader::AbstractFileReader(const CustomMimeType& mimeType, const std::string& description) : d(new Impl) { d->SetMimeType(mimeType); d->SetDescription(description); } ////////////////////// Reading ///////////////////////// std::vector AbstractFileReader::Read() { std::vector result; DataStorage::Pointer ds = StandaloneDataStorage::New().GetPointer(); this->Read(*ds); DataStorage::SetOfObjects::ConstPointer dataNodes = ds->GetAll(); for (DataStorage::SetOfObjects::ConstIterator iter = dataNodes->Begin(), iterEnd = dataNodes->End(); iter != iterEnd; ++iter) { result.push_back(iter.Value()->GetData()); } return result; } DataStorage::SetOfObjects::Pointer AbstractFileReader::Read(DataStorage& ds) { DataStorage::SetOfObjects::Pointer result = DataStorage::SetOfObjects::New(); std::vector data = this->Read(); for (std::vector::iterator iter = data.begin(); iter != data.end(); ++iter) { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(*iter); this->SetDefaultDataNodeProperties(node, this->GetInputLocation()); ds.Add(node); result->InsertElement(result->Size(), node); } return result; } IFileReader::ConfidenceLevel AbstractFileReader::GetConfidenceLevel() const { if (d->m_Stream) { if (*d->m_Stream) return Supported; } else { if (itksys::SystemTools::FileExists(this->GetInputLocation().c_str(), true)) { return Supported; } } return Unsupported; } //////////// µS Registration & Properties ////////////// us::ServiceRegistration AbstractFileReader::RegisterService(us::ModuleContext* context) { if (d->m_PrototypeFactory) return us::ServiceRegistration(); if(context == NULL) { context = us::GetModuleContext(); } d->RegisterMimeType(context); if (this->GetMimeType()->GetName().empty()) { MITK_WARN << "Not registering reader due to empty MIME type."; return us::ServiceRegistration(); } struct PrototypeFactory : public us::PrototypeServiceFactory { AbstractFileReader* const m_Prototype; PrototypeFactory(AbstractFileReader* prototype) : m_Prototype(prototype) {} us::InterfaceMap GetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/) { return us::MakeInterfaceMap(m_Prototype->Clone()); } void UngetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/, const us::InterfaceMap& service) { delete us::ExtractInterface(service); } }; d->m_PrototypeFactory = new PrototypeFactory(this); us::ServiceProperties props = this->GetServiceProperties(); d->m_Reg = context->RegisterService(d->m_PrototypeFactory, props); return d->m_Reg; } void AbstractFileReader::UnregisterService() { try { d->m_Reg.Unregister(); } catch (const std::exception&) {} } us::ServiceProperties AbstractFileReader::GetServiceProperties() const { us::ServiceProperties result; result[IFileReader::PROP_DESCRIPTION()] = this->GetDescription(); result[IFileReader::PROP_MIMETYPE()] = this->GetMimeType()->GetName(); result[us::ServiceConstants::SERVICE_RANKING()] = this->GetRanking(); return result; } us::ServiceRegistration AbstractFileReader::RegisterMimeType(us::ModuleContext* context) { return d->RegisterMimeType(context); } void AbstractFileReader::SetMimeType(const CustomMimeType& mimeType) { d->SetMimeType(mimeType); } void AbstractFileReader::SetDescription(const std::string& description) { d->SetDescription(description); } void AbstractFileReader::SetRanking(int ranking) { d->SetRanking(ranking); } int AbstractFileReader::GetRanking() const { return d->GetRanking(); } std::string AbstractFileReader::GetLocalFileName() const { std::string localFileName; if (d->m_Stream) { if (d->m_TmpFile.empty()) { // write the stream contents to temporary file std::string ext = itksys::SystemTools::GetFilenameExtension(this->GetInputLocation()); std::ofstream tmpStream; localFileName = mitk::IOUtil::CreateTemporaryFile(tmpStream, std::ios_base::out | std::ios_base::trunc | std::ios_base::binary, "XXXXXX" + ext); tmpStream << d->m_Stream->rdbuf(); d->m_TmpFile = localFileName; } else { localFileName = d->m_TmpFile; } } else { localFileName = d->m_Location; } return localFileName; } //////////////////////// Options /////////////////////// void AbstractFileReader::SetDefaultOptions(const IFileReader::Options& defaultOptions) { d->SetDefaultOptions(defaultOptions); } IFileReader::Options AbstractFileReader::GetDefaultOptions() const { return d->GetDefaultOptions(); } void AbstractFileReader::SetInput(const std::string& location) { d->m_Location = location; d->m_Stream = NULL; } void AbstractFileReader::SetInput(const std::string& location, std::istream* is) { if (d->m_Stream != is && !d->m_TmpFile.empty()) { std::remove(d->m_TmpFile.c_str()); d->m_TmpFile.clear(); } d->m_Location = location; d->m_Stream = is; } std::string AbstractFileReader::GetInputLocation() const { return d->m_Location; } std::istream*AbstractFileReader::GetInputStream() const { return d->m_Stream; } MimeType AbstractFileReader::GetRegisteredMimeType() const { return d->GetRegisteredMimeType(); } IFileReader::Options AbstractFileReader::GetOptions() const { return d->GetOptions(); } us::Any AbstractFileReader::GetOption(const std::string& name) const { return d->GetOption(name); } void AbstractFileReader::SetOptions(const Options& options) { d->SetOptions(options); } void AbstractFileReader::SetOption(const std::string& name, const us::Any& value) { d->SetOption(name, value); } ////////////////// MISC ////////////////// void AbstractFileReader::AddProgressCallback(const ProgressCallback& callback) { d->AddProgressCallback(callback); } void AbstractFileReader::RemoveProgressCallback(const ProgressCallback& callback) { d->RemoveProgressCallback(callback); } ////////////////// µS related Getters ////////////////// const CustomMimeType* AbstractFileReader::GetMimeType() const { return d->GetMimeType(); } void AbstractFileReader::SetMimeTypePrefix(const std::string& prefix) { d->SetMimeTypePrefix(prefix); } std::string AbstractFileReader::GetMimeTypePrefix() const { return d->GetMimeTypePrefix(); } std::string AbstractFileReader::GetDescription() const { return d->GetDescription(); } void AbstractFileReader::SetDefaultDataNodeProperties(DataNode* node, const std::string& filePath) { // path if (!filePath.empty()) { mitk::StringProperty::Pointer pathProp = mitk::StringProperty::New( itksys::SystemTools::GetFilenamePath(filePath) ); node->SetProperty(StringProperty::PATH, pathProp); } // name already defined? mitk::StringProperty::Pointer nameProp = dynamic_cast(node->GetProperty("name")); if(nameProp.IsNull() || (strcmp(nameProp->GetValue(),"No Name!")==0)) { // name already defined in BaseData mitk::StringProperty::Pointer baseDataNameProp = dynamic_cast(node->GetData()->GetProperty("name").GetPointer() ); if(baseDataNameProp.IsNull() || (strcmp(baseDataNameProp->GetValue(),"No Name!")==0)) { // name neither defined in node, nor in BaseData -> name = filebasename; - nameProp = mitk::StringProperty::New( this->GetMimeType()->GetFilenameWithoutExtension(filePath) ); + nameProp = mitk::StringProperty::New( this->GetRegisteredMimeType().GetFilenameWithoutExtension(filePath) ); node->SetProperty("name", nameProp); } else { // name defined in BaseData! nameProp = mitk::StringProperty::New(baseDataNameProp->GetValue()); node->SetProperty("name", nameProp); } } // visibility if(!node->GetProperty("visible")) { node->SetVisibility(true); } } } diff --git a/Modules/Core/src/IO/mitkIOMimeTypes.cpp b/Modules/Core/src/IO/mitkIOMimeTypes.cpp index df0e75c388..79f8654c06 100644 --- a/Modules/Core/src/IO/mitkIOMimeTypes.cpp +++ b/Modules/Core/src/IO/mitkIOMimeTypes.cpp @@ -1,280 +1,280 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkIOMimeTypes.h" #include "mitkCustomMimeType.h" #include "itkGDCMImageIO.h" namespace mitk { IOMimeTypes::DicomMimeType::DicomMimeType() : CustomMimeType(DICOM_MIMETYPE_NAME()) { this->AddExtension("gdcm"); this->AddExtension("dcm"); this->AddExtension("DCM"); this->AddExtension("dc3"); this->AddExtension("DC3"); this->AddExtension("ima"); this->AddExtension("img"); this->SetCategory(CATEGORY_IMAGES()); this->SetComment("DICOM"); } bool IOMimeTypes::DicomMimeType::AppliesTo(const std::string &path) const { if (CustomMimeType::AppliesTo(path)) return true; // Ask the GDCM ImageIO class directly itk::GDCMImageIO::Pointer gdcmIO = itk::GDCMImageIO::New(); return gdcmIO->CanReadFile(path.c_str()); } IOMimeTypes::DicomMimeType* IOMimeTypes::DicomMimeType::Clone() const { return new DicomMimeType(*this); } std::vector IOMimeTypes::Get() { std::vector mimeTypes; // order matters here (descending rank for mime types) mimeTypes.push_back(NRRD_MIMETYPE().Clone()); mimeTypes.push_back(NIFTI_MIMETYPE().Clone()); mimeTypes.push_back(VTK_IMAGE_MIMETYPE().Clone()); mimeTypes.push_back(VTK_PARALLEL_IMAGE_MIMETYPE().Clone()); mimeTypes.push_back(VTK_IMAGE_LEGACY_MIMETYPE().Clone()); mimeTypes.push_back(DICOM_MIMETYPE().Clone()); mimeTypes.push_back(VTK_POLYDATA_MIMETYPE().Clone()); mimeTypes.push_back(VTK_PARALLEL_POLYDATA_MIMETYPE().Clone()); mimeTypes.push_back(VTK_POLYDATA_LEGACY_MIMETYPE().Clone()); mimeTypes.push_back(STEREOLITHOGRAPHY_MIMETYPE().Clone()); mimeTypes.push_back(RAW_MIMETYPE().Clone()); mimeTypes.push_back(POINTSET_MIMETYPE().Clone()); return mimeTypes; } CustomMimeType IOMimeTypes::VTK_IMAGE_MIMETYPE() { CustomMimeType mimeType(VTK_IMAGE_NAME()); mimeType.AddExtension("vti"); mimeType.SetCategory(CATEGORY_IMAGES()); mimeType.SetComment("VTK Image"); return mimeType; } CustomMimeType IOMimeTypes::VTK_IMAGE_LEGACY_MIMETYPE() { CustomMimeType mimeType(VTK_IMAGE_LEGACY_NAME()); mimeType.AddExtension("vtk"); mimeType.SetCategory(CATEGORY_IMAGES()); mimeType.SetComment("VTK Legacy Image"); return mimeType; } CustomMimeType IOMimeTypes::VTK_PARALLEL_IMAGE_MIMETYPE() { CustomMimeType mimeType(VTK_PARALLEL_IMAGE_NAME()); mimeType.AddExtension("pvti"); mimeType.SetCategory(CATEGORY_IMAGES()); mimeType.SetComment("VTK Parallel Image"); return mimeType; } CustomMimeType IOMimeTypes::VTK_POLYDATA_MIMETYPE() { CustomMimeType mimeType(VTK_POLYDATA_NAME()); mimeType.AddExtension("vtp"); mimeType.SetCategory(CATEGORY_SURFACES()); mimeType.SetComment("VTK PolyData"); return mimeType; } CustomMimeType IOMimeTypes::VTK_POLYDATA_LEGACY_MIMETYPE() { CustomMimeType mimeType(VTK_POLYDATA_LEGACY_NAME()); mimeType.AddExtension("vtk"); mimeType.SetCategory(CATEGORY_SURFACES()); mimeType.SetComment("VTK Legacy PolyData"); return mimeType; } CustomMimeType IOMimeTypes::VTK_PARALLEL_POLYDATA_MIMETYPE() { CustomMimeType mimeType(VTK_PARALLEL_POLYDATA_NAME()); mimeType.AddExtension("pvtp"); mimeType.SetCategory(CATEGORY_SURFACES()); mimeType.SetComment("VTK Parallel PolyData"); return mimeType; } CustomMimeType IOMimeTypes::STEREOLITHOGRAPHY_MIMETYPE() { CustomMimeType mimeType(STEREOLITHOGRAPHY_NAME()); mimeType.AddExtension("stl"); mimeType.SetCategory(CATEGORY_SURFACES()); mimeType.SetComment("Stereolithography"); return mimeType; } std::string IOMimeTypes::STEREOLITHOGRAPHY_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".stl"; return name; } std::string IOMimeTypes::DEFAULT_BASE_NAME() { static std::string name = "application/vnd.mitk"; return name; } std::string IOMimeTypes::CATEGORY_IMAGES() { static std::string cat = "Images"; return cat; } std::string IOMimeTypes::CATEGORY_SURFACES() { static std::string cat = "Surfaces"; return cat; } std::string IOMimeTypes::VTK_IMAGE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.image"; return name; } std::string IOMimeTypes::VTK_IMAGE_LEGACY_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.image.legacy"; return name; } std::string IOMimeTypes::VTK_PARALLEL_IMAGE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.parallel.image"; return name; } std::string IOMimeTypes::VTK_POLYDATA_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.polydata"; return name; } std::string IOMimeTypes::VTK_POLYDATA_LEGACY_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.polydata.legacy"; return name; } std::string IOMimeTypes::VTK_PARALLEL_POLYDATA_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.parallel.polydata"; return name; } CustomMimeType IOMimeTypes::NRRD_MIMETYPE() { CustomMimeType mimeType(NRRD_MIMETYPE_NAME()); mimeType.AddExtension("nrrd"); mimeType.AddExtension("nhdr"); mimeType.SetCategory("Images"); mimeType.SetComment("NRRD"); return mimeType; } CustomMimeType IOMimeTypes::NIFTI_MIMETYPE() { CustomMimeType mimeType(NIFTI_MIMETYPE_NAME()); mimeType.AddExtension("nii"); mimeType.AddExtension("nii.gz"); mimeType.AddExtension("hdr"); + mimeType.AddExtension("hdr.gz"); mimeType.AddExtension("img"); mimeType.AddExtension("img.gz"); - mimeType.AddExtension("img.gz"); mimeType.AddExtension("nia"); mimeType.SetCategory("Images"); mimeType.SetComment("Nifti"); return mimeType; } CustomMimeType IOMimeTypes::RAW_MIMETYPE() { CustomMimeType mimeType(RAW_MIMETYPE_NAME()); mimeType.AddExtension("raw"); mimeType.SetCategory("Images"); mimeType.SetComment("Raw data"); return mimeType; } IOMimeTypes::DicomMimeType IOMimeTypes::DICOM_MIMETYPE() { return DicomMimeType(); } std::string IOMimeTypes::NRRD_MIMETYPE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".image.nrrd"; return name; } std::string IOMimeTypes::NIFTI_MIMETYPE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".image.nifti"; return name; } std::string IOMimeTypes::RAW_MIMETYPE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".image.raw"; return name; } std::string IOMimeTypes::DICOM_MIMETYPE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".image.dicom"; return name; } CustomMimeType IOMimeTypes::POINTSET_MIMETYPE() { CustomMimeType mimeType(POINTSET_MIMETYPE_NAME()); mimeType.AddExtension("mps"); mimeType.SetCategory("Point Sets"); mimeType.SetComment("MITK Point Set"); return mimeType; } std::string IOMimeTypes::POINTSET_MIMETYPE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".pointset"; return name; } } diff --git a/Modules/Core/src/IO/mitkIOUtil.cpp b/Modules/Core/src/IO/mitkIOUtil.cpp index 286fb983b3..75cb492baf 100644 --- a/Modules/Core/src/IO/mitkIOUtil.cpp +++ b/Modules/Core/src/IO/mitkIOUtil.cpp @@ -1,1077 +1,1108 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkIOUtil.h" #include #include #include #include #include #include #include #include #include #include #include #include +#include +#include //ITK #include //VTK #include #include #include #include #include static std::string GetLastErrorStr() { #ifdef US_PLATFORM_POSIX return std::string(strerror(errno)); #else // Retrieve the system error message for the last-error code LPVOID lpMsgBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); std::string errMsg((LPCTSTR)lpMsgBuf); LocalFree(lpMsgBuf); return errMsg; #endif } #ifdef US_PLATFORM_WINDOWS #include #include // make the posix flags point to the obsolte bsd types on windows #define S_IRUSR S_IREAD #define S_IWUSR S_IWRITE #else #include #include #include #endif #include #include static const char validLetters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; // A cross-platform version of the mkstemps function static int mkstemps_compat(char* tmpl, int suffixlen) { static unsigned long long value = 0; int savedErrno = errno; // Lower bound on the number of temporary files to attempt to generate. #define ATTEMPTS_MIN (62 * 62 * 62) /* The number of times to attempt to generate a temporary file. To conform to POSIX, this must be no smaller than TMP_MAX. */ #if ATTEMPTS_MIN < TMP_MAX const unsigned int attempts = TMP_MAX; #else const unsigned int attempts = ATTEMPTS_MIN; #endif const int len = strlen(tmpl); if ((len - suffixlen) < 6 || strncmp(&tmpl[len - 6 - suffixlen], "XXXXXX", 6)) { errno = EINVAL; return -1; } /* This is where the Xs start. */ char* XXXXXX = &tmpl[len - 6 - suffixlen]; /* Get some more or less random data. */ #ifdef US_PLATFORM_WINDOWS { SYSTEMTIME stNow; FILETIME ftNow; // get system time GetSystemTime(&stNow); stNow.wMilliseconds = 500; if (!SystemTimeToFileTime(&stNow, &ftNow)) { errno = -1; return -1; } unsigned long long randomTimeBits = ((static_cast(ftNow.dwHighDateTime) << 32) | static_cast(ftNow.dwLowDateTime)); value = randomTimeBits ^ static_cast(GetCurrentThreadId()); } #else { struct timeval tv; gettimeofday(&tv, NULL); unsigned long long randomTimeBits = ((static_cast(tv.tv_usec) << 32) | static_cast(tv.tv_sec)); value = randomTimeBits ^ static_cast(getpid()); } #endif for (unsigned int count = 0; count < attempts; value += 7777, ++count) { unsigned long long v = value; /* Fill in the random bits. */ XXXXXX[0] = validLetters[v % 62]; v /= 62; XXXXXX[1] = validLetters[v % 62]; v /= 62; XXXXXX[2] = validLetters[v % 62]; v /= 62; XXXXXX[3] = validLetters[v % 62]; v /= 62; XXXXXX[4] = validLetters[v % 62]; v /= 62; XXXXXX[5] = validLetters[v % 62]; int fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); if (fd >= 0) { errno = savedErrno; return fd; } else if (errno != EEXIST) { return -1; } } /* We got out of the loop because we ran out of combinations to try. */ errno = EEXIST; return -1; } // A cross-platform version of the POSIX mkdtemp function static char* mkdtemps_compat(char* tmpl, int suffixlen) { static unsigned long long value = 0; int savedErrno = errno; // Lower bound on the number of temporary dirs to attempt to generate. #define ATTEMPTS_MIN (62 * 62 * 62) /* The number of times to attempt to generate a temporary dir. To conform to POSIX, this must be no smaller than TMP_MAX. */ #if ATTEMPTS_MIN < TMP_MAX const unsigned int attempts = TMP_MAX; #else const unsigned int attempts = ATTEMPTS_MIN; #endif const int len = strlen(tmpl); if ((len - suffixlen) < 6 || strncmp(&tmpl[len - 6 - suffixlen], "XXXXXX", 6)) { errno = EINVAL; return NULL; } /* This is where the Xs start. */ char* XXXXXX = &tmpl[len - 6 - suffixlen]; /* Get some more or less random data. */ #ifdef US_PLATFORM_WINDOWS { SYSTEMTIME stNow; FILETIME ftNow; // get system time GetSystemTime(&stNow); stNow.wMilliseconds = 500; if (!SystemTimeToFileTime(&stNow, &ftNow)) { errno = -1; return NULL; } unsigned long long randomTimeBits = ((static_cast(ftNow.dwHighDateTime) << 32) | static_cast(ftNow.dwLowDateTime)); value = randomTimeBits ^ static_cast(GetCurrentThreadId()); } #else { struct timeval tv; gettimeofday(&tv, NULL); unsigned long long randomTimeBits = ((static_cast(tv.tv_usec) << 32) | static_cast(tv.tv_sec)); value = randomTimeBits ^ static_cast(getpid()); } #endif unsigned int count = 0; for (; count < attempts; value += 7777, ++count) { unsigned long long v = value; /* Fill in the random bits. */ XXXXXX[0] = validLetters[v % 62]; v /= 62; XXXXXX[1] = validLetters[v % 62]; v /= 62; XXXXXX[2] = validLetters[v % 62]; v /= 62; XXXXXX[3] = validLetters[v % 62]; v /= 62; XXXXXX[4] = validLetters[v % 62]; v /= 62; XXXXXX[5] = validLetters[v % 62]; #ifdef US_PLATFORM_WINDOWS int fd = _mkdir (tmpl); //, _S_IREAD | _S_IWRITE | _S_IEXEC); #else int fd = mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); #endif if (fd >= 0) { errno = savedErrno; return tmpl; } else if (errno != EEXIST) { return NULL; } } /* We got out of the loop because we ran out of combinations to try. */ errno = EEXIST; return NULL; } //#endif //************************************************************** // mitk::IOUtil method definitions namespace mitk { const std::string IOUtil::DEFAULTIMAGEEXTENSION = ".nrrd"; const std::string IOUtil::DEFAULTSURFACEEXTENSION = ".stl"; const std::string IOUtil::DEFAULTPOINTSETEXTENSION = ".mps"; struct IOUtil::Impl { struct FixedReaderOptionsFunctor : public ReaderOptionsFunctorBase { FixedReaderOptionsFunctor(const IFileReader::Options& options) : m_Options(options) {} virtual bool operator()(LoadInfo& loadInfo) { IFileReader* reader = loadInfo.m_ReaderSelector.GetSelected().GetReader(); if (reader) { reader->SetOptions(m_Options); } return false; } private: const IFileReader::Options& m_Options; }; struct FixedWriterOptionsFunctor : public WriterOptionsFunctorBase { FixedWriterOptionsFunctor(const IFileReader::Options& options) : m_Options(options) {} virtual bool operator()(SaveInfo& saveInfo) { IFileWriter* writer = saveInfo.m_WriterSelector.GetSelected().GetWriter(); if (writer) { writer->SetOptions(m_Options); } return false; } private: const IFileWriter::Options& m_Options; }; static BaseData::Pointer LoadBaseDataFromFile(const std::string& path); static void SetDefaultDataNodeProperties(mitk::DataNode* node, const std::string& filePath = std::string()); }; #ifdef US_PLATFORM_WINDOWS std::string IOUtil::GetProgramPath() { char path[512]; std::size_t index = std::string(path, GetModuleFileName(NULL, path, 512)).find_last_of('\\'); return std::string(path, index); } #elif defined(US_PLATFORM_APPLE) #include std::string IOUtil::GetProgramPath() { char path[512]; uint32_t size = sizeof(path); if (_NSGetExecutablePath(path, &size) == 0) { std::size_t index = std::string(path).find_last_of('/'); std::string strPath = std::string(path, index); //const char* execPath = strPath.c_str(); //mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch(execPath,false); return strPath; } return std::string(); } #else #include #include #include std::string IOUtil::GetProgramPath() { std::stringstream ss; ss << "/proc/" << getpid() << "/exe"; char proc[512] = {0}; ssize_t ch = readlink(ss.str().c_str(), proc, 512); if (ch == -1) return std::string(); std::size_t index = std::string(proc).find_last_of('/'); return std::string(proc, index); } #endif char IOUtil::GetDirectorySeparator() { #ifdef US_PLATFORM_WINDOWS return '\\'; #else return '/'; #endif } std::string IOUtil::GetTempPath() { static std::string result; if (result.empty()) { #ifdef US_PLATFORM_WINDOWS char tempPathTestBuffer[1]; DWORD bufferLength = ::GetTempPath(1, tempPathTestBuffer); if (bufferLength == 0) { mitkThrow() << GetLastErrorStr(); } std::vector tempPath(bufferLength); bufferLength = ::GetTempPath(bufferLength, &tempPath[0]); if (bufferLength == 0) { mitkThrow() << GetLastErrorStr(); } result.assign(tempPath.begin(), tempPath.begin() + static_cast(bufferLength)); #else result = "/tmp/"; #endif } return result; } std::string IOUtil::CreateTemporaryFile(const std::string& templateName, std::string path) { ofstream tmpOutputStream; std::string returnValue = CreateTemporaryFile(tmpOutputStream,templateName,path); tmpOutputStream.close(); return returnValue; } std::string IOUtil::CreateTemporaryFile(std::ofstream& f, const std::string& templateName, std::string path) { return CreateTemporaryFile(f, std::ios_base::out | std::ios_base::trunc, templateName, path); } std::string IOUtil::CreateTemporaryFile(std::ofstream& f, std::ios_base::openmode mode, const std::string& templateName, std::string path) { if (path.empty()) { path = GetTempPath(); } path += GetDirectorySeparator() + templateName; std::vector dst_path(path.begin(), path.end()); dst_path.push_back('\0'); std::size_t lastX = path.find_last_of('X'); std::size_t firstX = path.find_last_not_of('X', lastX); int firstNonX = firstX == std::string::npos ? - 1 : firstX - 1; while (lastX != std::string::npos && (lastX - firstNonX) < 6) { lastX = path.find_last_of('X', firstX); firstX = path.find_last_not_of('X', lastX); firstNonX = firstX == std::string::npos ? - 1 : firstX - 1; } std::size_t suffixlen = lastX == std::string::npos ? path.size() : path.size() - lastX - 1; int fd = mkstemps_compat(&dst_path[0], suffixlen); if(fd != -1) { path.assign(dst_path.begin(), dst_path.end() - 1); f.open(path.c_str(), mode | std::ios_base::out | std::ios_base::trunc); close(fd); } else { mitkThrow() << "Creating temporary file " << &dst_path[0] << " failed: " << GetLastErrorStr(); } return path; } std::string IOUtil::CreateTemporaryDirectory(const std::string& templateName, std::string path) { if (path.empty()) { path = GetTempPath(); } path += GetDirectorySeparator() + templateName; std::vector dst_path(path.begin(), path.end()); dst_path.push_back('\0'); std::size_t lastX = path.find_last_of('X'); std::size_t firstX = path.find_last_not_of('X', lastX); int firstNonX = firstX == std::string::npos ? - 1 : firstX - 1; while (lastX != std::string::npos && (lastX - firstNonX) < 6) { lastX = path.find_last_of('X', firstX); firstX = path.find_last_not_of('X', lastX); firstNonX = firstX == std::string::npos ? - 1 : firstX - 1; } std::size_t suffixlen = lastX == std::string::npos ? path.size() : path.size() - lastX - 1; if(mkdtemps_compat(&dst_path[0], suffixlen) == NULL) { mitkThrow() << "Creating temporary directory " << &dst_path[0] << " failed: " << GetLastErrorStr(); } path.assign(dst_path.begin(), dst_path.end() - 1); return path; } DataStorage::SetOfObjects::Pointer IOUtil::Load(const std::string& path, DataStorage& storage) { std::vector paths; paths.push_back(path); return Load(paths, storage); } DataStorage::SetOfObjects::Pointer IOUtil::Load(const std::string& path, const IFileReader::Options& options, DataStorage& storage) { std::vector loadInfos; loadInfos.push_back(LoadInfo(path)); DataStorage::SetOfObjects::Pointer nodeResult = DataStorage::SetOfObjects::New(); Impl::FixedReaderOptionsFunctor optionsCallback(options); std::string errMsg = Load(loadInfos, nodeResult, &storage, &optionsCallback); if (!errMsg.empty()) { mitkThrow() << errMsg; } return nodeResult; } std::vector IOUtil::Load(const std::string& path) { std::vector paths; paths.push_back(path); return Load(paths); } std::vector IOUtil::Load(const std::string& path, const IFileReader::Options& options) { std::vector loadInfos; loadInfos.push_back(LoadInfo(path)); Impl::FixedReaderOptionsFunctor optionsCallback(options); std::string errMsg = Load(loadInfos, NULL, NULL, &optionsCallback); if (!errMsg.empty()) { mitkThrow() << errMsg; } return loadInfos.front().m_Output; } DataStorage::SetOfObjects::Pointer IOUtil::Load(const std::vector& paths, DataStorage& storage) { DataStorage::SetOfObjects::Pointer nodeResult = DataStorage::SetOfObjects::New(); std::vector loadInfos; for (std::vector::const_iterator iter = paths.begin(), iterEnd = paths.end(); iter != iterEnd; ++iter) { LoadInfo loadInfo(*iter); loadInfos.push_back(loadInfo); } std::string errMsg = Load(loadInfos, nodeResult, &storage, NULL); if (!errMsg.empty()) { mitkThrow() << errMsg; } return nodeResult; } std::vector IOUtil::Load(const std::vector& paths) { std::vector result; std::vector loadInfos; for (std::vector::const_iterator iter = paths.begin(), iterEnd = paths.end(); iter != iterEnd; ++iter) { LoadInfo loadInfo(*iter); loadInfos.push_back(loadInfo); } std::string errMsg = Load(loadInfos, NULL, NULL, NULL); if (!errMsg.empty()) { mitkThrow() << errMsg; } for (std::vector::const_iterator iter = loadInfos.begin(), iterEnd = loadInfos.end(); iter != iterEnd; ++iter) { result.insert(result.end(), iter->m_Output.begin(), iter->m_Output.end()); } return result; } int IOUtil::LoadFiles(const std::vector &fileNames, DataStorage& ds) { return static_cast(Load(fileNames, ds)->Size()); } DataStorage::Pointer IOUtil::LoadFiles(const std::vector& fileNames) { mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); Load(fileNames, *ds); return ds.GetPointer(); } BaseData::Pointer IOUtil::LoadBaseData(const std::string& path) { return Impl::LoadBaseDataFromFile(path); } BaseData::Pointer IOUtil::Impl::LoadBaseDataFromFile(const std::string& path) { std::vector baseDataList = Load(path); // The Load(path) call above should throw an exception if nothing could be loaded assert(!baseDataList.empty()); return baseDataList.front(); } DataNode::Pointer IOUtil::LoadDataNode(const std::string& path) { BaseData::Pointer baseData = Impl::LoadBaseDataFromFile(path); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(baseData); Impl::SetDefaultDataNodeProperties(node, path); return node; } Image::Pointer IOUtil::LoadImage(const std::string& path) { BaseData::Pointer baseData = Impl::LoadBaseDataFromFile(path); mitk::Image::Pointer image = dynamic_cast(baseData.GetPointer()); if(image.IsNull()) { mitkThrow() << path << " is not a mitk::Image but a " << baseData->GetNameOfClass(); } return image; } Surface::Pointer IOUtil::LoadSurface(const std::string& path) { BaseData::Pointer baseData = Impl::LoadBaseDataFromFile(path); mitk::Surface::Pointer surface = dynamic_cast(baseData.GetPointer()); if(surface.IsNull()) { mitkThrow() << path << " is not a mitk::Surface but a " << baseData->GetNameOfClass(); } return surface; } PointSet::Pointer IOUtil::LoadPointSet(const std::string& path) { BaseData::Pointer baseData = Impl::LoadBaseDataFromFile(path); mitk::PointSet::Pointer pointset = dynamic_cast(baseData.GetPointer()); if(pointset.IsNull()) { mitkThrow() << path << " is not a mitk::PointSet but a " << baseData->GetNameOfClass(); } return pointset; } std::string IOUtil::Load(std::vector& loadInfos, DataStorage::SetOfObjects* nodeResult, DataStorage* ds, ReaderOptionsFunctorBase* optionsCallback) { if (loadInfos.empty()) { return "No input files given"; } int filesToRead = loadInfos.size(); mitk::ProgressBar::GetInstance()->AddStepsToDo(2*filesToRead); std::string errMsg; std::map usedReaderItems; for(std::vector::iterator infoIter = loadInfos.begin(), infoIterEnd = loadInfos.end(); infoIter != infoIterEnd; ++infoIter) { std::vector readers = infoIter->m_ReaderSelector.Get(); if (readers.empty()) { if (!itksys::SystemTools::FileExists(infoIter->m_Path.c_str())) { errMsg += "File '" + infoIter->m_Path + "' does not exist\n"; } else { errMsg += "No reader available for '" + infoIter->m_Path + "'\n"; } continue; } bool callOptionsCallback = readers.size() > 1 || !readers.front().GetReader()->GetOptions().empty(); // check if we already used a reader which should be re-used std::vector currMimeTypes = infoIter->m_ReaderSelector.GetMimeTypes(); std::string selectedMimeType; for (std::vector::const_iterator mimeTypeIter = currMimeTypes.begin(), mimeTypeIterEnd = currMimeTypes.end(); mimeTypeIter != mimeTypeIterEnd; ++mimeTypeIter) { std::map::const_iterator oldSelectedItemIter = usedReaderItems.find(mimeTypeIter->GetName()); if (oldSelectedItemIter != usedReaderItems.end()) { // we found an already used item for a mime-type which is contained // in the current reader set, check all current readers if there service // id equals the old reader for (std::vector::const_iterator currReaderItem = readers.begin(), currReaderItemEnd = readers.end(); currReaderItem != currReaderItemEnd; ++currReaderItem) { if (currReaderItem->GetMimeType().GetName() == mimeTypeIter->GetName() && currReaderItem->GetServiceId() == oldSelectedItemIter->second.GetServiceId() && currReaderItem->GetConfidenceLevel() >= oldSelectedItemIter->second.GetConfidenceLevel()) { // okay, we used the same reader already, re-use its options selectedMimeType = mimeTypeIter->GetName(); callOptionsCallback = false; infoIter->m_ReaderSelector.Select(oldSelectedItemIter->second.GetServiceId()); infoIter->m_ReaderSelector.GetSelected().GetReader()->SetOptions( oldSelectedItemIter->second.GetReader()->GetOptions()); break; } } if (!selectedMimeType.empty()) break; } } if (callOptionsCallback && optionsCallback) { callOptionsCallback = (*optionsCallback)(*infoIter); if (!callOptionsCallback && !infoIter->m_Cancel) { usedReaderItems.erase(selectedMimeType); FileReaderSelector::Item selectedItem = infoIter->m_ReaderSelector.GetSelected(); usedReaderItems.insert(std::make_pair(selectedItem.GetMimeType().GetName(), selectedItem)); } } if (infoIter->m_Cancel) { errMsg += "Reading operation(s) cancelled."; break; } IFileReader* reader = infoIter->m_ReaderSelector.GetSelected().GetReader(); if (reader == NULL) { errMsg += "Unexpected NULL reader."; break; } // Do the actual reading try { DataStorage::SetOfObjects::Pointer nodes; if (ds != NULL) { nodes = reader->Read(*ds); } else { nodes = DataStorage::SetOfObjects::New(); std::vector baseData = reader->Read(); for (std::vector::iterator iter = baseData.begin(); iter != baseData.end(); ++iter) { if (iter->IsNotNull()) { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(*iter); nodes->InsertElement(nodes->Size(), node); } } } for (DataStorage::SetOfObjects::ConstIterator nodeIter = nodes->Begin(), nodeIterEnd = nodes->End(); nodeIter != nodeIterEnd; ++nodeIter) { const mitk::DataNode::Pointer& node = nodeIter->Value(); mitk::BaseData::Pointer data = node->GetData(); if (data.IsNull()) { continue; } mitk::StringProperty::Pointer pathProp = mitk::StringProperty::New(infoIter->m_Path); data->SetProperty("path", pathProp); infoIter->m_Output.push_back(data); if (nodeResult) { nodeResult->push_back(nodeIter->Value()); } } if (infoIter->m_Output.empty() || (nodeResult && nodeResult->Size() == 0)) { errMsg += "Unknown read error occurred reading " + infoIter->m_Path; } } catch (const std::exception& e) { errMsg += "Exception occured when reading file " + infoIter->m_Path + ":\n" + e.what() + "\n\n"; } mitk::ProgressBar::GetInstance()->Progress(2); --filesToRead; } if (!errMsg.empty()) { MITK_ERROR << errMsg; } mitk::ProgressBar::GetInstance()->Progress(2*filesToRead); return errMsg; } +std::vector IOUtil::Load(const us::ModuleResource &usResource, std::ios_base::openmode mode) +{ + us::ModuleResourceStream resStream(usResource,mode); + + mitk::CoreServicePointer mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider()); + std::vector mimetypes = mimeTypeProvider->GetMimeTypesForFile(usResource.GetResourcePath()); + + std::vector data; + if(mimetypes.empty()) + { + mitkThrow() << "No mimetype for resource stream: "<< usResource.GetResourcePath(); + return data; + } + + mitk::FileReaderRegistry fileReaderRegistry; + std::vector > refs = fileReaderRegistry.GetReferences(mimetypes[0]); + if(refs.empty()) + { + mitkThrow() << "No reader available for resource stream: "<< usResource.GetResourcePath(); + return data; + } + + mitk::IFileReader* reader = fileReaderRegistry.GetReader(refs[0]); + reader->SetInput(usResource.GetResourcePath(),&resStream); + data = reader->Read(); + + return data; +} + void IOUtil::Save(const BaseData* data, const std::string& path) { Save(data, path, IFileWriter::Options()); } void IOUtil::Save(const BaseData* data, const std::string& path, const IFileWriter::Options& options) { Save(data, std::string(), path, options); } void IOUtil::Save(const BaseData* data, const std::string& mimeType, const std::string& path, bool addExtension) { Save(data, mimeType, path, IFileWriter::Options(), addExtension); } void IOUtil::Save(const BaseData* data, const std::string& mimeType, const std::string& path, const IFileWriter::Options& options, bool addExtension) { std::string errMsg; if (options.empty()) { errMsg = Save(data, mimeType, path, NULL, addExtension); } else { Impl::FixedWriterOptionsFunctor optionsCallback(options); errMsg = Save(data, mimeType, path, &optionsCallback, addExtension); } if (!errMsg.empty()) { mitkThrow() << errMsg; } } void IOUtil::Save(std::vector& saveInfos) { std::string errMsg = Save(saveInfos, NULL); if (!errMsg.empty()) { mitkThrow() << errMsg; } } bool IOUtil::SaveImage(mitk::Image::Pointer image, const std::string& path) { Save(image, path); return true; } bool IOUtil::SaveSurface(Surface::Pointer surface, const std::string& path) { Save(surface, path); return true; } bool IOUtil::SavePointSet(PointSet::Pointer pointset, const std::string& path) { Save(pointset, path); return true; } bool IOUtil::SaveBaseData( mitk::BaseData* data, const std::string& path) { Save(data, path); return true; } std::string IOUtil::Save(const BaseData* data, const std::string& mimeTypeName, const std::string& path, WriterOptionsFunctorBase* optionsCallback, bool addExtension) { if (path.empty()) { return "No output filename given"; } mitk::CoreServicePointer mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider()); MimeType mimeType = mimeTypeProvider->GetMimeTypeForName(mimeTypeName); SaveInfo saveInfo(data, mimeType, path); std::string ext = itksys::SystemTools::GetFilenameExtension(path); if (saveInfo.m_WriterSelector.IsEmpty()) { return std::string("No suitable writer found for the current data of type ") + data->GetNameOfClass() + (mimeType.IsValid() ? (std::string(" and mime-type ") + mimeType.GetName()) : std::string()) + (ext.empty() ? std::string() : (std::string(" with extension ") + ext)); } // Add an extension if not already specified if (ext.empty() && addExtension) { ext = saveInfo.m_MimeType.GetExtensions().empty() ? std::string() : "." + saveInfo.m_MimeType.GetExtensions().front(); } std::vector infos; infos.push_back(saveInfo); return Save(infos, optionsCallback); } std::string IOUtil::Save(std::vector& saveInfos, WriterOptionsFunctorBase* optionsCallback) { if (saveInfos.empty()) { return "No data for saving available"; } int filesToWrite = saveInfos.size(); mitk::ProgressBar::GetInstance()->AddStepsToDo(2*filesToWrite); std::string errMsg; std::set usedSaveInfos; for (std::vector::iterator infoIter = saveInfos.begin(), infoIterEnd = saveInfos.end(); infoIter != infoIterEnd; ++infoIter) { const std::string baseDataType = infoIter->m_BaseData->GetNameOfClass(); std::vector writers = infoIter->m_WriterSelector.Get(); // Error out if no compatible Writer was found if (writers.empty()) { errMsg += std::string("No writer available for ") + baseDataType + " data.\n"; continue; } bool callOptionsCallback = writers.size() > 1 || !writers[0].GetWriter()->GetOptions().empty(); // check if we already used a writer for this base data type // which should be re-used std::set::const_iterator oldSaveInfoIter = usedSaveInfos.find(*infoIter); if (oldSaveInfoIter != usedSaveInfos.end()) { // we previously saved a base data object of the same data with the same mime-type, // check if the same writer is contained in the current writer set and if the // confidence level matches FileWriterSelector::Item oldSelectedItem = oldSaveInfoIter->m_WriterSelector.Get(oldSaveInfoIter->m_WriterSelector.GetSelectedId()); for (std::vector::const_iterator currWriterItem = writers.begin(), currWriterItemEnd = writers.end(); currWriterItem != currWriterItemEnd; ++currWriterItem) { if (currWriterItem->GetServiceId() == oldSelectedItem.GetServiceId() && currWriterItem->GetConfidenceLevel() >= oldSelectedItem.GetConfidenceLevel()) { // okay, we used the same writer already, re-use its options callOptionsCallback = false; infoIter->m_WriterSelector.Select(oldSaveInfoIter->m_WriterSelector.GetSelectedId()); infoIter->m_WriterSelector.GetSelected().GetWriter()->SetOptions( oldSelectedItem.GetWriter()->GetOptions()); break; } } } if (callOptionsCallback && optionsCallback) { callOptionsCallback = (*optionsCallback)(*infoIter); if (!callOptionsCallback && !infoIter->m_Cancel) { usedSaveInfos.erase(*infoIter); usedSaveInfos.insert(*infoIter); } } if (infoIter->m_Cancel) { errMsg += "Writing operation(s) cancelled."; break; } IFileWriter* writer = infoIter->m_WriterSelector.GetSelected().GetWriter(); if (writer == NULL) { errMsg += "Unexpected NULL writer."; break; } // Do the actual writing try { writer->SetOutputLocation(infoIter->m_Path); writer->Write(); } catch(const std::exception& e) { errMsg += std::string("Exception occurred when writing to ") + infoIter->m_Path + ":\n" + e.what() + "\n"; } mitk::ProgressBar::GetInstance()->Progress(2); --filesToWrite; } if (!errMsg.empty()) { MITK_ERROR << errMsg; } mitk::ProgressBar::GetInstance()->Progress(2*filesToWrite); return errMsg; } // This method can be removed after the deprecated LoadDataNode() method was removed void IOUtil::Impl::SetDefaultDataNodeProperties(DataNode* node, const std::string& filePath) { // path mitk::StringProperty::Pointer pathProp = mitk::StringProperty::New( itksys::SystemTools::GetFilenamePath(filePath) ); node->SetProperty(StringProperty::PATH, pathProp); // name already defined? mitk::StringProperty::Pointer nameProp = dynamic_cast(node->GetProperty("name")); if(nameProp.IsNull() || (strcmp(nameProp->GetValue(),"No Name!")==0)) { // name already defined in BaseData mitk::StringProperty::Pointer baseDataNameProp = dynamic_cast(node->GetData()->GetProperty("name").GetPointer() ); if(baseDataNameProp.IsNull() || (strcmp(baseDataNameProp->GetValue(),"No Name!")==0)) { // name neither defined in node, nor in BaseData -> name = filename nameProp = mitk::StringProperty::New( itksys::SystemTools::GetFilenameWithoutExtension(filePath)); node->SetProperty("name", nameProp); } else { // name defined in BaseData! nameProp = mitk::StringProperty::New(baseDataNameProp->GetValue()); node->SetProperty("name", nameProp); } } // visibility if(!node->GetProperty("visible")) { node->SetVisibility(true); } } IOUtil::SaveInfo::SaveInfo(const BaseData* baseData, const MimeType& mimeType, const std::string& path) : m_BaseData(baseData) , m_WriterSelector(baseData, mimeType.GetName(), path) , m_MimeType(mimeType.IsValid() ? mimeType // use the original mime-type : (m_WriterSelector.IsEmpty() ? mimeType // no writer found, use the original invalid mime-type : m_WriterSelector.GetDefault().GetMimeType() // use the found default mime-type ) ) , m_Path(path) , m_Cancel(false) { } bool IOUtil::SaveInfo::operator<(const IOUtil::SaveInfo& other) const { int r = strcmp(m_BaseData->GetNameOfClass(), other.m_BaseData->GetNameOfClass()); if (r == 0) { return m_WriterSelector.GetSelected().GetMimeType() < other.m_WriterSelector.GetSelected().GetMimeType(); } return r < 0; } IOUtil::LoadInfo::LoadInfo(const std::string& path) : m_Path(path) , m_ReaderSelector(path) , m_Cancel(false) { } } diff --git a/Modules/Core/src/IO/mitkMimeType.cpp b/Modules/Core/src/IO/mitkMimeType.cpp index e1bdf713e8..01ad64867f 100644 --- a/Modules/Core/src/IO/mitkMimeType.cpp +++ b/Modules/Core/src/IO/mitkMimeType.cpp @@ -1,138 +1,143 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkMimeType.h" #include "mitkCustomMimeType.h" #include namespace mitk { struct MimeType::Impl : us::SharedData { Impl() : m_CustomMimeType(new CustomMimeType()) , m_Rank(-1) , m_Id(-1) {} Impl(const CustomMimeType& x, int rank, long id) : m_CustomMimeType(x.Clone()) , m_Rank(rank) , m_Id(id) {} std::auto_ptr m_CustomMimeType; int m_Rank; long m_Id; }; MimeType::MimeType() : m_Data(new Impl) { } MimeType::MimeType(const MimeType& other) : m_Data(other.m_Data) { } MimeType::MimeType(const CustomMimeType& x, int rank, long id) : m_Data(new Impl(x, rank, id)) { } MimeType::~MimeType() { } MimeType& MimeType::operator=(const MimeType& other) { m_Data = other.m_Data; return *this; } bool MimeType::operator==(const MimeType& other) const { return this->GetName() == other.GetName(); } bool MimeType::operator<(const MimeType& other) const { if (m_Data->m_Rank != other.m_Data->m_Rank) { return m_Data->m_Rank < other.m_Data->m_Rank; } return other.m_Data->m_Id < m_Data->m_Id; } std::string MimeType::GetName() const { return m_Data->m_CustomMimeType->GetName(); } std::string MimeType::GetCategory() const { return m_Data->m_CustomMimeType->GetCategory(); } std::vector MimeType::GetExtensions() const { return m_Data->m_CustomMimeType->GetExtensions(); } std::string MimeType::GetComment() const { return m_Data->m_CustomMimeType->GetComment(); } +std::string MimeType::GetFilenameWithoutExtension(const std::string& path) const +{ + return m_Data->m_CustomMimeType->GetFilenameWithoutExtension(path); +} + bool MimeType::AppliesTo(const std::string& path) const { return m_Data->m_CustomMimeType->AppliesTo(path); } bool MimeType::IsValid() const { return m_Data.Data() != NULL && m_Data->m_CustomMimeType.get() != NULL && !m_Data->m_CustomMimeType->GetName().empty(); } void MimeType::Swap(MimeType& m) { m_Data.Swap(m.m_Data); } void swap(MimeType& m1, MimeType& m2) { m1.Swap(m2); } std::ostream& operator<<(std::ostream& os, const MimeType& mimeType) { os << mimeType.GetName() << " (" << mimeType.GetCategory() << ", " << mimeType.GetComment() << ") "; std::vector extensions = mimeType.GetExtensions(); for (std::vector::const_iterator iter = extensions.begin(), endIter = extensions.end(); iter != endIter; ++iter) { if (iter != extensions.begin()) os << ", "; os << *iter; } return os; } } diff --git a/Modules/Core/src/Rendering/mitkSurfaceVtkMapper2D.cpp b/Modules/Core/src/Rendering/mitkSurfaceVtkMapper2D.cpp index 51d1f2867e..0cbf30d68b 100644 --- a/Modules/Core/src/Rendering/mitkSurfaceVtkMapper2D.cpp +++ b/Modules/Core/src/Rendering/mitkSurfaceVtkMapper2D.cpp @@ -1,340 +1,340 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSurfaceVtkMapper2D.h" //mitk includes #include #include #include "mitkVtkPropRenderer.h" #include #include #include #include #include #include //vtk includes #include #include #include #include #include #include #include #include #include #include #include // constructor LocalStorage mitk::SurfaceVtkMapper2D::LocalStorage::LocalStorage() { m_Mapper = vtkSmartPointer::New(); m_Mapper->ScalarVisibilityOff(); m_Actor = vtkSmartPointer::New(); - m_Actor->SetMapper( m_Mapper ); m_PropAssembly = vtkSmartPointer ::New(); m_PropAssembly->AddPart( m_Actor ); m_CuttingPlane = vtkSmartPointer::New(); m_Cutter = vtkSmartPointer::New(); m_Cutter->SetCutFunction(m_CuttingPlane); m_Mapper->SetInputConnection( m_Cutter->GetOutputPort() ); m_NormalGlyph = vtkSmartPointer::New(); m_InverseNormalGlyph = vtkSmartPointer::New(); // Source for the glyph filter m_ArrowSource = vtkSmartPointer::New(); //set small default values for fast rendering m_ArrowSource->SetTipRadius(0.05); m_ArrowSource->SetTipLength(0.20); m_ArrowSource->SetTipResolution(5); m_ArrowSource->SetShaftResolution(5); m_ArrowSource->SetShaftRadius(0.01); m_NormalGlyph->SetSourceConnection(m_ArrowSource->GetOutputPort()); m_NormalGlyph->SetVectorModeToUseNormal(); m_NormalGlyph->OrientOn(); m_InverseNormalGlyph->SetSourceConnection(m_ArrowSource->GetOutputPort()); m_InverseNormalGlyph->SetVectorModeToUseNormal(); m_InverseNormalGlyph->OrientOn(); m_NormalMapper = vtkSmartPointer::New(); m_NormalMapper->SetInputConnection(m_NormalGlyph->GetOutputPort()); m_NormalMapper->ScalarVisibilityOff(); m_InverseNormalMapper = vtkSmartPointer::New(); m_InverseNormalMapper->SetInputConnection(m_NormalGlyph->GetOutputPort()); m_InverseNormalMapper->ScalarVisibilityOff(); m_NormalActor = vtkSmartPointer::New(); m_NormalActor->SetMapper(m_NormalMapper); m_InverseNormalActor = vtkSmartPointer::New(); m_InverseNormalActor->SetMapper(m_InverseNormalMapper); m_ReverseSense = vtkSmartPointer::New(); - - m_PropAssembly->AddPart( m_NormalActor ); } // destructor LocalStorage mitk::SurfaceVtkMapper2D::LocalStorage::~LocalStorage() { } const mitk::Surface* mitk::SurfaceVtkMapper2D::GetInput() const { return static_cast ( GetDataNode()->GetData() ); } // constructor PointSetVtkMapper2D mitk::SurfaceVtkMapper2D::SurfaceVtkMapper2D() { } mitk::SurfaceVtkMapper2D::~SurfaceVtkMapper2D() { } // reset mapper so that nothing is displayed e.g. toggle visiblity of the propassembly void mitk::SurfaceVtkMapper2D::ResetMapper( BaseRenderer* renderer ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); ls->m_PropAssembly->VisibilityOff(); } vtkProp* mitk::SurfaceVtkMapper2D::GetVtkProp(mitk::BaseRenderer * renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); return ls->m_PropAssembly; } void mitk::SurfaceVtkMapper2D::Update(mitk::BaseRenderer* renderer) { const mitk::DataNode* node = GetDataNode(); if( node == NULL ) return; bool visible = true; node->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; mitk::Surface* surface = static_cast( node->GetData() ); if ( surface == NULL ) return; // Calculate time step of the input data for the specified renderer (integer value) this->CalculateTimeStep( renderer ); // Check if time step is valid const mitk::TimeGeometry *dataTimeGeometry = surface->GetTimeGeometry(); if ( ( dataTimeGeometry == NULL ) || ( dataTimeGeometry->CountTimeSteps() == 0 ) || ( !dataTimeGeometry->IsValidTimeStep( this->GetTimestep() ) ) ) { return; } surface->UpdateOutputInformation(); LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); //check if something important has changed and we need to rerender if ( (localStorage->m_LastUpdateTime < node->GetMTime()) //was the node modified? || (localStorage->m_LastUpdateTime < surface->GetPipelineMTime()) //Was the data modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometryUpdateTime()) //was the geometry modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometry()->GetMTime()) || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) { this->GenerateDataForRenderer( renderer ); } // since we have checked that nothing important has changed, we can set // m_LastUpdateTime to the current time localStorage->m_LastUpdateTime.Modified(); } void mitk::SurfaceVtkMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { const DataNode* node = GetDataNode(); Surface* surface = static_cast( node->GetData() ); const TimeGeometry *dataTimeGeometry = surface->GetTimeGeometry(); LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); ScalarType time =renderer->GetTime(); int timestep=0; if( time > itk::NumericTraits::NonpositiveMin() ) timestep = dataTimeGeometry->TimePointToTimeStep( time ); vtkSmartPointer inputPolyData = surface->GetVtkPolyData( timestep ); - if((inputPolyData==NULL) || (inputPolyData->GetNumberOfPoints() < 1 )) + if ((inputPolyData == NULL) || (inputPolyData->GetNumberOfPoints() < 1)) return; //apply color and opacity read from the PropertyList this->ApplyAllProperties(renderer); const PlaneGeometry* planeGeometry = renderer->GetCurrentWorldPlaneGeometry(); if( ( planeGeometry == NULL ) || ( !planeGeometry->IsValid() ) || ( !planeGeometry->HasReferenceGeometry() )) { return; } + if (localStorage->m_Actor->GetMapper() == NULL) + localStorage->m_Actor->SetMapper(localStorage->m_Mapper); + double origin[3]; origin[0] = planeGeometry->GetOrigin()[0]; origin[1] = planeGeometry->GetOrigin()[1]; origin[2] = planeGeometry->GetOrigin()[2]; double normal[3]; normal[0] = planeGeometry->GetNormal()[0]; normal[1] = planeGeometry->GetNormal()[1]; normal[2] = planeGeometry->GetNormal()[2]; localStorage->m_CuttingPlane->SetOrigin(origin); localStorage->m_CuttingPlane->SetNormal(normal); //Transform the data according to its geometry. //See UpdateVtkTransform documentation for details. vtkSmartPointer vtktransform = GetDataNode()->GetVtkTransform(this->GetTimestep()); vtkSmartPointer filter = vtkSmartPointer::New(); filter->SetTransform(vtktransform); filter->SetInputData(inputPolyData); localStorage->m_Cutter->SetInputConnection(filter->GetOutputPort()); localStorage->m_Cutter->Update(); bool generateNormals = false; node->GetBoolProperty("draw normals 2D", generateNormals); if(generateNormals) { localStorage->m_NormalGlyph->SetInputConnection( localStorage->m_Cutter->GetOutputPort() ); localStorage->m_NormalGlyph->Update(); localStorage->m_NormalMapper->SetInputConnection( localStorage->m_NormalGlyph->GetOutputPort() ); localStorage->m_PropAssembly->AddPart( localStorage->m_NormalActor ); } else { localStorage->m_NormalGlyph->SetInputConnection( NULL ); localStorage->m_PropAssembly->RemovePart( localStorage->m_NormalActor ); } bool generateInverseNormals = false; node->GetBoolProperty("invert normals", generateInverseNormals); if(generateInverseNormals) { localStorage->m_ReverseSense->SetInputConnection( localStorage->m_Cutter->GetOutputPort() ); localStorage->m_ReverseSense->ReverseCellsOff(); localStorage->m_ReverseSense->ReverseNormalsOn(); localStorage->m_InverseNormalGlyph->SetInputConnection( localStorage->m_ReverseSense->GetOutputPort() ); localStorage->m_InverseNormalGlyph->Update(); localStorage->m_InverseNormalMapper->SetInputConnection( localStorage->m_InverseNormalGlyph->GetOutputPort() ); localStorage->m_PropAssembly->AddPart( localStorage->m_InverseNormalActor ); } else { localStorage->m_ReverseSense->SetInputConnection( NULL ); localStorage->m_PropAssembly->RemovePart( localStorage->m_InverseNormalActor ); } } void mitk::SurfaceVtkMapper2D::ApplyAllProperties(mitk::BaseRenderer* renderer) { const DataNode * node = GetDataNode(); if(node == NULL) { return; } float lineWidth = 1.0f; node->GetFloatProperty("line width", lineWidth, renderer); LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); // check for color and opacity properties, use it for rendering if they exists float color[3]= { 1.0f, 1.0f, 1.0f }; node->GetColor(color, renderer, "color"); float opacity = 1.0f; node->GetOpacity(opacity, renderer, "opacity"); //Pass properties to VTK localStorage->m_Actor->GetProperty()->SetColor(color[0], color[1], color[2]); localStorage->m_Actor->GetProperty()->SetOpacity(opacity); localStorage->m_NormalActor->GetProperty()->SetOpacity(opacity); localStorage->m_InverseNormalActor->GetProperty()->SetOpacity(opacity); localStorage->m_Actor->GetProperty()->SetLineWidth(lineWidth); //By default, the cutter will also copy/compute normals of the cut //to the output polydata. The normals will influence the //vtkPolyDataMapper lightning. To view a clean cut the lighting has //to be disabled. localStorage->m_Actor->GetProperty()->SetLighting(0); bool scalarVisibility = false; node->GetBoolProperty("scalar visibility", scalarVisibility); localStorage->m_Mapper->SetScalarVisibility(scalarVisibility); //color for inverse normals float inverseNormalsColor[3]= { 1.0f, 0.0f, 0.0f }; node->GetColor(inverseNormalsColor, renderer, "back color"); localStorage->m_InverseNormalActor->GetProperty()->SetColor(inverseNormalsColor[0], inverseNormalsColor[1], inverseNormalsColor[2]); //color for normals float normalsColor[3]= { 0.0f, 1.0f, 0.0f }; node->GetColor(normalsColor, renderer, "front color"); localStorage->m_NormalActor->GetProperty()->SetColor(normalsColor[0], normalsColor[1], normalsColor[2]); //normals scaling float normalScaleFactor = 10.0f; node->GetFloatProperty( "front normal lenth (px)", normalScaleFactor, renderer ); localStorage->m_NormalGlyph->SetScaleFactor(normalScaleFactor); //inverse normals scaling float inverseNormalScaleFactor = 10.0f; node->GetFloatProperty( "back normal lenth (px)", inverseNormalScaleFactor, renderer ); localStorage->m_InverseNormalGlyph->SetScaleFactor(inverseNormalScaleFactor); } void mitk::SurfaceVtkMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { mitk::IPropertyAliases* aliases = mitk::CoreServices::GetPropertyAliases(); node->AddProperty( "line width", FloatProperty::New(2.0f), renderer, overwrite ); aliases->AddAlias( "line width", "Surface.2D.Line Width", "Surface"); node->AddProperty( "scalar mode", VtkScalarModeProperty::New(), renderer, overwrite ); node->AddProperty( "draw normals 2D", BoolProperty::New(false), renderer, overwrite ); aliases->AddAlias( "draw normals 2D", "Surface.2D.Normals.Draw Normals", "Surface"); node->AddProperty( "invert normals", BoolProperty::New(false), renderer, overwrite ); aliases->AddAlias( "invert normals", "Surface.2D.Normals.Draw Inverse Normals", "Surface"); node->AddProperty( "front color", ColorProperty::New(0.0, 1.0, 0.0), renderer, overwrite ); aliases->AddAlias( "front color", "Surface.2D.Normals.Normals Color", "Surface"); node->AddProperty( "back color", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite ); aliases->AddAlias( "back color", "Surface.2D.Normals.Inverse Normals Color", "Surface"); node->AddProperty( "front normal lenth (px)", FloatProperty::New(10.0), renderer, overwrite ); aliases->AddAlias( "front normal lenth (px)", "Surface.2D.Normals.Normals Scale Factor", "Surface"); node->AddProperty( "back normal lenth (px)", FloatProperty::New(10.0), renderer, overwrite ); aliases->AddAlias( "back normal lenth (px)", "Surface.2D.Normals.Inverse Normals Scale Factor", "Surface"); node->AddProperty( "layer", IntProperty::New(100), renderer, overwrite); Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/Core/test/mitkSurfaceToSurfaceFilterTest.cpp b/Modules/Core/test/mitkSurfaceToSurfaceFilterTest.cpp index 7f26be3e42..0fe7ca5980 100644 --- a/Modules/Core/test/mitkSurfaceToSurfaceFilterTest.cpp +++ b/Modules/Core/test/mitkSurfaceToSurfaceFilterTest.cpp @@ -1,121 +1,117 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSurface.h" #include "mitkSurfaceToSurfaceFilter.h" #include "mitkCommon.h" #include "mitkNumericTypes.h" +#include "mitkTestingMacros.h" #include "vtkPolyData.h" #include "vtkSphereSource.h" -#include int mitkSurfaceToSurfaceFilterTest(int /*argc*/, char* /*argv*/[]) { mitk::Surface::Pointer surface; surface = mitk::Surface::New(); vtkSphereSource* sphereSource = vtkSphereSource::New(); sphereSource->SetCenter(0,0,0); sphereSource->SetRadius(5.0); sphereSource->SetThetaResolution(10); sphereSource->SetPhiResolution(10); sphereSource->Update(); vtkPolyData* polys = sphereSource->GetOutput(); surface->SetVtkPolyData( polys ); sphereSource->Delete(); mitk::SurfaceToSurfaceFilter::Pointer filter = mitk::SurfaceToSurfaceFilter::New(); - std::cout << "Testing mitk::SurfaceToSurfaceFilter::SetInput() and ::GetNumberOfInputs() : " ; + MITK_TEST_OUTPUT(<<"Testing mitk::SurfaceToSurfaceFilter::SetInput() and ::GetNumberOfInputs() : "); filter->SetInput( surface ); - if ( filter->GetNumberOfInputs() < 1 ) - { - std::cout<<"[FAILED] : zero inputs set "<GetNumberOfInputs() == 1, "Number of inputs must be 1" ); + MITK_TEST_OUTPUT(<<"Testing if GetInput returns the right Input : "); + mitk::Surface::Pointer input = const_cast(filter->GetInput()); + MITK_ASSERT_EQUAL(input, surface, "GetInput() should return correct input. "); - std::cout << "Testing if GetInput returns the right Input : " << std::endl; - if ( filter->GetInput() != surface ) - { - std::cout<<"[FAILED] : GetInput does not return correct input. "<GetInput(5) == NULL, "GetInput(5) should return NULL. "); + MITK_TEST_OUTPUT(<<"Testing whether Output is created correctly : "); + MITK_TEST_CONDITION(filter->GetNumberOfOutputs() == filter->GetNumberOfInputs(), "Test if number of outputs == number of inputs"); - if ( filter->GetInput(5) != NULL ) - { - std::cout<<"[FAILED] : GetInput returns inputs that were not set. "< is NULL" << std::endl; + mitk::Surface::Pointer outputSurface = filter->GetOutput(); + MITK_ASSERT_EQUAL(outputSurface, surface, "Test if output == input"); + + filter->Update(); + outputSurface = filter->GetOutput(); + MITK_TEST_CONDITION(outputSurface->GetSizeOfPolyDataSeries() == surface->GetSizeOfPolyDataSeries(), "Test if number of PolyDatas in PolyDataSeries of output == number of PolyDatas of input"); + mitk::SurfaceToSurfaceFilter::Pointer s2sFilter = mitk::SurfaceToSurfaceFilter::New(); + MITK_TEST_FOR_EXCEPTION(mitk::Exception, s2sFilter->CreateOutputForInput(500)); - std::cout << "Testing whether Output is created correctly : " << std::endl; - if ( filter->GetNumberOfOutputs() != filter->GetNumberOfInputs() ) + std::vector polydatas; + for (unsigned int i = 0; i < 5; ++i) { - std::cout <<"[FAILED] : number of outputs != number of inputs" << std::endl; - return EXIT_FAILURE; + sphereSource = vtkSphereSource::New(); + sphereSource->SetCenter(0,i,0); + sphereSource->SetRadius(5.0 + i); + sphereSource->SetThetaResolution(10); + sphereSource->SetPhiResolution(10); + sphereSource->Update(); + + vtkPolyData* poly = sphereSource->GetOutput(); + mitk::Surface::Pointer s = mitk::Surface::New(); + s->SetVtkPolyData( poly ); + s2sFilter->SetInput(i, s); + polydatas.push_back(s2sFilter->GetOutput(i)->GetVtkPolyData()); + sphereSource->Delete(); } - std::cout << "[SUCCESS] : number of inputs == number of outputs." << std::endl; - - mitk::Surface::Pointer outputSurface = filter->GetOutput(); - if ( outputSurface->GetVtkPolyData()->GetNumberOfPolys() != surface->GetVtkPolyData()->GetNumberOfPolys() ) + // Test if the outputs are not recreated each time another input is added + for (unsigned int i = 0; i < 5; ++i) { - std::cout << "[FAILED] : number of Polys in PolyData of output != number of Polys in PolyData of input" << std::endl; - return EXIT_FAILURE; + MITK_TEST_CONDITION(s2sFilter->GetOutput(i)->GetVtkPolyData() == polydatas.at(i), "Test if pointers are still equal"); } - std::cout << "[SUCCESS] : number of Polys in PolyData of input and output are identical." << std::endl; - - - filter->Update(); - outputSurface = filter->GetOutput(); - if ( outputSurface->GetSizeOfPolyDataSeries() != surface->GetSizeOfPolyDataSeries() ) + // Test if the outputs are recreated after calling CreateOutputsForAllInputs() + s2sFilter->CreateOutputsForAllInputs(); + for (unsigned int i = 0; i < 5; ++i) { - std::cout << "[FAILED] : number of PolyDatas in PolyDataSeries of output != number of PolyDatas of input" << std::endl; - return EXIT_FAILURE; + MITK_TEST_CONDITION(s2sFilter->GetOutput(i)->GetVtkPolyData() != polydatas.at(i), "Test if pointers are not equal"); } - std::cout << "[SUCCESS] : Size of PolyDataSeries of input and output are identical." << std::endl; - //std::cout << "Testing RemoveInputs() : " << std::endl; //unsigned int numOfInputs = filter->GetNumberOfInputs(); //filter->RemoveInputs( mitk::Surface::New() ); //if ( filter->GetNumberOfInputs() != numOfInputs ) //{ // std::cout << "[FAILED] : input was removed that was not set." << std::endl; // return EXIT_FAILURE; //} //std::cout << "[SUCCESS] : no input was removed that was not set." << std::endl; //filter->RemoveInputs( surface ); //if ( filter->GetNumberOfInputs() != 0 ) //{ // std::cout << "[FAILED] : existing input was not removed correctly." << std::endl; // return EXIT_FAILURE; //} //std::cout << "[SUCCESS] : existing input was removed correctly." << std::endl; - - - std::cout<<"[TEST DONE]"< -#include #include #include #include #include #include namespace mitk { RTDoseReader::RTDoseReader(){} RTDoseReader::~RTDoseReader(){} mitk::DataNode::Pointer RTDoseReader:: LoadRTDose(const char* filename) { DcmFileFormat fileformat; OFCondition outp = fileformat.loadFile(filename, EXS_Unknown); if(outp.bad()) { MITK_ERROR << "Cant read the file" << std::endl; } DcmDataset *dataset = fileformat.getDataset(); std::string name = filename; itk::FilenamesContainer file; file.push_back(name); mitk::DicomSeriesReader* reader = new mitk::DicomSeriesReader; mitk::DataNode::Pointer originalNode = reader->LoadDicomSeries(file,false); if(originalNode.IsNull()) { MITK_ERROR << "Error reading the dcm file" << std::endl; return 0; } mitk::Image::Pointer originalImage = dynamic_cast(originalNode->GetData()); DRTDoseIOD doseObject; OFCondition result = doseObject.read(*dataset); if(result.bad()) { MITK_ERROR << "Error reading the Dataset" << std::endl; return 0; } OFString gridScaling; Float32 gridscale; doseObject.getDoseGridScaling(gridScaling); gridscale = OFStandard::atof(gridScaling.c_str()); AccessByItk_1(originalImage, MultiplayGridScaling, gridscale); double prescripeDose = this->GetMaxDoseValue(dataset); originalNode->SetName("RT Dose"); originalNode->SetFloatProperty(mitk::Constants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str(),prescripeDose); originalNode->SetFloatProperty(mitk::Constants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), 40); originalNode->SetBoolProperty(mitk::Constants::DOSE_PROPERTY_NAME.c_str(),true); return originalNode; } template void RTDoseReader::MultiplayGridScaling(itk::Image* image, Float32 gridscale) { typedef itk::Image InputImageType; itk::ImageRegionIterator it(image, image->GetRequestedRegion()); for(it=it.Begin(); !it.IsAtEnd(); ++it) { it.Set(it.Get()*gridscale); } } double RTDoseReader::GetMaxDoseValue(DcmDataset* dataSet) { DRTDoseIOD doseObject; OFCondition result = doseObject.read(*dataSet); if(result.bad()) { MITK_ERROR << "Error reading the RT Dose dataset" << std::endl; return 0; } Uint16 rows, columns, frames; OFString nrframes, gridScaling; const Uint16 *pixelData = NULL; Float32 gridscale; Uint16 &rows_ref = rows; Uint16 &columns_ref = columns; doseObject.getRows(rows_ref); doseObject.getColumns(columns_ref); doseObject.getNumberOfFrames(nrframes); doseObject.getDoseGridScaling(gridScaling); frames = atoi(nrframes.c_str()); gridscale = OFStandard::atof(gridScaling.c_str()); dataSet->findAndGetUint16Array(DCM_PixelData, pixelData, 0); int size = columns*rows*frames; double highest = 0; for(int i=0; ihighest) { highest = pixelData[i] * gridscale; } } return highest; } } diff --git a/Modules/DiffusionImaging/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.cpp b/Modules/DiffusionImaging/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.cpp index 43e32282a7..f437cccdf5 100644 --- a/Modules/DiffusionImaging/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.cpp +++ b/Modules/DiffusionImaging/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.cpp @@ -1,864 +1,864 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkConnectomicsNetworkCreator.h" #include #include #include "mitkConnectomicsConstantsManager.h" #include "mitkImageAccessByItk.h" #include "mitkImageStatisticsHolder.h" #include "mitkImageCast.h" #include "itkImageRegionIteratorWithIndex.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 ) , m_UseCoMCoordinates( false ) , m_LabelsToCoordinatesMap() , m_MappingStrategy( EndElementPositionAvoidingWhiteMatter ) , m_EndPointSearchRadius( 10.0 ) , m_ZeroLabelInvalid( true ) , m_AbortConnection( false ) { } -mitk::ConnectomicsNetworkCreator::ConnectomicsNetworkCreator( mitk::Image::Pointer segmentation, mitk::FiberBundleX::Pointer fiberBundle ) +mitk::ConnectomicsNetworkCreator::ConnectomicsNetworkCreator( mitk::Image::Pointer segmentation, mitk::FiberBundle::Pointer fiberBundle ) : m_FiberBundle(fiberBundle) , m_Segmentation(segmentation) , m_ConNetwork( mitk::ConnectomicsNetwork::New() ) , idCounter(0) , m_LabelToVertexMap() , m_LabelToNodePropertyMap() , allowLoops( false ) , m_LabelsToCoordinatesMap() , m_MappingStrategy( EndElementPositionAvoidingWhiteMatter ) , m_EndPointSearchRadius( 10.0 ) , m_ZeroLabelInvalid( true ) , m_AbortConnection( false ) { mitk::CastToItkImage( segmentation, m_SegmentationItk ); } mitk::ConnectomicsNetworkCreator::~ConnectomicsNetworkCreator() { } -void mitk::ConnectomicsNetworkCreator::SetFiberBundle(mitk::FiberBundleX::Pointer fiberBundle) +void mitk::ConnectomicsNetworkCreator::SetFiberBundle(mitk::FiberBundle::Pointer fiberBundle) { m_FiberBundle = fiberBundle; } void mitk::ConnectomicsNetworkCreator::SetSegmentation(mitk::Image::Pointer segmentation) { m_Segmentation = segmentation; mitk::CastToItkImage( segmentation, m_SegmentationItk ); } 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 = mitk::ConnectomicsNetwork::New(); m_LabelToVertexMap.clear(); m_LabelToNodePropertyMap.clear(); idCounter = 0; vtkSmartPointer fiberPolyData = m_FiberBundle->GetFiberPolyData(); vtkSmartPointer vLines = fiberPolyData->GetLines(); vLines->InitTraversal(); 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 ); } if ( singleTract && ( singleTract->Size() > 0 ) ) { AddConnectionToNetwork( ReturnAssociatedVertexPairForLabelPair( ReturnLabelForFiberTract( singleTract, m_MappingStrategy ) ) ); m_AbortConnection = false; } } // Prune unconnected nodes //m_ConNetwork->PruneUnconnectedSingleNodes(); // provide network with geometry m_ConNetwork->SetGeometry( dynamic_cast(m_Segmentation->GetGeometry()->Clone().GetPointer()) ); m_ConNetwork->UpdateBounds(); m_ConNetwork->SetIsModified( true ); MBI_INFO << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_INFO_NETWORK_CREATED; } void mitk::ConnectomicsNetworkCreator::AddConnectionToNetwork(ConnectionType newConnection) { if( m_AbortConnection ) { MITK_DEBUG << "Connection aborted"; return; } VertexType vertexA = newConnection.first; VertexType vertexB = newConnection.second; // 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( m_ZeroLabelInvalid && ( label == 0 ) ) { m_AbortConnection = true; return ULONG_MAX; } // 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 JustEndPointVerticesNoLabel: { return JustEndPointVerticesNoLabelTest( singleTract ); } case EndElementPositionAvoidingWhiteMatter: { return EndElementPositionLabelAvoidingWhiteMatter( singleTract ); } case PrecomputeAndDistance: { return PrecomputeVertexLocationsBySegmentation( singleTract ); } } // To remove warnings, this code should never be reached MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_MAPPING; ImageLabelPairType nullPair( 0,0 ); 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; itk::Index<3> firstElementSegIndex, lastElementSegIndex; if( singleTract->front().Size() != 3 ) { MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3; } for( unsigned 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_SegmentationItk->GetPixel(firstElementSegIndex); int lastLabel = m_SegmentationItk->GetPixel(lastElementSegIndex ); labelpair.first = firstLabel; labelpair.second = lastLabel; // Add property to property map CreateNewNode( firstLabel, firstElementSegIndex, m_UseCoMCoordinates ); CreateNewNode( lastLabel, lastElementSegIndex, m_UseCoMCoordinates ); } 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; itk::Index<3> firstElementSegIndex, lastElementSegIndex; if( singleTract->front().Size() != 3 ) { MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3; } for( unsigned 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_SegmentationItk->GetPixel(firstElementSegIndex); int lastLabel = m_SegmentationItk->GetPixel(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 ); itk::Index<3> 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 ); itk::Index<3> tempIndex = lastElementSegIndex; LinearExtensionUntilGreyMatter( indexVectorOfPointsToUse, singleTract, tempLabel, tempIndex ); lastLabel = tempLabel; lastElementSegIndex = tempIndex; } if ( retractFront ) { // label and coordinate temp storage int tempLabel( firstLabel ); itk::Index<3> tempIndex = firstElementSegIndex; RetractionUntilBrainMatter( true, singleTract, tempLabel, tempIndex ); firstLabel = tempLabel; firstElementSegIndex = tempIndex; } if ( retractEnd ) { // label and coordinate temp storage int tempLabel( lastLabel ); itk::Index<3> 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 CreateNewNode( firstLabel, firstElementSegIndex, m_UseCoMCoordinates ); CreateNewNode( lastLabel, lastElementSegIndex, m_UseCoMCoordinates ); } 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; itk::Index<3> firstElementSegIndex, lastElementSegIndex; if( singleTract->front().Size() != 3 ) { MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3; } for( unsigned 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 CreateNewNode( firstLabel, firstElementSegIndex, m_UseCoMCoordinates ); CreateNewNode( lastLabel, lastElementSegIndex, m_UseCoMCoordinates ); } 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 )|| ( labelInQuestion == freesurfer_Left_Cerebellum_Cortex ) || ( labelInQuestion == freesurfer_Right_Cerebellum_Cortex ) || ( labelInQuestion == freesurfer_Brain_Stem ) ); 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, itk::Index<3> & 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( unsigned int index( 0 ); index < indexVectorOfPointsToUse.size(); index++ ) { if( indexVectorOfPointsToUse[ index ] < 0 ) { MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_BEYOND_START; return; } if( (unsigned int)indexVectorOfPointsToUse[ index ] > singleTract->Size() ) { MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_BEYOND_END; 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( unsigned 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( unsigned 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( unsigned int index = 0; index < differenceVector.size() ; index++ ) { sum = sum + differenceVector[ index ] * differenceVector[ index ]; } length = std::sqrt( sum ); for( unsigned int index = 0; index < differenceVector.size() ; index++ ) { differenceVector[ index ] = differenceVector[ index ] / length; } // follow line until first non white matter label itk::Index<3> tempIndex; int tempLabel( label ); bool keepOn( true ); itk::ImageRegion<3> itkRegion = m_SegmentationItk->GetLargestPossibleRegion(); 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 ] ); } if( itkRegion.IsInside( tempIndex ) ) { tempLabel = m_SegmentationItk->GetPixel( tempIndex ); } else { tempLabel = -1; } 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, itk::Index<3> & 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( unsigned 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( unsigned 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( unsigned int index = 0; index < differenceVector.size() ; index++ ) { sum = sum + differenceVector[ index ] * differenceVector[ index ]; } length = std::sqrt( sum ); // retract itk::Index<3> 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_SegmentationItk->GetPixel( tempIndex ); if( !IsBackgroundLabel( tempLabel ) ) { // check whether result is within the search space { mitk::Point3D endPoint, foundPointSegmentation, foundPointFiber; for( unsigned int index = 0; index < singleTract->front().Size(); index++ ) { // this is in fiber (world) coordinates endPoint.SetElement( index, singleTract->GetElement( retractionStartIndex ).GetElement( index ) ); } for( int index( 0 ); index < 3; index++ ) { foundPointSegmentation.SetElement( index, currentPoint.GetElement( index ) + ( 1.0 + parameter ) / ( 1.0 + length ) * differenceVector[ index ] ); } SegmentationToFiberCoords( foundPointSegmentation, foundPointFiber ); std::vector< double > finalDistance; finalDistance.resize( singleTract->front().Size() ); for( unsigned int index = 0; index < singleTract->front().Size(); index++ ) { finalDistance[ index ] = foundPointFiber.GetElement( index ) - endPoint.GetElement( index ); } // calculate length of direction vector double finalLength( 0.0 ); double finalSum( 0.0 ); for( unsigned int index = 0; index < finalDistance.size() ; index++ ) { finalSum = finalSum + finalDistance[ index ] * finalDistance[ index ]; } finalLength = std::sqrt( finalSum ); if( finalLength > m_EndPointSearchRadius ) { // the found point was not within the search space return; } } label = tempLabel; mitkIndex = tempIndex; return; } // hit next point without finding brain matter currentRetractionIndex = currentRetractionIndex + retractionStepIndexSize; if( ( currentRetractionIndex < 1 ) || ( (unsigned int)currentRetractionIndex > ( singleTract->Size() - 2 ) ) ) { keepRetracting = false; } } } } void mitk::ConnectomicsNetworkCreator::CalculateCenterOfMass() { const int dimensions = 3; int max = m_Segmentation->GetStatistics()->GetScalarValueMax(); int min = m_Segmentation->GetStatistics()->GetScalarValueMin(); int range = max - min +1; // each label owns a vector of coordinates std::vector< std::vector< std::vector< double> > > coordinatesPerLabelVector; coordinatesPerLabelVector.resize( range ); itk::ImageRegionIteratorWithIndex it_itkImage( m_SegmentationItk, m_SegmentationItk->GetLargestPossibleRegion() ); for( it_itkImage.GoToBegin(); !it_itkImage.IsAtEnd(); ++it_itkImage ) { std::vector< double > coordinates; coordinates.resize(dimensions); itk::Index< dimensions > index = it_itkImage.GetIndex(); for( int loop(0); loop < dimensions; loop++) { coordinates.at( loop ) = index.GetElement( loop ); } // add the coordinates to the corresponding label vector coordinatesPerLabelVector.at( it_itkImage.Value() - min ).push_back( coordinates ); } for(int currentIndex(0), currentLabel( min ); currentIndex < range; currentIndex++, currentLabel++ ) { std::vector< double > currentCoordinates; currentCoordinates.resize(dimensions); int numberOfPoints = coordinatesPerLabelVector.at( currentIndex ).size(); std::vector< double > sumCoords; sumCoords.resize( dimensions ); for( int loop(0); loop < numberOfPoints; loop++ ) { for( int loopDimension( 0 ); loopDimension < dimensions; loopDimension++ ) { sumCoords.at( loopDimension ) += coordinatesPerLabelVector.at( currentIndex ).at( loop ).at( loopDimension ); } } for( int loopDimension( 0 ); loopDimension < dimensions; loopDimension++ ) { currentCoordinates.at( loopDimension ) = sumCoords.at( loopDimension ) / numberOfPoints; } m_LabelsToCoordinatesMap.insert( std::pair< int, std::vector >( currentLabel, currentCoordinates ) ); } //can now use center of mass coordinates m_UseCoMCoordinates = true; } std::vector< double > mitk::ConnectomicsNetworkCreator::GetCenterOfMass( int label ) { // if label is not known, warn if( ! ( m_LabelsToCoordinatesMap.count( label ) > 0 ) ) { MITK_ERROR << "Label " << label << " not found. Could not return coordinates."; std::vector< double > nullVector; nullVector.resize(3); return nullVector; } //return associated coordinates return m_LabelsToCoordinatesMap.find( label )->second; } void mitk::ConnectomicsNetworkCreator::CreateNewNode( int label, itk::Index<3> index, bool useCoM ) { // Only create node if it does not exist yet if( ! ( m_LabelToNodePropertyMap.count( label ) > 0 ) ) { NetworkNode newNode; newNode.coordinates.resize( 3 ); if( !useCoM ) { for( unsigned int loop = 0; loop < newNode.coordinates.size() ; loop++ ) { newNode.coordinates[ loop ] = index[ loop ] ; } } else { std::vector labelCoords = GetCenterOfMass( label ); for( unsigned int loop = 0; loop < newNode.coordinates.size() ; loop++ ) { newNode.coordinates[ loop ] = labelCoords.at( loop ) ; } } newNode.label = LabelToString( label ); m_LabelToNodePropertyMap.insert( std::pair< ImageLabelType, NetworkNode >( label, newNode ) ); } } diff --git a/Modules/DiffusionImaging/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.h b/Modules/DiffusionImaging/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.h index 4e5a492589..a7d399ce82 100644 --- a/Modules/DiffusionImaging/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.h +++ b/Modules/DiffusionImaging/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.h @@ -1,249 +1,249 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkConnectomicsNetworkCreator_h #define mitkConnectomicsNetworkCreator_h #include #include #include #include "mitkCommon.h" #include "mitkImage.h" -#include "mitkFiberBundleX.h" +#include "mitkFiberBundle.h" #include "mitkConnectomicsNetwork.h" #include namespace mitk { /** * \brief Creates connectomics networks from fibers and parcellation * * This class needs a parcellation image and a fiber image to be set. Then you can create * a connectomics network from the two, using different strategies. */ class MITKCONNECTOMICS_EXPORT ConnectomicsNetworkCreator : public itk::Object { public: /** Enum for different ways to create the mapping from fibers to network */ enum MappingStrategy { EndElementPosition, EndElementPositionAvoidingWhiteMatter, JustEndPointVerticesNoLabel, PrecomputeAndDistance }; /** Standard class typedefs. */ /** Method for creation through the object factory. */ mitkClassMacro(ConnectomicsNetworkCreator, itk::Object); itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Type for Images **/ typedef itk::Image ITKImageType; /** Types for the standardized Tract **/ typedef itk::Point PointType; typedef itk::VectorContainer TractType; typedef itk::VectorContainer< unsigned int, TractType::Pointer > TractContainerType; //init via smartpointer /** Types for Network **/ typedef mitk::ConnectomicsNetwork::VertexDescriptorType VertexType; typedef mitk::ConnectomicsNetwork::EdgeDescriptorType EdgeType; typedef mitk::ConnectomicsNetwork::NetworkNode NetworkNode; typedef std::pair< VertexType, VertexType > ConnectionType; /** Types for labels **/ typedef int ImageLabelType; typedef std::pair< ImageLabelType, ImageLabelType > ImageLabelPairType; /** Given a fiber bundle and a parcellation are set, this will create a network from both */ void CreateNetworkFromFibersAndSegmentation(); - void SetFiberBundle(mitk::FiberBundleX::Pointer fiberBundle); + void SetFiberBundle(mitk::FiberBundle::Pointer fiberBundle); void SetSegmentation(mitk::Image::Pointer segmentation); mitk::ConnectomicsNetwork::Pointer GetNetwork(); itkSetMacro(MappingStrategy, MappingStrategy); itkSetMacro(EndPointSearchRadius, double); itkSetMacro(ZeroLabelInvalid, bool); /** \brief Calculate the locations of vertices * * Calculate the center of mass for each label and store the information. This will need a set parcellation image. * Unless this function is called the first location where a label is encountered will be used. After calling this function * the center of mass will be used instead. */ void CalculateCenterOfMass(); protected: //////////////////// Functions /////////////////////// ConnectomicsNetworkCreator(); - ConnectomicsNetworkCreator( mitk::Image::Pointer segmentation, mitk::FiberBundleX::Pointer fiberBundle ); + ConnectomicsNetworkCreator( mitk::Image::Pointer segmentation, mitk::FiberBundle::Pointer fiberBundle ); ~ConnectomicsNetworkCreator(); /** Add a connection to the network */ void AddConnectionToNetwork(ConnectionType newConnection); /** Determine if a label is already identified with a vertex, otherwise create a new one */ VertexType ReturnAssociatedVertexForLabel( ImageLabelType label ); /** Return the vertexes associated with a pair of labels */ ConnectionType ReturnAssociatedVertexPairForLabelPair( ImageLabelPairType labelpair ); /** Return the pair of labels which identify the areas connected by a single fiber */ ImageLabelPairType ReturnLabelForFiberTract( TractType::Pointer singleTract, MappingStrategy strategy ); /** Assign the additional information which should be part of the vertex */ void SupplyVertexWithInformation( ImageLabelType& label, VertexType& vertex ); /** Create a string from the label */ std::string LabelToString( ImageLabelType& label ); /** Check whether the label in question belongs to white matter according to the freesurfer table */ bool IsNonWhiteMatterLabel( int labelInQuestion ); /** Check whether the label in question belongs to background according to the freesurfer table */ bool IsBackgroundLabel( int labelInQuestion ); /** Extend a straight line through the given points and look for the first non white matter label It will try extend in the direction of the points in the vector so a vector {B,C} will result in extending from C in the direction C-B */ void LinearExtensionUntilGreyMatter( std::vector & indexVectorOfPointsToUse, TractType::Pointer singleTract, int & label, itk::Index<3> & mitkIndex ); /** Retract fiber until the first brain matter label is hit The bool parameter controls whether the front or the end is retracted */ void RetractionUntilBrainMatter( bool retractFront, TractType::Pointer singleTract, int & label, itk::Index<3> & mitkIndex ); /** \brief Get the location of the center of mass for a specific label * This can throw an exception if the label is not found. */ std::vector< double > GetCenterOfMass( int label ); /** Convert point to itk point */ itk::Point GetItkPoint(double point[3]); /** \brief Creates a new node * * A new node will be created, using the label and either the supplied coordinates * or the center of mass coordinates, depending on the supplied bool. */ void CreateNewNode( int label, itk::Index<3>, bool useIndex ); ///////// Mapping strategies ////////// /** Use the position of the end and starting element only to map to labels Map a fiber to a vertex by taking the value of the parcellation image at the same world coordinates as the last and first element of the tract.*/ ImageLabelPairType EndElementPositionLabel( TractType::Pointer singleTract ); /** Map by distance between elements and vertices depending on their volume First go through the parcellation and compute the coordinates of the future vertices. Assign a radius according on their volume. Then map an edge to a label by considering the nearest vertices and comparing the distance to them to their radii. */ ImageLabelPairType PrecomputeVertexLocationsBySegmentation( TractType::Pointer singleTract ); /** Use the position of the end and starting element only to map to labels Just take first and last position, no labelling, nothing */ ImageLabelPairType JustEndPointVerticesNoLabelTest( TractType::Pointer singleTract ); /** Use the position of the end and starting element unless it is in white matter, then search for nearby parcellation to map to labels Map a fiber to a vertex by taking the value of the parcellation image at the same world coordinates as the last and first element of the tract. If this happens to be white matter, then try to extend the fiber in a line and take the first non-white matter parcel, that is intersected. */ ImageLabelPairType EndElementPositionLabelAvoidingWhiteMatter( TractType::Pointer singleTract ); ///////// Conversions ////////// /** Convert fiber index to segmentation index coordinates */ void FiberToSegmentationCoords( mitk::Point3D& fiberCoord, mitk::Point3D& segCoord ); /** Convert segmentation index to fiber index coordinates */ void SegmentationToFiberCoords( mitk::Point3D& segCoord, mitk::Point3D& fiberCoord ); /////////////////////// Variables //////////////////////// - mitk::FiberBundleX::Pointer m_FiberBundle; + mitk::FiberBundle::Pointer m_FiberBundle; mitk::Image::Pointer m_Segmentation; ITKImageType::Pointer m_SegmentationItk; // the graph itself mitk::ConnectomicsNetwork::Pointer m_ConNetwork; // the id counter int idCounter; // the map mapping labels to vertices std::map< ImageLabelType, VertexType > m_LabelToVertexMap; // mapping labels to additional information std::map< ImageLabelType, NetworkNode > m_LabelToNodePropertyMap; // toggles whether edges between a node and itself can exist bool allowLoops; // toggles whether to use the center of mass coordinates bool m_UseCoMCoordinates; // stores the coordinates of labels std::map< int, std::vector< double> > m_LabelsToCoordinatesMap; // the straty to use for mapping MappingStrategy m_MappingStrategy; // search radius for finding a non white matter/background area. Should be in mm double m_EndPointSearchRadius; // toggles whether a node with the label 0 may be present bool m_ZeroLabelInvalid; // used internally to communicate a connection should not be added if the a problem // is encountered while adding it bool m_AbortConnection; //////////////////////// IDs //////////////////////////// // These IDs are the freesurfer ids used in parcellation static const int freesurfer_Left_Cerebral_White_Matter = 2; static const int freesurfer_Left_Cerebellum_White_Matter = 7; static const int freesurfer_Left_Cerebellum_Cortex = 8; static const int freesurfer_Brain_Stem = 16; static const int freesurfer_Right_Cerebral_White_Matter = 41; static const int freesurfer_Right_Cerebellum_White_Matter = 46; static const int freesurfer_Right_Cerebellum_Cortex = 47; }; }// end namespace mitk #endif // _mitkConnectomicsNetworkCreator_H_INCLUDED diff --git a/Modules/DiffusionImaging/Connectomics/Testing/mitkConnectomicsNetworkCreationTest.cpp b/Modules/DiffusionImaging/Connectomics/Testing/mitkConnectomicsNetworkCreationTest.cpp index 010261f01e..1af41ca778 100644 --- a/Modules/DiffusionImaging/Connectomics/Testing/mitkConnectomicsNetworkCreationTest.cpp +++ b/Modules/DiffusionImaging/Connectomics/Testing/mitkConnectomicsNetworkCreationTest.cpp @@ -1,113 +1,113 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Testing #include "mitkTestingMacros.h" #include "mitkTestFixture.h" // std includes #include // MITK includes #include "mitkConnectomicsNetworkCreator.h" #include "mitkIOUtil.h" // VTK includes #include class mitkConnectomicsNetworkCreationTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkConnectomicsNetworkCreationTestSuite); /// \todo Fix VTK memory leaks. Bug 18097. vtkDebugLeaks::SetExitError(0); MITK_TEST(CreateNetworkFromFibersAndParcellation); CPPUNIT_TEST_SUITE_END(); private: std::string m_ParcellationPath; std::string m_FiberPath; std::string m_ReferenceNetworkPath; public: /** * @brief Setup Always call this method before each Test-case to ensure correct and new intialization of the used members for a new test case. (If the members are not used in a test, the method does not need to be called). */ void setUp() { m_ReferenceNetworkPath = GetTestDataFilePath("DiffusionImaging/Connectomics/reference.cnf"); m_ParcellationPath = GetTestDataFilePath("DiffusionImaging/Connectomics/parcellation.nrrd"); m_FiberPath = GetTestDataFilePath("DiffusionImaging/Connectomics/fiberBundle.fib"); } void tearDown() { m_ReferenceNetworkPath = ""; m_ParcellationPath = ""; m_FiberPath = ""; } void CreateNetworkFromFibersAndParcellation() { // load fiber image std::vector fiberInfile = mitk::IOUtil::Load( m_FiberPath ); if( fiberInfile.empty() ) { std::string errorMessage = "Fiber Image at " + m_FiberPath + " could not be read. Aborting."; CPPUNIT_ASSERT_MESSAGE( errorMessage, false ); } mitk::BaseData* fiberBaseData = fiberInfile.at(0); - mitk::FiberBundleX* fiberBundle = dynamic_cast( fiberBaseData ); + mitk::FiberBundle* fiberBundle = dynamic_cast( fiberBaseData ); // load parcellation std::vector parcellationInFile = mitk::IOUtil::Load( m_ParcellationPath ); if( parcellationInFile.empty() ) { std::string errorMessage = "Parcellation at " + m_ParcellationPath + " could not be read. Aborting."; CPPUNIT_ASSERT_MESSAGE( errorMessage, false ); } mitk::BaseData* parcellationBaseData = parcellationInFile.at(0); mitk::Image* parcellationImage = dynamic_cast( parcellationBaseData ); // do creation mitk::ConnectomicsNetworkCreator::Pointer connectomicsNetworkCreator = mitk::ConnectomicsNetworkCreator::New(); connectomicsNetworkCreator->SetSegmentation( parcellationImage ); connectomicsNetworkCreator->SetFiberBundle( fiberBundle ); connectomicsNetworkCreator->CalculateCenterOfMass(); connectomicsNetworkCreator->SetEndPointSearchRadius( 15 ); connectomicsNetworkCreator->CreateNetworkFromFibersAndSegmentation(); // load network std::vector referenceFile = mitk::IOUtil::Load( m_ReferenceNetworkPath ); if( referenceFile.empty() ) { std::string errorMessage = "Reference Network at " + m_ReferenceNetworkPath + " could not be read. Aborting."; CPPUNIT_ASSERT_MESSAGE( errorMessage, false ); } mitk::BaseData* referenceBaseData = referenceFile.at(0); mitk::ConnectomicsNetwork* referenceNetwork = dynamic_cast( referenceBaseData ); mitk::ConnectomicsNetwork::Pointer network = connectomicsNetworkCreator->GetNetwork(); CPPUNIT_ASSERT_MESSAGE( "Comparing created and reference network.", mitk::Equal( network.GetPointer(), referenceNetwork, mitk::eps, true) ); } }; MITK_TEST_SUITE_REGISTRATION(mitkConnectomicsNetworkCreation) diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.h b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.h index c619d12ab4..0641de02ce 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.h +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.h @@ -1,102 +1,102 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /*=================================================================== This file is based heavily on a corresponding ITK filter. ===================================================================*/ #ifndef __itkDiffusionTensorPrincipalDirectionImageFilter_h_ #define __itkDiffusionTensorPrincipalDirectionImageFilter_h_ #include #include #include #include #include #include #include #include -#include +#include namespace itk{ /** \brief Extracts principal eigenvectors of the input tensors */ template< class TTensorPixelType, class TPDPixelType=float> class DiffusionTensorPrincipalDirectionImageFilter : public ImageToImageFilter< Image< DiffusionTensor3D, 3 >, Image< Vector< TPDPixelType, 3 >, 3 > > { public: typedef DiffusionTensorPrincipalDirectionImageFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ImageToImageFilter< Image< DiffusionTensor3D, 3 >, Image< Vector< TPDPixelType, 3 >, 3 > > Superclass; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Runtime information support. */ itkTypeMacro(DiffusionTensorPrincipalDirectionImageFilter, ImageToImageFilter) typedef TTensorPixelType TensorComponentType; typedef TPDPixelType DirectionPixelType; typedef typename Superclass::InputImageType InputImageType; typedef typename Superclass::OutputImageType OutputImageType; typedef typename Superclass::OutputImageRegionType OutputImageRegionType; typedef itk::Image ItkUcharImgType; typedef vnl_vector_fixed< double, 3 > DirectionType; void SetImage( const InputImageType *image ); // input itkSetMacro( MaskImage, ItkUcharImgType::Pointer) itkSetMacro( NormalizeVectors, bool) // output - itkGetMacro( OutputFiberBundle, mitk::FiberBundleX::Pointer) + itkGetMacro( OutputFiberBundle, mitk::FiberBundle::Pointer) itkGetMacro( NumDirectionsImage, ItkUcharImgType::Pointer) protected: DiffusionTensorPrincipalDirectionImageFilter(); ~DiffusionTensorPrincipalDirectionImageFilter() {} void PrintSelf(std::ostream& os, Indent indent) const; void BeforeThreadedGenerateData(); void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType ); void AfterThreadedGenerateData(); private: bool m_NormalizeVectors; ///< Normalizes the output vector to length 1 - mitk::FiberBundleX::Pointer m_OutputFiberBundle; ///< Vector field representation of the output vectors + mitk::FiberBundle::Pointer m_OutputFiberBundle; ///< Vector field representation of the output vectors ItkUcharImgType::Pointer m_NumDirectionsImage; ///< Image containing the number of fiber directions per voxel ItkUcharImgType::Pointer m_MaskImage; ///< Extraction is only performed inside of the binary mask float m_MaxEigenvalue; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkDiffusionTensorPrincipalDirectionImageFilter.txx" #endif #endif //__itkDiffusionTensorPrincipalDirectionImageFilter_h_ diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.txx b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.txx index ff06a24936..e7abe7c63a 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.txx +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.txx @@ -1,235 +1,235 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkDiffusionTensorPrincipalDirectionImageFilter_txx #define __itkDiffusionTensorPrincipalDirectionImageFilter_txx #include #include #include #include "itkDiffusionTensorPrincipalDirectionImageFilter.h" #include "itkImageRegionConstIterator.h" #include "itkImageRegionConstIteratorWithIndex.h" #include "itkImageRegionIterator.h" #include "itkArray.h" #include "vnl/vnl_vector.h" #include #include #include #include #include #include #define _USE_MATH_DEFINES #include namespace itk { //#define QBALL_RECON_PI M_PI template< class TTensorPixelType, class TPDPixelType> DiffusionTensorPrincipalDirectionImageFilter< TTensorPixelType, TPDPixelType> ::DiffusionTensorPrincipalDirectionImageFilter() : m_NormalizeVectors(true) , m_MaxEigenvalue(0.0) { this->SetNumberOfRequiredInputs( 1 ); } template< class TTensorPixelType, class TPDPixelType> void DiffusionTensorPrincipalDirectionImageFilter< TTensorPixelType, TPDPixelType> ::BeforeThreadedGenerateData() { typename InputImageType::Pointer inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) ); Vector spacing = inputImagePointer->GetSpacing(); mitk::Point3D origin = inputImagePointer->GetOrigin(); itk::Matrix direction = inputImagePointer->GetDirection(); ImageRegion<3> imageRegion = inputImagePointer->GetLargestPossibleRegion(); if (m_MaskImage.IsNull()) { m_MaskImage = ItkUcharImgType::New(); m_MaskImage->SetSpacing( spacing ); m_MaskImage->SetOrigin( origin ); m_MaskImage->SetDirection( direction ); m_MaskImage->SetRegions( imageRegion ); m_MaskImage->Allocate(); m_MaskImage->FillBuffer(1); } m_NumDirectionsImage = ItkUcharImgType::New(); m_NumDirectionsImage->SetSpacing( spacing ); m_NumDirectionsImage->SetOrigin( origin ); m_NumDirectionsImage->SetDirection( direction ); m_NumDirectionsImage->SetRegions( imageRegion ); m_NumDirectionsImage->Allocate(); m_NumDirectionsImage->FillBuffer(0); itk::Vector< TPDPixelType, 3 > nullVec; nullVec.Fill(0.0); typename OutputImageType::Pointer outputImage = OutputImageType::New(); outputImage->SetSpacing( spacing ); outputImage->SetOrigin( origin ); outputImage->SetDirection( direction ); outputImage->SetRegions( imageRegion ); outputImage->Allocate(); outputImage->FillBuffer(nullVec); this->SetNthOutput(0, outputImage); } template< class TTensorPixelType, class TPDPixelType> void DiffusionTensorPrincipalDirectionImageFilter< TTensorPixelType, TPDPixelType> ::AfterThreadedGenerateData() { vtkSmartPointer m_VtkCellArray = vtkSmartPointer::New(); vtkSmartPointer m_VtkPoints = vtkSmartPointer::New(); typename OutputImageType::Pointer directionImage = static_cast< OutputImageType* >( this->ProcessObject::GetPrimaryOutput() ); ImageRegionConstIterator< OutputImageType > it(directionImage, directionImage->GetLargestPossibleRegion() ); mitk::Vector3D spacing = directionImage->GetSpacing(); double minSpacing = spacing[0]; if (spacing[1]GetPixel(index)==0) { ++it; continue; } itk::Vector< float, 3 > pixel = directionImage->GetPixel(index); DirectionType dir; dir[0] = pixel[0]; dir[1] = pixel[1]; dir[2] = pixel[2]; if (!m_NormalizeVectors && m_MaxEigenvalue>0) dir /= m_MaxEigenvalue; vtkSmartPointer container = vtkSmartPointer::New(); itk::ContinuousIndex center; center[0] = index[0]; center[1] = index[1]; center[2] = index[2]; itk::Point worldCenter; directionImage->TransformContinuousIndexToPhysicalPoint( center, worldCenter ); itk::Point worldStart; worldStart[0] = worldCenter[0]-dir[0]/2 * minSpacing; worldStart[1] = worldCenter[1]-dir[1]/2 * minSpacing; worldStart[2] = worldCenter[2]-dir[2]/2 * minSpacing; vtkIdType id = m_VtkPoints->InsertNextPoint(worldStart.GetDataPointer()); container->GetPointIds()->InsertNextId(id); itk::Point worldEnd; worldEnd[0] = worldCenter[0]+dir[0]/2 * minSpacing; worldEnd[1] = worldCenter[1]+dir[1]/2 * minSpacing; worldEnd[2] = worldCenter[2]+dir[2]/2 * minSpacing; id = m_VtkPoints->InsertNextPoint(worldEnd.GetDataPointer()); container->GetPointIds()->InsertNextId(id); m_VtkCellArray->InsertNextCell(container); ++it; } vtkSmartPointer directionsPolyData = vtkSmartPointer::New(); directionsPolyData->SetPoints(m_VtkPoints); directionsPolyData->SetLines(m_VtkCellArray); - m_OutputFiberBundle = mitk::FiberBundleX::New(directionsPolyData); + m_OutputFiberBundle = mitk::FiberBundle::New(directionsPolyData); } template< class TTensorPixelType, class TPDPixelType> void DiffusionTensorPrincipalDirectionImageFilter< TTensorPixelType, TPDPixelType> ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType ) { typedef itk::DiffusionTensor3D TensorType; typedef ImageRegionConstIterator< InputImageType > InputIteratorType; typename InputImageType::Pointer inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) ); typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetPrimaryOutput()); ImageRegionIterator< OutputImageType > outIt(outputImage, outputRegionForThread); InputIteratorType inIt(inputImagePointer, outputRegionForThread ); ImageRegionIterator< ItkUcharImgType > nIt(m_NumDirectionsImage, outputRegionForThread ); while( !inIt.IsAtEnd() ) { typename InputImageType::IndexType index = inIt.GetIndex(); if (m_MaskImage->GetPixel(index)==0) { ++inIt; ++nIt; ++outIt; continue; } typename InputImageType::PixelType b = inIt.Get(); TensorType tensor = b.GetDataPointer(); typename OutputImageType::PixelType dir; typename TensorType::EigenValuesArrayType eigenvalues; typename TensorType::EigenVectorsMatrixType eigenvectors; if(tensor.GetTrace()!=0) { tensor.ComputeEigenAnalysis(eigenvalues, eigenvectors); vnl_vector_fixed vec; vec[0] = eigenvectors(2,0); vec[1] = eigenvectors(2,1); vec[2] = eigenvectors(2,2); if (!m_NormalizeVectors) vec *= eigenvalues[2]; if (eigenvalues[2]>m_MaxEigenvalue) m_MaxEigenvalue = eigenvalues[2]; dir[0] = (TPDPixelType)vec[0]; dir[1] = (TPDPixelType)vec[1]; dir[2] = (TPDPixelType)vec[2]; outIt.Set( dir ); m_NumDirectionsImage->SetPixel(index, 1); } ++outIt; ++inIt; ++nIt; } std::cout << "One Thread finished extraction" << std::endl; } template< class TTensorPixelType, class TPDPixelType> void DiffusionTensorPrincipalDirectionImageFilter< TTensorPixelType, TPDPixelType> ::PrintSelf(std::ostream& os, Indent indent) const { } } #endif // __itkDiffusionQballPrincipleDirectionsImageFilter_txx diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkDwiPhantomGenerationFilter.cpp b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkDwiPhantomGenerationFilter.cpp index 65e1842d1e..82ec7eb936 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkDwiPhantomGenerationFilter.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkDwiPhantomGenerationFilter.cpp @@ -1,388 +1,388 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkDwiPhantomGenerationFilter_cpp #define __itkDwiPhantomGenerationFilter_cpp #include #include #include #include "itkDwiPhantomGenerationFilter.h" #include #include #include #include #include #include #include #include #include #include namespace itk { //#define QBALL_RECON_PI 3.14159265358979323846 template< class TOutputScalarType > DwiPhantomGenerationFilter< TOutputScalarType > ::DwiPhantomGenerationFilter() : m_BValue(1000) , m_SignalScale(1000) , m_BaselineImages(0) , m_MaxBaseline(0) , m_MeanBaseline(0) , m_NoiseVariance(0.004) , m_GreyMatterAdc(0.01) , m_SimulateBaseline(true) , m_DefaultBaseline(1000) { this->SetNumberOfRequiredOutputs (1); m_Spacing.Fill(2.5); m_Origin.Fill(0.0); m_DirectionMatrix.SetIdentity(); m_ImageRegion.SetSize(0, 10); m_ImageRegion.SetSize(1, 10); m_ImageRegion.SetSize(2, 10); typename OutputImageType::Pointer outImage = OutputImageType::New(); outImage->SetSpacing( m_Spacing ); // Set the image spacing outImage->SetOrigin( m_Origin ); // Set the image origin outImage->SetDirection( m_DirectionMatrix ); // Set the image direction outImage->SetLargestPossibleRegion( m_ImageRegion ); outImage->SetBufferedRegion( m_ImageRegion ); outImage->SetRequestedRegion( m_ImageRegion ); outImage->SetVectorLength(QBALL_ODFSIZE); outImage->Allocate(); // ITKv4 migration fix : removing OutputImageType::PixelType(0.0) // the conversion is handled internally by the itk::Image typename OutputImageType::PixelType fillValue(0.0); outImage->FillBuffer( fillValue ); this->SetNthOutput (0, outImage); } template< class TOutputScalarType > void DwiPhantomGenerationFilter< TOutputScalarType > ::GenerateTensors() { MITK_INFO << "Generating tensors"; for (int i=0; i kernel; kernel.Fill(0); float e1=ADC*(1+2*FA/sqrt(3-2*FA*FA)); float e2=ADC*(1-FA/sqrt(3-2*FA*FA)); float e3=e2; kernel.SetElement(0,e1); kernel.SetElement(3,e2); kernel.SetElement(5,e3); if (m_SimulateBaseline) { double l2 = GetTensorL2Norm(kernel); if (l2>m_MaxBaseline) m_MaxBaseline = l2; } MITK_INFO << "Kernel FA: " << kernel.GetFractionalAnisotropy(); vnl_vector_fixed kernelDir; kernelDir[0]=1; kernelDir[1]=0; kernelDir[2]=0; itk::DiffusionTensor3D tensor; vnl_vector_fixed dir = m_TensorDirection.at(i); MITK_INFO << "Tensor direction: " << dir; dir.normalize(); vnl_vector_fixed axis = vnl_cross_3d(kernelDir, dir); axis.normalize(); vnl_quaternion rotation(axis, acos(dot_product(kernelDir, dir))); rotation.normalize(); vnl_matrix_fixed matrix = rotation.rotation_matrix_transpose(); vnl_matrix_fixed tensorMatrix; tensorMatrix[0][0] = kernel[0]; tensorMatrix[0][1] = kernel[1]; tensorMatrix[0][2] = kernel[2]; tensorMatrix[1][0] = kernel[1]; tensorMatrix[1][1] = kernel[3]; tensorMatrix[1][2] = kernel[4]; tensorMatrix[2][0] = kernel[2]; tensorMatrix[2][1] = kernel[4]; tensorMatrix[2][2] = kernel[5]; tensorMatrix = matrix.transpose()*tensorMatrix*matrix; tensor[0] = tensorMatrix[0][0]; tensor[1] = tensorMatrix[0][1]; tensor[2] = tensorMatrix[0][2]; tensor[3] = tensorMatrix[1][1]; tensor[4] = tensorMatrix[1][2]; tensor[5] = tensorMatrix[2][2]; m_TensorList.push_back(tensor); } } template< class TOutputScalarType > void DwiPhantomGenerationFilter< TOutputScalarType >::AddNoise(typename OutputImageType::PixelType& pix) { for( unsigned int i=0; iGetNormalVariate(0.0, m_NoiseVariance), 2) + pow(m_SignalScale*m_RandGen->GetNormalVariate(0.0, m_NoiseVariance),2)); pix[i] += val; } } template< class TOutputScalarType > typename DwiPhantomGenerationFilter< TOutputScalarType >::OutputImageType::PixelType DwiPhantomGenerationFilter< TOutputScalarType >::SimulateMeasurement(itk::DiffusionTensor3D& T, float weight) { typename OutputImageType::PixelType out; out.SetSize(m_GradientList.size()); out.Fill(0); TOutputScalarType s0 = m_DefaultBaseline; if (m_SimulateBaseline) s0 = (GetTensorL2Norm(T)/m_MaxBaseline)*m_SignalScale; for( unsigned int i=0; i0.0001) { itk::DiffusionTensor3D S; S[0] = g[0]*g[0]; S[1] = g[1]*g[0]; S[2] = g[2]*g[0]; S[3] = g[1]*g[1]; S[4] = g[2]*g[1]; S[5] = g[2]*g[2]; double D = T[0]*S[0] + T[1]*S[1] + T[2]*S[2] + T[1]*S[1] + T[3]*S[3] + T[4]*S[4] + T[2]*S[2] + T[4]*S[4] + T[5]*S[5]; // check for corrupted tensor and generate signal if (D>=0) { D = weight*s0*exp ( -m_BValue * D ); out[i] = static_cast( D ); } } else out[i] = s0; } return out; } template< class TOutputScalarType > void DwiPhantomGenerationFilter< TOutputScalarType > ::GenerateData() { if (m_NoiseVariance < 0) m_NoiseVariance = 0.001; if (!m_SimulateBaseline) { MITK_INFO << "Baseline image values are set to default. Noise variance value is treated as SNR!"; if (m_NoiseVariance <= 0) m_NoiseVariance = 0.0001; if (m_NoiseVariance>99) m_NoiseVariance = 0; else { m_NoiseVariance = m_DefaultBaseline/(m_NoiseVariance*m_SignalScale); m_NoiseVariance *= m_NoiseVariance; } } m_RandGen = Statistics::MersenneTwisterRandomVariateGenerator::New(); m_RandGen->SetSeed(); typename OutputImageType::Pointer outImage = OutputImageType::New(); outImage->SetSpacing( m_Spacing ); outImage->SetOrigin( m_Origin ); outImage->SetDirection( m_DirectionMatrix ); outImage->SetLargestPossibleRegion( m_ImageRegion ); outImage->SetBufferedRegion( m_ImageRegion ); outImage->SetRequestedRegion( m_ImageRegion ); outImage->SetVectorLength(m_GradientList.size()); outImage->Allocate(); typename OutputImageType::PixelType pix; pix.SetSize(m_GradientList.size()); pix.Fill(0.0); outImage->FillBuffer(pix); this->SetNthOutput (0, outImage); double minSpacing = m_Spacing[0]; if (m_Spacing[1] nullVec; nullVec.Fill(0.0); ItkDirectionImage::Pointer img = ItkDirectionImage::New(); img->SetSpacing( m_Spacing ); img->SetOrigin( m_Origin ); img->SetDirection( m_DirectionMatrix ); img->SetRegions( m_ImageRegion ); img->Allocate(); img->FillBuffer(nullVec); m_DirectionImageContainer->InsertElement(m_DirectionImageContainer->Size(), img); } m_NumDirectionsImage = ItkUcharImgType::New(); m_NumDirectionsImage->SetSpacing( m_Spacing ); m_NumDirectionsImage->SetOrigin( m_Origin ); m_NumDirectionsImage->SetDirection( m_DirectionMatrix ); m_NumDirectionsImage->SetRegions( m_ImageRegion ); m_NumDirectionsImage->Allocate(); m_NumDirectionsImage->FillBuffer(0); m_SNRImage = ItkFloatImgType::New(); m_SNRImage->SetSpacing( m_Spacing ); m_SNRImage->SetOrigin( m_Origin ); m_SNRImage->SetDirection( m_DirectionMatrix ); m_SNRImage->SetRegions( m_ImageRegion ); m_SNRImage->Allocate(); m_SNRImage->FillBuffer(0); vtkSmartPointer m_VtkCellArray = vtkSmartPointer::New(); vtkSmartPointer m_VtkPoints = vtkSmartPointer::New(); m_BaselineImages = 0; for( unsigned int i=0; i IteratorOutputType; IteratorOutputType it (outImage, m_ImageRegion); // isotropic tensor itk::DiffusionTensor3D isoTensor; isoTensor.Fill(0); float e1 = m_GreyMatterAdc; float e2 = m_GreyMatterAdc; float e3 = m_GreyMatterAdc; isoTensor.SetElement(0,e1); isoTensor.SetElement(3,e2); isoTensor.SetElement(5,e3); m_MaxBaseline = GetTensorL2Norm(isoTensor); GenerateTensors(); // simulate measurement m_MeanBaseline = 0; double noiseStdev = sqrt(m_NoiseVariance); while(!it.IsAtEnd()) { pix = it.Get(); typename OutputImageType::IndexType index = it.GetIndex(); int numDirs = 0; for (int i=0; iGetPixel(index)!=0) { numDirs++; pix += SimulateMeasurement(m_TensorList[i], m_TensorWeight[i]); // set direction image pixel ItkDirectionImage::Pointer img = m_DirectionImageContainer->GetElement(i); itk::Vector< float, 3 > pixel = img->GetPixel(index); vnl_vector_fixed dir = m_TensorDirection.at(i); dir.normalize(); dir *= m_TensorWeight.at(i); pixel.SetElement(0, dir[0]); pixel.SetElement(1, dir[1]); pixel.SetElement(2, dir[2]); img->SetPixel(index, pixel); vtkSmartPointer container = vtkSmartPointer::New(); itk::ContinuousIndex center; center[0] = index[0]; center[1] = index[1]; center[2] = index[2]; itk::Point worldCenter; outImage->TransformContinuousIndexToPhysicalPoint( center, worldCenter ); itk::Point worldStart; worldStart[0] = worldCenter[0]-dir[0]/2 * minSpacing; worldStart[1] = worldCenter[1]-dir[1]/2 * minSpacing; worldStart[2] = worldCenter[2]-dir[2]/2 * minSpacing; vtkIdType id = m_VtkPoints->InsertNextPoint(worldStart.GetDataPointer()); container->GetPointIds()->InsertNextId(id); itk::Point worldEnd; worldEnd[0] = worldCenter[0]+dir[0]/2 * minSpacing; worldEnd[1] = worldCenter[1]+dir[1]/2 * minSpacing; worldEnd[2] = worldCenter[2]+dir[2]/2 * minSpacing; id = m_VtkPoints->InsertNextPoint(worldEnd.GetDataPointer()); container->GetPointIds()->InsertNextId(id); m_VtkCellArray->InsertNextCell(container); } } if (numDirs>1) { for (int i=0; iSetPixel(index, numDirs); if (m_NoiseVariance>0) m_SNRImage->SetPixel(index, pix[0]/(noiseStdev*m_SignalScale)); ++it; } m_MeanBaseline /= m_ImageRegion.GetNumberOfPixels(); if (m_NoiseVariance>0) MITK_INFO << "Mean SNR: " << m_MeanBaseline/(noiseStdev*m_SignalScale); else MITK_INFO << "No noise added"; // add rician noise it.GoToBegin(); while(!it.IsAtEnd()) { pix = it.Get(); AddNoise(pix); it.Set(pix); ++it; } // generate fiber bundle vtkSmartPointer directionsPolyData = vtkSmartPointer::New(); directionsPolyData->SetPoints(m_VtkPoints); directionsPolyData->SetLines(m_VtkCellArray); - m_OutputFiberBundle = mitk::FiberBundleX::New(directionsPolyData); + m_OutputFiberBundle = mitk::FiberBundle::New(directionsPolyData); } template< class TOutputScalarType > double DwiPhantomGenerationFilter< TOutputScalarType >::GetTensorL2Norm(itk::DiffusionTensor3D& T) { return sqrt(T[0]*T[0] + T[3]*T[3] + T[5]*T[5] + T[1]*T[2]*2.0 + T[2]*T[4]*2.0 + T[1]*T[4]*2.0); } } #endif // __itkDwiPhantomGenerationFilter_cpp diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkDwiPhantomGenerationFilter.h b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkDwiPhantomGenerationFilter.h index ced3a05ce8..67788a323a 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkDwiPhantomGenerationFilter.h +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkDwiPhantomGenerationFilter.h @@ -1,152 +1,152 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /*========================================================================= Program: Insight Segmentation & Registration Toolkit Module: $RCSfile: itkDiffusionTensor3DReconstructionImageFilter.h,v $ Language: C++ Date: $Date: 2006-03-27 17:01:06 $ Version: $Revision: 1.12 $ Copyright (c) Insight Software Consortium. All rights reserved. See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm 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 __itkDwiPhantomGenerationFilter_h_ #define __itkDwiPhantomGenerationFilter_h_ #include #include #include #include -#include +#include namespace itk{ /** * \brief Generation of synthetic diffusion weighted images using a second rank tensor model. */ template< class TOutputScalarType > class DwiPhantomGenerationFilter : public ImageSource< itk::VectorImage > { public: typedef DwiPhantomGenerationFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ImageSource< itk::VectorImage > Superclass; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Runtime information support. */ itkTypeMacro(DwiPhantomGenerationFilter, ImageSource) typedef typename Superclass::OutputImageType OutputImageType; typedef typename Superclass::OutputImageRegionType OutputImageRegionType; typedef itk::VectorContainer< int, double > AnglesContainerType; typedef Vector GradientType; typedef std::vector GradientListType; typedef itk::Matrix MatrixType; typedef itk::Image ItkUcharImgType; typedef itk::Image ItkFloatImgType; typedef Image< Vector< float, 3 >, 3> ItkDirectionImage; typedef VectorContainer< unsigned int, ItkDirectionImage::Pointer > ItkDirectionImageContainer; void SetGradientList(GradientListType gradientList){m_GradientList = gradientList;} void SetSignalRegions(std::vector< ItkUcharImgType::Pointer > signalRegions){m_SignalRegions = signalRegions;} void SetTensorFA(std::vector< float > faList){m_TensorFA = faList;} void SetTensorADC(std::vector< float > adcList){m_TensorADC = adcList;} void SetTensorWeight(std::vector< float > weightList){m_TensorWeight = weightList;} void SetTensorDirection(std::vector< vnl_vector_fixed > directionList){m_TensorDirection = directionList;} // input parameters itkSetMacro( BValue, float ) ///< signal parameter itkSetMacro( SignalScale, float ) ///< scaling factor for signal itkSetMacro( NoiseVariance, double ) ///< variance of rician noise itkSetMacro( GreyMatterAdc, float ) ///< ADC of isotropic diffusion tensor itkSetMacro( Spacing, mitk::Vector3D ) ///< parameter of output image itkSetMacro( Origin, mitk::Point3D ) ///< parameter of output image itkSetMacro( DirectionMatrix, MatrixType ) ///< parameter of output image itkSetMacro( ImageRegion, ImageRegion<3> ) ///< parameter of output image itkSetMacro( SimulateBaseline, bool ) ///< generate baseline image values as the l2 norm of the corresponding tensor used for the diffusion signal generation // output itkGetMacro( DirectionImageContainer, ItkDirectionImageContainer::Pointer) ///< contains one vectorimage for each input ROI itkGetMacro( NumDirectionsImage, ItkUcharImgType::Pointer) ///< contains number of directions per voxel itkGetMacro( SNRImage, ItkFloatImgType::Pointer) ///< contains local SNR values - itkGetMacro( OutputFiberBundle, mitk::FiberBundleX::Pointer) ///< output vector field + itkGetMacro( OutputFiberBundle, mitk::FiberBundle::Pointer) ///< output vector field protected: DwiPhantomGenerationFilter(); ~DwiPhantomGenerationFilter(){} void GenerateData(); private: // image variables itk::Vector m_Spacing; mitk::Point3D m_Origin; itk::Matrix m_DirectionMatrix; ImageRegion<3> m_ImageRegion; ItkDirectionImageContainer::Pointer m_DirectionImageContainer; ///< contains one vectorimage for each input ROI ItkUcharImgType::Pointer m_NumDirectionsImage; ///< contains number of directions per voxel ItkFloatImgType::Pointer m_SNRImage; ///< contains local SNR values - mitk::FiberBundleX::Pointer m_OutputFiberBundle; ///< output vector field + mitk::FiberBundle::Pointer m_OutputFiberBundle; ///< output vector field // signal regions std::vector< ItkUcharImgType::Pointer > m_SignalRegions; ///< binary images defining the regions for the signal generation std::vector< float > m_TensorFA; ///< kernel tensor parameter std::vector< float > m_TensorADC; ///< kernel tensor parameter std::vector< float > m_TensorWeight; ///< weight factor of the signal std::vector< vnl_vector_fixed > m_TensorDirection; ///< principal direction of the kernel tensor in the different ROIs // signal related variable GradientListType m_GradientList; ///< list of used diffusion gradient directions std::vector< itk::DiffusionTensor3D > m_TensorList; ///< kernel tensor rotated in the different directions float m_BValue; ///< signal parameter float m_SignalScale; ///< scaling factor for signal Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandGen; int m_BaselineImages; ///< number of simulated baseline images double m_MaxBaseline; ///< maximum value of the baseline image double m_MeanBaseline; ///< mean value of the baseline image double m_NoiseVariance; ///< variance of rician noise float m_GreyMatterAdc; ///< ADC of isotropic diffusion tensor bool m_SimulateBaseline; ///< generate baseline image values as the l2 norm of the corresponding tensor used for the diffusion signal generation TOutputScalarType m_DefaultBaseline; ///< default value for baseline image double GetTensorL2Norm(itk::DiffusionTensor3D& T); void GenerateTensors(); ///< rotates kernel tensor in the direction of the input direction vectors typename OutputImageType::PixelType SimulateMeasurement(itk::DiffusionTensor3D& tensor, float weight); void AddNoise(typename OutputImageType::PixelType& pix); ///< Adds rician noise to the input pixel }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkDwiPhantomGenerationFilter.cpp" #endif #endif //__itkDwiPhantomGenerationFilter_h_ diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkFiniteDiffOdfMaximaExtractionFilter.cpp b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkFiniteDiffOdfMaximaExtractionFilter.cpp index 5d6d751d14..b2f8429ad2 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkFiniteDiffOdfMaximaExtractionFilter.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkFiniteDiffOdfMaximaExtractionFilter.cpp @@ -1,520 +1,520 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkFiniteDiffOdfMaximaExtractionFilter_cpp #define __itkFiniteDiffOdfMaximaExtractionFilter_cpp #include "itkFiniteDiffOdfMaximaExtractionFilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace boost::math; namespace itk { static bool CompareVectors(const vnl_vector_fixed< double, 3 >& v1, const vnl_vector_fixed< double, 3 >& v2) { return (v1.magnitude()>v2.magnitude()); } template< class PixelType, int ShOrder, int NrOdfDirections > FiniteDiffOdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections> ::FiniteDiffOdfMaximaExtractionFilter() : m_NormalizationMethod(MAX_VEC_NORM) , m_MaxNumPeaks(2) , m_PeakThreshold(0.4) , m_AbsolutePeakThreshold(0) , m_ClusteringThreshold(0.9) , m_AngularThreshold(0.7) , m_NumCoeffs((ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder) , m_Toolkit(FSL) { this->SetNumberOfRequiredInputs(1); } template< class PixelType, int ShOrder, int NrOdfDirections > void FiniteDiffOdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections> ::FindCandidatePeaks(OdfType& odf, double thr, std::vector< DirectionType >& container) { double gfa = odf.GetGeneralizedFractionalAnisotropy(); //Find the peaks using a finite difference method bool flag = true; vnl_vector_fixed< bool, NrOdfDirections > used; used.fill(false); //Find the peaks for (int i=0; ithr && val*gfa>m_AbsolutePeakThreshold) // limit to one hemisphere ??? { flag = true; std::vector< int > neighbours = odf.GetNeighbors(i); for (unsigned int j=0; j std::vector< vnl_vector_fixed< double, 3 > > FiniteDiffOdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections>::MeanShiftClustering(std::vector< vnl_vector_fixed< double, 3 > >& inDirs) { std::vector< DirectionType > outDirs; if (inDirs.empty()) return inDirs; DirectionType oldMean, currentMean, workingMean; std::vector< int > touched; // initialize touched.resize(inDirs.size(), 0); bool free = true; currentMean = inDirs[0]; // initialize first seed while (free) { oldMean.fill(0.0); // start mean-shift clustering float angle = 0.0; int counter = 0; while ((currentMean-oldMean).magnitude()>0.0001) { counter = 0; oldMean = currentMean; workingMean = oldMean; workingMean.normalize(); currentMean.fill(0.0); for (unsigned int i=0; i=m_ClusteringThreshold) { currentMean += inDirs[i]; touched[i] = 1; counter++; } else if (-angle>=m_ClusteringThreshold) { currentMean -= inDirs[i]; touched[i] = 1; counter++; } } } // found stable mean if (counter>0) { float mag = currentMean.magnitude(); if (mag>0) { currentMean /= mag; outDirs.push_back(currentMean); } } // find next unused seed free = false; for (unsigned int i=0; i void FiniteDiffOdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections> ::BeforeThreadedGenerateData() { typename CoefficientImageType::Pointer ShCoeffImage = static_cast< CoefficientImageType* >( this->ProcessObject::GetInput(0) ); itk::Vector spacing = ShCoeffImage->GetSpacing(); double minSpacing = spacing[0]; if (spacing[1]GetOrigin(); itk::Matrix direction = ShCoeffImage->GetDirection(); ImageRegion<3> imageRegion = ShCoeffImage->GetLargestPossibleRegion(); if (m_MaskImage.IsNotNull()) { origin = m_MaskImage->GetOrigin(); direction = m_MaskImage->GetDirection(); imageRegion = m_MaskImage->GetLargestPossibleRegion(); } m_DirectionImageContainer = ItkDirectionImageContainer::New(); for (unsigned int i=0; i nullVec; nullVec.Fill(0.0); ItkDirectionImage::Pointer img = ItkDirectionImage::New(); img->SetSpacing( spacing ); img->SetOrigin( origin ); img->SetDirection( direction ); img->SetRegions( imageRegion ); img->Allocate(); img->FillBuffer(nullVec); m_DirectionImageContainer->InsertElement(m_DirectionImageContainer->Size(), img); } if (m_MaskImage.IsNull()) { m_MaskImage = ItkUcharImgType::New(); m_MaskImage->SetSpacing( spacing ); m_MaskImage->SetOrigin( origin ); m_MaskImage->SetDirection( direction ); m_MaskImage->SetRegions( imageRegion ); m_MaskImage->Allocate(); m_MaskImage->FillBuffer(1); } m_NumDirectionsImage = ItkUcharImgType::New(); m_NumDirectionsImage->SetSpacing( spacing ); m_NumDirectionsImage->SetOrigin( origin ); m_NumDirectionsImage->SetDirection( direction ); m_NumDirectionsImage->SetRegions( imageRegion ); m_NumDirectionsImage->Allocate(); m_NumDirectionsImage->FillBuffer(0); this->SetNumberOfIndexedOutputs(m_MaxNumPeaks); // calculate SH basis OdfType odf; vnl_matrix_fixed* directions = odf.GetDirections(); vnl_matrix< double > sphCoords; std::vector< DirectionType > dirs; for (int i=0; iget_column(i)); Cart2Sph(dirs, sphCoords); // convert candidate peaks to spherical angles m_ShBasis = CalcShBasis(sphCoords); // evaluate spherical harmonics at each peak MITK_INFO << "Starting finite differences maximum extraction"; MITK_INFO << "ODF sampling points: " << NrOdfDirections; MITK_INFO << "SH order: " << ShOrder; MITK_INFO << "Maximum peaks: " << m_MaxNumPeaks; MITK_INFO << "Relative threshold: " << m_PeakThreshold; MITK_INFO << "Absolute threshold: " << m_AbsolutePeakThreshold; MITK_INFO << "Clustering threshold: " << m_ClusteringThreshold; MITK_INFO << "Angular threshold: " << m_AngularThreshold; } template< class PixelType, int ShOrder, int NrOdfDirections > void FiniteDiffOdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections> ::AfterThreadedGenerateData() { MITK_INFO << "Generating vector field"; vtkSmartPointer m_VtkCellArray = vtkSmartPointer::New(); vtkSmartPointer m_VtkPoints = vtkSmartPointer::New(); typename CoefficientImageType::Pointer ShCoeffImage = static_cast< CoefficientImageType* >( this->ProcessObject::GetInput(0) ); ImageRegionConstIterator< CoefficientImageType > cit(ShCoeffImage, ShCoeffImage->GetLargestPossibleRegion() ); mitk::Vector3D spacing = ShCoeffImage->GetSpacing(); double minSpacing = spacing[0]; if (spacing[1]GetLargestPossibleRegion().GetSize()[0]*ShCoeffImage->GetLargestPossibleRegion().GetSize()[1]*ShCoeffImage->GetLargestPossibleRegion().GetSize()[2]; boost::progress_display disp(maxProgress); while( !cit.IsAtEnd() ) { ++disp; typename CoefficientImageType::IndexType index = cit.GetIndex(); if (m_MaskImage->GetPixel(index)==0) { ++cit; continue; } for (unsigned int i=0; iSize(); i++) { ItkDirectionImage::Pointer img = m_DirectionImageContainer->GetElement(i); itk::Vector< float, 3 > pixel = img->GetPixel(index); DirectionType dir; dir[0] = pixel[0]; dir[1] = pixel[1]; dir[2] = pixel[2]; vtkSmartPointer container = vtkSmartPointer::New(); itk::ContinuousIndex center; center[0] = index[0]; center[1] = index[1]; center[2] = index[2]; itk::Point worldCenter; m_MaskImage->TransformContinuousIndexToPhysicalPoint( center, worldCenter ); itk::Point worldStart; worldStart[0] = worldCenter[0]-dir[0]/2 * minSpacing; worldStart[1] = worldCenter[1]-dir[1]/2 * minSpacing; worldStart[2] = worldCenter[2]-dir[2]/2 * minSpacing; vtkIdType id = m_VtkPoints->InsertNextPoint(worldStart.GetDataPointer()); container->GetPointIds()->InsertNextId(id); itk::Point worldEnd; worldEnd[0] = worldCenter[0]+dir[0]/2 * minSpacing; worldEnd[1] = worldCenter[1]+dir[1]/2 * minSpacing; worldEnd[2] = worldCenter[2]+dir[2]/2 * minSpacing; id = m_VtkPoints->InsertNextPoint(worldEnd.GetDataPointer()); container->GetPointIds()->InsertNextId(id); m_VtkCellArray->InsertNextCell(container); } ++cit; } vtkSmartPointer directionsPolyData = vtkSmartPointer::New(); directionsPolyData->SetPoints(m_VtkPoints); directionsPolyData->SetLines(m_VtkCellArray); - m_OutputFiberBundle = mitk::FiberBundleX::New(directionsPolyData); + m_OutputFiberBundle = mitk::FiberBundle::New(directionsPolyData); for (unsigned int i=0; iSize(); i++) { ItkDirectionImage::Pointer img = m_DirectionImageContainer->GetElement(i); this->SetNthOutput(i, img); } } template< class PixelType, int ShOrder, int NrOdfDirections > void FiniteDiffOdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections> ::ThreadedGenerateData( const OutputImageRegionType& outputRegionForThread, ThreadIdType threadID ) { typename CoefficientImageType::Pointer ShCoeffImage = static_cast< CoefficientImageType* >( this->ProcessObject::GetInput(0) ); ImageRegionConstIterator< CoefficientImageType > cit(ShCoeffImage, outputRegionForThread ); OdfType odf; while( !cit.IsAtEnd() ) { typename CoefficientImageType::IndexType index = cit.GetIndex(); if (m_MaskImage->GetPixel(index)==0) { ++cit; continue; } CoefficientPixelType c = cit.Get(); // calculate ODF double max = 0; odf.Fill(0.0); for (int i=0; imax) max = odf[i]; } if (max<0.0001) { ++cit; continue; } std::vector< DirectionType > candidates, peaks, temp; peaks.clear(); max *= m_PeakThreshold; // relative threshold FindCandidatePeaks(odf, max, candidates); // find all local maxima candidates = MeanShiftClustering(candidates); // cluster maxima vnl_matrix< double > shBasis, sphCoords; Cart2Sph(candidates, sphCoords); // convert candidate peaks to spherical angles shBasis = CalcShBasis(sphCoords); // evaluate spherical harmonics at each peak max = 0.0; for (unsigned int i=0; imax) max = val; peaks.push_back(candidates[i]*val); } std::sort( peaks.begin(), peaks.end(), CompareVectors ); // sort peaks // kick out directions to close to a larger direction (too far away to cluster but too close to keep) unsigned int m = peaks.size(); if ( m>m_DirectionImageContainer->Size() ) m = m_DirectionImageContainer->Size(); for (unsigned int i=0; im_AngularThreshold && valm_DirectionImageContainer->Size() ) num = m_DirectionImageContainer->Size(); for (unsigned int i=0; i dir = peaks.at(i); ItkDirectionImage::Pointer img = m_DirectionImageContainer->GetElement(i); switch (m_NormalizationMethod) { case NO_NORM: break; case SINGLE_VEC_NORM: dir.normalize(); break; case MAX_VEC_NORM: dir /= max; break; } dir = m_MaskImage->GetDirection()*dir; itk::Vector< float, 3 > pixel; pixel.SetElement(0, -dir[0]); pixel.SetElement(1, dir[1]); pixel.SetElement(2, dir[2]); img->SetPixel(index, pixel); } m_NumDirectionsImage->SetPixel(index, num); ++cit; } MITK_INFO << "Thread " << threadID << " finished extraction"; } // convert cartesian to spherical coordinates template< class PixelType, int ShOrder, int NrOdfDirections > void FiniteDiffOdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections> ::Cart2Sph(const std::vector< DirectionType >& dir, vnl_matrix& sphCoords) { sphCoords.set_size(dir.size(), 2); for (unsigned int i=0; i vnl_matrix FiniteDiffOdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections> ::CalcShBasis(vnl_matrix& sphCoords) { int M = sphCoords.rows(); int j, m; double mag, plm; vnl_matrix shBasis; shBasis.set_size(M, m_NumCoeffs); for (int p=0; p(l,abs(m),cos(sphCoords(p,0))); mag = sqrt((double)(2*l+1)/(4.0*M_PI)*factorial(l-abs(m))/factorial(l+abs(m)))*plm; if (m<0) shBasis(p,j) = sqrt(2.0)*mag*cos(fabs((double)m)*sphCoords(p,1)); else if (m==0) shBasis(p,j) = mag; else shBasis(p,j) = pow(-1.0, m)*sqrt(2.0)*mag*sin(m*sphCoords(p,1)); break; case MRTRIX: plm = legendre_p(l,abs(m),-cos(sphCoords(p,0))); mag = sqrt((double)(2*l+1)/(4.0*M_PI)*factorial(l-abs(m))/factorial(l+abs(m)))*plm; if (m>0) shBasis(p,j) = mag*cos(m*sphCoords(p,1)); else if (m==0) shBasis(p,j) = mag; else shBasis(p,j) = mag*sin(-m*sphCoords(p,1)); break; } j++; } } return shBasis; } } #endif // __itkFiniteDiffOdfMaximaExtractionFilter_cpp diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkFiniteDiffOdfMaximaExtractionFilter.h b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkFiniteDiffOdfMaximaExtractionFilter.h index d5b274a4c0..85e715b5e6 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkFiniteDiffOdfMaximaExtractionFilter.h +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkFiniteDiffOdfMaximaExtractionFilter.h @@ -1,145 +1,145 @@ /*========================================================================= Program: Insight Segmentation & Registration Toolkit Module: $RCSfile: itkDiffusionTensor3DReconstructionImageFilter.h,v $ Language: C++ Date: $Date: 2006-03-27 17:01:06 $ Version: $Revision: 1.12 $ Copyright (c) Insight Software Consortium. All rights reserved. See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm 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 __itkFiniteDiffOdfMaximaExtractionFilter_h_ #define __itkFiniteDiffOdfMaximaExtractionFilter_h_ #include "itkImageToImageFilter.h" #include "vnl/vnl_vector_fixed.h" #include "vnl/vnl_matrix.h" #include "vnl/algo/vnl_svd.h" #include "itkVectorContainer.h" #include "itkVectorImage.h" -#include +#include #include namespace itk{ /** * \brief Extract ODF peaks by searching all local maxima on a densely sampled ODF und clustering these maxima to get the underlying fiber direction. * NrOdfDirections: number of sampling points on the ODF surface (about 20000 is a good value) */ template< class PixelType, int ShOrder, int NrOdfDirections > class FiniteDiffOdfMaximaExtractionFilter : public ImageToImageFilter< Image< Vector< PixelType, (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder >, 3 >, Image< Vector< PixelType, 3 >, 3 > > { public: enum Toolkit { ///< SH coefficient convention (depends on toolkit) FSL, MRTRIX }; enum NormalizationMethods { NO_NORM, ///< no length normalization of the output peaks SINGLE_VEC_NORM, ///< normalize the single peaks to length 1 MAX_VEC_NORM ///< normalize all peaks according to their length in comparison to the largest peak (0-1) }; typedef FiniteDiffOdfMaximaExtractionFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ImageToImageFilter< Image< Vector< PixelType, (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder >, 3 >, Image< Vector< PixelType, 3 >, 3 > > Superclass; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Runtime information support. */ itkTypeMacro(FiniteDiffOdfMaximaExtractionFilter, ImageToImageFilter) typedef typename Superclass::InputImageType CoefficientImageType; typedef typename CoefficientImageType::RegionType CoefficientImageRegionType; typedef typename CoefficientImageType::PixelType CoefficientPixelType; typedef typename Superclass::OutputImageType OutputImageType; typedef typename Superclass::OutputImageRegionType OutputImageRegionType; typedef OrientationDistributionFunction OdfType; typedef itk::Image ItkUcharImgType; typedef vnl_vector_fixed< double, 3 > DirectionType; typedef Image< Vector< float, 3 >, 3> ItkDirectionImage; typedef VectorContainer< unsigned int, ItkDirectionImage::Pointer > ItkDirectionImageContainer; // input itkSetMacro( MaxNumPeaks, unsigned int) ///< maximum number of peaks per voxel. if more peaks are detected, only the largest are kept. itkSetMacro( PeakThreshold, double) ///< threshold on the peak length relative to the largest peak inside the current voxel itkSetMacro( AbsolutePeakThreshold, double) ///< hard threshold on the peak length of all local maxima itkSetMacro( ClusteringThreshold, double) ///< directions closer together than the specified angular threshold will be clustered (in rad) itkSetMacro( AngularThreshold, double) ///< directions closer together than the specified threshold that remain after clustering are discarded (largest is kept) (in rad) itkSetMacro( MaskImage, ItkUcharImgType::Pointer) ///< only voxels inside the binary mask are processed itkSetMacro( NormalizationMethod, NormalizationMethods) ///< normalization method of ODF peaks // output - itkGetMacro( OutputFiberBundle, mitk::FiberBundleX::Pointer) ///< vector field (peak sizes rescaled for visualization purposes) + itkGetMacro( OutputFiberBundle, mitk::FiberBundle::Pointer) ///< vector field (peak sizes rescaled for visualization purposes) itkGetMacro( DirectionImageContainer, ItkDirectionImageContainer::Pointer) ///< container for output peaks itkGetMacro( NumDirectionsImage, ItkUcharImgType::Pointer) ///< number of peaks per voxel itkSetMacro( Toolkit, Toolkit) ///< define SH coefficient convention (depends on toolkit) itkGetMacro( Toolkit, Toolkit) ///< SH coefficient convention (depends on toolkit) protected: FiniteDiffOdfMaximaExtractionFilter(); ~FiniteDiffOdfMaximaExtractionFilter(){} void BeforeThreadedGenerateData(); void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType threadID ); void AfterThreadedGenerateData(); /** Extract all local maxima from the densely sampled ODF surface. Thresholding possible. **/ void FindCandidatePeaks(OdfType& odf, double odfMax, std::vector< DirectionType >& inDirs); /** Cluster input directions within a certain angular threshold **/ std::vector< DirectionType > MeanShiftClustering(std::vector< DirectionType >& inDirs); /** Convert cartesian to spherical coordinates **/ void Cart2Sph(const std::vector< DirectionType >& dir, vnl_matrix& sphCoords); /** Calculate spherical harmonic basis of the defined order **/ vnl_matrix CalcShBasis(vnl_matrix& sphCoords); private: NormalizationMethods m_NormalizationMethod; ///< normalization method of ODF peaks unsigned int m_MaxNumPeaks; ///< maximum number of peaks per voxel. if more peaks are detected, only the largest are kept. double m_PeakThreshold; ///< threshold on the peak length relative to the largest peak inside the current voxel double m_AbsolutePeakThreshold;///< hard threshold on the peak length of all local maxima vnl_matrix< double > m_ShBasis; ///< container for evaluated SH base functions double m_ClusteringThreshold; ///< directions closer together than the specified angular threshold will be clustered (in rad) double m_AngularThreshold; ///< directions closer together than the specified threshold that remain after clustering are discarded (largest is kept) (in rad) const int m_NumCoeffs; ///< number of spherical harmonics coefficients - mitk::FiberBundleX::Pointer m_OutputFiberBundle; ///< vector field (peak sizes rescaled for visualization purposes) + mitk::FiberBundle::Pointer m_OutputFiberBundle; ///< vector field (peak sizes rescaled for visualization purposes) ItkDirectionImageContainer::Pointer m_DirectionImageContainer;///< container for output peaks ItkUcharImgType::Pointer m_NumDirectionsImage; ///< number of peaks per voxel ItkUcharImgType::Pointer m_MaskImage; ///< only voxels inside the binary mask are processed Toolkit m_Toolkit; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkFiniteDiffOdfMaximaExtractionFilter.cpp" #endif #endif //__itkFiniteDiffOdfMaximaExtractionFilter_h_ diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkFslPeakImageConverter.cpp b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkFslPeakImageConverter.cpp index 357ed381e4..e582ffefc5 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkFslPeakImageConverter.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkFslPeakImageConverter.cpp @@ -1,171 +1,171 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkFslPeakImageConverter_cpp #define __itkFslPeakImageConverter_cpp #include #include #include #include "itkFslPeakImageConverter.h" #include #include #include #include #include #include #include #include #include namespace itk { template< class PixelType > FslPeakImageConverter< PixelType >::FslPeakImageConverter(): m_NormalizationMethod(NO_NORM) { } template< class PixelType > void FslPeakImageConverter< PixelType > ::GenerateData() { // output vector field vtkSmartPointer m_VtkCellArray = vtkSmartPointer::New(); vtkSmartPointer m_VtkPoints = vtkSmartPointer::New(); Vector spacing4 = m_InputImages->GetElement(0)->GetSpacing(); Point origin4 = m_InputImages->GetElement(0)->GetOrigin(); Matrix direction4 = m_InputImages->GetElement(0)->GetDirection(); ImageRegion<4> imageRegion4 = m_InputImages->GetElement(0)->GetLargestPossibleRegion(); itk::Vector spacing3; Point origin3; Matrix direction3; ImageRegion<3> imageRegion3; spacing3[0] = spacing4[0]; spacing3[1] = spacing4[1]; spacing3[2] = spacing4[2]; origin3[0] = origin4[0]; origin3[1] = origin4[1]; origin3[2] = origin4[2]; for (int r=0; r<3; r++) for (int c=0; c<3; c++) direction3[r][c] = direction4[r][c]; imageRegion3.SetSize(0, imageRegion4.GetSize()[0]); imageRegion3.SetSize(1, imageRegion4.GetSize()[1]); imageRegion3.SetSize(2, imageRegion4.GetSize()[2]); double minSpacing = spacing3[0]; if (spacing3[1] InputIteratorType; for (int i=0; iSize(); i++) { InputImageType::Pointer img = m_InputImages->GetElement(i); int x = img->GetLargestPossibleRegion().GetSize(0); int y = img->GetLargestPossibleRegion().GetSize(1); int z = img->GetLargestPossibleRegion().GetSize(2); ItkDirectionImageType::Pointer directionImage = ItkDirectionImageType::New(); directionImage->SetSpacing( spacing3 ); directionImage->SetOrigin( origin3 ); directionImage->SetDirection( direction3 ); directionImage->SetRegions( imageRegion3 ); directionImage->Allocate(); Vector< PixelType, 3 > nullVec; nullVec.Fill(0.0); directionImage->FillBuffer(nullVec); for (int a=0; a dirVec; dirVec.set_size(4); for (int k=0; k<3; k++) { index.SetElement(3,k); dirVec[k] = img->GetPixel(index); } dirVec[3] = 0; vtkSmartPointer container = vtkSmartPointer::New(); itk::ContinuousIndex center; center[0] = index[0]; center[1] = index[1]; center[2] = index[2]; center[3] = 0; itk::Point worldCenter; img->TransformContinuousIndexToPhysicalPoint( center, worldCenter ); switch (m_NormalizationMethod) { case NO_NORM: break; case SINGLE_VEC_NORM: dirVec.normalize(); break; } dirVec.normalize(); dirVec = img->GetDirection()*dirVec; itk::Point worldStart; worldStart[0] = worldCenter[0]-dirVec[0]/2 * minSpacing; worldStart[1] = worldCenter[1]-dirVec[1]/2 * minSpacing; worldStart[2] = worldCenter[2]-dirVec[2]/2 * minSpacing; vtkIdType id = m_VtkPoints->InsertNextPoint(worldStart.GetDataPointer()); container->GetPointIds()->InsertNextId(id); itk::Point worldEnd; worldEnd[0] = worldCenter[0]+dirVec[0]/2 * minSpacing; worldEnd[1] = worldCenter[1]+dirVec[1]/2 * minSpacing; worldEnd[2] = worldCenter[2]+dirVec[2]/2 * minSpacing; id = m_VtkPoints->InsertNextPoint(worldEnd.GetDataPointer()); container->GetPointIds()->InsertNextId(id); m_VtkCellArray->InsertNextCell(container); // generate direction image typename ItkDirectionImageType::IndexType index2; index2[0] = index[0]; index2[1] = index[1]; index2[2] = index[2]; Vector< PixelType, 3 > pixel; pixel.SetElement(0, dirVec[0]); pixel.SetElement(1, dirVec[1]); pixel.SetElement(2, dirVec[2]); directionImage->SetPixel(index2, pixel); } m_DirectionImageContainer->InsertElement(m_DirectionImageContainer->Size(), directionImage); } vtkSmartPointer directionsPolyData = vtkSmartPointer::New(); directionsPolyData->SetPoints(m_VtkPoints); directionsPolyData->SetLines(m_VtkCellArray); - m_OutputFiberBundle = mitk::FiberBundleX::New(directionsPolyData); + m_OutputFiberBundle = mitk::FiberBundle::New(directionsPolyData); } } #endif // __itkFslPeakImageConverter_cpp diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkFslPeakImageConverter.h b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkFslPeakImageConverter.h index a118e35021..9639353f6d 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkFslPeakImageConverter.h +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkFslPeakImageConverter.h @@ -1,89 +1,89 @@ /*========================================================================= Program: Insight Segmentation & Registration Toolkit Module: $RCSfile: itkDiffusionTensor3DReconstructionImageFilter.h,v $ Language: C++ Date: $Date: 2006-03-27 17:01:06 $ Version: $Revision: 1.12 $ Copyright (c) Insight Software Consortium. All rights reserved. See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm 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 __itkFslPeakImageConverter_h_ #define __itkFslPeakImageConverter_h_ #include #include -#include +#include #include namespace itk{ /** \class FslPeakImageConverter - Converts a series of 4D images containing directional (3D vector) information into a vector field stored as mitkFiberBundleX. + Converts a series of 4D images containing directional (3D vector) information into a vector field stored as mitkFiberBundle. These 4D files are for example generated by the FSL qboot command. */ template< class PixelType > class FslPeakImageConverter : public ProcessObject { public: enum NormalizationMethods { NO_NORM, ///< don't normalize peaks SINGLE_VEC_NORM ///< normalize peaks to length 1 }; typedef FslPeakImageConverter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ProcessObject Superclass; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Runtime information support. */ itkTypeMacro(FslPeakImageConverter, ImageToImageFilter) typedef vnl_vector_fixed< double, 3 > DirectionType; typedef VectorContainer< int, DirectionType > DirectionContainerType; typedef VectorContainer< int, DirectionContainerType::Pointer > ContainerType; typedef Image< float, 4 > InputImageType; typedef VectorContainer< int, InputImageType::Pointer > InputType; typedef Image< Vector< float, 3 >, 3> ItkDirectionImageType; typedef VectorContainer< int, ItkDirectionImageType::Pointer > DirectionImageContainerType; itkSetMacro( NormalizationMethod, NormalizationMethods) ///< normalization method of ODF peaks itkSetMacro( InputImages, InputType::Pointer) ///< MRtrix peak image of type itk::Image< float, 4 > - itkGetMacro( OutputFiberBundle, mitk::FiberBundleX::Pointer) ///< vector field (peak sizes rescaled for visualization purposes) + itkGetMacro( OutputFiberBundle, mitk::FiberBundle::Pointer) ///< vector field (peak sizes rescaled for visualization purposes) itkGetMacro( DirectionImageContainer, DirectionImageContainerType::Pointer) ///< container for output peaks void GenerateData(); protected: FslPeakImageConverter(); ~FslPeakImageConverter(){} NormalizationMethods m_NormalizationMethod; ///< normalization method of ODF peaks - mitk::FiberBundleX::Pointer m_OutputFiberBundle; ///< vector field (peak sizes rescaled for visualization purposes) + mitk::FiberBundle::Pointer m_OutputFiberBundle; ///< vector field (peak sizes rescaled for visualization purposes) InputType::Pointer m_InputImages; ///< MRtrix peak image of type itk::Image< float, 4 > DirectionImageContainerType::Pointer m_DirectionImageContainer; ///< container for output peaks private: }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkFslPeakImageConverter.cpp" #endif #endif //__itkFslPeakImageConverter_h_ diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkMrtrixPeakImageConverter.cpp b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkMrtrixPeakImageConverter.cpp index 49a5fc6b7e..9dc2978402 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkMrtrixPeakImageConverter.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkMrtrixPeakImageConverter.cpp @@ -1,211 +1,211 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkMrtrixPeakImageConverter_cpp #define __itkMrtrixPeakImageConverter_cpp #include #include #include #include "itkMrtrixPeakImageConverter.h" #include #include #include #include #include #include #include #include #include namespace itk { template< class PixelType > MrtrixPeakImageConverter< PixelType >::MrtrixPeakImageConverter(): m_NormalizationMethod(NO_NORM) { } template< class PixelType > void MrtrixPeakImageConverter< PixelType > ::GenerateData() { // output vector field vtkSmartPointer m_VtkCellArray = vtkSmartPointer::New(); vtkSmartPointer m_VtkPoints = vtkSmartPointer::New(); Vector spacing4 = m_InputImage->GetSpacing(); Point origin4 = m_InputImage->GetOrigin(); Matrix direction4 = m_InputImage->GetDirection(); ImageRegion<4> imageRegion4 = m_InputImage->GetLargestPossibleRegion(); Vector spacing3; Point origin3; Matrix direction3; ImageRegion<3> imageRegion3; spacing3[0] = spacing4[0]; spacing3[1] = spacing4[1]; spacing3[2] = spacing4[2]; origin3[0] = origin4[0]; origin3[1] = origin4[1]; origin3[2] = origin4[2]; for (int r=0; r<3; r++) for (int c=0; c<3; c++) direction3[r][c] = direction4[r][c]; imageRegion3.SetSize(0, imageRegion4.GetSize()[0]); imageRegion3.SetSize(1, imageRegion4.GetSize()[1]); imageRegion3.SetSize(2, imageRegion4.GetSize()[2]); double minSpacing = spacing3[0]; if (spacing3[1] InputIteratorType; int x = m_InputImage->GetLargestPossibleRegion().GetSize(0); int y = m_InputImage->GetLargestPossibleRegion().GetSize(1); int z = m_InputImage->GetLargestPossibleRegion().GetSize(2); int numDirs = m_InputImage->GetLargestPossibleRegion().GetSize(3)/3; m_NumDirectionsImage = ItkUcharImgType::New(); m_NumDirectionsImage->SetSpacing( spacing3 ); m_NumDirectionsImage->SetOrigin( origin3 ); m_NumDirectionsImage->SetDirection( direction3 ); m_NumDirectionsImage->SetRegions( imageRegion3 ); m_NumDirectionsImage->Allocate(); m_NumDirectionsImage->FillBuffer(0); for (int i=0; iSetSpacing( spacing3 ); directionImage->SetOrigin( origin3 ); directionImage->SetDirection( direction3 ); directionImage->SetRegions( imageRegion3 ); directionImage->Allocate(); Vector< PixelType, 3 > nullVec; nullVec.Fill(0.0); directionImage->FillBuffer(nullVec); m_DirectionImageContainer->InsertElement(m_DirectionImageContainer->Size(), directionImage); } double minangle = 0; for (int i=0; i dirVec; dirVec.set_size(4); for (int k=0; k<3; k++) { index.SetElement(3,k+i*3); dirVec[k] = m_InputImage->GetPixel(index); } dirVec[3] = 0; if (dirVec.magnitude()<0.0001) continue; vtkSmartPointer container = vtkSmartPointer::New(); itk::ContinuousIndex center; center[0] = index[0]; center[1] = index[1]; center[2] = index[2]; center[3] = 0; itk::Point worldCenter; m_InputImage->TransformContinuousIndexToPhysicalPoint( center, worldCenter ); switch (m_NormalizationMethod) { case NO_NORM: break; case SINGLE_VEC_NORM: dirVec.normalize(); break; } dirVec.normalize(); dirVec = m_InputImage->GetDirection()*dirVec; itk::Point worldStart; worldStart[0] = worldCenter[0]-dirVec[0]/2 * minSpacing; worldStart[1] = worldCenter[1]-dirVec[1]/2 * minSpacing; worldStart[2] = worldCenter[2]-dirVec[2]/2 * minSpacing; vtkIdType id = m_VtkPoints->InsertNextPoint(worldStart.GetDataPointer()); container->GetPointIds()->InsertNextId(id); itk::Point worldEnd; worldEnd[0] = worldCenter[0]+dirVec[0]/2 * minSpacing; worldEnd[1] = worldCenter[1]+dirVec[1]/2 * minSpacing; worldEnd[2] = worldCenter[2]+dirVec[2]/2 * minSpacing; id = m_VtkPoints->InsertNextPoint(worldEnd.GetDataPointer()); container->GetPointIds()->InsertNextId(id); m_VtkCellArray->InsertNextCell(container); // generate direction image typename ItkDirectionImageType::IndexType index2; index2[0] = a; index2[1] = b; index2[2] = c; // workaround ********************************************* dirVec = m_InputImage->GetDirection()*dirVec; dirVec.normalize(); // workaround ********************************************* Vector< PixelType, 3 > pixel; pixel.SetElement(0, dirVec[0]); pixel.SetElement(1, dirVec[1]); pixel.SetElement(2, dirVec[2]); for (int j=0; jElementAt(j); Vector< PixelType, 3 > tempPix = directionImage->GetPixel(index2); if (tempPix.GetNorm()<0.01) { directionImage->SetPixel(index2, pixel); break; } else { if ( fabs(dot_product(tempPix.GetVnlVector(), pixel.GetVnlVector()))>minangle ) { minangle = fabs(dot_product(tempPix.GetVnlVector(), pixel.GetVnlVector())); MITK_INFO << "Minimum angle: " << acos(minangle)*180.0/M_PI; } } } m_NumDirectionsImage->SetPixel(index2, m_NumDirectionsImage->GetPixel(index2)+1); } } vtkSmartPointer directionsPolyData = vtkSmartPointer::New(); directionsPolyData->SetPoints(m_VtkPoints); directionsPolyData->SetLines(m_VtkCellArray); - m_OutputFiberBundle = mitk::FiberBundleX::New(directionsPolyData); + m_OutputFiberBundle = mitk::FiberBundle::New(directionsPolyData); } } #endif // __itkMrtrixPeakImageConverter_cpp diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkMrtrixPeakImageConverter.h b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkMrtrixPeakImageConverter.h index ef134afc8f..34ad3f0e95 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkMrtrixPeakImageConverter.h +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkMrtrixPeakImageConverter.h @@ -1,91 +1,91 @@ /*========================================================================= Program: Insight Segmentation & Registration Toolkit Module: $RCSfile: itkDiffusionTensor3DReconstructionImageFilter.h,v $ Language: C++ Date: $Date: 2006-03-27 17:01:06 $ Version: $Revision: 1.12 $ Copyright (c) Insight Software Consortium. All rights reserved. See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm 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 __itkMrtrixPeakImageConverter_h_ #define __itkMrtrixPeakImageConverter_h_ #include #include -#include +#include #include namespace itk{ /** \class MrtrixPeakImageConverter - Converts a series of 4D images containing directional (3D vector) information into a vector field stored as mitkFiberBundleX. + Converts a series of 4D images containing directional (3D vector) information into a vector field stored as mitkFiberBundle. These 4D files are for example generated by the FSL qboot command. */ template< class PixelType > class MrtrixPeakImageConverter : public ProcessObject { public: enum NormalizationMethods { NO_NORM, ///< don't normalize peaks SINGLE_VEC_NORM ///< normalize peaks to length 1 }; typedef MrtrixPeakImageConverter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ProcessObject Superclass; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Runtime information support. */ itkTypeMacro(MrtrixPeakImageConverter, ImageToImageFilter) typedef vnl_vector_fixed< double, 3 > DirectionType; typedef VectorContainer< int, DirectionType > DirectionContainerType; typedef VectorContainer< int, DirectionContainerType::Pointer > ContainerType; typedef Image< float, 4 > InputImageType; typedef Image< Vector< float, 3 >, 3> ItkDirectionImageType; typedef VectorContainer< int, ItkDirectionImageType::Pointer > DirectionImageContainerType; typedef itk::Image ItkUcharImgType; itkSetMacro( NormalizationMethod, NormalizationMethods) ///< normalization method of ODF peaks itkSetMacro( InputImage, InputImageType::Pointer) ///< MRtrix direction image of type itk::Image< float, 4 > - itkGetMacro( OutputFiberBundle, mitk::FiberBundleX::Pointer) ///< vector field (peak sizes rescaled for visualization purposes) + itkGetMacro( OutputFiberBundle, mitk::FiberBundle::Pointer) ///< vector field (peak sizes rescaled for visualization purposes) itkGetMacro( DirectionImageContainer, DirectionImageContainerType::Pointer) ///< container for output peaks itkGetMacro( NumDirectionsImage, ItkUcharImgType::Pointer) ///< number of peaks per voxel void GenerateData(); protected: MrtrixPeakImageConverter(); ~MrtrixPeakImageConverter(){} NormalizationMethods m_NormalizationMethod; ///< normalization method of ODF peaks - mitk::FiberBundleX::Pointer m_OutputFiberBundle; ///< vector field (peak sizes rescaled for visualization purposes) + mitk::FiberBundle::Pointer m_OutputFiberBundle; ///< vector field (peak sizes rescaled for visualization purposes) InputImageType::Pointer m_InputImage; ///< MRtrix direction image of type itk::Image< float, 4 > DirectionImageContainerType::Pointer m_DirectionImageContainer; ///< container for output peaks ItkUcharImgType::Pointer m_NumDirectionsImage; ///< number of peaks per voxel private: }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkMrtrixPeakImageConverter.cpp" #endif #endif //__itkMrtrixPeakImageConverter_h_ diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkOdfMaximaExtractionFilter.cpp b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkOdfMaximaExtractionFilter.cpp index 23a79eb8cf..c7acd3de0f 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkOdfMaximaExtractionFilter.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkOdfMaximaExtractionFilter.cpp @@ -1,629 +1,629 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkOdfMaximaExtractionFilter_cpp #define __itkOdfMaximaExtractionFilter_cpp #include "itkOdfMaximaExtractionFilter.h" #include #include #include #include #include #include #include #include #include #include #include using namespace boost::math; using namespace std; namespace itk { template< class TOdfPixelType > OdfMaximaExtractionFilter< TOdfPixelType >::OdfMaximaExtractionFilter(): m_NormalizationMethod(MAX_VEC_NORM), m_PeakThreshold(0.2), m_MaxNumPeaks(10), m_ShCoeffImage(NULL), m_OutputFiberBundle(NULL), m_NumDirectionsImage(NULL), m_DirectionImageContainer(NULL) { } // solve ax? + bx? + cx + d = 0 using cardanos method template< class TOdfPixelType > bool OdfMaximaExtractionFilter::ReconstructQballImage() { if (m_ShCoeffImage.IsNotNull()) { cout << "Using preset coefficient image\n"; return true; } cout << "Starting qball reconstruction\n"; try { QballReconstructionFilterType::Pointer filter = QballReconstructionFilterType::New(); filter->SetGradientImage( m_DiffusionGradients, m_DiffusionImage ); filter->SetBValue(m_Bvalue); filter->SetLambda(0.006); filter->SetNormalizationMethod(QballReconstructionFilterType::QBAR_SOLID_ANGLE); filter->Update(); m_ShCoeffImage = filter->GetCoefficientImage(); if (m_ShCoeffImage.IsNull()) return false; return true; } catch (...) { return false; } } // solve ax³ + bx² + cx + d = 0 using cardanos method template< class TOdfPixelType > std::vector OdfMaximaExtractionFilter< TOdfPixelType > ::SolveCubic(const double& a, const double& b, const double& c, const double& d) { double A, B, p, q, r, D, offset, ee, tmp, root; vector roots; double inv3 = 1.0/3.0; if (a!=0) // solve ax³ + bx² + cx + d = 0 { p = b/a; q = c/a; r = d/a; // x³ + px² + qx + r = 0 A = q-p*p*inv3; B = (2.0*p*p*p-9.0*p*q+27.0*r)/27.0; A = A*inv3; B = B*0.5; D = B*B+A*A*A; offset = p*inv3; if (D>0.0) // one real root { ee = sqrt(D); tmp = -B+ee; root = cbrt(tmp); tmp = -B-ee; root += cbrt(tmp); root -= offset; roots.push_back(root); } else if (D<0.0) // three real roots { ee = sqrt(-D); double tmp2 = -B; double angle = 2.0*inv3*atan(ee/(sqrt(tmp2*tmp2+ee*ee)+tmp2)); double sqrt3 = sqrt(3.0); tmp = cos(angle); tmp2 = sin(angle); ee = sqrt(-A); root = 2*ee*tmp-offset; roots.push_back(root); root = -ee*(tmp+sqrt3*tmp2)-offset; roots.push_back(root); root = -ee*(tmp-sqrt3*tmp2)-offset; roots.push_back(root); } else // one or two real roots { tmp=-B; tmp=cbrt(tmp); root=2*tmp-offset; roots.push_back(root); if (A!=0 || B!=0) root=-tmp-offset; roots.push_back(root); } } else if (b!=0) // solve bx² + cx + d = 0 { D = c*c-4*b*d; if (D>0) { tmp = sqrt(D); root = (-c+tmp)/(2.0*b); roots.push_back(root); root = (-c-tmp)/(2.0*b); roots.push_back(root); } else if (D==0) root = -c/(2.0*b); roots.push_back(root); } else if (c!=0) // solve cx + d = 0 root = -d/c; roots.push_back(root); return roots; } template< class TOdfPixelType > double OdfMaximaExtractionFilter< TOdfPixelType > ::ODF_dtheta(const double& sn, const double& cs, const double& A, const double& B, const double& C, const double& D, const double& E, const double& F, const double& G, const double& H) { double dtheta=(G-7*E)*sn*sn + (7*F-35*D-H)*sn*cs + (H+C-F-3*A-5*D)*sn + (0.5*E+B+0.5*G)*cs -0.5*G+3.5*E; return dtheta; } template< class TOdfPixelType > double OdfMaximaExtractionFilter< TOdfPixelType > ::ODF_dtheta2(const double& sn, const double& cs, const double& A, const double& B, const double& C, const double& D, const double& E, const double& F, const double& G, const double& H) { double dtheta2=4*(G-7*E)*sn*cs + 2*(7*F-35*D-H)*(2*cs*cs-1) + 2*(H+C-F-3*A-5*D)*cs -(E+2*B+G)*sn; return dtheta2; } template< class TOdfPixelType > double OdfMaximaExtractionFilter< TOdfPixelType > ::ODF_dphi2(const double& sn, const double& cs, const double& A, const double& B, const double& C, const double& D, const double& E, const double& F, const double& G, const double& H) { double dphi2=35*D*((1+cs)*(1+cs)/4)+(3*A-30*D)*(1+cs)/2.0+3*D-A + 0.5*(7*E*(1+cs)/2.0-3*E+B)*sn + (7*F*(1+cs)/2+C-F)*(1-cs)/2.0 + G*sn*(1-cs)/4.0 + H*((1-cs)*(1-cs)/4); return dphi2; } template< class TOdfPixelType > void OdfMaximaExtractionFilter< TOdfPixelType > ::FindCandidatePeaks(const CoefficientPixelType& SHcoeff) { const double thr = 0.03; // threshold on the derivative of the ODF with respect to theta const double phi_step = 0.005; // step size for 1D exhaustive search on phi bool highRes; // when close to maxima increase resolution double mag, Y, Yp, sn, cs; double phi, dPhi; double A, B, C, D, E, F, G, H, Bp, Cp, Ep, Fp, Gp, Hp, Bs, Cs, Es, Fs, Gs, Hs; CoefficientPixelType a, ap; a = SHcoeff; ap = SHcoeff; m_CandidatePeaks.clear(); // clear peaks of last voxel for (int adaptiveStepwidth=0; adaptiveStepwidth<=1; adaptiveStepwidth++) { phi=0; while (phi<(2*M_PI)) // phi exhaustive search 0..pi { // calculate 4th order SH representtaion of ODF and according derivative for (int l=0; l<=4; l=l+2) { for (int m=-l; m<=l; m++) { int j=l*(l+1)/2+m; if (m<0) { mag = sqrt(((2*l+1)/(2*M_PI))*factorial(l+m)/factorial(l-m)); Y = mag*cos(m*phi); Yp = -m*mag*sin(m*phi); } else if (m==0) { Y = sqrt((2*l+1)/(4*M_PI)); Yp = 0; } else { mag = pow(-1.0,m)*sqrt(((2*l+1)/(2*M_PI))*factorial(l-m)/factorial(l+m)); Y = mag*sin(m*phi); Yp = m*mag*cos(m*phi); } a[j] = SHcoeff[j]*Y; ap[j] = SHcoeff[j]*Yp; } } // ODF A=0.5*a[3]; B=-3*(a[2]+a[4]); C=3*(a[1]+a[5]); D=0.125*a[10]; E=-2.5*(a[9]+a[11]); F=7.5*(a[8]+a[12]); G=-105*(a[7]+a[13]); H=105*(a[6]+a[14]); // phi derivative Bp=-3*(ap[2]+ap[4]); Cp=3*(ap[1]+ap[5]); Ep=-2.5*(ap[9]+ap[11]); Fp=7.5*(ap[8]+ap[12]); Gp=-105*(ap[7]+ap[13]); Hp=105*(ap[6]+ap[14]); // 2phi derivative Bs=-B; Cs=-4*C; Es=-E; Fs=-4*F; Gs=-9*G; Hs=-16*H; // solve cubic for tan(theta) std::vector tanTheta = SolveCubic(Hp+Cp-Fp, Gp+Bp-3*Ep, 6*Fp+Cp, Bp+4*Ep); highRes = false; dPhi = phi_step; //for each real cubic solution for tan(theta) for (int n=0; n hessian; hessian(0,0) = ODF_dtheta2(sn, cs, A, B, C, D, E, F, G, H); hessian(0,1) = ODF_dtheta(sn, cs, 0, Bp, Cp, 0, Ep, Fp, Gp, Hp); hessian(1,0) = hessian(0,1); hessian(1,1) = ODF_dphi2(sn, cs, 0, Bs, Cs, 0, Es, Fs, Gs, Hs); double det = vnl_det(hessian); // determinant double tr = vnl_trace(hessian); // trace highRes = true; // we are close to a maximum, so turn on high resolution 1D exhaustive search if (det>=0 && tr<=0) // check if we really have a local maximum { vnl_vector_fixed< double, 2 > peak; peak[0] = theta; peak[1] = phi; m_CandidatePeaks.push_back(peak); } } if (adaptiveStepwidth) // calculate adaptive step width { double t2=tanTheta[n]*tanTheta[n]; double t3=t2*tanTheta[n]; double t4=t3*tanTheta[n]; double const_step=phi_step*(1+t2)/sqrt(t2+t4+pow((((Hs+Cs-Fs)*t3+(Gs+Bs-3*Es)*t2+(6*Fs+Cs)*tanTheta[n]+(Bs+4*Es))/(3*(Hp+Cp-Fp)*t2+2*(Gp+Bp-3*Ep)*tanTheta[n]+(6*Fp+Cp))),2.0)); if (const_step std::vector< vnl_vector_fixed< double, 3 > > OdfMaximaExtractionFilter< TOdfPixelType > ::ClusterPeaks(const CoefficientPixelType& shCoeff) { const double distThres = 0.4; int npeaks = 0, nMin = 0; double dMin, dPos, dNeg, d; Vector3D u; vector< Vector3D > v; // initialize container for vector clusters std::vector < std::vector< Vector3D > > clusters; clusters.resize(m_CandidatePeaks.size()); for (int i=0; i::max(); for (int n=0; n shBasis, sphCoords; Cart2Sph(v, sphCoords); // convert candidate peaks to spherical angles shBasis = CalcShBasis(sphCoords, 4); // evaluate spherical harmonics at each peak vnl_vector odfVals(npeaks); odfVals.fill(0.0); double maxVal = itk::NumericTraits::NonpositiveMin(); int maxPos; for (int i=0; imaxVal ) { maxVal = odfVals(i); maxPos = i; } } v.clear(); vector< double > restVals; for (int i=0; i=m_PeakThreshold*maxVal ) { u[0] = odfVals(i)*cos(sphCoords(i,1))*sin(sphCoords(i,0)); u[1] = odfVals(i)*sin(sphCoords(i,1))*sin(sphCoords(i,0)); u[2] = odfVals(i)*cos(sphCoords(i,0)); restVals.push_back(odfVals(i)); v.push_back(u); } npeaks = v.size(); if (npeaks>m_MaxNumPeaks) // if still too many peaks, keep only the m_MaxNumPeaks with maximum value { vector< Vector3D > v2; for (int i=0; i::NonpositiveMin(); //Get the maximum ODF peak value and the corresponding peak index for (int i=0; imaxVal ) { maxVal = restVals[i]; maxPos = i; } v2.push_back(v[maxPos]); restVals[maxPos] = 0; //zero that entry in order to find the next maximum } return v2; } } return v; } // convert cartesian to spherical coordinates template< class TOdfPixelType > void OdfMaximaExtractionFilter< TOdfPixelType > ::Cart2Sph(const std::vector< Vector3D >& dir, vnl_matrix& sphCoords) { sphCoords.set_size(dir.size(), 2); for (int i=0; i vnl_matrix OdfMaximaExtractionFilter< TOdfPixelType > ::CalcShBasis(vnl_matrix& sphCoords, const int& shOrder) { int R = (shOrder+1)*(shOrder+2)/2; int M = sphCoords.rows(); int j, m; double mag, plm; vnl_matrix shBasis; shBasis.set_size(M,R); for (int p=0; p(l,abs(m),cos(sphCoords(p,0))); mag = sqrt((double)(2*l+1)/(4.0*M_PI)*factorial(l-abs(m))/factorial(l+abs(m)))*plm; if (m<0) shBasis(p,j) = sqrt(2.0)*mag*cos(fabs((double)m)*sphCoords(p,1)); else if (m==0) shBasis(p,j) = mag; else shBasis(p,j) = pow(-1.0, m)*sqrt(2.0)*mag*sin(m*sphCoords(p,1)); j++; } } return shBasis; } template< class TOdfPixelType > void OdfMaximaExtractionFilter< TOdfPixelType > ::GenerateData() { if (!ReconstructQballImage()) return; std::cout << "Starting maxima extraction\n"; switch (m_NormalizationMethod) { case NO_NORM: std::cout << "NO_NORM\n"; break; case SINGLE_VEC_NORM: std::cout << "SINGLE_VEC_NORM\n"; break; case MAX_VEC_NORM: std::cout << "MAX_VEC_NORM\n"; break; } typedef ImageRegionConstIterator< CoefficientImageType > InputIteratorType; InputIteratorType git(m_ShCoeffImage, m_ShCoeffImage->GetLargestPossibleRegion() ); itk::Vector spacing = m_ShCoeffImage->GetSpacing(); double minSpacing = spacing[0]; if (spacing[1]GetOrigin(); itk::Matrix direction = m_ShCoeffImage->GetDirection(); ImageRegion<3> imageRegion = m_ShCoeffImage->GetLargestPossibleRegion(); // initialize num directions image m_NumDirectionsImage = ItkUcharImgType::New(); m_NumDirectionsImage->SetSpacing( spacing ); m_NumDirectionsImage->SetOrigin( origin ); m_NumDirectionsImage->SetDirection( direction ); m_NumDirectionsImage->SetRegions( imageRegion ); m_NumDirectionsImage->Allocate(); m_NumDirectionsImage->FillBuffer(0); vtkSmartPointer m_VtkCellArray = vtkSmartPointer::New(); vtkSmartPointer m_VtkPoints = vtkSmartPointer::New(); m_DirectionImageContainer = ItkDirectionImageContainer::New(); for (int i=0; i nullVec; nullVec.Fill(0.0); ItkDirectionImage::Pointer img = ItkDirectionImage::New(); img->SetSpacing( spacing ); img->SetOrigin( origin ); img->SetDirection( direction ); img->SetRegions( imageRegion ); img->Allocate(); img->FillBuffer(nullVec); m_DirectionImageContainer->InsertElement(m_DirectionImageContainer->Size(), img); } if (m_MaskImage.IsNull()) { m_MaskImage = ItkUcharImgType::New(); m_MaskImage->SetSpacing( spacing ); m_MaskImage->SetOrigin( origin ); m_MaskImage->SetDirection( direction ); m_MaskImage->SetRegions( imageRegion ); m_MaskImage->Allocate(); m_MaskImage->FillBuffer(1); } itk::ImageRegionIterator dirIt(m_NumDirectionsImage, m_NumDirectionsImage->GetLargestPossibleRegion()); itk::ImageRegionIterator maskIt(m_MaskImage, m_MaskImage->GetLargestPossibleRegion()); int maxProgress = m_MaskImage->GetLargestPossibleRegion().GetSize()[0]*m_MaskImage->GetLargestPossibleRegion().GetSize()[1]*m_MaskImage->GetLargestPossibleRegion().GetSize()[2]; boost::progress_display disp(maxProgress); git.GoToBegin(); while( !git.IsAtEnd() ) { ++disp; if (maskIt.Value()<=0) { ++git; ++dirIt; ++maskIt; continue; } CoefficientPixelType c = git.Get(); FindCandidatePeaks(c); std::vector< Vector3D > directions = ClusterPeaks(c); typename CoefficientImageType::IndexType index = git.GetIndex(); float max = 0.0; for (int i=0; imax) max = directions.at(i).magnitude(); if (max<0.0001) max = 1.0; for (int i=0; iGetElement(i); itk::Vector< float, 3 > pixel; vnl_vector dir = directions.at(i); vtkSmartPointer container = vtkSmartPointer::New(); itk::ContinuousIndex center; center[0] = index[0]; center[1] = index[1]; center[2] = index[2]; itk::Point worldCenter; m_ShCoeffImage->TransformContinuousIndexToPhysicalPoint( center, worldCenter ); switch (m_NormalizationMethod) { case NO_NORM: break; case SINGLE_VEC_NORM: dir.normalize(); break; case MAX_VEC_NORM: dir /= max; break; } dir = m_MaskImage->GetDirection()*dir; pixel.SetElement(0, dir[0]); pixel.SetElement(1, dir[1]); pixel.SetElement(2, dir[2]); img->SetPixel(index, pixel); itk::Point worldStart; worldStart[0] = worldCenter[0]-dir[0]/2 * minSpacing; worldStart[1] = worldCenter[1]-dir[1]/2 * minSpacing; worldStart[2] = worldCenter[2]-dir[2]/2 * minSpacing; vtkIdType id = m_VtkPoints->InsertNextPoint(worldStart.GetDataPointer()); container->GetPointIds()->InsertNextId(id); itk::Point worldEnd; worldEnd[0] = worldCenter[0]+dir[0]/2 * minSpacing; worldEnd[1] = worldCenter[1]+dir[1]/2 * minSpacing; worldEnd[2] = worldCenter[2]+dir[2]/2 * minSpacing; id = m_VtkPoints->InsertNextPoint(worldEnd.GetDataPointer()); container->GetPointIds()->InsertNextId(id); m_VtkCellArray->InsertNextCell(container); } dirIt.Set(directions.size()); ++git; ++dirIt; ++maskIt; } vtkSmartPointer directionsPolyData = vtkSmartPointer::New(); directionsPolyData->SetPoints(m_VtkPoints); directionsPolyData->SetLines(m_VtkCellArray); - m_OutputFiberBundle = mitk::FiberBundleX::New(directionsPolyData); + m_OutputFiberBundle = mitk::FiberBundle::New(directionsPolyData); std::cout << "Maxima extraction finished\n"; } } #endif // __itkOdfMaximaExtractionFilter_cpp diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkOdfMaximaExtractionFilter.h b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkOdfMaximaExtractionFilter.h index 179fccb036..5ec120bca7 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkOdfMaximaExtractionFilter.h +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkOdfMaximaExtractionFilter.h @@ -1,145 +1,145 @@ /*========================================================================= Program: Insight Segmentation & Registration Toolkit Module: $RCSfile: itkDiffusionTensor3DReconstructionImageFilter.h,v $ Language: C++ Date: $Date: 2006-03-27 17:01:06 $ Version: $Revision: 1.12 $ Copyright (c) Insight Software Consortium. All rights reserved. See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm 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 __itkOdfMaximaExtractionFilter_h_ #define __itkOdfMaximaExtractionFilter_h_ -#include +#include #include #include #include #include namespace itk{ /** \class OdfMaximaExtractionFilter Class that estimates the maxima of the 4th order SH representation of an ODF using analytic calculations (according to Aganj et al, MICCAI, 2010) */ template< class TOdfPixelType > class OdfMaximaExtractionFilter : public ProcessObject { public: enum NormalizationMethods { NO_NORM, ///< don't normalize peaks SINGLE_VEC_NORM, ///< normalize peaks to length 1 MAX_VEC_NORM ///< largest peak is normalized to length 1, other peaks relative to it }; typedef OdfMaximaExtractionFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ProcessObject Superclass; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Runtime information support. */ itkTypeMacro(OdfMaximaExtractionFilter, ImageToImageFilter) typedef itk::AnalyticalDiffusionQballReconstructionImageFilter QballReconstructionFilterType; typedef QballReconstructionFilterType::CoefficientImageType CoefficientImageType; typedef CoefficientImageType::PixelType CoefficientPixelType; typedef itk::VectorImage< short, 3 > DiffusionImageType; typedef vnl_vector_fixed< double, 3 > Vector3D; typedef VectorContainer< unsigned int, Vector3D > DirectionContainerType; typedef VectorContainer< unsigned int, DirectionContainerType::Pointer > ContainerType; typedef itk::Image ItkUcharImgType; typedef itk::Image< itk::Vector< float, 3 >, 3> ItkDirectionImage; typedef itk::VectorContainer< unsigned int, ItkDirectionImage::Pointer > ItkDirectionImageContainer; // output - itkGetMacro( OutputFiberBundle, mitk::FiberBundleX::Pointer) ///< vector field (peak sizes rescaled for visualization purposes) + itkGetMacro( OutputFiberBundle, mitk::FiberBundle::Pointer) ///< vector field (peak sizes rescaled for visualization purposes) itkGetMacro( NumDirectionsImage, ItkUcharImgType::Pointer) ///< number of peaks per voxel itkGetMacro( DirectionImageContainer, ItkDirectionImageContainer::Pointer) ///< container for output peaks // input itkSetMacro( MaskImage, ItkUcharImgType::Pointer) ///< only voxels inside the binary mask are processed itkSetMacro( NormalizationMethod, NormalizationMethods) ///< normalization method of ODF peaks itkSetMacro( DiffusionGradients, DirectionContainerType::Pointer) ///< input for qball reconstruction itkSetMacro( DiffusionImage, DiffusionImageType::Pointer) ///< input for qball reconstruction itkSetMacro( Bvalue, float) ///< input for qball reconstruction itkSetMacro( ShCoeffImage, CoefficientImageType::Pointer) ///< conatins spherical harmonic coefficients itkSetMacro( MaxNumPeaks, unsigned int) ///< if more peaks are found, only the largest are kept itkSetMacro( PeakThreshold, double) ///< threshold on peak length relative to the largest peak in the current voxel void GenerateData(); protected: OdfMaximaExtractionFilter(); ~OdfMaximaExtractionFilter(){} /** CSA Qball reconstruction (SH order 4) **/ bool ReconstructQballImage(); /** calculate roots of cubic equation ax³ + bx² + cx + d = 0 using cardanos method **/ std::vector SolveCubic(const double& a, const double& b, const double& c, const double& d); /** derivatives of SH representation of the ODF **/ double ODF_dtheta2(const double& sn, const double& cs, const double& A, const double& B, const double& C, const double& D, const double& E, const double& F, const double& G, const double& H); /** derivatives of SH representation of the ODF **/ double ODF_dphi2(const double& sn, const double& cs, const double& A, const double& B, const double& C, const double& D, const double& E, const double& F, const double& G, const double& H); /** derivatives of SH representation of the ODF **/ double ODF_dtheta(const double& sn, const double& cs, const double& A, const double& B, const double& C, const double& D, const double& E, const double& F, const double& G, const double& H); /** calculate all directions fullfilling the maximum consitions **/ void FindCandidatePeaks(const CoefficientPixelType& SHcoeff); /** cluster the peaks detected by FindCandidatePeaks and retain maximum m_MaxNumPeaks **/ std::vector< Vector3D > ClusterPeaks(const CoefficientPixelType& shCoeff); void Cart2Sph(const std::vector< Vector3D >& dir, vnl_matrix& sphCoords); vnl_matrix CalcShBasis(vnl_matrix& sphCoords, const int& shOrder); // diffusion weighted image (mandatory input) DirectionContainerType::Pointer m_DiffusionGradients; ///< input for qball reconstruction DiffusionImageType::Pointer m_DiffusionImage; ///< input for qball reconstruction float m_Bvalue; ///< input for qball reconstruction // binary mask image (optional input) ItkUcharImgType::Pointer m_MaskImage; ///< only voxels inside the binary mask are processed // input parameters NormalizationMethods m_NormalizationMethod; ///< normalization for peaks double m_PeakThreshold; ///< threshold on peak length relative to the largest peak in the current voxel unsigned int m_MaxNumPeaks; ///< if more peaks are found, only the largest are kept // intermediate results CoefficientImageType::Pointer m_ShCoeffImage; ///< conatins spherical harmonic coefficients std::vector< vnl_vector_fixed< double, 2 > > m_CandidatePeaks; ///< container for candidate peaks (all extrema, also minima) // output data - mitk::FiberBundleX::Pointer m_OutputFiberBundle; ///< vector field (peak sizes rescaled for visualization purposes) + mitk::FiberBundle::Pointer m_OutputFiberBundle; ///< vector field (peak sizes rescaled for visualization purposes) ItkUcharImgType::Pointer m_NumDirectionsImage; ///< number of peaks per voxel ItkDirectionImageContainer::Pointer m_DirectionImageContainer; ///< output peaks private: }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkOdfMaximaExtractionFilter.cpp" #endif #endif //__itkOdfMaximaExtractionFilter_h_ diff --git a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp index 9d463749d1..6421f65a8b 100644 --- a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp @@ -1,410 +1,418 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDiffusionPropertyHelper.h" #include #include #include #include const std::string mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME = "meta.GradientDirections"; const std::string mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME = "meta.OriginalGradientDirections"; const std::string mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME = "meta.MeasurementFrame"; const std::string mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME = "meta.ReferenceBValue"; const std::string mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME = "BValueMap"; mitk::DiffusionPropertyHelper::DiffusionPropertyHelper() { } mitk::DiffusionPropertyHelper::DiffusionPropertyHelper( mitk::Image* inputImage) : m_Image( inputImage ) { // Update props } mitk::DiffusionPropertyHelper::~DiffusionPropertyHelper() { } + +mitk::DiffusionPropertyHelper::ImageType::Pointer mitk::DiffusionPropertyHelper::GetItkVectorImage(mitk::Image* image) +{ + ImageType::Pointer vectorImage = ImageType::New(); + mitk::CastToItkImage(image, vectorImage); + return vectorImage; +} + mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::DiffusionPropertyHelper::CalcAveragedDirectionSet(double precision, GradientDirectionsContainerType::Pointer directions) { // save old and construct new direction container GradientDirectionsContainerType::Pointer newDirections = GradientDirectionsContainerType::New(); // fill new direction container for(GradientDirectionsContainerType::ConstIterator gdcitOld = directions->Begin(); gdcitOld != directions->End(); ++gdcitOld) { // already exists? bool found = false; for(GradientDirectionsContainerType::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; } void mitk::DiffusionPropertyHelper::AverageRedundantGradients(double precision) { mitk::GradientDirectionsProperty* DirectionsProperty = static_cast( m_Image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ); GradientDirectionsContainerType::Pointer oldDirs = DirectionsProperty->GetGradientDirectionsContainer(); GradientDirectionsContainerType::Pointer newDirs = CalcAveragedDirectionSet(precision, oldDirs); // if sizes equal, we do not need to do anything in this function if(oldDirs->size() == newDirs->size()) return; // new image ImageType::Pointer oldImage = ImageType::New(); mitk::CastToItkImage( m_Image, oldImage); ImageType::Pointer newITKImage = ImageType::New(); newITKImage->SetSpacing( oldImage->GetSpacing() ); // Set the image spacing newITKImage->SetOrigin( oldImage->GetOrigin() ); // Set the image origin newITKImage->SetDirection( oldImage->GetDirection() ); // Set the image direction newITKImage->SetLargestPossibleRegion( oldImage->GetLargestPossibleRegion() ); newITKImage->SetVectorLength( newDirs->size() ); newITKImage->SetBufferedRegion( oldImage->GetLargestPossibleRegion() ); newITKImage->Allocate(); // average image data that corresponds to identical directions itk::ImageRegionIterator< ImageType > newIt(newITKImage, newITKImage->GetLargestPossibleRegion()); newIt.GoToBegin(); itk::ImageRegionIterator< ImageType > oldIt(oldImage, oldImage->GetLargestPossibleRegion()); oldIt.GoToBegin(); // initial new value of voxel ImageType::PixelType newVec; newVec.SetSize(newDirs->size()); newVec.AllocateElements(newDirs->size()); // find which gradients should be averaged GradientDirectionsContainerType::Pointer oldDirections = oldDirs; std::vector > dirIndices; for(GradientDirectionsContainerType::ConstIterator gdcitNew = newDirs->Begin(); gdcitNew != newDirs->End(); ++gdcitNew) { dirIndices.push_back(std::vector(0)); for(GradientDirectionsContainerType::ConstIterator gdcitOld = oldDirs->Begin(); gdcitOld != oldDirections->End(); ++gdcitOld) { if(AreAlike(gdcitNew.Value(), gdcitOld.Value(), precision)) { //MITK_INFO << gdcitNew.Value() << " " << gdcitOld.Value(); dirIndices[gdcitNew.Index()].push_back(gdcitOld.Index()); } } } //int ind1 = -1; while(!newIt.IsAtEnd()) { // progress //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 ImageType::PixelType oldVec = oldIt.Get(); for(unsigned int i=0; iSetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( newDirs ) ); m_Image->SetProperty( mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( newDirs ) ); ApplyMeasurementFrame(); UpdateBValueMap(); std::cout << std::endl; } void mitk::DiffusionPropertyHelper::ApplyMeasurementFrame() { if( m_Image->GetProperty(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).IsNull() ) { return; } GradientDirectionsContainerType::Pointer originalDirections = static_cast( m_Image->GetProperty(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer())->GetGradientDirectionsContainer(); MeasurementFrameType measurementFrame = GetMeasurementFrame(m_Image); GradientDirectionsContainerType::Pointer directions = GradientDirectionsContainerType::New(); if( originalDirections.IsNull() || ( originalDirections->size() == 0 ) ) { // original direction container was not set return; } int c = 0; for(GradientDirectionsContainerType::ConstIterator gdcit = originalDirections->Begin(); gdcit != originalDirections->End(); ++gdcit) { vnl_vector vec = gdcit.Value(); vec = vec.pre_multiply(measurementFrame); MITK_INFO << gdcit.Value(); directions->InsertElement(c, vec); c++; } m_Image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( directions ) ); } void mitk::DiffusionPropertyHelper::UpdateBValueMap() { BValueMapType b_ValueMap; if(m_Image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).IsNull()) { } else { b_ValueMap = static_cast(m_Image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); } if(!b_ValueMap.empty()) { b_ValueMap.clear(); } if( m_Image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).IsNotNull() ) { GradientDirectionsContainerType::Pointer directions = static_cast( m_Image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); GradientDirectionsContainerType::ConstIterator gdcit; for( gdcit = directions->Begin(); gdcit != directions->End(); ++gdcit) { MITK_INFO << gdcit.Value(); b_ValueMap[GetB_Value(gdcit.Index())].push_back(gdcit.Index()); } } m_Image->SetProperty( mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str(), mitk::BValueMapProperty::New( b_ValueMap ) ); } bool mitk::DiffusionPropertyHelper::AreAlike(GradientDirectionType g1, GradientDirectionType g2, double precision) { GradientDirectionType diff = g1 - g2; GradientDirectionType diff2 = g1 + g2; return diff.two_norm() < precision || diff2.two_norm() < precision; } float mitk::DiffusionPropertyHelper::GetB_Value(unsigned int i) { GradientDirectionsContainerType::Pointer directions = static_cast( m_Image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); float b_value = static_cast(m_Image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(); if(i > directions->Size()-1) return -1; if(directions->ElementAt(i).one_norm() <= 0.0) { return 0; } else { double twonorm = directions->ElementAt(i).two_norm(); double bval = b_value*twonorm*twonorm; if (bval<0) bval = ceil(bval - 0.5); else bval = floor(bval + 0.5); return bval; } } void mitk::DiffusionPropertyHelper::InitializeImage() { this->ApplyMeasurementFrame(); this->UpdateBValueMap(); // initialize missing properties mitk::MeasurementFrameProperty::Pointer mf = dynamic_cast( m_Image->GetProperty(MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer()); if( mf.IsNull() ) { //no measurement frame present, identity is assumed MeasurementFrameType identity; identity.set_identity(); m_Image->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( identity )); } } bool mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(const mitk::DataNode* node) { return IsDiffusionWeightedImage(dynamic_cast(node->GetData())); } bool mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(const mitk::Image * image) { bool isDiffusionWeightedImage( true ); if( image == NULL ) { isDiffusionWeightedImage = false; } if( isDiffusionWeightedImage ) { mitk::FloatProperty::Pointer referenceBValue = dynamic_cast(image->GetProperty(REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer()); if( referenceBValue.IsNull() ) { isDiffusionWeightedImage = false; } } unsigned int gradientDirections( 0 ); if( isDiffusionWeightedImage ) { mitk::GradientDirectionsProperty::Pointer gradientDirectionsProperty = dynamic_cast(image->GetProperty(GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer()); if( gradientDirectionsProperty.IsNull() ) { isDiffusionWeightedImage = false; } else { gradientDirections = gradientDirectionsProperty->GetGradientDirectionsContainer()->size(); } } if( isDiffusionWeightedImage ) { unsigned int components = image->GetPixelType().GetNumberOfComponents(); if( components != gradientDirections ) { isDiffusionWeightedImage = false; } } return isDiffusionWeightedImage; } const mitk::DiffusionPropertyHelper::BValueMapType & mitk::DiffusionPropertyHelper::GetBValueMap(const mitk::Image *image) { return dynamic_cast(image->GetProperty(BVALUEMAPPROPERTYNAME.c_str()).GetPointer())->GetBValueMap(); } float mitk::DiffusionPropertyHelper::GetReferenceBValue(const mitk::Image *image) { return dynamic_cast(image->GetProperty(REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer())->GetValue(); } const mitk::DiffusionPropertyHelper::MeasurementFrameType & mitk::DiffusionPropertyHelper::GetMeasurementFrame(const mitk::Image *image) { mitk::MeasurementFrameProperty::Pointer mf = dynamic_cast( image->GetProperty(MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer()); if( mf.IsNull() ) { //no measurement frame present, identity is assumed MeasurementFrameType identity; identity.set_identity(); mf = mitk::MeasurementFrameProperty::New( identity ); } return mf->GetMeasurementFrame(); } mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(const mitk::Image *image) { return dynamic_cast(image->GetProperty(ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer())->GetGradientDirectionsContainer(); } mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::DiffusionPropertyHelper::GetGradientContainer(const mitk::Image *image) { return dynamic_cast(image->GetProperty(GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer())->GetGradientDirectionsContainer(); } bool mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage() const { return IsDiffusionWeightedImage(m_Image); } const mitk::DiffusionPropertyHelper::BValueMapType &mitk::DiffusionPropertyHelper::GetBValueMap() const { return GetBValueMap(m_Image); } float mitk::DiffusionPropertyHelper::GetReferenceBValue() const { return GetReferenceBValue(m_Image); } const mitk::DiffusionPropertyHelper::MeasurementFrameType & mitk::DiffusionPropertyHelper::GetMeasurementFrame() const { return GetMeasurementFrame(m_Image); } mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::DiffusionPropertyHelper::GetOriginalGradientContainer() const { return GetOriginalGradientContainer(m_Image); } mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::DiffusionPropertyHelper::GetGradientContainer() const { return GetGradientContainer(m_Image); } diff --git a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.h b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.h index be48d90e8c..626243baea 100644 --- a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.h +++ b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.h @@ -1,135 +1,137 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKDIFFUSIONPROPERTYHELPER_H #define MITKDIFFUSIONPROPERTYHELPER_H #include #include #include #include #include #include namespace mitk { /** \brief Helper class for mitk::Images containing diffusion weighted data * * This class takes a pointer to a mitk::Image containing diffusion weighted information and provides * functions to manipulate the diffusion meta-data. Will log an error if required information is * missing. */ class MITKDIFFUSIONCORE_EXPORT DiffusionPropertyHelper { public: typedef short DiffusionPixelType; typedef mitk::BValueMapProperty::BValueMap BValueMapType; typedef GradientDirectionsProperty::GradientDirectionType GradientDirectionType; typedef GradientDirectionsProperty::GradientDirectionsContainerType GradientDirectionsContainerType; typedef mitk::MeasurementFrameProperty::MeasurementFrameType MeasurementFrameType; typedef itk::VectorImage< DiffusionPixelType, 3> ImageType; static const std::string GRADIENTCONTAINERPROPERTYNAME; static const std::string ORIGINALGRADIENTCONTAINERPROPERTYNAME; static const std::string MEASUREMENTFRAMEPROPERTYNAME; static const std::string REFERENCEBVALUEPROPERTYNAME; static const std::string BVALUEMAPPROPERTYNAME; /// Public constructor, takes a mitk::Image pointer as argument DiffusionPropertyHelper( mitk::Image* inputImage ); ~DiffusionPropertyHelper(); /** \brief Decide whether a provided image is a valid diffusion weighted image * * An image will be considered a valid diffusion weighted image if the following are true * - It has a reference b value * - It has a gradient directions property * - The number of gradients directions matches the number of components of the image * * This does not guarantee that the data is sensible or accurate, it just verfies that it * meets the formal requirements to possibly be a valid diffusion weighted image. */ static bool IsDiffusionWeightedImage(const mitk::Image *); static bool IsDiffusionWeightedImage(const mitk::DataNode* node); + static ImageType::Pointer GetItkVectorImage(Image *image); + /// Convenience method to get the BValueMap static const BValueMapType & GetBValueMap(const mitk::Image *); /// Convenience method to get the BValue static float GetReferenceBValue(const mitk::Image *); /** \brief Convenience method to get the measurement frame * * This method will return the measurement frame of the image. * * \note If the image has no associated measurement frame the identity will be returned. */ static const MeasurementFrameType & GetMeasurementFrame(const mitk::Image *); /// Convenience method to get the original gradient directions static GradientDirectionsContainerType::Pointer GetOriginalGradientContainer(const mitk::Image *); /// Convenience method to get the gradient directions static GradientDirectionsContainerType::Pointer GetGradientContainer(const mitk::Image *); const BValueMapType & GetBValueMap() const; float GetReferenceBValue() const; const MeasurementFrameType & GetMeasurementFrame() const; GradientDirectionsContainerType::Pointer GetOriginalGradientContainer() const; GradientDirectionsContainerType::Pointer GetGradientContainer() const; bool IsDiffusionWeightedImage() const; void AverageRedundantGradients(double precision); /** \brief Make certain the owned image is up to date with all necessary properties * * This function will generate the B Value map and copy all properties to the owned image. */ void InitializeImage(); GradientDirectionsContainerType::Pointer CalcAveragedDirectionSet(double precision, GradientDirectionsContainerType::Pointer directions); protected: DiffusionPropertyHelper(); /** * \brief Apply the previouse set MeasurementFrame to all gradients in the GradientsDirectionContainer (m_Directions) * * \warning first set the MeasurementFrame */ void ApplyMeasurementFrame(); /** * \brief Update the BValueMap (m_B_ValueMap) using the current gradient directions (m_Directions) * * \warning Have to be called after each manipulation on the GradientDirectionContainer * !especially after manipulation of the m_Directions (GetDirections()) container via pointer access! */ void UpdateBValueMap(); /// Determines whether gradients can be considered to be equal bool AreAlike(GradientDirectionType g1, GradientDirectionType g2, double precision); /// Get the b value belonging to an index float GetB_Value(unsigned int i); mitk::Image* m_Image; }; } #endif diff --git a/Modules/DiffusionImaging/DiffusionCore/Testing/mitkImageReconstructionTest.cpp b/Modules/DiffusionImaging/DiffusionCore/Testing/mitkImageReconstructionTest.cpp index 33bfd4cd53..5acb9e5171 100755 --- a/Modules/DiffusionImaging/DiffusionCore/Testing/mitkImageReconstructionTest.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/Testing/mitkImageReconstructionTest.cpp @@ -1,158 +1,157 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include -#include #include #include #include #include #include #include #include #include using namespace std; int mitkImageReconstructionTest(int argc, char* argv[]) { MITK_TEST_BEGIN("mitkImageReconstructionTest"); MITK_TEST_CONDITION_REQUIRED(argc>1,"check for input data") try { mitk::Image::Pointer dwi = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[1])->GetData()); itk::VectorImage::Pointer itkVectorImagePointer = itk::VectorImage::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); float b_value = mitk::DiffusionPropertyHelper::GetReferenceBValue( dwi ); mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradients = mitk::DiffusionPropertyHelper::GetGradientContainer(dwi); { MITK_INFO << "Tensor reconstruction " << argv[2]; mitk::TensorImage::Pointer tensorImage = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[2])->GetData()); typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, float > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); filter->SetGradientImage( gradients, itkVectorImagePointer ); filter->SetBValue( b_value ); filter->Update(); mitk::TensorImage::Pointer testImage = mitk::TensorImage::New(); testImage->InitializeByItk( filter->GetOutput() ); testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *tensorImage, 0.0001, true), "tensor reconstruction test."); } { MITK_INFO << "Numerical Q-ball reconstruction " << argv[3]; mitk::QBallImage::Pointer qballImage = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[3])->GetData()); typedef itk::DiffusionQballReconstructionImageFilter QballReconstructionImageFilterType; QballReconstructionImageFilterType::Pointer filter = QballReconstructionImageFilterType::New(); filter->SetGradientImage( gradients, itkVectorImagePointer ); filter->SetBValue( b_value ); filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_STANDARD); filter->Update(); mitk::QBallImage::Pointer testImage = mitk::QBallImage::New(); testImage->InitializeByItk( filter->GetOutput() ); testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *qballImage, 0.0001, true), "Numerical Q-ball reconstruction test."); } { MITK_INFO << "Standard Q-ball reconstruction " << argv[4]; mitk::QBallImage::Pointer qballImage = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[4])->GetData()); typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetGradientImage( gradients, itkVectorImagePointer ); filter->SetBValue( b_value ); filter->SetLambda(0.006); filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); filter->Update(); mitk::QBallImage::Pointer testImage = mitk::QBallImage::New(); testImage->InitializeByItk( filter->GetOutput() ); testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *qballImage, 0.0001, true), "Standard Q-ball reconstruction test."); } { MITK_INFO << "CSA Q-ball reconstruction " << argv[5]; mitk::QBallImage::Pointer qballImage = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[5])->GetData()); typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetGradientImage( gradients, itkVectorImagePointer ); filter->SetBValue( b_value ); filter->SetLambda(0.006); filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); mitk::QBallImage::Pointer testImage = mitk::QBallImage::New(); testImage->InitializeByItk( filter->GetOutput() ); testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *qballImage, 0.0001, true), "CSA Q-ball reconstruction test."); } { MITK_INFO << "ADC profile reconstruction " << argv[6]; mitk::QBallImage::Pointer qballImage = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[6])->GetData()); typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetGradientImage( gradients, itkVectorImagePointer ); filter->SetBValue( b_value ); filter->SetLambda(0.006); filter->SetNormalizationMethod(FilterType::QBAR_ADC_ONLY); filter->Update(); mitk::QBallImage::Pointer testImage = mitk::QBallImage::New(); testImage->InitializeByItk( filter->GetOutput() ); testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *qballImage, 0.0001, true), "ADC profile reconstruction test."); } { MITK_INFO << "Raw signal modeling " << argv[7]; mitk::QBallImage::Pointer qballImage = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[7])->GetData()); typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetGradientImage( gradients, itkVectorImagePointer ); filter->SetBValue( b_value ); filter->SetLambda(0.006); filter->SetNormalizationMethod(FilterType::QBAR_RAW_SIGNAL); filter->Update(); mitk::QBallImage::Pointer testImage = mitk::QBallImage::New(); testImage->InitializeByItk( filter->GetOutput() ); testImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *qballImage, 0.0001, true), "Raw signal modeling test."); } } catch (itk::ExceptionObject e) { MITK_INFO << e; return EXIT_FAILURE; } catch (std::exception e) { MITK_INFO << e.what(); return EXIT_FAILURE; } catch (...) { MITK_INFO << "ERROR!?!"; return EXIT_FAILURE; } MITK_TEST_END(); } diff --git a/Modules/DiffusionImaging/DiffusionIO/files.cmake b/Modules/DiffusionImaging/DiffusionIO/files.cmake index 5686192842..01f7540f91 100644 --- a/Modules/DiffusionImaging/DiffusionIO/files.cmake +++ b/Modules/DiffusionImaging/DiffusionIO/files.cmake @@ -1,39 +1,43 @@ set(CPP_FILES mitkDiffusionModuleActivator.cpp mitkNrrdTbssImageWriterFactory.cpp - #mitkFiberBundleXIOFactory.cpp + #mitkFiberBundleIOFactory.cpp mitkConnectomicsNetworkReader.cpp mitkConnectomicsNetworkWriter.cpp mitkConnectomicsNetworkSerializer.cpp mitkConnectomicsNetworkDefinitions.cpp mitkNrrdTbssRoiImageIOFactory.cpp - #mitkFiberBundleXWriterFactory.cpp + #mitkFiberBundleWriterFactory.cpp mitkNrrdTbssRoiImageWriterFactory.cpp mitkNrrdTensorImageReader.cpp mitkNrrdTensorImageWriter.cpp mitkTensorImageSerializer.cpp mitkTensorImageSource.cpp mitkFiberTrackingObjectFactory.cpp mitkConnectomicsObjectFactory.cpp mitkQuantificationObjectFactory.cpp mitkNrrdTbssImageIOFactory.cpp mitkDiffusionCoreObjectFactory.cpp mitkDiffusionIOMimeTypes.cpp - mitkNrrdDiffusionImageReader.cpp - mitkNrrdDiffusionImageWriter.cpp + mitkDiffusionImageNrrdReaderService.cpp + mitkDiffusionImageNrrdWriterService.cpp + mitkDiffusionImageNiftiReaderService.cpp + mitkDiffusionImageNiftiWriterService.cpp mitkNrrdQBallImageReader.cpp mitkNrrdQBallImageWriter.cpp mitkQBallImageSerializer.cpp - mitkFiberBundleXReader.cpp - mitkFiberBundleXWriter.cpp - mitkFiberBundleXSerializer.cpp - mitkFiberBundleXMapper2D.cpp - mitkFiberBundleXMapper3D.cpp + mitkFiberBundleTrackVisReader.cpp + mitkFiberBundleTrackVisWriter.cpp + mitkFiberBundleVtkReader.cpp + mitkFiberBundleVtkWriter.cpp + mitkFiberBundleSerializer.cpp + mitkFiberBundleMapper2D.cpp + mitkFiberBundleMapper3D.cpp mitkCompositeMapper.cpp ) diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionCoreObjectFactory.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionCoreObjectFactory.cpp index 9282a2e9d3..ac08e0bf2a 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionCoreObjectFactory.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionCoreObjectFactory.cpp @@ -1,159 +1,157 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDiffusionCoreObjectFactory.h" #include "mitkProperties.h" #include "mitkBaseRenderer.h" #include "mitkDataNode.h" -#include "mitkNrrdDiffusionImageWriter.h" - #include "mitkCompositeMapper.h" #include "mitkGPUVolumeMapper3D.h" #include "mitkVolumeDataVtkMapper3D.h" typedef short DiffusionPixelType; typedef std::multimap MultimapType; mitk::DiffusionCoreObjectFactory::DiffusionCoreObjectFactory() : CoreObjectFactoryBase() { static bool alreadyDone = false; if (!alreadyDone) { MITK_DEBUG << "DiffusionCoreObjectFactory c'tor" << std::endl; CreateFileExtensionsMap(); alreadyDone = true; } } mitk::DiffusionCoreObjectFactory::~DiffusionCoreObjectFactory() { } mitk::Mapper::Pointer mitk::DiffusionCoreObjectFactory::CreateMapper(mitk::DataNode* node, MapperSlotId id) { mitk::Mapper::Pointer newMapper=NULL; if ( id == mitk::BaseRenderer::Standard2D ) { std::string classname("QBallImage"); if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::CompositeMapper::New(); newMapper->SetDataNode(node); node->SetMapper(3, ((CompositeMapper*)newMapper.GetPointer())->GetImageMapper()); } classname = "TensorImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::CompositeMapper::New(); newMapper->SetDataNode(node); node->SetMapper(3, ((CompositeMapper*)newMapper.GetPointer())->GetImageMapper()); } } else if ( id == mitk::BaseRenderer::Standard3D ) { std::string classname("QBallImage"); if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::GPUVolumeMapper3D::New(); newMapper->SetDataNode(node); } classname = "TensorImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::GPUVolumeMapper3D::New(); newMapper->SetDataNode(node); } } return newMapper; } void mitk::DiffusionCoreObjectFactory::SetDefaultProperties(mitk::DataNode* node) { std::string classname = "QBallImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::CompositeMapper::SetDefaultProperties(node); mitk::GPUVolumeMapper3D::SetDefaultProperties(node); } classname = "TensorImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::CompositeMapper::SetDefaultProperties(node); mitk::GPUVolumeMapper3D::SetDefaultProperties(node); } } const char* mitk::DiffusionCoreObjectFactory::GetFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_FileExtensionsMap, fileExtension); return fileExtension.c_str(); } mitk::CoreObjectFactoryBase::MultimapType mitk::DiffusionCoreObjectFactory::GetFileExtensionsMap() { return m_FileExtensionsMap; } const char* mitk::DiffusionCoreObjectFactory::GetSaveFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_SaveFileExtensionsMap, fileExtension); return fileExtension.c_str(); } mitk::CoreObjectFactoryBase::MultimapType mitk::DiffusionCoreObjectFactory::GetSaveFileExtensionsMap() { return m_SaveFileExtensionsMap; } void mitk::DiffusionCoreObjectFactory::CreateFileExtensionsMap() { } struct RegisterDiffusionCoreObjectFactory{ RegisterDiffusionCoreObjectFactory() : m_Factory( mitk::DiffusionCoreObjectFactory::New() ) { mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory( m_Factory ); } ~RegisterDiffusionCoreObjectFactory() { mitk::CoreObjectFactory::GetInstance()->UnRegisterExtraFactory( m_Factory ); } mitk::DiffusionCoreObjectFactory::Pointer m_Factory; }; static RegisterDiffusionCoreObjectFactory registerDiffusionCoreObjectFactory; diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionIOMimeTypes.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionIOMimeTypes.cpp index 20ac728707..f3bb89a8e2 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionIOMimeTypes.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionIOMimeTypes.cpp @@ -1,233 +1,327 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDiffusionIOMimeTypes.h" #include "mitkIOMimeTypes.h" #include #include #include #include #include namespace mitk { std::vector DiffusionIOMimeTypes::Get() { std::vector mimeTypes; // order matters here (descending rank for mime types) - mimeTypes.push_back(DWI_MIMETYPE().Clone()); + mimeTypes.push_back(DWI_NRRD_MIMETYPE().Clone()); + mimeTypes.push_back(DWI_NIFTI_MIMETYPE().Clone()); mimeTypes.push_back(DTI_MIMETYPE().Clone()); mimeTypes.push_back(QBI_MIMETYPE().Clone()); - mimeTypes.push_back(FIBERBUNDLE_MIMETYPE().Clone()); + mimeTypes.push_back(FIBERBUNDLE_VTK_MIMETYPE().Clone()); + mimeTypes.push_back(FIBERBUNDLE_TRK_MIMETYPE().Clone()); mimeTypes.push_back(CONNECTOMICS_MIMETYPE().Clone()); return mimeTypes; } // Mime Types -CustomMimeType DiffusionIOMimeTypes::FIBERBUNDLE_MIMETYPE() +CustomMimeType DiffusionIOMimeTypes::FIBERBUNDLE_VTK_MIMETYPE() { - CustomMimeType mimeType(FIBERBUNDLE_MIMETYPE_NAME()); - std::string category = "Fiber Bundle File"; - mimeType.SetComment("Fiber Bundles"); + CustomMimeType mimeType(FIBERBUNDLE_VTK_MIMETYPE_NAME()); + std::string category = "VTK Fibers"; + mimeType.SetComment("VTK Fibers"); mimeType.SetCategory(category); mimeType.AddExtension("fib"); + mimeType.AddExtension("vtk"); + return mimeType; +} + +CustomMimeType DiffusionIOMimeTypes::FIBERBUNDLE_TRK_MIMETYPE() +{ + CustomMimeType mimeType(FIBERBUNDLE_TRK_MIMETYPE_NAME()); + std::string category = "TrackVis Fibers"; + mimeType.SetComment("TrackVis Fibers"); + mimeType.SetCategory(category); mimeType.AddExtension("trk"); - //mimeType.AddExtension("vtk"); return mimeType; } -DiffusionIOMimeTypes::DwiMimeType::DwiMimeType() - : CustomMimeType(DWI_MIMETYPE_NAME()) +DiffusionIOMimeTypes::DiffusionImageNrrdMimeType::DiffusionImageNrrdMimeType() + : CustomMimeType(DWI_NRRD_MIMETYPE_NAME()) { std::string category = "Diffusion Weighted Image"; this->SetCategory(category); this->SetComment("Diffusion Weighted Images"); this->AddExtension("dwi"); this->AddExtension("hdwi"); - this->AddExtension("fsl"); - this->AddExtension("fslgz"); this->AddExtension("nrrd"); } -bool DiffusionIOMimeTypes::DwiMimeType::AppliesTo(const std::string &path) const +bool DiffusionIOMimeTypes::DiffusionImageNrrdMimeType::AppliesTo(const std::string &path) const { bool canRead( CustomMimeType::AppliesTo(path) ); // fix for bug 18572 // Currently this function is called for writing as well as reading, in that case // the image information can of course not be read // This is a bug, this function should only be called for reading. if( ! itksys::SystemTools::FileExists( path.c_str() ) ) { return canRead; } //end fix for bug 18572 - std::string ext = itksys::SystemTools::GetFilenameLastExtension( path ); + std::string ext = this->GetExtension( path ); ext = itksys::SystemTools::LowerCase( ext ); // Simple NRRD files should only be considered for this mime type if they contain // corresponding tags if( ext == ".nrrd" ) { itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileName(path); try { io->ReadImageInformation(); itk::MetaDataDictionary imgMetaDictionary = io->GetMetaDataDictionary(); std::vector imgMetaKeys = imgMetaDictionary.GetKeys(); std::vector::const_iterator itKey = imgMetaKeys.begin(); std::string metaString; for (; itKey != imgMetaKeys.end(); itKey ++) { itk::ExposeMetaData (imgMetaDictionary, *itKey, metaString); if (itKey->find("modality") != std::string::npos) { if (metaString.find("DWMRI") != std::string::npos) { return canRead; } } } } catch( const itk::ExceptionObject &e ) { MITK_ERROR << "ITK Exception: " << e.what(); } canRead = false; } return canRead; } -DiffusionIOMimeTypes::DwiMimeType* DiffusionIOMimeTypes::DwiMimeType::Clone() const +DiffusionIOMimeTypes::DiffusionImageNrrdMimeType* DiffusionIOMimeTypes::DiffusionImageNrrdMimeType::Clone() const { - return new DwiMimeType(*this); + return new DiffusionImageNrrdMimeType(*this); } -DiffusionIOMimeTypes::DwiMimeType DiffusionIOMimeTypes::DWI_MIMETYPE() +DiffusionIOMimeTypes::DiffusionImageNrrdMimeType DiffusionIOMimeTypes::DWI_NRRD_MIMETYPE() +{ + return DiffusionImageNrrdMimeType(); +} + +DiffusionIOMimeTypes::DiffusionImageNiftiMimeType::DiffusionImageNiftiMimeType() + : CustomMimeType(DWI_NIFTI_MIMETYPE_NAME()) { - return DwiMimeType(); + std::string category = "Diffusion Weighted Image"; + this->SetCategory(category); + this->SetComment("Diffusion Weighted Images"); + this->AddExtension("fsl"); + this->AddExtension("fslgz"); + this->AddExtension("nii"); + this->AddExtension("nii.gz"); +} + +bool DiffusionIOMimeTypes::DiffusionImageNiftiMimeType::AppliesTo(const std::string &path) const +{ + bool canRead(CustomMimeType::AppliesTo(path)); + + // fix for bug 18572 + // Currently this function is called for writing as well as reading, in that case + // the image information can of course not be read + // This is a bug, this function should only be called for reading. + if (!itksys::SystemTools::FileExists(path.c_str())) + { + return canRead; + } + //end fix for bug 18572 + + std::string ext = this->GetExtension(path); + ext = itksys::SystemTools::LowerCase(ext); + + // Nifti files should only be considered for this mime type if they are + // accompanied by bvecs and bvals files defining the diffusion information + if (ext == ".nii" || ext == ".nii.gz") + { + std::string base = itksys::SystemTools::GetFilenamePath(path) + "/" + + this->GetFilenameWithoutExtension(path); + + if (itksys::SystemTools::FileExists(std::string(base + ".bvec").c_str()) + && itksys::SystemTools::FileExists(std::string(base + ".bval").c_str()) + ) + { + return canRead; + } + + if (itksys::SystemTools::FileExists(std::string(base + ".bvecs").c_str()) + && itksys::SystemTools::FileExists(std::string(base + ".bvals").c_str()) + ) + { + return canRead; + } + + canRead = false; + } + + return canRead; +} + +DiffusionIOMimeTypes::DiffusionImageNiftiMimeType* DiffusionIOMimeTypes::DiffusionImageNiftiMimeType::Clone() const +{ + return new DiffusionImageNiftiMimeType(*this); +} + + +DiffusionIOMimeTypes::DiffusionImageNiftiMimeType DiffusionIOMimeTypes::DWI_NIFTI_MIMETYPE() +{ + return DiffusionImageNiftiMimeType(); } CustomMimeType DiffusionIOMimeTypes::DTI_MIMETYPE() { CustomMimeType mimeType(DTI_MIMETYPE_NAME()); std::string category = "Tensor Images"; mimeType.SetComment("Diffusion Tensor Images"); mimeType.SetCategory(category); mimeType.AddExtension("dti"); mimeType.AddExtension("hdti"); return mimeType; } CustomMimeType DiffusionIOMimeTypes::QBI_MIMETYPE() { CustomMimeType mimeType(QBI_MIMETYPE_NAME()); std::string category = "Q-Ball Images"; mimeType.SetComment("Diffusion Q-Ball Images"); mimeType.SetCategory(category); mimeType.AddExtension("qbi"); mimeType.AddExtension("hqbi"); return mimeType; } CustomMimeType DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE() { CustomMimeType mimeType(CONNECTOMICS_MIMETYPE_NAME()); std::string category = "Connectomics Networks"; mimeType.SetComment("Connectomics Networks"); mimeType.SetCategory(category); mimeType.AddExtension("cnf"); return mimeType; } // Names -std::string DiffusionIOMimeTypes::DWI_MIMETYPE_NAME() +std::string DiffusionIOMimeTypes::DWI_NRRD_MIMETYPE_NAME() { static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".dwi"; return name; } +std::string DiffusionIOMimeTypes::DWI_NIFTI_MIMETYPE_NAME() +{ + static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".fsl"; + return name; +} + std::string DiffusionIOMimeTypes::DTI_MIMETYPE_NAME() { static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".dti"; return name; } std::string DiffusionIOMimeTypes::QBI_MIMETYPE_NAME() { static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".qbi"; return name; } -std::string DiffusionIOMimeTypes::FIBERBUNDLE_MIMETYPE_NAME() +std::string DiffusionIOMimeTypes::FIBERBUNDLE_VTK_MIMETYPE_NAME() { - static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".fib"; + static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".FiberBundle.vtk"; + return name; +} + +std::string DiffusionIOMimeTypes::FIBERBUNDLE_TRK_MIMETYPE_NAME() +{ + static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".FiberBundle.trk"; return name; } std::string DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE_NAME() { static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".cnf"; return name; } // Descriptions std::string DiffusionIOMimeTypes::FIBERBUNDLE_MIMETYPE_DESCRIPTION() { static std::string description = "Fiberbundles"; return description; } -std::string DiffusionIOMimeTypes::DWI_MIMETYPE_DESCRIPTION() +std::string DiffusionIOMimeTypes::DWI_NRRD_MIMETYPE_DESCRIPTION() +{ + static std::string description = "Diffusion Weighted Images"; + return description; +} + +std::string DiffusionIOMimeTypes::DWI_NIFTI_MIMETYPE_DESCRIPTION() { static std::string description = "Diffusion Weighted Images"; return description; } std::string DiffusionIOMimeTypes::DTI_MIMETYPE_DESCRIPTION() { static std::string description = "Diffusion Tensor Images"; return description; } std::string DiffusionIOMimeTypes::QBI_MIMETYPE_DESCRIPTION() { static std::string description = "Q-Ball Images"; return description; } std::string DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE_DESCRIPTION() { static std::string description = "Connectomics Networks"; return description; } } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionIOMimeTypes.h b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionIOMimeTypes.h index 2ba65f35e1..ba381c92cc 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionIOMimeTypes.h +++ b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionIOMimeTypes.h @@ -1,81 +1,96 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKDIFFUSIONIOMIMETYPES_H #define MITKDIFFUSIONIOMIMETYPES_H #include "mitkCustomMimeType.h" #include #include namespace mitk { class DiffusionIOMimeTypes { public: - class MITKDIFFUSIONIO_EXPORT DwiMimeType : public CustomMimeType + class MITKDIFFUSIONIO_EXPORT DiffusionImageNrrdMimeType : public CustomMimeType { public: - DwiMimeType(); + DiffusionImageNrrdMimeType(); virtual bool AppliesTo(const std::string &path) const; - virtual DwiMimeType* Clone() const; + virtual DiffusionImageNrrdMimeType* Clone() const; }; + class MITKDIFFUSIONIO_EXPORT DiffusionImageNiftiMimeType : public CustomMimeType + { + public: + DiffusionImageNiftiMimeType(); + virtual bool AppliesTo(const std::string &path) const; + virtual DiffusionImageNiftiMimeType* Clone() const; + }; // Get all Diffusion Mime Types static std::vector Get(); // ------------------------------ VTK formats ---------------------------------- - static CustomMimeType FIBERBUNDLE_MIMETYPE(); // fib - - static std::string FIBERBUNDLE_MIMETYPE_NAME(); + static CustomMimeType FIBERBUNDLE_VTK_MIMETYPE(); + static std::string FIBERBUNDLE_VTK_MIMETYPE_NAME(); static std::string FIBERBUNDLE_MIMETYPE_DESCRIPTION(); + // ------------------------------ TrackVis formats ---------------------------------- + + static CustomMimeType FIBERBUNDLE_TRK_MIMETYPE(); + static std::string FIBERBUNDLE_TRK_MIMETYPE_NAME(); + + // ------------------------- Image formats (ITK based) -------------------------- - static DwiMimeType DWI_MIMETYPE(); // dwi, hdwi + static DiffusionImageNrrdMimeType DWI_NRRD_MIMETYPE(); + static DiffusionImageNiftiMimeType DWI_NIFTI_MIMETYPE(); static CustomMimeType DTI_MIMETYPE(); // dti, hdti static CustomMimeType QBI_MIMETYPE(); // qbi, hqbi - static std::string DWI_MIMETYPE_NAME(); + static std::string DWI_NRRD_MIMETYPE_NAME(); + static std::string DWI_NIFTI_MIMETYPE_NAME(); static std::string DTI_MIMETYPE_NAME(); static std::string QBI_MIMETYPE_NAME(); - static std::string DWI_MIMETYPE_DESCRIPTION(); + static std::string DWI_NRRD_MIMETYPE_DESCRIPTION(); + static std::string DWI_NIFTI_MIMETYPE_DESCRIPTION(); static std::string DTI_MIMETYPE_DESCRIPTION(); static std::string QBI_MIMETYPE_DESCRIPTION(); // ------------------------------ MITK formats ---------------------------------- static CustomMimeType CONNECTOMICS_MIMETYPE(); // cnf static std::string CONNECTOMICS_MIMETYPE_NAME(); static std::string CONNECTOMICS_MIMETYPE_DESCRIPTION(); private: // purposely not implemented DiffusionIOMimeTypes(); DiffusionIOMimeTypes(const DiffusionIOMimeTypes&); }; } #endif // MITKDIFFUSIONIOMIMETYPES_H diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageReader.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNiftiReaderService.cpp similarity index 67% copy from Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageReader.cpp copy to Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNiftiReaderService.cpp index a2b29fd956..d2f42479cf 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageReader.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNiftiReaderService.cpp @@ -1,434 +1,458 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef __mitkNrrdDiffusionImageReader_cpp -#define __mitkNrrdDiffusionImageReader_cpp +#ifndef __mitkDiffusionImageNiftiReaderService_cpp +#define __mitkDiffusionImageNiftiReaderService_cpp -#include "mitkNrrdDiffusionImageReader.h" +#include "mitkDiffusionImageNiftiReaderService.h" #include #include // Diffusion properties #include #include #include #include // ITK includes #include #include #include "itksys/SystemTools.hxx" #include "itkImageFileReader.h" #include "itkMetaDataObject.h" -#include "itkNrrdImageIO.h" #include "itkNiftiImageIO.h" #include "mitkCustomMimeType.h" #include "mitkDiffusionIOMimeTypes.h" #include -#include #include #include #include "mitkIOUtil.h" namespace mitk { - NrrdDiffusionImageReader:: - NrrdDiffusionImageReader(const NrrdDiffusionImageReader & other) + DiffusionImageNiftiReaderService:: + DiffusionImageNiftiReaderService(const DiffusionImageNiftiReaderService & other) : AbstractFileReader(other) { } - NrrdDiffusionImageReader* NrrdDiffusionImageReader::Clone() const + DiffusionImageNiftiReaderService* DiffusionImageNiftiReaderService::Clone() const { - return new NrrdDiffusionImageReader(*this); + return new DiffusionImageNiftiReaderService(*this); } - NrrdDiffusionImageReader:: - ~NrrdDiffusionImageReader() + DiffusionImageNiftiReaderService:: + ~DiffusionImageNiftiReaderService() {} - NrrdDiffusionImageReader:: - NrrdDiffusionImageReader() - : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::DWI_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DWI_MIMETYPE_DESCRIPTION() ) + DiffusionImageNiftiReaderService:: + DiffusionImageNiftiReaderService() + : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::DWI_NIFTI_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DWI_NIFTI_MIMETYPE_DESCRIPTION() ) { m_ServiceReg = this->RegisterService(); } std::vector > - NrrdDiffusionImageReader:: + DiffusionImageNiftiReaderService:: Read() { std::vector > result; // Since everything is completely read in GenerateOutputInformation() it is stored // in a cache variable. A timestamp is associated. // If the timestamp of the cache variable is newer than the MTime, we only need to // assign the cache variable to the DataObject. // Otherwise, the tree must be read again from the file and OuputInformation must // be updated! if(m_OutputCache.IsNull()) InternalRead(); result.push_back(m_OutputCache.GetPointer()); return result; } - void NrrdDiffusionImageReader::InternalRead() + void DiffusionImageNiftiReaderService::InternalRead() { OutputType::Pointer outputForCache = OutputType::New(); if ( this->GetInputLocation() == "") { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, the filename to be read is empty!"); } else { try { 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; } } - MITK_INFO << "NrrdDiffusionImageReader: reading image information"; + MITK_INFO << "DiffusionImageNiftiReaderService: reading image information"; VectorImageType::Pointer itkVectorImage; - std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->GetInputLocation()); - ext = itksys::SystemTools::LowerCase(ext); - if (ext == ".hdwi" || ext == ".dwi" || ext == ".nrrd") - { - typedef itk::ImageFileReader FileReaderType; - FileReaderType::Pointer reader = FileReaderType::New(); - reader->SetFileName(this->GetInputLocation()); - itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); - reader->SetImageIO(io); - reader->Update(); - itkVectorImage = reader->GetOutput(); - } - else if(ext == ".fsl" || ext == ".fslgz") + std::string ext = this->GetMimeType()->GetExtension( this->GetInputLocation() ); + ext = itksys::SystemTools::LowerCase( ext ); + + if(ext == ".fsl" || ext == ".fslgz") { // create temporary file with correct ending for nifti-io std::string fname3 = "temp_dwi"; fname3 += ext == ".fsl" ? ".nii" : ".nii.gz"; itksys::SystemTools::CopyAFile(this->GetInputLocation().c_str(), fname3.c_str()); // create reader and read file typedef itk::Image ImageType4D; itk::NiftiImageIO::Pointer io2 = itk::NiftiImageIO::New(); typedef itk::ImageFileReader FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetFileName(fname3); reader->SetImageIO(io2); reader->Update(); ImageType4D::Pointer img4 = reader->GetOutput(); // delete temporary file itksys::SystemTools::RemoveFile(fname3.c_str()); + // convert 4D file to vector image + itkVectorImage = VectorImageType::New(); + + VectorImageType::SpacingType spacing; + ImageType4D::SpacingType spacing4 = img4->GetSpacing(); + for(int i=0; i<3; i++) + spacing[i] = spacing4[i]; + itkVectorImage->SetSpacing( spacing ); // Set the image spacing + + VectorImageType::PointType origin; + ImageType4D::PointType origin4 = img4->GetOrigin(); + for(int i=0; i<3; i++) + origin[i] = origin4[i]; + itkVectorImage->SetOrigin( origin ); // Set the image origin + + VectorImageType::DirectionType direction; + ImageType4D::DirectionType direction4 = img4->GetDirection(); + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + direction[i][j] = direction4[i][j]; + itkVectorImage->SetDirection( direction ); // Set the image direction + + VectorImageType::RegionType region; + ImageType4D::RegionType region4 = img4->GetLargestPossibleRegion(); + + VectorImageType::RegionType::SizeType size; + ImageType4D::RegionType::SizeType size4 = region4.GetSize(); + + for(int i=0; i<3; i++) + size[i] = size4[i]; + + VectorImageType::RegionType::IndexType index; + ImageType4D::RegionType::IndexType index4 = region4.GetIndex(); + for(int i=0; i<3; i++) + index[i] = index4[i]; + + region.SetSize(size); + region.SetIndex(index); + itkVectorImage->SetRegions( region ); + + itkVectorImage->SetVectorLength(size4[3]); + itkVectorImage->Allocate(); + + itk::ImageRegionIterator it ( itkVectorImage, itkVectorImage->GetLargestPossibleRegion() ); + typedef VectorImageType::PixelType VecPixType; + for (it.GoToBegin(); !it.IsAtEnd(); ++it) + { + VecPixType vec = it.Get(); + VectorImageType::IndexType currentIndex = it.GetIndex(); + for(int i=0; i<3; i++) + index4[i] = currentIndex[i]; + for(unsigned int ind=0; indGetPixel(index4); + } + it.Set(vec); + } + } + else if(ext == ".nii" || ext == ".nii.gz") + { + // create reader and read file + typedef itk::Image ImageType4D; + itk::NiftiImageIO::Pointer io2 = itk::NiftiImageIO::New(); + typedef itk::ImageFileReader FileReaderType; + FileReaderType::Pointer reader = FileReaderType::New(); + reader->SetFileName( this->GetInputLocation() ); + reader->SetImageIO(io2); + reader->Update(); + ImageType4D::Pointer img4 = reader->GetOutput(); + + // convert 4D file to vector image itkVectorImage = VectorImageType::New(); VectorImageType::SpacingType spacing; ImageType4D::SpacingType spacing4 = img4->GetSpacing(); for(int i=0; i<3; i++) spacing[i] = spacing4[i]; itkVectorImage->SetSpacing( spacing ); // Set the image spacing VectorImageType::PointType origin; ImageType4D::PointType origin4 = img4->GetOrigin(); for(int i=0; i<3; i++) origin[i] = origin4[i]; itkVectorImage->SetOrigin( origin ); // Set the image origin VectorImageType::DirectionType direction; ImageType4D::DirectionType direction4 = img4->GetDirection(); for(int i=0; i<3; i++) for(int j=0; j<3; j++) direction[i][j] = direction4[i][j]; itkVectorImage->SetDirection( direction ); // Set the image direction VectorImageType::RegionType region; ImageType4D::RegionType region4 = img4->GetLargestPossibleRegion(); VectorImageType::RegionType::SizeType size; ImageType4D::RegionType::SizeType size4 = region4.GetSize(); for(int i=0; i<3; i++) size[i] = size4[i]; VectorImageType::RegionType::IndexType index; ImageType4D::RegionType::IndexType index4 = region4.GetIndex(); for(int i=0; i<3; i++) index[i] = index4[i]; region.SetSize(size); region.SetIndex(index); itkVectorImage->SetRegions( region ); itkVectorImage->SetVectorLength(size4[3]); itkVectorImage->Allocate(); itk::ImageRegionIterator it ( itkVectorImage, itkVectorImage->GetLargestPossibleRegion() ); typedef VectorImageType::PixelType VecPixType; for (it.GoToBegin(); !it.IsAtEnd(); ++it) { VecPixType vec = it.Get(); VectorImageType::IndexType currentIndex = it.GetIndex(); for(int i=0; i<3; i++) index4[i] = currentIndex[i]; for(unsigned int ind=0; indGetPixel(index4); } it.Set(vec); } } // Diffusion Image information START GradientDirectionContainerType::Pointer DiffusionVectors = GradientDirectionContainerType::New(); GradientDirectionContainerType::Pointer OriginalDiffusionVectors = GradientDirectionContainerType::New(); MeasurementFrameType MeasurementFrame; float BValue = -1; // Diffusion Image information END - if (ext == ".hdwi" || ext == ".dwi" || ext == ".nrrd") + if(ext == ".fsl" || ext == ".fslgz" || ext == ".nii" || ext == ".nii.gz") { + // some parsing depending on the extension + bool useFSLstyle( true ); + std::string bvecsExtension(""); + std::string bvalsExtension(""); - itk::MetaDataDictionary imgMetaDictionary = itkVectorImage->GetMetaDataDictionary(); - std::vector imgMetaKeys = imgMetaDictionary.GetKeys(); - std::vector::const_iterator itKey = imgMetaKeys.begin(); - std::string metaString; + std::string base = itksys::SystemTools::GetFilenamePath( this->GetInputLocation() ) + "/" + + this->GetMimeType()->GetFilenameWithoutExtension( this->GetInputLocation() ); - GradientDirectionType vect3d; - - int numberOfImages = 0; - int numberOfGradientImages = 0; - bool readb0 = false; - double xx, xy, xz, yx, yy, yz, zx, zy, zz; - - for (; itKey != imgMetaKeys.end(); itKey ++) + // check for possible file names { - double x,y,z; - - itk::ExposeMetaData (imgMetaDictionary, *itKey, metaString); - if (itKey->find("DWMRI_gradient") != std::string::npos) + if( useFSLstyle && itksys::SystemTools::FileExists( std::string( base + ".bvec").c_str() ) + && itksys::SystemTools::FileExists( std::string( base + ".bval").c_str() ) + ) { - sscanf(metaString.c_str(), "%lf %lf %lf\n", &x, &y, &z); - vect3d[0] = x; vect3d[1] = y; vect3d[2] = z; - DiffusionVectors->InsertElement( numberOfImages, vect3d ); - ++numberOfImages; - // If the direction is 0.0, this is a reference image - if (vect3d[0] == 0.0 && - vect3d[1] == 0.0 && - vect3d[2] == 0.0) - { - continue; - } - ++numberOfGradientImages;; - } - else if (itKey->find("DWMRI_b-value") != std::string::npos) - { - readb0 = true; - BValue = atof(metaString.c_str()); + useFSLstyle = false; + bvecsExtension = ".bvec"; + bvalsExtension = ".bval"; } - else if (itKey->find("measurement frame") != std::string::npos) - { - sscanf(metaString.c_str(), " ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) \n", &xx, &xy, &xz, &yx, &yy, &yz, &zx, &zy, &zz); - if (xx>10e-10 || xy>10e-10 || xz>10e-10 || - yx>10e-10 || yy>10e-10 || yz>10e-10 || - zx>10e-10 || zy>10e-10 || zz>10e-10 ) - { - MeasurementFrame(0,0) = xx; - MeasurementFrame(0,1) = xy; - MeasurementFrame(0,2) = xz; - MeasurementFrame(1,0) = yx; - MeasurementFrame(1,1) = yy; - MeasurementFrame(1,2) = yz; - MeasurementFrame(2,0) = zx; - MeasurementFrame(2,1) = zy; - MeasurementFrame(2,2) = zz; - } - else - { - MeasurementFrame(0,0) = 1; - MeasurementFrame(0,1) = 0; - MeasurementFrame(0,2) = 0; - MeasurementFrame(1,0) = 0; - MeasurementFrame(1,1) = 1; - MeasurementFrame(1,2) = 0; - MeasurementFrame(2,0) = 0; - MeasurementFrame(2,1) = 0; - MeasurementFrame(2,2) = 1; - } + if( useFSLstyle && itksys::SystemTools::FileExists( std::string( base + ".bvecs").c_str() ) + && itksys::SystemTools::FileExists( std::string( base + ".bvals").c_str() ) + ) + { + useFSLstyle = false; + bvecsExtension = ".bvecs"; + bvalsExtension = ".bvals"; } } - if(!readb0) - { - MITK_INFO << "BValue not specified in header file"; - } - - } - else if(ext == ".fsl" || ext == ".fslgz") - { - std::string line; std::vector bvec_entries; std::string fname = this->GetInputLocation(); - fname += ".bvecs"; + if( useFSLstyle ) + { + fname += ".bvecs"; + } + else + { + fname = std::string( base + bvecsExtension); + } std::ifstream myfile (fname.c_str()); if (myfile.is_open()) { while ( myfile.good() ) { getline (myfile,line); char* pch = strtok (const_cast(line.c_str())," "); while (pch != NULL) { bvec_entries.push_back(atof(pch)); pch = strtok (NULL, " "); } } myfile.close(); } else { MITK_INFO << "Unable to open bvecs file"; } std::vector bval_entries; std::string fname2 = this->GetInputLocation(); - fname2 += ".bvals"; + if( useFSLstyle ) + { + fname2 += ".bvals"; + } + else + { + fname2 = std::string( base + bvalsExtension); + } std::ifstream myfile2 (fname2.c_str()); if (myfile2.is_open()) { while ( myfile2.good() ) { getline (myfile2,line); char* pch = strtok (const_cast(line.c_str())," "); while (pch != NULL) { bval_entries.push_back(atof(pch)); pch = strtok (NULL, " "); } } myfile2.close(); } else { MITK_INFO << "Unable to open bvals file"; } BValue = -1; unsigned int numb = bval_entries.size(); for(unsigned int i=0; i vec; vec[0] = bvec_entries.at(i); vec[1] = bvec_entries.at(i+numb); vec[2] = bvec_entries.at(i+2*numb); // Adjust the vector length to encode gradient strength float factor = b_val/BValue; if(vec.magnitude() > 0) { vec[0] = sqrt(factor)*vec[0]; vec[1] = sqrt(factor)*vec[1]; vec[2] = sqrt(factor)*vec[2]; } DiffusionVectors->InsertElement(i,vec); } for(int i=0; i<3; i++) for(int j=0; j<3; j++) MeasurementFrame[i][j] = i==j ? 1 : 0; } outputForCache = mitk::GrabItkImageMemory( itkVectorImage); // create BValueMap mitk::BValueMapProperty::BValueMap BValueMap = mitk::BValueMapProperty::CreateBValueMap(DiffusionVectors,BValue); outputForCache->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( DiffusionVectors ) ); outputForCache->SetProperty( mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( OriginalDiffusionVectors ) ); outputForCache->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( MeasurementFrame ) ); outputForCache->SetProperty( mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str(), mitk::BValueMapProperty::New( BValueMap ) ); outputForCache->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( BValue ) ); // Since we have already read the tree, we can store it in a cache variable // so that it can be assigned to the DataObject in GenerateData(); m_OutputCache = outputForCache; m_CacheTime.Modified(); try { setlocale(LC_ALL, currLocale.c_str()); } catch(...) { MITK_INFO << "Could not reset locale " << currLocale; } } catch(std::exception& e) { MITK_INFO << "Std::Exception while reading file!!"; MITK_INFO << e.what(); throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what()); } catch(...) { MITK_INFO << "Exception while reading file!!"; throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested vessel tree file!"); } } } } //namespace MITK #endif diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageReader.h b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNiftiReaderService.h similarity index 78% copy from Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageReader.h copy to Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNiftiReaderService.h index ac1fb1d29c..864dc67ee2 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageReader.h +++ b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNiftiReaderService.h @@ -1,73 +1,73 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef __mitkNrrdDiffusionImageReader_h -#define __mitkNrrdDiffusionImageReader_h +#ifndef __mitkDiffusionImageNiftiReaderService_h +#define __mitkDiffusionImageNiftiReaderService_h #include "mitkCommon.h" // MITK includes #include "mitkImageSource.h" #include "mitkFileReader.h" #include // ITK includes #include "itkVectorImage.h" #include "mitkAbstractFileReader.h" namespace mitk { /** \brief */ - class NrrdDiffusionImageReader : public mitk::AbstractFileReader + class DiffusionImageNiftiReaderService : public mitk::AbstractFileReader { public: - NrrdDiffusionImageReader(const NrrdDiffusionImageReader & other); - NrrdDiffusionImageReader(); - virtual ~NrrdDiffusionImageReader(); + DiffusionImageNiftiReaderService(const DiffusionImageNiftiReaderService & other); + DiffusionImageNiftiReaderService(); + virtual ~DiffusionImageNiftiReaderService(); using AbstractFileReader::Read; virtual std::vector > Read(); typedef short DiffusionPixelType; typedef mitk::Image OutputType; typedef mitk::DiffusionPropertyHelper::ImageType VectorImageType; typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType; typedef mitk::DiffusionPropertyHelper::MeasurementFrameType MeasurementFrameType; typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType; protected: OutputType::Pointer m_OutputCache; itk::TimeStamp m_CacheTime; void InternalRead(); private: - NrrdDiffusionImageReader* Clone() const; + DiffusionImageNiftiReaderService* Clone() const; us::ServiceRegistration m_ServiceReg; }; } //namespace MITK -#endif // __mitkNrrdDiffusionImageReader_h +#endif // __mitkDiffusionImageNiftiReaderService_h diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageWriter.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNiftiWriterService.cpp similarity index 60% rename from Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageWriter.cpp rename to Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNiftiWriterService.cpp index 179126a472..abda78b674 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageWriter.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNiftiWriterService.cpp @@ -1,332 +1,443 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef __mitkNrrdDiffusionImageWriter__cpp -#define __mitkNrrdDiffusionImageWriter__cpp +#ifndef __mitkDiffusionImageNiftiWriterService__cpp +#define __mitkDiffusionImageNiftiWriterService__cpp -#include "mitkNrrdDiffusionImageWriter.h" +#include "mitkDiffusionImageNiftiWriterService.h" #include "itkMetaDataDictionary.h" #include "itkMetaDataObject.h" -#include "itkNrrdImageIO.h" #include "itkNiftiImageIO.h" #include "itkImageFileWriter.h" #include "itksys/SystemTools.hxx" #include "mitkDiffusionIOMimeTypes.h" #include "mitkImageCast.h" #include #include -mitk::NrrdDiffusionImageWriter::NrrdDiffusionImageWriter() - : AbstractFileWriter(mitk::Image::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::DWI_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DWI_MIMETYPE_DESCRIPTION()) +mitk::DiffusionImageNiftiWriterService::DiffusionImageNiftiWriterService() + : AbstractFileWriter(mitk::Image::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::DWI_NIFTI_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DWI_NIFTI_MIMETYPE_DESCRIPTION()) { RegisterService(); } -mitk::NrrdDiffusionImageWriter::NrrdDiffusionImageWriter(const mitk::NrrdDiffusionImageWriter& other) +mitk::DiffusionImageNiftiWriterService::DiffusionImageNiftiWriterService(const mitk::DiffusionImageNiftiWriterService& other) : AbstractFileWriter(other) { } -mitk::NrrdDiffusionImageWriter::~NrrdDiffusionImageWriter() +mitk::DiffusionImageNiftiWriterService::~DiffusionImageNiftiWriterService() {} -void mitk::NrrdDiffusionImageWriter::Write() +void mitk::DiffusionImageNiftiWriterService::Write() { mitk::Image::ConstPointer input = dynamic_cast(this->GetInput()); VectorImageType::Pointer itkImg; mitk::CastToItkImage(input,itkImg); if (input.IsNull()) { - MITK_ERROR <<"Sorry, input to NrrdDiffusionImageWriter is NULL!"; + MITK_ERROR <<"Sorry, input to DiffusionImageNiftiWriterService is NULL!"; return; } if ( this->GetOutputLocation().empty() ) { MITK_ERROR << "Sorry, filename has not been set!"; return ; } 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; } } char keybuffer[512]; char valbuffer[512]; //itk::MetaDataDictionary dic = input->GetImage()->GetMetaDataDictionary(); vnl_matrix_fixed measurementFrame = mitk::DiffusionPropertyHelper::GetMeasurementFrame(input); if (measurementFrame(0,0) || measurementFrame(0,1) || measurementFrame(0,2) || measurementFrame(1,0) || measurementFrame(1,1) || measurementFrame(1,2) || measurementFrame(2,0) || measurementFrame(2,1) || measurementFrame(2,2)) { sprintf( valbuffer, " (%lf,%lf,%lf) (%lf,%lf,%lf) (%lf,%lf,%lf)", measurementFrame(0,0), measurementFrame(0,1), measurementFrame(0,2), measurementFrame(1,0), measurementFrame(1,1), measurementFrame(1,2), measurementFrame(2,0), measurementFrame(2,1), measurementFrame(2,2)); itk::EncapsulateMetaData(itkImg->GetMetaDataDictionary(),std::string("measurement frame"),std::string(valbuffer)); } sprintf( valbuffer, "DWMRI"); itk::EncapsulateMetaData(itkImg->GetMetaDataDictionary(),std::string("modality"),std::string(valbuffer)); if(mitk::DiffusionPropertyHelper::GetGradientContainer(input)->Size()) { sprintf( valbuffer, "%1f", mitk::DiffusionPropertyHelper::GetReferenceBValue(input) ); itk::EncapsulateMetaData(itkImg->GetMetaDataDictionary(),std::string("DWMRI_b-value"),std::string(valbuffer)); } for(unsigned int i=0; iSize(); i++) { sprintf( keybuffer, "DWMRI_gradient_%04d", i ); /*if(itk::ExposeMetaData(input->GetMetaDataDictionary(), std::string(keybuffer),tmp)) continue;*/ sprintf( valbuffer, "%1f %1f %1f", mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(0), mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(1), mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(2)); itk::EncapsulateMetaData(itkImg->GetMetaDataDictionary(),std::string(keybuffer),std::string(valbuffer)); } typedef itk::VectorImage ImageType; - std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->GetOutputLocation()); + std::string ext = this->GetMimeType()->GetExtension(this->GetOutputLocation()); ext = itksys::SystemTools::LowerCase(ext); - // default extension is .dwi + // default extension is .nii if( ext == "") { - ext = ".nrrd"; + ext = ".nii"; this->SetOutputLocation(this->GetOutputLocation() + ext); } - - if (ext == ".hdwi" || ext == ".nrrd" || ext == ".dwi") - { - - MITK_INFO << "Extension " << ext; - itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); - //io->SetNrrdVectorType( nrrdKindList ); - io->SetFileType( itk::ImageIOBase::Binary ); - io->UseCompressionOn(); - - typedef itk::ImageFileWriter WriterType; - WriterType::Pointer nrrdWriter = WriterType::New(); - nrrdWriter->UseInputMetaDataDictionaryOn(); - nrrdWriter->SetInput( itkImg ); - nrrdWriter->SetImageIO(io); - nrrdWriter->SetFileName(this->GetOutputLocation()); - nrrdWriter->UseCompressionOn(); - nrrdWriter->SetImageIO(io); - try - { - nrrdWriter->Update(); - } - catch (itk::ExceptionObject e) - { - std::cout << e << std::endl; - throw; - } - - } - else if (ext == ".fsl" || ext == ".fslgz") + if (ext == ".fsl" || ext == ".fslgz") { MITK_INFO << "Writing Nifti-Image for FSL"; typedef itk::Image ImageType4D; ImageType4D::Pointer img4 = ImageType4D::New(); ImageType::SpacingType spacing = itkImg->GetSpacing(); ImageType4D::SpacingType spacing4; for(int i=0; i<3; i++) spacing4[i] = spacing[i]; spacing4[3] = 1; img4->SetSpacing( spacing4 ); // Set the image spacing ImageType::PointType origin = itkImg->GetOrigin(); ImageType4D::PointType origin4; for(int i=0; i<3; i++) origin4[i] = origin[i]; origin4[3] = 0; img4->SetOrigin( origin4 ); // Set the image origin ImageType::DirectionType direction = itkImg->GetDirection(); ImageType4D::DirectionType direction4; for(int i=0; i<3; i++) for(int j=0; j<3; j++) direction4[i][j] = direction[i][j]; for(int i=0; i<4; i++) direction4[i][3] = 0; for(int i=0; i<4; i++) direction4[3][i] = 0; direction4[3][3] = 1; img4->SetDirection( direction4 ); // Set the image direction ImageType::RegionType region = itkImg->GetLargestPossibleRegion(); ImageType4D::RegionType region4; ImageType::RegionType::SizeType size = region.GetSize(); ImageType4D::RegionType::SizeType size4; for(int i=0; i<3; i++) size4[i] = size[i]; size4[3] = itkImg->GetVectorLength(); ImageType::RegionType::IndexType index = region.GetIndex(); ImageType4D::RegionType::IndexType index4; for(int i=0; i<3; i++) index4[i] = index[i]; index4[3] = 0; region4.SetSize(size4); region4.SetIndex(index4); img4->SetRegions( region4 ); img4->Allocate(); itk::ImageRegionIterator it (itkImg, itkImg->GetLargestPossibleRegion() ); typedef ImageType::PixelType VecPixType; for (it.GoToBegin(); !it.IsAtEnd(); ++it) { VecPixType vec = it.Get(); ImageType::IndexType currentIndex = it.GetIndex(); for(unsigned int ind=0; indSetPixel(index4, vec[ind]); } } // create copy of file with correct ending for mitk std::string fname3 = this->GetOutputLocation(); std::string::iterator itend = fname3.end(); if (ext == ".fsl") fname3.replace( itend-3, itend, "nii"); else fname3.replace( itend-5, itend, "nii.gz"); itk::NiftiImageIO::Pointer io4 = itk::NiftiImageIO::New(); typedef itk::VectorImage ImageType; typedef itk::ImageFileWriter WriterType4; WriterType4::Pointer nrrdWriter4 = WriterType4::New(); nrrdWriter4->UseInputMetaDataDictionaryOn(); nrrdWriter4->SetInput( img4 ); nrrdWriter4->SetFileName(fname3); nrrdWriter4->UseCompressionOn(); nrrdWriter4->SetImageIO(io4); try { nrrdWriter4->Update(); } catch (itk::ExceptionObject e) { std::cout << e << std::endl; throw; } itksys::SystemTools::CopyAFile(fname3.c_str(), this->GetOutputLocation().c_str()); if(mitk::DiffusionPropertyHelper::GetGradientContainer(input)->Size()) { std::ofstream myfile; std::string fname = this->GetOutputLocation(); fname += ".bvals"; myfile.open (fname.c_str()); for(unsigned int i=0; iSize(); i++) { double twonorm = mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).two_norm(); myfile << mitk::DiffusionPropertyHelper::GetReferenceBValue(input)*twonorm*twonorm << " "; } myfile.close(); std::ofstream myfile2; std::string fname2 = this->GetOutputLocation(); fname2 += ".bvecs"; myfile2.open (fname2.c_str()); for(int j=0; j<3; j++) { for(unsigned int i=0; iSize(); i++) { //need to modify the length GradientDirectionContainerType::Pointer grads = mitk::DiffusionPropertyHelper::GetGradientContainer(input); GradientDirectionType direction = grads->ElementAt(i); direction.normalize(); myfile2 << direction.get(j) << " "; //myfile2 << input->GetDirections()->ElementAt(i).get(j) << " "; } myfile2 << std::endl; } std::ofstream myfile3; std::string fname4 = this->GetOutputLocation(); fname4 += ".ttk"; myfile3.open (fname4.c_str()); for(unsigned int i=0; iSize(); i++) { for(int j=0; j<3; j++) { myfile3 << mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(j) << " "; } myfile3 << std::endl; } } } + else if (ext == ".nii" || ext == ".nii.gz") + { + MITK_INFO << "Writing Nifti-Image"; + + typedef itk::Image ImageType4D; + ImageType4D::Pointer img4 = ImageType4D::New(); + + ImageType::SpacingType spacing = itkImg->GetSpacing(); + ImageType4D::SpacingType spacing4; + for(int i=0; i<3; i++) + spacing4[i] = spacing[i]; + spacing4[3] = 1; + img4->SetSpacing( spacing4 ); // Set the image spacing + + ImageType::PointType origin = itkImg->GetOrigin(); + ImageType4D::PointType origin4; + for(int i=0; i<3; i++) + origin4[i] = origin[i]; + origin4[3] = 0; + img4->SetOrigin( origin4 ); // Set the image origin + + ImageType::DirectionType direction = itkImg->GetDirection(); + ImageType4D::DirectionType direction4; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + direction4[i][j] = direction[i][j]; + for(int i=0; i<4; i++) + direction4[i][3] = 0; + for(int i=0; i<4; i++) + direction4[3][i] = 0; + direction4[3][3] = 1; + img4->SetDirection( direction4 ); // Set the image direction + + ImageType::RegionType region = itkImg->GetLargestPossibleRegion(); + ImageType4D::RegionType region4; + + ImageType::RegionType::SizeType size = region.GetSize(); + ImageType4D::RegionType::SizeType size4; + + for(int i=0; i<3; i++) + size4[i] = size[i]; + size4[3] = itkImg->GetVectorLength(); + + ImageType::RegionType::IndexType index = region.GetIndex(); + ImageType4D::RegionType::IndexType index4; + for(int i=0; i<3; i++) + index4[i] = index[i]; + index4[3] = 0; + + region4.SetSize(size4); + region4.SetIndex(index4); + img4->SetRegions( region4 ); + + img4->Allocate(); + + itk::ImageRegionIterator it (itkImg, itkImg->GetLargestPossibleRegion() ); + typedef ImageType::PixelType VecPixType; + + for (it.GoToBegin(); !it.IsAtEnd(); ++it) + { + VecPixType vec = it.Get(); + ImageType::IndexType currentIndex = it.GetIndex(); + for(unsigned int ind=0; indSetPixel(index4, vec[ind]); + } + } + + itk::NiftiImageIO::Pointer io4 = itk::NiftiImageIO::New(); + + typedef itk::VectorImage ImageType; + typedef itk::ImageFileWriter WriterType4; + WriterType4::Pointer nrrdWriter4 = WriterType4::New(); + nrrdWriter4->UseInputMetaDataDictionaryOn(); + nrrdWriter4->SetInput( img4 ); + nrrdWriter4->SetFileName(this->GetOutputLocation()); + nrrdWriter4->UseCompressionOn(); + nrrdWriter4->SetImageIO(io4); + try + { + nrrdWriter4->Update(); + } + catch (itk::ExceptionObject e) + { + std::cout << e << std::endl; + throw; + } + + + if(mitk::DiffusionPropertyHelper::GetGradientContainer(input)->Size()) + { + std::ofstream myfile; + std::string fname = itksys::SystemTools::GetFilenamePath( this->GetOutputLocation() ) + "/" + + this->GetMimeType()->GetFilenameWithoutExtension( this->GetOutputLocation() ); + fname += ".bvals"; + myfile.open (fname.c_str()); + for(unsigned int i=0; iSize(); i++) + { + double twonorm = mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).two_norm(); + myfile << mitk::DiffusionPropertyHelper::GetReferenceBValue(input)*twonorm*twonorm << " "; + } + myfile.close(); + + std::ofstream myfile2; + std::string fname2 = itksys::SystemTools::GetFilenamePath( this->GetOutputLocation() ) + "/" + + this->GetMimeType()->GetFilenameWithoutExtension( this->GetOutputLocation() ); + fname2 += ".bvecs"; + myfile2.open (fname2.c_str()); + for(int j=0; j<3; j++) + { + for(unsigned int i=0; iSize(); i++) + { + //need to modify the length + GradientDirectionContainerType::Pointer grads = mitk::DiffusionPropertyHelper::GetGradientContainer(input); + GradientDirectionType direction = grads->ElementAt(i); + direction.normalize(); + myfile2 << direction.get(j) << " "; + //myfile2 << input->GetDirections()->ElementAt(i).get(j) << " "; + } + myfile2 << std::endl; + } + + std::ofstream myfile3; + std::string fname4 = itksys::SystemTools::GetFilenamePath( this->GetOutputLocation() ) + "/" + + this->GetMimeType()->GetFilenameWithoutExtension( this->GetOutputLocation() ); + fname4 += ".ttk"; + myfile3.open (fname4.c_str()); + for(unsigned int i=0; iSize(); i++) + { + for(int j=0; j<3; j++) + { + myfile3 << mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(j) << " "; + } + myfile3 << std::endl; + } + } + } try { setlocale(LC_ALL, currLocale.c_str()); } catch(...) { MITK_INFO << "Could not reset locale " << currLocale; } } -mitk::NrrdDiffusionImageWriter* mitk::NrrdDiffusionImageWriter::Clone() const +mitk::DiffusionImageNiftiWriterService* mitk::DiffusionImageNiftiWriterService::Clone() const { - return new NrrdDiffusionImageWriter(*this); + return new DiffusionImageNiftiWriterService(*this); } -mitk::IFileWriter::ConfidenceLevel mitk::NrrdDiffusionImageWriter::GetConfidenceLevel() const +mitk::IFileWriter::ConfidenceLevel mitk::DiffusionImageNiftiWriterService::GetConfidenceLevel() const { mitk::Image::ConstPointer input = dynamic_cast(this->GetInput()); if (input.IsNull() || !mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( input ) ) { return Unsupported; } else { return Supported; } } -#endif //__mitkNrrdDiffusionImageWriter__cpp +#endif //__mitkDiffusionImageNiftiWriterService__cpp diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageWriter.h b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNiftiWriterService.h similarity index 75% copy from Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageWriter.h copy to Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNiftiWriterService.h index 1bedf714ce..a57e4f3854 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageWriter.h +++ b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNiftiWriterService.h @@ -1,58 +1,58 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef _MITK_NRRDDIFFVOL_WRITER__H_ -#define _MITK_NRRDDIFFVOL_WRITER__H_ +#ifndef _MITK_DiffusionImageNiftiWriterService__H_ +#define _MITK_DiffusionImageNiftiWriterService__H_ #include #include namespace mitk { /** * Writes diffusion volumes to a file * @ingroup Process */ -class NrrdDiffusionImageWriter : public mitk::AbstractFileWriter +class DiffusionImageNiftiWriterService : public mitk::AbstractFileWriter { public: - NrrdDiffusionImageWriter(); - virtual ~NrrdDiffusionImageWriter(); + DiffusionImageNiftiWriterService(); + virtual ~DiffusionImageNiftiWriterService(); using AbstractFileWriter::Write; virtual void Write(); virtual ConfidenceLevel GetConfidenceLevel() const; typedef mitk::DiffusionPropertyHelper::ImageType VectorImageType; typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType; typedef mitk::DiffusionPropertyHelper::MeasurementFrameType MeasurementFrameType; typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType; protected: - NrrdDiffusionImageWriter(const NrrdDiffusionImageWriter& other); - virtual mitk::NrrdDiffusionImageWriter* Clone() const; + DiffusionImageNiftiWriterService(const DiffusionImageNiftiWriterService& other); + virtual mitk::DiffusionImageNiftiWriterService* Clone() const; }; } // end of namespace mitk #endif diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageReader.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNrrdReaderService.cpp similarity index 55% rename from Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageReader.cpp rename to Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNrrdReaderService.cpp index a2b29fd956..f20e032301 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageReader.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNrrdReaderService.cpp @@ -1,434 +1,268 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef __mitkNrrdDiffusionImageReader_cpp -#define __mitkNrrdDiffusionImageReader_cpp +#ifndef __mitkDiffusionImageNrrdReaderService_cpp +#define __mitkDiffusionImageNrrdReaderService_cpp -#include "mitkNrrdDiffusionImageReader.h" +#include "mitkDiffusionImageNrrdReaderService.h" #include #include // Diffusion properties #include #include #include #include // ITK includes #include #include #include "itksys/SystemTools.hxx" #include "itkImageFileReader.h" #include "itkMetaDataObject.h" #include "itkNrrdImageIO.h" -#include "itkNiftiImageIO.h" #include "mitkCustomMimeType.h" #include "mitkDiffusionIOMimeTypes.h" #include -#include #include #include #include "mitkIOUtil.h" namespace mitk { - NrrdDiffusionImageReader:: - NrrdDiffusionImageReader(const NrrdDiffusionImageReader & other) + DiffusionImageNrrdReaderService:: + DiffusionImageNrrdReaderService(const DiffusionImageNrrdReaderService & other) : AbstractFileReader(other) { } - NrrdDiffusionImageReader* NrrdDiffusionImageReader::Clone() const + DiffusionImageNrrdReaderService* DiffusionImageNrrdReaderService::Clone() const { - return new NrrdDiffusionImageReader(*this); + return new DiffusionImageNrrdReaderService(*this); } - NrrdDiffusionImageReader:: - ~NrrdDiffusionImageReader() + DiffusionImageNrrdReaderService:: + ~DiffusionImageNrrdReaderService() {} - NrrdDiffusionImageReader:: - NrrdDiffusionImageReader() - : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::DWI_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DWI_MIMETYPE_DESCRIPTION() ) + DiffusionImageNrrdReaderService:: + DiffusionImageNrrdReaderService() + : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::DWI_NRRD_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DWI_NRRD_MIMETYPE_DESCRIPTION() ) { m_ServiceReg = this->RegisterService(); } std::vector > - NrrdDiffusionImageReader:: + DiffusionImageNrrdReaderService:: Read() { std::vector > result; // Since everything is completely read in GenerateOutputInformation() it is stored // in a cache variable. A timestamp is associated. // If the timestamp of the cache variable is newer than the MTime, we only need to // assign the cache variable to the DataObject. // Otherwise, the tree must be read again from the file and OuputInformation must // be updated! if(m_OutputCache.IsNull()) InternalRead(); result.push_back(m_OutputCache.GetPointer()); return result; } - void NrrdDiffusionImageReader::InternalRead() + void DiffusionImageNrrdReaderService::InternalRead() { OutputType::Pointer outputForCache = OutputType::New(); if ( this->GetInputLocation() == "") { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, the filename to be read is empty!"); } else { try { 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; } } - MITK_INFO << "NrrdDiffusionImageReader: reading image information"; + MITK_INFO << "DiffusionImageNrrdReaderService: reading image information"; VectorImageType::Pointer itkVectorImage; - std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->GetInputLocation()); - ext = itksys::SystemTools::LowerCase(ext); + std::string ext = this->GetMimeType()->GetExtension( this->GetInputLocation() ); + ext = itksys::SystemTools::LowerCase( ext ); + if (ext == ".hdwi" || ext == ".dwi" || ext == ".nrrd") { typedef itk::ImageFileReader FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetFileName(this->GetInputLocation()); itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); reader->SetImageIO(io); reader->Update(); itkVectorImage = reader->GetOutput(); } - else if(ext == ".fsl" || ext == ".fslgz") - { - // create temporary file with correct ending for nifti-io - std::string fname3 = "temp_dwi"; - fname3 += ext == ".fsl" ? ".nii" : ".nii.gz"; - itksys::SystemTools::CopyAFile(this->GetInputLocation().c_str(), fname3.c_str()); - - // create reader and read file - typedef itk::Image ImageType4D; - itk::NiftiImageIO::Pointer io2 = itk::NiftiImageIO::New(); - typedef itk::ImageFileReader FileReaderType; - FileReaderType::Pointer reader = FileReaderType::New(); - reader->SetFileName(fname3); - reader->SetImageIO(io2); - reader->Update(); - ImageType4D::Pointer img4 = reader->GetOutput(); - - // delete temporary file - itksys::SystemTools::RemoveFile(fname3.c_str()); - - // convert 4D file to vector image - itkVectorImage = VectorImageType::New(); - - VectorImageType::SpacingType spacing; - ImageType4D::SpacingType spacing4 = img4->GetSpacing(); - for(int i=0; i<3; i++) - spacing[i] = spacing4[i]; - itkVectorImage->SetSpacing( spacing ); // Set the image spacing - - VectorImageType::PointType origin; - ImageType4D::PointType origin4 = img4->GetOrigin(); - for(int i=0; i<3; i++) - origin[i] = origin4[i]; - itkVectorImage->SetOrigin( origin ); // Set the image origin - - VectorImageType::DirectionType direction; - ImageType4D::DirectionType direction4 = img4->GetDirection(); - for(int i=0; i<3; i++) - for(int j=0; j<3; j++) - direction[i][j] = direction4[i][j]; - itkVectorImage->SetDirection( direction ); // Set the image direction - - VectorImageType::RegionType region; - ImageType4D::RegionType region4 = img4->GetLargestPossibleRegion(); - - VectorImageType::RegionType::SizeType size; - ImageType4D::RegionType::SizeType size4 = region4.GetSize(); - - for(int i=0; i<3; i++) - size[i] = size4[i]; - - VectorImageType::RegionType::IndexType index; - ImageType4D::RegionType::IndexType index4 = region4.GetIndex(); - for(int i=0; i<3; i++) - index[i] = index4[i]; - - region.SetSize(size); - region.SetIndex(index); - itkVectorImage->SetRegions( region ); - - itkVectorImage->SetVectorLength(size4[3]); - itkVectorImage->Allocate(); - - itk::ImageRegionIterator it ( itkVectorImage, itkVectorImage->GetLargestPossibleRegion() ); - typedef VectorImageType::PixelType VecPixType; - for (it.GoToBegin(); !it.IsAtEnd(); ++it) - { - VecPixType vec = it.Get(); - VectorImageType::IndexType currentIndex = it.GetIndex(); - for(int i=0; i<3; i++) - index4[i] = currentIndex[i]; - for(unsigned int ind=0; indGetPixel(index4); - } - it.Set(vec); - } - } // Diffusion Image information START GradientDirectionContainerType::Pointer DiffusionVectors = GradientDirectionContainerType::New(); GradientDirectionContainerType::Pointer OriginalDiffusionVectors = GradientDirectionContainerType::New(); MeasurementFrameType MeasurementFrame; float BValue = -1; // Diffusion Image information END if (ext == ".hdwi" || ext == ".dwi" || ext == ".nrrd") { itk::MetaDataDictionary imgMetaDictionary = itkVectorImage->GetMetaDataDictionary(); std::vector imgMetaKeys = imgMetaDictionary.GetKeys(); std::vector::const_iterator itKey = imgMetaKeys.begin(); std::string metaString; GradientDirectionType vect3d; int numberOfImages = 0; int numberOfGradientImages = 0; bool readb0 = false; double xx, xy, xz, yx, yy, yz, zx, zy, zz; for (; itKey != imgMetaKeys.end(); itKey ++) { double x,y,z; itk::ExposeMetaData (imgMetaDictionary, *itKey, metaString); if (itKey->find("DWMRI_gradient") != std::string::npos) { sscanf(metaString.c_str(), "%lf %lf %lf\n", &x, &y, &z); vect3d[0] = x; vect3d[1] = y; vect3d[2] = z; DiffusionVectors->InsertElement( numberOfImages, vect3d ); ++numberOfImages; // If the direction is 0.0, this is a reference image if (vect3d[0] == 0.0 && vect3d[1] == 0.0 && vect3d[2] == 0.0) { continue; } ++numberOfGradientImages;; } else if (itKey->find("DWMRI_b-value") != std::string::npos) { readb0 = true; BValue = atof(metaString.c_str()); } else if (itKey->find("measurement frame") != std::string::npos) { sscanf(metaString.c_str(), " ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) \n", &xx, &xy, &xz, &yx, &yy, &yz, &zx, &zy, &zz); if (xx>10e-10 || xy>10e-10 || xz>10e-10 || yx>10e-10 || yy>10e-10 || yz>10e-10 || zx>10e-10 || zy>10e-10 || zz>10e-10 ) { MeasurementFrame(0,0) = xx; MeasurementFrame(0,1) = xy; MeasurementFrame(0,2) = xz; MeasurementFrame(1,0) = yx; MeasurementFrame(1,1) = yy; MeasurementFrame(1,2) = yz; MeasurementFrame(2,0) = zx; MeasurementFrame(2,1) = zy; MeasurementFrame(2,2) = zz; } else { MeasurementFrame(0,0) = 1; MeasurementFrame(0,1) = 0; MeasurementFrame(0,2) = 0; MeasurementFrame(1,0) = 0; MeasurementFrame(1,1) = 1; MeasurementFrame(1,2) = 0; MeasurementFrame(2,0) = 0; MeasurementFrame(2,1) = 0; MeasurementFrame(2,2) = 1; } } } if(!readb0) { MITK_INFO << "BValue not specified in header file"; } } - else if(ext == ".fsl" || ext == ".fslgz") - { - - std::string line; - std::vector bvec_entries; - std::string fname = this->GetInputLocation(); - fname += ".bvecs"; - std::ifstream myfile (fname.c_str()); - if (myfile.is_open()) - { - while ( myfile.good() ) - { - getline (myfile,line); - char* pch = strtok (const_cast(line.c_str())," "); - while (pch != NULL) - { - bvec_entries.push_back(atof(pch)); - pch = strtok (NULL, " "); - } - } - myfile.close(); - } - else - { - MITK_INFO << "Unable to open bvecs file"; - } - - std::vector bval_entries; - std::string fname2 = this->GetInputLocation(); - fname2 += ".bvals"; - std::ifstream myfile2 (fname2.c_str()); - if (myfile2.is_open()) - { - while ( myfile2.good() ) - { - getline (myfile2,line); - char* pch = strtok (const_cast(line.c_str())," "); - while (pch != NULL) - { - bval_entries.push_back(atof(pch)); - pch = strtok (NULL, " "); - } - } - myfile2.close(); - } - else - { - MITK_INFO << "Unable to open bvals file"; - } - - - BValue = -1; - unsigned int numb = bval_entries.size(); - for(unsigned int i=0; i vec; - vec[0] = bvec_entries.at(i); - vec[1] = bvec_entries.at(i+numb); - vec[2] = bvec_entries.at(i+2*numb); - - // Adjust the vector length to encode gradient strength - float factor = b_val/BValue; - if(vec.magnitude() > 0) - { - vec[0] = sqrt(factor)*vec[0]; - vec[1] = sqrt(factor)*vec[1]; - vec[2] = sqrt(factor)*vec[2]; - } - - DiffusionVectors->InsertElement(i,vec); - } - - for(int i=0; i<3; i++) - for(int j=0; j<3; j++) - MeasurementFrame[i][j] = i==j ? 1 : 0; - } outputForCache = mitk::GrabItkImageMemory( itkVectorImage); // create BValueMap mitk::BValueMapProperty::BValueMap BValueMap = mitk::BValueMapProperty::CreateBValueMap(DiffusionVectors,BValue); outputForCache->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( DiffusionVectors ) ); outputForCache->SetProperty( mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( OriginalDiffusionVectors ) ); outputForCache->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( MeasurementFrame ) ); outputForCache->SetProperty( mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str(), mitk::BValueMapProperty::New( BValueMap ) ); outputForCache->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( BValue ) ); // Since we have already read the tree, we can store it in a cache variable // so that it can be assigned to the DataObject in GenerateData(); m_OutputCache = outputForCache; m_CacheTime.Modified(); try { setlocale(LC_ALL, currLocale.c_str()); } catch(...) { MITK_INFO << "Could not reset locale " << currLocale; } } catch(std::exception& e) { MITK_INFO << "Std::Exception while reading file!!"; MITK_INFO << e.what(); throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what()); } catch(...) { MITK_INFO << "Exception while reading file!!"; throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested vessel tree file!"); } } } } //namespace MITK #endif diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageReader.h b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNrrdReaderService.h similarity index 79% rename from Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageReader.h rename to Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNrrdReaderService.h index ac1fb1d29c..357b1b038a 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageReader.h +++ b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNrrdReaderService.h @@ -1,73 +1,73 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef __mitkNrrdDiffusionImageReader_h -#define __mitkNrrdDiffusionImageReader_h +#ifndef __mitkDiffusionImageNrrdReaderService_h +#define __mitkDiffusionImageNrrdReaderService_h #include "mitkCommon.h" // MITK includes #include "mitkImageSource.h" #include "mitkFileReader.h" #include // ITK includes #include "itkVectorImage.h" #include "mitkAbstractFileReader.h" namespace mitk { /** \brief */ - class NrrdDiffusionImageReader : public mitk::AbstractFileReader + class DiffusionImageNrrdReaderService : public mitk::AbstractFileReader { public: - NrrdDiffusionImageReader(const NrrdDiffusionImageReader & other); - NrrdDiffusionImageReader(); - virtual ~NrrdDiffusionImageReader(); + DiffusionImageNrrdReaderService(const DiffusionImageNrrdReaderService & other); + DiffusionImageNrrdReaderService(); + virtual ~DiffusionImageNrrdReaderService(); using AbstractFileReader::Read; virtual std::vector > Read(); typedef short DiffusionPixelType; typedef mitk::Image OutputType; typedef mitk::DiffusionPropertyHelper::ImageType VectorImageType; typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType; typedef mitk::DiffusionPropertyHelper::MeasurementFrameType MeasurementFrameType; typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType; protected: OutputType::Pointer m_OutputCache; itk::TimeStamp m_CacheTime; void InternalRead(); private: - NrrdDiffusionImageReader* Clone() const; + DiffusionImageNrrdReaderService* Clone() const; us::ServiceRegistration m_ServiceReg; }; } //namespace MITK -#endif // __mitkNrrdDiffusionImageReader_h +#endif // __mitkDiffusionImageNrrdReaderService_h diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNrrdWriterService.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNrrdWriterService.cpp new file mode 100644 index 0000000000..556ade866b --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNrrdWriterService.cpp @@ -0,0 +1,185 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __mitkDiffusionImageNrrdWriterService__cpp +#define __mitkDiffusionImageNrrdWriterService__cpp + +#include "mitkDiffusionImageNrrdWriterService.h" +#include "itkMetaDataDictionary.h" +#include "itkMetaDataObject.h" +#include "itkNrrdImageIO.h" +#include "itkImageFileWriter.h" +#include "itksys/SystemTools.hxx" +#include "mitkDiffusionIOMimeTypes.h" +#include "mitkImageCast.h" + +#include +#include + + +mitk::DiffusionImageNrrdWriterService::DiffusionImageNrrdWriterService() + : AbstractFileWriter(mitk::Image::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::DWI_NRRD_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DWI_NRRD_MIMETYPE_DESCRIPTION()) +{ + RegisterService(); +} + +mitk::DiffusionImageNrrdWriterService::DiffusionImageNrrdWriterService(const mitk::DiffusionImageNrrdWriterService& other) + : AbstractFileWriter(other) +{ +} + +mitk::DiffusionImageNrrdWriterService::~DiffusionImageNrrdWriterService() +{} + +void mitk::DiffusionImageNrrdWriterService::Write() +{ + mitk::Image::ConstPointer input = dynamic_cast(this->GetInput()); + + VectorImageType::Pointer itkImg; + mitk::CastToItkImage(input,itkImg); + + if (input.IsNull()) + { + MITK_ERROR <<"Sorry, input to DiffusionImageNrrdWriterService is NULL!"; + return; + } + if ( this->GetOutputLocation().empty() ) + { + MITK_ERROR << "Sorry, filename has not been set!"; + return ; + } + 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; + } + } + + char keybuffer[512]; + char valbuffer[512]; + + //itk::MetaDataDictionary dic = input->GetImage()->GetMetaDataDictionary(); + + vnl_matrix_fixed measurementFrame = mitk::DiffusionPropertyHelper::GetMeasurementFrame(input); + if (measurementFrame(0,0) || measurementFrame(0,1) || measurementFrame(0,2) || + measurementFrame(1,0) || measurementFrame(1,1) || measurementFrame(1,2) || + measurementFrame(2,0) || measurementFrame(2,1) || measurementFrame(2,2)) + { + sprintf( valbuffer, " (%lf,%lf,%lf) (%lf,%lf,%lf) (%lf,%lf,%lf)", measurementFrame(0,0), measurementFrame(0,1), measurementFrame(0,2), measurementFrame(1,0), measurementFrame(1,1), measurementFrame(1,2), measurementFrame(2,0), measurementFrame(2,1), measurementFrame(2,2)); + itk::EncapsulateMetaData(itkImg->GetMetaDataDictionary(),std::string("measurement frame"),std::string(valbuffer)); + } + + sprintf( valbuffer, "DWMRI"); + itk::EncapsulateMetaData(itkImg->GetMetaDataDictionary(),std::string("modality"),std::string(valbuffer)); + + if(mitk::DiffusionPropertyHelper::GetGradientContainer(input)->Size()) + { + sprintf( valbuffer, "%1f", mitk::DiffusionPropertyHelper::GetReferenceBValue(input) ); + itk::EncapsulateMetaData(itkImg->GetMetaDataDictionary(),std::string("DWMRI_b-value"),std::string(valbuffer)); + } + + for(unsigned int i=0; iSize(); i++) + { + sprintf( keybuffer, "DWMRI_gradient_%04d", i ); + + /*if(itk::ExposeMetaData(input->GetMetaDataDictionary(), + std::string(keybuffer),tmp)) + continue;*/ + + sprintf( valbuffer, "%1f %1f %1f", mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(0), + mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(1), mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(2)); + + itk::EncapsulateMetaData(itkImg->GetMetaDataDictionary(),std::string(keybuffer),std::string(valbuffer)); + } + + typedef itk::VectorImage ImageType; + + std::string ext = this->GetMimeType()->GetExtension(this->GetOutputLocation()); + ext = itksys::SystemTools::LowerCase(ext); + + // default extension is .dwi + if( ext == "") + { + ext = ".nrrd"; + this->SetOutputLocation(this->GetOutputLocation() + ext); + } + + if (ext == ".hdwi" || ext == ".nrrd" || ext == ".dwi") + { + + MITK_INFO << "Extension " << ext; + itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); + //io->SetNrrdVectorType( nrrdKindList ); + io->SetFileType( itk::ImageIOBase::Binary ); + io->UseCompressionOn(); + + typedef itk::ImageFileWriter WriterType; + WriterType::Pointer nrrdWriter = WriterType::New(); + nrrdWriter->UseInputMetaDataDictionaryOn(); + nrrdWriter->SetInput( itkImg ); + nrrdWriter->SetImageIO(io); + nrrdWriter->SetFileName(this->GetOutputLocation()); + nrrdWriter->UseCompressionOn(); + nrrdWriter->SetImageIO(io); + try + { + nrrdWriter->Update(); + } + catch (itk::ExceptionObject e) + { + std::cout << e << std::endl; + throw; + } + + } + + try + { + setlocale(LC_ALL, currLocale.c_str()); + } + catch(...) + { + MITK_INFO << "Could not reset locale " << currLocale; + } +} + +mitk::DiffusionImageNrrdWriterService* mitk::DiffusionImageNrrdWriterService::Clone() const +{ + return new DiffusionImageNrrdWriterService(*this); +} + +mitk::IFileWriter::ConfidenceLevel mitk::DiffusionImageNrrdWriterService::GetConfidenceLevel() const +{ + mitk::Image::ConstPointer input = dynamic_cast(this->GetInput()); + if (input.IsNull() || !mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( input ) ) + { + return Unsupported; + } + else + { + return Supported; + } +} + +#endif //__mitkDiffusionImageNrrdWriterService__cpp diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageWriter.h b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNrrdWriterService.h similarity index 75% rename from Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageWriter.h rename to Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNrrdWriterService.h index 1bedf714ce..9b436c66b5 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkNrrdDiffusionImageWriter.h +++ b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionImageNrrdWriterService.h @@ -1,58 +1,58 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef _MITK_NRRDDIFFVOL_WRITER__H_ -#define _MITK_NRRDDIFFVOL_WRITER__H_ +#ifndef _MITK_DiffusionImageNrrdWriterService__H_ +#define _MITK_DiffusionImageNrrdWriterService__H_ #include #include namespace mitk { /** * Writes diffusion volumes to a file * @ingroup Process */ -class NrrdDiffusionImageWriter : public mitk::AbstractFileWriter +class DiffusionImageNrrdWriterService : public mitk::AbstractFileWriter { public: - NrrdDiffusionImageWriter(); - virtual ~NrrdDiffusionImageWriter(); + DiffusionImageNrrdWriterService(); + virtual ~DiffusionImageNrrdWriterService(); using AbstractFileWriter::Write; virtual void Write(); virtual ConfidenceLevel GetConfidenceLevel() const; typedef mitk::DiffusionPropertyHelper::ImageType VectorImageType; typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType; typedef mitk::DiffusionPropertyHelper::MeasurementFrameType MeasurementFrameType; typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType; protected: - NrrdDiffusionImageWriter(const NrrdDiffusionImageWriter& other); - virtual mitk::NrrdDiffusionImageWriter* Clone() const; + DiffusionImageNrrdWriterService(const DiffusionImageNrrdWriterService& other); + virtual mitk::DiffusionImageNrrdWriterService* Clone() const; }; } // end of namespace mitk #endif diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionModuleActivator.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionModuleActivator.cpp index c4bd31236b..1a4edcb659 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionModuleActivator.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkDiffusionModuleActivator.cpp @@ -1,99 +1,122 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include -#include +#include +#include #include #include -#include +#include +#include #include -#include +#include +#include #include #include -#include +#include +#include #include #include "mitkDiffusionIOMimeTypes.h" namespace mitk { /** \brief Registers services for segmentation module. */ class DiffusionModuleActivator : public us::ModuleActivator { public: void Load(us::ModuleContext* context) { us::ServiceProperties props; props[ us::ServiceConstants::SERVICE_RANKING() ] = 10; - std::vector mimeTypes = mitk::DiffusionIOMimeTypes::Get(); - for (std::vector::const_iterator mimeTypeIter = mimeTypes.begin(), - iterEnd = mimeTypes.end(); mimeTypeIter != iterEnd; ++mimeTypeIter) + m_MimeTypes = mitk::DiffusionIOMimeTypes::Get(); + for (std::vector::const_iterator mimeTypeIter = m_MimeTypes.begin(), + iterEnd = m_MimeTypes.end(); mimeTypeIter != iterEnd; ++mimeTypeIter) { context->RegisterService(*mimeTypeIter, props); } - m_NrrdDiffusionImageReader = new NrrdDiffusionImageReader(); + m_DiffusionImageNrrdReaderService = new DiffusionImageNrrdReaderService(); + m_DiffusionImageNiftiReaderService = new DiffusionImageNiftiReaderService(); m_NrrdTensorImageReader = new NrrdTensorImageReader(); m_NrrdQBallImageReader = new NrrdQBallImageReader(); - m_FiberBundleXReader = new FiberBundleXReader(); + m_FiberBundleVtkReader = new FiberBundleVtkReader(); + m_FiberBundleTrackVisReader = new FiberBundleTrackVisReader(); m_ConnectomicsNetworkReader = new ConnectomicsNetworkReader(); - m_NrrdDiffusionImageWriter = new NrrdDiffusionImageWriter(); + m_DiffusionImageNrrdWriterService = new DiffusionImageNrrdWriterService(); + m_DiffusionImageNiftiWriterService = new DiffusionImageNiftiWriterService(); m_NrrdTensorImageWriter = new NrrdTensorImageWriter(); m_NrrdQBallImageWriter = new NrrdQBallImageWriter(); - m_FiberBundleXWriter = new FiberBundleXWriter(); + m_FiberBundleVtkWriter = new FiberBundleVtkWriter(); + m_FiberBundleTrackVisWriter = new FiberBundleTrackVisWriter(); m_ConnectomicsNetworkWriter = new ConnectomicsNetworkWriter(); } void Unload(us::ModuleContext*) { - delete m_NrrdDiffusionImageReader; + for (unsigned int loop(0); loop < m_MimeTypes.size(); ++loop) + { + delete m_MimeTypes.at(loop); + } + + delete m_DiffusionImageNrrdReaderService; + delete m_DiffusionImageNiftiReaderService; delete m_NrrdTensorImageReader; delete m_NrrdQBallImageReader; - delete m_FiberBundleXReader; + delete m_FiberBundleVtkReader; + delete m_FiberBundleTrackVisReader; delete m_ConnectomicsNetworkReader; - delete m_NrrdDiffusionImageWriter; + delete m_DiffusionImageNrrdWriterService; + delete m_DiffusionImageNiftiWriterService; delete m_NrrdTensorImageWriter; delete m_NrrdQBallImageWriter; - delete m_FiberBundleXWriter; + delete m_FiberBundleVtkWriter; + delete m_FiberBundleTrackVisWriter; delete m_ConnectomicsNetworkWriter; } private: - NrrdDiffusionImageReader * m_NrrdDiffusionImageReader; + DiffusionImageNrrdReaderService * m_DiffusionImageNrrdReaderService; + DiffusionImageNiftiReaderService * m_DiffusionImageNiftiReaderService; NrrdTensorImageReader * m_NrrdTensorImageReader; NrrdQBallImageReader * m_NrrdQBallImageReader; - FiberBundleXReader * m_FiberBundleXReader; + FiberBundleVtkReader * m_FiberBundleVtkReader; + FiberBundleTrackVisReader * m_FiberBundleTrackVisReader; ConnectomicsNetworkReader * m_ConnectomicsNetworkReader; - NrrdDiffusionImageWriter * m_NrrdDiffusionImageWriter; + DiffusionImageNrrdWriterService * m_DiffusionImageNrrdWriterService; + DiffusionImageNiftiWriterService * m_DiffusionImageNiftiWriterService; NrrdTensorImageWriter * m_NrrdTensorImageWriter; NrrdQBallImageWriter * m_NrrdQBallImageWriter; - FiberBundleXWriter * m_FiberBundleXWriter; + FiberBundleVtkWriter * m_FiberBundleVtkWriter; + FiberBundleTrackVisWriter * m_FiberBundleTrackVisWriter; ConnectomicsNetworkWriter * m_ConnectomicsNetworkWriter; + std::vector m_MimeTypes; + }; } US_EXPORT_MODULE_ACTIVATOR(mitk::DiffusionModuleActivator) diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper2D.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper2D.cpp similarity index 87% rename from Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper2D.cpp rename to Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper2D.cpp index fc7de2ff13..e2fd8d57fd 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper2D.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper2D.cpp @@ -1,199 +1,199 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "mitkFiberBundleXMapper2D.h" +#include "mitkFiberBundleMapper2D.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -mitk::FiberBundleXMapper2D::FiberBundleXMapper2D() +mitk::FiberBundleMapper2D::FiberBundleMapper2D() : m_LineWidth(1) { m_lut = vtkLookupTable::New(); m_lut->Build(); } -mitk::FiberBundleXMapper2D::~FiberBundleXMapper2D() +mitk::FiberBundleMapper2D::~FiberBundleMapper2D() { } -mitk::FiberBundleX* mitk::FiberBundleXMapper2D::GetInput() +mitk::FiberBundle* mitk::FiberBundleMapper2D::GetInput() { - return dynamic_cast< mitk::FiberBundleX * > ( GetDataNode()->GetData() ); + return dynamic_cast< mitk::FiberBundle * > ( GetDataNode()->GetData() ); } -void mitk::FiberBundleXMapper2D::Update(mitk::BaseRenderer * renderer) +void mitk::FiberBundleMapper2D::Update(mitk::BaseRenderer * renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; // 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_LocalStorageHandler.GetLocalStorage(renderer); //set renderer independent shader properties const DataNode::Pointer node = this->GetDataNode(); 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"; float fiberOpacity; this->GetDataNode()->GetOpacity(fiberOpacity, NULL); node->SetFloatProperty("shader.mitkShaderFiberClipping.fiberThickness",thickness); node->SetIntProperty("shader.mitkShaderFiberClipping.fiberFadingON",fiberfading); node->SetFloatProperty("shader.mitkShaderFiberClipping.fiberOpacity",fiberOpacity); - mitk::FiberBundleX* fiberBundle = this->GetInput(); + mitk::FiberBundle* fiberBundle = this->GetInput(); if (fiberBundle==NULL) return; int lineWidth = 0; node->GetIntProperty("LineWidth", lineWidth); if (m_LineWidth!=lineWidth) { m_LineWidth = lineWidth; fiberBundle->RequestUpdate2D(); } if ( localStorage->m_LastUpdateTimeGetDisplayGeometry()->GetMTime() || localStorage->m_LastUpdateTimeGetUpdateTime2D() ) { this->UpdateShaderParameter(renderer); this->GenerateDataForRenderer( renderer ); } } -void mitk::FiberBundleXMapper2D::UpdateShaderParameter(mitk::BaseRenderer * renderer) +void mitk::FiberBundleMapper2D::UpdateShaderParameter(mitk::BaseRenderer * 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 planeNormal[3]; planeNormal[0] = planeGeo->GetNormal()[0]; planeNormal[1] = planeGeo->GetNormal()[1]; planeNormal[2] = planeGeo->GetNormal()[2]; float tmp1 = planeGeo->GetOrigin()[0] * planeNormal[0]; float tmp2 = planeGeo->GetOrigin()[1] * planeNormal[1]; float tmp3 = planeGeo->GetOrigin()[2] * planeNormal[2]; float thickness = tmp1 + tmp2 + tmp3; //attention, correct normalvector DataNode::Pointer node = this->GetDataNode(); node->SetFloatProperty("shader.mitkShaderFiberClipping.slicingPlane.w",thickness,renderer); node->SetFloatProperty("shader.mitkShaderFiberClipping.slicingPlane.x",planeNormal[0],renderer); node->SetFloatProperty("shader.mitkShaderFiberClipping.slicingPlane.y",planeNormal[1],renderer); node->SetFloatProperty("shader.mitkShaderFiberClipping.slicingPlane.z",planeNormal[2],renderer); } // vtkActors and Mappers are feeded here -void mitk::FiberBundleXMapper2D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) +void mitk::FiberBundleMapper2D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { - mitk::FiberBundleX* fiberBundle = this->GetInput(); + mitk::FiberBundle* fiberBundle = this->GetInput(); //the handler of local storage gets feeded in this method with requested data for related renderwindow FBXLocalStorage *localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); mitk::DataNode* node = this->GetDataNode(); if ( node == NULL ) return; vtkSmartPointer fiberPolyData = fiberBundle->GetFiberPolyData(); if (fiberPolyData == NULL) return; fiberPolyData->GetPointData()->AddArray(fiberBundle->GetFiberColors()); localStorage->m_FiberMapper->ScalarVisibilityOn(); localStorage->m_FiberMapper->SetScalarModeToUsePointFieldData(); localStorage->m_FiberMapper->SetLookupTable(m_lut); //apply the properties after the slice was set localStorage->m_PointActor->GetProperty()->SetOpacity(0.999); localStorage->m_FiberMapper->SelectColorArray("FIBER_COLORS"); localStorage->m_FiberMapper->SetInputData(fiberPolyData); localStorage->m_PointActor->SetMapper(localStorage->m_FiberMapper); localStorage->m_PointActor->GetProperty()->ShadingOn(); localStorage->m_PointActor->GetProperty()->SetLineWidth(m_LineWidth); // Applying shading properties this->ApplyShaderProperties(renderer); // We have been modified => save this for next Update() localStorage->m_LastUpdateTime.Modified(); } -vtkProp* mitk::FiberBundleXMapper2D::GetVtkProp(mitk::BaseRenderer *renderer) +vtkProp* mitk::FiberBundleMapper2D::GetVtkProp(mitk::BaseRenderer *renderer) { this->Update(renderer); return m_LocalStorageHandler.GetLocalStorage(renderer)->m_PointActor; } -void mitk::FiberBundleXMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) +void mitk::FiberBundleMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { Superclass::SetDefaultProperties(node, renderer, overwrite); node->SetProperty("shader",mitk::ShaderProperty::New("mitkShaderFiberClipping")); // Shaders IShaderRepository* shaderRepo = CoreServices::GetShaderRepository(); if (shaderRepo) { shaderRepo->AddDefaultProperties(node, renderer, overwrite); } //add other parameters to propertylist node->AddProperty( "Fiber2DSliceThickness", mitk::FloatProperty::New(1.0f), renderer, overwrite ); node->AddProperty( "Fiber2DfadeEFX", mitk::BoolProperty::New(true), renderer, overwrite ); node->AddProperty( "color", mitk::ColorProperty::New(1.0,1.0,1.0), renderer, overwrite); node->AddProperty( "TubeRadius",mitk::FloatProperty::New( 0.0 ), renderer, overwrite); } -mitk::FiberBundleXMapper2D::FBXLocalStorage::FBXLocalStorage() +mitk::FiberBundleMapper2D::FBXLocalStorage::FBXLocalStorage() { m_PointActor = vtkSmartPointer::New(); m_FiberMapper = vtkSmartPointer::New(); } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper2D.h b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper2D.h similarity index 89% rename from Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper2D.h rename to Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper2D.h index 85d61d0df8..ba1089e97f 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper2D.h +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper2D.h @@ -1,109 +1,109 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef FIBERBUNDLEXMAPPER2D_H_HEADER_INCLUDED -#define FIBERBUNDLEXMAPPER2D_H_HEADER_INCLUDED +#ifndef FiberBundleMAPPER2D_H_HEADER_INCLUDED +#define FiberBundleMAPPER2D_H_HEADER_INCLUDED //MITK Rendering #include #include //#include #include -#include +#include #include class vtkActor; //class vtkPropAssembly; //lets see if we need it class mitkBaseRenderer; class vtkPolyDataMapper; class vtkCutter; class vtkPlane; class vtkPolyData; namespace mitk { struct IShaderRepository; -class FiberBundleXMapper2D : public VtkMapper +class FiberBundleMapper2D : public VtkMapper { public: - mitkClassMacro(FiberBundleXMapper2D, VtkMapper); + mitkClassMacro(FiberBundleMapper2D, VtkMapper); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - mitk::FiberBundleX* GetInput(); + mitk::FiberBundle* GetInput(); /** \brief Checks whether this mapper needs to update itself and generate data. */ virtual void Update(mitk::BaseRenderer * renderer); static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false ); //### methods of MITK-VTK rendering pipeline virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); //### end of methods of MITK-VTK rendering pipeline class FBXLocalStorage : public mitk::Mapper::BaseLocalStorage { public: /** \brief Point Actor of a 2D render window. */ vtkSmartPointer m_PointActor; /** \brief Point Mapper of a 2D render window. */ vtkSmartPointer m_FiberMapper; vtkSmartPointer m_SlicingPlane; //needed later when optimized 2D mapper vtkSmartPointer m_SlicedResult; //might be depricated in optimized 2D mapper /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; /** \brief Constructor of the local storage. Do as much actions as possible in here to avoid double executions. */ FBXLocalStorage(); //if u copy&paste from this 2Dmapper, be aware that the implementation of this constructor is in the cpp file ~FBXLocalStorage() { } }; /** \brief This member holds all three LocalStorages for the three 2D render windows. */ mitk::LocalStorageHandler m_LocalStorageHandler; protected: - FiberBundleXMapper2D(); - virtual ~FiberBundleXMapper2D(); + FiberBundleMapper2D(); + virtual ~FiberBundleMapper2D(); /** Does the actual resampling, without rendering. */ virtual void GenerateDataForRenderer(mitk::BaseRenderer*); void UpdateShaderParameter(mitk::BaseRenderer*); private: vtkSmartPointer m_lut; int m_LineWidth; }; }//end namespace #endif diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper3D.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper3D.cpp similarity index 82% rename from Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper3D.cpp rename to Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper3D.cpp index fd949cdbfa..b69590a4fe 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper3D.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper3D.cpp @@ -1,189 +1,189 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "mitkFiberBundleXMapper3D.h" +#include "mitkFiberBundleMapper3D.h" #include #include #include #include #include #include #include #include -mitk::FiberBundleXMapper3D::FiberBundleXMapper3D() +mitk::FiberBundleMapper3D::FiberBundleMapper3D() : m_TubeRadius(0.0) , m_TubeSides(15) , m_LineWidth(1) { m_lut = vtkLookupTable::New(); m_lut->Build(); } -mitk::FiberBundleXMapper3D::~FiberBundleXMapper3D() +mitk::FiberBundleMapper3D::~FiberBundleMapper3D() { } -const mitk::FiberBundleX* mitk::FiberBundleXMapper3D::GetInput() +const mitk::FiberBundle* mitk::FiberBundleMapper3D::GetInput() { - return static_cast ( GetDataNode()->GetData() ); + return static_cast ( GetDataNode()->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::FiberBundleXMapper3D::InternalGenerateData(mitk::BaseRenderer *renderer) +void mitk::FiberBundleMapper3D::InternalGenerateData(mitk::BaseRenderer *renderer) { - mitk::FiberBundleX* fiberBundle = dynamic_cast (GetDataNode()->GetData()); + mitk::FiberBundle* fiberBundle = dynamic_cast (GetDataNode()->GetData()); if (fiberBundle == NULL) return; vtkSmartPointer fiberPolyData = fiberBundle->GetFiberPolyData(); if (fiberPolyData == NULL) return; fiberPolyData->GetPointData()->AddArray(fiberBundle->GetFiberColors()); float tmpopa; this->GetDataNode()->GetOpacity(tmpopa, NULL); FBXLocalStorage3D *localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); if (m_TubeRadius>0.0) { vtkSmartPointer tubeFilter = vtkSmartPointer::New(); tubeFilter->SetInputData(fiberPolyData); tubeFilter->SetNumberOfSides(m_TubeSides); tubeFilter->SetRadius(m_TubeRadius); tubeFilter->Update(); fiberPolyData = tubeFilter->GetOutput(); } if (tmpopa<1) { vtkSmartPointer depthSort = vtkSmartPointer::New(); depthSort->SetInputData( fiberPolyData ); depthSort->SetCamera( renderer->GetVtkRenderer()->GetActiveCamera() ); depthSort->SetDirectionToFrontToBack(); depthSort->Update(); localStorage->m_FiberMapper->SetInputConnection(depthSort->GetOutputPort()); } else { localStorage->m_FiberMapper->SetInputData(fiberPolyData); } localStorage->m_FiberMapper->SelectColorArray("FIBER_COLORS"); localStorage->m_FiberMapper->ScalarVisibilityOn(); localStorage->m_FiberMapper->SetScalarModeToUsePointFieldData(); localStorage->m_FiberActor->SetMapper(localStorage->m_FiberMapper); localStorage->m_FiberMapper->SetLookupTable(m_lut); // set Opacity localStorage->m_FiberActor->GetProperty()->SetOpacity((double) tmpopa); localStorage->m_FiberActor->GetProperty()->SetLineWidth(m_LineWidth); localStorage->m_FiberAssembly->AddPart(localStorage->m_FiberActor); localStorage->m_LastUpdateTime.Modified(); } -void mitk::FiberBundleXMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) +void mitk::FiberBundleMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; const DataNode* node = this->GetDataNode(); FBXLocalStorage3D* localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); - mitk::FiberBundleX* fiberBundle = dynamic_cast(node->GetData()); + mitk::FiberBundle* fiberBundle = dynamic_cast(node->GetData()); // did any rendering properties change? float tubeRadius = 0; node->GetFloatProperty("TubeRadius", tubeRadius); if (m_TubeRadius!=tubeRadius) { m_TubeRadius = tubeRadius; fiberBundle->RequestUpdate3D(); } int tubeSides = 0; node->GetIntProperty("TubeSides", tubeSides); if (m_TubeSides!=tubeSides) { m_TubeSides = tubeSides; fiberBundle->RequestUpdate3D(); } int lineWidth = 0; node->GetIntProperty("LineWidth", lineWidth); if (m_LineWidth!=lineWidth) { m_LineWidth = lineWidth; fiberBundle->RequestUpdate3D(); } if (localStorage->m_LastUpdateTime>=fiberBundle->GetUpdateTime3D()) return; // Calculate time step of the input data for the specified renderer (integer value) // this method is implemented in mitkMapper this->CalculateTimeStep( renderer ); this->InternalGenerateData(renderer); } -void mitk::FiberBundleXMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) +void mitk::FiberBundleMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { Superclass::SetDefaultProperties(node, renderer, overwrite); node->AddProperty( "LineWidth", mitk::IntProperty::New( true ), renderer, overwrite ); node->AddProperty( "opacity", mitk::FloatProperty::New( 1.0 ), renderer, overwrite); node->AddProperty( "color", mitk::ColorProperty::New(1.0,1.0,1.0), renderer, overwrite); node->AddProperty( "pickable", mitk::BoolProperty::New( true ), renderer, overwrite); node->AddProperty( "TubeRadius",mitk::FloatProperty::New( 0.0 ), renderer, overwrite); node->AddProperty( "TubeSides",mitk::IntProperty::New( 15 ), renderer, overwrite); } -vtkProp* mitk::FiberBundleXMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) +vtkProp* mitk::FiberBundleMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { return m_LocalStorageHandler.GetLocalStorage(renderer)->m_FiberAssembly; } -void mitk::FiberBundleXMapper3D::UpdateVtkObjects() +void mitk::FiberBundleMapper3D::UpdateVtkObjects() { } -void mitk::FiberBundleXMapper3D::SetVtkMapperImmediateModeRendering(vtkMapper *) +void mitk::FiberBundleMapper3D::SetVtkMapperImmediateModeRendering(vtkMapper *) { } -mitk::FiberBundleXMapper3D::FBXLocalStorage3D::FBXLocalStorage3D() +mitk::FiberBundleMapper3D::FBXLocalStorage3D::FBXLocalStorage3D() { m_FiberActor = vtkSmartPointer::New(); m_FiberMapper = vtkSmartPointer::New(); m_FiberAssembly = vtkSmartPointer::New(); } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper3D.h b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper3D.h similarity index 86% rename from Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper3D.h rename to Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper3D.h index b583b97a98..e1ffad5bb8 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXMapper3D.h +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper3D.h @@ -1,104 +1,104 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef FiberBundleXMapper3D_H_HEADER_INCLUDED -#define FiberBundleXMapper3D_H_HEADER_INCLUDED +#ifndef FiberBundleMapper3D_H_HEADER_INCLUDED +#define FiberBundleMapper3D_H_HEADER_INCLUDED //#include //?? necessary #include -#include +#include #include #include #include #include class vtkPropAssembly; namespace mitk { //##Documentation -//## @brief Mapper for FiberBundleX +//## @brief Mapper for FiberBundle //## @ingroup Mapper -class FiberBundleXMapper3D : public VtkMapper +class FiberBundleMapper3D : public VtkMapper { public: - mitkClassMacro(FiberBundleXMapper3D, VtkMapper) + mitkClassMacro(FiberBundleMapper3D, VtkMapper) itkFactorylessNewMacro(Self) itkCloneMacro(Self) //========== essential implementation for 3D mapper ======== - const FiberBundleX* GetInput(); + const FiberBundle* GetInput(); virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer); //looks like depricated.. should be replaced bz GetViewProp() static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false ); static void SetVtkMapperImmediateModeRendering(vtkMapper *mapper); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); //========================================================= class FBXLocalStorage3D : public mitk::Mapper::BaseLocalStorage { public: /** \brief Point Actor of a 3D render window. */ vtkSmartPointer m_FiberActor; /** \brief Point Mapper of a 3D render window. */ vtkSmartPointer m_FiberMapper; vtkSmartPointer m_FiberAssembly; /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; /** \brief Constructor of the local storage. Do as much actions as possible in here to avoid double executions. */ FBXLocalStorage3D(); //if u copy&paste from this 2Dmapper, be aware that the implementation of this constructor is in the cpp file ~FBXLocalStorage3D() { } }; /** \brief This member holds all three LocalStorages for the 3D render window(s). */ mitk::LocalStorageHandler m_LocalStorageHandler; protected: - FiberBundleXMapper3D(); - virtual ~FiberBundleXMapper3D(); + FiberBundleMapper3D(); + virtual ~FiberBundleMapper3D(); void InternalGenerateData(mitk::BaseRenderer *renderer); void UpdateVtkObjects(); //?? private: vtkSmartPointer m_lut; float m_TubeRadius; int m_TubeSides; int m_LineWidth; }; } // end namespace mitk -#endif /* FiberBundleXMapper3D_H_HEADER_INCLUDED */ +#endif /* FiberBundleMapper3D_H_HEADER_INCLUDED */ diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXSerializer.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleSerializer.cpp similarity index 68% rename from Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXSerializer.cpp rename to Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleSerializer.cpp index cd9b2a3725..28f7963fab 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXSerializer.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleSerializer.cpp @@ -1,72 +1,72 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "mitkFiberBundleXSerializer.h" -#include "mitkFiberBundleX.h" -#include "mitkFiberBundleXWriter.h" +#include "mitkFiberBundleSerializer.h" +#include "mitkFiberBundle.h" +#include "mitkFiberBundleVtkWriter.h" #include #include -MITK_REGISTER_SERIALIZER(FiberBundleXSerializer) +MITK_REGISTER_SERIALIZER(FiberBundleSerializer) -mitk::FiberBundleXSerializer::FiberBundleXSerializer() +mitk::FiberBundleSerializer::FiberBundleSerializer() { } -mitk::FiberBundleXSerializer::~FiberBundleXSerializer() +mitk::FiberBundleSerializer::~FiberBundleSerializer() { } -std::string mitk::FiberBundleXSerializer::Serialize() +std::string mitk::FiberBundleSerializer::Serialize() { - const FiberBundleX* fb = dynamic_cast( m_Data.GetPointer() ); + const FiberBundle* fb = dynamic_cast( m_Data.GetPointer() ); if (fb == NULL) { MITK_ERROR << " Object at " << (const void*) this->m_Data - << " is not an mitk::FiberBundleX. Cannot serialize as FiberBundleX."; + << " is not an mitk::FiberBundle. Cannot serialize as FiberBundle."; return ""; } std::string filename( this->GetUniqueFilenameInWorkingDirectory() ); filename += "_"; filename += m_FilenameHint; filename += ".fib"; std::string fullname(m_WorkingDirectory); fullname += "/"; fullname += itksys::SystemTools::ConvertToOutputPath(filename.c_str()); try { - mitk::IOUtil::Save(const_cast(fb),fullname); + mitk::IOUtil::Save(const_cast(fb),fullname); } catch (std::exception& e) { MITK_ERROR << " Error serializing object at " << (const void*) this->m_Data << " to " << fullname << ": " << e.what(); return ""; } return filename; } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXSerializer.h b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleSerializer.h similarity index 72% rename from Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXSerializer.h rename to Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleSerializer.h index 02043bd112..df9640df27 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXSerializer.h +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleSerializer.h @@ -1,39 +1,39 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef mitkFiberBundleXSerializer_h_included -#define mitkFiberBundleXSerializer_h_included +#ifndef mitkFiberBundleSerializer_h_included +#define mitkFiberBundleSerializer_h_included #include "mitkBaseDataSerializer.h" namespace mitk { /** \brief Serializes mitk::Surface for mitk::SceneIO */ -class FiberBundleXSerializer : public BaseDataSerializer +class FiberBundleSerializer : public BaseDataSerializer { public: - mitkClassMacro( FiberBundleXSerializer, BaseDataSerializer ); + mitkClassMacro( FiberBundleSerializer, BaseDataSerializer ); itkFactorylessNewMacro(Self) itkCloneMacro(Self) virtual std::string Serialize(); protected: - FiberBundleXSerializer(); - virtual ~FiberBundleXSerializer(); + FiberBundleSerializer(); + virtual ~FiberBundleSerializer(); }; } // namespace #endif diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTrackVisReader.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTrackVisReader.cpp new file mode 100644 index 0000000000..5e7a3712be --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTrackVisReader.cpp @@ -0,0 +1,86 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkFiberBundleTrackVisReader.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mitkDiffusionIOMimeTypes.h" + + +mitk::FiberBundleTrackVisReader::FiberBundleTrackVisReader() + : mitk::AbstractFileReader( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_TRK_MIMETYPE_NAME(), "TrackVis Fiber Bundle Reader" ) +{ + m_ServiceReg = this->RegisterService(); +} + +mitk::FiberBundleTrackVisReader::FiberBundleTrackVisReader(const FiberBundleTrackVisReader &other) + :mitk::AbstractFileReader(other) +{ +} + +mitk::FiberBundleTrackVisReader * mitk::FiberBundleTrackVisReader::Clone() const +{ + return new FiberBundleTrackVisReader(*this); +} + +std::vector > mitk::FiberBundleTrackVisReader::Read() +{ + + std::vector > result; + try + { + const std::string& locale = "C"; + const std::string& currLocale = setlocale( LC_ALL, NULL ); + setlocale(LC_ALL, locale.c_str()); + + std::string filename = this->GetInputLocation(); + + std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename); + ext = itksys::SystemTools::LowerCase(ext); + + if (ext==".trk") + { + FiberBundle::Pointer image = FiberBundle::New(); + TrackVisFiberReader reader; + reader.open(this->GetInputLocation().c_str()); + reader.read(image.GetPointer()); + result.push_back(image.GetPointer()); + return result; + } + + setlocale(LC_ALL, currLocale.c_str()); + MITK_INFO << "Fiber bundle read"; + } + catch(...) + { + throw; + } + return result; +} diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXReader.h b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTrackVisReader.h similarity index 67% copy from Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXReader.h copy to Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTrackVisReader.h index 386fdad556..035e96f44e 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXReader.h +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTrackVisReader.h @@ -1,52 +1,52 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef __mitkFiberBundleXReader_h -#define __mitkFiberBundleXReader_h +#ifndef __mitkFiberBundleTrackVisReader_h +#define __mitkFiberBundleTrackVisReader_h #include #include -#include +#include #include #include namespace mitk { /** \brief */ - class FiberBundleXReader : public AbstractFileReader + class FiberBundleTrackVisReader : public AbstractFileReader { public: - FiberBundleXReader(); - virtual ~FiberBundleXReader(){} - FiberBundleXReader(const FiberBundleXReader& other); - virtual FiberBundleXReader * Clone() const; + FiberBundleTrackVisReader(); + virtual ~FiberBundleTrackVisReader(){} + FiberBundleTrackVisReader(const FiberBundleTrackVisReader& other); + virtual FiberBundleTrackVisReader * Clone() const; using mitk::AbstractFileReader::Read; virtual std::vector > Read(); private: us::ServiceRegistration m_ServiceReg; }; } //namespace MITK -#endif // __mitkFiberBundleXReader_h +#endif // __mitkFiberBundleReader_h diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTrackVisWriter.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTrackVisWriter.cpp new file mode 100644 index 0000000000..109ffc3480 --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTrackVisWriter.cpp @@ -0,0 +1,104 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkFiberBundleTrackVisWriter.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mitkDiffusionIOMimeTypes.h" + +mitk::FiberBundleTrackVisWriter::FiberBundleTrackVisWriter() + : mitk::AbstractFileWriter(mitk::FiberBundle::GetStaticNameOfClass(), mitk::DiffusionIOMimeTypes::FIBERBUNDLE_TRK_MIMETYPE_NAME(), "TrackVis Fiber Bundle Reader") +{ + // Options defaultOptions; + // this->SetDefaultOptions(defaultOptions); + RegisterService(); +} + +mitk::FiberBundleTrackVisWriter::FiberBundleTrackVisWriter(const mitk::FiberBundleTrackVisWriter & other) + :mitk::AbstractFileWriter(other) +{} + +mitk::FiberBundleTrackVisWriter::~FiberBundleTrackVisWriter() +{} + +mitk::FiberBundleTrackVisWriter * mitk::FiberBundleTrackVisWriter::Clone() const +{ + return new mitk::FiberBundleTrackVisWriter(*this); +} + +void mitk::FiberBundleTrackVisWriter::Write() +{ + + std::ostream* out; + std::ofstream outStream; + + if( this->GetOutputStream() ) + { + out = this->GetOutputStream(); + }else{ + outStream.open( this->GetOutputLocation().c_str() ); + out = &outStream; + } + + if ( !out->good() ) + { + mitkThrow() << "Stream not good."; + } + + try + { + const std::string& locale = "C"; + const std::string& currLocale = setlocale( LC_ALL, NULL ); + setlocale(LC_ALL, locale.c_str()); + + std::locale previousLocale(out->getloc()); + std::locale I("C"); + out->imbue(I); + + std::string filename = this->GetOutputLocation().c_str(); + + mitk::FiberBundle::ConstPointer input = dynamic_cast(this->GetInput()); + std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->GetOutputLocation().c_str()); + + // default extension is .fib + if(ext == "") + { + ext = ".trk"; + this->SetOutputLocation(this->GetOutputLocation() + ext); + } + + MITK_INFO << "Writing fiber bundle as TRK"; + TrackVisFiberReader trk; + trk.create(filename, input.GetPointer()); + trk.writeHdr(); + trk.append(input.GetPointer()); + + setlocale(LC_ALL, currLocale.c_str()); + MITK_INFO << "Fiber bundle written"; + } + catch(...) + { + throw; + } +} diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXWriter.h b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTrackVisWriter.h similarity index 82% copy from Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXWriter.h copy to Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTrackVisWriter.h index e7c7194e03..576a1b86b0 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXWriter.h +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleTrackVisWriter.h @@ -1,118 +1,118 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef __mitkFiberBundleXWriter_h -#define __mitkFiberBundleXWriter_h +#ifndef __mitkFiberBundleTrackVisWriter_h +#define __mitkFiberBundleTrackVisWriter_h #include -#include "mitkFiberBundleX.h" +#include "mitkFiberBundle.h" #include namespace mitk { /** * Writes fiber bundles to a file * @ingroup Process */ -class FiberBundleXWriter : public mitk::AbstractFileWriter +class FiberBundleTrackVisWriter : public mitk::AbstractFileWriter { public: - FiberBundleXWriter(); - FiberBundleXWriter(const FiberBundleXWriter & other); - virtual FiberBundleXWriter * Clone() const; - virtual ~FiberBundleXWriter(); + FiberBundleTrackVisWriter(); + FiberBundleTrackVisWriter(const FiberBundleTrackVisWriter & other); + virtual FiberBundleTrackVisWriter * Clone() const; + virtual ~FiberBundleTrackVisWriter(); using mitk::AbstractFileWriter::Write; virtual void Write(); static const char* XML_GEOMETRY; static const char* XML_MATRIX_XX; static const char* XML_MATRIX_XY; static const char* XML_MATRIX_XZ; static const char* XML_MATRIX_YX; static const char* XML_MATRIX_YY; static const char* XML_MATRIX_YZ; static const char* XML_MATRIX_ZX; static const char* XML_MATRIX_ZY; static const char* XML_MATRIX_ZZ; static const char* XML_ORIGIN_X; static const char* XML_ORIGIN_Y; static const char* XML_ORIGIN_Z; static const char* XML_SPACING_X; static const char* XML_SPACING_Y; static const char* XML_SPACING_Z; static const char* XML_SIZE_X; static const char* XML_SIZE_Y; static const char* XML_SIZE_Z; static const char* XML_FIBER_BUNDLE; static const char* XML_FIBER; static const char* XML_PARTICLE; static const char* XML_ID; static const char* XML_POS_X; static const char* XML_POS_Y; static const char* XML_POS_Z; static const char* VERSION_STRING; static const char* XML_FIBER_BUNDLE_FILE; static const char* XML_FILE_VERSION; static const char* XML_NUM_FIBERS; static const char* XML_NUM_PARTICLES; static const char* ASCII_FILE; static const char* FILE_NAME; }; } // end of namespace mitk -#endif //__mitkFiberBundleXWriter_h +#endif //__mitkFiberBundleWriter_h diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXReader.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleVtkReader.cpp similarity index 89% rename from Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXReader.cpp rename to Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleVtkReader.cpp index 025f2bbe20..cf874cb3ac 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXReader.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleVtkReader.cpp @@ -1,229 +1,219 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "mitkFiberBundleXReader.h" +#include "mitkFiberBundleVtkReader.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkDiffusionIOMimeTypes.h" -mitk::FiberBundleXReader::FiberBundleXReader() - : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_MIMETYPE() ), mitk::DiffusionIOMimeTypes::FIBERBUNDLE_MIMETYPE_DESCRIPTION() ) +mitk::FiberBundleVtkReader::FiberBundleVtkReader() + : mitk::AbstractFileReader( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_VTK_MIMETYPE_NAME(), "VTK Fiber Bundle Reader" ) { m_ServiceReg = this->RegisterService(); } -mitk::FiberBundleXReader::FiberBundleXReader(const FiberBundleXReader &other) +mitk::FiberBundleVtkReader::FiberBundleVtkReader(const FiberBundleVtkReader &other) :mitk::AbstractFileReader(other) { } -mitk::FiberBundleXReader * mitk::FiberBundleXReader::Clone() const +mitk::FiberBundleVtkReader * mitk::FiberBundleVtkReader::Clone() const { - return new FiberBundleXReader(*this); + return new FiberBundleVtkReader(*this); } -std::vector > mitk::FiberBundleXReader::Read() +std::vector > mitk::FiberBundleVtkReader::Read() { std::vector > result; try { const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, NULL ); setlocale(LC_ALL, locale.c_str()); std::string filename = this->GetInputLocation(); std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename); ext = itksys::SystemTools::LowerCase(ext); - if (ext==".trk") - { - FiberBundleX::Pointer image = FiberBundleX::New(); - TrackVisFiberReader reader; - reader.open(this->GetInputLocation().c_str()); - reader.read(image.GetPointer()); - result.push_back(image.GetPointer()); - return result; - } - vtkSmartPointer chooser=vtkSmartPointer::New(); chooser->SetFileName( this->GetInputLocation().c_str() ); if( chooser->IsFilePolyData()) { vtkSmartPointer reader = vtkSmartPointer::New(); reader->SetFileName( this->GetInputLocation().c_str() ); reader->Update(); if ( reader->GetOutput() != NULL ) { vtkSmartPointer fiberPolyData = reader->GetOutput(); - FiberBundleX::Pointer fiberBundle = FiberBundleX::New(fiberPolyData); + FiberBundle::Pointer fiberBundle = FiberBundle::New(fiberPolyData); vtkSmartPointer weights = vtkFloatArray::SafeDownCast(fiberPolyData->GetCellData()->GetArray("FIBER_WEIGHTS")); if (weights!=NULL) { // float weight=0; // for (int i=0; iGetSize(); i++) // if (!mitk::Equal(weights->GetValue(i),weight,0.00001)) // { // MITK_INFO << "Weight: " << weights->GetValue(i); // weight = weights->GetValue(i); // } fiberBundle->SetFiberWeights(weights); } vtkSmartPointer fiberColors = vtkUnsignedCharArray::SafeDownCast(fiberPolyData->GetPointData()->GetArray("FIBER_COLORS")); if (fiberColors!=NULL) fiberBundle->SetFiberColors(fiberColors); result.push_back(fiberBundle.GetPointer()); return result; } } else // try to read deprecated fiber bundle file format { MITK_INFO << "Reading xml fiber bundle"; vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); vtkSmartPointer cellArray = vtkSmartPointer::New(); vtkSmartPointer points = vtkSmartPointer::New(); TiXmlDocument doc( this->GetInputLocation().c_str() ); if(doc.LoadFile()) { TiXmlHandle hDoc(&doc); TiXmlElement* pElem; TiXmlHandle hRoot(0); pElem = hDoc.FirstChildElement().Element(); // save this for later hRoot = TiXmlHandle(pElem); pElem = hRoot.FirstChildElement("geometry").Element(); // read geometry mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); // read origin mitk::Point3D origin; double temp = 0; pElem->Attribute("origin_x", &temp); origin[0] = temp; pElem->Attribute("origin_y", &temp); origin[1] = temp; pElem->Attribute("origin_z", &temp); origin[2] = temp; geometry->SetOrigin(origin); // read spacing ScalarType spacing[3]; pElem->Attribute("spacing_x", &temp); spacing[0] = temp; pElem->Attribute("spacing_y", &temp); spacing[1] = temp; pElem->Attribute("spacing_z", &temp); spacing[2] = temp; geometry->SetSpacing(spacing); // read transform vtkMatrix4x4* m = vtkMatrix4x4::New(); pElem->Attribute("xx", &temp); m->SetElement(0,0,temp); pElem->Attribute("xy", &temp); m->SetElement(1,0,temp); pElem->Attribute("xz", &temp); m->SetElement(2,0,temp); pElem->Attribute("yx", &temp); m->SetElement(0,1,temp); pElem->Attribute("yy", &temp); m->SetElement(1,1,temp); pElem->Attribute("yz", &temp); m->SetElement(2,1,temp); pElem->Attribute("zx", &temp); m->SetElement(0,2,temp); pElem->Attribute("zy", &temp); m->SetElement(1,2,temp); pElem->Attribute("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); // read bounds float bounds[] = {0, 0, 0, 0, 0, 0}; pElem->Attribute("size_x", &temp); bounds[1] = temp; pElem->Attribute("size_y", &temp); bounds[3] = temp; pElem->Attribute("size_z", &temp); bounds[5] = temp; geometry->SetFloatBounds(bounds); geometry->SetImageGeometry(true); pElem = hRoot.FirstChildElement("fiber_bundle").FirstChild().Element(); for( ; pElem ; pElem=pElem->NextSiblingElement()) { TiXmlElement* pElem2 = pElem->FirstChildElement(); vtkSmartPointer container = vtkSmartPointer::New(); for( ; pElem2; pElem2=pElem2->NextSiblingElement()) { Point3D point; pElem2->Attribute("pos_x", &temp); point[0] = temp; pElem2->Attribute("pos_y", &temp); point[1] = temp; pElem2->Attribute("pos_z", &temp); point[2] = temp; geometry->IndexToWorld(point, point); vtkIdType id = points->InsertNextPoint(point.GetDataPointer()); container->GetPointIds()->InsertNextId(id); } cellArray->InsertNextCell(container); } fiberPolyData->SetPoints(points); fiberPolyData->SetLines(cellArray); vtkSmartPointer cleaner = vtkSmartPointer::New(); cleaner->SetInputData(fiberPolyData); cleaner->Update(); fiberPolyData = cleaner->GetOutput(); - FiberBundleX::Pointer image = FiberBundleX::New(fiberPolyData); + FiberBundle::Pointer image = FiberBundle::New(fiberPolyData); result.push_back(image.GetPointer()); return result; } else { MITK_ERROR << "could not open xml file"; throw "could not open xml file"; } } setlocale(LC_ALL, currLocale.c_str()); MITK_INFO << "Fiber bundle read"; } catch(...) { throw; } return result; } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXReader.h b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleVtkReader.h similarity index 70% rename from Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXReader.h rename to Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleVtkReader.h index 386fdad556..3f5ec08a60 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXReader.h +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleVtkReader.h @@ -1,52 +1,52 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef __mitkFiberBundleXReader_h -#define __mitkFiberBundleXReader_h +#ifndef __mitkFiberBundleVtkReader_h +#define __mitkFiberBundleVtkReader_h #include #include -#include +#include #include #include namespace mitk { /** \brief */ - class FiberBundleXReader : public AbstractFileReader + class FiberBundleVtkReader : public AbstractFileReader { public: - FiberBundleXReader(); - virtual ~FiberBundleXReader(){} - FiberBundleXReader(const FiberBundleXReader& other); - virtual FiberBundleXReader * Clone() const; + FiberBundleVtkReader(); + virtual ~FiberBundleVtkReader(){} + FiberBundleVtkReader(const FiberBundleVtkReader& other); + virtual FiberBundleVtkReader * Clone() const; using mitk::AbstractFileReader::Read; virtual std::vector > Read(); private: us::ServiceRegistration m_ServiceReg; }; } //namespace MITK -#endif // __mitkFiberBundleXReader_h +#endif // __mitkFiberBundleReader_h diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleVtkWriter.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleVtkWriter.cpp new file mode 100644 index 0000000000..b8794229f9 --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleVtkWriter.cpp @@ -0,0 +1,133 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkFiberBundleVtkWriter.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mitkDiffusionIOMimeTypes.h" + +mitk::FiberBundleVtkWriter::FiberBundleVtkWriter() + : mitk::AbstractFileWriter(mitk::FiberBundle::GetStaticNameOfClass(), mitk::DiffusionIOMimeTypes::FIBERBUNDLE_VTK_MIMETYPE_NAME(), "VTK Fiber Bundle Reader") +{ + Options defaultOptions; + defaultOptions["Save as binary file"] = true; + defaultOptions["Save color information"] = true; + defaultOptions["Save fiber weights"] = true; + this->SetDefaultOptions(defaultOptions); + RegisterService(); +} + +mitk::FiberBundleVtkWriter::FiberBundleVtkWriter(const mitk::FiberBundleVtkWriter & other) + :mitk::AbstractFileWriter(other) +{} + +mitk::FiberBundleVtkWriter::~FiberBundleVtkWriter() +{} + +mitk::FiberBundleVtkWriter * mitk::FiberBundleVtkWriter::Clone() const +{ + return new mitk::FiberBundleVtkWriter(*this); +} + +void mitk::FiberBundleVtkWriter::Write() +{ + + std::ostream* out; + std::ofstream outStream; + + if( this->GetOutputStream() ) + { + out = this->GetOutputStream(); + }else{ + outStream.open( this->GetOutputLocation().c_str() ); + out = &outStream; + } + + if ( !out->good() ) + { + mitkThrow() << "Stream not good."; + } + + try + { + const std::string& locale = "C"; + const std::string& currLocale = setlocale( LC_ALL, NULL ); + setlocale(LC_ALL, locale.c_str()); + + std::locale previousLocale(out->getloc()); + std::locale I("C"); + out->imbue(I); + + std::string filename = this->GetOutputLocation().c_str(); + + mitk::FiberBundle::ConstPointer input = dynamic_cast(this->GetInput()); + std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->GetOutputLocation().c_str()); + Options options = this->GetOptions(); + + vtkSmartPointer fibPoly = input->GetFiberPolyData(); + if (us::any_cast(options["Save fiber weights"])) + { + MITK_INFO << "Adding fiber weight information"; + fibPoly->GetCellData()->AddArray(input->GetFiberWeights()); + } + else if (fibPoly->GetCellData()->HasArray("FIBER_WEIGHTS")) + fibPoly->GetCellData()->RemoveArray("FIBER_WEIGHTS"); + if (us::any_cast(options["Save color information"])) + { + MITK_INFO << "Adding color information"; + fibPoly->GetPointData()->AddArray(input->GetFiberColors()); + } + else if (fibPoly->GetPointData()->HasArray("FIBER_COLORS")) + fibPoly->GetPointData()->RemoveArray("FIBER_COLORS"); + + // default extension is .fib + if(ext == "") + { + ext = ".fib"; + this->SetOutputLocation(this->GetOutputLocation() + ext); + } + + vtkSmartPointer writer = vtkSmartPointer::New(); + writer->SetInputData(fibPoly); + writer->SetFileName(filename.c_str()); + if (us::any_cast(options["Save as binary file"])) + { + MITK_INFO << "Writing fiber bundle as vtk binary file"; + writer->SetFileTypeToBinary(); + } + else + { + MITK_INFO << "Writing fiber bundle as vtk ascii file"; + writer->SetFileTypeToASCII(); + } + writer->Write(); + + setlocale(LC_ALL, currLocale.c_str()); + MITK_INFO << "Fiber bundle written"; + } + catch(...) + { + throw; + } +} diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXWriter.h b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleVtkWriter.h similarity index 84% rename from Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXWriter.h rename to Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleVtkWriter.h index e7c7194e03..bd44ba9d36 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXWriter.h +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleVtkWriter.h @@ -1,118 +1,118 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef __mitkFiberBundleXWriter_h -#define __mitkFiberBundleXWriter_h +#ifndef __mitkFiberBundleVtkWriter_h +#define __mitkFiberBundleVtkWriter_h #include -#include "mitkFiberBundleX.h" +#include "mitkFiberBundle.h" #include namespace mitk { /** * Writes fiber bundles to a file * @ingroup Process */ -class FiberBundleXWriter : public mitk::AbstractFileWriter +class FiberBundleVtkWriter : public mitk::AbstractFileWriter { public: - FiberBundleXWriter(); - FiberBundleXWriter(const FiberBundleXWriter & other); - virtual FiberBundleXWriter * Clone() const; - virtual ~FiberBundleXWriter(); + FiberBundleVtkWriter(); + FiberBundleVtkWriter(const FiberBundleVtkWriter & other); + virtual FiberBundleVtkWriter * Clone() const; + virtual ~FiberBundleVtkWriter(); using mitk::AbstractFileWriter::Write; virtual void Write(); static const char* XML_GEOMETRY; static const char* XML_MATRIX_XX; static const char* XML_MATRIX_XY; static const char* XML_MATRIX_XZ; static const char* XML_MATRIX_YX; static const char* XML_MATRIX_YY; static const char* XML_MATRIX_YZ; static const char* XML_MATRIX_ZX; static const char* XML_MATRIX_ZY; static const char* XML_MATRIX_ZZ; static const char* XML_ORIGIN_X; static const char* XML_ORIGIN_Y; static const char* XML_ORIGIN_Z; static const char* XML_SPACING_X; static const char* XML_SPACING_Y; static const char* XML_SPACING_Z; static const char* XML_SIZE_X; static const char* XML_SIZE_Y; static const char* XML_SIZE_Z; static const char* XML_FIBER_BUNDLE; static const char* XML_FIBER; static const char* XML_PARTICLE; static const char* XML_ID; static const char* XML_POS_X; static const char* XML_POS_Y; static const char* XML_POS_Z; static const char* VERSION_STRING; static const char* XML_FIBER_BUNDLE_FILE; static const char* XML_FILE_VERSION; static const char* XML_NUM_FIBERS; static const char* XML_NUM_PARTICLES; static const char* ASCII_FILE; static const char* FILE_NAME; }; } // end of namespace mitk -#endif //__mitkFiberBundleXWriter_h +#endif //__mitkFiberBundleWriter_h diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXWriter.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXWriter.cpp deleted file mode 100644 index 987d8f75fc..0000000000 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleXWriter.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - -#include "mitkFiberBundleXWriter.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mitkDiffusionIOMimeTypes.h" - -mitk::FiberBundleXWriter::FiberBundleXWriter() - : mitk::AbstractFileWriter(mitk::FiberBundleX::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_MIMETYPE() ), mitk::DiffusionIOMimeTypes::FIBERBUNDLE_MIMETYPE_DESCRIPTION()) -{ - RegisterService(); -} - -mitk::FiberBundleXWriter::FiberBundleXWriter(const mitk::FiberBundleXWriter & other) - :mitk::AbstractFileWriter(other) -{} - -mitk::FiberBundleXWriter::~FiberBundleXWriter() -{} - -mitk::FiberBundleXWriter * mitk::FiberBundleXWriter::Clone() const -{ - return new mitk::FiberBundleXWriter(*this); -} - -void mitk::FiberBundleXWriter::Write() -{ - - std::ostream* out; - std::ofstream outStream; - - if( this->GetOutputStream() ) - { - out = this->GetOutputStream(); - }else{ - outStream.open( this->GetOutputLocation().c_str() ); - out = &outStream; - } - - if ( !out->good() ) - { - mitkThrow() << "Stream not good."; - } - - try - { - const std::string& locale = "C"; - const std::string& currLocale = setlocale( LC_ALL, NULL ); - setlocale(LC_ALL, locale.c_str()); - - - std::locale previousLocale(out->getloc()); - std::locale I("C"); - out->imbue(I); - - std::string filename = this->GetOutputLocation().c_str(); - - mitk::FiberBundleX::ConstPointer input = dynamic_cast(this->GetInput()); - std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->GetOutputLocation().c_str()); - - vtkSmartPointer fibPoly = input->GetFiberPolyData(); - fibPoly->GetCellData()->AddArray(input->GetFiberWeights()); - fibPoly->GetPointData()->AddArray(input->GetFiberColors()); - - // default extension is .fib - if(ext == "") - { - ext = ".fib"; - this->SetOutputLocation(this->GetOutputLocation() + ext); - } - - if (ext==".fib" || ext==".vtk") - { - MITK_INFO << "Writing fiber bundle as binary VTK"; - vtkSmartPointer writer = vtkSmartPointer::New(); - writer->SetInputData(fibPoly); - writer->SetFileName(filename.c_str()); - writer->SetFileTypeToBinary(); - writer->Write(); - } - else if (ext==".afib") - { - itksys::SystemTools::ReplaceString(filename,".afib",".fib"); - MITK_INFO << "Writing fiber bundle as ascii VTK"; - vtkSmartPointer writer = vtkSmartPointer::New(); - writer->SetInputData(fibPoly); - writer->SetFileName(filename.c_str()); - writer->SetFileTypeToASCII(); - writer->Write(); - } - else if (ext==".avtk") - { - itksys::SystemTools::ReplaceString(filename,".avtk",".vtk"); - MITK_INFO << "Writing fiber bundle as ascii VTK"; - vtkSmartPointer writer = vtkSmartPointer::New(); - writer->SetInputData(fibPoly); - writer->SetFileName(filename.c_str()); - writer->SetFileTypeToASCII(); - writer->Write(); - } - else if (ext==".trk") - { - MITK_INFO << "Writing fiber bundle as TRK"; - TrackVisFiberReader trk; - trk.create(filename, input.GetPointer()); - trk.writeHdr(); - trk.append(input.GetPointer()); - } - - setlocale(LC_ALL, currLocale.c_str()); - MITK_INFO << "Fiber bundle written"; - } - catch(...) - { - throw; - } -} diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberTrackingObjectFactory.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberTrackingObjectFactory.cpp index cb78e2f291..a3ccbf6e60 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberTrackingObjectFactory.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberTrackingObjectFactory.cpp @@ -1,114 +1,114 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkFiberTrackingObjectFactory.h" mitk::FiberTrackingObjectFactory::FiberTrackingObjectFactory() : CoreObjectFactoryBase() { } mitk::FiberTrackingObjectFactory::~FiberTrackingObjectFactory() { } mitk::Mapper::Pointer mitk::FiberTrackingObjectFactory::CreateMapper(mitk::DataNode* node, MapperSlotId id) { mitk::Mapper::Pointer newMapper=NULL; if ( id == mitk::BaseRenderer::Standard2D ) { - std::string classname("FiberBundleX"); + std::string classname("FiberBundle"); if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { - newMapper = mitk::FiberBundleXMapper2D::New(); + newMapper = mitk::FiberBundleMapper2D::New(); newMapper->SetDataNode(node); } } else if ( id == mitk::BaseRenderer::Standard3D ) { - std::string classname("FiberBundleX"); + std::string classname("FiberBundle"); if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { - newMapper = mitk::FiberBundleXMapper3D::New(); + newMapper = mitk::FiberBundleMapper3D::New(); newMapper->SetDataNode(node); } } return newMapper; } void mitk::FiberTrackingObjectFactory::SetDefaultProperties(mitk::DataNode* node) { - std::string classname("FiberBundleX"); + std::string classname("FiberBundle"); if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { - mitk::FiberBundleXMapper3D::SetDefaultProperties(node); - mitk::FiberBundleXMapper2D::SetDefaultProperties(node); + mitk::FiberBundleMapper3D::SetDefaultProperties(node); + mitk::FiberBundleMapper2D::SetDefaultProperties(node); } } const char* mitk::FiberTrackingObjectFactory::GetFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_FileExtensionsMap, fileExtension); return fileExtension.c_str(); } mitk::CoreObjectFactoryBase::MultimapType mitk::FiberTrackingObjectFactory::GetFileExtensionsMap() { return m_FileExtensionsMap; } const char* mitk::FiberTrackingObjectFactory::GetSaveFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_SaveFileExtensionsMap, fileExtension); return fileExtension.c_str(); } mitk::CoreObjectFactoryBase::MultimapType mitk::FiberTrackingObjectFactory::GetSaveFileExtensionsMap() { return m_SaveFileExtensionsMap; } void mitk::FiberTrackingObjectFactory::CreateFileExtensionsMap() { } void mitk::FiberTrackingObjectFactory::RegisterIOFactories() { } struct RegisterFiberTrackingObjectFactory{ RegisterFiberTrackingObjectFactory() : m_Factory( mitk::FiberTrackingObjectFactory::New() ) { mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory( m_Factory ); } ~RegisterFiberTrackingObjectFactory() { mitk::CoreObjectFactory::GetInstance()->UnRegisterExtraFactory( m_Factory ); } mitk::FiberTrackingObjectFactory::Pointer m_Factory; }; static RegisterFiberTrackingObjectFactory registerFiberTrackingObjectFactory; diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberTrackingObjectFactory.h b/Modules/DiffusionImaging/DiffusionIO/mitkFiberTrackingObjectFactory.h index b26f470e1b..0c0806e8c2 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberTrackingObjectFactory.h +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberTrackingObjectFactory.h @@ -1,70 +1,70 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKFIBERTRACKINGOBJECTFACTORY_H #define MITKFIBERTRACKINGOBJECTFACTORY_H #include "mitkCoreObjectFactory.h" //modernized fiberbundle datastrucutre -#include "mitkFiberBundleX.h" -#include "mitkFiberBundleXMapper3D.h" -#include "mitkFiberBundleXMapper2D.h" +#include "mitkFiberBundle.h" +#include "mitkFiberBundleMapper3D.h" +#include "mitkFiberBundleMapper2D.h" -//#include "mitkFiberBundleXThreadMonitorMapper3D.h" -//#include "mitkFiberBundleXThreadMonitor.h" +//#include "mitkFiberBundleThreadMonitorMapper3D.h" +//#include "mitkFiberBundleThreadMonitor.h" namespace mitk { class FiberTrackingObjectFactory : public CoreObjectFactoryBase { public: mitkClassMacro(FiberTrackingObjectFactory,CoreObjectFactoryBase) itkFactorylessNewMacro(Self) itkCloneMacro(Self) ~FiberTrackingObjectFactory(); virtual Mapper::Pointer CreateMapper(mitk::DataNode* node, MapperSlotId slotId); virtual void SetDefaultProperties(mitk::DataNode* node); virtual const char* GetFileExtensions(); virtual mitk::CoreObjectFactoryBase::MultimapType GetFileExtensionsMap(); virtual const char* GetSaveFileExtensions(); virtual mitk::CoreObjectFactoryBase::MultimapType GetSaveFileExtensionsMap(); void RegisterIOFactories(); protected: FiberTrackingObjectFactory(); private: void CreateFileExtensionsMap(); std::string m_ExternalFileExtensions; std::string m_InternalFileExtensions; std::string m_SaveFileExtensions; MultimapType m_FileExtensionsMap; MultimapType m_SaveFileExtensionsMap; }; } #endif // MITKFIBERTRACKINGOBJECTFACTORY_H diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkEvaluateTractogramDirectionsFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkEvaluateTractogramDirectionsFilter.h index a54a2cb1b9..47f590315a 100755 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkEvaluateTractogramDirectionsFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkEvaluateTractogramDirectionsFilter.h @@ -1,108 +1,108 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /*=================================================================== This file is based heavily on a corresponding ITK filter. ===================================================================*/ #ifndef __itkEvaluateTractogramDirectionsFilter_h_ #define __itkEvaluateTractogramDirectionsFilter_h_ #include #include -#include +#include #include namespace itk{ /** \brief Calculates the voxel-wise angular error of the input tractogram to a set of voxel-wise directions. */ template< class PixelType > class EvaluateTractogramDirectionsFilter : public ImageSource< Image< PixelType, 3 > > { public: typedef EvaluateTractogramDirectionsFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ImageSource< Image< PixelType, 3 > > Superclass; typedef typename Superclass::OutputImageRegionType OutputImageRegionType; typedef typename Superclass::OutputImageType OutputImageType; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Runtime information support. */ itkTypeMacro(EvaluateTractogramDirectionsFilter, ImageToImageFilter) - typedef mitk::FiberBundleX FiberBundleType; + typedef mitk::FiberBundle FiberBundleType; typedef Vector< float, 3 > DirectionType; typedef Image< DirectionType, 3 > DirectionImageType; typedef VectorContainer< int, DirectionImageType::Pointer > DirectionImageContainerType; typedef Image< float, 3 > FloatImageType; typedef Image< bool, 3 > BoolImageType; typedef Image< unsigned char, 3 > UCharImageType; typedef Image< double, 3 > DoubleImageType; itkSetMacro( Tractogram, FiberBundleType::Pointer) ///< Input tractogram itkSetMacro( ReferenceImageSet , DirectionImageContainerType::Pointer) ///< Input images containing one reference direction per voxel. itkSetMacro( MaskImage , UCharImageType::Pointer) ///< Calculation is only performed inside of the mask image. itkSetMacro( IgnoreMissingDirections , bool) ///< If in one voxel, the number of directions differs between the input tractogram and the reference, the excess directions are ignored. Otherwise, the error to the next closest direction is calculated. itkSetMacro( UseInterpolation , bool) ///< Use trilinear interpolation. /** Output statistics. */ itkGetMacro( MeanAngularError, float) itkGetMacro( MinAngularError, float) itkGetMacro( MaxAngularError, float) itkGetMacro( VarAngularError, float) itkGetMacro( MedianAngularError, float) protected: EvaluateTractogramDirectionsFilter(); ~EvaluateTractogramDirectionsFilter() {} void GenerateData(); itk::Point GetItkPoint(double point[3]); itk::Vector GetItkVector(double point[3]); vnl_vector_fixed GetVnlVector(double point[3]); vnl_vector_fixed GetVnlVector(Vector< PixelType, 3 >& vector); UCharImageType::Pointer m_MaskImage; DirectionImageContainerType::Pointer m_ReferenceImageSet; bool m_IgnoreMissingDirections; double m_MeanAngularError; double m_MedianAngularError; double m_MaxAngularError; double m_MinAngularError; double m_VarAngularError; std::vector< double > m_AngularErrorVector; double m_Eps; FiberBundleType::Pointer m_Tractogram; bool m_UseInterpolation; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkEvaluateTractogramDirectionsFilter.cpp" #endif #endif //__itkEvaluateTractogramDirectionsFilter_h_ diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFiberCurvatureFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFiberCurvatureFilter.cpp index 883473377c..81ebca3171 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFiberCurvatureFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFiberCurvatureFilter.cpp @@ -1,147 +1,147 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "itkFiberCurvatureFilter.h" #define _USE_MATH_DEFINES #include #include #include #include namespace itk{ FiberCurvatureFilter::FiberCurvatureFilter() : m_AngularDeviation(20) , m_Distance(1.0) , m_RemoveFibers(false) { } FiberCurvatureFilter::~FiberCurvatureFilter() { } void FiberCurvatureFilter::GenerateData() { vtkSmartPointer inputPoly = m_InputFiberBundle->GetFiberPolyData(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Applying curvature threshold"; boost::progress_display disp(inputPoly->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp; vtkCell* cell = inputPoly->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; j > vectors; vnl_vector_fixed< float, 3 > meanV; while(dist1) { double p1[3]; points->GetPoint(c-1, p1); double p2[3]; points->GetPoint(c, p2); vnl_vector_fixed< float, 3 > v; v[0] = p2[0]-p1[0]; v[1] = p2[1]-p1[1]; v[2] = p2[2]-p1[2]; dist += v.magnitude(); v.normalize(); vectors.push_back(v); meanV += v; c--; } c = j; dist = 0; while(distGetPoint(c, p1); double p2[3]; points->GetPoint(c+1, p2); vnl_vector_fixed< float, 3 > v; v[0] = p2[0]-p1[0]; v[1] = p2[1]-p1[1]; v[2] = p2[2]-p1[2]; dist += v.magnitude(); v.normalize(); vectors.push_back(v); meanV += v; c++; } meanV.normalize(); double dev = 0; for (int c=0; c1.0) angle = 1.0; if (angle<0.0) angle = 0.0; dev += acos(angle)*180/M_PI; } if (vectors.size()>0) dev /= vectors.size(); if (devGetPoint(j, p); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } else { if (m_RemoveFibers) { container = vtkSmartPointer::New(); break; } if (container->GetNumberOfPoints()>0) vtkNewCells->InsertNextCell(container); container = vtkSmartPointer::New(); } } if (container->GetNumberOfPoints()>0) vtkNewCells->InsertNextCell(container); } vtkSmartPointer outputPoly = vtkSmartPointer::New(); outputPoly->SetPoints(vtkNewPoints); outputPoly->SetLines(vtkNewCells); - m_OutputFiberBundle = FiberBundleX::New(outputPoly); + m_OutputFiberBundle = FiberBundle::New(outputPoly); } } diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFiberCurvatureFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFiberCurvatureFilter.h index 3230a2675b..eeeb588d60 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFiberCurvatureFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFiberCurvatureFilter.h @@ -1,83 +1,83 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef itkFiberCurvatureFilter_h #define itkFiberCurvatureFilter_h // MITK #include -#include +#include #include // ITK #include // VTK #include #include #include #include #include using namespace std; namespace itk{ /** * \brief Generates artificial fibers distributed in and interpolated between the input planar figures. */ class FiberCurvatureFilter : public ProcessObject { public: typedef FiberCurvatureFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkTypeMacro( FiberCurvatureFilter, ProcessObject ) virtual void Update(){ this->GenerateData(); } itkSetMacro( Distance, double ) itkSetMacro( AngularDeviation, double ) itkSetMacro( RemoveFibers, bool ) - itkSetMacro( InputFiberBundle, FiberBundleX::Pointer ) - itkGetMacro( OutputFiberBundle, FiberBundleX::Pointer ) + itkSetMacro( InputFiberBundle, FiberBundle::Pointer ) + itkGetMacro( OutputFiberBundle, FiberBundle::Pointer ) protected: void GenerateData(); FiberCurvatureFilter(); virtual ~FiberCurvatureFilter(); - FiberBundleX::Pointer m_InputFiberBundle; - FiberBundleX::Pointer m_OutputFiberBundle; + FiberBundle::Pointer m_InputFiberBundle; + FiberBundle::Pointer m_OutputFiberBundle; double m_AngularDeviation; double m_Distance; bool m_RemoveFibers; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkFiberCurvatureFilter.cpp" #endif #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFibersFromPlanarFiguresFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFibersFromPlanarFiguresFilter.cpp index 41eaac38e2..6d2506664a 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFibersFromPlanarFiguresFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFibersFromPlanarFiguresFilter.cpp @@ -1,241 +1,241 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "itkFibersFromPlanarFiguresFilter.h" #define _USE_MATH_DEFINES #include // MITK #include #include #include #include #include #include #include #include #include // ITK #include #include #include #include // MISC #include namespace itk{ FibersFromPlanarFiguresFilter::FibersFromPlanarFiguresFilter() { } FibersFromPlanarFiguresFilter::~FibersFromPlanarFiguresFilter() { } void FibersFromPlanarFiguresFilter::GeneratePoints() { Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New(); randGen->SetSeed((unsigned int)0); m_2DPoints.clear(); int count = 0; while (count < m_Parameters.m_Density) { mitk::Vector2D p; switch (m_Parameters.m_Distribution) { case FiberGenerationParameters::DISTRIBUTE_GAUSSIAN: p[0] = randGen->GetNormalVariate(0, m_Parameters.m_Variance); p[1] = randGen->GetNormalVariate(0, m_Parameters.m_Variance); break; default: p[0] = randGen->GetUniformVariate(-1, 1); p[1] = randGen->GetUniformVariate(-1, 1); } if (sqrt(p[0]*p[0]+p[1]*p[1]) <= 1) { m_2DPoints.push_back(p); count++; } } } void FibersFromPlanarFiguresFilter::GenerateData() { // check if enough fiducials are available for (unsigned int i=0; i m_VtkCellArray = vtkSmartPointer::New(); vtkSmartPointer m_VtkPoints = vtkSmartPointer::New(); vector< mitk::PlanarEllipse::Pointer > bundle = m_Parameters.m_Fiducials.at(i); vector< unsigned int > fliplist; if (i container = vtkSmartPointer::New(); mitk::PlanarEllipse::Pointer figure = bundle.at(0); mitk::Point2D p0 = figure->GetControlPoint(0); mitk::Point2D p1 = figure->GetControlPoint(1); mitk::Point2D p2 = figure->GetControlPoint(2); mitk::Point2D p3 = figure->GetControlPoint(3); double r1 = p0.EuclideanDistanceTo(p1); double r2 = p0.EuclideanDistanceTo(p2); mitk::Vector2D eDir = p1-p0; eDir.Normalize(); mitk::Vector2D tDir = p3-p0; tDir.Normalize(); // apply twist vnl_matrix_fixed tRot; tRot[0][0] = tDir[0]; tRot[1][1] = tRot[0][0]; tRot[1][0] = sin(acos(tRot[0][0])); tRot[0][1] = -tRot[1][0]; if (tDir[1]<0) tRot.inplace_transpose(); m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector()); // apply new ellipse shape vnl_vector_fixed< double, 2 > newP; newP[0] = m_2DPoints.at(j)[0]; newP[1] = m_2DPoints.at(j)[1]; double alpha = acos(eDir[0]); if (eDir[1]>0) alpha = 2*M_PI-alpha; vnl_matrix_fixed eRot; eRot[0][0] = cos(alpha); eRot[1][1] = eRot[0][0]; eRot[1][0] = sin(alpha); eRot[0][1] = -eRot[1][0]; newP = eRot*newP; newP[0] *= r1; newP[1] *= r2; newP = eRot.transpose()*newP; p0[0] += newP[0]; p0[1] += newP[1]; const mitk::PlaneGeometry* planeGeo = figure->GetPlaneGeometry(); mitk::Point3D w, wc; planeGeo->Map(p0, w); wc = figure->GetWorldControlPoint(0); vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer()); container->GetPointIds()->InsertNextId(id); vnl_vector_fixed< double, 3 > n = planeGeo->GetNormalVnl(); for (unsigned int k=1; kGetControlPoint(0); p1 = figure->GetControlPoint(1); p2 = figure->GetControlPoint(2); p3 = figure->GetControlPoint(3); r1 = p0.EuclideanDistanceTo(p1); r2 = p0.EuclideanDistanceTo(p2); eDir = p1-p0; eDir.Normalize(); mitk::Vector2D tDir2 = p3-p0; tDir2.Normalize(); mitk::Vector2D temp; temp.SetVnlVector(tRot.transpose() * tDir2.GetVnlVector()); // apply twist tRot[0][0] = tDir[0]*tDir2[0] + tDir[1]*tDir2[1]; tRot[1][1] = tRot[0][0]; tRot[1][0] = sin(acos(tRot[0][0])); tRot[0][1] = -tRot[1][0]; if (temp[1]<0) tRot.inplace_transpose(); m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector()); tDir = tDir2; // apply new ellipse shape newP[0] = m_2DPoints.at(j)[0]; newP[1] = m_2DPoints.at(j)[1]; // calculate normal mitk::PlaneGeometry* planeGeo = const_cast(figure->GetPlaneGeometry()); mitk::Vector3D perp = wc-planeGeo->ProjectPointOntoPlane(wc); perp.Normalize(); vnl_vector_fixed< double, 3 > n2 = planeGeo->GetNormalVnl(); wc = figure->GetWorldControlPoint(0); // is flip needed? if (dot_product(perp.GetVnlVector(),n2)>0 && dot_product(n,n2)<=0.00001) newP[0] *= -1; if (fliplist.at(k)>0) newP[0] *= -1; n = n2; alpha = acos(eDir[0]); if (eDir[1]>0) alpha = 2*M_PI-alpha; eRot[0][0] = cos(alpha); eRot[1][1] = eRot[0][0]; eRot[1][0] = sin(alpha); eRot[0][1] = -eRot[1][0]; newP = eRot*newP; newP[0] *= r1; newP[1] *= r2; newP = eRot.transpose()*newP; p0[0] += newP[0]; p0[1] += newP[1]; mitk::Point3D w; planeGeo->Map(p0, w); vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer()); container->GetPointIds()->InsertNextId(id); } m_VtkCellArray->InsertNextCell(container); } vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); fiberPolyData->SetPoints(m_VtkPoints); fiberPolyData->SetLines(m_VtkCellArray); - mitk::FiberBundleX::Pointer mitkFiberBundle = mitk::FiberBundleX::New(fiberPolyData); + mitk::FiberBundle::Pointer mitkFiberBundle = mitk::FiberBundle::New(fiberPolyData); mitkFiberBundle->ResampleSpline(m_Parameters.m_Sampling, m_Parameters.m_Tension, m_Parameters.m_Continuity, m_Parameters.m_Bias); m_FiberBundles.push_back(mitkFiberBundle); } } } diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFibersFromPlanarFiguresFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFibersFromPlanarFiguresFilter.h index f7e9451f76..3e6c0c0809 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFibersFromPlanarFiguresFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFibersFromPlanarFiguresFilter.h @@ -1,87 +1,87 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef itkFibersFromPlanarFiguresFilter_h #define itkFibersFromPlanarFiguresFilter_h // MITK #include -#include +#include #include // ITK #include // VTK #include #include #include #include #include using namespace std; namespace itk{ /** * \brief Generates artificial fibers distributed in and interpolated between the input planar figures. */ class FibersFromPlanarFiguresFilter : public ProcessObject { public: typedef FibersFromPlanarFiguresFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; - typedef mitk::FiberBundleX::Pointer FiberType; - typedef vector< mitk::FiberBundleX::Pointer > FiberContainerType; + typedef mitk::FiberBundle::Pointer FiberType; + typedef vector< mitk::FiberBundle::Pointer > FiberContainerType; itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkTypeMacro( FibersFromPlanarFiguresFilter, ProcessObject ) virtual void Update(){ this->GenerateData(); } // input void SetParameters( FiberGenerationParameters param ) ///< Simulation parameters. { m_Parameters = param; } // output FiberContainerType GetFiberBundles(){ return m_FiberBundles; } protected: void GenerateData(); FibersFromPlanarFiguresFilter(); virtual ~FibersFromPlanarFiguresFilter(); void GeneratePoints(); FiberContainerType m_FiberBundles; ///< container for the output fiber bundles vector< mitk::Vector2D > m_2DPoints; ///< container for the 2D fiber waypoints FiberGenerationParameters m_Parameters; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkFibersFromPlanarFiguresFilter.cpp" #endif #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractDensityImageFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractDensityImageFilter.h index b0e3724eed..fc9c23714e 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractDensityImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractDensityImageFilter.h @@ -1,87 +1,87 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkTractDensityImageFilter_h__ #define __itkTractDensityImageFilter_h__ #include #include #include #include -#include +#include namespace itk{ /** * \brief Generates tract density images from input fiberbundles (Calamante 2010). */ template< class OutputImageType > class TractDensityImageFilter : public ImageSource< OutputImageType > { public: typedef TractDensityImageFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef typename OutputImageType::PixelType OutPixelType; itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkTypeMacro( TractDensityImageFilter, ImageSource ) itkSetMacro( UpsamplingFactor, float) ///< use higher resolution for ouput image itkGetMacro( UpsamplingFactor, float) ///< use higher resolution for ouput image itkSetMacro( InvertImage, bool) ///< voxelvalue = 1-voxelvalue itkGetMacro( InvertImage, bool) ///< voxelvalue = 1-voxelvalue itkSetMacro( BinaryOutput, bool) ///< generate binary fiber envelope itkGetMacro( BinaryOutput, bool) ///< generate binary fiber envelope itkSetMacro( OutputAbsoluteValues, bool) ///< output absolute values of the number of fibers per voxel itkGetMacro( OutputAbsoluteValues, bool) ///< output absolute values of the number of fibers per voxel itkSetMacro( UseImageGeometry, bool) ///< use input image geometry to initialize output image itkGetMacro( UseImageGeometry, bool) ///< use input image geometry to initialize output image - itkSetMacro( FiberBundle, mitk::FiberBundleX::Pointer) ///< input fiber bundle + itkSetMacro( FiberBundle, mitk::FiberBundle::Pointer) ///< input fiber bundle itkSetMacro( InputImage, typename OutputImageType::Pointer) ///< use input image geometry to initialize output image itkSetMacro( UseTrilinearInterpolation, bool ) itkSetMacro( DoFiberResampling, bool ) void GenerateData(); protected: itk::Point GetItkPoint(double point[3]); TractDensityImageFilter(); virtual ~TractDensityImageFilter(); typename OutputImageType::Pointer m_InputImage; ///< use input image geometry to initialize output image - mitk::FiberBundleX::Pointer m_FiberBundle; ///< input fiber bundle + mitk::FiberBundle::Pointer m_FiberBundle; ///< input fiber bundle float m_UpsamplingFactor; ///< use higher resolution for ouput image bool m_InvertImage; ///< voxelvalue = 1-voxelvalue bool m_BinaryOutput; ///< generate binary fiber envelope bool m_UseImageGeometry; ///< use input image geometry to initialize output image bool m_OutputAbsoluteValues; ///< do not normalize image values to 0-1 bool m_UseTrilinearInterpolation; bool m_DoFiberResampling; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkTractDensityImageFilter.cpp" #endif #endif // __itkTractDensityImageFilter_h__ diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h index c284489d44..ee42dfddc7 100755 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h @@ -1,131 +1,131 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkTractsToDWIImageFilter_h__ #define __itkTractsToDWIImageFilter_h__ -#include +#include #include #include #include #include #include #include #include namespace itk { /** * \brief Generates artificial diffusion weighted image volume from the input fiberbundle using a generic multicompartment model. * See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details. */ template< class PixelType > class TractsToDWIImageFilter : public ImageSource< itk::VectorImage< PixelType, 3 > > { public: typedef TractsToDWIImageFilter Self; typedef ImageSource< itk::VectorImage< PixelType, 3 > > Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef typename Superclass::OutputImageType OutputImageType; typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkUcharImgType; - typedef mitk::FiberBundleX::Pointer FiberBundleType; + typedef mitk::FiberBundle::Pointer FiberBundleType; typedef itk::VectorImage< double, 3 > DoubleDwiType; typedef itk::Matrix MatrixType; typedef itk::Image< double, 2 > SliceType; typedef itk::VnlForwardFFTImageFilter::OutputImageType ComplexSliceType; typedef itk::Vector< double,3> DoubleVectorType; itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkTypeMacro( TractsToDWIImageFilter, ImageSource ) /** Input */ itkSetMacro( FiberBundle, FiberBundleType ) ///< Input fiber bundle itkSetMacro( UseConstantRandSeed, bool ) ///< Seed for random generator. void SetParameters( FiberfoxParameters param ) ///< Simulation parameters. { m_Parameters = param; } /** Output */ FiberfoxParameters GetParameters(){ return m_Parameters; } std::vector< ItkDoubleImgType::Pointer > GetVolumeFractions() ///< one double image for each compartment containing the corresponding volume fraction per voxel { return m_VolumeFractions; } mitk::LevelWindow GetLevelWindow(){ return m_LevelWindow; } itkGetMacro( StatusText, std::string ) void GenerateData(); protected: TractsToDWIImageFilter(); virtual ~TractsToDWIImageFilter(); itk::Point GetItkPoint(double point[3]); itk::Vector GetItkVector(double point[3]); vnl_vector_fixed GetVnlVector(double point[3]); vnl_vector_fixed GetVnlVector(Vector< float, 3 >& vector); double RoundToNearest(double num); std::string GetTime(); /** Transform generated image compartment by compartment, channel by channel and slice by slice using DFT and add k-space artifacts. */ DoubleDwiType::Pointer DoKspaceStuff(std::vector< DoubleDwiType::Pointer >& images); /** Generate signal of non-fiber compartments. */ void SimulateNonFiberSignal(ItkUcharImgType::IndexType index, double intraAxonalVolume, int g=-1); /** Move fibers to simulate headmotion */ void SimulateMotion(int g=-1); // input mitk::FiberfoxParameters m_Parameters; FiberBundleType m_FiberBundle; // output mitk::LevelWindow m_LevelWindow; std::vector< ItkDoubleImgType::Pointer > m_VolumeFractions; std::string m_StatusText; // MISC itk::TimeProbe m_TimeProbe; bool m_UseConstantRandSeed; bool m_MaskImageSet; ofstream m_Logfile; // signal generation FiberBundleType m_FiberBundleWorkingCopy; ///< we work on an upsampled version of the input bundle FiberBundleType m_FiberBundleTransformed; ///< transformed bundle simulating headmotion itk::Vector m_UpsampledSpacing; itk::Point m_UpsampledOrigin; ImageRegion<3> m_UpsampledImageRegion; double m_VoxelVolume; std::vector< DoubleDwiType::Pointer > m_CompartmentImages; ItkUcharImgType::Pointer m_MaskImage; ///< copy of mask image (changes for each motion step) ItkUcharImgType::Pointer m_UpsampledMaskImage; ///< helper image for motion simulation DoubleVectorType m_Rotation; DoubleVectorType m_Translation; itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandGen; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkTractsToDWIImageFilter.cpp" #endif #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToFiberEndingsImageFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToFiberEndingsImageFilter.h index 74cf06930d..4687fb80fa 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToFiberEndingsImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToFiberEndingsImageFilter.h @@ -1,86 +1,86 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkTractsToFiberEndingsImageFilter_h__ #define __itkTractsToFiberEndingsImageFilter_h__ #include #include #include #include -#include +#include namespace itk{ /** * \brief Generates image where the pixel values are set according to the number of fibers ending in the voxel. */ template< class OutputImageType > class TractsToFiberEndingsImageFilter : public ImageSource< OutputImageType > { public: typedef TractsToFiberEndingsImageFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef typename OutputImageType::PixelType OutPixelType; itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkTypeMacro( TractsToFiberEndingsImageFilter, ImageSource ) /** Upsampling factor **/ itkSetMacro( UpsamplingFactor, float) itkGetMacro( UpsamplingFactor, float) /** Invert Image **/ itkSetMacro( InvertImage, bool) itkGetMacro( InvertImage, bool) - itkSetMacro( FiberBundle, mitk::FiberBundleX::Pointer) + itkSetMacro( FiberBundle, mitk::FiberBundle::Pointer) itkSetMacro( InputImage, typename OutputImageType::Pointer) /** Use input image geometry to initialize output image **/ itkSetMacro( UseImageGeometry, bool) itkGetMacro( UseImageGeometry, bool) itkSetMacro( BinaryOutput, bool) void GenerateData(); protected: itk::Point GetItkPoint(double point[3]); TractsToFiberEndingsImageFilter(); virtual ~TractsToFiberEndingsImageFilter(); - mitk::FiberBundleX::Pointer m_FiberBundle; ///< input fiber bundle + mitk::FiberBundle::Pointer m_FiberBundle; ///< input fiber bundle float m_UpsamplingFactor; ///< use higher resolution for ouput image bool m_InvertImage; ///< voxelvalue = 1-voxelvalue bool m_UseImageGeometry; ///< output image is given other geometry than fiberbundle (input image geometry) bool m_BinaryOutput; typename OutputImageType::Pointer m_InputImage; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkTractsToFiberEndingsImageFilter.cpp" #endif #endif // __itkTractsToFiberEndingsImageFilter_h__ diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToRgbaImageFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToRgbaImageFilter.h index 9571a150e1..29a3aa3393 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToRgbaImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToRgbaImageFilter.h @@ -1,80 +1,80 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkTractsToRgbaImageFilter_h__ #define __itkTractsToRgbaImageFilter_h__ #include #include #include #include -#include +#include namespace itk{ /** * \brief Generates RGBA image from the input fibers where color values are set according to the local fiber directions. */ template< class OutputImageType > class TractsToRgbaImageFilter : public ImageSource< OutputImageType > { public: typedef TractsToRgbaImageFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef typename OutputImageType::PixelType OutPixelType; typedef itk::Image InputImageType; itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkTypeMacro( TractsToRgbaImageFilter, ImageSource ) /** Upsampling factor **/ itkSetMacro( UpsamplingFactor, float) itkGetMacro( UpsamplingFactor, float) - itkSetMacro( FiberBundle, mitk::FiberBundleX::Pointer) + itkSetMacro( FiberBundle, mitk::FiberBundle::Pointer) itkSetMacro( InputImage, typename InputImageType::Pointer) /** Use input image geometry to initialize output image **/ itkSetMacro( UseImageGeometry, bool) itkGetMacro( UseImageGeometry, bool) void GenerateData(); protected: itk::Point GetItkPoint(double point[3]); TractsToRgbaImageFilter(); virtual ~TractsToRgbaImageFilter(); - mitk::FiberBundleX::Pointer m_FiberBundle; ///< input fiber bundle + mitk::FiberBundle::Pointer m_FiberBundle; ///< input fiber bundle float m_UpsamplingFactor; ///< use higher resolution for ouput image bool m_UseImageGeometry; ///< output image is given other geometry than fiberbundle (input image geometry) typename InputImageType::Pointer m_InputImage; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkTractsToRgbaImageFilter.cpp" #endif #endif // __itkTractsToRgbaImageFilter_h__ diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.cpp index ad60351fb8..4d434011cb 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.cpp @@ -1,565 +1,565 @@ #include "itkTractsToVectorImageFilter.h" // VTK #include #include #include // ITK #include #include // misc #define _USE_MATH_DEFINES #include #include namespace itk{ static bool CompareVectorLengths(const vnl_vector_fixed< double, 3 >& v1, const vnl_vector_fixed< double, 3 >& v2) { return (v1.magnitude()>v2.magnitude()); } template< class PixelType > TractsToVectorImageFilter< PixelType >::TractsToVectorImageFilter(): m_AngularThreshold(0.7), m_Epsilon(0.999), m_MaskImage(NULL), m_NormalizeVectors(false), m_UseWorkingCopy(true), m_MaxNumDirections(3), m_SizeThreshold(0.3), m_NumDirectionsImage(NULL), m_CreateDirectionImages(true) { this->SetNumberOfRequiredOutputs(1); } template< class PixelType > TractsToVectorImageFilter< PixelType >::~TractsToVectorImageFilter() { } template< class PixelType > vnl_vector_fixed TractsToVectorImageFilter< PixelType >::GetVnlVector(double point[]) { vnl_vector_fixed vnlVector; vnlVector[0] = point[0]; vnlVector[1] = point[1]; vnlVector[2] = point[2]; return vnlVector; } template< class PixelType > itk::Point TractsToVectorImageFilter< PixelType >::GetItkPoint(double point[]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } template< class PixelType > void TractsToVectorImageFilter< PixelType >::GenerateData() { mitk::BaseGeometry::Pointer geometry = m_FiberBundle->GetGeometry(); // calculate new image parameters itk::Vector spacing; itk::Point origin; itk::Matrix direction; ImageRegion<3> imageRegion; if (!m_MaskImage.IsNull()) { spacing = m_MaskImage->GetSpacing(); imageRegion = m_MaskImage->GetLargestPossibleRegion(); origin = m_MaskImage->GetOrigin(); direction = m_MaskImage->GetDirection(); } else { spacing = geometry->GetSpacing(); origin = geometry->GetOrigin(); mitk::BaseGeometry::BoundsArrayType bounds = geometry->GetBounds(); origin[0] += bounds.GetElement(0); origin[1] += bounds.GetElement(2); origin[2] += bounds.GetElement(4); 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)); m_MaskImage = ItkUcharImgType::New(); m_MaskImage->SetSpacing( spacing ); m_MaskImage->SetOrigin( origin ); m_MaskImage->SetDirection( direction ); m_MaskImage->SetRegions( imageRegion ); m_MaskImage->Allocate(); m_MaskImage->FillBuffer(1); } OutputImageType::RegionType::SizeType outImageSize = imageRegion.GetSize(); m_OutImageSpacing = m_MaskImage->GetSpacing(); m_ClusteredDirectionsContainer = ContainerType::New(); // initialize num directions image m_NumDirectionsImage = ItkUcharImgType::New(); m_NumDirectionsImage->SetSpacing( spacing ); m_NumDirectionsImage->SetOrigin( origin ); m_NumDirectionsImage->SetDirection( direction ); m_NumDirectionsImage->SetRegions( imageRegion ); m_NumDirectionsImage->Allocate(); m_NumDirectionsImage->FillBuffer(0); // initialize direction images m_DirectionImageContainer = DirectionImageContainerType::New(); // resample fiber bundle double minSpacing = 1; if(m_OutImageSpacing[0]GetDeepCopy(); // resample fiber bundle for sufficient voxel coverage m_FiberBundle->ResampleSpline(minSpacing/10); // iterate over all fibers vtkSmartPointer fiberPolyData = m_FiberBundle->GetFiberPolyData(); int numFibers = m_FiberBundle->GetNumFibers(); m_DirectionsContainer = ContainerType::New(); MITK_INFO << "Generating directions from tractogram"; boost::progress_display disp(numFibers); for( int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (numPoints<2) continue; vnl_vector_fixed dir; itk::Point worldPos; vnl_vector v; for( int j=0; jGetPoint(j); worldPos = GetItkPoint(temp); itk::Index<3> index; m_MaskImage->TransformPhysicalPointToIndex(worldPos, index); if (!m_MaskImage->GetLargestPossibleRegion().IsInside(index) || m_MaskImage->GetPixel(index)==0) continue; // get fiber tangent direction at this position v = GetVnlVector(temp); dir = GetVnlVector(points->GetPoint(j+1))-v; if (dir.is_zero()) continue; dir.normalize(); // add direction to container unsigned int idx = index[0] + outImageSize[0]*(index[1] + outImageSize[1]*index[2]); DirectionContainerType::Pointer dirCont; if (m_DirectionsContainer->IndexExists(idx)) { dirCont = m_DirectionsContainer->GetElement(idx); if (dirCont.IsNull()) { dirCont = DirectionContainerType::New(); dirCont->push_back(dir); m_DirectionsContainer->InsertElement(idx, dirCont); } else dirCont->push_back(dir); } else { dirCont = DirectionContainerType::New(); dirCont->push_back(dir); m_DirectionsContainer->InsertElement(idx, dirCont); } } } vtkSmartPointer m_VtkCellArray = vtkSmartPointer::New(); vtkSmartPointer m_VtkPoints = vtkSmartPointer::New(); itk::ImageRegionIterator dirIt(m_NumDirectionsImage, m_NumDirectionsImage->GetLargestPossibleRegion()); MITK_INFO << "Clustering directions"; boost::progress_display disp2(outImageSize[0]*outImageSize[1]*outImageSize[2]); while(!dirIt.IsAtEnd()) { ++disp2; OutputImageType::IndexType index = dirIt.GetIndex(); int idx = index[0]+(index[1]+index[2]*outImageSize[1])*outImageSize[0]; if (!m_DirectionsContainer->IndexExists(idx)) { ++dirIt; continue; } DirectionContainerType::Pointer dirCont = m_DirectionsContainer->GetElement(idx); if (dirCont.IsNull() || dirCont->empty()) { ++dirIt; continue; } std::vector< double > lengths; lengths.resize(dirCont->size(), 1); // all peaks have size 1 DirectionContainerType::Pointer directions; if (m_MaxNumDirections>0) { directions = FastClustering(dirCont, lengths); std::sort( directions->begin(), directions->end(), CompareVectorLengths ); } else directions = dirCont; unsigned int numDir = directions->size(); if (m_MaxNumDirections>0 && numDir>m_MaxNumDirections) numDir = m_MaxNumDirections; int count = 0; for (unsigned int i=0; i container = vtkSmartPointer::New(); itk::ContinuousIndex center; center[0] = index[0]; center[1] = index[1]; center[2] = index[2]; itk::Point worldCenter; m_MaskImage->TransformContinuousIndexToPhysicalPoint( center, worldCenter ); DirectionType dir = directions->at(i); if (dir.magnitude()size()) { ItkDirectionImageType::Pointer directionImage = ItkDirectionImageType::New(); directionImage->SetSpacing( spacing ); directionImage->SetOrigin( origin ); directionImage->SetDirection( direction ); directionImage->SetRegions( imageRegion ); directionImage->Allocate(); Vector< float, 3 > nullVec; nullVec.Fill(0.0); directionImage->FillBuffer(nullVec); m_DirectionImageContainer->InsertElement(i, directionImage); } // set direction image pixel ItkDirectionImageType::Pointer directionImage = m_DirectionImageContainer->GetElement(i); Vector< float, 3 > pixel; pixel.SetElement(0, dir[0]); pixel.SetElement(1, dir[1]); pixel.SetElement(2, dir[2]); directionImage->SetPixel(index, pixel); } // add direction to vector field (with spacing compensation) itk::Point worldStart; worldStart[0] = worldCenter[0]-dir[0]/2*minSpacing; worldStart[1] = worldCenter[1]-dir[1]/2*minSpacing; worldStart[2] = worldCenter[2]-dir[2]/2*minSpacing; vtkIdType id = m_VtkPoints->InsertNextPoint(worldStart.GetDataPointer()); container->GetPointIds()->InsertNextId(id); itk::Point worldEnd; worldEnd[0] = worldCenter[0]+dir[0]/2*minSpacing; worldEnd[1] = worldCenter[1]+dir[1]/2*minSpacing; worldEnd[2] = worldCenter[2]+dir[2]/2*minSpacing; id = m_VtkPoints->InsertNextPoint(worldEnd.GetDataPointer()); container->GetPointIds()->InsertNextId(id); m_VtkCellArray->InsertNextCell(container); } dirIt.Set(count); ++dirIt; } vtkSmartPointer directionsPolyData = vtkSmartPointer::New(); directionsPolyData->SetPoints(m_VtkPoints); directionsPolyData->SetLines(m_VtkCellArray); - m_OutputFiberBundle = mitk::FiberBundleX::New(directionsPolyData); + m_OutputFiberBundle = mitk::FiberBundle::New(directionsPolyData); } template< class PixelType > TractsToVectorImageFilter< PixelType >::DirectionContainerType::Pointer TractsToVectorImageFilter< PixelType >::FastClustering(DirectionContainerType::Pointer inDirs, std::vector< double > lengths) { DirectionContainerType::Pointer outDirs = DirectionContainerType::New(); if (inDirs->size()<2) return inDirs; DirectionType oldMean, currentMean; std::vector< int > touched; // initialize touched.resize(inDirs->size(), 0); bool free = true; currentMean = inDirs->at(0); // initialize first seed currentMean.normalize(); double length = lengths.at(0); touched[0] = 1; std::vector< double > newLengths; bool meanChanged = false; double max = 0; while (free) { oldMean.fill(0.0); // start mean-shift clustering double angle = 0; while (fabs(dot_product(currentMean, oldMean))<0.99) { oldMean = currentMean; currentMean.fill(0.0); for (unsigned int i=0; isize(); i++) { angle = dot_product(oldMean, inDirs->at(i)); if (angle>=m_AngularThreshold) { currentMean += inDirs->at(i); if (meanChanged) length += lengths.at(i); touched[i] = 1; meanChanged = true; } else if (-angle>=m_AngularThreshold) { currentMean -= inDirs->at(i); if (meanChanged) length += lengths.at(i); touched[i] = 1; meanChanged = true; } } if(!meanChanged) currentMean = oldMean; else currentMean.normalize(); } // found stable mean outDirs->push_back(currentMean); newLengths.push_back(length); if (length>max) max = length; // find next unused seed free = false; for (unsigned int i=0; iat(i); free = true; meanChanged = false; length = lengths.at(i); touched[i] = 1; break; } } if (inDirs->size()==outDirs->size()) { if (max>0) for (unsigned int i=0; isize(); i++) outDirs->SetElement(i, outDirs->at(i)*newLengths.at(i)/max); return outDirs; } else return FastClustering(outDirs, newLengths); } //template< class PixelType > //std::vector< DirectionType > TractsToVectorImageFilter< PixelType >::Clustering(std::vector< DirectionType >& inDirs) //{ // std::vector< DirectionType > outDirs; // if (inDirs.empty()) // return outDirs; // DirectionType oldMean, currentMean, workingMean; // std::vector< DirectionType > normalizedDirs; // std::vector< int > touched; // for (std::size_t i=0; i0.0001) // { // counter = 0; // oldMean = currentMean; // workingMean = oldMean; // workingMean.normalize(); // currentMean.fill(0.0); // for (std::size_t i=0; i=m_AngularThreshold) // { // currentMean += inDirs[i]; // counter++; // } // else if (-angle>=m_AngularThreshold) // { // currentMean -= inDirs[i]; // counter++; // } // } // } // // found stable mean // if (counter>0) // { // bool add = true; // DirectionType normMean = currentMean; // normMean.normalize(); // for (std::size_t i=0; i0) // { // if (mag>max) // max = mag; // outDirs.push_back(currentMean); // } // } // } // } // if (m_NormalizeVectors) // for (std::size_t i=0; i0) // for (std::size_t i=0; i //TractsToVectorImageFilter< PixelType >::DirectionContainerType::Pointer TractsToVectorImageFilter< PixelType >::MeanShiftClustering(DirectionContainerType::Pointer dirCont) //{ // DirectionContainerType::Pointer container = DirectionContainerType::New(); // double max = 0; // for (DirectionContainerType::ConstIterator it = dirCont->Begin(); it!=dirCont->End(); ++it) // { // vnl_vector_fixed mean = ClusterStep(dirCont, it.Value()); // if (mean.is_zero()) // continue; // bool addMean = true; // for (DirectionContainerType::ConstIterator it2 = container->Begin(); it2!=container->End(); ++it2) // { // vnl_vector_fixed dir = it2.Value(); // double angle = fabs(dot_product(mean, dir)/(mean.magnitude()*dir.magnitude())); // if (angle>=m_Epsilon) // { // addMean = false; // break; // } // } // if (addMean) // { // if (m_NormalizeVectors) // mean.normalize(); // else if (mean.magnitude()>max) // max = mean.magnitude(); // container->InsertElement(container->Size(), mean); // } // } // // max normalize voxel directions // if (max>0 && !m_NormalizeVectors) // for (std::size_t i=0; iSize(); i++) // container->ElementAt(i) /= max; // if (container->Size()Size()) // return MeanShiftClustering(container); // else // return container; //} //template< class PixelType > //vnl_vector_fixed TractsToVectorImageFilter< PixelType >::ClusterStep(DirectionContainerType::Pointer dirCont, vnl_vector_fixed currentMean) //{ // vnl_vector_fixed newMean; newMean.fill(0); // for (DirectionContainerType::ConstIterator it = dirCont->Begin(); it!=dirCont->End(); ++it) // { // vnl_vector_fixed dir = it.Value(); // double angle = dot_product(currentMean, dir)/(currentMean.magnitude()*dir.magnitude()); // if (angle>=m_AngularThreshold) // newMean += dir; // else if (-angle>=m_AngularThreshold) // newMean -= dir; // } // if (fabs(dot_product(currentMean, newMean)/(currentMean.magnitude()*newMean.magnitude()))>=m_Epsilon || newMean.is_zero()) // return newMean; // else // return ClusterStep(dirCont, newMean); //} } diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.h index 3a3eab15be..67a324ac46 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.h @@ -1,110 +1,110 @@ #ifndef __itkTractsToVectorImageFilter_h__ #define __itkTractsToVectorImageFilter_h__ // MITK -#include +#include // ITK #include #include // VTK #include #include #include #include #include using namespace mitk; namespace itk{ /** * \brief Extracts the voxel-wise main directions of the input fiber bundle. */ template< class PixelType > class TractsToVectorImageFilter : public ImageSource< VectorImage< float, 3 > > { public: typedef TractsToVectorImageFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef itk::Vector OutputVectorType; typedef itk::Image OutputImageType; typedef std::vector< OutputImageType::Pointer > OutputImageContainerType; typedef vnl_vector_fixed< double, 3 > DirectionType; typedef VectorContainer< unsigned int, DirectionType > DirectionContainerType; typedef VectorContainer< unsigned int, DirectionContainerType::Pointer > ContainerType; typedef Image< Vector< float, 3 >, 3> ItkDirectionImageType; typedef VectorContainer< unsigned int, ItkDirectionImageType::Pointer > DirectionImageContainerType; typedef itk::Image ItkUcharImgType; typedef itk::Image ItkDoubleImgType; itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkTypeMacro( TractsToVectorImageFilter, ImageSource ) itkSetMacro( SizeThreshold, float) itkGetMacro( SizeThreshold, float) itkSetMacro( AngularThreshold, float) ///< cluster directions that are closer together than the specified threshold itkGetMacro( AngularThreshold, float) ///< cluster directions that are closer together than the specified threshold itkSetMacro( NormalizeVectors, bool) ///< Normalize vectors to length 1 itkGetMacro( NormalizeVectors, bool) ///< Normalize vectors to length 1 itkSetMacro( UseWorkingCopy, bool) ///< Do not modify input fiber bundle. Use a copy. itkGetMacro( UseWorkingCopy, bool) ///< Do not modify input fiber bundle. Use a copy. itkSetMacro( MaxNumDirections, unsigned long) ///< If more directions are extracted, only the largest are kept. itkGetMacro( MaxNumDirections, unsigned long) ///< If more directions are extracted, only the largest are kept. itkSetMacro( MaskImage, ItkUcharImgType::Pointer) ///< only process voxels inside mask - itkSetMacro( FiberBundle, FiberBundleX::Pointer) ///< input fiber bundle + itkSetMacro( FiberBundle, FiberBundle::Pointer) ///< input fiber bundle itkGetMacro( ClusteredDirectionsContainer, ContainerType::Pointer) ///< output directions itkGetMacro( NumDirectionsImage, ItkUcharImgType::Pointer) ///< number of directions per voxel - itkGetMacro( OutputFiberBundle, FiberBundleX::Pointer) ///< vector field for visualization purposes + itkGetMacro( OutputFiberBundle, FiberBundle::Pointer) ///< vector field for visualization purposes itkGetMacro( DirectionImageContainer, DirectionImageContainerType::Pointer) ///< output directions itkSetMacro( CreateDirectionImages, bool) void GenerateData(); protected: DirectionContainerType::Pointer FastClustering(DirectionContainerType::Pointer inDirs, std::vector< double > lengths); ///< cluster fiber directions // std::vector< DirectionType > Clustering(std::vector< DirectionType >& inDirs); // DirectionContainerType::Pointer MeanShiftClustering(DirectionContainerType::Pointer dirCont); // vnl_vector_fixed ClusterStep(DirectionContainerType::Pointer dirCont, vnl_vector_fixed currentMean); vnl_vector_fixed GetVnlVector(double point[3]); itk::Point GetItkPoint(double point[3]); TractsToVectorImageFilter(); virtual ~TractsToVectorImageFilter(); - FiberBundleX::Pointer m_FiberBundle; ///< input fiber bundle + FiberBundle::Pointer m_FiberBundle; ///< input fiber bundle float m_AngularThreshold; ///< cluster directions that are closer together than the specified threshold float m_Epsilon; ///< epsilon for vector equality check ItkUcharImgType::Pointer m_MaskImage; ///< only voxels inside the binary mask are processed bool m_NormalizeVectors; ///< normalize vectors to length 1 itk::Vector m_OutImageSpacing; ///< spacing of output image ContainerType::Pointer m_DirectionsContainer; ///< container for fiber directions bool m_UseWorkingCopy; ///< do not modify input fiber bundle but work on copy unsigned long m_MaxNumDirections; ///< if more directions per voxel are extracted, only the largest are kept float m_SizeThreshold; bool m_CreateDirectionImages; // output datastructures ContainerType::Pointer m_ClusteredDirectionsContainer; ///< contains direction vectors for each voxel ItkUcharImgType::Pointer m_NumDirectionsImage; ///< shows number of fibers per voxel DirectionImageContainerType::Pointer m_DirectionImageContainer; ///< contains images that contain the output directions - FiberBundleX::Pointer m_OutputFiberBundle; ///< vector field for visualization purposes + FiberBundle::Pointer m_OutputFiberBundle; ///< vector field for visualization purposes }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkTractsToVectorImageFilter.cpp" #endif #endif // __itkTractsToVectorImageFilter_h__ diff --git a/Modules/DiffusionImaging/FiberTracking/CMakeLists.txt b/Modules/DiffusionImaging/FiberTracking/CMakeLists.txt index 7936ebba5e..78a0983713 100644 --- a/Modules/DiffusionImaging/FiberTracking/CMakeLists.txt +++ b/Modules/DiffusionImaging/FiberTracking/CMakeLists.txt @@ -1,65 +1,65 @@ set(_module_deps MitkDiffusionCore MitkGraphAlgorithms) mitk_check_module_dependencies( MODULES ${_module_deps} MISSING_DEPENDENCIES_VAR _missing_deps ) # Enable OpenMP support find_package(OpenMP) if(NOT OPENMP_FOUND) message("OpenMP is not available.") endif() if(OPENMP_FOUND) message(STATUS "Found OpenMP.") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") endif() if(NOT _missing_deps) set(lut_url http://mitk.org/download/data/FibertrackingLUT.tar.gz) set(lut_tarball ${CMAKE_CURRENT_BINARY_DIR}/FibertrackingLUT.tar.gz) message("Downloading FiberTracking LUT ${lut_url}...") file(DOWNLOAD ${lut_url} ${lut_tarball} EXPECTED_MD5 38ecb6d4a826c9ebb0f4965eb9aeee44 TIMEOUT 60 STATUS status SHOW_PROGRESS ) list(GET status 0 status_code) list(GET status 1 status_msg) if(NOT status_code EQUAL 0) message(SEND_ERROR "${status_msg} (error code ${status_code})") else() message("done.") endif() file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Resources) message("Unpacking FiberTracking LUT tarball...") execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf ../FibertrackingLUT.tar.gz WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Resources RESULT_VARIABLE result ERROR_VARIABLE err_msg) if(result) message(SEND_ERROR "Unpacking FibertrackingLUT.tar.gz failed: ${err_msg}") else() message("done.") endif() endif() MITK_CREATE_MODULE( SUBPROJECTS MITK-DTI - INCLUDE_DIRS Algorithms Algorithms/GibbsTracking Algorithms/StochasticTracking IODataStructures IODataStructures/FiberBundleX IODataStructures/PlanarFigureComposite Interactions SignalModels Rendering ${CMAKE_CURRENT_BINARY_DIR} + INCLUDE_DIRS Algorithms Algorithms/GibbsTracking Algorithms/StochasticTracking IODataStructures IODataStructures/FiberBundle IODataStructures/PlanarFigureComposite Interactions SignalModels Rendering ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${_module_deps} PACKAGE_DEPENDS PUBLIC ITK|ITKFFT ITK|ITKDiffusionTensorImage #WARNINGS_AS_ERRORS ) if(MODULE_IS_ENABLED) add_subdirectory(Testing) endif() diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.cpp similarity index 93% rename from Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp rename to Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.cpp index 7d5e97f8ac..14db052d96 100755 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.cpp @@ -1,1849 +1,1849 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #define _USE_MATH_DEFINES -#include "mitkFiberBundleX.h" +#include "mitkFiberBundle.h" #include #include #include #include "mitkImagePixelReadAccessor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -const char* mitk::FiberBundleX::FIBER_ID_ARRAY = "Fiber_IDs"; +const char* mitk::FiberBundle::FIBER_ID_ARRAY = "Fiber_IDs"; using namespace std; -mitk::FiberBundleX::FiberBundleX( vtkPolyData* fiberPolyData ) +mitk::FiberBundle::FiberBundle( vtkPolyData* fiberPolyData ) : m_NumFibers(0) , m_FiberSampling(0) { m_FiberWeights = vtkSmartPointer::New(); m_FiberWeights->SetName("FIBER_WEIGHTS"); m_FiberPolyData = vtkSmartPointer::New(); if (fiberPolyData != NULL) { m_FiberPolyData = fiberPolyData; this->DoColorCodingOrientationBased(); } this->UpdateFiberGeometry(); this->GenerateFiberIds(); } -mitk::FiberBundleX::~FiberBundleX() +mitk::FiberBundle::~FiberBundle() { } -mitk::FiberBundleX::Pointer mitk::FiberBundleX::GetDeepCopy() +mitk::FiberBundle::Pointer mitk::FiberBundle::GetDeepCopy() { - mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(m_FiberPolyData); + mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(m_FiberPolyData); newFib->SetFiberColors(this->m_FiberColors); newFib->SetFiberWeights(this->m_FiberWeights); return newFib; } -vtkSmartPointer mitk::FiberBundleX::GeneratePolyDataByIds(std::vector fiberIds) +vtkSmartPointer mitk::FiberBundle::GeneratePolyDataByIds(std::vector fiberIds) { vtkSmartPointer newFiberPolyData = vtkSmartPointer::New(); vtkSmartPointer newLineSet = vtkSmartPointer::New(); vtkSmartPointer newPointSet = vtkSmartPointer::New(); 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++) { newFiber->GetPointIds()->SetId(i, newPointSet->GetNumberOfPoints()); newPointSet->InsertNextPoint(fibPoints->GetPoint(i)[0], fibPoints->GetPoint(i)[1], fibPoints->GetPoint(i)[2]); } newLineSet->InsertNextCell(newFiber); ++finIt; } newFiberPolyData->SetPoints(newPointSet); newFiberPolyData->SetLines(newLineSet); return newFiberPolyData; } // merge two fiber bundles -mitk::FiberBundleX::Pointer mitk::FiberBundleX::AddBundle(mitk::FiberBundleX* fib) +mitk::FiberBundle::Pointer mitk::FiberBundle::AddBundle(mitk::FiberBundle* fib) { if (fib==NULL) { MITK_WARN << "trying to call AddBundle with NULL argument"; return NULL; } MITK_INFO << "Adding fibers"; vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); // add current fiber bundle vtkSmartPointer weights = vtkSmartPointer::New(); weights->SetNumberOfValues(this->GetNumFibers()+fib->GetNumFibers()); unsigned int counter = 0; for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } weights->InsertValue(counter, this->GetFiberWeight(i)); vNewLines->InsertNextCell(container); counter++; } // add new fiber bundle for (int i=0; iGetFiberPolyData()->GetNumberOfCells(); i++) { vtkCell* cell = fib->GetFiberPolyData()->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } weights->InsertValue(counter, fib->GetFiberWeight(i)); vNewLines->InsertNextCell(container); counter++; } // initialize polydata vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle - mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(vNewPolyData); + mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(vNewPolyData); newFib->SetFiberWeights(weights); return newFib; } // subtract two fiber bundles -mitk::FiberBundleX::Pointer mitk::FiberBundleX::SubtractBundle(mitk::FiberBundleX* fib) +mitk::FiberBundle::Pointer mitk::FiberBundle::SubtractBundle(mitk::FiberBundle* fib) { MITK_INFO << "Subtracting fibers"; vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); // iterate over current fibers boost::progress_display disp(m_NumFibers); for( int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (points==NULL || numPoints<=0) continue; int numFibers2 = fib->GetNumFibers(); bool contained = false; for( int i2=0; i2GetFiberPolyData()->GetCell(i2); int numPoints2 = cell2->GetNumberOfPoints(); vtkPoints* points2 = cell2->GetPoints(); if (points2==NULL)// || numPoints2<=0) continue; // check endpoints if (numPoints2==numPoints) { itk::Point point_start = GetItkPoint(points->GetPoint(0)); itk::Point point_end = GetItkPoint(points->GetPoint(numPoints-1)); itk::Point point2_start = GetItkPoint(points2->GetPoint(0)); itk::Point point2_end = GetItkPoint(points2->GetPoint(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; break; } } } // add to result because fiber is not subtracted if (!contained) { vtkSmartPointer container = vtkSmartPointer::New(); for( int j=0; jInsertNextPoint(points->GetPoint(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 - return mitk::FiberBundleX::New(vNewPolyData); + return mitk::FiberBundle::New(vNewPolyData); } -itk::Point mitk::FiberBundleX::GetItkPoint(double point[3]) +itk::Point mitk::FiberBundle::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) +void mitk::FiberBundle::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(); GenerateFiberIds(); } /* * return vtkPolyData */ -vtkSmartPointer mitk::FiberBundleX::GetFiberPolyData() const +vtkSmartPointer mitk::FiberBundle::GetFiberPolyData() const { return m_FiberPolyData; } -void mitk::FiberBundleX::DoColorCodingOrientationBased() +void mitk::FiberBundle::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 //================================================= 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 = 4; m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(numOfPoints * componentSize); m_FiberColors->SetNumberOfComponents(componentSize); m_FiberColors->SetName("FIBER_COLORS"); int numOfFibers = m_FiberPolyData->GetNumberOfLines(); if (numOfFibers < 1) return; /* extract single fibers of fiberBundle */ vtkCellArray* fiberList = m_FiberPolyData->GetLines(); fiberList->InitTraversal(); for (int fi=0; fiGetNextCell(pointsPerFiber, idList); /* 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); } m_FiberColors->InsertTupleValue(idList[i], rgba); } } else if (pointsPerFiber == 1) { /* a single point does not define a fiber (use vertex mechanisms instead */ continue; } else { MITK_DEBUG << "Fiber with 0 points detected... please check your tractography algorithm!" ; continue; } } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } -void mitk::FiberBundleX::SetFiberOpacity(vtkDoubleArray* FAValArray) +void mitk::FiberBundle::SetFiberOpacity(vtkDoubleArray* FAValArray) { for(long i=0; iGetNumberOfTuples(); i++) { double faValue = FAValArray->GetValue(i); faValue = faValue * 255.0; m_FiberColors->SetComponent(i,3, (unsigned char) faValue ); } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } -void mitk::FiberBundleX::ResetFiberOpacity() +void mitk::FiberBundle::ResetFiberOpacity() { for(long i=0; iGetNumberOfTuples(); i++) m_FiberColors->SetComponent(i,3, 255.0 ); m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } -void mitk::FiberBundleX::ColorFibersByScalarMap(mitk::Image::Pointer FAimage, bool opacity) +void mitk::FiberBundle::ColorFibersByScalarMap(mitk::Image::Pointer FAimage, bool opacity) { mitkPixelTypeMultiplex2( ColorFibersByScalarMap, FAimage->GetPixelType(), FAimage, opacity ); m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } template -void mitk::FiberBundleX::ColorFibersByScalarMap(const mitk::PixelType, mitk::Image::Pointer image, bool opacity) +void mitk::FiberBundle::ColorFibersByScalarMap(const mitk::PixelType, mitk::Image::Pointer image, bool opacity) { m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4); m_FiberColors->SetNumberOfComponents(4); m_FiberColors->SetName("FIBER_COLORS"); mitk::ImagePixelReadAccessor readimage(image, image->GetVolumeData(0)); unsigned char rgba[4] = {0,0,0,0}; vtkPoints* pointSet = m_FiberPolyData->GetPoints(); mitk::LookupTable::Pointer mitkLookup = mitk::LookupTable::New(); vtkSmartPointer lookupTable = vtkSmartPointer::New(); lookupTable->SetTableRange(0.0, 0.8); lookupTable->Build(); mitkLookup->SetVtkLookupTable(lookupTable); mitkLookup->SetType(mitk::LookupTable::JET); 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 pixelValue = readimage.GetPixelByWorldCoordinates(px); double color[3]; lookupTable->GetColor(pixelValue, color); rgba[0] = (unsigned char) (255.0 * color[0]); rgba[1] = (unsigned char) (255.0 * color[1]); rgba[2] = (unsigned char) (255.0 * color[2]); if (opacity) rgba[3] = (unsigned char) (255.0 * pixelValue); else rgba[3] = (unsigned char) (255.0); m_FiberColors->InsertTupleValue(i, rgba); } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } -void mitk::FiberBundleX::SetFiberColors(float r, float g, float b, float alpha) +void mitk::FiberBundle::SetFiberColors(float r, float g, float b, float alpha) { m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4); m_FiberColors->SetNumberOfComponents(4); m_FiberColors->SetName("FIBER_COLORS"); unsigned char rgba[4] = {0,0,0,0}; for(long i=0; iGetNumberOfPoints(); ++i) { rgba[0] = (unsigned char) r; rgba[1] = (unsigned char) g; rgba[2] = (unsigned char) b; rgba[3] = (unsigned char) alpha; m_FiberColors->InsertTupleValue(i, rgba); } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } -void mitk::FiberBundleX::GenerateFiberIds() +void mitk::FiberBundle::GenerateFiberIds() { if (m_FiberPolyData == NULL) return; vtkSmartPointer idFiberFilter = vtkSmartPointer::New(); idFiberFilter->SetInputData(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::FiberBundleX::Pointer mitk::FiberBundleX::ExtractFiberSubset(ItkUcharImgType* mask, bool anyPoint, bool invert) +mitk::FiberBundle::Pointer mitk::FiberBundle::ExtractFiberSubset(ItkUcharImgType* mask, bool anyPoint, bool invert) { vtkSmartPointer polyData = m_FiberPolyData; if (anyPoint) { float minSpacing = 1; if(mask->GetSpacing()[0]GetSpacing()[1] && mask->GetSpacing()[0]GetSpacing()[2]) minSpacing = mask->GetSpacing()[0]; else if (mask->GetSpacing()[1] < mask->GetSpacing()[2]) minSpacing = mask->GetSpacing()[1]; else minSpacing = mask->GetSpacing()[2]; - mitk::FiberBundleX::Pointer fibCopy = this->GetDeepCopy(); + mitk::FiberBundle::Pointer fibCopy = this->GetDeepCopy(); fibCopy->ResampleSpline(minSpacing/5); polyData = fibCopy->GetFiberPolyData(); } vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Extracting fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkCell* cellOriginal = m_FiberPolyData->GetCell(i); int numPointsOriginal = cellOriginal->GetNumberOfPoints(); vtkPoints* pointsOriginal = cellOriginal->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); if (numPoints>1 && numPointsOriginal) { if (anyPoint) { if (!invert) { for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetPixel(idx)>0 && mask->GetLargestPossibleRegion().IsInside(idx) ) { for (int k=0; kGetPoint(k); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } break; } } } else { bool includeFiber = true; for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetPixel(idx)>0 && mask->GetLargestPossibleRegion().IsInside(idx) ) { includeFiber = false; break; } } if (includeFiber) { for (int k=0; kGetPoint(k); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } } else { double* start = pointsOriginal->GetPoint(0); itk::Point itkStart; itkStart[0] = start[0]; itkStart[1] = start[1]; itkStart[2] = start[2]; itk::Index<3> idxStart; mask->TransformPhysicalPointToIndex(itkStart, idxStart); double* end = pointsOriginal->GetPoint(numPointsOriginal-1); itk::Point itkEnd; itkEnd[0] = end[0]; itkEnd[1] = end[1]; itkEnd[2] = end[2]; itk::Index<3> idxEnd; mask->TransformPhysicalPointToIndex(itkEnd, idxEnd); if ( mask->GetPixel(idxStart)>0 && mask->GetPixel(idxEnd)>0 && mask->GetLargestPossibleRegion().IsInside(idxStart) && mask->GetLargestPossibleRegion().IsInside(idxEnd) ) { for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } } vtkNewCells->InsertNextCell(container); } if (vtkNewCells->GetNumberOfCells()<=0) return NULL; vtkSmartPointer newPolyData = vtkSmartPointer::New(); newPolyData->SetPoints(vtkNewPoints); newPolyData->SetLines(vtkNewCells); - return mitk::FiberBundleX::New(newPolyData); + return mitk::FiberBundle::New(newPolyData); } -mitk::FiberBundleX::Pointer mitk::FiberBundleX::RemoveFibersOutside(ItkUcharImgType* mask, bool invert) +mitk::FiberBundle::Pointer mitk::FiberBundle::RemoveFibersOutside(ItkUcharImgType* mask, bool invert) { float minSpacing = 1; if(mask->GetSpacing()[0]GetSpacing()[1] && mask->GetSpacing()[0]GetSpacing()[2]) minSpacing = mask->GetSpacing()[0]; else if (mask->GetSpacing()[1] < mask->GetSpacing()[2]) minSpacing = mask->GetSpacing()[1]; else minSpacing = mask->GetSpacing()[2]; - mitk::FiberBundleX::Pointer fibCopy = this->GetDeepCopy(); + mitk::FiberBundle::Pointer fibCopy = this->GetDeepCopy(); fibCopy->ResampleSpline(minSpacing/10); vtkSmartPointer polyData =fibCopy->GetFiberPolyData(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Cutting fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); if (numPoints>1) { int newNumPoints = 0; for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetPixel(idx)>0 && mask->GetLargestPossibleRegion().IsInside(idx) && !invert ) { vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); newNumPoints++; } else if ( (mask->GetPixel(idx)<=0 || !mask->GetLargestPossibleRegion().IsInside(idx)) && invert ) { vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); newNumPoints++; } else if (newNumPoints>0) { vtkNewCells->InsertNextCell(container); newNumPoints = 0; container = vtkSmartPointer::New(); } } if (newNumPoints>0) vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()<=0) return NULL; vtkSmartPointer newPolyData = vtkSmartPointer::New(); newPolyData->SetPoints(vtkNewPoints); newPolyData->SetLines(vtkNewCells); - mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(newPolyData); + mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(newPolyData); newFib->ResampleSpline(minSpacing/2); return newFib; } -mitk::FiberBundleX::Pointer mitk::FiberBundleX::ExtractFiberSubset(BaseData* roi) +mitk::FiberBundle::Pointer mitk::FiberBundle::ExtractFiberSubset(BaseData* roi) { if (roi==NULL || !(dynamic_cast(roi) || dynamic_cast(roi)) ) return NULL; std::vector tmp = ExtractFiberIdSubset(roi); if (tmp.size()<=0) - return mitk::FiberBundleX::New(); + return mitk::FiberBundle::New(); vtkSmartPointer pTmp = GeneratePolyDataByIds(tmp); - return mitk::FiberBundleX::New(pTmp); + return mitk::FiberBundle::New(pTmp); } -std::vector mitk::FiberBundleX::ExtractFiberIdSubset(BaseData* roi) +std::vector mitk::FiberBundle::ExtractFiberIdSubset(BaseData* roi) { std::vector result; if (roi==NULL) return result; mitk::PlanarFigureComposite::Pointer pfc = dynamic_cast(roi); if (!pfc.IsNull()) // handle composite { switch (pfc->getOperationType()) { case 0: // AND { result = this->ExtractFiberIdSubset(pfc->getChildAt(0)); std::vector::iterator it; for (int i=1; igetNumberOfChildren(); ++i) { std::vector inRoi = this->ExtractFiberIdSubset(pfc->getChildAt(i)); std::vector rest(std::min(result.size(),inRoi.size())); it = std::set_intersection(result.begin(), result.end(), inRoi.begin(), inRoi.end(), rest.begin() ); rest.resize( it - rest.begin() ); result = rest; } break; } case 1: // OR { result = ExtractFiberIdSubset(pfc->getChildAt(0)); std::vector::iterator it; for (int i=1; igetNumberOfChildren(); ++i) { it = result.end(); std::vector inRoi = ExtractFiberIdSubset(pfc->getChildAt(i)); result.insert(it, inRoi.begin(), inRoi.end()); } // remove duplicates sort(result.begin(), result.end()); it = unique(result.begin(), result.end()); result.resize( it - result.begin() ); break; } case 2: // NOT { for(long i=0; iGetNumFibers(); i++) result.push_back(i); std::vector::iterator it; for (long i=0; igetNumberOfChildren(); ++i) { std::vector inRoi = ExtractFiberIdSubset(pfc->getChildAt(i)); std::vector rest(result.size()-inRoi.size()); it = std::set_difference(result.begin(), result.end(), inRoi.begin(), inRoi.end(), rest.begin() ); rest.resize( it - rest.begin() ); result = rest; } break; } } } else if ( dynamic_cast(roi) ) // actual extraction { if ( dynamic_cast(roi) ) { mitk::PlanarFigure::Pointer planarPoly = dynamic_cast(roi); //create vtkPolygon using controlpoints from planarFigure polygon vtkSmartPointer polygonVtk = vtkSmartPointer::New(); for (unsigned int i=0; iGetNumberOfControlPoints(); ++i) { itk::Point p = planarPoly->GetWorldControlPoint(i); vtkIdType id = polygonVtk->GetPoints()->InsertNextPoint(p[0], p[1], p[2] ); polygonVtk->GetPointIds()->InsertNextId(id); } MITK_INFO << "Extracting with polygon"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j, p1); double p2[3] = {0,0,0}; points->GetPoint(j+1, p2); double tolerance = 0.001; // Outputs double t = 0; // Parametric coordinate of intersection (0 (corresponding to p1) to 1 (corresponding to p2)) double x[3] = {0,0,0}; // The coordinate of the intersection double pcoords[3] = {0,0,0}; int subId = 0; int iD = polygonVtk->IntersectWithLine(p1, p2, tolerance, t, x, pcoords, subId); if (iD!=0) { result.push_back(i); break; } } } } else if ( dynamic_cast(roi) ) { mitk::PlanarFigure::Pointer planarFigure = dynamic_cast(roi); Vector3D planeNormal = planarFigure->GetPlaneGeometry()->GetNormal(); planeNormal.Normalize(); //calculate circle radius mitk::Point3D V1w = planarFigure->GetWorldControlPoint(0); //centerPoint mitk::Point3D V2w = planarFigure->GetWorldControlPoint(1); //radiusPoint double radius = V1w.EuclideanDistanceTo(V2w); radius *= radius; MITK_INFO << "Extracting with circle"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j, p1); double p2[3] = {0,0,0}; points->GetPoint(j+1, p2); // Outputs double t = 0; // Parametric coordinate of intersection (0 (corresponding to p1) to 1 (corresponding to p2)) double x[3] = {0,0,0}; // The coordinate of the intersection int iD = vtkPlane::IntersectWithLine(p1,p2,planeNormal.GetDataPointer(),V1w.GetDataPointer(),t,x); if (iD!=0) { double dist = (x[0]-V1w[0])*(x[0]-V1w[0])+(x[1]-V1w[1])*(x[1]-V1w[1])+(x[2]-V1w[2])*(x[2]-V1w[2]); if( dist <= radius) { result.push_back(i); break; } } } } } return result; } return result; } -void mitk::FiberBundleX::UpdateFiberGeometry() +void mitk::FiberBundle::UpdateFiberGeometry() { vtkSmartPointer cleaner = vtkSmartPointer::New(); cleaner->SetInputData(m_FiberPolyData); cleaner->PointMergingOff(); cleaner->Update(); m_FiberPolyData = cleaner->GetOutput(); m_FiberLengths.clear(); m_MeanFiberLength = 0; m_MedianFiberLength = 0; m_LengthStDev = 0; m_NumFibers = m_FiberPolyData->GetNumberOfCells(); if (m_FiberColors==NULL || m_FiberColors->GetNumberOfTuples()!=m_FiberPolyData->GetNumberOfPoints()) this->DoColorCodingOrientationBased(); if (m_FiberWeights->GetSize()!=m_NumFibers) { m_FiberWeights = vtkSmartPointer::New(); m_FiberWeights->SetName("FIBER_WEIGHTS"); m_FiberWeights->SetNumberOfValues(m_NumFibers); this->SetFiberWeights(1); } if (m_NumFibers<=0) // no fibers present; apply default geometry { m_MinFiberLength = 0; m_MaxFiberLength = 0; mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->SetImageGeometry(false); float b[] = {0, 1, 0, 1, 0, 1}; geometry->SetFloatBounds(b); SetGeometry(geometry); return; } double b[6]; m_FiberPolyData->GetBounds(b); // calculate statistics for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int p = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); float length = 0; for (int j=0; jGetPoint(j, p1); double p2[3]; points->GetPoint(j+1, p2); float dist = std::sqrt((p1[0]-p2[0])*(p1[0]-p2[0])+(p1[1]-p2[1])*(p1[1]-p2[1])+(p1[2]-p2[2])*(p1[2]-p2[2])); length += dist; } m_FiberLengths.push_back(length); m_MeanFiberLength += length; if (i==0) { m_MinFiberLength = length; m_MaxFiberLength = length; } else { if (lengthm_MaxFiberLength) m_MaxFiberLength = length; } } m_MeanFiberLength /= m_NumFibers; std::vector< float > sortedLengths = m_FiberLengths; std::sort(sortedLengths.begin(), sortedLengths.end()); for (int i=0; i1) m_LengthStDev /= (m_NumFibers-1); else m_LengthStDev = 0; m_LengthStDev = std::sqrt(m_LengthStDev); m_MedianFiberLength = sortedLengths.at(m_NumFibers/2); mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->SetFloatBounds(b); this->SetGeometry(geometry); m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } -float mitk::FiberBundleX::GetFiberWeight(unsigned int fiber) +float mitk::FiberBundle::GetFiberWeight(unsigned int fiber) { return m_FiberWeights->GetValue(fiber); } -void mitk::FiberBundleX::SetFiberWeights(float newWeight) +void mitk::FiberBundle::SetFiberWeights(float newWeight) { for (int i=0; iGetSize(); i++) m_FiberWeights->SetValue(i, newWeight); } -void mitk::FiberBundleX::SetFiberWeights(vtkSmartPointer weights) +void mitk::FiberBundle::SetFiberWeights(vtkSmartPointer weights) { if (m_NumFibers!=weights->GetSize()) return; for (int i=0; iGetSize(); i++) m_FiberWeights->SetValue(i, weights->GetValue(i)); m_FiberWeights->SetName("FIBER_WEIGHTS"); } -void mitk::FiberBundleX::SetFiberWeight(unsigned int fiber, float weight) +void mitk::FiberBundle::SetFiberWeight(unsigned int fiber, float weight) { m_FiberWeights->SetValue(fiber, weight); } -void mitk::FiberBundleX::SetFiberColors(vtkSmartPointer fiberColors) +void mitk::FiberBundle::SetFiberColors(vtkSmartPointer fiberColors) { for(long i=0; iGetNumberOfPoints(); ++i) { unsigned char source[4] = {0,0,0,0}; fiberColors->GetTupleValue(i, source); unsigned char target[4] = {0,0,0,0}; target[0] = source[0]; target[1] = source[1]; target[2] = source[2]; target[3] = source[3]; m_FiberColors->InsertTupleValue(i, target); } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } -itk::Matrix< double, 3, 3 > mitk::FiberBundleX::TransformMatrix(itk::Matrix< double, 3, 3 > m, double rx, double ry, double rz) +itk::Matrix< double, 3, 3 > mitk::FiberBundle::TransformMatrix(itk::Matrix< double, 3, 3 > m, double rx, double ry, double rz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; m = rot*m; return m; } -itk::Point mitk::FiberBundleX::TransformPoint(vnl_vector_fixed< double, 3 > point, double rx, double ry, double rz, double tx, double ty, double tz) +itk::Point mitk::FiberBundle::TransformPoint(vnl_vector_fixed< double, 3 > point, double rx, double ry, double rz, double tx, double ty, double tz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; vnl_matrix_fixed< double, 3, 3 > rot = rotZ*rotY*rotX; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); point[0] -= center[0]; point[1] -= center[1]; point[2] -= center[2]; point = rot*point; point[0] += center[0]+tx; point[1] += center[1]+ty; point[2] += center[2]+tz; itk::Point out; out[0] = point[0]; out[1] = point[1]; out[2] = point[2]; return out; } -void mitk::FiberBundleX::TransformFibers(double rx, double ry, double rz, double tx, double ty, double tz) +void mitk::FiberBundle::TransformFibers(double rx, double ry, double rz, double tx, double ty, double tz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; vnl_matrix_fixed< double, 3, 3 > rot = rotZ*rotY*rotX; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vnl_vector_fixed< double, 3 > dir; dir[0] = p[0]-center[0]; dir[1] = p[1]-center[1]; dir[2] = p[2]-center[2]; dir = rot*dir; dir[0] += center[0]+tx; dir[1] += center[1]+ty; dir[2] += center[2]+tz; vtkIdType id = vtkNewPoints->InsertNextPoint(dir.data_block()); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } -void mitk::FiberBundleX::RotateAroundAxis(double x, double y, double z) +void mitk::FiberBundle::RotateAroundAxis(double x, double y, double z) { x = x*M_PI/180; y = y*M_PI/180; z = z*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vnl_vector_fixed< double, 3 > dir; dir[0] = p[0]-center[0]; dir[1] = p[1]-center[1]; dir[2] = p[2]-center[2]; dir = rotZ*rotY*rotX*dir; dir[0] += center[0]; dir[1] += center[1]; dir[2] += center[2]; vtkIdType id = vtkNewPoints->InsertNextPoint(dir.data_block()); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } -void mitk::FiberBundleX::ScaleFibers(double x, double y, double z, bool subtractCenter) +void mitk::FiberBundle::ScaleFibers(double x, double y, double z, bool subtractCenter) { MITK_INFO << "Scaling fibers"; boost::progress_display disp(m_NumFibers); mitk::BaseGeometry* geom = this->GetGeometry(); mitk::Point3D c = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); if (subtractCenter) { p[0] -= c[0]; p[1] -= c[1]; p[2] -= c[2]; } p[0] *= x; p[1] *= y; p[2] *= z; if (subtractCenter) { p[0] += c[0]; p[1] += c[1]; p[2] += c[2]; } vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } -void mitk::FiberBundleX::TranslateFibers(double x, double y, double z) +void mitk::FiberBundle::TranslateFibers(double x, double y, double z) { vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); p[0] += x; p[1] += y; p[2] += z; vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } -void mitk::FiberBundleX::MirrorFibers(unsigned int axis) +void mitk::FiberBundle::MirrorFibers(unsigned int axis) { if (axis>2) return; MITK_INFO << "Mirroring fibers"; boost::progress_display disp(m_NumFibers); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); p[axis] = -p[axis]; vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } -void mitk::FiberBundleX::RemoveDir(vnl_vector_fixed dir, double threshold) +void mitk::FiberBundle::RemoveDir(vnl_vector_fixed dir, double threshold) { dir.normalize(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp ; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures vtkSmartPointer container = vtkSmartPointer::New(); bool discard = false; for (int j=0; jGetPoint(j, p1); double p2[3]; points->GetPoint(j+1, p2); vnl_vector_fixed< double, 3 > v1; v1[0] = p2[0]-p1[0]; v1[1] = p2[1]-p1[1]; v1[2] = p2[2]-p1[2]; if (v1.magnitude()>0.001) { v1.normalize(); if (fabs(dot_product(v1,dir))>threshold) { discard = true; break; } } } if (!discard) { for (int j=0; jGetPoint(j, p1); vtkIdType id = vtkNewPoints->InsertNextPoint(p1); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); // UpdateColorCoding(); // UpdateFiberGeometry(); } -bool mitk::FiberBundleX::ApplyCurvatureThreshold(float minRadius, bool deleteFibers) +bool mitk::FiberBundle::ApplyCurvatureThreshold(float minRadius, bool deleteFibers) { if (minRadius<0) return true; vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Applying curvature threshold"; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp ; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p1); double p2[3]; points->GetPoint(j+1, p2); double p3[3]; points->GetPoint(j+2, p3); vnl_vector_fixed< float, 3 > v1, v2, v3; v1[0] = p2[0]-p1[0]; v1[1] = p2[1]-p1[1]; v1[2] = p2[2]-p1[2]; v2[0] = p3[0]-p2[0]; v2[1] = p3[1]-p2[1]; v2[2] = p3[2]-p2[2]; v3[0] = p1[0]-p3[0]; v3[1] = p1[1]-p3[1]; v3[2] = p1[2]-p3[2]; float a = v1.magnitude(); float b = v2.magnitude(); float c = v3.magnitude(); float r = a*b*c/std::sqrt((a+b+c)*(a+b-c)*(b+c-a)*(a-b+c)); // radius of triangle via Heron's formula (area of triangle) vtkIdType id = vtkNewPoints->InsertNextPoint(p1); container->GetPointIds()->InsertNextId(id); if (deleteFibers && rInsertNextCell(container); container = vtkSmartPointer::New(); } else if (j==numPoints-3) { id = vtkNewPoints->InsertNextPoint(p2); container->GetPointIds()->InsertNextId(id); id = vtkNewPoints->InsertNextPoint(p3); container->GetPointIds()->InsertNextId(id); vtkNewCells->InsertNextCell(container); } } } if (vtkNewCells->GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); return true; } -bool mitk::FiberBundleX::RemoveShortFibers(float lengthInMM) +bool mitk::FiberBundle::RemoveShortFibers(float lengthInMM) { MITK_INFO << "Removing short fibers"; if (lengthInMM<=0 || lengthInMMm_MaxFiberLength) // can't remove all fibers { MITK_WARN << "Process aborted. No fibers would be left!"; return false; } vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); float min = m_MaxFiberLength; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (m_FiberLengths.at(i)>=lengthInMM) { vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); if (m_FiberLengths.at(i)GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); return true; } -bool mitk::FiberBundleX::RemoveLongFibers(float lengthInMM) +bool mitk::FiberBundle::RemoveLongFibers(float lengthInMM) { if (lengthInMM<=0 || lengthInMM>m_MaxFiberLength) return true; if (lengthInMM vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Removing long fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (m_FiberLengths.at(i)<=lengthInMM) { vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); return true; } -void mitk::FiberBundleX::ResampleSpline(float pointDistance, double tension, double continuity, double bias ) +void mitk::FiberBundle::ResampleSpline(float pointDistance, double tension, double continuity, double bias ) { if (pointDistance<=0) return; vtkSmartPointer vtkSmoothPoints = vtkSmartPointer::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 = vtkSmartPointer::New(); //cellcontainer for smoothed lines vtkIdType pointHelperCnt = 0; MITK_INFO << "Smoothing fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer newPoints = vtkSmartPointer::New(); for (int j=0; jInsertNextPoint(points->GetPoint(j)); float length = m_FiberLengths.at(i); int sampling = std::ceil(length/pointDistance); vtkSmartPointer xSpline = vtkSmartPointer::New(); vtkSmartPointer ySpline = vtkSmartPointer::New(); vtkSmartPointer zSpline = vtkSmartPointer::New(); xSpline->SetDefaultBias(bias); xSpline->SetDefaultTension(tension); xSpline->SetDefaultContinuity(continuity); ySpline->SetDefaultBias(bias); ySpline->SetDefaultTension(tension); ySpline->SetDefaultContinuity(continuity); zSpline->SetDefaultBias(bias); zSpline->SetDefaultTension(tension); zSpline->SetDefaultContinuity(continuity); vtkSmartPointer spline = vtkSmartPointer::New(); spline->SetXSpline(xSpline); spline->SetYSpline(ySpline); spline->SetZSpline(zSpline); spline->SetPoints(newPoints); vtkSmartPointer functionSource = vtkSmartPointer::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 = vtkSmartPointer::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); this->SetFiberPolyData(m_FiberPolyData, true); m_FiberSampling = 10/pointDistance; } -void mitk::FiberBundleX::ResampleSpline(float pointDistance) +void mitk::FiberBundle::ResampleSpline(float pointDistance) { ResampleSpline(pointDistance, 0, 0, 0 ); } -unsigned long mitk::FiberBundleX::GetNumberOfPoints() +unsigned long mitk::FiberBundle::GetNumberOfPoints() { unsigned long points = 0; for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); points += cell->GetNumberOfPoints(); } return points; } -void mitk::FiberBundleX::Compress(float error) +void mitk::FiberBundle::Compress(float error) { vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Compressing fibers"; unsigned long numRemovedPoints = 0; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures std::vector< int > removedPoints; removedPoints.resize(numPoints, 0); removedPoints[0]=-1; removedPoints[numPoints-1]=-1; vtkSmartPointer container = vtkSmartPointer::New(); bool pointFound = true; while (pointFound) { pointFound = false; double minError = error; int removeIndex = -1; for (int j=0; jGetPoint(j, cand); vnl_vector_fixed< double, 3 > candV; candV[0]=cand[0]; candV[1]=cand[1]; candV[2]=cand[2]; int validP = -1; vnl_vector_fixed< double, 3 > pred; for (int k=j-1; k>=0; k--) if (removedPoints[k]<=0) { double ref[3]; points->GetPoint(k, ref); pred[0]=ref[0]; pred[1]=ref[1]; pred[2]=ref[2]; validP = k; break; } int validS = -1; vnl_vector_fixed< double, 3 > succ; for (int k=j+1; kGetPoint(k, ref); succ[0]=ref[0]; succ[1]=ref[1]; succ[2]=ref[2]; validS = k; break; } if (validP>=0 && validS>=0) { double a = (candV-pred).magnitude(); double b = (candV-succ).magnitude(); double c = (pred-succ).magnitude(); double s=0.5*(a+b+c); double hc=(2.0/c)*sqrt(fabs(s*(s-a)*(s-b)*(s-c))); if (hcGetPoint(j, cand); vtkIdType id = vtkNewPoints->InsertNextPoint(cand); container->GetPointIds()->InsertNextId(id); } } vtkNewCells->InsertNextCell(container); } if (vtkNewCells->GetNumberOfCells()>0) { MITK_INFO << "Removed points: " << numRemovedPoints; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } } // reapply selected colorcoding in case polydata structure has changed -bool mitk::FiberBundleX::Equals(mitk::FiberBundleX* fib, double eps) +bool mitk::FiberBundle::Equals(mitk::FiberBundle* fib, double eps) { if (fib==NULL) { MITK_INFO << "Reference bundle is NULL!"; return false; } if (m_NumFibers!=fib->GetNumFibers()) { MITK_INFO << "Unequal number of fibers!"; MITK_INFO << m_NumFibers << " vs. " << fib->GetNumFibers(); return false; } for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkCell* cell2 = fib->GetFiberPolyData()->GetCell(i); int numPoints2 = cell2->GetNumberOfPoints(); vtkPoints* points2 = cell2->GetPoints(); if (numPoints2!=numPoints) { MITK_INFO << "Unequal number of points in fiber " << i << "!"; MITK_INFO << numPoints2 << " vs. " << numPoints; return false; } for (int j=0; jGetPoint(j); double* p2 = points2->GetPoint(j); if (fabs(p1[0]-p2[0])>eps || fabs(p1[1]-p2[1])>eps || fabs(p1[2]-p2[2])>eps) { MITK_INFO << "Unequal points in fiber " << i << " at position " << j << "!"; MITK_INFO << "p1: " << p1[0] << ", " << p1[1] << ", " << p1[2]; MITK_INFO << "p2: " << p2[0] << ", " << p2[1] << ", " << p2[2]; return false; } } } return true; } /* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */ -void mitk::FiberBundleX::UpdateOutputInformation() +void mitk::FiberBundle::UpdateOutputInformation() { } -void mitk::FiberBundleX::SetRequestedRegionToLargestPossibleRegion() +void mitk::FiberBundle::SetRequestedRegionToLargestPossibleRegion() { } -bool mitk::FiberBundleX::RequestedRegionIsOutsideOfTheBufferedRegion() +bool mitk::FiberBundle::RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } -bool mitk::FiberBundleX::VerifyRequestedRegion() +bool mitk::FiberBundle::VerifyRequestedRegion() { return true; } -void mitk::FiberBundleX::SetRequestedRegion(const itk::DataObject* ) +void mitk::FiberBundle::SetRequestedRegion(const itk::DataObject* ) { } diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.h b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.h similarity index 87% rename from Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.h rename to Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.h index a20c166205..146e4c7eb7 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.h +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.h @@ -1,178 +1,178 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef _MITK_FiberBundleX_H -#define _MITK_FiberBundleX_H +#ifndef _MITK_FiberBundle_H +#define _MITK_FiberBundle_H //includes for MITK datastructure #include #include #include //includes storing fiberdata #include #include #include #include #include #include //#include #include #include #include namespace mitk { /** * \brief Base Class for Fiber Bundles; */ -class MITKFIBERTRACKING_EXPORT FiberBundleX : public BaseData +class MITKFIBERTRACKING_EXPORT FiberBundle : public BaseData { public: typedef itk::Image ItkUcharImgType; // fiber colorcodings static const char* FIBER_ID_ARRAY; virtual void UpdateOutputInformation(); virtual void SetRequestedRegionToLargestPossibleRegion(); virtual bool RequestedRegionIsOutsideOfTheBufferedRegion(); virtual bool VerifyRequestedRegion(); virtual void SetRequestedRegion(const itk::DataObject*); - mitkClassMacro( FiberBundleX, BaseData ) + mitkClassMacro( FiberBundle, BaseData ) itkFactorylessNewMacro(Self) itkCloneMacro(Self) mitkNewMacro1Param(Self, vtkSmartPointer) // custom constructor // colorcoding related methods void ColorFibersByScalarMap(mitk::Image::Pointer, bool opacity); template void ColorFibersByScalarMap(const mitk::PixelType pixelType, mitk::Image::Pointer, bool opacity); void DoColorCodingOrientationBased(); void SetFiberOpacity(vtkDoubleArray *FAValArray); void ResetFiberOpacity(); void SetFiberColors(vtkSmartPointer fiberColors); void SetFiberColors(float r, float g, float b, float alpha=255); vtkSmartPointer GetFiberColors() const { return m_FiberColors; } // fiber compression void Compress(float error = 0.0); // fiber resampling void ResampleSpline(float pointDistance=1); void ResampleSpline(float pointDistance, double tension, double continuity, double bias ); bool RemoveShortFibers(float lengthInMM); bool RemoveLongFibers(float lengthInMM); bool ApplyCurvatureThreshold(float minRadius, bool deleteFibers); void MirrorFibers(unsigned int axis); void RotateAroundAxis(double x, double y, double z); void TranslateFibers(double x, double y, double z); void ScaleFibers(double x, double y, double z, bool subtractCenter=true); void TransformFibers(double rx, double ry, double rz, double tx, double ty, double tz); void RemoveDir(vnl_vector_fixed dir, double threshold); itk::Point TransformPoint(vnl_vector_fixed< double, 3 > point, double rx, double ry, double rz, double tx, double ty, double tz); itk::Matrix< double, 3, 3 > TransformMatrix(itk::Matrix< double, 3, 3 > m, double rx, double ry, double rz); // add/subtract fibers - FiberBundleX::Pointer AddBundle(FiberBundleX* fib); - FiberBundleX::Pointer SubtractBundle(FiberBundleX* fib); + FiberBundle::Pointer AddBundle(FiberBundle* fib); + FiberBundle::Pointer SubtractBundle(FiberBundle* fib); // fiber subset extraction - FiberBundleX::Pointer ExtractFiberSubset(BaseData* roi); + FiberBundle::Pointer ExtractFiberSubset(BaseData* roi); std::vector ExtractFiberIdSubset(BaseData* roi); - FiberBundleX::Pointer ExtractFiberSubset(ItkUcharImgType* mask, bool anyPoint, bool invert=false); - FiberBundleX::Pointer RemoveFibersOutside(ItkUcharImgType* mask, bool invert=false); + FiberBundle::Pointer ExtractFiberSubset(ItkUcharImgType* mask, bool anyPoint, bool invert=false); + FiberBundle::Pointer RemoveFibersOutside(ItkUcharImgType* mask, bool invert=false); vtkSmartPointer GeneratePolyDataByIds( std::vector ); // TODO: make protected void GenerateFiberIds(); // TODO: make protected // get/set data vtkSmartPointer GetFiberWeights() const { return m_FiberWeights; } float GetFiberWeight(unsigned int fiber); void SetFiberWeights(float newWeight); void SetFiberWeight(unsigned int fiber, float weight); void SetFiberWeights(vtkSmartPointer weights); void SetFiberPolyData(vtkSmartPointer, bool updateGeometry = true); vtkSmartPointer GetFiberPolyData() const; itkGetMacro( NumFibers, int) //itkGetMacro( FiberSampling, int) int GetNumFibers() const {return m_NumFibers;} itkGetMacro( MinFiberLength, float ) itkGetMacro( MaxFiberLength, float ) itkGetMacro( MeanFiberLength, float ) itkGetMacro( MedianFiberLength, float ) itkGetMacro( LengthStDev, float ) itkGetMacro( UpdateTime2D, itk::TimeStamp ) itkGetMacro( UpdateTime3D, itk::TimeStamp ) void RequestUpdate2D(){ m_UpdateTime2D.Modified(); } void RequestUpdate3D(){ m_UpdateTime3D.Modified(); } void RequestUpdate(){ m_UpdateTime2D.Modified(); m_UpdateTime3D.Modified(); } unsigned long GetNumberOfPoints(); // copy fiber bundle - mitk::FiberBundleX::Pointer GetDeepCopy(); + mitk::FiberBundle::Pointer GetDeepCopy(); // compare fiber bundles - bool Equals(FiberBundleX* fib, double eps=0.0001); + bool Equals(FiberBundle* fib, double eps=0.0001); itkSetMacro( ReferenceGeometry, mitk::BaseGeometry::Pointer ) itkGetConstMacro( ReferenceGeometry, mitk::BaseGeometry::Pointer ) protected: - FiberBundleX( vtkPolyData* fiberPolyData = NULL ); - virtual ~FiberBundleX(); + FiberBundle( vtkPolyData* fiberPolyData = NULL ); + virtual ~FiberBundle(); itk::Point GetItkPoint(double point[3]); // calculate geometry from fiber extent void UpdateFiberGeometry(); private: // actual fiber container vtkSmartPointer m_FiberPolyData; // contains fiber ids vtkSmartPointer m_FiberIdDataSet; int m_NumFibers; vtkSmartPointer m_FiberColors; vtkSmartPointer m_FiberWeights; std::vector< float > m_FiberLengths; float m_MinFiberLength; float m_MaxFiberLength; float m_MeanFiberLength; float m_MedianFiberLength; float m_LengthStDev; int m_FiberSampling; itk::TimeStamp m_UpdateTime2D; itk::TimeStamp m_UpdateTime3D; mitk::BaseGeometry::Pointer m_ReferenceGeometry; }; } // namespace mitk -#endif /* _MITK_FiberBundleX_H */ +#endif /* _MITK_FiberBundle_H */ diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleXSource.cpp b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundleSource.cpp similarity index 100% rename from Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleXSource.cpp rename to Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundleSource.cpp diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleXSource.h b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundleSource.h similarity index 100% rename from Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleXSource.h rename to Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundleSource.h diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.cpp b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundleThreadMonitor.cpp similarity index 55% rename from Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.cpp rename to Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundleThreadMonitor.cpp index caf0d042cd..3aa3cbf85f 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.cpp +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundleThreadMonitor.cpp @@ -1,254 +1,254 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "mitkFiberBundleXThreadMonitor.h" +#include "mitkFiberBundleThreadMonitor.h" -mitk::FiberBundleXThreadMonitor::FiberBundleXThreadMonitor() +mitk::FiberBundleThreadMonitor::FiberBundleThreadMonitor() : m_monitorBracketOpen("[") , m_monitorBracketClose("]") , m_monitorHeading("Monitoring Fiberprocessing Threads") , m_monitorMask("Thread Status:\nStarted: Finished: Terminated:") , m_monitorStatus("_initialized") , m_monitorStarted(0) , m_monitorFinished(0) , m_monitorTerminated(0) { m_monitorBracketOpenPosition[0] = 0; m_monitorBracketOpenPosition[1] = 0; m_monitorBracketClosePosition[0] = 0; m_monitorBracketClosePosition[1] = 0; m_monitorHeadingPosition[0] = 0; m_monitorHeadingPosition[1] = 0; m_monitorMaskPosition[0] = 0; m_monitorMaskPosition[1] = 0; m_monitorStatusPosition[0] = 0; m_monitorStatusPosition[1] = 0; m_monitorStartedPosition[0] = 0; m_monitorStartedPosition[1] = 0; m_monitorFinishedPosition[0] = 0; m_monitorFinishedPosition[1] = 0; m_monitorTerminatedPosition[0] = 0; m_monitorTerminatedPosition[1] = 0; m_monitorHeadingOpacity = 0; m_monitorMaskOpacity = 0; m_monitorTerminatedOpacity = 0; m_monitorFinishedOpacity = 0; m_monitorStartedOpacity = 0; m_monitorStatusOpacity = 0; } -mitk::FiberBundleXThreadMonitor::~FiberBundleXThreadMonitor() +mitk::FiberBundleThreadMonitor::~FiberBundleThreadMonitor() { } -QString mitk::FiberBundleXThreadMonitor::getBracketOpen(){ +QString mitk::FiberBundleThreadMonitor::getBracketOpen(){ return m_monitorBracketOpen; } -mitk::Point2D mitk::FiberBundleXThreadMonitor::getBracketOpenPosition(){ +mitk::Point2D mitk::FiberBundleThreadMonitor::getBracketOpenPosition(){ return m_monitorBracketOpenPosition; } -void mitk::FiberBundleXThreadMonitor::setBracketOpenPosition(mitk::Point2D pnt){ +void mitk::FiberBundleThreadMonitor::setBracketOpenPosition(mitk::Point2D pnt){ m_monitorBracketOpenPosition[0] = pnt[0]; m_monitorBracketOpenPosition[1] = pnt[1]; } -QString mitk::FiberBundleXThreadMonitor::getBracketClose(){ +QString mitk::FiberBundleThreadMonitor::getBracketClose(){ return m_monitorBracketClose; } -mitk::Point2D mitk::FiberBundleXThreadMonitor::getBracketClosePosition(){ +mitk::Point2D mitk::FiberBundleThreadMonitor::getBracketClosePosition(){ return m_monitorBracketClosePosition; } -void mitk::FiberBundleXThreadMonitor::setBracketClosePosition(mitk::Point2D pnt){ +void mitk::FiberBundleThreadMonitor::setBracketClosePosition(mitk::Point2D pnt){ m_monitorBracketClosePosition[0] = pnt[0]; m_monitorBracketClosePosition[1] = pnt[1]; } -QString mitk::FiberBundleXThreadMonitor::getHeading(){ +QString mitk::FiberBundleThreadMonitor::getHeading(){ return m_monitorHeading; } -mitk::Point2D mitk::FiberBundleXThreadMonitor::getHeadingPosition(){ +mitk::Point2D mitk::FiberBundleThreadMonitor::getHeadingPosition(){ return m_monitorHeadingPosition; } -void mitk::FiberBundleXThreadMonitor::setHeadingPosition(mitk::Point2D pnt){ +void mitk::FiberBundleThreadMonitor::setHeadingPosition(mitk::Point2D pnt){ m_monitorHeadingPosition[0] = pnt[0]; m_monitorHeadingPosition[1] = pnt[1]; } -int mitk::FiberBundleXThreadMonitor::getHeadingOpacity(){ +int mitk::FiberBundleThreadMonitor::getHeadingOpacity(){ return m_monitorHeadingOpacity; } -void mitk::FiberBundleXThreadMonitor::setHeadingOpacity(int opacity){ +void mitk::FiberBundleThreadMonitor::setHeadingOpacity(int opacity){ m_monitorHeadingOpacity = opacity; } -QString mitk::FiberBundleXThreadMonitor::getMask(){ +QString mitk::FiberBundleThreadMonitor::getMask(){ return m_monitorMask; } -mitk::Point2D mitk::FiberBundleXThreadMonitor::getMaskPosition(){ +mitk::Point2D mitk::FiberBundleThreadMonitor::getMaskPosition(){ return m_monitorMaskPosition; } -void mitk::FiberBundleXThreadMonitor::setMaskPosition(mitk::Point2D pnt){ +void mitk::FiberBundleThreadMonitor::setMaskPosition(mitk::Point2D pnt){ m_monitorMaskPosition[0] = pnt[0]; m_monitorMaskPosition[1] = pnt[1]; } -int mitk::FiberBundleXThreadMonitor::getMaskOpacity(){ +int mitk::FiberBundleThreadMonitor::getMaskOpacity(){ return m_monitorMaskOpacity; } -void mitk::FiberBundleXThreadMonitor::setMaskOpacity(int opacity){ +void mitk::FiberBundleThreadMonitor::setMaskOpacity(int opacity){ m_monitorMaskOpacity = opacity; } -QString mitk::FiberBundleXThreadMonitor::getStatus(){ +QString mitk::FiberBundleThreadMonitor::getStatus(){ return m_monitorStatus; } -void mitk::FiberBundleXThreadMonitor::setStatus(QString status){ +void mitk::FiberBundleThreadMonitor::setStatus(QString status){ m_statusMutex.lock(); m_monitorStatus = status; m_statusMutex.unlock(); } -mitk::Point2D mitk::FiberBundleXThreadMonitor::getStatusPosition(){ +mitk::Point2D mitk::FiberBundleThreadMonitor::getStatusPosition(){ return m_monitorStatusPosition; } -void mitk::FiberBundleXThreadMonitor::setStatusPosition(mitk::Point2D pnt){ +void mitk::FiberBundleThreadMonitor::setStatusPosition(mitk::Point2D pnt){ m_monitorStatusPosition[0] = pnt[0]; m_monitorStatusPosition[1] = pnt[1]; } -int mitk::FiberBundleXThreadMonitor::getStatusOpacity(){ +int mitk::FiberBundleThreadMonitor::getStatusOpacity(){ return m_monitorStatusOpacity; } -void mitk::FiberBundleXThreadMonitor::setStatusOpacity(int opacity){ +void mitk::FiberBundleThreadMonitor::setStatusOpacity(int opacity){ m_monitorStatusOpacity = opacity; } -int mitk::FiberBundleXThreadMonitor::getStarted(){ +int mitk::FiberBundleThreadMonitor::getStarted(){ return m_monitorStarted; } /* is thread safe :) */ -void mitk::FiberBundleXThreadMonitor::setStarted(int val) +void mitk::FiberBundleThreadMonitor::setStarted(int val) { m_startedMutex.lock(); m_monitorStarted = val; m_startedMutex.unlock(); } -mitk::Point2D mitk::FiberBundleXThreadMonitor::getStartedPosition(){ +mitk::Point2D mitk::FiberBundleThreadMonitor::getStartedPosition(){ return m_monitorStartedPosition; } -void mitk::FiberBundleXThreadMonitor::setStartedPosition(mitk::Point2D pnt){ +void mitk::FiberBundleThreadMonitor::setStartedPosition(mitk::Point2D pnt){ m_monitorStartedPosition[0] = pnt[0]; m_monitorStartedPosition[1] = pnt[1]; } -int mitk::FiberBundleXThreadMonitor::getStartedOpacity(){ +int mitk::FiberBundleThreadMonitor::getStartedOpacity(){ return m_monitorStartedOpacity; } -void mitk::FiberBundleXThreadMonitor::setStartedOpacity(int opacity){ +void mitk::FiberBundleThreadMonitor::setStartedOpacity(int opacity){ m_monitorStartedOpacity = opacity; } -int mitk::FiberBundleXThreadMonitor::getFinished(){ +int mitk::FiberBundleThreadMonitor::getFinished(){ return m_monitorFinished; } -void mitk::FiberBundleXThreadMonitor::setFinished(int val) +void mitk::FiberBundleThreadMonitor::setFinished(int val) { m_finishedMutex.lock(); m_monitorFinished = val; m_finishedMutex.unlock(); } -mitk::Point2D mitk::FiberBundleXThreadMonitor::getFinishedPosition(){ +mitk::Point2D mitk::FiberBundleThreadMonitor::getFinishedPosition(){ return m_monitorFinishedPosition; } -void mitk::FiberBundleXThreadMonitor::setFinishedPosition(mitk::Point2D pnt){ +void mitk::FiberBundleThreadMonitor::setFinishedPosition(mitk::Point2D pnt){ m_monitorFinishedPosition[0] = pnt[0]; m_monitorFinishedPosition[1] = pnt[1]; } -int mitk::FiberBundleXThreadMonitor::getFinishedOpacity(){ +int mitk::FiberBundleThreadMonitor::getFinishedOpacity(){ return m_monitorFinishedOpacity; } -void mitk::FiberBundleXThreadMonitor::setFinishedOpacity(int opacity){ +void mitk::FiberBundleThreadMonitor::setFinishedOpacity(int opacity){ m_monitorFinishedOpacity = opacity; } -int mitk::FiberBundleXThreadMonitor::getTerminated(){ +int mitk::FiberBundleThreadMonitor::getTerminated(){ return m_monitorTerminated; } -void mitk::FiberBundleXThreadMonitor::setTerminated(int val) +void mitk::FiberBundleThreadMonitor::setTerminated(int val) { m_terminatedMutex.lock(); m_monitorTerminated = val; m_terminatedMutex.unlock(); } -mitk::Point2D mitk::FiberBundleXThreadMonitor::getTerminatedPosition(){ +mitk::Point2D mitk::FiberBundleThreadMonitor::getTerminatedPosition(){ return m_monitorTerminatedPosition; } -void mitk::FiberBundleXThreadMonitor::setTerminatedPosition(mitk::Point2D pnt){ +void mitk::FiberBundleThreadMonitor::setTerminatedPosition(mitk::Point2D pnt){ m_monitorTerminatedPosition[0] = pnt[0]; m_monitorTerminatedPosition[1] = pnt[1]; } -int mitk::FiberBundleXThreadMonitor::getTerminatedOpacity(){ +int mitk::FiberBundleThreadMonitor::getTerminatedOpacity(){ return m_monitorTerminatedOpacity; } -void mitk::FiberBundleXThreadMonitor::setTerminatedOpacity(int opacity){ +void mitk::FiberBundleThreadMonitor::setTerminatedOpacity(int opacity){ m_monitorTerminatedOpacity = opacity; } /* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */ -void mitk::FiberBundleXThreadMonitor::UpdateOutputInformation() +void mitk::FiberBundleThreadMonitor::UpdateOutputInformation() { } -void mitk::FiberBundleXThreadMonitor::SetRequestedRegionToLargestPossibleRegion() +void mitk::FiberBundleThreadMonitor::SetRequestedRegionToLargestPossibleRegion() { } -bool mitk::FiberBundleXThreadMonitor::RequestedRegionIsOutsideOfTheBufferedRegion() +bool mitk::FiberBundleThreadMonitor::RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } -bool mitk::FiberBundleXThreadMonitor::VerifyRequestedRegion() +bool mitk::FiberBundleThreadMonitor::VerifyRequestedRegion() { return true; } -void mitk::FiberBundleXThreadMonitor::SetRequestedRegion(const itk::DataObject *data ) +void mitk::FiberBundleThreadMonitor::SetRequestedRegion(const itk::DataObject *data ) { } diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.h b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundleThreadMonitor.h similarity index 93% rename from Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.h rename to Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundleThreadMonitor.h index 08a8721610..ba718a9ed9 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.h +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundleThreadMonitor.h @@ -1,154 +1,154 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef _MITK_FiberBundleXThreadMonitor_H -#define _MITK_FiberBundleXThreadMonitor_H +#ifndef _MITK_FiberBundleThreadMonitor_H +#define _MITK_FiberBundleThreadMonitor_H //includes for MITK datastructure #include "mitkBaseData.h" #include #include #include namespace mitk { /** * \brief Base Class for Fiber Bundles; */ - class MITKFIBERTRACKING_EXPORT FiberBundleXThreadMonitor : public BaseData + class MITKFIBERTRACKING_EXPORT FiberBundleThreadMonitor : public BaseData { public: // ======virtual methods must have====== virtual void UpdateOutputInformation(); virtual void SetRequestedRegionToLargestPossibleRegion(); virtual bool RequestedRegionIsOutsideOfTheBufferedRegion(); virtual bool VerifyRequestedRegion(); virtual void SetRequestedRegion(const itk::DataObject *data ); //======================================= - mitkClassMacro( FiberBundleXThreadMonitor, BaseData ); + mitkClassMacro( FiberBundleThreadMonitor, BaseData ); itkFactorylessNewMacro(Self) itkCloneMacro(Self) void setTextL1(QString); QString getTextL1(); QString getBracketOpen(); mitk::Point2D getBracketOpenPosition(); void setBracketOpenPosition(mitk::Point2D); int getBracketOpenOpacity(); // range 0 - 10, multiplicationfactor 0.1 (in mapper) QString getBracketClose(); mitk::Point2D getBracketClosePosition(); void setBracketClosePosition(mitk::Point2D); int getBracketCloseOpacity(); // range 0 - 10, multiplicationfactor 0.1 (in mapper) QString getHeading(); mitk::Point2D getHeadingPosition(); void setHeadingPosition(mitk::Point2D); int getHeadingOpacity(); // range 0 - 10, multiplicationfactor 0.1 (in mapper) void setHeadingOpacity(int); QString getMask(); mitk::Point2D getMaskPosition(); void setMaskPosition(mitk::Point2D); int getMaskOpacity(); // multiplicationfactor 0.1 (in mapper) void setMaskOpacity(int); QString getStatus(); void setStatus(QString); mitk::Point2D getStatusPosition(); void setStatusPosition(mitk::Point2D); int getStatusOpacity(); // multiplicationfactor 0.1 (in mapper) void setStatusOpacity(int); int getStarted(); void setStarted(int); mitk::Point2D getStartedPosition(); void setStartedPosition(mitk::Point2D); int getStartedOpacity(); // multiplicationfactor 0.1 (in mapper) void setStartedOpacity(int); int getFinished(); void setFinished(int); mitk::Point2D getFinishedPosition(); void setFinishedPosition(mitk::Point2D); int getFinishedOpacity(); // multiplicationfactor 0.1 (in mapper) void setFinishedOpacity(int); int getTerminated(); void setTerminated(int); mitk::Point2D getTerminatedPosition(); void setTerminatedPosition(mitk::Point2D); int getTerminatedOpacity(); // multiplicationfactor 0.1 (in mapper) void setTerminatedOpacity(int); protected: - FiberBundleXThreadMonitor(); - virtual ~FiberBundleXThreadMonitor(); + FiberBundleThreadMonitor(); + virtual ~FiberBundleThreadMonitor(); private: QString m_monitorBracketOpen; mitk::Point2D m_monitorBracketOpenPosition; QString m_monitorBracketClose; mitk::Point2D m_monitorBracketClosePosition; QString m_monitorHeading; mitk::Point2D m_monitorHeadingPosition; int m_monitorHeadingOpacity; QString m_monitorMask; mitk::Point2D m_monitorMaskPosition; int m_monitorMaskOpacity; QString m_monitorStatus; mitk::Point2D m_monitorStatusPosition; int m_monitorStatusOpacity; int m_monitorStarted; mitk::Point2D m_monitorStartedPosition; int m_monitorStartedOpacity; int m_monitorFinished; mitk::Point2D m_monitorFinishedPosition; int m_monitorFinishedOpacity; int m_monitorTerminated; mitk::Point2D m_monitorTerminatedPosition; int m_monitorTerminatedOpacity; QMutex m_startedMutex; QMutex m_finishedMutex; QMutex m_terminatedMutex; QMutex m_statusMutex; }; } // namespace mitk -#endif /* _MITK_FiberBundleX_H */ +#endif /* _MITK_FiberBundle_H */ diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkTrackvis.cpp b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkTrackvis.cpp similarity index 98% rename from Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkTrackvis.cpp rename to Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkTrackvis.cpp index e63fdb8603..93bd176a51 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkTrackvis.cpp +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkTrackvis.cpp @@ -1,237 +1,237 @@ #include #include TrackVisFiberReader::TrackVisFiberReader() { m_Filename = ""; m_FilePointer = NULL; } TrackVisFiberReader::~TrackVisFiberReader() { if (m_FilePointer) fclose( m_FilePointer ); } // Create a TrackVis file and store standard metadata. The file is ready to append fibers. // --------------------------------------------------------------------------------------- -short TrackVisFiberReader::create(string filename , const mitk::FiberBundleX *fib) +short TrackVisFiberReader::create(string filename , const mitk::FiberBundle *fib) { // prepare the header for(int i=0; i<3 ;i++) { if (fib->GetReferenceGeometry().IsNotNull()) { m_Header.dim[i] = fib->GetReferenceGeometry()->GetExtent(i); m_Header.voxel_size[i] = fib->GetReferenceGeometry()->GetSpacing()[i]; m_Header.origin[i] = fib->GetReferenceGeometry()->GetOrigin()[i]; } else { m_Header.dim[i] = fib->GetGeometry()->GetExtent(i); m_Header.voxel_size[i] = fib->GetGeometry()->GetSpacing()[i]; m_Header.origin[i] = fib->GetGeometry()->GetOrigin()[i]; } } m_Header.n_scalars = 0; m_Header.n_properties = 0; sprintf(m_Header.voxel_order,"LPS"); m_Header.image_orientation_patient[0] = 1.0; m_Header.image_orientation_patient[1] = 0.0; m_Header.image_orientation_patient[2] = 0.0; m_Header.image_orientation_patient[3] = 0.0; m_Header.image_orientation_patient[4] = 1.0; m_Header.image_orientation_patient[5] = 0.0; m_Header.pad1[0] = 0; m_Header.pad1[1] = 0; m_Header.pad2[0] = 0; m_Header.pad2[1] = 0; m_Header.invert_x = 0; m_Header.invert_y = 0; m_Header.invert_z = 0; m_Header.swap_xy = 0; m_Header.swap_yz = 0; m_Header.swap_zx = 0; m_Header.n_count = 0; m_Header.version = 1; m_Header.hdr_size = 1000; // write the header to the file m_FilePointer = fopen(filename.c_str(),"w+b"); if (m_FilePointer == NULL) { printf("[ERROR] Unable to create file '%s'\n",filename.c_str()); return 0; } sprintf(m_Header.id_string,"TRACK"); if (fwrite((char*)&m_Header, 1, 1000, m_FilePointer) != 1000) MITK_ERROR << "TrackVis::create : Error occurding during writing fiber."; this->m_Filename = filename; return 1; } // Open an existing TrackVis file and read metadata information. // The file pointer is positiond at the beginning of fibers data // ------------------------------------------------------------- short TrackVisFiberReader::open( string filename ) { m_FilePointer = fopen(filename.c_str(),"r+b"); if (m_FilePointer == NULL) { printf("[ERROR] Unable to open file '%s'\n",filename.c_str()); return 0; } this->m_Filename = filename; return fread((char*)(&m_Header), 1, 1000, m_FilePointer); } // Append a fiber to the file // -------------------------- -short TrackVisFiberReader::append(const mitk::FiberBundleX *fib) +short TrackVisFiberReader::append(const mitk::FiberBundle *fib) { vtkPolyData* poly = fib->GetFiberPolyData(); for (int i=0; iGetNumFibers(); i++) { vtkCell* cell = poly->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); unsigned int numSaved, pos = 0; //float* tmp = new float[3*maxSteps]; std::vector< float > tmp; tmp.reserve(3*numPoints); numSaved = numPoints; for(unsigned int i=0; iGetPoint(i); tmp[pos++] = p[0]; tmp[pos++] = p[1]; tmp[pos++] = p[2]; } // write the coordinates to the file if ( fwrite((char*)&numSaved, 1, 4, m_FilePointer) != 4 ) { printf( "[ERROR] Problems saving the fiber!\n" ); return 1; } if ( fwrite((char*)&(tmp.front()), 1, 4*pos, m_FilePointer) != 4*pos ) { printf( "[ERROR] Problems saving the fiber!\n" ); return 1; } } return 0; } //// Read one fiber from the file //// ---------------------------- -short TrackVisFiberReader::read( mitk::FiberBundleX* fib ) +short TrackVisFiberReader::read( mitk::FiberBundle* fib ) { int numPoints; vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); while (fread((char*)&numPoints, 1, 4, m_FilePointer)==4) { if ( numPoints <= 0 ) { printf( "[ERROR] Trying to read a fiber with %d points!\n", numPoints ); return -1; } vtkSmartPointer container = vtkSmartPointer::New(); float tmp[3]; for(int i=0; iInsertNextPoint(tmp); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); fiberPolyData->SetPoints(vtkNewPoints); fiberPolyData->SetLines(vtkNewCells); MITK_INFO << "Coordinate convention: " << m_Header.voxel_order; mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); vtkSmartPointer< vtkMatrix4x4 > matrix = vtkSmartPointer< vtkMatrix4x4 >::New(); matrix->Identity(); if (m_Header.voxel_order[0]=='R') matrix->SetElement(0,0,-matrix->GetElement(0,0)); if (m_Header.voxel_order[1]=='A') matrix->SetElement(1,1,-matrix->GetElement(1,1)); if (m_Header.voxel_order[2]=='I') matrix->SetElement(2,2,-matrix->GetElement(2,2)); geometry->SetIndexToWorldTransformByVtkMatrix(matrix); vtkSmartPointer transformFilter = vtkSmartPointer::New(); transformFilter->SetInputData(fiberPolyData); transformFilter->SetTransform(geometry->GetVtkTransform()); transformFilter->Update(); fib->SetFiberPolyData(transformFilter->GetOutput()); mitk::Point3D origin; origin[0]=m_Header.origin[0]; origin[1]=m_Header.origin[1]; origin[2]=m_Header.origin[2]; geometry->SetOrigin(origin); mitk::Vector3D spacing; spacing[0]=m_Header.voxel_size[0]; spacing[1]=m_Header.voxel_size[1]; spacing[2]=m_Header.voxel_size[2]; geometry->SetSpacing(spacing); geometry->SetExtentInMM(0, m_Header.voxel_size[0]*m_Header.dim[0]); geometry->SetExtentInMM(1, m_Header.voxel_size[1]*m_Header.dim[1]); geometry->SetExtentInMM(2, m_Header.voxel_size[2]*m_Header.dim[2]); fib->SetReferenceGeometry(dynamic_cast(geometry.GetPointer())); return numPoints; } // Update the field in the header to the new FIBER TOTAL. // ------------------------------------------------------ void TrackVisFiberReader::updateTotal( int totFibers ) { fseek(m_FilePointer, 1000-12, SEEK_SET); if (fwrite((char*)&totFibers, 1, 4, m_FilePointer) != 4) MITK_ERROR << "[ERROR] Problems saving the fiber!"; } void TrackVisFiberReader::writeHdr() { fseek(m_FilePointer, 0, SEEK_SET); if (fwrite((char*)&m_Header, 1, 1000, m_FilePointer) != 1000) MITK_ERROR << "[ERROR] Problems saving the fiber!"; } // Close the TrackVis file, but keep the metadata in the header. // ------------------------------------------------------------- void TrackVisFiberReader::close() { fclose(m_FilePointer); m_FilePointer = NULL; } bool TrackVisFiberReader::IsTransformValid() { if (fabs(m_Header.image_orientation_patient[0])<=0.001 || fabs(m_Header.image_orientation_patient[3])<=0.001 || fabs(m_Header.image_orientation_patient[5])<=0.001) return false; return true; } diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkTrackvis.h b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkTrackvis.h similarity index 91% rename from Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkTrackvis.h rename to Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkTrackvis.h index 67f19e1376..2d151f3313 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkTrackvis.h +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkTrackvis.h @@ -1,82 +1,82 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _TRACKVIS #define _TRACKVIS #include -#include +#include #include #include #include #include #include #include using namespace std; // Structure to hold metadata of a TrackVis file // --------------------------------------------- struct TrackVis_header { char id_string[6]; short int dim[3]; float voxel_size[3]; float origin[3]; short int n_scalars; char scalar_name[10][20]; short int n_properties; char property_name[10][20]; char reserved[508]; char voxel_order[4]; char pad2[4]; float image_orientation_patient[6]; char pad1[2]; unsigned char invert_x; unsigned char invert_y; unsigned char invert_z; unsigned char swap_xy; unsigned char swap_yz; unsigned char swap_zx; int n_count; int version; int hdr_size; }; // Class to handle TrackVis files. // ------------------------------- class MITKFIBERTRACKING_EXPORT TrackVisFiberReader { private: string m_Filename; FILE* m_FilePointer; public: TrackVis_header m_Header; - short create(string m_Filename, const mitk::FiberBundleX* fib); + short create(string m_Filename, const mitk::FiberBundle* fib); short open( string m_Filename ); - short read( mitk::FiberBundleX* fib ); - short append(const mitk::FiberBundleX* fib ); + short read( mitk::FiberBundle* fib ); + short append(const mitk::FiberBundle* fib ); void writeHdr(); void updateTotal( int totFibers ); void close(); bool IsTransformValid(); TrackVisFiberReader(); ~TrackVisFiberReader(); }; #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Interactions/mitkFiberBundleInteractor.cpp b/Modules/DiffusionImaging/FiberTracking/Interactions/mitkFiberBundleInteractor.cpp index 29096f44b0..ba35536836 100644 --- a/Modules/DiffusionImaging/FiberTracking/Interactions/mitkFiberBundleInteractor.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Interactions/mitkFiberBundleInteractor.cpp @@ -1,240 +1,240 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkFiberBundleInteractor.h" #include #include #include #include #include #include #include #include #include #include #include -#include +#include #include "mitkBaseRenderer.h" #include #include #include #include #include #include // #include mitk::FiberBundleInteractor::FiberBundleInteractor(const char * type, DataNode* dataNode) : Interactor(type, dataNode), m_LastPosition(0) { m_LastPoint.Fill(0); } mitk::FiberBundleInteractor::~FiberBundleInteractor() {} void mitk::FiberBundleInteractor::SelectFiber(int position) { MITK_INFO << "mitk::FiberBundleInteractor::SelectFiber " << position; mitk::PointSet* pointSet = dynamic_cast(m_DataNode->GetData()); if (pointSet == NULL) return; if (pointSet->GetSize()<=0)//if List is empty, then no select of a point can be done! return; mitk::Point3D noPoint;//dummyPoint... not needed anyway noPoint.Fill(0); mitk::PointOperation* doOp = new mitk::PointOperation(OpSELECTPOINT, noPoint, position); if (m_UndoEnabled) { mitk::PointOperation* undoOp = new mitk::PointOperation(OpDESELECTPOINT, noPoint, position); OperationEvent *operationEvent = new OperationEvent(pointSet, doOp, undoOp); m_UndoController->SetOperationEvent(operationEvent); } pointSet->ExecuteOperation(doOp); } void mitk::FiberBundleInteractor::DeselectAllFibers() { MITK_INFO << "mitk::FiberBundleInteractor::DeselectAllFibers "; mitk::PointSet* pointSet = dynamic_cast(m_DataNode->GetData()); if (pointSet == NULL) return; mitk::PointSet::DataType *itkPointSet = pointSet->GetPointSet(); mitk::PointSet::PointsContainer::Iterator it, end; end = itkPointSet->GetPoints()->End(); for (it = itkPointSet->GetPoints()->Begin(); it != end; it++) { int position = it->Index(); PointSet::PointDataType pointData = {0, false, PTUNDEFINED}; itkPointSet->GetPointData(position, &pointData); if ( pointData.selected )//then declare an operation which unselects this point; UndoOperation as well! { mitk::Point3D noPoint; noPoint.Fill(0); mitk::PointOperation* doOp = new mitk::PointOperation(OpDESELECTPOINT, noPoint, position); if (m_UndoEnabled) { mitk::PointOperation* undoOp = new mitk::PointOperation(OpSELECTPOINT, noPoint, position); OperationEvent *operationEvent = new OperationEvent(pointSet, doOp, undoOp); m_UndoController->SetOperationEvent(operationEvent); } pointSet->ExecuteOperation(doOp); } } } float mitk::FiberBundleInteractor::CanHandleEvent(StateEvent const* stateEvent) const //go through all points and check, if the given Point lies near a line { mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); //checking if a keyevent can be handled: if (posEvent == 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; } } //Mouse event handling: //on MouseMove do nothing! reimplement if needed differently if (stateEvent->GetEvent()->GetType() == mitk::Type_MouseMove) { return 0; } //check on the right data-type - mitk::FiberBundleX* bundle = dynamic_cast(m_DataNode->GetData()); + mitk::FiberBundle* bundle = dynamic_cast(m_DataNode->GetData()); if (bundle == NULL) return 0; return 0.5; } bool mitk::FiberBundleInteractor::ExecuteAction( Action* action, mitk::StateEvent const* stateEvent ) { bool ok = false;//for return type bool //checking corresponding Data; has to be a PointSet or a subclass - mitk::FiberBundleX* bundle = dynamic_cast(m_DataNode->GetData()); + mitk::FiberBundle* bundle = dynamic_cast(m_DataNode->GetData()); if (bundle == NULL) return false; // Get Event and extract renderer vtkRenderWindowInteractor *renderWindowInteractor = NULL; /*Each case must watch the type of the event!*/ switch (action->GetActionId()) { case AcCHECKHOVERING: { // QApplication::restoreOverrideCursor(); // Re-enable VTK interactor (may have been disabled previously) if ( renderWindowInteractor != NULL ) { renderWindowInteractor->Enable(); } const DisplayPositionEvent *dpe = dynamic_cast< const DisplayPositionEvent * >( stateEvent->GetEvent() ); // Check if we have a DisplayPositionEvent if ( dpe != NULL ) { // Check if an object is present at the current mouse position DataNode *pickedNode = dpe->GetPickedObjectNode(); if ( pickedNode != m_DataNode ) { // if(pickedNode == 0) // MITK_INFO << "picked node is NULL, no hovering"; // else // MITK_INFO << "wrong node: " << pickedNode; this->HandleEvent( new StateEvent( EIDNOFIGUREHOVER ) ); ok = true; break; } m_CurrentPickedPoint = dpe->GetWorldPosition(); m_CurrentPickedDisplayPoint = dpe->GetDisplayPosition(); // QApplication::setOverrideCursor(Qt::UpArrowCursor); this->HandleEvent( new StateEvent( EIDFIGUREHOVER ) ); } ok = true; break; } break; // case AcSELECTPICKEDOBJECT: // MITK_INFO << "FiberBundleInteractor AcSELECTPICKEDOBJECT"; // break; // case AcDESELECTALL: // MITK_INFO << "FiberBundleInteractor AcDESELECTALL"; // break; case AcREMOVE: { MITK_INFO << "picking fiber at " << m_CurrentPickedPoint; // QmitkStdMultiWidgetEditor::Pointer multiWidgetEditor; // multiWidgetEditor->GetStdMultiWidget()->GetRenderWindow1()->GetRenderer()->GetSliceNavigationController()->SelectSliceByPoint( // m_CurrentPickedPoint); BaseRenderer* renderer = mitk::BaseRenderer::GetByName("stdmulti.widget1"); renderer->GetSliceNavigationController()->SelectSliceByPoint( m_CurrentPickedPoint); renderer = mitk::BaseRenderer::GetByName("stdmulti.widget2"); renderer->GetSliceNavigationController()->SelectSliceByPoint( m_CurrentPickedPoint); renderer = mitk::BaseRenderer::GetByName("stdmulti.widget3"); renderer->GetSliceNavigationController()->SelectSliceByPoint( m_CurrentPickedPoint); // mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } break; default: return Superclass::ExecuteAction( action, stateEvent ); } return ok; } diff --git a/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXThreadMonitorMapper3D.cpp b/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleThreadMonitorMapper3D.cpp similarity index 82% rename from Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXThreadMonitorMapper3D.cpp rename to Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleThreadMonitorMapper3D.cpp index cff4f67bb3..4402c2d72a 100644 --- a/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXThreadMonitorMapper3D.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleThreadMonitorMapper3D.cpp @@ -1,206 +1,206 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "mitkFiberBundleXThreadMonitorMapper3D.h" +#include "mitkFiberBundleThreadMonitorMapper3D.h" #include #include //#include #include -mitk::FiberBundleXThreadMonitorMapper3D::FiberBundleXThreadMonitorMapper3D() +mitk::FiberBundleThreadMonitorMapper3D::FiberBundleThreadMonitorMapper3D() : m_FiberMonitorMapper(vtkSmartPointer::New()) , m_TextActorClose(vtkSmartPointer::New()) , m_TextActorOpen(vtkSmartPointer::New()) , m_TextActorHeading(vtkSmartPointer::New()) , m_TextActorMask(vtkSmartPointer::New()) , m_TextActorStatus(vtkSmartPointer::New()) , m_TextActorStarted(vtkSmartPointer::New()) , m_TextActorFinished(vtkSmartPointer::New()) , m_TextActorTerminated(vtkSmartPointer::New()) , m_FiberAssembly(vtkPropAssembly::New()) , m_lastModifiedMonitorNodeTime(-1) { m_FiberAssembly->AddPart(m_TextActorClose); m_FiberAssembly->AddPart(m_TextActorOpen); m_FiberAssembly->AddPart(m_TextActorHeading); m_FiberAssembly->AddPart(m_TextActorMask); m_FiberAssembly->AddPart(m_TextActorStatus); m_FiberAssembly->AddPart(m_TextActorStarted); m_FiberAssembly->AddPart(m_TextActorFinished); m_FiberAssembly->AddPart(m_TextActorTerminated); } -mitk::FiberBundleXThreadMonitorMapper3D::~FiberBundleXThreadMonitorMapper3D() +mitk::FiberBundleThreadMonitorMapper3D::~FiberBundleThreadMonitorMapper3D() { m_FiberAssembly->Delete(); } -const mitk::FiberBundleXThreadMonitor* mitk::FiberBundleXThreadMonitorMapper3D::GetInput() +const mitk::FiberBundleThreadMonitor* mitk::FiberBundleThreadMonitorMapper3D::GetInput() { - return static_cast ( GetDataNode()->GetData() ); + return static_cast ( GetDataNode()->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::FiberBundleXThreadMonitorMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) +void mitk::FiberBundleThreadMonitorMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; const DataNode *node = this->GetDataNode(); if (m_lastModifiedMonitorNodeTime >= node->GetMTime()) return; m_lastModifiedMonitorNodeTime = node->GetMTime(); // MITK_INFO << m_LastUpdateTime; - FiberBundleXThreadMonitor* monitor = dynamic_cast ( GetDataNode()->GetData() ); + FiberBundleThreadMonitor* monitor = dynamic_cast ( GetDataNode()->GetData() ); // m_TextActor->SetInput( monitor->getTextL1().toStdString().c_str() ); m_TextActorClose->SetInput( monitor->getBracketClose().toStdString().c_str() ); vtkTextProperty* tpropClose = m_TextActorClose->GetTextProperty(); //tprop->SetFontFamilyToArial (); //tprop->SetLineSpacing(1.0); tpropClose->SetFontSize(16); tpropClose->SetColor(0.85,0.8,0.8); m_TextActorClose->SetDisplayPosition( monitor->getBracketClosePosition()[0], monitor->getBracketClosePosition()[1] ); //m_TextActorClose->Modified(); m_TextActorOpen->SetInput( monitor->getBracketOpen().toStdString().c_str() ); vtkTextProperty* tpropOpen = m_TextActorOpen->GetTextProperty(); //tprop->SetFontFamilyToArial (); //tprop->SetLineSpacing(1.0); tpropOpen->SetFontSize(16); tpropOpen->SetColor(0.85,0.8,0.8); m_TextActorOpen->SetDisplayPosition( monitor->getBracketOpenPosition()[0], monitor->getBracketOpenPosition()[1] ); //m_TextActorOpen->Modified(); m_TextActorHeading->SetInput( monitor->getHeading().toStdString().c_str() ); vtkTextProperty* tpropHeading = m_TextActorHeading->GetTextProperty(); tpropHeading->SetFontSize(12); tpropHeading->SetOpacity( monitor->getHeadingOpacity() * 0.1 ); tpropHeading->SetColor(0.85,0.8,0.8); m_TextActorHeading->SetDisplayPosition( monitor->getHeadingPosition()[0], monitor->getHeadingPosition()[1] ); //m_TextActorHeading->Modified(); m_TextActorMask->SetInput( monitor->getMask().toStdString().c_str() ); vtkTextProperty* tpropMask = m_TextActorMask->GetTextProperty(); tpropMask->SetFontSize(12); tpropMask->SetOpacity( monitor->getMaskOpacity() * 0.1 ); tpropMask->SetColor(1.0,1.0,1.0); m_TextActorMask->SetDisplayPosition( monitor->getMaskPosition()[0], monitor->getMaskPosition()[1] ); //m_TextActorHeading->Modified(); m_TextActorStatus->SetInput(monitor->getStatus().toStdString().c_str()); vtkTextProperty* tpropStatus = m_TextActorStatus->GetTextProperty(); tpropStatus->SetFontSize(10); tpropStatus->SetOpacity( monitor->getStatusOpacity() * 0.1 ); tpropStatus->SetColor(0.85,0.8,0.8); m_TextActorStatus->SetDisplayPosition( monitor->getStatusPosition()[0], monitor->getStatusPosition()[1] ); //m_TextActorStatus->Modified(); m_TextActorStarted->SetInput(QString::number(monitor->getStarted()).toStdString().c_str()); vtkTextProperty* tpropStarted = m_TextActorStarted->GetTextProperty(); tpropStarted->SetFontSize(12); tpropStarted->SetOpacity( monitor->getStartedOpacity() * 0.1 ); tpropStarted->SetColor(0.0,1.0,0.0); m_TextActorStarted->SetDisplayPosition( monitor->getStartedPosition()[0], monitor->getStartedPosition()[1] ); //m_TextActorStarted->Modified(); m_TextActorFinished->SetInput(QString::number(monitor->getFinished()).toStdString().c_str()); vtkTextProperty* tpropFinished = m_TextActorFinished->GetTextProperty(); tpropFinished->SetFontSize(12); tpropFinished->SetOpacity( monitor->getFinishedOpacity() * 0.1 ); tpropFinished->SetColor(1.0,1.0,1.0); m_TextActorFinished->SetDisplayPosition( monitor->getFinishedPosition()[0], monitor->getFinishedPosition()[1] ); //m_TextActorFinished->Modified(); m_TextActorTerminated->SetInput(QString::number(monitor->getTerminated()).toStdString().c_str()); vtkTextProperty* tpropTerminated = m_TextActorTerminated->GetTextProperty(); tpropTerminated->SetFontSize(12); tpropTerminated->SetOpacity( monitor->getTerminatedOpacity() * 0.1 ); tpropTerminated->SetColor(1.0,1.0,1.0); m_TextActorTerminated->SetDisplayPosition( monitor->getTerminatedPosition()[0], monitor->getTerminatedPosition()[1] ); //m_TextActorTerminated->Modified(); // Calculate time step of the input data for the specified renderer (integer value) // this method is implemented in mitkMapper // this->CalculateTimeStep( renderer ); } -void mitk::FiberBundleXThreadMonitorMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) +void mitk::FiberBundleThreadMonitorMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { -// MITK_INFO << "FiberBundleXxXXMapper3D()SetDefaultProperties"; +// MITK_INFO << "FiberBundlexXXMapper3D()SetDefaultProperties"; Superclass::SetDefaultProperties(node, renderer, overwrite); } -vtkProp* mitk::FiberBundleXThreadMonitorMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) +vtkProp* mitk::FiberBundleThreadMonitorMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { - //MITK_INFO << "FiberBundleXxXXMapper3D()GetVTKProp"; + //MITK_INFO << "FiberBundlexXXMapper3D()GetVTKProp"; //this->GenerateData(); return m_FiberAssembly; } -void mitk::FiberBundleXThreadMonitorMapper3D::ApplyProperties(mitk::BaseRenderer* renderer) +void mitk::FiberBundleThreadMonitorMapper3D::ApplyProperties(mitk::BaseRenderer* renderer) { -// MITK_INFO << "FiberBundleXXXXMapper3D ApplyProperties(renderer)"; +// MITK_INFO << "FiberBundleXXXMapper3D ApplyProperties(renderer)"; } -void mitk::FiberBundleXThreadMonitorMapper3D::UpdateVtkObjects() +void mitk::FiberBundleThreadMonitorMapper3D::UpdateVtkObjects() { -// MITK_INFO << "FiberBundleXxxXMapper3D UpdateVtkObjects()"; +// MITK_INFO << "FiberBundlexxXMapper3D UpdateVtkObjects()"; } -void mitk::FiberBundleXThreadMonitorMapper3D::SetVtkMapperImmediateModeRendering(vtkMapper *) +void mitk::FiberBundleThreadMonitorMapper3D::SetVtkMapperImmediateModeRendering(vtkMapper *) { } diff --git a/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXThreadMonitorMapper3D.h b/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleThreadMonitorMapper3D.h similarity index 79% rename from Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXThreadMonitorMapper3D.h rename to Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleThreadMonitorMapper3D.h index 266967ab92..d775152cb8 100644 --- a/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXThreadMonitorMapper3D.h +++ b/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleThreadMonitorMapper3D.h @@ -1,90 +1,90 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef FiberBundleXThreadMonitorMapper3D_H_HEADER_INCLUDED -#define FiberBundleXThreadMonitorMapper3D_H_HEADER_INCLUDED +#ifndef FiberBundleThreadMonitorMapper3D_H_HEADER_INCLUDED +#define FiberBundleThreadMonitorMapper3D_H_HEADER_INCLUDED //#include //?? necessary #include #include -#include +#include #include #include #include class vtkPropAssembly; namespace mitk { //##Documentation - //## @brief Mapper for FiberBundleX + //## @brief Mapper for FiberBundle //## @ingroup Mapper - class MITKFIBERTRACKING_EXPORT FiberBundleXThreadMonitorMapper3D : public VtkMapper + class MITKFIBERTRACKING_EXPORT FiberBundleThreadMonitorMapper3D : public VtkMapper { public: - mitkClassMacro(FiberBundleXThreadMonitorMapper3D, VtkMapper); + mitkClassMacro(FiberBundleThreadMonitorMapper3D, VtkMapper); itkFactorylessNewMacro(Self) itkCloneMacro(Self) //========== essential implementation for 3D mapper ======== - const FiberBundleXThreadMonitor* GetInput(); + const FiberBundleThreadMonitor* GetInput(); virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer); //looks like depricated.. should be replaced bz GetViewProp() static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false ); virtual void ApplyProperties(mitk::BaseRenderer* renderer); static void SetVtkMapperImmediateModeRendering(vtkMapper *mapper); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); //========================================================= protected: - FiberBundleXThreadMonitorMapper3D(); - virtual ~FiberBundleXThreadMonitorMapper3D(); + FiberBundleThreadMonitorMapper3D(); + virtual ~FiberBundleThreadMonitorMapper3D(); void UpdateVtkObjects(); //?? vtkSmartPointer m_FiberMonitorMapper; vtkSmartPointer m_TextActorClose; vtkSmartPointer m_TextActorOpen; vtkSmartPointer m_TextActorHeading; vtkSmartPointer m_TextActorMask; vtkSmartPointer m_TextActorStatus; vtkSmartPointer m_TextActorStarted; vtkSmartPointer m_TextActorFinished; vtkSmartPointer m_TextActorTerminated; vtkPropAssembly* m_FiberAssembly; private: double m_lastModifiedMonitorNodeTime; }; } // end namespace mitk -#endif /* FiberBundleXMapper3D_H_HEADER_INCLUDED */ +#endif /* FiberBundleMapper3D_H_HEADER_INCLUDED */ diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/CMakeLists.txt b/Modules/DiffusionImaging/FiberTracking/Testing/CMakeLists.txt index 3b03f3f67d..712d4ecde0 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/CMakeLists.txt +++ b/Modules/DiffusionImaging/FiberTracking/Testing/CMakeLists.txt @@ -1,14 +1,14 @@ MITK_CREATE_MODULE_TESTS() if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") -mitkAddCustomModuleTest(mitkFiberBundleXReaderWriterTest mitkFiberBundleXReaderWriterTest) +mitkAddCustomModuleTest(mitkFiberBundleReaderWriterTest mitkFiberBundleReaderWriterTest) mitkAddCustomModuleTest(mitkGibbsTrackingTest mitkGibbsTrackingTest ${MITK_DATA_DIR}/DiffusionImaging/qBallImage.qbi ${MITK_DATA_DIR}/DiffusionImaging/diffusionImageMask.nrrd ${MITK_DATA_DIR}/DiffusionImaging/gibbsTrackingParameters.gtp ${MITK_DATA_DIR}/DiffusionImaging/gibbsTractogram.fib) mitkAddCustomModuleTest(mitkStreamlineTrackingTest mitkStreamlineTrackingTest ${MITK_DATA_DIR}/DiffusionImaging/tensorImage.dti ${MITK_DATA_DIR}/DiffusionImaging/diffusionImageMask.nrrd ${MITK_DATA_DIR}/DiffusionImaging/streamlineTractogramInterpolated.fib) #mitkAddCustomModuleTest(mitkPeakExtractionTest mitkPeakExtractionTest ${MITK_DATA_DIR}/DiffusionImaging/qBallImage_SHCoeffs.nrrd ${MITK_DATA_DIR}/DiffusionImaging/diffusionImageMask.nrrd ${MITK_DATA_DIR}/DiffusionImaging/qBallImage_VectorField.fib) mitkAddCustomModuleTest(mitkLocalFiberPlausibilityTest mitkLocalFiberPlausibilityTest ${MITK_DATA_DIR}/DiffusionImaging/fiberBundleX.fib ${MITK_DATA_DIR}/DiffusionImaging/LDFP_GT_DIRECTION_0.nrrd ${MITK_DATA_DIR}/DiffusionImaging/LDFP_GT_DIRECTION_1.nrrd ${MITK_DATA_DIR}/DiffusionImaging/LDFP_ERROR_IMAGE.nrrd ${MITK_DATA_DIR}/DiffusionImaging/LDFP_NUM_DIRECTIONS.nrrd ${MITK_DATA_DIR}/DiffusionImaging/LDFP_VECTOR_FIELD.fib ${MITK_DATA_DIR}/DiffusionImaging/LDFP_ERROR_IMAGE_IGNORE.nrrd) mitkAddCustomModuleTest(mitkFiberTransformationTest mitkFiberTransformationTest ${MITK_DATA_DIR}/DiffusionImaging/fiberBundleX.fib ${MITK_DATA_DIR}/DiffusionImaging/fiberBundleX_transformed.fib) mitkAddCustomModuleTest(mitkFiberExtractionTest mitkFiberExtractionTest ${MITK_DATA_DIR}/DiffusionImaging/fiberBundleX.fib ${MITK_DATA_DIR}/DiffusionImaging/fiberBundleX_extracted.fib ${MITK_DATA_DIR}/DiffusionImaging/ROI1.pf ${MITK_DATA_DIR}/DiffusionImaging/ROI2.pf ${MITK_DATA_DIR}/DiffusionImaging/ROI3.pf ${MITK_DATA_DIR}/DiffusionImaging/ROIIMAGE.nrrd ${MITK_DATA_DIR}/DiffusionImaging/fiberBundleX_inside.fib ${MITK_DATA_DIR}/DiffusionImaging/fiberBundleX_outside.fib ${MITK_DATA_DIR}/DiffusionImaging/fiberBundleX_passing-mask.fib ${MITK_DATA_DIR}/DiffusionImaging/fiberBundleX_ending-in-mask.fib ${MITK_DATA_DIR}/DiffusionImaging/fiberBundleX_subtracted.fib ${MITK_DATA_DIR}/DiffusionImaging/fiberBundleX_added.fib) mitkAddCustomModuleTest(mitkFiberGenerationTest mitkFiberGenerationTest ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/Fiducial_0.pf ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/Fiducial_1.pf ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/Fiducial_2.pf ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/uniform.fib ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/gaussian.fib) mitkAddCustomModuleTest(mitkFiberfoxSignalGenerationTest mitkFiberfoxSignalGenerationTest ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/gaussian.fib ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/StickBall_RELAX.dwi ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/StickAstrosticks_RELAX.dwi ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/StickDot_RELAX.dwi ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/TensorBall_RELAX.dwi ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/StickTensorBall_RELAX.dwi ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/StickTensorBallAstrosticks_RELAX.dwi ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/gibbsringing.dwi ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/ghost.dwi ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/aliasing.dwi ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/eddy.dwi ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/linearmotion.dwi ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/randommotion.dwi ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/spikes.dwi ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/riciannoise.dwi ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/chisquarenoise.dwi ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/distortions.dwi ${MITK_DATA_DIR}/DiffusionImaging/Fiberfox/Fieldmap.nrrd) mitkAddCustomModuleTest(mitkFiberfoxAddArtifactsToDwiTest mitkFiberfoxAddArtifactsToDwiTest) ENDIF() diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/files.cmake b/Modules/DiffusionImaging/FiberTracking/Testing/files.cmake index 5ac537c171..a71e6776fa 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/files.cmake +++ b/Modules/DiffusionImaging/FiberTracking/Testing/files.cmake @@ -1,14 +1,14 @@ SET(MODULE_CUSTOM_TESTS - mitkFiberBundleXReaderWriterTest.cpp + mitkFiberBundleReaderWriterTest.cpp mitkGibbsTrackingTest.cpp mitkStreamlineTrackingTest.cpp mitkPeakExtractionTest.cpp mitkLocalFiberPlausibilityTest.cpp mitkFiberTransformationTest.cpp mitkFiberExtractionTest.cpp mitkFiberGenerationTest.cpp mitkFiberfoxSignalGenerationTest.cpp mitkFiberfoxAddArtifactsToDwiTest.cpp ) diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberBundleXReaderWriterTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberBundleReaderWriterTest.cpp similarity index 61% rename from Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberBundleXReaderWriterTest.cpp rename to Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberBundleReaderWriterTest.cpp index cc2a56745f..1105138c17 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberBundleXReaderWriterTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberBundleReaderWriterTest.cpp @@ -1,74 +1,71 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTestingMacros.h" -#include -#include +#include #include #include #include #include #include "mitkTestFixture.h" -class mitkFiberBundleXReaderWriterTestSuite : public mitk::TestFixture +class mitkFiberBundleReaderWriterTestSuite : public mitk::TestFixture { - CPPUNIT_TEST_SUITE(mitkFiberBundleXReaderWriterTestSuite); + CPPUNIT_TEST_SUITE(mitkFiberBundleReaderWriterTestSuite); MITK_TEST(Equal_SaveLoad_ReturnsTrue); CPPUNIT_TEST_SUITE_END(); private: /** Members used inside the different (sub-)tests. All members are initialized via setUp().*/ - mitk::FiberBundleX::Pointer fib1; - mitk::FiberBundleX::Pointer fib2; + mitk::FiberBundle::Pointer fib1; + mitk::FiberBundle::Pointer fib2; public: void setUp() { fib1 = NULL; fib2 = NULL; - const std::string s1="", s2=""; std::string filename = GetTestDataFilePath("DiffusionImaging/fiberBundleX.fib"); - std::vector fibInfile = mitk::BaseDataIO::LoadBaseDataFromFile( filename, s1, s2, false ); + std::vector fibInfile = mitk::IOUtil::Load( filename); mitk::BaseData::Pointer baseData = fibInfile.at(0); - fib1 = dynamic_cast(baseData.GetPointer()); + + fib1 = dynamic_cast(baseData.GetPointer()); } void tearDown() { fib1 = NULL; fib2 = NULL; } void Equal_SaveLoad_ReturnsTrue() { - const std::string s1="", s2=""; mitk::IOUtil::Save(fib1.GetPointer(), std::string(MITK_TEST_OUTPUT_DIR)+"/writerTest.fib"); - std::vector fibInfile = mitk::BaseDataIO::LoadBaseDataFromFile( std::string(MITK_TEST_OUTPUT_DIR)+"/writerTest.fib", s1, s2, false ); - mitk::BaseData::Pointer baseData = fibInfile.at(0); - fib2 = dynamic_cast(baseData.GetPointer()); + std::vector baseData = mitk::IOUtil::Load(std::string(MITK_TEST_OUTPUT_DIR)+"/writerTest.fib"); + fib2 = dynamic_cast(baseData[0].GetPointer()); CPPUNIT_ASSERT_MESSAGE("Should be equal", fib1->Equals(fib2)); //MITK_ASSERT_EQUAL(fib1, fib2, "A saved and re-loaded file should be equal"); } }; -MITK_TEST_SUITE_REGISTRATION(mitkFiberBundleXReaderWriter) +MITK_TEST_SUITE_REGISTRATION(mitkFiberBundleReaderWriter) diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberExtractionTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberExtractionTest.cpp index 847be12cb8..dc6fe5cc97 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberExtractionTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberExtractionTest.cpp @@ -1,109 +1,109 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include -#include +#include #include #include #include #include /**Documentation * Test if fiber transfortaiom methods work correctly */ int mitkFiberExtractionTest(int argc, char* argv[]) { MITK_TEST_BEGIN("mitkFiberExtractionTest"); /// \todo Fix VTK memory leaks. Bug 18097. vtkDebugLeaks::SetExitError(0); MITK_INFO << "argc: " << argc; MITK_TEST_CONDITION_REQUIRED(argc==13,"check for input data") try{ - mitk::FiberBundleX::Pointer groundTruthFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[1])->GetData()); - mitk::FiberBundleX::Pointer testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[2])->GetData()); + mitk::FiberBundle::Pointer groundTruthFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[1])->GetData()); + mitk::FiberBundle::Pointer testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[2])->GetData()); // test planar figure based extraction mitk::PlanarFigure::Pointer pf1 = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[3])->GetData()); mitk::PlanarFigure::Pointer pf2 = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[4])->GetData()); mitk::PlanarFigure::Pointer pf3 = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[5])->GetData()); MITK_INFO << "TEST1"; mitk::PlanarFigureComposite::Pointer pfc1 = mitk::PlanarFigureComposite::New(); pfc1->setOperationType(mitk::PFCOMPOSITION_AND_OPERATION); pfc1->addPlanarFigure(dynamic_cast(pf2.GetPointer())); pfc1->addPlanarFigure(dynamic_cast(pf3.GetPointer())); MITK_INFO << "TEST2"; mitk::PlanarFigureComposite::Pointer pfc2 = mitk::PlanarFigureComposite::New(); pfc2->setOperationType(mitk::PFCOMPOSITION_OR_OPERATION); pfc2->addPlanarFigure(dynamic_cast(pf1.GetPointer())); pfc2->addPlanarFigure(pfc1.GetPointer()); MITK_INFO << "TEST3"; - mitk::FiberBundleX::Pointer extractedFibs = groundTruthFibs->ExtractFiberSubset(pfc2); + mitk::FiberBundle::Pointer extractedFibs = groundTruthFibs->ExtractFiberSubset(pfc2); MITK_INFO << "TEST4"; MITK_TEST_CONDITION_REQUIRED(extractedFibs->Equals(testFibs),"check planar figure extraction") MITK_INFO << "TEST5"; // test subtraction and addition - mitk::FiberBundleX::Pointer notExtractedFibs = groundTruthFibs->SubtractBundle(extractedFibs); + mitk::FiberBundle::Pointer notExtractedFibs = groundTruthFibs->SubtractBundle(extractedFibs); MITK_INFO << argv[11]; - testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[11])->GetData()); + testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[11])->GetData()); MITK_TEST_CONDITION_REQUIRED(notExtractedFibs->Equals(testFibs),"check bundle subtraction") - mitk::FiberBundleX::Pointer joinded = extractedFibs->AddBundle(notExtractedFibs); - testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[12])->GetData()); + mitk::FiberBundle::Pointer joinded = extractedFibs->AddBundle(notExtractedFibs); + testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[12])->GetData()); MITK_TEST_CONDITION_REQUIRED(joinded->Equals(testFibs),"check bundle addition") // test binary image based extraction mitk::Image::Pointer mitkRoiImage = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[6])->GetData()); typedef itk::Image< unsigned char, 3 > itkUCharImageType; itkUCharImageType::Pointer itkRoiImage = itkUCharImageType::New(); mitk::CastToItkImage(mitkRoiImage, itkRoiImage); - mitk::FiberBundleX::Pointer inside = groundTruthFibs->RemoveFibersOutside(itkRoiImage, false); + mitk::FiberBundle::Pointer inside = groundTruthFibs->RemoveFibersOutside(itkRoiImage, false); mitk::IOUtil::SaveBaseData(inside, mitk::IOUtil::GetTempPath()+"inside.fib"); - mitk::FiberBundleX::Pointer outside = groundTruthFibs->RemoveFibersOutside(itkRoiImage, true); + mitk::FiberBundle::Pointer outside = groundTruthFibs->RemoveFibersOutside(itkRoiImage, true); mitk::IOUtil::SaveBaseData(outside, mitk::IOUtil::GetTempPath()+"outside.fib"); - mitk::FiberBundleX::Pointer passing = groundTruthFibs->ExtractFiberSubset(itkRoiImage, true); + mitk::FiberBundle::Pointer passing = groundTruthFibs->ExtractFiberSubset(itkRoiImage, true); mitk::IOUtil::SaveBaseData(passing, mitk::IOUtil::GetTempPath()+"passing.fib"); - mitk::FiberBundleX::Pointer ending = groundTruthFibs->ExtractFiberSubset(itkRoiImage, false); + mitk::FiberBundle::Pointer ending = groundTruthFibs->ExtractFiberSubset(itkRoiImage, false); mitk::IOUtil::SaveBaseData(ending, mitk::IOUtil::GetTempPath()+"ending.fib"); - testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[7])->GetData()); + testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[7])->GetData()); MITK_TEST_CONDITION_REQUIRED(inside->Equals(testFibs),"check inside mask extraction") - testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[8])->GetData()); + testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[8])->GetData()); MITK_TEST_CONDITION_REQUIRED(outside->Equals(testFibs),"check outside mask extraction") - testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[9])->GetData()); + testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[9])->GetData()); MITK_TEST_CONDITION_REQUIRED(passing->Equals(testFibs),"check passing mask extraction") - testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[10])->GetData()); + testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[10])->GetData()); MITK_TEST_CONDITION_REQUIRED(ending->Equals(testFibs),"check ending in mask extraction") } catch(...) { return EXIT_FAILURE; } // always end with this! MITK_TEST_END(); } diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberGenerationTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberGenerationTest.cpp index 2e06ab9d38..c4f2d01f28 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberGenerationTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberGenerationTest.cpp @@ -1,78 +1,78 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include -#include +#include #include #include /**Documentation * Test if fiber transfortaiom methods work correctly */ int mitkFiberGenerationTest(int argc, char* argv[]) { MITK_TEST_BEGIN("mitkFiberGenerationTest"); MITK_TEST_CONDITION_REQUIRED(argc==6,"check for input data") try{ mitk::PlanarEllipse::Pointer pf1 = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[1])->GetData()); mitk::PlanarEllipse::Pointer pf2 = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[2])->GetData()); mitk::PlanarEllipse::Pointer pf3 = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[3])->GetData()); - mitk::FiberBundleX::Pointer uniform = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[4])->GetData()); - mitk::FiberBundleX::Pointer gaussian = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[5])->GetData()); + mitk::FiberBundle::Pointer uniform = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[4])->GetData()); + mitk::FiberBundle::Pointer gaussian = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[5])->GetData()); FiberGenerationParameters parameters; vector< mitk::PlanarEllipse::Pointer > fid; fid.push_back(pf1); fid.push_back(pf2); fid.push_back(pf3); vector< unsigned int > flip; flip.push_back(0); flip.push_back(0); flip.push_back(0); parameters.m_Fiducials.push_back(fid); parameters.m_FlipList.push_back(flip); parameters.m_Density = 50; parameters.m_Tension = 0; parameters.m_Continuity = 0; parameters.m_Bias = 0; parameters.m_Sampling = 1; parameters.m_Variance = 0.1; // check uniform fiber distribution { itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New(); parameters.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; filter->SetParameters(parameters); filter->Update(); - vector< mitk::FiberBundleX::Pointer > fiberBundles = filter->GetFiberBundles(); + vector< mitk::FiberBundle::Pointer > fiberBundles = filter->GetFiberBundles(); MITK_TEST_CONDITION_REQUIRED(uniform->Equals(fiberBundles.at(0)),"check uniform bundle") } // check gaussian fiber distribution { itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New(); parameters.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN; filter->SetParameters(parameters); filter->SetParameters(parameters); filter->Update(); - vector< mitk::FiberBundleX::Pointer > fiberBundles = filter->GetFiberBundles(); + vector< mitk::FiberBundle::Pointer > fiberBundles = filter->GetFiberBundles(); MITK_TEST_CONDITION_REQUIRED(gaussian->Equals(fiberBundles.at(0)),"check gaussian bundle") } } catch(...) { return EXIT_FAILURE; } // always end with this! MITK_TEST_END(); } diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberTransformationTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberTransformationTest.cpp index 764fcf9fe1..9e48b3c7f1 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberTransformationTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberTransformationTest.cpp @@ -1,53 +1,53 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include -#include +#include /**Documentation * Test if fiber transfortaiom methods work correctly */ int mitkFiberTransformationTest(int argc, char* argv[]) { MITK_TEST_BEGIN("mitkFiberTransformationTest"); MITK_TEST_CONDITION_REQUIRED(argc==3,"check for input data") try{ - mitk::FiberBundleX::Pointer groundTruthFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[1])->GetData()); - mitk::FiberBundleX::Pointer transformedFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[2])->GetData()); + mitk::FiberBundle::Pointer groundTruthFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[1])->GetData()); + mitk::FiberBundle::Pointer transformedFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[2])->GetData()); groundTruthFibs->RotateAroundAxis(90, 45, 10); groundTruthFibs->TranslateFibers(2, 3, 5); groundTruthFibs->ScaleFibers(1, 0.1, 1.3); groundTruthFibs->RemoveLongFibers(150); groundTruthFibs->RemoveShortFibers(20); groundTruthFibs->ResampleSpline(1.0); groundTruthFibs->ApplyCurvatureThreshold(3.0, true); groundTruthFibs->MirrorFibers(0); groundTruthFibs->MirrorFibers(1); groundTruthFibs->MirrorFibers(2); MITK_TEST_CONDITION_REQUIRED(groundTruthFibs->Equals(transformedFibs),"check transformation") } catch(...) { return EXIT_FAILURE; } // always end with this! MITK_TEST_END(); } diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxAddArtifactsToDwiTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxAddArtifactsToDwiTest.cpp index 53622ec71b..92284a7db5 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxAddArtifactsToDwiTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxAddArtifactsToDwiTest.cpp @@ -1,199 +1,199 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include -#include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef itk::VectorImage ITKDiffusionImageType; /**Documentation * Test the Fiberfox simulation functions (diffusion weighted image -> diffusion weighted image) */ class mitkFiberfoxAddArtifactsToDwiTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkFiberfoxAddArtifactsToDwiTestSuite); MITK_TEST(Spikes); MITK_TEST(GibbsRinging); MITK_TEST(Ghost); MITK_TEST(Aliasing); MITK_TEST(Eddy); MITK_TEST(RicianNoise); MITK_TEST(ChiSquareNoise); MITK_TEST(Distortions); CPPUNIT_TEST_SUITE_END(); private: mitk::Image::Pointer m_InputDwi; FiberfoxParameters m_Parameters; public: void setUp() { // reference files m_InputDwi = dynamic_cast(mitk::IOUtil::LoadDataNode(GetTestDataFilePath("DiffusionImaging/Fiberfox/StickBall_RELAX.dwi"))->GetData()); // parameter setup ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(m_InputDwi, itkVectorImagePointer); m_Parameters = FiberfoxParameters(); m_Parameters.m_SignalGen.m_ImageRegion = itkVectorImagePointer->GetLargestPossibleRegion(); m_Parameters.m_SignalGen.m_ImageSpacing = itkVectorImagePointer->GetSpacing(); m_Parameters.m_SignalGen.m_ImageOrigin = itkVectorImagePointer->GetOrigin(); m_Parameters.m_SignalGen.m_ImageDirection = itkVectorImagePointer->GetDirection(); m_Parameters.m_SignalGen.m_Bvalue = static_cast(m_InputDwi->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(); m_Parameters.m_SignalGen.SetGradienDirections( static_cast( m_InputDwi->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); } bool CompareDwi(itk::VectorImage< short, 3 >* dwi1, itk::VectorImage< short, 3 >* dwi2) { typedef itk::VectorImage< short, 3 > DwiImageType; try{ itk::ImageRegionIterator< DwiImageType > it1(dwi1, dwi1->GetLargestPossibleRegion()); itk::ImageRegionIterator< DwiImageType > it2(dwi2, dwi2->GetLargestPossibleRegion()); while(!it1.IsAtEnd()) { if (it1.Get()!=it2.Get()) return false; ++it1; ++it2; } } catch(...) { return false; } return true; } void StartSimulation(string testFileName) { mitk::Image::Pointer refImage = NULL; if (!testFileName.empty()) CPPUNIT_ASSERT(refImage = dynamic_cast(mitk::IOUtil::LoadDataNode(testFileName)->GetData())); ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(m_InputDwi, itkVectorImagePointer); itk::AddArtifactsToDwiImageFilter< short >::Pointer artifactsToDwiFilter = itk::AddArtifactsToDwiImageFilter< short >::New(); artifactsToDwiFilter->SetUseConstantRandSeed(true); artifactsToDwiFilter->SetInput(itkVectorImagePointer); artifactsToDwiFilter->SetParameters(m_Parameters); CPPUNIT_ASSERT_NO_THROW(artifactsToDwiFilter->Update()); mitk::Image::Pointer testImage = mitk::GrabItkImageMemory( artifactsToDwiFilter->GetOutput() ); testImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( m_Parameters.m_SignalGen.GetGradientDirections() ) ); testImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( m_Parameters.m_SignalGen.m_Bvalue ) ); mitk::DiffusionPropertyHelper propertyHelper( testImage ); propertyHelper.InitializeImage(); if (refImage.IsNotNull()) { ITKDiffusionImageType::Pointer itkTestVectorImagePointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(testImage, itkTestVectorImagePointer); ITKDiffusionImageType::Pointer itkRefVectorImagePointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(refImage, itkRefVectorImagePointer); if (!CompareDwi( itkTestVectorImagePointer, itkRefVectorImagePointer)) mitk::IOUtil::SaveBaseData(testImage, mitk::IOUtil::GetTempPath()+"testImage.dwi"); CPPUNIT_ASSERT_MESSAGE(testFileName, CompareDwi( itkTestVectorImagePointer, itkRefVectorImagePointer)); } } void Spikes() { m_Parameters.m_SignalGen.m_Spikes = 5; m_Parameters.m_SignalGen.m_SpikeAmplitude = 1; StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/spikes2.dwi") ); } void GibbsRinging() { m_Parameters.m_SignalGen.m_DoAddGibbsRinging = true; StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/gibbsringing2.dwi") ); } void Ghost() { m_Parameters.m_SignalGen.m_KspaceLineOffset = 0.25; StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/ghost2.dwi") ); } void Aliasing() { m_Parameters.m_SignalGen.m_CroppingFactor = 0.4; StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/aliasing2.dwi") ); } void Eddy() { m_Parameters.m_SignalGen.m_EddyStrength = 0.05; StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/eddy2.dwi") ); } void RicianNoise() { mitk::RicianNoiseModel* ricianNoiseModel = new mitk::RicianNoiseModel(); ricianNoiseModel->SetNoiseVariance(1000000); ricianNoiseModel->SetSeed(0); m_Parameters.m_NoiseModel = ricianNoiseModel; StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/riciannoise2.dwi") ); delete m_Parameters.m_NoiseModel; } void ChiSquareNoise() { mitk::ChiSquareNoiseModel* chiSquareNoiseModel = new mitk::ChiSquareNoiseModel(); chiSquareNoiseModel->SetNoiseVariance(1000000); chiSquareNoiseModel->SetSeed(0); m_Parameters.m_NoiseModel = chiSquareNoiseModel; StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/chisquarenoise2.dwi") ); delete m_Parameters.m_NoiseModel; } void Distortions() { mitk::Image::Pointer mitkFMap = dynamic_cast(mitk::IOUtil::LoadDataNode( GetTestDataFilePath("DiffusionImaging/Fiberfox/Fieldmap.nrrd") )->GetData()); typedef itk::Image ItkDoubleImgType; ItkDoubleImgType::Pointer fMap = ItkDoubleImgType::New(); mitk::CastToItkImage(mitkFMap, fMap); m_Parameters.m_SignalGen.m_FrequencyMap = fMap; StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/distortions2.dwi") ); } }; MITK_TEST_SUITE_REGISTRATION(mitkFiberfoxAddArtifactsToDwi) diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxSignalGenerationTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxSignalGenerationTest.cpp index 1e73c01dce..7265da47be 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxSignalGenerationTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxSignalGenerationTest.cpp @@ -1,293 +1,293 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include -#include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef itk::VectorImage< short, 3> ItkDwiType; /**Documentation * Test the Fiberfox simulation functions (fiberBundle -> diffusion weighted image) */ bool CompareDwi(itk::VectorImage< short, 3 >* dwi1, itk::VectorImage< short, 3 >* dwi2) { typedef itk::VectorImage< short, 3 > DwiImageType; try{ itk::ImageRegionIterator< DwiImageType > it1(dwi1, dwi1->GetLargestPossibleRegion()); itk::ImageRegionIterator< DwiImageType > it2(dwi2, dwi2->GetLargestPossibleRegion()); while(!it1.IsAtEnd()) { if (it1.Get()!=it2.Get()) return false; ++it1; ++it2; } } catch(...) { return false; } return true; } -void StartSimulation(FiberfoxParameters parameters, FiberBundleX::Pointer fiberBundle, mitk::Image::Pointer refImage, string message) +void StartSimulation(FiberfoxParameters parameters, FiberBundle::Pointer fiberBundle, mitk::Image::Pointer refImage, string message) { itk::TractsToDWIImageFilter< short >::Pointer tractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); tractsToDwiFilter->SetUseConstantRandSeed(true); tractsToDwiFilter->SetParameters(parameters); tractsToDwiFilter->SetFiberBundle(fiberBundle); tractsToDwiFilter->Update(); mitk::Image::Pointer testImage = mitk::GrabItkImageMemory( tractsToDwiFilter->GetOutput() ); testImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( parameters.m_SignalGen.GetGradientDirections() ) ); testImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( parameters.m_SignalGen.m_Bvalue ) ); mitk::DiffusionPropertyHelper propertyHelper( testImage ); propertyHelper.InitializeImage(); if (refImage.IsNotNull()) { if( static_cast( refImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer().IsNotNull() ) { ItkDwiType::Pointer itkTestImagePointer = ItkDwiType::New(); mitk::CastToItkImage(testImage, itkTestImagePointer); ItkDwiType::Pointer itkRefImagePointer = ItkDwiType::New(); mitk::CastToItkImage(refImage, itkRefImagePointer); bool cond = CompareDwi(itkTestImagePointer, itkRefImagePointer); if (!cond) { MITK_INFO << "Saving test and rference image to " << mitk::IOUtil::GetTempPath(); mitk::IOUtil::SaveBaseData(testImage, mitk::IOUtil::GetTempPath()+"testImage.nrrd"); mitk::IOUtil::SaveBaseData(refImage, mitk::IOUtil::GetTempPath()+"refImage.nrrd"); } MITK_TEST_CONDITION_REQUIRED(cond, message); } } } int mitkFiberfoxSignalGenerationTest(int argc, char* argv[]) { MITK_TEST_BEGIN("mitkFiberfoxSignalGenerationTest"); MITK_TEST_CONDITION_REQUIRED(argc>=19,"check for input data"); // input fiber bundle - FiberBundleX::Pointer fiberBundle = dynamic_cast(mitk::IOUtil::Load(argv[1])[0].GetPointer()); + FiberBundle::Pointer fiberBundle = dynamic_cast(mitk::IOUtil::Load(argv[1])[0].GetPointer()); // reference diffusion weighted images mitk::Image::Pointer stickBall = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[2])->GetData()); mitk::Image::Pointer stickAstrosticks = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[3])->GetData()); mitk::Image::Pointer stickDot = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[4])->GetData()); mitk::Image::Pointer tensorBall = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[5])->GetData()); mitk::Image::Pointer stickTensorBall = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[6])->GetData()); mitk::Image::Pointer stickTensorBallAstrosticks = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[7])->GetData()); mitk::Image::Pointer gibbsringing = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[8])->GetData()); mitk::Image::Pointer ghost = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[9])->GetData()); mitk::Image::Pointer aliasing = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[10])->GetData()); mitk::Image::Pointer eddy = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[11])->GetData()); mitk::Image::Pointer linearmotion = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[12])->GetData()); mitk::Image::Pointer randommotion = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[13])->GetData()); mitk::Image::Pointer spikes = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[14])->GetData()); mitk::Image::Pointer riciannoise = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[15])->GetData()); mitk::Image::Pointer chisquarenoise = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[16])->GetData()); mitk::Image::Pointer distortions = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[17])->GetData()); mitk::Image::Pointer mitkFMap = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[18])->GetData()); typedef itk::Image ItkDoubleImgType; ItkDoubleImgType::Pointer fMap = ItkDoubleImgType::New(); mitk::CastToItkImage(mitkFMap, fMap); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(stickBall, itkVectorImagePointer); FiberfoxParameters parameters; parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_SignalGen.m_SignalScale = 10000; parameters.m_SignalGen.m_ImageRegion = itkVectorImagePointer->GetLargestPossibleRegion(); parameters.m_SignalGen.m_ImageSpacing = itkVectorImagePointer->GetSpacing(); parameters.m_SignalGen.m_ImageOrigin = itkVectorImagePointer->GetOrigin(); parameters.m_SignalGen.m_ImageDirection = itkVectorImagePointer->GetDirection(); parameters.m_SignalGen.m_Bvalue = static_cast(stickBall->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(); parameters.m_SignalGen.SetGradienDirections( static_cast( stickBall->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); // intra and inter axonal compartments mitk::StickModel stickModel; stickModel.SetBvalue(parameters.m_SignalGen.m_Bvalue); stickModel.SetT2(110); stickModel.SetDiffusivity(0.001); stickModel.SetGradientList(parameters.m_SignalGen.GetGradientDirections()); mitk::TensorModel tensorModel; tensorModel.SetT2(110); stickModel.SetBvalue(parameters.m_SignalGen.m_Bvalue); tensorModel.SetDiffusivity1(0.001); tensorModel.SetDiffusivity2(0.00025); tensorModel.SetDiffusivity3(0.00025); tensorModel.SetGradientList(parameters.m_SignalGen.GetGradientDirections()); // extra axonal compartment models mitk::BallModel ballModel; ballModel.SetT2(80); ballModel.SetBvalue(parameters.m_SignalGen.m_Bvalue); ballModel.SetDiffusivity(0.001); ballModel.SetGradientList(parameters.m_SignalGen.GetGradientDirections()); mitk::AstroStickModel astrosticksModel; astrosticksModel.SetT2(80); astrosticksModel.SetBvalue(parameters.m_SignalGen.m_Bvalue); astrosticksModel.SetDiffusivity(0.001); astrosticksModel.SetRandomizeSticks(true); astrosticksModel.SetSeed(0); astrosticksModel.SetGradientList(parameters.m_SignalGen.GetGradientDirections()); mitk::DotModel dotModel; dotModel.SetT2(80); dotModel.SetGradientList(parameters.m_SignalGen.GetGradientDirections()); // noise models mitk::RicianNoiseModel* ricianNoiseModel = new mitk::RicianNoiseModel(); ricianNoiseModel->SetNoiseVariance(1000000); ricianNoiseModel->SetSeed(0); // Rician noise mitk::ChiSquareNoiseModel* chiSquareNoiseModel = new mitk::ChiSquareNoiseModel(); chiSquareNoiseModel->SetNoiseVariance(1000000); chiSquareNoiseModel->SetSeed(0); try{ // Stick-Ball parameters.m_FiberModelList.push_back(&stickModel); parameters.m_NonFiberModelList.push_back(&ballModel); StartSimulation(parameters, fiberBundle, stickBall, argv[2]); // Srick-Astrosticks parameters.m_NonFiberModelList.clear(); parameters.m_NonFiberModelList.push_back(&astrosticksModel); StartSimulation(parameters, fiberBundle, stickAstrosticks, argv[3]); // Stick-Dot parameters.m_NonFiberModelList.clear(); parameters.m_NonFiberModelList.push_back(&dotModel); StartSimulation(parameters, fiberBundle, stickDot, argv[4]); // Tensor-Ball parameters.m_FiberModelList.clear(); parameters.m_FiberModelList.push_back(&tensorModel); parameters.m_NonFiberModelList.clear(); parameters.m_NonFiberModelList.push_back(&ballModel); StartSimulation(parameters, fiberBundle, tensorBall, argv[5]); // Stick-Tensor-Ball parameters.m_FiberModelList.clear(); parameters.m_FiberModelList.push_back(&stickModel); parameters.m_FiberModelList.push_back(&tensorModel); parameters.m_NonFiberModelList.clear(); parameters.m_NonFiberModelList.push_back(&ballModel); StartSimulation(parameters, fiberBundle, stickTensorBall, argv[6]); // Stick-Tensor-Ball-Astrosticks parameters.m_NonFiberModelList.push_back(&astrosticksModel); StartSimulation(parameters, fiberBundle, stickTensorBallAstrosticks, argv[7]); // Gibbs ringing parameters.m_FiberModelList.clear(); parameters.m_FiberModelList.push_back(&stickModel); parameters.m_NonFiberModelList.clear(); parameters.m_NonFiberModelList.push_back(&ballModel); parameters.m_SignalGen.m_DoAddGibbsRinging = true; StartSimulation(parameters, fiberBundle, gibbsringing, argv[8]); // Ghost parameters.m_SignalGen.m_DoAddGibbsRinging = false; parameters.m_SignalGen.m_KspaceLineOffset = 0.25; StartSimulation(parameters, fiberBundle, ghost, argv[9]); // Aliasing parameters.m_SignalGen.m_KspaceLineOffset = 0; parameters.m_SignalGen.m_CroppingFactor = 0.4; parameters.m_SignalGen.m_SignalScale = 1000; StartSimulation(parameters, fiberBundle, aliasing, argv[10]); // Eddy currents parameters.m_SignalGen.m_CroppingFactor = 1; parameters.m_SignalGen.m_SignalScale = 10000; parameters.m_SignalGen.m_EddyStrength = 0.05; StartSimulation(parameters, fiberBundle, eddy, argv[11]); // Motion (linear) parameters.m_SignalGen.m_EddyStrength = 0.0; parameters.m_SignalGen.m_DoAddMotion = true; parameters.m_SignalGen.m_DoRandomizeMotion = false; parameters.m_SignalGen.m_Translation[1] = 10; parameters.m_SignalGen.m_Rotation[2] = 90; StartSimulation(parameters, fiberBundle, linearmotion, argv[12]); // Motion (random) parameters.m_SignalGen.m_DoRandomizeMotion = true; parameters.m_SignalGen.m_Translation[1] = 5; parameters.m_SignalGen.m_Rotation[2] = 45; StartSimulation(parameters, fiberBundle, randommotion, argv[13]); // Spikes parameters.m_SignalGen.m_DoAddMotion = false; parameters.m_SignalGen.m_Spikes = 5; parameters.m_SignalGen.m_SpikeAmplitude = 1; StartSimulation(parameters, fiberBundle, spikes, argv[14]); // Rician noise parameters.m_SignalGen.m_Spikes = 0; parameters.m_NoiseModel = ricianNoiseModel; StartSimulation(parameters, fiberBundle, riciannoise, argv[15]); delete parameters.m_NoiseModel; // Chi-square noise parameters.m_NoiseModel = chiSquareNoiseModel; StartSimulation(parameters, fiberBundle, chisquarenoise, argv[16]); delete parameters.m_NoiseModel; // Distortions parameters.m_NoiseModel = NULL; parameters.m_SignalGen.m_FrequencyMap = fMap; StartSimulation(parameters, fiberBundle, distortions, argv[17]); } catch (std::exception &e) { MITK_TEST_CONDITION_REQUIRED(false, e.what()); } // always end with this! MITK_TEST_END(); } diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkGibbsTrackingTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkGibbsTrackingTest.cpp index d9fa1dfd9a..635d5d0a28 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkGibbsTrackingTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkGibbsTrackingTest.cpp @@ -1,93 +1,92 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include -#include #include -#include +#include +#include using namespace mitk; /**Documentation * Test for gibbs tracking filter */ int mitkGibbsTrackingTest(int argc, char* argv[]) { MITK_TEST_BEGIN("mitkGibbsTrackingTest"); MITK_TEST_CONDITION_REQUIRED(argc>4,"check for input data") QBallImage::Pointer mitkQballImage; Image::Pointer mitkMaskImage; - mitk::FiberBundleX::Pointer fib1; + mitk::FiberBundle::Pointer fib1; try{ MITK_INFO << "Q-Ball image: " << argv[1]; MITK_INFO << "Mask image: " << argv[2]; MITK_INFO << "Parameter file: " << argv[3]; MITK_INFO << "Reference bundle: " << argv[4]; - const std::string s1="", s2=""; - std::vector infile = mitk::BaseDataIO::LoadBaseDataFromFile( argv[1], s1, s2, false ); + std::vector infile = mitk::IOUtil::Load( argv[1]); mitkQballImage = dynamic_cast(infile.at(0).GetPointer()); MITK_TEST_CONDITION_REQUIRED(mitkQballImage.IsNotNull(),"check qball image") - infile = mitk::BaseDataIO::LoadBaseDataFromFile( argv[2], s1, s2, false ); + infile = mitk::IOUtil::Load( argv[2] ); mitkMaskImage = dynamic_cast(infile.at(0).GetPointer()); MITK_TEST_CONDITION_REQUIRED(mitkMaskImage.IsNotNull(),"check mask image") - infile = mitk::BaseDataIO::LoadBaseDataFromFile( argv[4], s1, s2, false ); - fib1 = dynamic_cast(infile.at(0).GetPointer()); + infile = mitk::IOUtil::Load( argv[4]); + fib1 = dynamic_cast(infile.at(0).GetPointer()); MITK_TEST_CONDITION_REQUIRED(fib1.IsNotNull(),"check fiber bundle") typedef itk::Vector OdfVectorType; typedef itk::Image OdfVectorImgType; typedef itk::Image MaskImgType; typedef itk::GibbsTrackingFilter GibbsTrackingFilterType; OdfVectorImgType::Pointer itk_qbi = OdfVectorImgType::New(); mitk::CastToItkImage(mitkQballImage, itk_qbi); MaskImgType::Pointer itk_mask = MaskImgType::New(); mitk::CastToItkImage(mitkMaskImage, itk_mask); GibbsTrackingFilterType::Pointer gibbsTracker = GibbsTrackingFilterType::New(); gibbsTracker->SetQBallImage(itk_qbi.GetPointer()); gibbsTracker->SetMaskImage(itk_mask); gibbsTracker->SetDuplicateImage(false); gibbsTracker->SetRandomSeed(1); gibbsTracker->SetLoadParameterFile(argv[3]); gibbsTracker->Update(); - mitk::FiberBundleX::Pointer fib2 = mitk::FiberBundleX::New(gibbsTracker->GetFiberBundle()); + mitk::FiberBundle::Pointer fib2 = mitk::FiberBundle::New(gibbsTracker->GetFiberBundle()); MITK_TEST_CONDITION_REQUIRED(fib1->Equals(fib2), "check if gibbs tracking has changed"); gibbsTracker->SetRandomSeed(0); gibbsTracker->Update(); - fib2 = mitk::FiberBundleX::New(gibbsTracker->GetFiberBundle()); + fib2 = mitk::FiberBundle::New(gibbsTracker->GetFiberBundle()); MITK_TEST_CONDITION_REQUIRED(!fib1->Equals(fib2), "check if gibbs tracking has changed after wrong seed"); } catch(...) { return EXIT_FAILURE; } // always end with this! MITK_TEST_END(); } diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkLocalFiberPlausibilityTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkLocalFiberPlausibilityTest.cpp index 1d7bd6c369..556c6d695c 100755 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkLocalFiberPlausibilityTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkLocalFiberPlausibilityTest.cpp @@ -1,167 +1,166 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include using namespace std; int mitkLocalFiberPlausibilityTest(int argc, char* argv[]) { MITK_TEST_BEGIN("mitkLocalFiberPlausibilityTest"); MITK_TEST_CONDITION_REQUIRED(argc==8,"check for input data") string fibFile = argv[1]; vector< string > referenceImages; referenceImages.push_back(argv[2]); referenceImages.push_back(argv[3]); string LDFP_ERROR_IMAGE = argv[4]; string LDFP_NUM_DIRECTIONS = argv[5]; string LDFP_VECTOR_FIELD = argv[6]; string LDFP_ERROR_IMAGE_IGNORE = argv[7]; float angularThreshold = 30; try { typedef itk::Image ItkUcharImgType; typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; typedef itk::VectorContainer< unsigned int, ItkDirectionImage3DType::Pointer > ItkDirectionImageContainerType; typedef itk::EvaluateDirectionImagesFilter< float > EvaluationFilterType; // load fiber bundle - mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); + mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); // load reference directions ItkDirectionImageContainerType::Pointer referenceImageContainer = ItkDirectionImageContainerType::New(); for (unsigned int i=0; i(mitk::IOUtil::LoadDataNode(referenceImages.at(i))->GetData()); typedef mitk::ImageToItk< ItkDirectionImage3DType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkDirectionImage3DType::Pointer itkImg = caster->GetOutput(); referenceImageContainer->InsertElement(referenceImageContainer->Size(),itkImg); } catch(...){ MITK_INFO << "could not load: " << referenceImages.at(i); } } ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); ItkDirectionImage3DType::Pointer dirImg = referenceImageContainer->GetElement(0); itkMaskImage->SetSpacing( dirImg->GetSpacing() ); itkMaskImage->SetOrigin( dirImg->GetOrigin() ); itkMaskImage->SetDirection( dirImg->GetDirection() ); itkMaskImage->SetLargestPossibleRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetBufferedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetRequestedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->Allocate(); itkMaskImage->FillBuffer(1); // extract directions from fiber bundle itk::TractsToVectorImageFilter::Pointer fOdfFilter = itk::TractsToVectorImageFilter::New(); fOdfFilter->SetFiberBundle(inputTractogram); fOdfFilter->SetMaskImage(itkMaskImage); fOdfFilter->SetAngularThreshold(cos(angularThreshold*M_PI/180)); fOdfFilter->SetNormalizeVectors(true); fOdfFilter->SetMaxNumDirections(3); fOdfFilter->SetSizeThreshold(0.3); fOdfFilter->SetUseWorkingCopy(false); fOdfFilter->SetNumberOfThreads(1); fOdfFilter->Update(); ItkDirectionImageContainerType::Pointer directionImageContainer = fOdfFilter->GetDirectionImageContainer(); // Get directions and num directions image ItkUcharImgType::Pointer numDirImage = fOdfFilter->GetNumDirectionsImage(); mitk::Image::Pointer mitkNumDirImage = mitk::Image::New(); mitkNumDirImage->InitializeByItk( numDirImage.GetPointer() ); mitkNumDirImage->SetVolume( numDirImage->GetBufferPointer() ); - mitk::FiberBundleX::Pointer testDirections = fOdfFilter->GetOutputFiberBundle(); + mitk::FiberBundle::Pointer testDirections = fOdfFilter->GetOutputFiberBundle(); //mitk::IOUtil::SaveImage(mitkNumDirImage, "/local/mitk/release-binary/MITK-superbuild/CMakeExternals/Source/MITK-Data/DiffusionImaging/LDFP_NUM_DIRECTIONS.nrrd"); //mitk::IOUtil::SaveBaseData(testDirections, "/local/mitk/release-binary/MITK-superbuild/CMakeExternals/Source/MITK-Data/DiffusionImaging/LDFP_VECTOR_FIELD.fib"); // evaluate directions with missing directions EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New(); evaluationFilter->SetImageSet(directionImageContainer); evaluationFilter->SetReferenceImageSet(referenceImageContainer); evaluationFilter->SetMaskImage(itkMaskImage); evaluationFilter->SetIgnoreMissingDirections(false); evaluationFilter->Update(); EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0); mitk::Image::Pointer mitkAngularErrorImage = mitk::Image::New(); mitkAngularErrorImage->InitializeByItk( angularErrorImage.GetPointer() ); mitkAngularErrorImage->SetVolume( angularErrorImage->GetBufferPointer() ); //mitk::IOUtil::SaveImage(mitkAngularErrorImage, "/local/mitk/release-binary/MITK-superbuild/CMakeExternals/Source/MITK-Data/DiffusionImaging/LDFP_ERROR_IMAGE.nrrd"); // evaluate directions without missing directions evaluationFilter->SetIgnoreMissingDirections(true); evaluationFilter->Update(); EvaluationFilterType::OutputImageType::Pointer angularErrorImageIgnore = evaluationFilter->GetOutput(0); mitk::Image::Pointer mitkAngularErrorImageIgnore = mitk::Image::New(); mitkAngularErrorImageIgnore->InitializeByItk( angularErrorImageIgnore.GetPointer() ); mitkAngularErrorImageIgnore->SetVolume( angularErrorImageIgnore->GetBufferPointer() ); //mitk::IOUtil::SaveImage(mitkAngularErrorImageIgnore, "/local/mitk/release-binary/MITK-superbuild/CMakeExternals/Source/MITK-Data/DiffusionImaging/LDFP_ERROR_IMAGE_IGNORE.nrrd"); mitk::Image::Pointer gtAngularErrorImageIgnore = dynamic_cast(mitk::IOUtil::LoadDataNode(LDFP_ERROR_IMAGE_IGNORE)->GetData()); mitk::Image::Pointer gtAngularErrorImage = dynamic_cast(mitk::IOUtil::LoadDataNode(LDFP_ERROR_IMAGE)->GetData()); mitk::Image::Pointer gtNumTestDirImage = dynamic_cast(mitk::IOUtil::LoadDataNode(LDFP_NUM_DIRECTIONS)->GetData()); - mitk::FiberBundleX::Pointer gtTestDirections = dynamic_cast(mitk::IOUtil::LoadDataNode(LDFP_VECTOR_FIELD)->GetData()); + mitk::FiberBundle::Pointer gtTestDirections = dynamic_cast(mitk::IOUtil::LoadDataNode(LDFP_VECTOR_FIELD)->GetData()); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(gtAngularErrorImageIgnore, mitkAngularErrorImageIgnore, 0.01, true), "Check if error images are equal (ignored missing directions)."); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(gtAngularErrorImage, mitkAngularErrorImage, 0.01, true), "Check if error images are equal."); MITK_TEST_CONDITION_REQUIRED(testDirections->Equals(gtTestDirections), "Check if vector fields are equal."); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(gtNumTestDirImage, mitkNumDirImage, 0.1, true), "Check if num direction images are equal."); } catch (itk::ExceptionObject e) { MITK_INFO << e; return EXIT_FAILURE; } catch (std::exception e) { MITK_INFO << e.what(); return EXIT_FAILURE; } catch (...) { MITK_INFO << "ERROR!?!"; return EXIT_FAILURE; } MITK_TEST_END(); } diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkPeakExtractionTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkPeakExtractionTest.cpp index 6110dc612f..fd106794d7 100755 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkPeakExtractionTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkPeakExtractionTest.cpp @@ -1,108 +1,106 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include -#include #include #include #include #include #include #include #include #include #include #include #include using namespace std; int mitkPeakExtractionTest(int argc, char* argv[]) { MITK_TEST_BEGIN("mitkStreamlineTrackingTest"); MITK_TEST_CONDITION_REQUIRED(argc>3,"check for input data") string shCoeffFileName = argv[1]; string maskFileName = argv[2]; string referenceFileName = argv[3]; MITK_INFO << "SH-coefficient file: " << shCoeffFileName; MITK_INFO << "Mask file: " << maskFileName; MITK_INFO << "Reference fiber file: " << referenceFileName; try { mitk::CoreObjectFactory::GetInstance(); mitk::Image::Pointer image = mitk::IOUtil::LoadImage(shCoeffFileName); mitk::Image::Pointer mitkMaskImage = mitk::IOUtil::LoadImage(maskFileName); typedef itk::Image ItkUcharImgType; typedef itk::FiniteDiffOdfMaximaExtractionFilter< float, 4, 20242 > MaximaExtractionFilterType; MaximaExtractionFilterType::Pointer filter = MaximaExtractionFilterType::New(); MITK_INFO << "Casting mask image ..."; ItkUcharImgType::Pointer itkMask = ItkUcharImgType::New(); mitk::CastToItkImage(mitkMaskImage, itkMask); filter->SetMaskImage(itkMask); MITK_INFO << "Casting SH image ..."; typedef mitk::ImageToItk< MaximaExtractionFilterType::CoefficientImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(image); caster->Update(); filter->SetInput(caster->GetOutput()); filter->SetMaxNumPeaks(2); filter->SetPeakThreshold(0.4); filter->SetAbsolutePeakThreshold(0.01); filter->SetAngularThreshold(25); filter->SetNormalizationMethod(MaximaExtractionFilterType::MAX_VEC_NORM); filter->SetNumberOfThreads(1); MITK_INFO << "Starting extraction ..."; filter->Update(); - mitk::FiberBundleX::Pointer fib1 = filter->GetOutputFiberBundle(); + mitk::FiberBundle::Pointer fib1 = filter->GetOutputFiberBundle(); MITK_INFO << "Loading reference ..."; - const std::string s1="", s2=""; - std::vector infile = mitk::BaseDataIO::LoadBaseDataFromFile( referenceFileName, s1, s2, false ); - mitk::FiberBundleX::Pointer fib2 = dynamic_cast(infile.at(0).GetPointer()); + std::vector infile = mitk::IOUtil::Load( referenceFileName ); + mitk::FiberBundle::Pointer fib2 = dynamic_cast(infile.at(0).GetPointer()); // TODO: reduce epsilon. strange issues with differing values between windows and linux. MITK_TEST_CONDITION_REQUIRED(fib1->Equals(fib2), "Check if tractograms are equal."); } catch (itk::ExceptionObject e) { MITK_INFO << e; return EXIT_FAILURE; } catch (std::exception e) { MITK_INFO << e.what(); return EXIT_FAILURE; } catch (...) { MITK_INFO << "ERROR!?!"; return EXIT_FAILURE; } MITK_TEST_END(); } diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkStreamlineTrackingTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkStreamlineTrackingTest.cpp index 32c55d131b..144c64b1a4 100755 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkStreamlineTrackingTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkStreamlineTrackingTest.cpp @@ -1,128 +1,127 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include -#include -#include +#include #include #include #include using namespace std; int mitkStreamlineTrackingTest(int argc, char* argv[]) { MITK_TEST_BEGIN("mitkStreamlineTrackingTest"); MITK_TEST_CONDITION_REQUIRED(argc>3,"check for input data") string dtiFileName = argv[1]; string maskFileName = argv[2]; string referenceFileName = argv[3]; MITK_INFO << "DTI file: " << dtiFileName; MITK_INFO << "Mask file: " << maskFileName; MITK_INFO << "Reference fiber file: " << referenceFileName; float minFA = 0.05; float minCurv = -1; float stepSize = -1; float tendf = 1; float tendg = 0; float minLength = 20; int numSeeds = 1; bool interpolate = true; try { MITK_INFO << "Loading tensor image ..."; typedef itk::Image< itk::DiffusionTensor3D, 3 > ItkTensorImage; mitk::TensorImage::Pointer mitkTensorImage = dynamic_cast(mitk::IOUtil::LoadDataNode(dtiFileName)->GetData()); ItkTensorImage::Pointer itk_dti = ItkTensorImage::New(); mitk::CastToItkImage(mitkTensorImage, itk_dti); MITK_INFO << "Loading seed image ..."; typedef itk::Image< unsigned char, 3 > ItkUCharImageType; mitk::Image::Pointer mitkSeedImage = mitk::IOUtil::LoadImage(maskFileName); MITK_INFO << "Loading mask image ..."; mitk::Image::Pointer mitkMaskImage = mitk::IOUtil::LoadImage(maskFileName); // instantiate tracker typedef itk::StreamlineTrackingFilter< float > FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput(itk_dti); filter->SetSeedsPerVoxel(numSeeds); filter->SetFaThreshold(minFA); filter->SetMinCurvatureRadius(minCurv); filter->SetStepSize(stepSize); filter->SetF(tendf); filter->SetG(tendg); filter->SetInterpolate(interpolate); filter->SetMinTractLength(minLength); filter->SetNumberOfThreads(1); if (mitkSeedImage.IsNotNull()) { ItkUCharImageType::Pointer mask = ItkUCharImageType::New(); mitk::CastToItkImage(mitkSeedImage, mask); filter->SetSeedImage(mask); } if (mitkMaskImage.IsNotNull()) { ItkUCharImageType::Pointer mask = ItkUCharImageType::New(); mitk::CastToItkImage(mitkMaskImage, mask); filter->SetMaskImage(mask); } filter->Update(); vtkSmartPointer fiberBundle = filter->GetFiberPolyData(); - mitk::FiberBundleX::Pointer fib1 = mitk::FiberBundleX::New(fiberBundle); + mitk::FiberBundle::Pointer fib1 = mitk::FiberBundle::New(fiberBundle); - mitk::FiberBundleX::Pointer fib2 = dynamic_cast(mitk::IOUtil::LoadDataNode(referenceFileName)->GetData()); + mitk::FiberBundle::Pointer fib2 = dynamic_cast(mitk::IOUtil::LoadDataNode(referenceFileName)->GetData()); MITK_TEST_CONDITION_REQUIRED(fib2.IsNotNull(), "Check if reference tractogram is not null."); bool ok = fib1->Equals(fib2); if (!ok) { MITK_WARN << "TEST FAILED. TRACTOGRAMS ARE NOT EQUAL!"; mitk::IOUtil::SaveBaseData(fib1, mitk::IOUtil::GetTempPath()+"testBundle.fib"); mitk::IOUtil::SaveBaseData(fib2, mitk::IOUtil::GetTempPath()+"refBundle.fib"); MITK_INFO << "OUTPUT: " << mitk::IOUtil::GetTempPath(); } MITK_TEST_CONDITION_REQUIRED(ok, "Check if tractograms are equal."); } catch (itk::ExceptionObject e) { MITK_INFO << e; return EXIT_FAILURE; } catch (std::exception e) { MITK_INFO << e.what(); return EXIT_FAILURE; } catch (...) { MITK_INFO << "ERROR!?!"; return EXIT_FAILURE; } MITK_TEST_END(); } diff --git a/Modules/DiffusionImaging/FiberTracking/files.cmake b/Modules/DiffusionImaging/FiberTracking/files.cmake index 71bb1066a5..adc2368cf2 100644 --- a/Modules/DiffusionImaging/FiberTracking/files.cmake +++ b/Modules/DiffusionImaging/FiberTracking/files.cmake @@ -1,78 +1,78 @@ set(CPP_FILES mitkFiberTrackingModuleActivator.cpp ## IO datastructures - IODataStructures/FiberBundleX/mitkFiberBundleX.cpp - IODataStructures/FiberBundleX/mitkTrackvis.cpp + IODataStructures/FiberBundle/mitkFiberBundle.cpp + IODataStructures/FiberBundle/mitkTrackvis.cpp IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp # Interactions Interactions/mitkFiberBundleInteractor.cpp # Tractography Algorithms/GibbsTracking/mitkParticleGrid.cpp Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.cpp Algorithms/GibbsTracking/mitkEnergyComputer.cpp Algorithms/GibbsTracking/mitkGibbsEnergyComputer.cpp Algorithms/GibbsTracking/mitkFiberBuilder.cpp Algorithms/GibbsTracking/mitkSphereInterpolator.cpp ) set(H_FILES - # DataStructures -> FiberBundleX - IODataStructures/FiberBundleX/mitkFiberBundleX.h - IODataStructures/FiberBundleX/mitkTrackvis.h + # DataStructures -> FiberBundle + IODataStructures/FiberBundle/mitkFiberBundle.h + IODataStructures/FiberBundle/mitkTrackvis.h IODataStructures/mitkFiberfoxParameters.h # Algorithms Algorithms/itkTractDensityImageFilter.h Algorithms/itkTractsToFiberEndingsImageFilter.h Algorithms/itkTractsToRgbaImageFilter.h # moved to DiffusionCore #Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.h Algorithms/itkFibersFromPlanarFiguresFilter.h Algorithms/itkTractsToDWIImageFilter.h Algorithms/itkTractsToVectorImageFilter.h Algorithms/itkKspaceImageFilter.h Algorithms/itkDftImageFilter.h Algorithms/itkAddArtifactsToDwiImageFilter.h Algorithms/itkFieldmapGeneratorFilter.h Algorithms/itkEvaluateDirectionImagesFilter.h Algorithms/itkEvaluateTractogramDirectionsFilter.h Algorithms/itkFiberCurvatureFilter.h # (old) Tractography Algorithms/itkGibbsTrackingFilter.h Algorithms/itkStochasticTractographyFilter.h Algorithms/itkStreamlineTrackingFilter.h Algorithms/GibbsTracking/mitkParticle.h Algorithms/GibbsTracking/mitkParticleGrid.h Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.h Algorithms/GibbsTracking/mitkSimpSamp.h Algorithms/GibbsTracking/mitkEnergyComputer.h Algorithms/GibbsTracking/mitkGibbsEnergyComputer.h Algorithms/GibbsTracking/mitkSphereInterpolator.h Algorithms/GibbsTracking/mitkFiberBuilder.h # Signal Models SignalModels/mitkDiffusionSignalModel.h SignalModels/mitkTensorModel.h SignalModels/mitkBallModel.h SignalModels/mitkDotModel.h SignalModels/mitkAstroStickModel.h SignalModels/mitkStickModel.h SignalModels/mitkRawShModel.h SignalModels/mitkDiffusionNoiseModel.h SignalModels/mitkRicianNoiseModel.h SignalModels/mitkChiSquareNoiseModel.h ) set(RESOURCE_FILES # Binary directory resources FiberTrackingLUTBaryCoords.bin FiberTrackingLUTIndices.bin # Shaders Shaders/mitkShaderFiberClipping.xml ) diff --git a/Modules/DiffusionImaging/MiniApps/CopyGeometry.cpp b/Modules/DiffusionImaging/MiniApps/CopyGeometry.cpp index fee3f5a616..6c2d96ade3 100755 --- a/Modules/DiffusionImaging/MiniApps/CopyGeometry.cpp +++ b/Modules/DiffusionImaging/MiniApps/CopyGeometry.cpp @@ -1,81 +1,77 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include -#include #include #include "mitkCommandLineParser.h" using namespace mitk; int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Copy Geometry"); parser.setCategory("Preprocessing Tools"); parser.setDescription("Copies Geometry from one image unto another"); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("in", "i", mitkCommandLineParser::InputFile, "Input:", "input image", us::Any(), false); parser.addArgument("ref", "r", mitkCommandLineParser::InputFile, "Reference:", "reference image", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputFile, "Output:", "output image", us::Any(), false); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; // mandatory arguments string imageName = us::any_cast(parsedArgs["in"]); string refImage = us::any_cast(parsedArgs["ref"]); string outImage = us::any_cast(parsedArgs["out"]); try { - const std::string s1="", s2=""; - std::vector infile = BaseDataIO::LoadBaseDataFromFile( refImage, s1, s2, false ); - Image::Pointer source = dynamic_cast(infile.at(0).GetPointer()); - infile = BaseDataIO::LoadBaseDataFromFile( imageName, s1, s2, false ); - Image::Pointer target = dynamic_cast(infile.at(0).GetPointer()); + Image::Pointer source = mitk::IOUtil::LoadImage(refImage); + Image::Pointer target = mitk::IOUtil::LoadImage(imageName); mitk::BaseGeometry* s_geom = source->GetGeometry(); mitk::BaseGeometry* t_geom = target->GetGeometry(); t_geom->SetIndexToWorldTransform(s_geom->GetIndexToWorldTransform()); target->SetGeometry(t_geom); - mitk::IOUtil::Save(target.GetPointer(), outImage.c_str()); + mitk::IOUtil::SaveImage(target, outImage); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/DICOMLoader.cpp b/Modules/DiffusionImaging/MiniApps/DICOMLoader.cpp index 40b1980dbf..9049d2e054 100644 --- a/Modules/DiffusionImaging/MiniApps/DICOMLoader.cpp +++ b/Modules/DiffusionImaging/MiniApps/DICOMLoader.cpp @@ -1,286 +1,285 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "mitkBaseDataIOFactory.h" #include "mitkImage.h" #include "mitkBaseData.h" #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include "mitkDiffusionDICOMFileReader.h" #include "mitkDICOMTagBasedSorter.h" #include "mitkDICOMSortByTag.h" #include "itkMergeDiffusionImagesFilter.h" #include static mitk::StringList& GetInputFilenames() { static mitk::StringList inputs; return inputs; } void SetInputFileNames( std::string input_directory ) { // I. Get all files in directory itksys::Directory input; input.Load( input_directory.c_str() ); // II. Push back files mitk::StringList inputlist;//, mergedlist; for( unsigned long idx=0; idxAddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0010) ); // Number of Rows tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0011) ); // Number of Columns tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0030) ); // Pixel Spacing tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0018, 0x1164) ); // Imager Pixel Spacing tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x0037) ); // Image Orientation (Patient) // TODO add tolerance parameter (l. 1572 of original code) tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0018, 0x0050) ); // Slice Thickness tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0008) ); // Number of Frames tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x0052) ); // Frame of Reference UID mitk::DICOMSortCriterion::ConstPointer sorting = mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0020, 0x0013), // instance number mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0020, 0x0012) //acquisition number ).GetPointer() ).GetPointer(); tagSorter->SetSortCriterion( sorting ); MITK_INFO("dicom.loader.read.init") << "[]" ; MITK_INFO("dicom.loader.read.inputs") << " " << input_files.size(); gdcmReader->SetInputFiles( input_files ); gdcmReader->AddSortingElement( tagSorter ); gdcmReader->AnalyzeInputFiles(); gdcmReader->LoadImages(); mitk::Image::Pointer loaded_image = gdcmReader->GetOutput(0).GetMitkImage(); return loaded_image; } typedef short DiffusionPixelType; typedef itk::VectorImage DwiImageType; typedef DwiImageType::PixelType DwiPixelType; typedef DwiImageType::RegionType DwiRegionType; typedef std::vector< DwiImageType::Pointer > DwiImageContainerType; typedef mitk::Image DiffusionImageType; typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientContainerType; typedef std::vector< GradientContainerType::Pointer > GradientListContainerType; void SearchForInputInSubdirs( std::string root_directory, std::string subdir_prefix , std::vector& output_container) { // I. Get all dirs in directory itksys::Directory rootdir; rootdir.Load( root_directory.c_str() ); MITK_INFO("dicom.loader.setinputdirs.start") << "Prefix = " << subdir_prefix; for( unsigned int idx=0; idx parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) { return EXIT_FAILURE; } std::string inputDirectory = us::any_cast( parsedArgs["inputdir"] ); MITK_INFO << "Loading data from directory: " << inputDirectory; // retrieve the prefix flag (if set) bool search_for_subdirs = false; std::string subdir_prefix; if( parsedArgs.count("dwprefix")) { subdir_prefix = us::any_cast( parsedArgs["dwprefix"] ); if (subdir_prefix != "") { MITK_INFO << "Prefix specified, will search for subdirs in the input directory!"; search_for_subdirs = true; } } // retrieve the output std::string outputFile = us::any_cast< std::string >( parsedArgs["output"] ); // if the executable is called with a single directory, just parse the given folder for files and read them into a diffusion image if( !search_for_subdirs ) { SetInputFileNames( inputDirectory ); MITK_INFO << "Got " << GetInputFilenames().size() << " input files."; mitk::Image::Pointer d_img = ReadInDICOMFiles( GetInputFilenames(), outputFile ); try { mitk::IOUtil::Save(d_img, outputFile.c_str()); } catch( const itk::ExceptionObject& e) { MITK_ERROR << "Failed to write out the output file. \n\t Reason : ITK Exception " << e.what(); } } // if the --dwprefix flag is set, then we have to look for the directories, load each of them separately and afterwards merge the images else { std::vector output_container; SearchForInputInSubdirs( inputDirectory, subdir_prefix, output_container ); // final output image mitk::Image::Pointer image = mitk::Image::New(); if( output_container.size() > 1 ) { DwiImageContainerType imageContainer; GradientListContainerType gradientListContainer; std::vector< double > bValueContainer; for ( std::vector< mitk::Image::Pointer >::iterator dwi = output_container.begin(); dwi != output_container.end(); ++dwi ) { mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(*dwi, itkVectorImagePointer); imageContainer.push_back(itkVectorImagePointer); gradientListContainer.push_back( mitk::DiffusionPropertyHelper::GetGradientContainer(*dwi)); bValueContainer.push_back( mitk::DiffusionPropertyHelper::GetReferenceBValue(*dwi)); } typedef itk::MergeDiffusionImagesFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetImageVolumes(imageContainer); filter->SetGradientLists(gradientListContainer); filter->SetBValues(bValueContainer); filter->Update(); vnl_matrix_fixed< double, 3, 3 > mf; mf.set_identity(); image = mitk::GrabItkImageMemory( filter->GetOutput() ); image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetOutputGradients() ) ); image->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( filter->GetB_Value() ) ); image->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( mf ) ); mitk::DiffusionPropertyHelper propertyHelper( image ); propertyHelper.InitializeImage(); } // just output the image if there was only one folder found else { image = output_container.at(0); } MITK_INFO("dicom.import.writeout") << " [OutputFile] " << outputFile.c_str(); try { mitk::IOUtil::Save(image, outputFile.c_str()); } catch( const itk::ExceptionObject& e) { MITK_ERROR << "Failed to write out the output file. \n\t Reason : ITK Exception " << e.what(); } } return 1; } diff --git a/Modules/DiffusionImaging/MiniApps/DiffusionIndices.cpp b/Modules/DiffusionImaging/MiniApps/DiffusionIndices.cpp index 1e7d950ae2..bd92f97e4d 100644 --- a/Modules/DiffusionImaging/MiniApps/DiffusionIndices.cpp +++ b/Modules/DiffusionImaging/MiniApps/DiffusionIndices.cpp @@ -1,144 +1,143 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include -#include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include +#include /** * Calculate indices derived from Qball or tensor images */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Diffusion Indices"); parser.setCategory("Diffusion Related Measures"); parser.setDescription("Computes requested diffusion related measures"); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input image (tensor, Q-ball or FSL/MRTrix SH-coefficient image)", us::Any(), false); parser.addArgument("index", "idx", mitkCommandLineParser::String, "Index:", "index (fa, gfa, ra, ad, rd, ca, l2, l3, md)", us::Any(), false); parser.addArgument("outFile", "o", mitkCommandLineParser::OutputFile, "Output:", "output file", us::Any(), false); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string inFileName = us::any_cast(parsedArgs["input"]); string index = us::any_cast(parsedArgs["index"]); string outFileName = us::any_cast(parsedArgs["outFile"]); string ext = itksys::SystemTools::GetFilenameLastExtension(outFileName); if (ext.empty()) outFileName += ".nrrd"; try { // load input image - const std::string s1="", s2=""; - std::vector infile = mitk::BaseDataIO::LoadBaseDataFromFile( inFileName, s1, s2, false ); + std::vector infile = mitk::IOUtil::Load( inFileName ); if( boost::algorithm::ends_with(inFileName, ".qbi") && index=="gfa" ) { typedef itk::Vector OdfVectorType; typedef itk::Image ItkQballImageType; - mitk::QBallImage::Pointer mitkQballImage = dynamic_cast(infile.at(0).GetPointer()); + mitk::QBallImage::Pointer mitkQballImage = dynamic_cast(infile[0].GetPointer()); ItkQballImageType::Pointer itk_qbi = ItkQballImageType::New(); mitk::CastToItkImage(mitkQballImage, itk_qbi); typedef itk::DiffusionQballGeneralizedFaImageFilter GfaFilterType; GfaFilterType::Pointer gfaFilter = GfaFilterType::New(); gfaFilter->SetInput(itk_qbi); gfaFilter->SetComputationMethod(GfaFilterType::GFA_STANDARD); gfaFilter->Update(); itk::ImageFileWriter< itk::Image >::Pointer fileWriter = itk::ImageFileWriter< itk::Image >::New(); fileWriter->SetInput(gfaFilter->GetOutput()); fileWriter->SetFileName(outFileName); fileWriter->Update(); } else if( boost::algorithm::ends_with(inFileName, ".dti") ) { typedef itk::Image< itk::DiffusionTensor3D, 3 > ItkTensorImage; - mitk::TensorImage::Pointer mitkTensorImage = dynamic_cast(infile.at(0).GetPointer()); + mitk::TensorImage::Pointer mitkTensorImage = dynamic_cast(infile[0].GetPointer()); ItkTensorImage::Pointer itk_dti = ItkTensorImage::New(); mitk::CastToItkImage(mitkTensorImage, itk_dti); typedef itk::TensorDerivedMeasurementsFilter MeasurementsType; MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itk_dti.GetPointer() ); if(index=="fa") measurementsCalculator->SetMeasure(MeasurementsType::FA); else if(index=="ra") measurementsCalculator->SetMeasure(MeasurementsType::RA); else if(index=="ad") measurementsCalculator->SetMeasure(MeasurementsType::AD); else if(index=="rd") measurementsCalculator->SetMeasure(MeasurementsType::RD); else if(index=="ca") measurementsCalculator->SetMeasure(MeasurementsType::CA); else if(index=="l2") measurementsCalculator->SetMeasure(MeasurementsType::L2); else if(index=="l3") measurementsCalculator->SetMeasure(MeasurementsType::L3); else if(index=="md") measurementsCalculator->SetMeasure(MeasurementsType::MD); else { MITK_WARN << "No valid diffusion index for input image (tensor image) defined"; return EXIT_FAILURE; } measurementsCalculator->Update(); itk::ImageFileWriter< itk::Image >::Pointer fileWriter = itk::ImageFileWriter< itk::Image >::New(); fileWriter->SetInput(measurementsCalculator->GetOutput()); fileWriter->SetFileName(outFileName); fileWriter->Update(); } else std::cout << "Diffusion index " << index << " not supported for supplied file type."; } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/DwiDenoising.cpp b/Modules/DiffusionImaging/MiniApps/DwiDenoising.cpp index e611fa8580..19bc0c9511 100644 --- a/Modules/DiffusionImaging/MiniApps/DwiDenoising.cpp +++ b/Modules/DiffusionImaging/MiniApps/DwiDenoising.cpp @@ -1,162 +1,144 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include -#include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include #include typedef mitk::Image DiffusionImageType; typedef itk::Image ImageType; -mitk::BaseData::Pointer LoadFile(std::string filename) -{ - if( filename.empty() ) - return NULL; - - const std::string s1="", s2=""; - std::vector infile = mitk::BaseDataIO::LoadBaseDataFromFile( filename, s1, s2, false ); - if( infile.empty() ) - { - std::cout << "File " << filename << " could not be read!"; - return NULL; - } - - mitk::BaseData::Pointer baseData = infile.at(0); - return baseData; -} - /** * Denoises DWI using the Nonlocal - Means algorithm */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("DWI Denoising"); parser.setCategory("Preprocessing Tools"); parser.setContributor("MBI"); parser.setDescription("Denoising for diffusion weighted images using a non-local means algorithm."); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input image (DWI)", us::Any(), false); parser.addArgument("variance", "v", mitkCommandLineParser::Float, "Variance:", "noise variance", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::InputFile, "Mask:", "brainmask for input image", us::Any(), true); parser.addArgument("search", "s", mitkCommandLineParser::Int, "Search radius:", "search radius", us::Any(), true); parser.addArgument("compare", "c", mitkCommandLineParser::Int, "Comparison radius:", "comparison radius", us::Any(), true); parser.addArgument("joint", "j", mitkCommandLineParser::Bool, "Joint information:", "use joint information"); parser.addArgument("rician", "r", mitkCommandLineParser::Bool, "Rician adaption:", "use rician adaption"); parser.changeParameterGroup("Output", "Output of this miniapp"); parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output:", "output image (DWI)", us::Any(), false); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string inFileName = us::any_cast(parsedArgs["input"]); double variance = static_cast(us::any_cast(parsedArgs["variance"])); string maskName; if (parsedArgs.count("mask")) maskName = us::any_cast(parsedArgs["mask"]); string outFileName = us::any_cast(parsedArgs["output"]); // boost::algorithm::erase_all(outFileName, ".dwi"); int search = 4; if (parsedArgs.count("search")) search = us::any_cast(parsedArgs["search"]); int compare = 1; if (parsedArgs.count("compare")) compare = us::any_cast(parsedArgs["compare"]); bool joint = false; if (parsedArgs.count("joint")) joint = true; bool rician = false; if (parsedArgs.count("rician")) rician = true; try { if( boost::algorithm::ends_with(inFileName, ".dwi")) { - DiffusionImageType::Pointer dwi = dynamic_cast(LoadFile(inFileName).GetPointer()); + DiffusionImageType::Pointer dwi = mitk::IOUtil::LoadImage(inFileName); mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); itk::NonLocalMeansDenoisingFilter::Pointer filter = itk::NonLocalMeansDenoisingFilter::New(); filter->SetNumberOfThreads(12); filter->SetInputImage( itkVectorImagePointer ); if (!maskName.empty()) { - mitk::Image::Pointer mask = dynamic_cast(LoadFile(maskName).GetPointer()); + mitk::Image::Pointer mask = mitk::IOUtil::LoadImage(maskName); ImageType::Pointer itkMask = ImageType::New(); mitk::CastToItkImage(mask, itkMask); filter->SetInputMask(itkMask); } filter->SetUseJointInformation(joint); filter->SetUseRicianAdaption(rician); filter->SetSearchRadius(search); filter->SetComparisonRadius(compare); filter->SetVariance(variance); filter->Update(); DiffusionImageType::Pointer output = mitk::GrabItkImageMemory( filter->GetOutput() ); output->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi) ) ); output->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi) ) ); mitk::DiffusionPropertyHelper propertyHelper( output ); propertyHelper.InitializeImage(); // std::stringstream name; // name << outFileName << "_NLM_" << search << "-" << compare << "-" << variance << ".dwi"; mitk::IOUtil::Save(output, outFileName.c_str()); } else { std::cout << "Only supported for .dwi!"; } } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/ExportShImage.cpp b/Modules/DiffusionImaging/MiniApps/ExportShImage.cpp index 385489228b..242ad2fcb8 100755 --- a/Modules/DiffusionImaging/MiniApps/ExportShImage.cpp +++ b/Modules/DiffusionImaging/MiniApps/ExportShImage.cpp @@ -1,136 +1,135 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include template int StartShConversion(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Export SH Image"); parser.setCategory("Preprocessing Tools"); parser.setDescription(" "); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "MITK SH image", us::Any(), false); parser.addArgument("output", "o", mitkCommandLineParser::InputFile, "Output", "MRtrix SH image", us::Any(), false); parser.addArgument("shOrder", "sh", mitkCommandLineParser::Int, "SH order:", "spherical harmonics order"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string inFile = us::any_cast(parsedArgs["input"]); string outFile = us::any_cast(parsedArgs["output"]); try { typedef itk::Image< float, 4 > OutImageType; typedef itk::Image< itk::Vector< float, (shOrder*shOrder + shOrder + 2)/2 + shOrder >, 3 > InputImageType; typename InputImageType::Pointer itkInImage = InputImageType::New(); typedef itk::ImageFileReader< InputImageType > ReaderType; typename ReaderType::Pointer reader = ReaderType::New(); std::cout << "reading " << inFile; reader->SetFileName(inFile.c_str()); reader->Update(); itkInImage = reader->GetOutput(); // extract directions from fiber bundle typename itk::ShCoefficientImageExporter::Pointer filter = itk::ShCoefficientImageExporter::New(); filter->SetInputImage(itkInImage); filter->GenerateData(); OutImageType::Pointer outImage = filter->GetOutputImage(); typedef itk::ImageFileWriter< OutImageType > WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetFileName(outFile.c_str()); writer->SetInput(outImage); writer->Update(); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input image", "MITK SH image", us::Any(), false); parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output image", "MRtrix SH image", us::Any(), false); parser.addArgument("shOrder", "sh", mitkCommandLineParser::Int, "Spherical harmonics order", "spherical harmonics order"); parser.setCategory("Preprocessing Tools"); parser.setTitle("Export SH Image"); parser.setDescription(" "); parser.setContributor("MBI"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; int shOrder = -1; if (parsedArgs.count("shOrder")) shOrder = us::any_cast(parsedArgs["shOrder"]); switch (shOrder) { case 4: return StartShConversion<4>(argc, argv); case 6: return StartShConversion<6>(argc, argv); case 8: return StartShConversion<8>(argc, argv); case 10: return StartShConversion<10>(argc, argv); case 12: return StartShConversion<12>(argc, argv); } return EXIT_FAILURE; } diff --git a/Modules/DiffusionImaging/MiniApps/FiberDirectionExtraction.cpp b/Modules/DiffusionImaging/MiniApps/FiberDirectionExtraction.cpp index 85643a5636..b7e01c9e99 100755 --- a/Modules/DiffusionImaging/MiniApps/FiberDirectionExtraction.cpp +++ b/Modules/DiffusionImaging/MiniApps/FiberDirectionExtraction.cpp @@ -1,174 +1,173 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Fiber Direction Extraction"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setDescription(" "); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input tractogram (.fib/.trk)", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output root", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::InputFile, "Mask:", "mask image"); parser.addArgument("athresh", "a", mitkCommandLineParser::Float, "Angular threshold:", "angular threshold in degrees. closer fiber directions are regarded as one direction and clustered together.", 25, true); parser.addArgument("peakthresh", "t", mitkCommandLineParser::Float, "Peak size threshold:", "peak size threshold relative to largest peak in voxel", 0.2, true); parser.addArgument("verbose", "v", mitkCommandLineParser::Bool, "Verbose:", "output optional and intermediate calculation results"); parser.addArgument("numdirs", "d", mitkCommandLineParser::Int, "Max. num. directions:", "maximum number of fibers per voxel", 3, true); parser.addArgument("normalize", "n", mitkCommandLineParser::Bool, "Normalize:", "normalize vectors"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string fibFile = us::any_cast(parsedArgs["input"]); string maskImage(""); if (parsedArgs.count("mask")) maskImage = us::any_cast(parsedArgs["mask"]); float peakThreshold = 0.2; if (parsedArgs.count("peakthresh")) peakThreshold = us::any_cast(parsedArgs["peakthresh"]); float angularThreshold = 25; if (parsedArgs.count("athresh")) angularThreshold = us::any_cast(parsedArgs["athresh"]); string outRoot = us::any_cast(parsedArgs["out"]); bool verbose = false; if (parsedArgs.count("verbose")) verbose = us::any_cast(parsedArgs["verbose"]); int maxNumDirs = 3; if (parsedArgs.count("numdirs")) maxNumDirs = us::any_cast(parsedArgs["numdirs"]); bool normalize = false; if (parsedArgs.count("normalize")) normalize = us::any_cast(parsedArgs["normalize"]); try { typedef itk::Image ItkUcharImgType; typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; typedef itk::VectorContainer< unsigned int, ItkDirectionImage3DType::Pointer > ItkDirectionImageContainerType; // load fiber bundle - mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); + mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); // load/create mask image ItkUcharImgType::Pointer itkMaskImage = NULL; if (maskImage.compare("")!=0) { std::cout << "Using mask image"; itkMaskImage = ItkUcharImgType::New(); mitk::Image::Pointer mitkMaskImage = dynamic_cast(mitk::IOUtil::LoadDataNode(maskImage)->GetData()); mitk::CastToItkImage(mitkMaskImage, itkMaskImage); } // extract directions from fiber bundle itk::TractsToVectorImageFilter::Pointer fOdfFilter = itk::TractsToVectorImageFilter::New(); fOdfFilter->SetFiberBundle(inputTractogram); fOdfFilter->SetMaskImage(itkMaskImage); fOdfFilter->SetAngularThreshold(cos(angularThreshold*M_PI/180)); fOdfFilter->SetNormalizeVectors(normalize); fOdfFilter->SetUseWorkingCopy(false); fOdfFilter->SetSizeThreshold(peakThreshold); fOdfFilter->SetMaxNumDirections(maxNumDirs); fOdfFilter->Update(); ItkDirectionImageContainerType::Pointer directionImageContainer = fOdfFilter->GetDirectionImageContainer(); // write direction images for (unsigned int i=0; iSize(); i++) { itk::TractsToVectorImageFilter::ItkDirectionImageType::Pointer itkImg = directionImageContainer->GetElement(i); typedef itk::ImageFileWriter< itk::TractsToVectorImageFilter::ItkDirectionImageType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_DIRECTION_"); outfilename.append(boost::lexical_cast(i)); outfilename.append(".nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(itkImg); writer->Update(); } if (verbose) { // write vector field - mitk::FiberBundleX::Pointer directions = fOdfFilter->GetOutputFiberBundle(); + mitk::FiberBundle::Pointer directions = fOdfFilter->GetOutputFiberBundle(); string outfilename = outRoot; outfilename.append("_VECTOR_FIELD.fib"); mitk::IOUtil::SaveBaseData(directions.GetPointer(), outfilename ); // write num direction image { ItkUcharImgType::Pointer numDirImage = fOdfFilter->GetNumDirectionsImage(); typedef itk::ImageFileWriter< ItkUcharImgType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_NUM_DIRECTIONS.nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(numDirImage); writer->Update(); } } } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/FiberExtraction.cpp b/Modules/DiffusionImaging/MiniApps/FiberExtraction.cpp index 802a70f1e4..b038c2526c 100755 --- a/Modules/DiffusionImaging/MiniApps/FiberExtraction.cpp +++ b/Modules/DiffusionImaging/MiniApps/FiberExtraction.cpp @@ -1,155 +1,154 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include -#include +#include #include #include #define _USE_MATH_DEFINES #include int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Fiber Extraction"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setContributor("MBI"); parser.setDescription(" "); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::String, "Input:", "input tractogram (.fib/.trk)", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::String, "Output:", "output tractogram", us::Any(), false); parser.addArgument("planfirgure1", "pf1", mitkCommandLineParser::String, "Figure 1:", "first ROI", us::Any(), false); parser.addArgument("planfirgure2", "pf2", mitkCommandLineParser::String, "Figure 2:", "second ROI", us::Any()); parser.addArgument("operation", "op", mitkCommandLineParser::String, "Operation:", "logical operation (AND, OR, NOT)", us::Any()); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string inFib = us::any_cast(parsedArgs["input"]); string outFib = us::any_cast(parsedArgs["out"]); string pf1_path = us::any_cast(parsedArgs["planfirgure1"]); string operation(""); string pf2_path(""); if (parsedArgs.count("operation")) { operation = us::any_cast(parsedArgs["operation"]); if (parsedArgs.count("planfirgure2") && (operation=="AND" || operation=="OR")) pf2_path = us::any_cast(parsedArgs["planfirgure2"]); } try { typedef itk::Image ItkUcharImgType; // load fiber bundle - mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(inFib)->GetData()); - mitk::FiberBundleX::Pointer result; + mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(inFib)->GetData()); + mitk::FiberBundle::Pointer result; mitk::BaseData::Pointer input1 = mitk::IOUtil::LoadDataNode(pf1_path)->GetData(); mitk::PlanarFigure::Pointer pf1 = dynamic_cast(input1.GetPointer()); if (pf1.IsNotNull()) { mitk::BaseData::Pointer input2; mitk::PlanarFigure::Pointer pf2; if (!pf2_path.empty()) { input2 = mitk::IOUtil::LoadDataNode(pf2_path)->GetData(); pf2 = dynamic_cast(input2.GetPointer()); } mitk::PlanarFigureComposite::Pointer pfc = mitk::PlanarFigureComposite::New(); if (operation.empty()) { result = inputTractogram->ExtractFiberSubset(input1); } else if (operation=="NOT") { pfc->setOperationType(mitk::PFCOMPOSITION_NOT_OPERATION); pfc->addPlanarFigure(input1); result = inputTractogram->ExtractFiberSubset(pfc); } else if (operation=="AND" && pf2.IsNotNull()) { pfc->setOperationType(mitk::PFCOMPOSITION_AND_OPERATION); pfc->addPlanarFigure(input1); pfc->addPlanarFigure(input2); result = inputTractogram->ExtractFiberSubset(pfc); } else if (operation=="OR" && pf2.IsNotNull()) { pfc->setOperationType(mitk::PFCOMPOSITION_OR_OPERATION); pfc->addPlanarFigure(input1); pfc->addPlanarFigure(input2); result = inputTractogram->ExtractFiberSubset(pfc); } else { std::cout << "Could not process input:"; std::cout << pf1_path; std::cout << pf2_path; std::cout << operation; } } else { ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); mitk::Image::Pointer mitkMaskImage = dynamic_cast(mitk::IOUtil::LoadDataNode(pf1_path)->GetData()); mitk::CastToItkImage(mitkMaskImage, itkMaskImage); if (operation=="NOT") result = inputTractogram->ExtractFiberSubset(itkMaskImage, true, true); else result = inputTractogram->ExtractFiberSubset(itkMaskImage, true, false); } if (result.IsNotNull()) mitk::IOUtil::SaveBaseData(result, outFib); else std::cout << "No valid fiber bundle extracted."; } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/FiberJoin.cpp b/Modules/DiffusionImaging/MiniApps/FiberJoin.cpp index 5e8dd0c7c3..6cbeb3248b 100755 --- a/Modules/DiffusionImaging/MiniApps/FiberJoin.cpp +++ b/Modules/DiffusionImaging/MiniApps/FiberJoin.cpp @@ -1,89 +1,89 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "MiniAppManager.h" #include #include #include "ctkCommandLineParser.h" #include #include #include #include #include #include -#include +#include #define _USE_MATH_DEFINES #include int FiberJoin(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Fiber Join"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setContributor("MBI"); parser.setDescription(""); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::StringList, "Input:", "input tractograms (.fib, vtk file format)", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::String, "Output:", "output tractogram", us::Any(), false); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; mitkCommandLineParser::StringContainerType inFibs = us::any_cast(parsedArgs["input"]); string outFib = us::any_cast(parsedArgs["out"]); if (inFibs.size()<=1) { std::cout << "More than one input tractogram required!"; return EXIT_FAILURE; } try { - mitk::FiberBundleX::Pointer result = dynamic_cast(mitk::IOUtil::LoadDataNode(inFibs.at(0))->GetData()); + mitk::FiberBundle::Pointer result = dynamic_cast(mitk::IOUtil::LoadDataNode(inFibs.at(0))->GetData()); for (int i=1; i(mitk::IOUtil::LoadDataNode(inFibs.at(i))->GetData()); + mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(inFibs.at(i))->GetData()); result = result->AddBundle(inputTractogram); } catch(...){ std::cout << "could not load: " << inFibs.at(i); } } mitk::IOUtil::SaveBaseData(result, outFib); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } RegisterDiffusionMiniApp(FiberJoin); diff --git a/Modules/DiffusionImaging/MiniApps/FiberProcessing.cpp b/Modules/DiffusionImaging/MiniApps/FiberProcessing.cpp index 3408851a97..4314696bd2 100644 --- a/Modules/DiffusionImaging/MiniApps/FiberProcessing.cpp +++ b/Modules/DiffusionImaging/MiniApps/FiberProcessing.cpp @@ -1,206 +1,203 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include -#include #include -#include +#include #include "mitkCommandLineParser.h" #include #include #include -mitk::FiberBundleX::Pointer LoadFib(std::string filename) +mitk::FiberBundle::Pointer LoadFib(std::string filename) { - const std::string s1="", s2=""; - std::vector fibInfile = mitk::BaseDataIO::LoadBaseDataFromFile( filename, s1, s2, false ); + std::vector fibInfile = mitk::IOUtil::Load(filename); if( fibInfile.empty() ) std::cout << "File " << filename << " could not be read!"; - mitk::BaseData::Pointer baseData = fibInfile.at(0); - return dynamic_cast(baseData.GetPointer()); + return dynamic_cast(baseData.GetPointer()); } int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Fiber Processing"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setDescription(" "); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input fiber bundle (.fib)", us::Any(), false); parser.addArgument("outFile", "o", mitkCommandLineParser::OutputFile, "Output:", "output fiber bundle (.fib)", us::Any(), false); parser.addArgument("smooth", "s", mitkCommandLineParser::Float, "Spline resampling:", "Resample fiber using splines with the given point distance (in mm)"); parser.addArgument("compress", "c", mitkCommandLineParser::Float, "Compress:", "Compress fiber using the given error threshold (in mm)"); parser.addArgument("minLength", "l", mitkCommandLineParser::Float, "Minimum length:", "Minimum fiber length (in mm)"); parser.addArgument("maxLength", "m", mitkCommandLineParser::Float, "Maximum length:", "Maximum fiber length (in mm)"); parser.addArgument("minCurv", "a", mitkCommandLineParser::Float, "Minimum curvature radius:", "Minimum curvature radius (in mm)"); parser.addArgument("mirror", "p", mitkCommandLineParser::Int, "Invert coordinates:", "Invert fiber coordinates XYZ (e.g. 010 to invert y-coordinate of each fiber point)"); parser.addArgument("rotate-x", "rx", mitkCommandLineParser::Float, "Rotate x-axis:", "Rotate around x-axis (if copy is given the copy is rotated, in deg)"); parser.addArgument("rotate-y", "ry", mitkCommandLineParser::Float, "Rotate y-axis:", "Rotate around y-axis (if copy is given the copy is rotated, in deg)"); parser.addArgument("rotate-z", "rz", mitkCommandLineParser::Float, "Rotate z-axis:", "Rotate around z-axis (if copy is given the copy is rotated, in deg)"); parser.addArgument("scale-x", "sx", mitkCommandLineParser::Float, "Scale x-axis:", "Scale in direction of x-axis (if copy is given the copy is scaled)"); parser.addArgument("scale-y", "sy", mitkCommandLineParser::Float, "Scale y-axis:", "Scale in direction of y-axis (if copy is given the copy is scaled)"); parser.addArgument("scale-z", "sz", mitkCommandLineParser::Float, "Scale z-axis", "Scale in direction of z-axis (if copy is given the copy is scaled)"); parser.addArgument("translate-x", "tx", mitkCommandLineParser::Float, "Translate x-axis:", "Translate in direction of x-axis (if copy is given the copy is translated, in mm)"); parser.addArgument("translate-y", "ty", mitkCommandLineParser::Float, "Translate y-axis:", "Translate in direction of y-axis (if copy is given the copy is translated, in mm)"); parser.addArgument("translate-z", "tz", mitkCommandLineParser::Float, "Translate z-axis:", "Translate in direction of z-axis (if copy is given the copy is translated, in mm)"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; float smoothDist = -1; if (parsedArgs.count("smooth")) smoothDist = us::any_cast(parsedArgs["smooth"]); float compress = -1; if (parsedArgs.count("compress")) compress = us::any_cast(parsedArgs["compress"]); float minFiberLength = -1; if (parsedArgs.count("minLength")) minFiberLength = us::any_cast(parsedArgs["minLength"]); float maxFiberLength = -1; if (parsedArgs.count("maxLength")) maxFiberLength = us::any_cast(parsedArgs["maxLength"]); float curvThres = -1; if (parsedArgs.count("minCurv")) curvThres = us::any_cast(parsedArgs["minCurv"]); int axis = 0; if (parsedArgs.count("mirror")) axis = us::any_cast(parsedArgs["mirror"]); float rotateX = 0; if (parsedArgs.count("rotate-x")) rotateX = us::any_cast(parsedArgs["rotate-x"]); float rotateY = 0; if (parsedArgs.count("rotate-y")) rotateY = us::any_cast(parsedArgs["rotate-y"]); float rotateZ = 0; if (parsedArgs.count("rotate-z")) rotateZ = us::any_cast(parsedArgs["rotate-z"]); float scaleX = 0; if (parsedArgs.count("scale-x")) scaleX = us::any_cast(parsedArgs["scale-x"]); float scaleY = 0; if (parsedArgs.count("scale-y")) scaleY = us::any_cast(parsedArgs["scale-y"]); float scaleZ = 0; if (parsedArgs.count("scale-z")) scaleZ = us::any_cast(parsedArgs["scale-z"]); float translateX = 0; if (parsedArgs.count("translate-x")) translateX = us::any_cast(parsedArgs["translate-x"]); float translateY = 0; if (parsedArgs.count("translate-y")) translateY = us::any_cast(parsedArgs["translate-y"]); float translateZ = 0; if (parsedArgs.count("translate-z")) translateZ = us::any_cast(parsedArgs["translate-z"]); string inFileName = us::any_cast(parsedArgs["input"]); string outFileName = us::any_cast(parsedArgs["outFile"]); try { - mitk::FiberBundleX::Pointer fib = LoadFib(inFileName); + mitk::FiberBundle::Pointer fib = LoadFib(inFileName); if (minFiberLength>0) fib->RemoveShortFibers(minFiberLength); if (maxFiberLength>0) fib->RemoveLongFibers(maxFiberLength); if (curvThres>0) fib->ApplyCurvatureThreshold(curvThres, false); if (smoothDist>0) fib->ResampleSpline(smoothDist); if (compress>0) fib->Compress(compress); if (axis/100==1) fib->MirrorFibers(0); if ((axis%100)/10==1) fib->MirrorFibers(1); if (axis%10==1) fib->MirrorFibers(2); if (rotateX > 0 || rotateY > 0 || rotateZ > 0){ std::cout << "Rotate " << rotateX << " " << rotateY << " " << rotateZ; fib->RotateAroundAxis(rotateX, rotateY, rotateZ); } if (translateX > 0 || translateY > 0 || translateZ > 0){ fib->TranslateFibers(translateX, translateY, translateZ); } if (scaleX > 0 || scaleY > 0 || scaleZ > 0) fib->ScaleFibers(scaleX, scaleY, scaleZ); mitk::IOUtil::SaveBaseData(fib.GetPointer(), outFileName ); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/Fiberfox.cpp b/Modules/DiffusionImaging/MiniApps/Fiberfox.cpp index 07f78f9e38..d47a1db705 100755 --- a/Modules/DiffusionImaging/MiniApps/Fiberfox.cpp +++ b/Modules/DiffusionImaging/MiniApps/Fiberfox.cpp @@ -1,84 +1,83 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include -#include #include -#include +#include #include #include "mitkCommandLineParser.h" #include #include #include "boost/property_tree/ptree.hpp" #include "boost/property_tree/xml_parser.hpp" #include "boost/foreach.hpp" /** TODO: Proritype signal komplett speichern oder bild mit speichern. */ /** TODO: Tarball aus images und parametern? */ /** TODO: Artefakte auf bild in miniapp */ using namespace mitk; int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("FiberFox"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setContributor("MBI"); parser.setDescription(" "); parser.setArgumentPrefix("--", "-"); parser.addArgument("out", "o", mitkCommandLineParser::OutputFile, "Output root:", "output root", us::Any(), false); parser.addArgument("parameters", "p", mitkCommandLineParser::InputFile, "Parameter file:", "fiberfox parameter file", us::Any(), false); parser.addArgument("fiberbundle", "f", mitkCommandLineParser::String, "Fiberbundle:", "", us::Any(), false); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string outName = us::any_cast(parsedArgs["out"]); string paramName = us::any_cast(parsedArgs["parameters"]); string fibFile = ""; if (parsedArgs.count("fiberbundle")) fibFile = us::any_cast(parsedArgs["fiberbundle"]); { FiberfoxParameters parameters; parameters.LoadParameters(paramName); - mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); + mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); itk::TractsToDWIImageFilter< short >::Pointer tractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); tractsToDwiFilter->SetParameters(parameters); tractsToDwiFilter->SetFiberBundle(inputTractogram); tractsToDwiFilter->Update(); mitk::Image::Pointer image = mitk::GrabItkImageMemory( tractsToDwiFilter->GetOutput() ); image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( parameters.m_SignalGen.GetGradientDirections() ) ); image->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( parameters.m_SignalGen.m_Bvalue ) ); mitk::DiffusionPropertyHelper propertyHelper( image ); propertyHelper.InitializeImage(); mitk::IOUtil::Save(image, outName.c_str()); } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/FileFormatConverter.cpp b/Modules/DiffusionImaging/MiniApps/FileFormatConverter.cpp index f758f91601..7aa93838d2 100644 --- a/Modules/DiffusionImaging/MiniApps/FileFormatConverter.cpp +++ b/Modules/DiffusionImaging/MiniApps/FileFormatConverter.cpp @@ -1,80 +1,77 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include -#include #include -#include +#include #include "mitkCommandLineParser.h" using namespace mitk; int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Format Converter"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setDescription(""); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("in", "i", mitkCommandLineParser::InputFile, "Input:", "input file", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputFile, "Output:", "output file", us::Any(), false); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; // mandatory arguments string inName = us::any_cast(parsedArgs["in"]); string outName = us::any_cast(parsedArgs["out"]); try { - const std::string s1="", s2=""; - std::vector infile = BaseDataIO::LoadBaseDataFromFile( inName, s1, s2, false ); - mitk::BaseData::Pointer baseData = infile.at(0); + std::vector baseData = mitk::IOUtil::Load(inName); - if ( dynamic_cast(baseData.GetPointer()) ) + if ( baseData.size()>0 && dynamic_cast(baseData[0].GetPointer()) ) { - mitk::IOUtil::Save(dynamic_cast(baseData.GetPointer()), outName.c_str()); + mitk::IOUtil::Save(dynamic_cast(baseData[0].GetPointer()), outName.c_str()); } - else if ( dynamic_cast(baseData.GetPointer()) ) + else if ( baseData.size()>0 && dynamic_cast(baseData[0].GetPointer()) ) { - mitk::IOUtil::Save(dynamic_cast(baseData.GetPointer()) ,outName.c_str()); + mitk::IOUtil::Save(dynamic_cast(baseData[0].GetPointer()) ,outName.c_str()); } else std::cout << "File type currently not supported!"; } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/GibbsTracking.cpp b/Modules/DiffusionImaging/MiniApps/GibbsTracking.cpp index d980327a74..881014cba2 100755 --- a/Modules/DiffusionImaging/MiniApps/GibbsTracking.cpp +++ b/Modules/DiffusionImaging/MiniApps/GibbsTracking.cpp @@ -1,241 +1,237 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include -#include -#include +#include #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include template typename itk::ShCoefficientImageImporter< float, shOrder >::QballImageType::Pointer TemplatedConvertShCoeffs(mitk::Image* mitkImg, int toolkit, bool noFlip = false) { typedef itk::ShCoefficientImageImporter< float, shOrder > FilterType; typedef mitk::ImageToItk< itk::Image< float, 4 > > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(mitkImg); caster->Update(); itk::Image< float, 4 >::Pointer itkImage = caster->GetOutput(); typename FilterType::Pointer filter = FilterType::New(); if (noFlip) { filter->SetInputImage(itkImage); } else { std::cout << "Flipping image"; itk::FixedArray flipAxes; flipAxes[0] = true; flipAxes[1] = true; flipAxes[2] = false; flipAxes[3] = false; itk::FlipImageFilter< itk::Image< float, 4 > >::Pointer flipper = itk::FlipImageFilter< itk::Image< float, 4 > >::New(); flipper->SetInput(itkImage); flipper->SetFlipAxes(flipAxes); flipper->Update(); itk::Image< float, 4 >::Pointer flipped = flipper->GetOutput(); itk::Matrix< double,4,4 > m = itkImage->GetDirection(); m[0][0] *= -1; m[1][1] *= -1; flipped->SetDirection(m); itk::Point< float, 4 > o = itkImage->GetOrigin(); o[0] -= (flipped->GetLargestPossibleRegion().GetSize(0)-1); o[1] -= (flipped->GetLargestPossibleRegion().GetSize(1)-1); flipped->SetOrigin(o); filter->SetInputImage(flipped); } switch (toolkit) { case 0: filter->SetToolkit(FilterType::FSL); break; case 1: filter->SetToolkit(FilterType::MRTRIX); break; default: filter->SetToolkit(FilterType::FSL); } filter->GenerateData(); return filter->GetQballImage(); } int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Gibbs Tracking"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setDescription(" "); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input image (tensor, Q-ball or FSL/MRTrix SH-coefficient image)", us::Any(), false); parser.addArgument("parameters", "p", mitkCommandLineParser::InputFile, "Parameters:", "parameter file (.gtp)", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::InputFile, "Mask:", "binary mask image"); parser.addArgument("shConvention", "s", mitkCommandLineParser::String, "SH coefficient:", "sh coefficient convention (FSL, MRtrix)", string("FSL"), true); parser.addArgument("outFile", "o", mitkCommandLineParser::OutputFile, "Output:", "output fiber bundle (.fib)", us::Any(), false); parser.addArgument("noFlip", "f", mitkCommandLineParser::Bool, "No flip:", "do not flip input image to match MITK coordinate convention"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string inFileName = us::any_cast(parsedArgs["input"]); string paramFileName = us::any_cast(parsedArgs["parameters"]); string outFileName = us::any_cast(parsedArgs["outFile"]); bool noFlip = false; if (parsedArgs.count("noFlip")) noFlip = us::any_cast(parsedArgs["noFlip"]); try { // instantiate gibbs tracker typedef itk::Vector OdfVectorType; typedef itk::Image ItkQballImageType; typedef itk::GibbsTrackingFilter GibbsTrackingFilterType; GibbsTrackingFilterType::Pointer gibbsTracker = GibbsTrackingFilterType::New(); // load input image - const std::string s1="", s2=""; - std::vector infile = mitk::BaseDataIO::LoadBaseDataFromFile( inFileName, s1, s2, false ); - - mitk::Image::Pointer mitkImage = dynamic_cast(infile.at(0).GetPointer()); + mitk::Image::Pointer mitkImage = mitk::IOUtil::LoadImage(inFileName); // try to cast to qball image if( boost::algorithm::ends_with(inFileName, ".qbi") ) { std::cout << "Loading qball image ..."; - mitk::QBallImage::Pointer mitkQballImage = dynamic_cast(infile.at(0).GetPointer()); + mitk::QBallImage::Pointer mitkQballImage = dynamic_cast(mitkImage.GetPointer()); ItkQballImageType::Pointer itk_qbi = ItkQballImageType::New(); mitk::CastToItkImage(mitkQballImage, itk_qbi); gibbsTracker->SetQBallImage(itk_qbi.GetPointer()); } else if( boost::algorithm::ends_with(inFileName, ".dti") ) { std::cout << "Loading tensor image ..."; typedef itk::Image< itk::DiffusionTensor3D, 3 > ItkTensorImage; - mitk::TensorImage::Pointer mitkTensorImage = dynamic_cast(infile.at(0).GetPointer()); + mitk::TensorImage::Pointer mitkTensorImage = dynamic_cast(mitkImage.GetPointer()); ItkTensorImage::Pointer itk_dti = ItkTensorImage::New(); mitk::CastToItkImage(mitkTensorImage, itk_dti); gibbsTracker->SetTensorImage(itk_dti); } else if ( boost::algorithm::ends_with(inFileName, ".nii") ) { std::cout << "Loading sh-coefficient image ..."; int nrCoeffs = mitkImage->GetLargestPossibleRegion().GetSize()[3]; int c=3, d=2-2*nrCoeffs; double D = c*c-4*d; int shOrder; if (D>0) { shOrder = (-c+sqrt(D))/2.0; if (shOrder<0) shOrder = (-c-sqrt(D))/2.0; } else if (D==0) shOrder = -c/2.0; std::cout << "using SH-order " << shOrder; int toolkitConvention = 0; if (parsedArgs.count("shConvention")) { string convention = us::any_cast(parsedArgs["shConvention"]).c_str(); if ( boost::algorithm::equals(convention, "MRtrix") ) { toolkitConvention = 1; std::cout << "Using MRtrix style sh-coefficient convention"; } else std::cout << "Using FSL style sh-coefficient convention"; } else std::cout << "Using FSL style sh-coefficient convention"; switch (shOrder) { case 4: gibbsTracker->SetQBallImage(TemplatedConvertShCoeffs<4>(mitkImage, toolkitConvention, noFlip)); break; case 6: gibbsTracker->SetQBallImage(TemplatedConvertShCoeffs<6>(mitkImage, toolkitConvention, noFlip)); break; case 8: gibbsTracker->SetQBallImage(TemplatedConvertShCoeffs<8>(mitkImage, toolkitConvention, noFlip)); break; case 10: gibbsTracker->SetQBallImage(TemplatedConvertShCoeffs<10>(mitkImage, toolkitConvention, noFlip)); break; case 12: gibbsTracker->SetQBallImage(TemplatedConvertShCoeffs<12>(mitkImage, toolkitConvention, noFlip)); break; default: std::cout << "SH-order " << shOrder << " not supported"; } } else return EXIT_FAILURE; // global tracking if (parsedArgs.count("mask")) { typedef itk::Image MaskImgType; mitk::Image::Pointer mitkMaskImage = mitk::IOUtil::LoadImage(us::any_cast(parsedArgs["mask"])); MaskImgType::Pointer itk_mask = MaskImgType::New(); mitk::CastToItkImage(mitkMaskImage, itk_mask); gibbsTracker->SetMaskImage(itk_mask); } gibbsTracker->SetDuplicateImage(false); gibbsTracker->SetLoadParameterFile( paramFileName ); // gibbsTracker->SetLutPath( "" ); gibbsTracker->Update(); - mitk::FiberBundleX::Pointer mitkFiberBundle = mitk::FiberBundleX::New(gibbsTracker->GetFiberBundle()); + mitk::FiberBundle::Pointer mitkFiberBundle = mitk::FiberBundle::New(gibbsTracker->GetFiberBundle()); mitkFiberBundle->SetReferenceGeometry(mitkImage->GetGeometry()); mitk::IOUtil::SaveBaseData(mitkFiberBundle.GetPointer(), outFileName ); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/ImageResampler.cpp b/Modules/DiffusionImaging/MiniApps/ImageResampler.cpp index c7058badc0..14e50bf47b 100644 --- a/Modules/DiffusionImaging/MiniApps/ImageResampler.cpp +++ b/Modules/DiffusionImaging/MiniApps/ImageResampler.cpp @@ -1,314 +1,314 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include // ITK #include #include #include "itkLinearInterpolateImageFunction.h" #include "itkWindowedSincInterpolateImageFunction.h" #include "itkIdentityTransform.h" #include "itkResampleImageFilter.h" #include "itkResampleDwiImageFilter.h" typedef itk::Image InputImageType; static mitk::Image::Pointer TransformToReference(mitk::Image *reference, mitk::Image *moving, bool sincInterpol = false) { // Convert to itk Images InputImageType::Pointer itkReference = InputImageType::New(); InputImageType::Pointer itkMoving = InputImageType::New(); mitk::CastToItkImage(reference,itkReference); mitk::CastToItkImage(moving,itkMoving); // Identify Transform typedef itk::IdentityTransform T_Transform; T_Transform::Pointer _pTransform = T_Transform::New(); _pTransform->SetIdentity(); typedef itk::WindowedSincInterpolateImageFunction< InputImageType, 3> WindowedSincInterpolatorType; WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New(); typedef itk::ResampleImageFilter ResampleFilterType; ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetInput(itkMoving); resampler->SetReferenceImage( itkReference ); resampler->UseReferenceImageOn(); resampler->SetTransform(_pTransform); resampler->SetInterpolator(sinc_interpolator); resampler->Update(); // Convert back to mitk mitk::Image::Pointer result = mitk::Image::New(); result->InitializeByItk(resampler->GetOutput()); GrabItkImageMemory( resampler->GetOutput() , result ); return result; } static std::vector &split(const std::string &s, char delim, std::vector &elems) { std::stringstream ss(s); std::string item; while (std::getline(ss, item, delim)) { elems.push_back(item); } return elems; } static std::vector split(const std::string &s, char delim) { std::vector < std::string > elems; return split(s, delim, elems); } static mitk::Image::Pointer ResampleBySpacing(mitk::Image *input, float *spacing, bool useLinInt = true) { InputImageType::Pointer itkImage = InputImageType::New(); CastToItkImage(input,itkImage); /** * 1) Resampling * */ // Identity transform. // We don't want any transform on our image except rescaling which is not // specified by a transform but by the input/output spacing as we will see // later. // So no transform will be specified. typedef itk::IdentityTransform T_Transform; // The resampler type itself. typedef itk::ResampleImageFilter T_ResampleFilter; // Prepare the resampler. // Instantiate the transform and specify it should be the id transform. T_Transform::Pointer _pTransform = T_Transform::New(); _pTransform->SetIdentity(); // Instantiate the resampler. Wire in the transform and the interpolator. T_ResampleFilter::Pointer _pResizeFilter = T_ResampleFilter::New(); // Specify the input. _pResizeFilter->SetInput(itkImage); _pResizeFilter->SetTransform(_pTransform); // Set the output origin. _pResizeFilter->SetOutputOrigin(itkImage->GetOrigin()); // Compute the size of the output. // The size (# of pixels) in the output is recomputed using // the ratio of the input and output sizes. InputImageType::SpacingType inputSpacing = itkImage->GetSpacing(); InputImageType::SpacingType outputSpacing; const InputImageType::RegionType& inputSize = itkImage->GetLargestPossibleRegion(); InputImageType::SizeType outputSize; typedef InputImageType::SizeType::SizeValueType SizeValueType; // Set the output spacing. outputSpacing[0] = spacing[0]; outputSpacing[1] = spacing[1]; outputSpacing[2] = spacing[2]; outputSize[0] = static_cast(inputSize.GetSize()[0] * inputSpacing[0] / outputSpacing[0] + .5); outputSize[1] = static_cast(inputSize.GetSize()[1] * inputSpacing[1] / outputSpacing[1] + .5); outputSize[2] = static_cast(inputSize.GetSize()[2] * inputSpacing[2] / outputSpacing[2] + .5); _pResizeFilter->SetOutputSpacing(outputSpacing); _pResizeFilter->SetSize(outputSize); typedef itk::LinearInterpolateImageFunction< InputImageType > LinearInterpolatorType; LinearInterpolatorType::Pointer lin_interpolator = LinearInterpolatorType::New(); typedef itk::WindowedSincInterpolateImageFunction< InputImageType, 4> WindowedSincInterpolatorType; WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New(); if (useLinInt) _pResizeFilter->SetInterpolator(lin_interpolator); else _pResizeFilter->SetInterpolator(sinc_interpolator); _pResizeFilter->Update(); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk(_pResizeFilter->GetOutput()); mitk::GrabItkImageMemory( _pResizeFilter->GetOutput(), image); return image; } /// Save images according to file type static void SaveImage(std::string fileName, mitk::Image* image, std::string fileType ) { std::cout << "----Save to " << fileName; mitk::IOUtil::Save(image, fileName); } mitk::Image::Pointer ResampleDWIbySpacing(mitk::Image::Pointer input, float* spacing, bool useLinInt = true) { itk::Vector spacingVector; spacingVector[0] = spacing[0]; spacingVector[1] = spacing[1]; spacingVector[2] = spacing[2]; typedef itk::ResampleDwiImageFilter ResampleFilterType; mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(input, itkVectorImagePointer); ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetInput( itkVectorImagePointer ); resampler->SetInterpolation(ResampleFilterType::Interpolate_Linear); resampler->SetNewSpacing(spacingVector); resampler->Update(); mitk::Image::Pointer output = mitk::GrabItkImageMemory( resampler->GetOutput() ); output->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( mitk::DiffusionPropertyHelper::GetGradientContainer(input) ) ); output->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( mitk::DiffusionPropertyHelper::GetReferenceBValue(input) ) ); mitk::DiffusionPropertyHelper propertyHelper( output ); propertyHelper.InitializeImage(); return output; } int main( int argc, char* argv[] ) { mitkCommandLineParser parser; parser.setArgumentPrefix("--","-"); parser.setTitle("Image Resampler"); parser.setCategory("Preprocessing Tools"); parser.setContributor("MBI"); parser.setDescription("Resample an image to eigther a specific spacing or to a reference image."); // Add command line argument names parser.addArgument("help", "h",mitkCommandLineParser::Bool, "Show this help text"); parser.addArgument("input", "i", mitkCommandLineParser::InputImage, "Input:", "Input file",us::Any(),false); parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output:", "Output file",us::Any(),false); parser.addArgument("spacing", "s", mitkCommandLineParser::String, "Spacing:", "Resample provide x,y,z spacing in mm (e.g. -r 1,1,3), is not applied to tensor data",us::Any()); parser.addArgument("reference", "r", mitkCommandLineParser::InputImage, "Reference:", "Resample using supplied reference image. Also cuts image to same dimensions",us::Any()); parser.addArgument("win-sinc", "w", mitkCommandLineParser::Bool, "Windowed-sinc interpolation:", "Use windowed-sinc interpolation (3) instead of linear interpolation ",us::Any()); map parsedArgs = parser.parseArguments(argc, argv); // Handle special arguments bool useSpacing = false; bool useLinearInterpol = true; { if (parsedArgs.size() == 0) { return EXIT_FAILURE; } if (parsedArgs.count("sinc-int")) useLinearInterpol = false; // Show a help message if ( parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } } std::string outputFile = us::any_cast(parsedArgs["output"]); std::string inputFile = us::any_cast(parsedArgs["input"]); std::vector spacings; float spacing[3]; if (parsedArgs.count("spacing")) { std::string arg = us::any_cast(parsedArgs["spacing"]); if (arg != "") { spacings = split(arg ,','); spacing[0] = atoi(spacings.at(0).c_str()); spacing[1] = atoi(spacings.at(1).c_str()); spacing[2] = atoi(spacings.at(2).c_str()); useSpacing = true; } } std::string refImageFile = ""; if (parsedArgs.count("reference")) { refImageFile = us::any_cast(parsedArgs["reference"]); } if (refImageFile =="" && useSpacing == false) { MITK_ERROR << "No information how to resample is supplied. Use eigther --spacing or --reference !"; return EXIT_FAILURE; } mitk::Image::Pointer refImage; if (!useSpacing) refImage = mitk::IOUtil::LoadImage(refImageFile); - mitk::Image::Pointer inputDWI = dynamic_cast(mitk::IOUtil::LoadBaseData(inputFile).GetPointer()); - if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(inputDWI)) + mitk::Image::Pointer inputDWI = mitk::IOUtil::LoadImage(inputFile); + if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(inputDWI.GetPointer())) { mitk::Image::Pointer outputImage; if (useSpacing) outputImage = ResampleDWIbySpacing(inputDWI, spacing); else { MITK_WARN << "Not supported yet, to resample a DWI please set a new spacing."; return EXIT_FAILURE; } mitk::IOUtil::Save(outputImage, outputFile.c_str()); return EXIT_SUCCESS; } mitk::Image::Pointer inputImage = mitk::IOUtil::LoadImage(inputFile); mitk::Image::Pointer resultImage; if (useSpacing) resultImage = ResampleBySpacing(inputImage,spacing); else resultImage = TransformToReference(refImage,inputImage); mitk::IOUtil::SaveImage(resultImage, outputFile); return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/LocalDirectionalFiberPlausibility.cpp b/Modules/DiffusionImaging/MiniApps/LocalDirectionalFiberPlausibility.cpp index 0b58518ab5..326838cef7 100755 --- a/Modules/DiffusionImaging/MiniApps/LocalDirectionalFiberPlausibility.cpp +++ b/Modules/DiffusionImaging/MiniApps/LocalDirectionalFiberPlausibility.cpp @@ -1,301 +1,300 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Local Directional Fiber Plausibility"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setDescription(" "); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input tractogram (.fib, vtk ascii file format)", us::Any(), false); parser.addArgument("reference", "r", mitkCommandLineParser::StringList, "Reference images:", "reference direction images", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output root", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::StringList, "Masks:", "mask images"); parser.addArgument("athresh", "a", mitkCommandLineParser::Float, "Angular threshold:", "angular threshold in degrees. closer fiber directions are regarded as one direction and clustered together.", 25, true); parser.addArgument("verbose", "v", mitkCommandLineParser::Bool, "Verbose:", "output optional and intermediate calculation results"); parser.addArgument("ignore", "n", mitkCommandLineParser::Bool, "Ignore:", "don't increase error for missing or too many directions"); parser.addArgument("fileID", "id", mitkCommandLineParser::String, "ID:", "optional ID field"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; mitkCommandLineParser::StringContainerType referenceImages = us::any_cast(parsedArgs["reference"]); mitkCommandLineParser::StringContainerType maskImages; if (parsedArgs.count("mask")) maskImages = us::any_cast(parsedArgs["mask"]); string fibFile = us::any_cast(parsedArgs["input"]); float angularThreshold = 25; if (parsedArgs.count("athresh")) angularThreshold = us::any_cast(parsedArgs["athresh"]); string outRoot = us::any_cast(parsedArgs["out"]); bool verbose = false; if (parsedArgs.count("verbose")) verbose = us::any_cast(parsedArgs["verbose"]); bool ignore = false; if (parsedArgs.count("ignore")) ignore = us::any_cast(parsedArgs["ignore"]); string fileID = ""; if (parsedArgs.count("fileID")) fileID = us::any_cast(parsedArgs["fileID"]); try { typedef itk::Image ItkUcharImgType; typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; typedef itk::VectorContainer< unsigned int, ItkDirectionImage3DType::Pointer > ItkDirectionImageContainerType; typedef itk::EvaluateDirectionImagesFilter< float > EvaluationFilterType; // load fiber bundle - mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); + mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); // load reference directions ItkDirectionImageContainerType::Pointer referenceImageContainer = ItkDirectionImageContainerType::New(); for (unsigned int i=0; i(mitk::IOUtil::LoadDataNode(referenceImages.at(i))->GetData()); typedef mitk::ImageToItk< ItkDirectionImage3DType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkDirectionImage3DType::Pointer itkImg = caster->GetOutput(); referenceImageContainer->InsertElement(referenceImageContainer->Size(),itkImg); } catch(...){ std::cout << "could not load: " << referenceImages.at(i); } } ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); ItkDirectionImage3DType::Pointer dirImg = referenceImageContainer->GetElement(0); itkMaskImage->SetSpacing( dirImg->GetSpacing() ); itkMaskImage->SetOrigin( dirImg->GetOrigin() ); itkMaskImage->SetDirection( dirImg->GetDirection() ); itkMaskImage->SetLargestPossibleRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetBufferedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetRequestedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->Allocate(); itkMaskImage->FillBuffer(1); // extract directions from fiber bundle itk::TractsToVectorImageFilter::Pointer fOdfFilter = itk::TractsToVectorImageFilter::New(); fOdfFilter->SetFiberBundle(inputTractogram); fOdfFilter->SetMaskImage(itkMaskImage); fOdfFilter->SetAngularThreshold(cos(angularThreshold*M_PI/180)); fOdfFilter->SetNormalizeVectors(true); fOdfFilter->SetUseWorkingCopy(false); fOdfFilter->Update(); ItkDirectionImageContainerType::Pointer directionImageContainer = fOdfFilter->GetDirectionImageContainer(); if (verbose) { // write vector field - mitk::FiberBundleX::Pointer directions = fOdfFilter->GetOutputFiberBundle(); + mitk::FiberBundle::Pointer directions = fOdfFilter->GetOutputFiberBundle(); string outfilename = outRoot; outfilename.append("_VECTOR_FIELD.fib"); mitk::IOUtil::SaveBaseData(directions.GetPointer(), outfilename ); // write direction images for (unsigned int i=0; iSize(); i++) { itk::TractsToVectorImageFilter::ItkDirectionImageType::Pointer itkImg = directionImageContainer->GetElement(i); typedef itk::ImageFileWriter< itk::TractsToVectorImageFilter::ItkDirectionImageType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_DIRECTION_"); outfilename.append(boost::lexical_cast(i)); outfilename.append(".nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(itkImg); writer->Update(); } // write num direction image { ItkUcharImgType::Pointer numDirImage = fOdfFilter->GetNumDirectionsImage(); typedef itk::ImageFileWriter< ItkUcharImgType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_NUM_DIRECTIONS.nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(numDirImage); writer->Update(); } } string logFile = outRoot; logFile.append("_ANGULAR_ERROR.csv"); ofstream file; file.open (logFile.c_str()); if (maskImages.size()>0) { for (unsigned int i=0; i(mitk::IOUtil::LoadDataNode(maskImages.at(i))->GetData()); mitk::CastToItkImage(mitkMaskImage, itkMaskImage); // evaluate directions EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New(); evaluationFilter->SetImageSet(directionImageContainer); evaluationFilter->SetReferenceImageSet(referenceImageContainer); evaluationFilter->SetMaskImage(itkMaskImage); evaluationFilter->SetIgnoreMissingDirections(ignore); evaluationFilter->Update(); if (verbose) { EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0); typedef itk::ImageFileWriter< EvaluationFilterType::OutputImageType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_ERROR_IMAGE.nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(angularErrorImage); writer->Update(); } string maskFileName = itksys::SystemTools::GetFilenameWithoutExtension(maskImages.at(i)); unsigned found = maskFileName.find_last_of("_"); string sens = itksys::SystemTools::GetFilenameWithoutLastExtension(fibFile); if (!fileID.empty()) sens = fileID; sens.append(","); sens.append(maskFileName.substr(found+1)); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMeanAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMedianAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMaxAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMinAngularError())); sens.append(","); sens.append(boost::lexical_cast(std::sqrt(evaluationFilter->GetVarAngularError()))); sens.append(";\n"); file << sens; } } else { // evaluate directions EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New(); evaluationFilter->SetImageSet(directionImageContainer); evaluationFilter->SetReferenceImageSet(referenceImageContainer); evaluationFilter->SetMaskImage(itkMaskImage); evaluationFilter->SetIgnoreMissingDirections(ignore); evaluationFilter->Update(); if (verbose) { EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0); typedef itk::ImageFileWriter< EvaluationFilterType::OutputImageType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_ERROR_IMAGE.nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(angularErrorImage); writer->Update(); } string sens = itksys::SystemTools::GetFilenameWithoutLastExtension(fibFile); if (!fileID.empty()) sens = fileID; sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMeanAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMedianAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMaxAngularError())); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMinAngularError())); sens.append(","); sens.append(boost::lexical_cast(std::sqrt(evaluationFilter->GetVarAngularError()))); sens.append(";\n"); file << sens; } file.close(); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/MultishellMethods.cpp b/Modules/DiffusionImaging/MiniApps/MultishellMethods.cpp index bc81479de8..368b967924 100644 --- a/Modules/DiffusionImaging/MiniApps/MultishellMethods.cpp +++ b/Modules/DiffusionImaging/MiniApps/MultishellMethods.cpp @@ -1,219 +1,216 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include -#include #include #include #include -#include +#include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include #include #include #include int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Multishell Methods"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setDescription(""); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("in", "i", mitkCommandLineParser::InputFile, "Input:", "input file", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputFile, "Output:", "output file", us::Any(), false); parser.addArgument("adc", "D", mitkCommandLineParser::Bool, "ADC:", "ADC Average", us::Any(), false); parser.addArgument("akc", "K", mitkCommandLineParser::Bool, "Kurtosis fit:", "Kurtosis Fit", us::Any(), false); parser.addArgument("biexp", "B", mitkCommandLineParser::Bool, "BiExp fit:", "BiExp fit", us::Any(), false); parser.addArgument("targetbvalue", "b", mitkCommandLineParser::String, "b Value:", "target bValue (mean, min, max)", us::Any(), false); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; // mandatory arguments string inName = us::any_cast(parsedArgs["in"]); string outName = us::any_cast(parsedArgs["out"]); bool applyADC = us::any_cast(parsedArgs["adc"]); bool applyAKC = us::any_cast(parsedArgs["akc"]); bool applyBiExp = us::any_cast(parsedArgs["biexp"]); string targetType = us::any_cast(parsedArgs["targetbvalue"]); try { std::cout << "Loading " << inName; - const std::string s1="", s2=""; - std::vector infile = mitk::BaseDataIO::LoadBaseDataFromFile( inName, s1, s2, false ); - mitk::BaseData::Pointer baseData = infile.at(0); - if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(baseData.GetPointer()) ) ) + mitk::Image::Pointer dwi = mitk::IOUtil::LoadImage(inName); + + if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dwi ) ) { - mitk::Image::Pointer dwi = dynamic_cast(baseData.GetPointer()); typedef itk::RadialMultishellToSingleshellImageFilter FilterType; typedef itk::DwiGradientLengthCorrectionFilter CorrectionFilterType; CorrectionFilterType::Pointer roundfilter = CorrectionFilterType::New(); roundfilter->SetRoundingValue( 1000 ); roundfilter->SetReferenceBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue( dwi )); roundfilter->SetReferenceGradientDirectionContainer(mitk::DiffusionPropertyHelper::GetGradientContainer(dwi)); roundfilter->Update(); dwi->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( roundfilter->GetNewBValue() ) ); dwi->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( roundfilter->GetOutputGradientDirectionContainer() ) ); // filter input parameter const mitk::DiffusionPropertyHelper::BValueMapType &originalShellMap = mitk::DiffusionPropertyHelper::GetBValueMap(dwi); mitk::DiffusionPropertyHelper::ImageType::Pointer vectorImage = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, vectorImage); const mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientContainer = mitk::DiffusionPropertyHelper::GetGradientContainer(dwi); const unsigned int &bValue = mitk::DiffusionPropertyHelper::GetReferenceBValue( dwi ); // filter call vnl_vector bValueList(originalShellMap.size()-1); double targetBValue = bValueList.mean(); mitk::DiffusionPropertyHelper::BValueMapType::const_iterator it = originalShellMap.begin(); ++it; int i = 0 ; for(; it != originalShellMap.end(); ++it) bValueList.put(i++,it->first); if( targetType == "mean" ) targetBValue = bValueList.mean(); else if( targetType == "min" ) targetBValue = bValueList.min_value(); else if( targetType == "max" ) targetBValue = bValueList.max_value(); if(applyADC) { FilterType::Pointer filter = FilterType::New(); filter->SetInput(vectorImage); filter->SetOriginalGradientDirections(gradientContainer); filter->SetOriginalBValueMap(originalShellMap); filter->SetOriginalBValue(bValue); itk::ADCAverageFunctor::Pointer functor = itk::ADCAverageFunctor::New(); functor->setListOfBValues(bValueList); functor->setTargetBValue(targetBValue); filter->SetFunctor(functor); filter->Update(); // create new DWI image mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( filter->GetOutput() ); outImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( targetBValue ) ); outImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetTargetGradientDirections() ) ); mitk::DiffusionPropertyHelper propertyHelper( outImage ); propertyHelper.InitializeImage(); mitk::IOUtil::Save(outImage, (outName + "_ADC.dwi").c_str()); } if(applyAKC) { FilterType::Pointer filter = FilterType::New(); filter->SetInput(vectorImage); filter->SetOriginalGradientDirections(gradientContainer); filter->SetOriginalBValueMap(originalShellMap); filter->SetOriginalBValue(bValue); itk::KurtosisFitFunctor::Pointer functor = itk::KurtosisFitFunctor::New(); functor->setListOfBValues(bValueList); functor->setTargetBValue(targetBValue); filter->SetFunctor(functor); filter->Update(); // create new DWI image mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( filter->GetOutput() ); outImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( targetBValue ) ); outImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetTargetGradientDirections() ) ); mitk::DiffusionPropertyHelper propertyHelper( outImage ); propertyHelper.InitializeImage(); mitk::IOUtil::Save(outImage, (string(outName) + "_AKC.dwi").c_str()); } if(applyBiExp) { FilterType::Pointer filter = FilterType::New(); filter->SetInput(vectorImage); filter->SetOriginalGradientDirections(gradientContainer); filter->SetOriginalBValueMap(originalShellMap); filter->SetOriginalBValue(bValue); itk::BiExpFitFunctor::Pointer functor = itk::BiExpFitFunctor::New(); functor->setListOfBValues(bValueList); functor->setTargetBValue(targetBValue); filter->SetFunctor(functor); filter->Update(); // create new DWI image mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( filter->GetOutput() ); outImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( targetBValue ) ); outImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetTargetGradientDirections() ) ); mitk::DiffusionPropertyHelper propertyHelper( outImage ); propertyHelper.InitializeImage(); mitk::IOUtil::Save(outImage, (string(outName) + "_BiExp.dwi").c_str()); } } } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/NetworkCreation.cpp b/Modules/DiffusionImaging/MiniApps/NetworkCreation.cpp index 0641920173..757326ccf5 100644 --- a/Modules/DiffusionImaging/MiniApps/NetworkCreation.cpp +++ b/Modules/DiffusionImaging/MiniApps/NetworkCreation.cpp @@ -1,139 +1,138 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // std includes #include // CTK includes #include "mitkCommandLineParser.h" // MITK includes -#include #include "mitkConnectomicsNetworkCreator.h" #include #include int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Network Creation"); parser.setCategory("Connectomics"); parser.setDescription(""); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("fiberImage", "f", mitkCommandLineParser::InputFile, "Input image", "input fiber image (.fib)", us::Any(), false); parser.addArgument("parcellation", "p", mitkCommandLineParser::InputFile, "Parcellation image", "parcellation image", us::Any(), false); parser.addArgument("outputNetwork", "o", mitkCommandLineParser::String, "Output network", "where to save the output (.cnf)", us::Any(), false); parser.addArgument("radius", "r", mitkCommandLineParser::Int, "Radius", "Search radius in mm", 15, true); parser.addArgument("noCenterOfMass", "com", mitkCommandLineParser::Bool, "No center of mass", "Do not use center of mass for node positions"); parser.setCategory("Connectomics"); parser.setTitle("Network Creation"); parser.setDescription(""); parser.setContributor("MBI"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; //default values int searchRadius( 15 ); bool noCenterOfMass( false ); // parse command line arguments std::string fiberFilename = us::any_cast(parsedArgs["fiberImage"]); std::string parcellationFilename = us::any_cast(parsedArgs["parcellation"]); std::string outputFilename = us::any_cast(parsedArgs["outputNetwork"]); if (parsedArgs.count("radius")) searchRadius = us::any_cast(parsedArgs["radius"]); if (parsedArgs.count("noCenterOfMass")) noCenterOfMass = us::any_cast(parsedArgs["noCenterOfMass"]); try { const std::string s1="", s2=""; // load fiber image std::vector fiberInfile = - mitk::BaseDataIO::LoadBaseDataFromFile( fiberFilename, s1, s2, false ); + mitk::IOUtil::Load( fiberFilename); if( fiberInfile.empty() ) { std::string errorMessage = "Fiber Image at " + fiberFilename + " could not be read. Aborting."; MITK_ERROR << errorMessage; return EXIT_FAILURE; } mitk::BaseData* fiberBaseData = fiberInfile.at(0); - mitk::FiberBundleX* fiberBundle = dynamic_cast( fiberBaseData ); + mitk::FiberBundle* fiberBundle = dynamic_cast( fiberBaseData ); // load parcellation std::vector parcellationInFile = - mitk::BaseDataIO::LoadBaseDataFromFile( parcellationFilename, s1, s2, false ); + mitk::IOUtil::Load( parcellationFilename); if( parcellationInFile.empty() ) { std::string errorMessage = "Parcellation at " + parcellationFilename + " could not be read. Aborting."; MITK_ERROR << errorMessage; return EXIT_FAILURE; } mitk::BaseData* parcellationBaseData = parcellationInFile.at(0); mitk::Image* parcellationImage = dynamic_cast( parcellationBaseData ); // do creation mitk::ConnectomicsNetworkCreator::Pointer connectomicsNetworkCreator = mitk::ConnectomicsNetworkCreator::New(); connectomicsNetworkCreator->SetSegmentation( parcellationImage ); connectomicsNetworkCreator->SetFiberBundle( fiberBundle ); if( !noCenterOfMass ) { connectomicsNetworkCreator->CalculateCenterOfMass(); } connectomicsNetworkCreator->SetEndPointSearchRadius( searchRadius ); connectomicsNetworkCreator->CreateNetworkFromFibersAndSegmentation(); mitk::ConnectomicsNetwork::Pointer network = connectomicsNetworkCreator->GetNetwork(); std::cout << "searching writer"; mitk::IOUtil::SaveBaseData(network.GetPointer(), outputFilename ); return EXIT_SUCCESS; } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } std::cout << "DONE"; return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/NetworkStatistics.cpp b/Modules/DiffusionImaging/MiniApps/NetworkStatistics.cpp index 35065cf252..2d5e637ff2 100644 --- a/Modules/DiffusionImaging/MiniApps/NetworkStatistics.cpp +++ b/Modules/DiffusionImaging/MiniApps/NetworkStatistics.cpp @@ -1,522 +1,520 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // std includes #include #include #include #include #include #include // boost includes #include // ITK includes #include // CTK includes #include "mitkCommandLineParser.h" // MITK includes -#include #include #include #include +#include int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Network Creation"); parser.setCategory("Connectomics"); parser.setDescription(""); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("inputNetwork", "i", mitkCommandLineParser::InputFile, "Input network", "input connectomics network (.cnf)", us::Any(), false); parser.addArgument("outputFile", "o", mitkCommandLineParser::OutputFile, "Output file", "name of output file", us::Any(), false); parser.addArgument("noGlobalStatistics", "g", mitkCommandLineParser::Bool, "No global statistics", "Do not calculate global statistics"); parser.addArgument("createConnectivityMatriximage", "I", mitkCommandLineParser::Bool, "Write connectivity matrix image", "Write connectivity matrix image"); parser.addArgument("binaryConnectivity", "b", mitkCommandLineParser::Bool, "Binary connectivity", "Whether to create a binary connectivity matrix"); parser.addArgument("rescaleConnectivity", "r", mitkCommandLineParser::Bool, "Rescale connectivity", "Whether to rescale the connectivity matrix"); parser.addArgument("localStatistics", "L", mitkCommandLineParser::StringList, "Local statistics", "Provide a list of node labels for local statistics", us::Any()); parser.addArgument("regionList", "R", mitkCommandLineParser::StringList, "Region list", "A space separated list of regions. Each region has the format\n regionname;label1;label2;...;labelN", us::Any()); parser.addArgument("granularity", "gr", mitkCommandLineParser::Int, "Granularity", "How finely to test the density range and how many thresholds to consider",1); parser.addArgument("startDensity", "d", mitkCommandLineParser::Float, "Start Density", "Largest density for the range",1.0); parser.addArgument("thresholdStepSize", "t", mitkCommandLineParser::Int, "Step size threshold", "Distance of two adjacent thresholds",3); parser.setCategory("Connectomics"); parser.setTitle("Network Statistics"); parser.setDescription(""); parser.setContributor("MBI"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; //default values bool noGlobalStatistics( false ); bool binaryConnectivity( false ); bool rescaleConnectivity( false ); bool createConnectivityMatriximage( false ); int granularity( 1 ); double startDensity( 1.0 ); int thresholdStepSize( 3 ); // parse command line arguments std::string networkName = us::any_cast(parsedArgs["inputNetwork"]); std::string outName = us::any_cast(parsedArgs["outputFile"]); mitkCommandLineParser::StringContainerType localLabels; if(parsedArgs.count("localStatistics")) { localLabels = us::any_cast(parsedArgs["localStatistics"]); } mitkCommandLineParser::StringContainerType unparsedRegions; std::map< std::string, std::vector > parsedRegions; std::map< std::string, std::vector >::iterator parsedRegionsIterator; if(parsedArgs.count("regionList")) { unparsedRegions = us::any_cast(parsedArgs["regionList"]); for(unsigned int index(0); index < unparsedRegions.size(); index++ ) { std::vector< std::string > tempRegionVector; boost::split(tempRegionVector, unparsedRegions.at(index), boost::is_any_of(";")); std::vector< std::string >::const_iterator begin = tempRegionVector.begin(); std::vector< std::string >::const_iterator last = tempRegionVector.begin() + tempRegionVector.size(); std::vector< std::string > insertRegionVector(begin + 1, last); if( parsedRegions.count( tempRegionVector.at(0) ) == 0 ) { parsedRegions.insert( std::pair< std::string, std::vector >( tempRegionVector.at(0), insertRegionVector) ); } else { MITK_ERROR << "Region already exists. Skipping second occurrence."; } } } if (parsedArgs.count("noGlobalStatistics")) noGlobalStatistics = us::any_cast(parsedArgs["noGlobalStatistics"]); if (parsedArgs.count("binaryConnectivity")) binaryConnectivity = us::any_cast(parsedArgs["binaryConnectivity"]); if (parsedArgs.count("rescaleConnectivity")) rescaleConnectivity = us::any_cast(parsedArgs["rescaleConnectivity"]); if (parsedArgs.count("createConnectivityMatriximage")) createConnectivityMatriximage = us::any_cast(parsedArgs["createConnectivityMatriximage"]); if (parsedArgs.count("granularity")) granularity = us::any_cast(parsedArgs["granularity"]); if (parsedArgs.count("startDensity")) startDensity = us::any_cast(parsedArgs["startDensity"]); if (parsedArgs.count("thresholdStepSize")) thresholdStepSize = us::any_cast(parsedArgs["thresholdStepSize"]); try { - const std::string s1="", s2=""; - // load network std::vector networkFile = - mitk::BaseDataIO::LoadBaseDataFromFile( networkName, s1, s2, false ); + mitk::IOUtil::Load( networkName); if( networkFile.empty() ) { std::string errorMessage = "File at " + networkName + " could not be read. Aborting."; MITK_ERROR << errorMessage; return EXIT_FAILURE; } mitk::BaseData* networkBaseData = networkFile.at(0); mitk::ConnectomicsNetwork* network = dynamic_cast( networkBaseData ); if( !network ) { std::string errorMessage = "Read file at " + networkName + " could not be recognized as network. Aborting."; MITK_ERROR << errorMessage; return EXIT_FAILURE; } // streams std::stringstream globalHeaderStream; globalHeaderStream << "NumberOfVertices " << "NumberOfEdges " << "AverageDegree " << "ConnectionDensity " << "NumberOfConnectedComponents " << "AverageComponentSize " << "LargestComponentSize " << "RatioOfNodesInLargestComponent " << "HopPlotExponent " << "EffectiveHopDiameter " << "AverageClusteringCoefficientsC " << "AverageClusteringCoefficientsD " << "AverageClusteringCoefficientsE " << "AverageVertexBetweennessCentrality " << "AverageEdgeBetweennessCentrality " << "NumberOfIsolatedPoints " << "RatioOfIsolatedPoints " << "NumberOfEndPoints " << "RatioOfEndPoints " << "Diameter " << "Diameter90 " << "Radius " << "Radius90 " << "AverageEccentricity " << "AverageEccentricity90 " << "AveragePathLength " << "NumberOfCentralPoints " << "RatioOfCentralPoints " << "SpectralRadius " << "SecondLargestEigenValue " << "AdjacencyTrace " << "AdjacencyEnergy " << "LaplacianTrace " << "LaplacianEnergy " << "LaplacianSpectralGap " << "NormalizedLaplacianTrace " << "NormalizedLaplacianEnergy " << "NormalizedLaplacianNumberOf2s " << "NormalizedLaplacianNumberOf1s " << "NormalizedLaplacianNumberOf0s " << "NormalizedLaplacianLowerSlope " << "NormalizedLaplacianUpperSlope " << "SmallWorldness" << std::endl; std::stringstream localHeaderStream; std::stringstream regionalHeaderStream; std::stringstream globalDataStream; std::stringstream localDataStream; std::stringstream regionalDataStream; std::string globalOutName = outName + "_global.txt"; std::string localOutName = outName + "_local.txt"; std::string regionalOutName = outName + "_regional.txt"; bool firstRun( true ); // iterate over all three possible methods for(unsigned int method( 0 ); method < 3; method++) { // 0 - Random removal threshold // 1 - Largest density below threshold // 2 - Threshold based // iterate over possible targets for( unsigned int step( 0 ); step < granularity; step++ ) { double targetValue( 0.0 ); bool newStep( true ); switch ( method ) { case mitk::ConnectomicsNetworkThresholder::RandomRemovalOfWeakest : case mitk::ConnectomicsNetworkThresholder::LargestLowerThanDensity : targetValue = startDensity * (1 - static_cast( step ) / ( granularity + 0.5 ) ); break; case mitk::ConnectomicsNetworkThresholder::ThresholdBased : targetValue = static_cast( thresholdStepSize * step ); break; default: MITK_ERROR << "Invalid thresholding method called, aborting."; return EXIT_FAILURE; break; } mitk::ConnectomicsNetworkThresholder::Pointer thresholder = mitk::ConnectomicsNetworkThresholder::New(); thresholder->SetNetwork( network ); thresholder->SetTargetThreshold( targetValue ); thresholder->SetTargetDensity( targetValue ); thresholder->SetThresholdingScheme( static_cast(method) ); mitk::ConnectomicsNetwork::Pointer thresholdedNetwork = thresholder->GetThresholdedNetwork(); mitk::ConnectomicsStatisticsCalculator::Pointer statisticsCalculator = mitk::ConnectomicsStatisticsCalculator::New(); statisticsCalculator->SetNetwork( thresholdedNetwork ); statisticsCalculator->Update(); // global statistics if( !noGlobalStatistics ) { globalDataStream << statisticsCalculator->GetNumberOfVertices() << " " << statisticsCalculator->GetNumberOfEdges() << " " << statisticsCalculator->GetAverageDegree() << " " << statisticsCalculator->GetConnectionDensity() << " " << statisticsCalculator->GetNumberOfConnectedComponents() << " " << statisticsCalculator->GetAverageComponentSize() << " " << statisticsCalculator->GetLargestComponentSize() << " " << statisticsCalculator->GetRatioOfNodesInLargestComponent() << " " << statisticsCalculator->GetHopPlotExponent() << " " << statisticsCalculator->GetEffectiveHopDiameter() << " " << statisticsCalculator->GetAverageClusteringCoefficientsC() << " " << statisticsCalculator->GetAverageClusteringCoefficientsD() << " " << statisticsCalculator->GetAverageClusteringCoefficientsE() << " " << statisticsCalculator->GetAverageVertexBetweennessCentrality() << " " << statisticsCalculator->GetAverageEdgeBetweennessCentrality() << " " << statisticsCalculator->GetNumberOfIsolatedPoints() << " " << statisticsCalculator->GetRatioOfIsolatedPoints() << " " << statisticsCalculator->GetNumberOfEndPoints() << " " << statisticsCalculator->GetRatioOfEndPoints() << " " << statisticsCalculator->GetDiameter() << " " << statisticsCalculator->GetDiameter90() << " " << statisticsCalculator->GetRadius() << " " << statisticsCalculator->GetRadius90() << " " << statisticsCalculator->GetAverageEccentricity() << " " << statisticsCalculator->GetAverageEccentricity90() << " " << statisticsCalculator->GetAveragePathLength() << " " << statisticsCalculator->GetNumberOfCentralPoints() << " " << statisticsCalculator->GetRatioOfCentralPoints() << " " << statisticsCalculator->GetSpectralRadius() << " " << statisticsCalculator->GetSecondLargestEigenValue() << " " << statisticsCalculator->GetAdjacencyTrace() << " " << statisticsCalculator->GetAdjacencyEnergy() << " " << statisticsCalculator->GetLaplacianTrace() << " " << statisticsCalculator->GetLaplacianEnergy() << " " << statisticsCalculator->GetLaplacianSpectralGap() << " " << statisticsCalculator->GetNormalizedLaplacianTrace() << " " << statisticsCalculator->GetNormalizedLaplacianEnergy() << " " << statisticsCalculator->GetNormalizedLaplacianNumberOf2s() << " " << statisticsCalculator->GetNormalizedLaplacianNumberOf1s() << " " << statisticsCalculator->GetNormalizedLaplacianNumberOf0s() << " " << statisticsCalculator->GetNormalizedLaplacianLowerSlope() << " " << statisticsCalculator->GetNormalizedLaplacianUpperSlope() << " " << statisticsCalculator->GetSmallWorldness() << std::endl; } // end global statistics //create connectivity matrix png if( createConnectivityMatriximage ) { std::string connectivity_png_postfix = "_connectivity"; if( binaryConnectivity ) { connectivity_png_postfix += "_binary"; } else if( rescaleConnectivity ) { connectivity_png_postfix += "_rescaled"; } connectivity_png_postfix += ".png"; /* File format * A png file depicting the binary connectivity matrix */ itk::ConnectomicsNetworkToConnectivityMatrixImageFilter::Pointer filter = itk::ConnectomicsNetworkToConnectivityMatrixImageFilter::New(); filter->SetInputNetwork( network ); filter->SetBinaryConnectivity( binaryConnectivity ); filter->SetRescaleConnectivity( rescaleConnectivity ); filter->Update(); typedef itk::ConnectomicsNetworkToConnectivityMatrixImageFilter::OutputImageType connectivityMatrixImageType; itk::ImageFileWriter< connectivityMatrixImageType >::Pointer connectivityWriter = itk::ImageFileWriter< connectivityMatrixImageType >::New(); connectivityWriter->SetInput( filter->GetOutput() ); connectivityWriter->SetFileName( outName + connectivity_png_postfix); connectivityWriter->Update(); std::cout << "Connectivity matrix image written."; } // end create connectivity matrix png /* * We can either calculate local indices for specific nodes, or specific regions */ // Create LabelToIndex translation std::map< std::string, int > labelToIdMap; std::vector< mitk::ConnectomicsNetwork::NetworkNode > nodeVector = thresholdedNetwork->GetVectorOfAllNodes(); for(int loop(0); loop < nodeVector.size(); loop++) { labelToIdMap.insert( std::pair< std::string, int>(nodeVector.at(loop).label, nodeVector.at(loop).id) ); } std::vector< int > degreeVector = thresholdedNetwork->GetDegreeOfNodes(); std::vector< double > ccVector = thresholdedNetwork->GetLocalClusteringCoefficients( ); std::vector< double > bcVector = thresholdedNetwork->GetNodeBetweennessVector( ); // calculate local indices { // only add to header for the first step of the first method if( firstRun ) { localHeaderStream << "Th_method " << "Th_target " << "density"; } double density = statisticsCalculator->GetConnectionDensity(); localDataStream << "\n" << method << " " << targetValue << " " << density; for(unsigned int loop(0); loop < localLabels.size(); loop++ ) { if( network->CheckForLabel(localLabels.at( loop )) ) { if( firstRun ) { localHeaderStream << " " << localLabels.at( loop ) << "_Degree " << localLabels.at( loop ) << "_CC " << localLabels.at( loop ) << "_BC"; } localDataStream << " " << degreeVector.at( labelToIdMap.find( localLabels.at( loop ) )->second ) << " " << ccVector.at( labelToIdMap.find( localLabels.at( loop ) )->second ) << " " << bcVector.at( labelToIdMap.find( localLabels.at( loop ) )->second ); } else { MITK_ERROR << "Illegal label. Label: \"" << localLabels.at( loop ) << "\" not found."; } } } // calculate regional indices { // only add to header for the first step of the first method if( firstRun ) { regionalHeaderStream << "Th_method " << "Th_target " << "density"; } double density = statisticsCalculator->GetConnectionDensity(); regionalDataStream << "\n" << method << " " << targetValue << " " << density; for( parsedRegionsIterator = parsedRegions.begin(); parsedRegionsIterator != parsedRegions.end(); parsedRegionsIterator++ ) { std::vector regionLabelsVector = parsedRegionsIterator->second; std::string regionName = parsedRegionsIterator->first; double sumDegree( 0 ); double sumCC( 0 ); double sumBC( 0 ); double count( 0 ); for( int loop(0); loop < regionLabelsVector.size(); loop++ ) { if( thresholdedNetwork->CheckForLabel(regionLabelsVector.at( loop )) ) { sumDegree = sumDegree + degreeVector.at( labelToIdMap.find( regionLabelsVector.at( loop ) )->second ); sumCC = sumCC + ccVector.at( labelToIdMap.find( regionLabelsVector.at( loop ) )->second ); sumBC = sumBC + bcVector.at( labelToIdMap.find( regionLabelsVector.at( loop ) )->second ); count = count + 1; } else { MITK_ERROR << "Illegal label. Label: \"" << regionLabelsVector.at( loop ) << "\" not found."; } } // only add to header for the first step of the first method if( firstRun ) { regionalHeaderStream << " " << regionName << "_LocalAverageDegree " << regionName << "_LocalAverageCC " << regionName << "_LocalAverageBC " << regionName << "_NumberOfNodes"; } regionalDataStream << " " << sumDegree / count << " " << sumCC / count << " " << sumBC / count << " " << count; } } firstRun = false; } }// end calculate local averages if( !noGlobalStatistics ) { std::cout << "Writing to " << globalOutName; std::ofstream glocalOutFile( globalOutName.c_str(), ios::out ); if( ! glocalOutFile.is_open() ) { std::string errorMessage = "Could not open " + globalOutName + " for writing."; MITK_ERROR << errorMessage; return EXIT_FAILURE; } glocalOutFile << globalHeaderStream.str() << globalDataStream.str(); glocalOutFile.close(); } if( localLabels.size() > 0 ) { std::cout << "Writing to " << localOutName; std::ofstream localOutFile( localOutName.c_str(), ios::out ); if( ! localOutFile.is_open() ) { std::string errorMessage = "Could not open " + localOutName + " for writing."; MITK_ERROR << errorMessage; return EXIT_FAILURE; } localOutFile << localHeaderStream.str() << localDataStream.str(); localOutFile.close(); } if( parsedRegions.size() > 0 ) { std::cout << "Writing to " << regionalOutName; std::ofstream regionalOutFile( regionalOutName.c_str(), ios::out ); if( ! regionalOutFile.is_open() ) { std::string errorMessage = "Could not open " + regionalOutName + " for writing."; MITK_ERROR << errorMessage; return EXIT_FAILURE; } regionalOutFile << regionalHeaderStream.str() << regionalDataStream.str(); regionalOutFile.close(); } return EXIT_SUCCESS; } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } std::cout << "DONE"; return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/PeakExtraction.cpp b/Modules/DiffusionImaging/MiniApps/PeakExtraction.cpp index 7f8d7c47c0..25145658c4 100755 --- a/Modules/DiffusionImaging/MiniApps/PeakExtraction.cpp +++ b/Modules/DiffusionImaging/MiniApps/PeakExtraction.cpp @@ -1,374 +1,355 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include -#include #include #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include -mitk::Image::Pointer LoadData(std::string filename) -{ - if( filename.empty() ) - return NULL; - - const std::string s1="", s2=""; - std::vector infile = mitk::BaseDataIO::LoadBaseDataFromFile( filename, s1, s2, false ); - if( infile.empty() ) - { - std::cout << "File " << filename << " could not be read!"; - return NULL; - } - - mitk::BaseData::Pointer baseData = infile.at(0); - return dynamic_cast(baseData.GetPointer()); -} - - template int StartPeakExtraction(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("image", "i", mitkCommandLineParser::InputFile, "Input image", "sh coefficient image", us::Any(), false); parser.addArgument("outroot", "o", mitkCommandLineParser::OutputDirectory, "Output directory", "output root", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::InputFile, "Mask", "mask image"); parser.addArgument("normalization", "n", mitkCommandLineParser::Int, "Normalization", "0=no norm, 1=max norm, 2=single vec norm", 1, true); parser.addArgument("numpeaks", "p", mitkCommandLineParser::Int, "Max. number of peaks", "maximum number of extracted peaks", 2, true); parser.addArgument("peakthres", "r", mitkCommandLineParser::Float, "Peak threshold", "peak threshold relative to largest peak", 0.4, true); parser.addArgument("abspeakthres", "a", mitkCommandLineParser::Float, "Absolute peak threshold", "absolute peak threshold weighted with local GFA value", 0.06, true); parser.addArgument("shConvention", "s", mitkCommandLineParser::String, "Use specified SH-basis", "use specified SH-basis (MITK, FSL, MRtrix)", string("MITK"), true); parser.addArgument("noFlip", "f", mitkCommandLineParser::Bool, "No flip", "do not flip input image to match MITK coordinate convention"); parser.setCategory("Preprocessing Tools"); parser.setTitle("Peak Extraction"); parser.setDescription(""); parser.setContributor("MBI"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; // mandatory arguments string imageName = us::any_cast(parsedArgs["image"]); string outRoot = us::any_cast(parsedArgs["outroot"]); // optional arguments string maskImageName(""); if (parsedArgs.count("mask")) maskImageName = us::any_cast(parsedArgs["mask"]); int normalization = 1; if (parsedArgs.count("normalization")) normalization = us::any_cast(parsedArgs["normalization"]); int numPeaks = 2; if (parsedArgs.count("numpeaks")) numPeaks = us::any_cast(parsedArgs["numpeaks"]); float peakThres = 0.4; if (parsedArgs.count("peakthres")) peakThres = us::any_cast(parsedArgs["peakthres"]); float absPeakThres = 0.06; if (parsedArgs.count("abspeakthres")) absPeakThres = us::any_cast(parsedArgs["abspeakthres"]); bool noFlip = false; if (parsedArgs.count("noFlip")) noFlip = us::any_cast(parsedArgs["noFlip"]); std::cout << "image: " << imageName; std::cout << "outroot: " << outRoot; if (!maskImageName.empty()) std::cout << "mask: " << maskImageName; else std::cout << "no mask image selected"; std::cout << "numpeaks: " << numPeaks; std::cout << "peakthres: " << peakThres; std::cout << "abspeakthres: " << absPeakThres; std::cout << "shOrder: " << shOrder; try { - mitk::Image::Pointer image = LoadData(imageName); - mitk::Image::Pointer mask = LoadData(maskImageName); + mitk::Image::Pointer image = mitk::IOUtil::LoadImage(imageName); + mitk::Image::Pointer mask = mitk::IOUtil::LoadImage(maskImageName); typedef itk::Image ItkUcharImgType; typedef itk::FiniteDiffOdfMaximaExtractionFilter< float, shOrder, 20242 > MaximaExtractionFilterType; typename MaximaExtractionFilterType::Pointer filter = MaximaExtractionFilterType::New(); int toolkitConvention = 0; if (parsedArgs.count("shConvention")) { string convention = us::any_cast(parsedArgs["shConvention"]).c_str(); if ( boost::algorithm::equals(convention, "FSL") ) { toolkitConvention = 1; std::cout << "Using FSL SH-basis"; } else if ( boost::algorithm::equals(convention, "MRtrix") ) { toolkitConvention = 2; std::cout << "Using MRtrix SH-basis"; } else std::cout << "Using MITK SH-basis"; } else std::cout << "Using MITK SH-basis"; ItkUcharImgType::Pointer itkMaskImage = NULL; if (mask.IsNotNull()) { try{ itkMaskImage = ItkUcharImgType::New(); mitk::CastToItkImage(mask, itkMaskImage); filter->SetMaskImage(itkMaskImage); } catch(...) { } } if (toolkitConvention>0) { std::cout << "Converting coefficient image to MITK format"; typedef itk::ShCoefficientImageImporter< float, shOrder > ConverterType; typedef mitk::ImageToItk< itk::Image< float, 4 > > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(image); caster->Update(); itk::Image< float, 4 >::Pointer itkImage = caster->GetOutput(); typename ConverterType::Pointer converter = ConverterType::New(); if (noFlip) { converter->SetInputImage(itkImage); } else { std::cout << "Flipping image"; itk::FixedArray flipAxes; flipAxes[0] = true; flipAxes[1] = true; flipAxes[2] = false; flipAxes[3] = false; itk::FlipImageFilter< itk::Image< float, 4 > >::Pointer flipper = itk::FlipImageFilter< itk::Image< float, 4 > >::New(); flipper->SetInput(itkImage); flipper->SetFlipAxes(flipAxes); flipper->Update(); itk::Image< float, 4 >::Pointer flipped = flipper->GetOutput(); itk::Matrix< double,4,4 > m = itkImage->GetDirection(); m[0][0] *= -1; m[1][1] *= -1; flipped->SetDirection(m); itk::Point< float, 4 > o = itkImage->GetOrigin(); o[0] -= (flipped->GetLargestPossibleRegion().GetSize(0)-1); o[1] -= (flipped->GetLargestPossibleRegion().GetSize(1)-1); flipped->SetOrigin(o); converter->SetInputImage(flipped); } std::cout << "Starting conversion"; switch (toolkitConvention) { case 1: converter->SetToolkit(ConverterType::FSL); filter->SetToolkit(MaximaExtractionFilterType::FSL); break; case 2: converter->SetToolkit(ConverterType::MRTRIX); filter->SetToolkit(MaximaExtractionFilterType::MRTRIX); break; default: converter->SetToolkit(ConverterType::FSL); filter->SetToolkit(MaximaExtractionFilterType::FSL); break; } converter->GenerateData(); filter->SetInput(converter->GetCoefficientImage()); } else { try{ typedef mitk::ImageToItk< typename MaximaExtractionFilterType::CoefficientImageType > CasterType; typename CasterType::Pointer caster = CasterType::New(); caster->SetInput(image); caster->Update(); filter->SetInput(caster->GetOutput()); } catch(...) { std::cout << "wrong image type"; return EXIT_FAILURE; } } filter->SetMaxNumPeaks(numPeaks); filter->SetPeakThreshold(peakThres); filter->SetAbsolutePeakThreshold(absPeakThres); filter->SetAngularThreshold(1); switch (normalization) { case 0: filter->SetNormalizationMethod(MaximaExtractionFilterType::NO_NORM); break; case 1: filter->SetNormalizationMethod(MaximaExtractionFilterType::MAX_VEC_NORM); break; case 2: filter->SetNormalizationMethod(MaximaExtractionFilterType::SINGLE_VEC_NORM); break; } std::cout << "Starting extraction"; filter->Update(); // write direction images { typedef typename MaximaExtractionFilterType::ItkDirectionImageContainer ItkDirectionImageContainer; typename ItkDirectionImageContainer::Pointer container = filter->GetDirectionImageContainer(); for (unsigned int i=0; iSize(); i++) { typename MaximaExtractionFilterType::ItkDirectionImage::Pointer itkImg = container->GetElement(i); if (itkMaskImage.IsNotNull()) { itkImg->SetDirection(itkMaskImage->GetDirection()); itkImg->SetOrigin(itkMaskImage->GetOrigin()); } string outfilename = outRoot; outfilename.append("_DIRECTION_"); outfilename.append(boost::lexical_cast(i)); outfilename.append(".nrrd"); typedef itk::ImageFileWriter< typename MaximaExtractionFilterType::ItkDirectionImage > WriterType; typename WriterType::Pointer writer = WriterType::New(); writer->SetFileName(outfilename); writer->SetInput(itkImg); writer->Update(); } } // write num directions image { ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage(); if (itkMaskImage.IsNotNull()) { numDirImage->SetDirection(itkMaskImage->GetDirection()); numDirImage->SetOrigin(itkMaskImage->GetOrigin()); } string outfilename = outRoot.c_str(); outfilename.append("_NUM_DIRECTIONS.nrrd"); typedef itk::ImageFileWriter< ItkUcharImgType > WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetFileName(outfilename); writer->SetInput(numDirImage); writer->Update(); } // write vector field { - mitk::FiberBundleX::Pointer directions = filter->GetOutputFiberBundle(); + mitk::FiberBundle::Pointer directions = filter->GetOutputFiberBundle(); string outfilename = outRoot.c_str(); outfilename.append("_VECTOR_FIELD.fib"); mitk::IOUtil::Save(directions.GetPointer(),outfilename.c_str()); } } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("image", "i", mitkCommandLineParser::InputFile, "Input image", "sh coefficient image", us::Any(), false); parser.addArgument("shOrder", "sh", mitkCommandLineParser::Int, "Spherical harmonics order", "spherical harmonics order"); parser.addArgument("outroot", "o", mitkCommandLineParser::OutputDirectory, "Output directory", "output root", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::InputFile, "Mask", "mask image"); parser.addArgument("normalization", "n", mitkCommandLineParser::Int, "Normalization", "0=no norm, 1=max norm, 2=single vec norm", 1, true); parser.addArgument("numpeaks", "p", mitkCommandLineParser::Int, "Max. number of peaks", "maximum number of extracted peaks", 2, true); parser.addArgument("peakthres", "r", mitkCommandLineParser::Float, "Peak threshold", "peak threshold relative to largest peak", 0.4, true); parser.addArgument("abspeakthres", "a", mitkCommandLineParser::Float, "Absolute peak threshold", "absolute peak threshold weighted with local GFA value", 0.06, true); parser.addArgument("shConvention", "s", mitkCommandLineParser::String, "Use specified SH-basis", "use specified SH-basis (MITK, FSL, MRtrix)", string("MITK"), true); parser.addArgument("noFlip", "f", mitkCommandLineParser::Bool, "No flip", "do not flip input image to match MITK coordinate convention"); parser.setCategory("Preprocessing Tools"); parser.setTitle("Peak Extraction"); parser.setDescription(""); parser.setContributor("MBI"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; int shOrder = -1; if (parsedArgs.count("shOrder")) shOrder = us::any_cast(parsedArgs["shOrder"]); switch (shOrder) { case 4: return StartPeakExtraction<4>(argc, argv); case 6: return StartPeakExtraction<6>(argc, argv); case 8: return StartPeakExtraction<8>(argc, argv); case 10: return StartPeakExtraction<10>(argc, argv); case 12: return StartPeakExtraction<12>(argc, argv); } return EXIT_FAILURE; } diff --git a/Modules/DiffusionImaging/MiniApps/PeaksAngularError.cpp b/Modules/DiffusionImaging/MiniApps/PeaksAngularError.cpp index 51a28efe4c..be8f9a93f7 100755 --- a/Modules/DiffusionImaging/MiniApps/PeaksAngularError.cpp +++ b/Modules/DiffusionImaging/MiniApps/PeaksAngularError.cpp @@ -1,205 +1,204 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("test", "t", mitkCommandLineParser::StringList, "Test images", "test direction images", us::Any(), false); parser.addArgument("reference", "r", mitkCommandLineParser::StringList, "Reference images", "reference direction images", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output directory", "output root", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::InputFile, "Mask", "mask image"); parser.addArgument("verbose", "v", mitkCommandLineParser::Bool, "Verbose", "output optional and intermediate calculation results"); parser.addArgument("ignore", "i", mitkCommandLineParser::Bool, "Ignore", "don't increase error for missing or too many directions"); parser.setCategory("Preprocessing Tools"); parser.setTitle("Peaks Angular Error"); parser.setDescription(""); parser.setContributor("MBI"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; mitkCommandLineParser::StringContainerType testImages = us::any_cast(parsedArgs["test"]); mitkCommandLineParser::StringContainerType referenceImages = us::any_cast(parsedArgs["reference"]); string maskImage(""); if (parsedArgs.count("mask")) maskImage = us::any_cast(parsedArgs["mask"]); string outRoot = us::any_cast(parsedArgs["out"]); bool verbose = false; if (parsedArgs.count("verbose")) verbose = us::any_cast(parsedArgs["verbose"]); bool ignore = false; if (parsedArgs.count("ignore")) ignore = us::any_cast(parsedArgs["ignore"]); try { typedef itk::Image ItkUcharImgType; typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; typedef itk::VectorContainer< unsigned int, ItkDirectionImage3DType::Pointer > ItkDirectionImageContainerType; typedef itk::EvaluateDirectionImagesFilter< float > EvaluationFilterType; ItkDirectionImageContainerType::Pointer directionImageContainer = ItkDirectionImageContainerType::New(); for (unsigned int i=0; i(mitk::IOUtil::LoadDataNode(testImages.at(i))->GetData()); typedef mitk::ImageToItk< ItkDirectionImage3DType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkDirectionImage3DType::Pointer itkImg = caster->GetOutput(); directionImageContainer->InsertElement(directionImageContainer->Size(),itkImg); } catch(...){ std::cout << "could not load: " << referenceImages.at(i); } } // load reference directions ItkDirectionImageContainerType::Pointer referenceImageContainer = ItkDirectionImageContainerType::New(); for (unsigned int i=0; i(mitk::IOUtil::LoadDataNode(referenceImages.at(i))->GetData()); typedef mitk::ImageToItk< ItkDirectionImage3DType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkDirectionImage3DType::Pointer itkImg = caster->GetOutput(); referenceImageContainer->InsertElement(referenceImageContainer->Size(),itkImg); } catch(...){ std::cout << "could not load: " << referenceImages.at(i); } } // load/create mask image ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); if (maskImage.compare("")==0) { ItkDirectionImage3DType::Pointer dirImg = referenceImageContainer->GetElement(0); itkMaskImage->SetSpacing( dirImg->GetSpacing() ); itkMaskImage->SetOrigin( dirImg->GetOrigin() ); itkMaskImage->SetDirection( dirImg->GetDirection() ); itkMaskImage->SetLargestPossibleRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetBufferedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetRequestedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->Allocate(); itkMaskImage->FillBuffer(1); } else { mitk::Image::Pointer mitkMaskImage = dynamic_cast(mitk::IOUtil::LoadDataNode(maskImage)->GetData()); mitk::CastToItkImage(mitkMaskImage, itkMaskImage); } // evaluate directions EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New(); evaluationFilter->SetImageSet(directionImageContainer); evaluationFilter->SetReferenceImageSet(referenceImageContainer); evaluationFilter->SetMaskImage(itkMaskImage); evaluationFilter->SetIgnoreMissingDirections(ignore); evaluationFilter->Update(); if (verbose) { EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0); typedef itk::ImageFileWriter< EvaluationFilterType::OutputImageType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_ERROR_IMAGE.nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(angularErrorImage); writer->Update(); } string logFile = outRoot; logFile.append("_ANGULAR_ERROR.csv"); ofstream file; file.open (logFile.c_str()); string sens = "Mean:"; sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMeanAngularError())); sens.append(";\n"); sens.append("Median:"); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMedianAngularError())); sens.append(";\n"); sens.append("Maximum:"); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMaxAngularError())); sens.append(";\n"); sens.append("Minimum:"); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMinAngularError())); sens.append(";\n"); sens.append("STDEV:"); sens.append(","); sens.append(boost::lexical_cast(std::sqrt(evaluationFilter->GetVarAngularError()))); sens.append(";\n"); file << sens; file.close(); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/QballReconstruction.cpp b/Modules/DiffusionImaging/MiniApps/QballReconstruction.cpp index 13ea2b526b..e5b0960af0 100644 --- a/Modules/DiffusionImaging/MiniApps/QballReconstruction.cpp +++ b/Modules/DiffusionImaging/MiniApps/QballReconstruction.cpp @@ -1,263 +1,262 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "mitkBaseDataIOFactory.h" #include #include "mitkImage.h" #include "itkAnalyticalDiffusionQballReconstructionImageFilter.h" #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include +#include using namespace mitk; /** * Perform Q-ball reconstruction using a spherical harmonics basis */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input file", "input raw dwi (.dwi or .fsl/.fslgz)", us::Any(), false); parser.addArgument("outFile", "o", mitkCommandLineParser::OutputFile, "Output file", "output file", us::Any(), false); parser.addArgument("shOrder", "sh", mitkCommandLineParser::Int, "Spherical harmonics order", "spherical harmonics order", 4, true); parser.addArgument("b0Threshold", "t", mitkCommandLineParser::Int, "b0 threshold", "baseline image intensity threshold", 0, true); parser.addArgument("lambda", "r", mitkCommandLineParser::Float, "Lambda", "ragularization factor lambda", 0.006, true); parser.addArgument("csa", "csa", mitkCommandLineParser::Bool, "Constant solid angle consideration", "use constant solid angle consideration"); parser.addArgument("outputCoeffs", "shc", mitkCommandLineParser::Bool, "Output coefficients", "output file containing the SH coefficients"); parser.addArgument("mrtrix", "mb", mitkCommandLineParser::Bool, "MRtrix", "use MRtrix compatible spherical harmonics definition"); parser.setCategory("Preprocessing Tools"); parser.setTitle("Qball Reconstruction"); parser.setDescription(""); parser.setContributor("MBI"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; std::string inFileName = us::any_cast(parsedArgs["input"]); std::string outfilename = us::any_cast(parsedArgs["outFile"]); outfilename = itksys::SystemTools::GetFilenamePath(outfilename)+"/"+itksys::SystemTools::GetFilenameWithoutExtension(outfilename); int threshold = 0; if (parsedArgs.count("b0Threshold")) threshold = us::any_cast(parsedArgs["b0Threshold"]); int shOrder = 4; if (parsedArgs.count("shOrder")) shOrder = us::any_cast(parsedArgs["shOrder"]); float lambda = 0.006; if (parsedArgs.count("lambda")) lambda = us::any_cast(parsedArgs["lambda"]); int normalization = 0; if (parsedArgs.count("csa") && us::any_cast(parsedArgs["csa"])) normalization = 6; bool outCoeffs = false; if (parsedArgs.count("outputCoeffs")) outCoeffs = us::any_cast(parsedArgs["outputCoeffs"]); bool mrTrix = false; if (parsedArgs.count("mrtrix")) mrTrix = us::any_cast(parsedArgs["mrtrix"]); try { - const std::string s1="", s2=""; - std::vector infile = BaseDataIO::LoadBaseDataFromFile( inFileName, s1, s2, false ); + std::vector infile = mitk::IOUtil::Load(inFileName); Image::Pointer dwi = dynamic_cast(infile.at(0).GetPointer()); mitk::DiffusionPropertyHelper propertyHelper(dwi); propertyHelper.AverageRedundantGradients(0.001); propertyHelper.InitializeImage(); mitk::QBallImage::Pointer image = mitk::QBallImage::New(); mitk::Image::Pointer coeffsImage = mitk::Image::New(); std::cout << "SH order: " << shOrder; std::cout << "lambda: " << lambda; std::cout << "B0 threshold: " << threshold; switch ( shOrder ) { case 4: { typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer ); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); filter->SetThreshold( threshold ); filter->SetLambda(lambda); filter->SetUseMrtrixBasis(mrTrix); if (normalization==0) filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); else filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); break; } case 6: { typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer ); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); filter->SetThreshold( threshold ); filter->SetLambda(lambda); filter->SetUseMrtrixBasis(mrTrix); if (normalization==0) filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); else filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); break; } case 8: { typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer ); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); filter->SetThreshold( threshold ); filter->SetLambda(lambda); filter->SetUseMrtrixBasis(mrTrix); if (normalization==0) filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); else filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); break; } case 10: { typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer ); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); filter->SetThreshold( threshold ); filter->SetLambda(lambda); filter->SetUseMrtrixBasis(mrTrix); if (normalization==0) filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); else filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); break; } case 12: { typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer ); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); filter->SetThreshold( threshold ); filter->SetLambda(lambda); if (normalization==0) filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); else filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); break; } default: { std::cout << "Supplied SH order not supported. Using default order of 4."; typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer ); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); filter->SetThreshold( threshold ); filter->SetLambda(lambda); filter->SetUseMrtrixBasis(mrTrix); if (normalization==0) filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); else filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); } } std::string coeffout = outfilename; coeffout += "_shcoeffs.nrrd"; outfilename += ".qbi"; mitk::IOUtil::SaveBaseData(image, outfilename); if (outCoeffs) mitk::IOUtil::SaveImage(coeffsImage, coeffout); } catch ( itk::ExceptionObject &err) { std::cout << "Exception: " << err; } catch ( std::exception err) { std::cout << "Exception: " << err.what(); } catch ( ... ) { std::cout << "Exception!"; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/StreamlineTracking.cpp b/Modules/DiffusionImaging/MiniApps/StreamlineTracking.cpp index 8bf091d69e..328d7d0528 100755 --- a/Modules/DiffusionImaging/MiniApps/StreamlineTracking.cpp +++ b/Modules/DiffusionImaging/MiniApps/StreamlineTracking.cpp @@ -1,177 +1,176 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include -#include -#include +#include #include #include #include "mitkCommandLineParser.h" #include int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::StringList, "Input image", "input tensor image (.dti)", us::Any(), false); parser.addArgument("seed", "si", mitkCommandLineParser::InputFile, "Seed image", "binary seed image", us::Any(), true); parser.addArgument("mask", "mi", mitkCommandLineParser::InputFile, "Mask", "binary mask image", us::Any(), true); parser.addArgument("faImage", "fai", mitkCommandLineParser::InputFile, "FA image", "FA image", us::Any(), true); parser.addArgument("minFA", "fa", mitkCommandLineParser::Float, "Min. FA threshold", "minimum fractional anisotropy threshold", 0.15, true); parser.addArgument("minCurv", "c", mitkCommandLineParser::Float, "Min. curvature radius", "minimum curvature radius in mm (default = 0.5*minimum-spacing)"); parser.addArgument("stepSize", "s", mitkCommandLineParser::Float, "Step size", "step size in mm (default = 0.1*minimum-spacing)"); parser.addArgument("tendf", "f", mitkCommandLineParser::Float, "Weight f", "Weighting factor between first eigenvector (f=1 equals FACT tracking) and input vector dependent direction (f=0).", 1.0, true); parser.addArgument("tendg", "g", mitkCommandLineParser::Float, "Weight g", "Weighting factor between input vector (g=0) and tensor deflection (g=1 equals TEND tracking)", 0.0, true); parser.addArgument("numSeeds", "n", mitkCommandLineParser::Int, "Seeds per voxel", "Number of seeds per voxel.", 1, true); parser.addArgument("minLength", "l", mitkCommandLineParser::Float, "Min. fiber length", "minimum fiber length in mm", 20, true); parser.addArgument("interpolate", "ip", mitkCommandLineParser::Bool, "Interpolate", "Use linear interpolation", false, true); parser.addArgument("outFile", "o", mitkCommandLineParser::String, "Output file", "output fiber bundle (.fib)", us::Any(), false); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setTitle("Streamline Tracking"); parser.setDescription(""); parser.setContributor("MBI"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; mitkCommandLineParser::StringContainerType inputImages = us::any_cast(parsedArgs["input"]); string dtiFileName; string outFileName = us::any_cast(parsedArgs["outFile"]); float minFA = 0.15; float minCurv = -1; float stepSize = -1; float tendf = 1; float tendg = 0; float minLength = 20; int numSeeds = 1; bool interpolate = false; if (parsedArgs.count("minCurv")) minCurv = us::any_cast(parsedArgs["minCurv"]); if (parsedArgs.count("minFA")) minFA = us::any_cast(parsedArgs["minFA"]); if (parsedArgs.count("stepSize")) stepSize = us::any_cast(parsedArgs["stepSize"]); if (parsedArgs.count("tendf")) tendf = us::any_cast(parsedArgs["tendf"]); if (parsedArgs.count("tendg")) tendg = us::any_cast(parsedArgs["tendg"]); if (parsedArgs.count("minLength")) minLength = us::any_cast(parsedArgs["minLength"]); if (parsedArgs.count("numSeeds")) numSeeds = us::any_cast(parsedArgs["numSeeds"]); if (parsedArgs.count("interpolate")) interpolate = us::any_cast(parsedArgs["interpolate"]); try { typedef itk::StreamlineTrackingFilter< float > FilterType; FilterType::Pointer filter = FilterType::New(); mitk::Image::Pointer mitkImage = NULL; std::cout << "Loading tensor images ..."; typedef itk::Image< itk::DiffusionTensor3D, 3 > ItkTensorImage; dtiFileName = inputImages.at(0); for (unsigned int i=0; i(mitk::IOUtil::LoadDataNode(inputImages.at(i))->GetData()); mitk::TensorImage::Pointer img = dynamic_cast(mitk::IOUtil::LoadDataNode(inputImages.at(i))->GetData()); ItkTensorImage::Pointer itk_dti = ItkTensorImage::New(); mitk::CastToItkImage(img, itk_dti); filter->SetInput(i, itk_dti); } catch(...){ std::cout << "could not load: " << inputImages.at(i); } } std::cout << "Loading seed image ..."; typedef itk::Image< unsigned char, 3 > ItkUCharImageType; mitk::Image::Pointer mitkSeedImage = NULL; if (parsedArgs.count("seed")) mitkSeedImage = mitk::IOUtil::LoadImage(us::any_cast(parsedArgs["seed"])); std::cout << "Loading mask image ..."; mitk::Image::Pointer mitkMaskImage = NULL; if (parsedArgs.count("mask")) mitkMaskImage = mitk::IOUtil::LoadImage(us::any_cast(parsedArgs["mask"])); // instantiate tracker filter->SetSeedsPerVoxel(numSeeds); filter->SetFaThreshold(minFA); filter->SetMinCurvatureRadius(minCurv); filter->SetStepSize(stepSize); filter->SetF(tendf); filter->SetG(tendg); filter->SetInterpolate(interpolate); filter->SetMinTractLength(minLength); if (mitkSeedImage.IsNotNull()) { ItkUCharImageType::Pointer mask = ItkUCharImageType::New(); mitk::CastToItkImage(mitkSeedImage, mask); filter->SetSeedImage(mask); } if (mitkMaskImage.IsNotNull()) { ItkUCharImageType::Pointer mask = ItkUCharImageType::New(); mitk::CastToItkImage(mitkMaskImage, mask); filter->SetMaskImage(mask); } filter->Update(); vtkSmartPointer fiberBundle = filter->GetFiberPolyData(); if ( fiberBundle->GetNumberOfLines()==0 ) { std::cout << "No fibers reconstructed. Check parametrization."; return EXIT_FAILURE; } - mitk::FiberBundleX::Pointer fib = mitk::FiberBundleX::New(fiberBundle); + mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(fiberBundle); fib->SetReferenceGeometry(mitkImage->GetGeometry()); mitk::IOUtil::SaveBaseData(fib.GetPointer(), outFileName ); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/TensorReconstruction.cpp b/Modules/DiffusionImaging/MiniApps/TensorReconstruction.cpp index f0063b77a4..bcd79465eb 100644 --- a/Modules/DiffusionImaging/MiniApps/TensorReconstruction.cpp +++ b/Modules/DiffusionImaging/MiniApps/TensorReconstruction.cpp @@ -1,102 +1,100 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "mitkBaseDataIOFactory.h" #include "mitkImage.h" #include #include "mitkBaseData.h" #include #include #include #include #include #include "mitkCommandLineParser.h" #include +#include using namespace mitk; /** * Convert files from one ending to the other */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input file", "input raw dwi (.dwi or .fsl/.fslgz)", us::Any(), false); parser.addArgument("outFile", "o", mitkCommandLineParser::OutputFile, "Output file", "output file", us::Any(), false); parser.addArgument("b0Threshold", "t", mitkCommandLineParser::Int, "b0 threshold", "baseline image intensity threshold", 0, true); parser.setCategory("Preprocessing Tools"); parser.setTitle("Tensor Reconstruction"); parser.setDescription(""); parser.setContributor("MBI"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; std::string inFileName = us::any_cast(parsedArgs["input"]); std::string outfilename = us::any_cast(parsedArgs["outFile"]); outfilename = itksys::SystemTools::GetFilenamePath(outfilename)+"/"+itksys::SystemTools::GetFilenameWithoutExtension(outfilename); outfilename += ".dti"; int threshold = 0; if (parsedArgs.count("b0Threshold")) threshold = us::any_cast(parsedArgs["b0Threshold"]); try { - const std::string s1="", s2=""; - std::vector infile = BaseDataIO::LoadBaseDataFromFile( inFileName, s1, s2, false ); - Image::Pointer dwi = dynamic_cast(infile.at(0).GetPointer()); + Image::Pointer dwi = IOUtil::LoadImage(inFileName); mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, float > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer ); filter->SetBValue( mitk::DiffusionPropertyHelper::GetReferenceBValue( dwi )); filter->SetThreshold(threshold); filter->Update(); // Save tensor image itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileType( itk::ImageIOBase::Binary ); io->UseCompressionOn(); itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< float >, 3 > >::Pointer writer = itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< float >, 3 > >::New(); writer->SetInput(filter->GetOutput()); writer->SetFileName(outfilename); writer->SetImageIO(io); writer->UseCompressionOn(); writer->Update(); } catch ( itk::ExceptionObject &err) { std::cout << "Exception: " << err; } catch ( std::exception err) { std::cout << "Exception: " << err.what(); } catch ( ... ) { std::cout << "Exception!"; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/MiniApps/TractogramAngularError.cpp b/Modules/DiffusionImaging/MiniApps/TractogramAngularError.cpp index aa2a25ef82..39fb8c85ef 100755 --- a/Modules/DiffusionImaging/MiniApps/TractogramAngularError.cpp +++ b/Modules/DiffusionImaging/MiniApps/TractogramAngularError.cpp @@ -1,202 +1,202 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "MiniAppManager.h" #include #include #include #include #include #include #include #include "ctkCommandLineParser.h" #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include int TractogramAngularError(int argc, char* argv[]) { ctkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", ctkCommandLineParser::String, "input tractogram (.fib, vtk ascii file format)", us::Any(), false); parser.addArgument("reference", "r", ctkCommandLineParser::StringList, "reference direction images", us::Any(), false); parser.addArgument("out", "o", ctkCommandLineParser::String, "output root", us::Any(), false); parser.addArgument("mask", "m", ctkCommandLineParser::String, "mask image"); parser.addArgument("verbose", "v", ctkCommandLineParser::Bool, "output optional and intermediate calculation results"); parser.addArgument("ignore", "n", ctkCommandLineParser::Bool, "don't increase error for missing or too many directions"); parser.addArgument("trilinear", "t", ctkCommandLineParser::Bool, "use trilinear instead of nearest neighbor interpolation"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; ctkCommandLineParser::StringContainerType referenceImages = us::any_cast(parsedArgs["reference"]); string fibFile = us::any_cast(parsedArgs["input"]); string maskImage(""); if (parsedArgs.count("mask")) maskImage = us::any_cast(parsedArgs["mask"]); string outRoot = us::any_cast(parsedArgs["out"]); bool verbose = false; if (parsedArgs.count("verbose")) verbose = us::any_cast(parsedArgs["verbose"]); bool ignore = false; if (parsedArgs.count("ignore")) ignore = us::any_cast(parsedArgs["ignore"]); bool interpolate = false; if (parsedArgs.count("interpolate")) interpolate = us::any_cast(parsedArgs["interpolate"]); try { RegisterDiffusionCoreObjectFactory(); RegisterFiberTrackingObjectFactory(); typedef itk::Image ItkUcharImgType; typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; typedef itk::VectorContainer< int, ItkDirectionImage3DType::Pointer > ItkDirectionImageContainerType; typedef itk::EvaluateTractogramDirectionsFilter< float > EvaluationFilterType; // load fiber bundle - mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); + mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); if (!inputTractogram) return EXIT_FAILURE; // load reference directions ItkDirectionImageContainerType::Pointer referenceImageContainer = ItkDirectionImageContainerType::New(); for (int i=0; i(mitk::IOUtil::LoadDataNode(referenceImages.at(i))->GetData()); typedef mitk::ImageToItk< ItkDirectionImage3DType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkDirectionImage3DType::Pointer itkImg = caster->GetOutput(); referenceImageContainer->InsertElement(referenceImageContainer->Size(),itkImg); } catch(...){ MITK_INFO << "could not load: " << referenceImages.at(i); } } // load/create mask image ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); if (maskImage.compare("")==0) { ItkDirectionImage3DType::Pointer dirImg = referenceImageContainer->GetElement(0); itkMaskImage->SetSpacing( dirImg->GetSpacing() ); itkMaskImage->SetOrigin( dirImg->GetOrigin() ); itkMaskImage->SetDirection( dirImg->GetDirection() ); itkMaskImage->SetLargestPossibleRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetBufferedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->SetRequestedRegion( dirImg->GetLargestPossibleRegion() ); itkMaskImage->Allocate(); itkMaskImage->FillBuffer(1); } else { mitk::Image::Pointer mitkMaskImage = dynamic_cast(mitk::IOUtil::LoadDataNode(maskImage)->GetData()); mitk::CastToItkImage(mitkMaskImage, itkMaskImage); } // evaluate directions EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New(); evaluationFilter->SetTractogram(inputTractogram); evaluationFilter->SetReferenceImageSet(referenceImageContainer); evaluationFilter->SetMaskImage(itkMaskImage); evaluationFilter->SetIgnoreMissingDirections(ignore); evaluationFilter->SetUseInterpolation(interpolate); evaluationFilter->Update(); if (verbose) { EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0); typedef itk::ImageFileWriter< EvaluationFilterType::OutputImageType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_ERROR_IMAGE.nrrd"); writer->SetFileName(outfilename.c_str()); writer->SetInput(angularErrorImage); writer->Update(); } string logFile = outRoot; logFile.append("_ANGULAR_ERROR.csv"); ofstream file; file.open (logFile.c_str()); string sens = "Mean:"; sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMeanAngularError())); sens.append(";\n"); sens.append("Median:"); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMedianAngularError())); sens.append(";\n"); sens.append("Maximum:"); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMaxAngularError())); sens.append(";\n"); sens.append("Minimum:"); sens.append(","); sens.append(boost::lexical_cast(evaluationFilter->GetMinAngularError())); sens.append(";\n"); sens.append("STDEV:"); sens.append(","); sens.append(boost::lexical_cast(std::sqrt(evaluationFilter->GetVarAngularError()))); sens.append(";\n"); file << sens; file.close(); } catch (itk::ExceptionObject e) { MITK_INFO << e; return EXIT_FAILURE; } catch (std::exception e) { MITK_INFO << e.what(); return EXIT_FAILURE; } catch (...) { MITK_INFO << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } RegisterDiffusionMiniApp(TractogramAngularError); diff --git a/Modules/DiffusionImaging/MiniApps/TractometerMetrics.cpp b/Modules/DiffusionImaging/MiniApps/TractometerMetrics.cpp index 0acfa5b28a..d37e7c3980 100755 --- a/Modules/DiffusionImaging/MiniApps/TractometerMetrics.cpp +++ b/Modules/DiffusionImaging/MiniApps/TractometerMetrics.cpp @@ -1,415 +1,414 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include #include #include #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Tractometer Metrics"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setDescription(""); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", mitkCommandLineParser::InputFile, "Input:", "input tractogram (.fib, vtk ascii file format)", us::Any(), false); parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output root", us::Any(), false); parser.addArgument("labels", "l", mitkCommandLineParser::StringList, "Label pairs:", "label pairs", false); parser.addArgument("labelimage", "li", mitkCommandLineParser::String, "Label image:", "label image", false); parser.addArgument("verbose", "v", mitkCommandLineParser::Bool, "Verbose:", "output valid, invalid and no connections as fiber bundles"); parser.addArgument("fileID", "id", mitkCommandLineParser::String, "ID:", "optional ID field"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; mitkCommandLineParser::StringContainerType labelpairs = us::any_cast(parsedArgs["labels"]); string fibFile = us::any_cast(parsedArgs["input"]); string labelImageFile = us::any_cast(parsedArgs["labelimage"]); string outRoot = us::any_cast(parsedArgs["out"]); string fileID = ""; if (parsedArgs.count("fileID")) fileID = us::any_cast(parsedArgs["fileID"]); bool verbose = false; if (parsedArgs.count("verbose")) verbose = us::any_cast(parsedArgs["verbose"]); try { typedef itk::Image ItkShortImgType; typedef itk::Image ItkUcharImgType; // load fiber bundle - mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); + mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::LoadDataNode(labelImageFile)->GetData()); typedef mitk::ImageToItk< ItkShortImgType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkShortImgType::Pointer labelImage = caster->GetOutput(); string path = itksys::SystemTools::GetFilenamePath(labelImageFile); std::vector< bool > detected; std::vector< std::pair< int, int > > labelsvector; std::vector< ItkUcharImgType::Pointer > bundleMasks; std::vector< ItkUcharImgType::Pointer > bundleMasksCoverage; short max = 0; for (unsigned int i=0; i l; l.first = boost::lexical_cast(labelpairs.at(i)); l.second = boost::lexical_cast(labelpairs.at(i+1)); std::cout << labelpairs.at(i); std::cout << labelpairs.at(i+1); if (l.first>max) max=l.first; if (l.second>max) max=l.second; labelsvector.push_back(l); detected.push_back(false); { mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::LoadDataNode(path+"/Bundle"+boost::lexical_cast(labelsvector.size())+"_MASK.nrrd")->GetData()); typedef mitk::ImageToItk< ItkUcharImgType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkUcharImgType::Pointer bundle = caster->GetOutput(); bundleMasks.push_back(bundle); } { mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::LoadDataNode(path+"/Bundle"+boost::lexical_cast(labelsvector.size())+"_MASK_COVERAGE.nrrd")->GetData()); typedef mitk::ImageToItk< ItkUcharImgType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkUcharImgType::Pointer bundle = caster->GetOutput(); bundleMasksCoverage.push_back(bundle); } } vnl_matrix< unsigned char > matrix; matrix.set_size(max, max); matrix.fill(0); vtkSmartPointer polyData = inputTractogram->GetFiberPolyData(); int validConnections = 0; int noConnection = 0; int validBundles = 0; int invalidBundles = 0; int invalidConnections = 0; ItkUcharImgType::Pointer coverage = ItkUcharImgType::New(); coverage->SetSpacing(labelImage->GetSpacing()); coverage->SetOrigin(labelImage->GetOrigin()); coverage->SetDirection(labelImage->GetDirection()); coverage->SetLargestPossibleRegion(labelImage->GetLargestPossibleRegion()); coverage->SetBufferedRegion( labelImage->GetLargestPossibleRegion() ); coverage->SetRequestedRegion( labelImage->GetLargestPossibleRegion() ); coverage->Allocate(); coverage->FillBuffer(0); vtkSmartPointer noConnPoints = vtkSmartPointer::New(); vtkSmartPointer noConnCells = vtkSmartPointer::New(); vtkSmartPointer invalidPoints = vtkSmartPointer::New(); vtkSmartPointer invalidCells = vtkSmartPointer::New(); vtkSmartPointer validPoints = vtkSmartPointer::New(); vtkSmartPointer validCells = vtkSmartPointer::New(); boost::progress_display disp(inputTractogram->GetNumFibers()); for (int i=0; iGetNumFibers(); i++) { ++disp; vtkCell* cell = polyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (numPoints>1) { double* start = points->GetPoint(0); itk::Point itkStart; itkStart[0] = start[0]; itkStart[1] = start[1]; itkStart[2] = start[2]; itk::Index<3> idxStart; labelImage->TransformPhysicalPointToIndex(itkStart, idxStart); double* end = points->GetPoint(numPoints-1); itk::Point itkEnd; itkEnd[0] = end[0]; itkEnd[1] = end[1]; itkEnd[2] = end[2]; itk::Index<3> idxEnd; labelImage->TransformPhysicalPointToIndex(itkEnd, idxEnd); if ( labelImage->GetPixel(idxStart)==0 || labelImage->GetPixel(idxEnd)==0 ) { noConnection++; if (verbose) { vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = noConnPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } noConnCells->InsertNextCell(container); } } else { bool invalid = true; for (unsigned int i=0; i l = labelsvector.at(i); if ( (labelImage->GetPixel(idxStart)==l.first && labelImage->GetPixel(idxEnd)==l.second) || (labelImage->GetPixel(idxStart)==l.second && labelImage->GetPixel(idxEnd)==l.first) ) { for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; bundle->TransformPhysicalPointToIndex(itkP, idx); if ( !bundle->GetPixel(idx)>0 && bundle->GetLargestPossibleRegion().IsInside(idx) ) { outside=true; } } if (!outside) { validConnections++; if (detected.at(i)==false) validBundles++; detected.at(i) = true; invalid = false; vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = validPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; coverage->TransformPhysicalPointToIndex(itkP, idx); if ( coverage->GetLargestPossibleRegion().IsInside(idx) ) coverage->SetPixel(idx, 1); } validCells->InsertNextCell(container); } break; } } if (invalid==true) { invalidConnections++; int x = labelImage->GetPixel(idxStart)-1; int y = labelImage->GetPixel(idxEnd)-1; if (x>=0 && y>0 && x container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = invalidPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } invalidCells->InsertNextCell(container); } } } } } if (verbose) { mitk::CoreObjectFactory::FileWriterList fileWriters = mitk::CoreObjectFactory::GetInstance()->GetFileWriters(); vtkSmartPointer noConnPolyData = vtkSmartPointer::New(); noConnPolyData->SetPoints(noConnPoints); noConnPolyData->SetLines(noConnCells); - mitk::FiberBundleX::Pointer noConnFib = mitk::FiberBundleX::New(noConnPolyData); + mitk::FiberBundle::Pointer noConnFib = mitk::FiberBundle::New(noConnPolyData); string ncfilename = outRoot; ncfilename.append("_NC.fib"); mitk::IOUtil::SaveBaseData(noConnFib.GetPointer(), ncfilename ); vtkSmartPointer invalidPolyData = vtkSmartPointer::New(); invalidPolyData->SetPoints(invalidPoints); invalidPolyData->SetLines(invalidCells); - mitk::FiberBundleX::Pointer invalidFib = mitk::FiberBundleX::New(invalidPolyData); + mitk::FiberBundle::Pointer invalidFib = mitk::FiberBundle::New(invalidPolyData); string icfilename = outRoot; icfilename.append("_IC.fib"); mitk::IOUtil::SaveBaseData(invalidFib.GetPointer(), icfilename ); vtkSmartPointer validPolyData = vtkSmartPointer::New(); validPolyData->SetPoints(validPoints); validPolyData->SetLines(validCells); - mitk::FiberBundleX::Pointer validFib = mitk::FiberBundleX::New(validPolyData); + mitk::FiberBundle::Pointer validFib = mitk::FiberBundle::New(validPolyData); string vcfilename = outRoot; vcfilename.append("_VC.fib"); mitk::IOUtil::SaveBaseData(validFib.GetPointer(), vcfilename ); { typedef itk::ImageFileWriter< ItkUcharImgType > WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetFileName(outRoot+"_ABC.nrrd"); writer->SetInput(coverage); writer->Update(); } } // calculate coverage int wmVoxels = 0; int coveredVoxels = 0; itk::ImageRegionIterator it (coverage, coverage->GetLargestPossibleRegion()); while(!it.IsAtEnd()) { bool wm = false; for (unsigned int i=0; iGetPixel(it.GetIndex())>0) { wm = true; wmVoxels++; break; } } if (wm && it.Get()>0) coveredVoxels++; ++it; } int numFibers = inputTractogram->GetNumFibers(); double nc = (double)noConnection/numFibers; double vc = (double)validConnections/numFibers; double ic = (double)invalidConnections/numFibers; if (numFibers==0) { nc = 0.0; vc = 0.0; ic = 0.0; } int vb = validBundles; int ib = invalidBundles; double abc = (double)coveredVoxels/wmVoxels; std::cout << "NC: " << nc; std::cout << "VC: " << vc; std::cout << "IC: " << ic; std::cout << "VB: " << vb; std::cout << "IB: " << ib; std::cout << "ABC: " << abc; string logFile = outRoot; logFile.append("_TRACTOMETER.csv"); ofstream file; file.open (logFile.c_str()); { string sens = itksys::SystemTools::GetFilenameWithoutLastExtension(fibFile); if (!fileID.empty()) sens = fileID; sens.append(","); sens.append(boost::lexical_cast(nc)); sens.append(","); sens.append(boost::lexical_cast(vc)); sens.append(","); sens.append(boost::lexical_cast(ic)); sens.append(","); sens.append(boost::lexical_cast(validBundles)); sens.append(","); sens.append(boost::lexical_cast(invalidBundles)); sens.append(","); sens.append(boost::lexical_cast(abc)); sens.append(";\n"); file << sens; } file.close(); } catch (itk::ExceptionObject e) { std::cout << e; return EXIT_FAILURE; } catch (std::exception e) { std::cout << e.what(); return EXIT_FAILURE; } catch (...) { std::cout << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/Quantification/Testing/mitkTractAnalyzerTest.cpp b/Modules/DiffusionImaging/Quantification/Testing/mitkTractAnalyzerTest.cpp index e2b9600047..5fa9f05f74 100644 --- a/Modules/DiffusionImaging/Quantification/Testing/mitkTractAnalyzerTest.cpp +++ b/Modules/DiffusionImaging/Quantification/Testing/mitkTractAnalyzerTest.cpp @@ -1,92 +1,82 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include -#include #include +#include /**Documentation * test for the class "mitkTractAnalyzer". */ int mitkTractAnalyzerTest(int argc , char* argv[]) { MITK_TEST_BEGIN("TractAnalyzer"); // Load image typedef itk::Image FloatImageType; typedef itk::ImageFileReader ImageReaderType; ImageReaderType::Pointer reader = ImageReaderType::New(); reader->SetFileName(argv[1]); reader->Update(); FloatImageType::Pointer itkImage = reader->GetOutput(); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitk::CastToMitkImage(itkImage, mitkImage); - // load point set - - mitk::PointSetReader::Pointer pointSetReader = mitk::PointSetReader::New(); - pointSetReader->SetFileName(argv[2]); - pointSetReader->Update(); - - mitk::PointSet::Pointer pointSet = pointSetReader->GetOutput(); - - + mitk::PointSet::Pointer pointSet = mitk::IOUtil::LoadPointSet(argv[2]); mitk::TractAnalyzer analyzer; analyzer.SetInputImage(mitkImage); analyzer.SetThreshold(0.2); analyzer.SetPointSet(pointSet); analyzer.MakeRoi(); mitk::TbssRoiImage::Pointer tbssRoi = analyzer.GetRoiImage(); - - std::vector< itk::Index<3> > roi = tbssRoi->GetRoi(); // Output roi for debug purposes std::cout << "ROI\n"; for(unsigned int t=0; t ix = roi.at(t); std::cout << ix[0] << ", " << ix[1] << ", " << ix[2] << "\n"; } std::cout << std::endl; // check the cost of the roi double cost = analyzer.GetCostSum(); std::cout << "Cost: " << cost << std::endl; bool equal = mitk::Equal(cost, 5162.854, 0.001); MITK_TEST_CONDITION(equal, "Checking cost of found ROI"); MITK_TEST_END(); } diff --git a/Modules/IGT/Algorithms/mitkIGTLMessageToNavigationDataFilter.cpp b/Modules/IGT/Algorithms/mitkIGTLMessageToNavigationDataFilter.cpp new file mode 100644 index 0000000000..889f56ccdb --- /dev/null +++ b/Modules/IGT/Algorithms/mitkIGTLMessageToNavigationDataFilter.cpp @@ -0,0 +1,455 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkIGTLMessageToNavigationDataFilter.h" +#include "igtlTrackingDataMessage.h" +#include "igtlQuaternionTrackingDataMessage.h" +#include "igtlTransformMessage.h" +#include "mitkQuaternion.h" +#include + + +mitk::IGTLMessageToNavigationDataFilter::IGTLMessageToNavigationDataFilter() +: mitk::NavigationDataSource() +{ + mitk::NavigationData::Pointer output = mitk::NavigationData::New(); + this->SetNumberOfRequiredOutputs(1); + this->SetNthOutput(0, output.GetPointer()); +} + + +mitk::IGTLMessageToNavigationDataFilter::~IGTLMessageToNavigationDataFilter() +{ +} + + +void mitk::IGTLMessageToNavigationDataFilter::SetInput( const IGTLMessage* msg ) +{ + this->SetInput(0, msg); +} + + +void mitk::IGTLMessageToNavigationDataFilter::SetInput( unsigned int idx, const IGTLMessage* msg ) +{ + if ( msg == NULL ) // if an input is set to NULL, remove it + { + this->RemoveInput(idx); + } + else + { + // ProcessObject is not const-correct so a const_cast is required here + this->ProcessObject::SetNthInput(idx, const_cast(msg)); + } + this->CreateOutputsForAllInputs(); +} + + +const mitk::IGTLMessage* +mitk::IGTLMessageToNavigationDataFilter::GetInput( void ) const +{ + if (this->GetNumberOfInputs() < 1) + return NULL; + + return static_cast(this->ProcessObject::GetInput(0)); +} + + +const mitk::IGTLMessage* +mitk::IGTLMessageToNavigationDataFilter::GetInput( unsigned int idx ) const +{ + if (this->GetNumberOfInputs() < 1) + return NULL; + + return static_cast(this->ProcessObject::GetInput(idx)); +} + + +const mitk::IGTLMessage* +mitk::IGTLMessageToNavigationDataFilter::GetInput(std::string messageName) const +{ + const DataObjectPointerArray& inputs = const_cast(this)->GetInputs(); + for (DataObjectPointerArray::const_iterator it = inputs.begin(); + it != inputs.end(); ++it) + { + if (std::string(messageName) == + (static_cast(it->GetPointer()))->GetName()) + { + return static_cast(it->GetPointer()); + } + } + return NULL; +} + + +itk::ProcessObject::DataObjectPointerArraySizeType +mitk::IGTLMessageToNavigationDataFilter::GetInputIndex( std::string messageName ) +{ + DataObjectPointerArray outputs = this->GetInputs(); + for (DataObjectPointerArray::size_type i = 0; i < outputs.size(); ++i) + { + if (messageName == + (static_cast(outputs.at(i).GetPointer()))->GetName()) + { + return i; + } + } + throw std::invalid_argument("output name does not exist"); +} + +void mitk::IGTLMessageToNavigationDataFilter::ConnectTo( + mitk::IGTLMessageSource* UpstreamFilter) +{ + for (DataObjectPointerArraySizeType i = 0; + i < UpstreamFilter->GetNumberOfOutputs(); i++) + { + this->SetInput(i, UpstreamFilter->GetOutput(i)); + } +} + +void mitk::IGTLMessageToNavigationDataFilter::SetNumberOfExpectedOutputs( + unsigned int numOutputs) +{ + this->SetNumberOfIndexedOutputs(numOutputs); + this->CreateOutputsForAllInputs(); +} + + +void mitk::IGTLMessageToNavigationDataFilter::CreateOutputsForAllInputs() +{ + // create outputs for all inputs +// this->SetNumberOfIndexedOutputs(this->GetNumberOfIndexedInputs()); + bool isModified = false; + for (unsigned int idx = 0; idx < this->GetNumberOfIndexedOutputs(); ++idx) + { + if (this->GetOutput(idx) == NULL) + { + mitk::NavigationData::Pointer newOutput = mitk::NavigationData::New(); + this->SetNthOutput(idx, newOutput); + isModified = true; + } + } + + if(isModified) + this->Modified(); +} + +void mitk::IGTLMessageToNavigationDataFilter::GenerateTransformData() +{ + const mitk::IGTLMessage* input = this->GetInput(0); + assert(input); + + //cast the input message into the proper type + igtl::TransformMessage* tMsg = + (igtl::TransformMessage*)(input->GetMessage().GetPointer()); + + //check if cast was successful + if ( !tMsg ) + { + mitkThrow() << "Cast from igtl::MessageBase to igtl::TransformMessage " + << "failed! Please check the message."; + } + + /* update outputs with tracking data from tools */ + for (unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i) + { + mitk::NavigationData* output = this->GetOutput(i); + assert(output); + + if (input->IsDataValid() == false) + { + output->SetDataValid(false); + continue; + } + + //debug output + tMsg->Print(std::cout); + + //get the transformation matrix and convert it into an affinetransformation + igtl::Matrix4x4 transformation_; + tMsg->GetMatrix(transformation_); + mitk::AffineTransform3D::Pointer affineTransformation = + mitk::AffineTransform3D::New(); + mitk::Matrix3D transformation; + mitk::Vector3D offset; + for ( unsigned int r = 0; r < 3; r++ ) + { + for ( unsigned int c = 0; c < 3; c++ ) + { + transformation.GetVnlMatrix().set( r , c , transformation_[r][c] ); + } + offset.SetElement(r, transformation_[r][3]); + } + //convert the igtl matrix here and set it in the affine transformation + affineTransformation->SetMatrix(transformation); + affineTransformation->SetOffset(offset); + + //create a new navigation data here, there is a neat constructor for + //affine transformations that sets the orientation, position according to + //the affine transformation. The other values are initialized with standard + //values + mitk::NavigationData::Pointer nd = + mitk::NavigationData::New(affineTransformation, true); + //set the time stamp + nd->SetIGTTimeStamp(input->GetTimeStamp()); + //set the name +// nd->SetName(td->GetName()); + + output->Graft(nd); + + nd->Print(std::cout); + } +} + +void mitk::IGTLMessageToNavigationDataFilter::GenerateTrackingDataData() +{ + const mitk::IGTLMessage* input = this->GetInput(0); + assert(input); + + //cast the input message into the proper type + igtl::TrackingDataMessage* tdMsg = + (igtl::TrackingDataMessage*)(input->GetMessage().GetPointer()); + + //check if cast was successful + if ( !tdMsg ) + { + mitkThrow() << "Cast from igtl::MessageBase to igtl::TrackingDataMessage " + << "failed! Please check the message."; + } + + //get the number of tracking data elements + unsigned int numTrackingDataElements = + tdMsg->GetNumberOfTrackingDataElements(); + + if ( !numTrackingDataElements ) + { + MITK_ERROR("IGTLMsgToNavDataFilter") << "There are no tracking data " + "elements in this message"; + } + + /* update outputs with tracking data from tools */ + for (unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i) + { + mitk::NavigationData* output = this->GetOutput(i); + assert(output); + + //invalidate the output + output->SetDataValid(false); + + //check if the current index, all outputs that have no corresponding input + //tracking element stay invalidated, the others are validated according to + //the tracking element + if ( input->IsDataValid() == false || i >= numTrackingDataElements ) + { + continue; + } + output->SetDataValid(true); + + //get the tracking data element which holds all the data + igtl::TrackingDataElement::Pointer td; + tdMsg->GetTrackingDataElement(i, td); + + //get the transformation matrix and convert it into an affinetransformation + igtl::Matrix4x4 transformation_; + td->GetMatrix(transformation_); + mitk::AffineTransform3D::Pointer affineTransformation = + mitk::AffineTransform3D::New(); + mitk::Matrix3D transformation; + mitk::Vector3D offset; + for ( unsigned int r = 0; r < 3; r++ ) + { + for ( unsigned int c = 0; c < 3; c++ ) + { + transformation.GetVnlMatrix().set( r , c , transformation_[r][c] ); + } + offset.SetElement(r, transformation_[r][3]); + } + //convert the igtl matrix here and set it in the affine transformation + affineTransformation->SetMatrix(transformation); + affineTransformation->SetOffset(offset); + + mitk::NavigationData::Pointer nd; + + //check the rotation matrix + vnl_matrix_fixed rotationMatrix = + affineTransformation->GetMatrix().GetVnlMatrix(); + vnl_matrix_fixed rotationMatrixTransposed = + rotationMatrix.transpose(); + // a quadratic matrix is a rotation matrix exactly when determinant is 1 + // and transposed is inverse + if (!Equal(1.0, vnl_det(rotationMatrix), 0.1) + || !((rotationMatrix*rotationMatrixTransposed).is_identity(0.1))) + { + MITK_ERROR("IGTLMsgToNavDataFilter") << "tried to initialize NavData " + << "with non-rotation matrix :" << rotationMatrix << " (Does your " + "AffineTransform3D object include spacing? This is not " + "supported by NavigationData objects!)"; + nd = mitk::NavigationData::New(); + } + else + { + //create a new navigation data here, there is a neat constructor for + //affine transformations that sets the orientation, position according to + //the affine transformation. The other values are initialized with standard + //values + nd = mitk::NavigationData::New(affineTransformation, true); + } + //set the time stamp + nd->SetIGTTimeStamp(input->GetTimeStamp()); + //set the name + nd->SetName(td->GetName()); + output->Graft(nd); + } +} + +void +mitk::IGTLMessageToNavigationDataFilter::GenerateQuaternionTrackingDataData() +{ + const mitk::IGTLMessage* input = this->GetInput(0); + assert(input); + + //cast the input message into the proper type + igtl::QuaternionTrackingDataMessage* tdMsg = + (igtl::QuaternionTrackingDataMessage*)(input->GetMessage().GetPointer()); + + //check if cast was successful + if ( !tdMsg ) + { + mitkThrow() << "Cast from igtl::MessageBase to igtl::TrackingDataMessage " + << "failed! Please check the message."; + } + + //get the number of tracking data elements + unsigned int numTrackingDataElements = + tdMsg->GetNumberOfQuaternionTrackingDataElements(); + + if ( !numTrackingDataElements ) + { + MITK_ERROR("IGTLMsgToNavDataFilter") << "There are no tracking data " + "elements in this message"; + } + + /* update outputs with tracking data from tools */ + for (unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i) + { + mitk::NavigationData* output = this->GetOutput(i); + assert(output); + + //invalidate the output + output->SetDataValid(false); + + //check if the current index, all outputs that have no corresponding input + //tracking element stay invalidated, the others are validated according to + //the tracking element + if ( input->IsDataValid() == false || i >= numTrackingDataElements ) + { + continue; + } + output->SetDataValid(true); + + + //get the tracking data element which holds all the data + igtl::QuaternionTrackingDataElement::Pointer td; + tdMsg->GetQuaternionTrackingDataElement(i, td); + + //get the quaternion and set it + float quaternion_[4]; //igtl quat type + td->GetQuaternion(quaternion_); + mitk::Quaternion quaternion; + quaternion.put(0, quaternion_[0]); + quaternion.put(1, quaternion_[1]); + quaternion.put(2, quaternion_[2]); + quaternion.put(3, quaternion_[3]); + output->SetOrientation(quaternion); + output->SetHasOrientation(true); + + //get the position and set it + float position_[3]; //igtl position type + td->GetPosition(position_); + mitk::NavigationData::PositionType position; //mitk position type + position.SetElement(0, position_[0]); + position.SetElement(1, position_[1]); + position.SetElement(2, position_[2]); + output->SetPosition(position); + output->SetHasPosition(true); + //set the time stamp + output->SetIGTTimeStamp(input->GetTimeStamp()); + //set the name + output->SetName(td->GetName()); + + //there is no explicit covarience matrix + output->SetCovErrorMatrix(mitk::NavigationData::CovarianceMatrixType()); + } +} + +void mitk::IGTLMessageToNavigationDataFilter::GenerateData() +{ + //get the IGTLMessage from the previous filter + const mitk::IGTLMessage* input = this->GetInput(0); + assert(input); + + //check if the message is valid, if it is not valid we do not generate new + //outputs + if ( !input->IsDataValid() ) + { + MITK_DEBUG("IGTLMessageToNavigationDataFilter") << "Input data is invalid."; + return; + } + + //get the message type + const char* msgType = input->GetIGTLMessageType(); + + //check if the IGTL message has the proper type + if( strcmp(msgType, "TRANSFORM") == 0 ) + { + this->GenerateTransformData(); + } + else if( strcmp(msgType, "TDATA") == 0 ) + { + this->GenerateTrackingDataData(); + } + else if( strcmp(msgType, "QTDATA") == 0 ) + { + this->GenerateQuaternionTrackingDataData(); + } + else + { + //the message has another type + //ignore + MITK_INFO("IGTLMessageToNavigationDataFilter") << "The input has a unknown " + << "message type: " + << msgType; + } +} + + +void mitk::IGTLMessageToNavigationDataFilter::GenerateOutputInformation() +{ +// Superclass::GenerateOutputInformation(); + +// mitk::NavigationData* output = this->GetOutput(0); +// assert(output); +// const mitk::IGTLMessage* input = this->GetInput(0); +// assert(input); + + itkDebugMacro(<<"GenerateOutputInformation()"); + +// output->Initialize(input->GetPixelType(), input->GetDimension(), input->GetDimensions()); + +// // initialize geometry +// output->SetPropertyList(input->GetPropertyList()->Clone()); +// mitk::TimeGeometry::Pointer clonGeometry = input->GetTimeGeometry()->Clone(); +// output->SetTimeGeometry(clonGeometry.GetPointer()); +} diff --git a/Modules/IGT/Algorithms/mitkIGTLMessageToNavigationDataFilter.h b/Modules/IGT/Algorithms/mitkIGTLMessageToNavigationDataFilter.h new file mode 100644 index 0000000000..c2fd45f69b --- /dev/null +++ b/Modules/IGT/Algorithms/mitkIGTLMessageToNavigationDataFilter.h @@ -0,0 +1,142 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKOPENIGTLINKMESSAGETONAVIGATIONDATAFILTER_H_HEADER_INCLUDED_ +#define MITKOPENIGTLINKMESSAGETONAVIGATIONDATAFILTER_H_HEADER_INCLUDED_ + +#include +#include "mitkIGTLMessage.h" +#include "mitkIGTLMessageSource.h" +#include "MitkIGTExports.h" + +namespace mitk +{ + + /**Documentation + * \brief IGTLinkMessageToNavigationDataFilter is a filter that receives + * OpenIGTLink messages as input and produce NavigationDatas as output + * + * IGTLinkMessageToNavigationDataFilter is a filter that receives + * OpenIGTLink messages as input and produce NavigationDatas as output. + * If the OpenIGTLink message is not of the proper type the filter will not + * do anything. + * + * \ingroup IGT + */ + class MITKIGT_EXPORT + IGTLMessageToNavigationDataFilter : public NavigationDataSource + { + public: + mitkClassMacro(IGTLMessageToNavigationDataFilter, NavigationDataSource); + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + using Superclass::SetInput; + + /** + * \brief Set the input of this filter + * + * \warning: this will set the number of outputs to the number of inputs, + * deleting any extra outputs that might have been initialized. + * Subclasses that have a different number of outputs than inputs + * must overwrite the SetInput methods. + */ + virtual void SetInput( const IGTLMessage* msg); + + /** + * \brief Set input with id idx of this filter + * + * \warning: this will set the number of outputs to the number of inputs, + * deleting any extra outputs that might have been initialized. + * Subclasses that have a different number of outputs than inputs + * must overwrite the SetInput methods. + * If the last input is set to NULL, the number of inputs will be decreased by + * one (-> removing the last input). If other inputs are set to NULL, the + * number of inputs will not change. + */ + virtual void SetInput( unsigned int idx, const IGTLMessage* msg); + + /** Set an input */ +// virtual void SetInput(const DataObjectIdentifierType & key, DataObject *input); + + /** + * \brief Get the input of this filter + */ + const IGTLMessage* GetInput(void) const; + + /** + * \brief Get the input with id idx of this filter + */ + const IGTLMessage* GetInput(unsigned int idx) const; + + /** + * \brief Get the input with name messageName of this filter + */ + const IGTLMessage* GetInput(std::string messageName) const; + + /** + *\brief return the index of the input with name messageName, + * throw std::invalid_argument exception if that name was not found + * + */ + DataObjectPointerArraySizeType GetInputIndex(std::string messageName); + + /** + *\brief Connects the input of this filter to the outputs of the given + * IGTLMessageSource + * + * This method does not support smartpointer. use FilterX.GetPointer() to + * retrieve a dumbpointer. + */ + virtual void ConnectTo(mitk::IGTLMessageSource * UpstreamFilter); + + /** + *\brief Sets the number of expected outputs. + * + * Normally, this is done automatically by the filter concept. However, in our + * case we can not know, for example, how many tracking elements are stored + * in the incoming igtl message. Therefore, we have to set the number here to + * the expected value. + */ + void SetNumberOfExpectedOutputs(unsigned int numOutputs); + + protected: + IGTLMessageToNavigationDataFilter(); + virtual ~IGTLMessageToNavigationDataFilter(); + + virtual void GenerateData(); + void GenerateTransformData(); + void GenerateTrackingDataData(); + void GenerateQuaternionTrackingDataData(); + + /** + * \brief Create an output for each input + * + * This Method sets the number of outputs to the number of inputs + * and creates missing outputs objects. + * \warning any additional outputs that exist before the method is called are + * deleted + */ + void CreateOutputsForAllInputs(); + + /** + * \brief Defines how the input will be copied into the output + */ + virtual void GenerateOutputInformation(); + }; +} // namespace mitk +#endif /* MITKOPENIGTLMESSAGETONAVIGATIONDATAFILTER_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/Algorithms/mitkNavigationDataToIGTLMessageFilter.cpp b/Modules/IGT/Algorithms/mitkNavigationDataToIGTLMessageFilter.cpp new file mode 100644 index 0000000000..345fd6ddfe --- /dev/null +++ b/Modules/IGT/Algorithms/mitkNavigationDataToIGTLMessageFilter.cpp @@ -0,0 +1,344 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkNavigationDataToIGTLMessageFilter.h" + +#include "igtlQuaternionTrackingDataMessage.h" +#include "igtlTrackingDataMessage.h" +#include "igtlTransformMessage.h" +#include "igtlPositionMessage.h" + +#include +#include + +mitk::NavigationDataToIGTLMessageFilter::NavigationDataToIGTLMessageFilter() +{ + mitk::IGTLMessage::Pointer output = mitk::IGTLMessage::New(); + this->SetNumberOfRequiredOutputs(1); + this->SetNthOutput(0, output.GetPointer()); + + this->SetNumberOfRequiredInputs(1); + +// m_OperationMode = Mode3D; + m_CurrentTimeStep = 0; +// m_RingBufferSize = 50; //the default ring buffer size +// m_NumberForMean = 100; +} + +mitk::NavigationDataToIGTLMessageFilter::~NavigationDataToIGTLMessageFilter() +{ +} + +void mitk::NavigationDataToIGTLMessageFilter::GenerateData() +{ + switch (m_OperationMode) + { + case ModeSendQTDataMsg: + this->GenerateDataModeSendQTDataMsg(); + break; + case ModeSendTDataMsg: + this->GenerateDataModeSendTDataMsg(); + break; + case ModeSendQTransMsg: + this->GenerateDataModeSendQTransMsg(); + break; + case ModeSendTransMsg: + this->GenerateDataModeSendTransMsg(); + break; + default: + break; + } +} + + +void mitk::NavigationDataToIGTLMessageFilter::SetInput(const NavigationData* nd) +{ + // Process object is not const-correct so the const_cast is required here + this->ProcessObject::SetNthInput(0, const_cast(nd)); + this->CreateOutputsForAllInputs(); +} + + +void mitk::NavigationDataToIGTLMessageFilter::SetInput(unsigned int idx, const NavigationData* nd) +{ + // Process object is not const-correct so the const_cast is required here + this->ProcessObject::SetNthInput(idx, const_cast(nd)); + this->CreateOutputsForAllInputs(); +} + + +const mitk::NavigationData* mitk::NavigationDataToIGTLMessageFilter::GetInput( void ) +{ + if (this->GetNumberOfInputs() < 1) + return NULL; + return static_cast(this->ProcessObject::GetInput(0)); +} + + +const mitk::NavigationData* mitk::NavigationDataToIGTLMessageFilter::GetInput( unsigned int idx ) +{ + if (this->GetNumberOfInputs() < 1) + return NULL; + return static_cast(this->ProcessObject::GetInput(idx)); +} + + +void mitk::NavigationDataToIGTLMessageFilter::CreateOutputsForAllInputs() +{ + switch (m_OperationMode) + { + case ModeSendQTDataMsg: + // create one message output for all navigation data inputs + this->SetNumberOfIndexedOutputs(this->GetNumberOfIndexedInputs()); + // set the type for this filter + this->SetType("QTDATA"); + break; + case ModeSendTDataMsg: + // create one message output for all navigation data inputs + this->SetNumberOfIndexedOutputs(this->GetNumberOfIndexedInputs()); + // set the type for this filter + this->SetType("TDATA"); + break; + case ModeSendQTransMsg: + // create one message output for all navigation data input together + this->SetNumberOfIndexedOutputs(this->GetNumberOfIndexedInputs()); + // set the type for this filter + this->SetType("POSITION"); + break; + case ModeSendTransMsg: + // create one message output for all navigation data input together + this->SetNumberOfIndexedOutputs(this->GetNumberOfIndexedInputs()); + // set the type for this filter + this->SetType("TRANS"); + break; + default: + break; + } + + for (unsigned int idx = 0; idx < this->GetNumberOfIndexedOutputs(); ++idx) + { + if (this->GetOutput(idx) == NULL) + { + DataObjectPointer newOutput = this->MakeOutput(idx); + this->SetNthOutput(idx, newOutput); + } + this->Modified(); + } +} + + +void ConvertAffineTransformationIntoIGTLMatrix(mitk::AffineTransform3D* trans, + igtl::Matrix4x4 igtlTransform) +{ + const mitk::AffineTransform3D::MatrixType& matrix = trans->GetMatrix(); + mitk::Vector3D position = trans->GetOffset(); + //copy the data into a matrix type that igtl understands + for ( unsigned int r = 0; r < 3; r++ ) + { + for ( unsigned int c = 0; c < 3; c++ ) + { + igtlTransform[r][c] = matrix(r,c); + } + igtlTransform[r][3] = position[r]; + } + for ( unsigned int c = 0; c < 3; c++ ) + { + igtlTransform[3][c] = 0.0; + } + igtlTransform[3][3] = 1.0; +} + +void mitk::NavigationDataToIGTLMessageFilter::GenerateDataModeSendQTransMsg() +{ + // for each output message + for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs() ; ++i) + { + mitk::IGTLMessage* output = this->GetOutput(i); + assert(output); + const mitk::NavigationData* input = this->GetInput(i); + assert(input); + // do not add navigation data to message if input is invalid + if (input->IsDataValid() == false) + continue; + + //get the navigation data components + mitk::NavigationData::PositionType pos = input->GetPosition(); + mitk::NavigationData::OrientationType ori = input->GetOrientation(); + + //insert this information into the message + igtl::PositionMessage::Pointer posMsg = igtl::PositionMessage::New(); + posMsg->SetPosition(pos[0], pos[1], pos[2]); + posMsg->SetQuaternion(ori[0], ori[1], ori[2], ori[3]); + posMsg->SetTimeStamp((unsigned int)input->GetIGTTimeStamp(), 0); + posMsg->SetDeviceName(input->GetName()); + posMsg->Pack(); + + //add the igtl message to the mitk::IGTLMessage + output->SetMessage(posMsg.GetPointer()); + } +} + +void mitk::NavigationDataToIGTLMessageFilter::GenerateDataModeSendTransMsg() +{ + // for each output message + for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs() ; ++i) + { + mitk::IGTLMessage* output = this->GetOutput(i); + assert(output); + const mitk::NavigationData* input = this->GetInput(i); + assert(input); + // do not add navigation data to message if input is invalid + if (input->IsDataValid() == false) + continue; + + //get the navigation data components + mitk::AffineTransform3D::Pointer transform = input->GetAffineTransform3D(); + mitk::NavigationData::PositionType position = transform->GetOffset(); + + //convert the transform into a igtl type + igtl::Matrix4x4 igtlTransform; + ConvertAffineTransformationIntoIGTLMatrix(transform, igtlTransform); + + //insert this information into the message + igtl::TransformMessage::Pointer transMsg = igtl::TransformMessage::New(); + transMsg->SetMatrix(igtlTransform); + transMsg->SetPosition(position[0], position[1], position[2]); + transMsg->SetTimeStamp((unsigned int)input->GetIGTTimeStamp(), 0); + transMsg->SetDeviceName(input->GetName()); + transMsg->Pack(); + + //add the igtl message to the mitk::IGTLMessage + output->SetMessage(transMsg.GetPointer()); + } +} + +void mitk::NavigationDataToIGTLMessageFilter::GenerateDataModeSendQTDataMsg() +{ + mitk::IGTLMessage* output = this->GetOutput(); + assert(output); + + //create a output igtl message + igtl::QuaternionTrackingDataMessage::Pointer qtdMsg = + igtl::QuaternionTrackingDataMessage::New(); + + mitk::NavigationData::PositionType pos; + mitk::NavigationData::OrientationType ori; + + for (unsigned int index = 0; index < this->GetNumberOfIndexedInputs(); index++) + { + const mitk::NavigationData* nd = GetInput(index); + assert(nd); + + //get the navigation data components + pos = nd->GetPosition(); + ori = nd->GetOrientation(); + + //insert the information into the tracking element + igtl::QuaternionTrackingDataElement::Pointer tde = + igtl::QuaternionTrackingDataElement::New(); + tde->SetPosition(pos[0], pos[1], pos[2]); + tde->SetQuaternion(ori[0], ori[1], ori[2], ori[3]); + tde->SetName(nd->GetName()); + + //insert this element into the tracking data message + qtdMsg->AddQuaternionTrackingDataElement(tde); + + //copy the time stamp + //todo find a better way to do that + qtdMsg->SetTimeStamp((unsigned int)nd->GetIGTTimeStamp(), 0); + } + qtdMsg->Pack(); + + //add the igtl message to the mitk::IGTLMessage + output->SetMessage(qtdMsg.GetPointer()); +} + +void mitk::NavigationDataToIGTLMessageFilter::GenerateDataModeSendTDataMsg() +{ + bool isValidData = true; + mitk::IGTLMessage* output = this->GetOutput(); + assert(output); + + //create a output igtl message + igtl::TrackingDataMessage::Pointer tdMsg = igtl::TrackingDataMessage::New(); + + mitk::AffineTransform3D::Pointer transform; + Vector3D position; + igtl::Matrix4x4 igtlTransform; + vnl_matrix_fixed rotationMatrix; + vnl_matrix_fixed rotationMatrixTransposed; + + for (unsigned int index = 0; index < this->GetNumberOfIndexedInputs(); index++) + { + const mitk::NavigationData* nd = GetInput(index); + assert(nd); + + //create a new tracking element + igtl::TrackingDataElement::Pointer tde = igtl::TrackingDataElement::New(); + + //get the navigation data components + transform = nd->GetAffineTransform3D(); + position = transform->GetOffset(); + + //check the rotation matrix + rotationMatrix = transform->GetMatrix().GetVnlMatrix(); + rotationMatrixTransposed = rotationMatrix.transpose(); + // a quadratic matrix is a rotation matrix exactly when determinant is 1 + // and transposed is inverse + if (!Equal(1.0, vnl_det(rotationMatrix), 0.1) + || !((rotationMatrix*rotationMatrixTransposed).is_identity(0.1))) + { + //the rotation matrix is not valid! => invalidate the current element + isValidData = false; + } + + //convert the transform into a igtl type + ConvertAffineTransformationIntoIGTLMatrix(transform, igtlTransform); + + //fill the tracking element with life + tde->SetMatrix(igtlTransform); + tde->SetPosition(position[0], position[1], position[2]); + tde->SetName(nd->GetName()); + + //insert this element into the tracking data message + tdMsg->AddTrackingDataElement(tde); + + //copy the time stamp + //todo find a better way to do that + tdMsg->SetTimeStamp((unsigned int)nd->GetIGTTimeStamp(), 0); + } + tdMsg->Pack(); + //add the igtl message to the mitk::IGTLMessage + output->SetMessage(tdMsg.GetPointer()); + output->SetDataValid(isValidData); +} + +void mitk::NavigationDataToIGTLMessageFilter::SetOperationMode( OperationMode mode ) +{ + m_OperationMode = mode; + this->Modified(); + this->CreateOutputsForAllInputs(); +} + +void mitk::NavigationDataToIGTLMessageFilter::ConnectTo( + mitk::NavigationDataSource* UpstreamFilter) +{ + for (DataObjectPointerArraySizeType i = 0; + i < UpstreamFilter->GetNumberOfOutputs(); i++) + { + this->SetInput(i, UpstreamFilter->GetOutput(i)); + } +} diff --git a/Modules/IGT/Algorithms/mitkNavigationDataToIGTLMessageFilter.h b/Modules/IGT/Algorithms/mitkNavigationDataToIGTLMessageFilter.h new file mode 100644 index 0000000000..d2af03efb5 --- /dev/null +++ b/Modules/IGT/Algorithms/mitkNavigationDataToIGTLMessageFilter.h @@ -0,0 +1,169 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef _MITKNAVIGATIONDATATOIGTLMessageFILTER_H__ +#define _MITKNAVIGATIONDATATOIGTLMessageFILTER_H__ + +#include "mitkCommon.h" +#include "mitkPointSet.h" +#include "mitkIGTLMessageSource.h" +#include "mitkNavigationData.h" +#include "mitkNavigationDataSource.h" + +namespace mitk { + + /**Documentation + * + * \brief This filter creates IGTL messages from mitk::NavigaitionData objects + * + * + * \ingroup IGT + * + */ + class MITKIGT_EXPORT NavigationDataToIGTLMessageFilter : public IGTLMessageSource + { + public: + mitkClassMacro(NavigationDataToIGTLMessageFilter, IGTLMessageSource); + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + /**Documentation + * \brief There are four different operation modes. + * + * - ModeSendQTransMsg: every input NavigationData is processed into one + * output message that contains a position and a orientation (quaternion). + * - ModeSendTransMsg: every input NavigationData is processed into one + * output message that contains a 4x4 transformation. + * - ModeSendQTDataMsg:all input NavigationData is processed into one single + * output message that contains a position and orientation (quaternion) for + * each navigation data. + * - ModeSendTDataMsg:all input NavigationData is processed into one single + * output message that contains a 4x4 transformation for + * each navigation data. + */ + enum OperationMode + { + ModeSendQTransMsg, + ModeSendTransMsg, + ModeSendQTDataMsg, + ModeSendTDataMsg + }; + + /** + * \brief filter execute method + */ + virtual void GenerateData(); + + using Superclass::SetInput; + + /** + * \brief Sets one input NavigationData + */ + virtual void SetInput(const mitk::NavigationData *NavigationData); + + /** + * \brief Sets the input NavigationData at a specific index + */ + virtual void SetInput(unsigned int idx, const NavigationData* nd); + + /** + * \brief Returns the input of this filter + */ + const mitk::NavigationData* GetInput(); + + /** + * \brief Returns the input number idx of this filter + */ + const mitk::NavigationData* GetInput(unsigned int idx); + + /** + * \brief Sets the mode of this filter. + * + * See OperationMode for the behavior in the different modes + * \warn A call to this method will change the number of outputs of the filter. + * After calling this method, all previously acquired pointers to outputs are invalid + * Always set the operation mode first, then get the outputs with GetOutput() + */ + virtual void SetOperationMode(OperationMode mode); + + /** + * \brief returns the mode of this filter. + * + * See OperationMode for the behavior in the different modes + */ + itkGetConstMacro(OperationMode, OperationMode); + + /** + * empty implementation to prevent calling of the superclass method that + * would try to copy information from the input NavigationData to the output + * PointSet, which makes no sense! + */ + void GenerateOutputInformation() {}; + + /** + *\brief Connects the input of this filter to the outputs of the given + * NavigationDataSource + * + * This method does not support smartpointer. use FilterX.GetPointer() to + * retrieve a dumbpointer. + */ + virtual void ConnectTo(mitk::NavigationDataSource * UpstreamFilter); + + protected: + NavigationDataToIGTLMessageFilter(); + + virtual ~NavigationDataToIGTLMessageFilter(); + + /** + * \brief Generates the output + * + */ +// virtual void GenerateData(); + + /** + * \brief Generates the output for ModeSendQTDataMsg + * + */ + virtual void GenerateDataModeSendQTDataMsg(); + + /** + * \brief Generates the output for ModeSendTDataMsg + */ + virtual void GenerateDataModeSendTDataMsg(); + + /** + * \brief Generates the output for ModeSendQTransMsg + * + */ + virtual void GenerateDataModeSendQTransMsg(); + + /** + * \brief Generates the output for ModeSendTransMsg + */ + virtual void GenerateDataModeSendTransMsg(); + + /** + * \brief create output objects according to OperationMode for all inputs + */ + virtual void CreateOutputsForAllInputs(); + + OperationMode m_OperationMode; ///< Stores the mode. See enum OperationMode +// unsigned int m_RingBufferSize; ///< Stores the ringbuffer size + unsigned int m_CurrentTimeStep; ///< Indicates the current timestamp +// unsigned int m_NumberForMean; ///< Number of Navigation Data, which should be averaged + }; +} // namespace mitk +#endif // _MITKNAVIGATIONDATATOIGTLMessageFILTER_H__ diff --git a/Modules/IGT/CMakeLists.txt b/Modules/IGT/CMakeLists.txt index 4c9722c526..3b5d60f64d 100644 --- a/Modules/IGT/CMakeLists.txt +++ b/Modules/IGT/CMakeLists.txt @@ -1,57 +1,57 @@ include(MITKIGTHardware.cmake) if(MITK_USE_MICRON_TRACKER) set(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_MICRON_TRACKER_INCLUDE_DIR}) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_MICRON_TRACKER_LIB}) endif(MITK_USE_MICRON_TRACKER) if(MITK_USE_OPTITRACK_TRACKER) set(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_OPTITRACK_TRACKER_INCLUDE_DIR}) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_OPTITRACK_TRACKER_LIB}) add_definitions( -DMITK_USE_OPTITRACK_TRACKER ) endif(MITK_USE_OPTITRACK_TRACKER) if(MITK_USE_MICROBIRD_TRACKER) set(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_USE_MICROBIRD_TRACKER_INCLUDE_DIR}) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_USE_MICROBIRD_TRACKER_LIB}) endif(MITK_USE_MICROBIRD_TRACKER) MITK_CREATE_MODULE( SUBPROJECTS MITK-IGT INCLUDE_DIRS Algorithms Common DataManagement ExceptionHandling IO Rendering TrackingDevices TestingHelper INTERNAL_INCLUDE_DIRS ${INCLUDE_DIRS_INTERNAL} - DEPENDS MitkImageStatistics MitkSceneSerialization MitkIGTBase - PACKAGE_DEPENDS ITK|ITKRegistrationCommon tinyxml + DEPENDS MitkImageStatistics MitkSceneSerialization MitkIGTBase MitkOpenIGTLink + PACKAGE_DEPENDS ITK|ITKRegistrationCommon tinyxml OpenIGTLink ADDITIONAL_LIBS "${ADDITIONAL_LIBS}" #WARNINGS_AS_ERRORS disabled for release 2014-03 because of bug 17463 ) if(MitkIGT_IS_ENABLED) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/ClaronMicron.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/IntuitiveDaVinci.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAurora.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAurora_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAuroraCompactFG_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAuroraPlanarFG_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAuroraTabletopFG_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAuroraTabletopFG_Prototype_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIPolarisOldModel.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIPolarisSpectra.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIPolarisSpectraExtendedPyramid.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIPolarisVicra.stl ) endif() if(NOT MODULE_IS_ENABLED) message(STATUS "IGTTutorialStep1 won't be built. Missing: ${_RESULT}") else() ## create IGT config configure_file(mitkIGTConfig.h.in ${PROJECT_BINARY_DIR}/mitkIGTConfig.h @ONLY) # add test programm for serial communication classADD_EXECUTABLE(SerialCommunicationTest IGTTrackingDevices/mitkSerialCommunicationTest.cpp)target_link_libraries(SerialCommunicationTest mitkIGT Mitk tinyxml PocoXML) add_subdirectory(Tutorial) add_subdirectory(Testing) endif() diff --git a/Modules/IGT/Testing/files.cmake b/Modules/IGT/Testing/files.cmake index 8a89a47489..cc77978970 100644 --- a/Modules/IGT/Testing/files.cmake +++ b/Modules/IGT/Testing/files.cmake @@ -1,64 +1,65 @@ set(MODULE_TESTS # IMPORTANT: If you plan to deactivate / comment out a test please write a bug number to the commented out line of code. # # Example: #mitkMyTest #this test is commented out because of bug 12345 # # It is important that the bug is open and that the test will be activated again before the bug is closed. This assures that # no test is forgotten after it was commented out. If there is no bug for your current problem, please add a new one and # mark it as critical. ################## ON THE FENCE TESTS ################################################# # none ################## DISABLED TESTS ##################################################### # mitkNavigationToolStorageDeserializerTest.cpp # This test was disabled because of bug 17303. # mitkNavigationToolStorageSerializerAndDeserializerIntegrationTest.cpp # This test was disabled because of bug 17181. # mitkNavigationToolStorageSerializerTest.cpp # This test was disabled because of bug 18671 ################# RUNNING TESTS ####################################################### mitkCameraVisualizationTest.cpp mitkClaronInterfaceTest.cpp mitkClaronToolTest.cpp mitkClaronTrackingDeviceTest.cpp mitkInternalTrackingToolTest.cpp mitkNavigationDataDisplacementFilterTest.cpp mitkNavigationDataLandmarkTransformFilterTest.cpp mitkNavigationDataObjectVisualizationFilterTest.cpp mitkNavigationDataSetTest.cpp mitkNavigationDataTest.cpp mitkNavigationDataRecorderTest.cpp mitkNavigationDataReferenceTransformFilterTest.cpp mitkNavigationDataSequentialPlayerTest.cpp mitkNavigationDataSetReaderWriterXMLTest.cpp mitkNavigationDataSetReaderWriterCSVTest.cpp mitkNavigationDataSourceTest.cpp mitkNavigationDataToMessageFilterTest.cpp mitkNavigationDataToNavigationDataFilterTest.cpp mitkNavigationDataToPointSetFilterTest.cpp + mitkNavigationDataToIGTLMessageFilterTest.cpp mitkNavigationDataTransformFilterTest.cpp mitkNDIPassiveToolTest.cpp mitkNDIProtocolTest.cpp mitkNDITrackingDeviceTest.cpp mitkTimeStampTest.cpp mitkTrackingVolumeGeneratorTest.cpp mitkTrackingDeviceTest.cpp mitkTrackingToolTest.cpp mitkVirtualTrackingDeviceTest.cpp # mitkNavigationDataPlayerTest.cpp # random fails see bug 16485. # We decided to won't fix because of complete restructuring via bug 15959. mitkTrackingDeviceSourceTest.cpp mitkTrackingDeviceSourceConfiguratorTest.cpp mitkNavigationDataEvaluationFilterTest.cpp mitkTrackingTypesTest.cpp # ------------------ Navigation Tool Management Tests ------------------- mitkNavigationToolStorageTest.cpp mitkNavigationToolTest.cpp mitkNavigationToolReaderAndWriterTest.cpp # ----------------------------------------------------------------------- ) set(MODULE_CUSTOM_TESTS mitkNDIAuroraHardwareTest.cpp mitkNDIPolarisHardwareTest.cpp mitkClaronTrackingDeviceHardwareTest.cpp ) diff --git a/Modules/IGT/Testing/mitkNavigationDataToIGTLMessageFilterTest.cpp b/Modules/IGT/Testing/mitkNavigationDataToIGTLMessageFilterTest.cpp new file mode 100644 index 0000000000..cb37e65683 --- /dev/null +++ b/Modules/IGT/Testing/mitkNavigationDataToIGTLMessageFilterTest.cpp @@ -0,0 +1,261 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkNavigationDataToIGTLMessageFilter.h" +#include "mitkNavigationDataSequentialPlayer.h" +#include "mitkNavigationDataReaderXML.h" +#include +#include +#include +#include +#include +#include + +#include + +/** +* Simple test for the class "NavigationDataToIGTLMessageFilter". +* +* argc and argv are the command line parameters which were passed to +* the ADD_TEST command in the CMakeLists.txt file. For the automatic +* tests, argv is either empty for the simple tests or contains the filename +* of a test image for the image tests (see CMakeLists.txt). +*/ + +mitk::NavigationDataToIGTLMessageFilter::Pointer m_NavigationDataToIGTLMessageFilter; + +static void Setup() +{ + m_NavigationDataToIGTLMessageFilter = mitk::NavigationDataToIGTLMessageFilter::New(); +} + +static void SetInputs() +{ + //Build up test data + mitk::NavigationData::Pointer nd0 = mitk::NavigationData::New(); + mitk::NavigationData::Pointer nd1 = mitk::NavigationData::New(); + mitk::NavigationData::Pointer nd2 = mitk::NavigationData::New(); + mitk::NavigationData::Pointer nd3 = mitk::NavigationData::New(); + + mitk::NavigationData::PositionType point0; + point0[0] = 1.0; + point0[1] = 2.0; + point0[2] = 3.0; + mitk::NavigationData::OrientationType orientation0; + orientation0.put(0, 1.0); + orientation0.put(1, 0.0); + orientation0.put(2, 0.0); + orientation0.put(3, 0.0); + nd0->SetPosition(point0); + nd0->SetOrientation(orientation0); + nd0->SetDataValid(true); + + mitk::NavigationData::PositionType point1; + point1[0] = 4.0; + point1[1] = 5.0; + point1[2] = 6.0; + mitk::NavigationData::OrientationType orientation1; + orientation1.put(0, 21.0); + orientation1.put(1, 22.0); + orientation1.put(2, 23.0); + orientation1.put(3, 24.0); + nd1->SetPosition(point1); + nd1->SetOrientation(orientation1); + nd1->SetDataValid(true); + + mitk::NavigationData::PositionType point2; + point2[0] = 7.0; + point2[1] = 8.0; + point2[2] = 9.0; + mitk::NavigationData::OrientationType orientation2; + orientation2.put(0, 31.0); + orientation2.put(1, 32.0); + orientation2.put(2, 33.0); + orientation2.put(3, 34.0); + nd2->SetPosition(point2); + nd2->SetOrientation(orientation2); + nd2->SetDataValid(true); + + mitk::NavigationData::PositionType point3; + point3[0] = 10.0; + point3[1] = 11.0; + point3[2] = 12.0; + mitk::NavigationData::OrientationType orientation3; + orientation3.put(0, 0.0); + orientation3.put(1, 0.0); + orientation3.put(2, 0.0); + orientation3.put(3, 1.0); + nd3->SetPosition(point3); + nd3->SetOrientation(orientation3); + nd3->SetDataValid(true); + + m_NavigationDataToIGTLMessageFilter->SetInput(0, nd0); + m_NavigationDataToIGTLMessageFilter->SetInput(1, nd1); + m_NavigationDataToIGTLMessageFilter->SetInput(2, nd2); + m_NavigationDataToIGTLMessageFilter->SetInput(3, nd3); +} + +static void TestModeQTransMsg() +{ + Setup(); + SetInputs(); + m_NavigationDataToIGTLMessageFilter->SetOperationMode( + mitk::NavigationDataToIGTLMessageFilter::ModeSendQTransMsg); + + //Process + mitk::IGTLMessage::Pointer msg0 = m_NavigationDataToIGTLMessageFilter->GetOutput(); + mitk::IGTLMessage::Pointer msg1 = m_NavigationDataToIGTLMessageFilter->GetOutput(1); + mitk::IGTLMessage::Pointer msg2 = m_NavigationDataToIGTLMessageFilter->GetOutput(2); + mitk::IGTLMessage::Pointer msg3 = m_NavigationDataToIGTLMessageFilter->GetOutput(3); + + msg0->Update(); + + igtl::PositionMessage::Pointer igtlMsg0 = + dynamic_cast(msg0->GetMessage().GetPointer()); + igtl::PositionMessage::Pointer igtlMsg3 = + dynamic_cast(msg3->GetMessage().GetPointer()); + + MITK_TEST_OUTPUT(<< "Testing the converted OpenIGTLink messages:"); + MITK_TEST_CONDITION(igtlMsg0.IsNotNull(), "Message0 is not null?"); + MITK_TEST_CONDITION(igtlMsg3.IsNotNull(), "Message3 is not null?"); + + //Convert the data from the igtl message back to mitk types + float pos0_[3]; + float orientation0_[4]; + igtlMsg0->GetPosition(pos0_); + igtlMsg0->GetQuaternion(orientation0_); + mitk::NavigationData::PositionType pos0; + pos0[0] = pos0_[0]; + pos0[1] = pos0_[1]; + pos0[2] = pos0_[2]; + mitk::NavigationData::OrientationType orientation0; + orientation0[0] = orientation0_[0]; + orientation0[1] = orientation0_[1]; + orientation0[2] = orientation0_[2]; + orientation0[3] = orientation0_[3]; + float pos3_[3]; + float orientation3_[4]; + igtlMsg3->GetPosition(pos3_); + igtlMsg3->GetQuaternion(orientation3_); + mitk::NavigationData::PositionType pos3; + pos3[0] = pos3_[0]; + pos3[1] = pos3_[1]; + pos3[2] = pos3_[2]; + mitk::NavigationData::OrientationType orientation3; + orientation3[0] = orientation3_[0]; + orientation3[1] = orientation3_[1]; + orientation3[2] = orientation3_[2]; + orientation3[3] = orientation3_[3]; + + MITK_TEST_OUTPUT(<< "Testing the conversion of navigation data object to QTrans OpenIGTLink messages:"); + MITK_TEST_CONDITION(mitk::Equal(pos0, m_NavigationDataToIGTLMessageFilter->GetInput(0)->GetPosition()), "Position0 correct?"); + MITK_TEST_CONDITION(mitk::Equal(pos3, m_NavigationDataToIGTLMessageFilter->GetInput(3)->GetPosition()), "Position3 correct?"); + MITK_TEST_CONDITION(mitk::Equal(orientation0, m_NavigationDataToIGTLMessageFilter->GetInput(0)->GetOrientation()), "Orientation0 correct?"); + MITK_TEST_CONDITION(mitk::Equal(orientation3, m_NavigationDataToIGTLMessageFilter->GetInput(3)->GetOrientation()), "Orientation3 correct?"); +} + +static void TestModeTransMsg() +{ + Setup(); + SetInputs(); + m_NavigationDataToIGTLMessageFilter->SetOperationMode( + mitk::NavigationDataToIGTLMessageFilter::ModeSendTransMsg); + + //Process + mitk::IGTLMessage::Pointer msg0 = m_NavigationDataToIGTLMessageFilter->GetOutput(); + mitk::IGTLMessage::Pointer msg1 = m_NavigationDataToIGTLMessageFilter->GetOutput(1); + mitk::IGTLMessage::Pointer msg2 = m_NavigationDataToIGTLMessageFilter->GetOutput(2); + mitk::IGTLMessage::Pointer msg3 = m_NavigationDataToIGTLMessageFilter->GetOutput(3); + + msg0->Update(); + + igtl::TransformMessage::Pointer igtlMsg0 = + dynamic_cast(msg0->GetMessage().GetPointer()); + igtl::TransformMessage::Pointer igtlMsg3 = + dynamic_cast(msg3->GetMessage().GetPointer()); + + MITK_TEST_OUTPUT(<< "Testing the converted OpenIGTLink messages:"); + MITK_TEST_CONDITION(igtlMsg0.IsNotNull(), "Message0 is not null?"); + MITK_TEST_CONDITION(igtlMsg3.IsNotNull(), "Message3 is not null?"); + + //Convert the data from the igtl message back to mitk types + mitk::AffineTransform3D::Pointer affineTransformation0 = + mitk::AffineTransform3D::New(); + igtl::Matrix4x4 transformation0_; + mitk::Matrix3D transformation0; + mitk::Vector3D offset0; + igtlMsg0->GetMatrix(transformation0_); + for ( unsigned int r = 0; r < 3; r++ ) + { + for ( unsigned int c = 0; c < 3; c++ ) + { + transformation0.GetVnlMatrix().set( r , c , transformation0_[r][c] ); + } + offset0.SetElement(r, transformation0_[r][3]); + } + //convert the igtl matrix here and set it in the affine transformation + affineTransformation0->SetMatrix(transformation0); + affineTransformation0->SetOffset(offset0); + //the easiest way to convert the affine transform to position and quaternion + mitk::NavigationData::Pointer nd0 = + mitk::NavigationData::New(affineTransformation0, true); + + + mitk::AffineTransform3D::Pointer affineTransformation3 = + mitk::AffineTransform3D::New(); + igtl::Matrix4x4 transformation3_; + mitk::Matrix3D transformation3; + mitk::Vector3D offset3; + igtlMsg3->GetMatrix(transformation3_); + for ( unsigned int r = 0; r < 3; r++ ) + { + for ( unsigned int c = 0; c < 3; c++ ) + { + transformation3.GetVnlMatrix().set( r , c , transformation3_[r][c] ); + } + offset3.SetElement(r, transformation3_[r][3]); + } + //convert the igtl matrix here and set it in the affine transformation + affineTransformation3->SetMatrix(transformation3); + affineTransformation3->SetOffset(offset3); + //the easiest way to convert the affine transform to position and quaternion + mitk::NavigationData::Pointer nd3 = + mitk::NavigationData::New(affineTransformation3, true); + + MITK_TEST_OUTPUT(<< "Testing the conversion of navigation data object to Trans OpenIGTLink messages:"); + MITK_TEST_CONDITION(mitk::Equal(nd0->GetPosition(), m_NavigationDataToIGTLMessageFilter->GetInput(0)->GetPosition()), "Position0 correct?"); + MITK_TEST_CONDITION(mitk::Equal(nd3->GetPosition(), m_NavigationDataToIGTLMessageFilter->GetInput(3)->GetPosition()), "Position3 correct?"); + MITK_TEST_CONDITION(mitk::Equal(nd0->GetOrientation(), m_NavigationDataToIGTLMessageFilter->GetInput(0)->GetOrientation()), "Orientation0 correct?"); + MITK_TEST_CONDITION(mitk::Equal(nd3->GetOrientation(), m_NavigationDataToIGTLMessageFilter->GetInput(3)->GetOrientation()), "Orientation3 correct?"); +} + +static void NavigationDataToIGTLMessageFilterContructor_DefaultCall_IsNotEmpty() +{ + Setup(); + MITK_TEST_CONDITION_REQUIRED(m_NavigationDataToIGTLMessageFilter.IsNotNull(),"Testing instantiation"); + //I think this test is meaningless, because it will never ever fail. I keep it for know just to be save. +} + +int mitkNavigationDataToIGTLMessageFilterTest(int /* argc */, char* /*argv*/[]) +{ + MITK_TEST_BEGIN("NavigationDataToIGTLMessageFilter"); + + NavigationDataToIGTLMessageFilterContructor_DefaultCall_IsNotEmpty(); + TestModeQTransMsg(); + TestModeTransMsg(); + + MITK_TEST_END(); +} diff --git a/Modules/IGT/TrackingDevices/mitkTrackingVolumeGenerator.cpp b/Modules/IGT/TrackingDevices/mitkTrackingVolumeGenerator.cpp index 6be1ba4578..ae4ab0ee53 100644 --- a/Modules/IGT/TrackingDevices/mitkTrackingVolumeGenerator.cpp +++ b/Modules/IGT/TrackingDevices/mitkTrackingVolumeGenerator.cpp @@ -1,135 +1,116 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTrackingVolumeGenerator.h" -#include "mitkSTLFileReader.h" #include "mitkStandardFileLocations.h" #include "mitkConfig.h" #include #include #include #include #include #include +#include +#include #include #include #include #include #include #include mitk::TrackingVolumeGenerator::TrackingVolumeGenerator() { m_Data = mitk::DeviceDataUnspecified; } void mitk::TrackingVolumeGenerator::SetTrackingDevice (mitk::TrackingDevice::Pointer tracker) { this->m_Data = mitk::GetFirstCompatibleDeviceDataForLine(tracker->GetType()); } void mitk::TrackingVolumeGenerator::GenerateData() { mitk::Surface::Pointer output = this->GetOutput(); //the surface wich represents the tracking volume std::string filepath = ""; // Full path to file (wil be resolved later) std::string filename = this->m_Data.VolumeModelLocation; // Name of the file or possibly a magic String, e.g. "cube" MITK_INFO << "volume: " << filename; // See if filename matches a magic string. if (filename.compare("cube") == 0){ vtkSmartPointer cubeSource = vtkSmartPointer::New(); double bounds[6]; bounds[0] = bounds[2] = bounds[4] = -400.0; // initialize bounds to -400 ... +400 cube. This is the default value of the bounds[1] = bounds[3] = bounds[5] = 400.0; // virtual tracking device, but it can be changed. In that case, // the tracking volume polydata has to be updated manually cubeSource->SetBounds(bounds); cubeSource->Update(); output->SetVtkPolyData(cubeSource->GetOutput()); //set the vtkCubeSource as polyData of the surface return; } if (filename.compare("") == 0) // empty String means no model, return empty output { // initialize with empty poly data (otherwise old surfaces may be returned) => so an empty surface is returned vtkPolyData *emptyPolyData = vtkPolyData::New(); output->SetVtkPolyData(emptyPolyData); emptyPolyData->Delete(); return; } // from here on, we assume that filename contains an actual filename and not a magic string us::Module* module = us::GetModuleContext()->GetModule(); us::ModuleResource moduleResource = module->GetResource(filename); - // Create ResourceStream from Resource - us::ModuleResourceStream resStream(moduleResource,std::ios_base::binary); + std::vector data = mitk::IOUtil::Load(moduleResource); - ofstream tmpOutputStream; - std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpOutputStream); - tmpOutputStream << resStream.rdbuf(); - tmpOutputStream.close(); + if(data.empty()) + MITK_ERROR << "Exception while reading file:"; + mitk::Surface::Pointer fileoutput = dynamic_cast(data[0].GetPointer()); - //filepath = mitk::StandardFileLocations::GetInstance()->FindFile(filename.c_str()); + output->SetVtkPolyData(fileoutput->GetVtkPolyData()); - if (tmpFilePath.empty()) - { - MITK_ERROR << ("Volume Generator could not find the specified file " + filename); - return; - } - - mitk::STLFileReader::Pointer stlReader = mitk::STLFileReader::New(); - stlReader->SetFileName( tmpFilePath.c_str() ); - stlReader->Update(); - - std::remove(tmpFilePath.c_str()); - - if ( stlReader->GetOutput() == NULL) - { - MITK_ERROR << "Error while reading file"; - return ; - } - output->SetVtkPolyData( stlReader->GetOutput()->GetVtkPolyData());//set the visible trackingvolume } void mitk::TrackingVolumeGenerator::SetTrackingDeviceType(mitk::TrackingDeviceType deviceType) { m_Data = mitk::GetFirstCompatibleDeviceDataForLine(deviceType); } mitk::TrackingDeviceType mitk::TrackingVolumeGenerator::GetTrackingDeviceType() const { return m_Data.Line; } void mitk::TrackingVolumeGenerator::SetTrackingDeviceData(mitk::TrackingDeviceData deviceData) { m_Data= deviceData; } mitk::TrackingDeviceData mitk::TrackingVolumeGenerator::GetTrackingDeviceData() const { return m_Data; } diff --git a/Modules/IGT/files.cmake b/Modules/IGT/files.cmake index a23020d003..aef21bf3f1 100644 --- a/Modules/IGT/files.cmake +++ b/Modules/IGT/files.cmake @@ -1,90 +1,92 @@ set(CPP_FILES TestingHelper/mitkNavigationToolStorageTestHelper.cpp Algorithms/mitkNavigationDataDelayFilter.cpp Algorithms/mitkNavigationDataDisplacementFilter.cpp Algorithms/mitkNavigationDataEvaluationFilter.cpp Algorithms/mitkNavigationDataLandmarkTransformFilter.cpp Algorithms/mitkNavigationDataReferenceTransformFilter.cpp Algorithms/mitkNavigationDataSmoothingFilter.cpp Algorithms/mitkNavigationDataToMessageFilter.cpp Algorithms/mitkNavigationDataToNavigationDataFilter.cpp Algorithms/mitkNavigationDataToPointSetFilter.cpp Algorithms/mitkNavigationDataTransformFilter.cpp + Algorithms/mitkIGTLMessageToNavigationDataFilter.cpp + Algorithms/mitkNavigationDataToIGTLMessageFilter.cpp Common/mitkIGTTimeStamp.cpp Common/mitkSerialCommunication.cpp Common/mitkTrackingTypes.cpp DataManagement/mitkNavigationData.cpp DataManagement/mitkNavigationDataSet.cpp DataManagement/mitkNavigationDataSource.cpp DataManagement/mitkNavigationTool.cpp DataManagement/mitkNavigationToolStorage.cpp DataManagement/mitkTrackingDeviceSourceConfigurator.cpp DataManagement/mitkTrackingDeviceSource.cpp ExceptionHandling/mitkIGTException.cpp ExceptionHandling/mitkIGTHardwareException.cpp ExceptionHandling/mitkIGTIOException.cpp IO/mitkNavigationDataPlayer.cpp IO/mitkNavigationDataPlayerBase.cpp IO/mitkNavigationDataRecorder.cpp IO/mitkNavigationDataRecorderDeprecated.cpp IO/mitkNavigationDataSequentialPlayer.cpp IO/mitkNavigationToolReader.cpp IO/mitkNavigationToolStorageSerializer.cpp IO/mitkNavigationToolStorageDeserializer.cpp IO/mitkNavigationToolWriter.cpp IO/mitkNavigationDataReaderInterface.cpp IO/mitkNavigationDataReaderXML.cpp IO/mitkNavigationDataReaderCSV.cpp IO/mitkNavigationDataSetWriterXML.cpp IO/mitkNavigationDataSetWriterCSV.cpp Rendering/mitkCameraVisualization.cpp Rendering/mitkNavigationDataObjectVisualizationFilter.cpp TrackingDevices/mitkClaronTool.cpp TrackingDevices/mitkClaronTrackingDevice.cpp TrackingDevices/mitkInternalTrackingTool.cpp TrackingDevices/mitkNDIPassiveTool.cpp TrackingDevices/mitkNDIProtocol.cpp TrackingDevices/mitkNDITrackingDevice.cpp TrackingDevices/mitkTrackingDevice.cpp TrackingDevices/mitkTrackingTool.cpp TrackingDevices/mitkTrackingVolumeGenerator.cpp TrackingDevices/mitkVirtualTrackingDevice.cpp TrackingDevices/mitkVirtualTrackingTool.cpp TrackingDevices/mitkOptitrackErrorMessages.cpp TrackingDevices/mitkOptitrackTrackingDevice.cpp TrackingDevices/mitkOptitrackTrackingTool.cpp ) set(RESOURCE_FILES ClaronMicron.stl IntuitiveDaVinci.stl NDIAurora.stl NDIAurora_Dome.stl NDIAuroraCompactFG_Dome.stl NDIAuroraPlanarFG_Dome.stl NDIAuroraTabletopFG_Dome.stl NDIAuroraTabletopFG_Prototype_Dome.stl NDIPolarisOldModel.stl NDIPolarisSpectra.stl NDIPolarisSpectraExtendedPyramid.stl NDIPolarisVicra.stl ) if(MITK_USE_MICRON_TRACKER) set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkClaronInterface.cpp) else() set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkClaronInterfaceStub.cpp) endif(MITK_USE_MICRON_TRACKER) if(MITK_USE_MICROBIRD_TRACKER) set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkMicroBirdTrackingDevice.cpp) endif(MITK_USE_MICROBIRD_TRACKER) diff --git a/Modules/IGTUI/Qmitk/QmitkIGTLoggerWidget.cpp b/Modules/IGTUI/Qmitk/QmitkIGTLoggerWidget.cpp index 59fcdfb14b..8c83ef105a 100644 --- a/Modules/IGTUI/Qmitk/QmitkIGTLoggerWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkIGTLoggerWidget.cpp @@ -1,310 +1,309 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkIGTLoggerWidget.h" //mitk headers #include "mitkTrackingTypes.h" -#include #include #include #include #include #include #include #include #include //itk headers #include //qt headers #include #include #include QmitkIGTLoggerWidget::QmitkIGTLoggerWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), m_Recorder(NULL), m_RecordingActivated(false) { m_Controls = NULL; CreateQtPartControl(this); CreateConnections(); //set output file this->SetOutputFileName(); //update milliseconds and samples this->SetDefaultRecordingSettings(); } QmitkIGTLoggerWidget::~QmitkIGTLoggerWidget() { m_RecordingTimer->stop(); m_Recorder = NULL; m_RecordingTimer = NULL; } void QmitkIGTLoggerWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkIGTLoggerWidgetControls; m_Controls->setupUi(parent); m_RecordingTimer = new QTimer(this); } } void QmitkIGTLoggerWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_pbLoadDir), SIGNAL(clicked()), this, SLOT(OnChangePressed()) ); connect( (QObject*)(m_Controls->m_pbStartRecording), SIGNAL(clicked(bool)), this, SLOT(OnStartRecording(bool)) ); connect( m_RecordingTimer, SIGNAL(timeout()), this, SLOT(OnRecording()) ); connect( (QObject*)(m_Controls->m_leRecordingValue), SIGNAL(editingFinished()), this, SLOT(UpdateRecordingTime()) ); connect( (QObject*)(m_Controls->m_cbRecordingType), SIGNAL(activated(int)), this, SLOT(UpdateRecordingTime()) ); connect( (QObject*)(m_Controls->m_leOutputFile), SIGNAL(editingFinished()), this, SLOT(UpdateOutputFileName()) ); } } void QmitkIGTLoggerWidget::SetDataStorage(mitk::DataStorage* dataStorage) { m_DataStorage = dataStorage; } void QmitkIGTLoggerWidget::OnStartRecording(bool recording) { if (m_Recorder.IsNull()) { QMessageBox::warning(NULL, "Warning", QString("Please start tracking before recording!")); return; } if (m_CmpFilename.isEmpty()) { QMessageBox::warning(NULL, "Warning", QString("Please specify filename!")); return; } if(recording) { if (!m_RecordingActivated) { //m_Recorder->SetFileName(m_CmpFilename.toStdString()); try { /*start the recording mechanism */ m_Recorder->StartRecording(); m_RecordingTimer->start(50); //now every update of the recorder stores one line into the file for each added NavigationData mitk::StatusBar::GetInstance()->DisplayText("Recording tracking data now"); // Display recording message for 75ms in status bar emit SignalRecordingStarted(); } catch (std::exception& e) { QMessageBox::warning(NULL, "IGT-Tracking Logger: Error", QString("Error while recording tracking data: %1").arg(e.what())); mitk::StatusBar::GetInstance()->DisplayText(""); // Display recording message for 75ms in status bar } m_Controls->m_pbStartRecording->setText("Stop recording"); m_Controls->m_leRecordingValue->setEnabled(false); m_Controls->m_cbRecordingType->setEnabled(false); m_RecordingActivated = true; if(m_Controls->m_cbRecordingType->currentIndex()==0) { bool success = false; QString str_ms = m_Controls->m_leRecordingValue->text(); int int_ms = str_ms.toInt(&success); if (success) QTimer::singleShot(int_ms, this, SLOT(StopRecording())); } } else { this->StopRecording(); } } else { this->StopRecording(); m_Controls->m_pbStartRecording->setChecked(false); } } void QmitkIGTLoggerWidget::StopRecording() { m_RecordingTimer->stop(); m_Recorder->StopRecording(); mitk::StatusBar::GetInstance()->DisplayText("Recording STOPPED", 2000); // Display message for 2s in status bar m_Controls->m_pbStartRecording->setText("Start recording"); m_Controls->m_pbStartRecording->setChecked(false); m_Controls->m_leRecordingValue->setEnabled(true); m_Controls->m_cbRecordingType->setEnabled(true); m_RecordingActivated = false; try { // write NavigationDataSet on StopRecording mitk::NavigationDataSetWriterXML().Write(m_CmpFilename.toStdString(), m_Recorder->GetNavigationDataSet()); } catch(const std::exception &e) { // TODO: catch must be adapted when new file writer are merged to master QMessageBox::warning(NULL, "IGT-Tracking Logger: Error", QString("Error while writing tracking data: %1").arg(e.what())); MITK_WARN << "File could not be written."; } emit SignalRecordingStopped(); } void QmitkIGTLoggerWidget::OnRecording() { static unsigned int sampleCounter = 0; unsigned int int_samples = m_Samples.toInt(); if(sampleCounter >= int_samples) { this->StopRecording(); sampleCounter=0; return; } m_Recorder->Update(); if (m_Controls->m_cbRecordingType->currentIndex()==1) sampleCounter++; } void QmitkIGTLoggerWidget::OnChangePressed() { QString oldName = m_CmpFilename; m_CmpFilename.clear(); m_CmpFilename = QFileDialog::getSaveFileName( QApplication::activeWindow() , "Save tracking data", "IGT_Tracking_Data.xml", "XML files (*.xml)" ); if (m_CmpFilename.isEmpty())//if something went wrong or user pressed cancel in the save dialog { m_CmpFilename=oldName; } m_Controls->m_leOutputFile->setText(m_CmpFilename); } void QmitkIGTLoggerWidget::UpdateOutputFileName() { QString oldName = m_CmpFilename; m_CmpFilename.clear(); m_CmpFilename = m_Controls->m_leOutputFile->text(); if (m_CmpFilename.isEmpty()) { QMessageBox::warning(NULL, "Warning", QString("Please enter valid path! Using previous path again.")); m_CmpFilename=oldName; m_Controls->m_leOutputFile->setText(m_CmpFilename); } } void QmitkIGTLoggerWidget::SetRecorder( mitk::NavigationDataRecorder::Pointer recorder ) { m_Recorder = recorder; } void QmitkIGTLoggerWidget::UpdateRecordingTime() { // milliseconds selected in the combobox if (m_Controls->m_cbRecordingType->currentIndex()==0) { m_MilliSeconds = m_Controls->m_leRecordingValue->text(); if(m_MilliSeconds.compare("infinite")==0) { this->SetDefaultRecordingSettings(); } bool success = false; m_MilliSeconds.toInt(&success); if (!success) { QMessageBox::warning(NULL, "Warning", QString("Please enter a number!")); this->SetDefaultRecordingSettings(); return; } } else if(m_Controls->m_cbRecordingType->currentIndex()==1) // #samples selected in the combobox { m_Samples = m_Controls->m_leRecordingValue->text(); if(m_Samples.compare("infinite")==0) { this->SetDefaultRecordingSettings(); } bool success = false; m_Samples.toInt(&success); if (!success) { QMessageBox::warning(NULL, "Warning", QString("Please enter a number!")); this->SetDefaultRecordingSettings(); return; } } else if (m_Controls->m_cbRecordingType->currentIndex()==2)// infinite selected in the combobox { // U+221E unicode symbole for infinite QString infinite("infinite"); m_Controls->m_leRecordingValue->setText(infinite); } // m_Controls->m_leSamples->setText(QString::number(samples)); } void QmitkIGTLoggerWidget::SetDefaultRecordingSettings() { m_Controls->m_leRecordingValue->setText("2000"); m_Controls->m_cbRecordingType->setCurrentIndex(0); m_Samples="100"; m_MilliSeconds="2000"; } void QmitkIGTLoggerWidget::SetOutputFileName() { std::string tmpDir = itksys::SystemTools::GetCurrentWorkingDirectory(); QString dir = QString(tmpDir.c_str()); QString filename = "IGT_Tracking_Data.xml"; m_CmpFilename.append(dir); if(dir.isEmpty()) { QMessageBox::warning(NULL, "Warning", QString("Could not load current working directory")); return; } if(dir.endsWith("/")||dir.endsWith("\\")) { m_CmpFilename.append(filename); } else { m_CmpFilename.append("/"); m_CmpFilename.append(filename); } m_Controls->m_leOutputFile->setText(m_CmpFilename); } diff --git a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp index 63361eacd4..b0b0d49bca 100644 --- a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp @@ -1,576 +1,575 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkIGTPlayerWidget.h" //mitk headers #include "mitkTrackingTypes.h" -#include #include #include #include #include #include #include #include #include "mitkNavigationDataReaderXML.h" //qt headers #include #include #include QmitkIGTPlayerWidget::QmitkIGTPlayerWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), m_RealTimePlayer(mitk::NavigationDataPlayer::New()), m_SequentialPlayer(mitk::NavigationDataSequentialPlayer::New()), m_StartTime(-1.0), m_CurrentSequentialPointNumber(0), m_Controls(new Ui::QmitkIGTPlayerWidgetControls) { m_Controls->setupUi(this); m_PlayingTimer = new QTimer(this); // initialize update timer CreateConnections(); m_Controls->samplePositionHorizontalSlider->setVisible(false); this->ResetLCDNumbers(); // reset lcd numbers at start } QmitkIGTPlayerWidget::~QmitkIGTPlayerWidget() { m_PlayingTimer->stop(); delete m_Controls; } void QmitkIGTPlayerWidget::CreateConnections() { connect( (QObject*)(m_Controls->playPushButton), SIGNAL(clicked(bool)), this, SLOT(OnPlayButtonClicked(bool)) ); // play button connect( (QObject*)(m_PlayingTimer), SIGNAL(timeout()), this, SLOT(OnPlaying()) ); // update timer connect( (QObject*) (m_Controls->beginPushButton), SIGNAL(clicked()), this, SLOT(OnGoToBegin()) ); // reset player and go to begin connect( (QObject*) (m_Controls->stopPushButton), SIGNAL(clicked()), this, SLOT(OnGoToEnd()) ); // reset player // pass this widgets protected combobox signal to public signal connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); // pass this widgets protected checkbox signal to public signal connect( m_Controls->splineModeCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(SignalSplineModeToggled(bool)) ); //connect( m_Controls->sequencialModeCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnSequencialModeToggled(bool)) ); connect( m_Controls->samplePositionHorizontalSlider, SIGNAL(sliderPressed()), this, SLOT(OnSliderPressed()) ); connect( m_Controls->samplePositionHorizontalSlider, SIGNAL(sliderReleased()), this, SLOT(OnSliderReleased()) ); connect( m_Controls->m_OpenFileButton, SIGNAL(clicked()), this, SLOT(OnOpenFileButtonPressed()) ); } bool QmitkIGTPlayerWidget::IsTrajectoryInSplineMode() { return m_Controls->splineModeCheckBox->isChecked(); } bool QmitkIGTPlayerWidget::CheckInputFileValid() { QFile file(m_CmpFilename); // check if file exists if(!file.exists()) { QMessageBox::warning(NULL, "IGTPlayer: Error", "No valid input file was loaded. Please load input file first!"); return false; } return true; } unsigned int QmitkIGTPlayerWidget::GetNumberOfTools() { unsigned int result = 0; if(this->GetCurrentPlaybackMode() == RealTimeMode) { if(m_RealTimePlayer.IsNotNull()) result = m_RealTimePlayer->GetNumberOfOutputs(); } else if(this->GetCurrentPlaybackMode() == SequentialMode) { if(m_SequentialPlayer.IsNotNull()) result = m_SequentialPlayer->GetNumberOfOutputs(); } // at the moment this works only if player is initialized return result; } void QmitkIGTPlayerWidget::SetUpdateRate(unsigned int msecs) { m_PlayingTimer->setInterval((int) msecs); // set update timer update rate } void QmitkIGTPlayerWidget::OnPlayButtonClicked(bool checked) { if ( ! checked ) { if ( this->GetCurrentPlaybackMode() == RealTimeMode ) { m_RealTimePlayer->StopPlaying(); } else if ( this->GetCurrentPlaybackMode() == SequentialMode ) { // m_SequentialPlayer-> } } if(CheckInputFileValid()) // no playing possible without valid input file { switch ( this->GetCurrentPlaybackMode() ) { case RealTimeMode: { break; } case SequentialMode: { break; } } PlaybackMode currentMode = this->GetCurrentPlaybackMode(); bool isRealTimeMode = currentMode == RealTimeMode; bool isSequentialMode = currentMode == SequentialMode; if(checked) // play { if( (isRealTimeMode && m_RealTimePlayer.IsNull()) || (isSequentialMode && m_SequentialPlayer.IsNull())) // start play { mitk::NavigationDataSet::Pointer navigationDataSet; try { mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); navigationDataSet = reader->Read(m_CmpFilename.toStdString()); } catch(mitk::IGTException) { std::string errormessage = "Error during start playing. Invalid or wrong file?"; QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); m_Controls->playPushButton->setChecked(false); m_RealTimePlayer = NULL; return; } if(isRealTimeMode) { m_RealTimePlayer = mitk::NavigationDataPlayer::New(); m_RealTimePlayer->SetNavigationDataSet(navigationDataSet); try { m_RealTimePlayer->StartPlaying(); } catch(mitk::IGTException) { std::string errormessage = "Error during start playing. Invalid or wrong file?"; QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); m_Controls->playPushButton->setChecked(false); m_RealTimePlayer = NULL; return; } } else if(isSequentialMode) { m_SequentialPlayer = mitk::NavigationDataSequentialPlayer::New(); try { m_SequentialPlayer->SetNavigationDataSet(navigationDataSet); } catch(mitk::IGTException) { std::string errormessage = "Error during start playing. Invalid or wrong file type?"; QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); m_Controls->playPushButton->setChecked(false); m_RealTimePlayer = NULL; return; } m_Controls->samplePositionHorizontalSlider->setMinimum(0); m_Controls->samplePositionHorizontalSlider->setMaximum(m_SequentialPlayer->GetNumberOfSnapshots()); m_Controls->samplePositionHorizontalSlider->setEnabled(true); } m_PlayingTimer->start(100); emit SignalPlayingStarted(); } else // resume play { if(isRealTimeMode) m_RealTimePlayer->Resume(); m_PlayingTimer->start(100); emit SignalPlayingResumed(); } } else // pause { if(isRealTimeMode) m_RealTimePlayer->Pause(); m_PlayingTimer->stop(); emit SignalPlayingPaused(); } } else { m_Controls->playPushButton->setChecked(false); // uncheck play button if file unvalid } } QmitkIGTPlayerWidget::PlaybackMode QmitkIGTPlayerWidget::GetCurrentPlaybackMode() { /*if(m_Controls->sequencialModeCheckBox->isChecked()) return SequentialMode; else*/ return RealTimeMode; } QTimer* QmitkIGTPlayerWidget::GetPlayingTimer() { return m_PlayingTimer; } void QmitkIGTPlayerWidget::OnStopPlaying() { this->StopPlaying(); } void QmitkIGTPlayerWidget::StopPlaying() { m_PlayingTimer->stop(); emit SignalPlayingStopped(); if(m_RealTimePlayer.IsNotNull()) m_RealTimePlayer->StopPlaying(); m_StartTime = -1; // set starttime back m_CurrentSequentialPointNumber = 0; m_Controls->samplePositionHorizontalSlider->setSliderPosition(m_CurrentSequentialPointNumber); m_Controls->sampleLCDNumber->display(static_cast(m_CurrentSequentialPointNumber)); this->ResetLCDNumbers(); m_Controls->playPushButton->setChecked(false); // set play button unchecked } void QmitkIGTPlayerWidget::OnPlaying() { switch ( this->GetCurrentPlaybackMode() ) { case RealTimeMode: { if ( m_RealTimePlayer.IsNull() ) { return; } if ( m_StartTime < 0 ) { // get playback start time m_StartTime = m_RealTimePlayer->GetOutput()->GetTimeStamp(); } if( ! m_RealTimePlayer->IsAtEnd() ) { m_RealTimePlayer->Update(); // update player int msc = (int) (m_RealTimePlayer->GetOutput()->GetTimeStamp() - m_StartTime); // calculation for playing time display int ms = msc % 1000; msc = (msc - ms) / 1000; int s = msc % 60; int min = (msc-s) / 60; // set lcd numbers m_Controls->msecLCDNumber->display(ms); m_Controls->secLCDNumber->display(s); m_Controls->minLCDNumber->display(min); emit SignalPlayerUpdated(); // player successfully updated } else { this->StopPlaying(); // if player is at EOF } break; } case SequentialMode: { if ( m_SequentialPlayer.IsNull() ) { return; } if ( m_CurrentSequentialPointNumber < m_SequentialPlayer->GetNumberOfSnapshots() ) { m_SequentialPlayer->Update(); // update sequential player m_Controls->samplePositionHorizontalSlider->setSliderPosition(m_CurrentSequentialPointNumber++); // refresh slider position m_Controls->sampleLCDNumber->display(static_cast(m_CurrentSequentialPointNumber)); //for debugging purposes //std::cout << "Sample: " << m_CurrentSequentialPointNumber << " X: " << m_SequentialPlayer->GetOutput()->GetPosition()[0] << " Y: " << m_SequentialPlayer->GetOutput()->GetPosition()[1] << " Y: " << m_SequentialPlayer->GetOutput()->GetPosition()[2] << std::endl; emit SignalPlayerUpdated(); // player successfully updated } else { this->StopPlaying(); // if player is at EOF } break; } } } const std::vector QmitkIGTPlayerWidget::GetNavigationDatas() { std::vector navDatas; if(this->GetCurrentPlaybackMode() == RealTimeMode && m_RealTimePlayer.IsNotNull()) { for(unsigned int i=0; i < m_RealTimePlayer->GetNumberOfOutputs(); ++i) { navDatas.push_back(m_RealTimePlayer->GetOutput(i)); // push back current navigation data for each tool } } else if(this->GetCurrentPlaybackMode() == SequentialMode && m_SequentialPlayer.IsNotNull()) { for(unsigned int i=0; i < m_SequentialPlayer->GetNumberOfOutputs(); ++i) { navDatas.push_back(m_SequentialPlayer->GetOutput(i)); // push back current navigation data for each tool } } return navDatas; } const mitk::PointSet::Pointer QmitkIGTPlayerWidget::GetNavigationDatasPointSet() { mitk::PointSet::Pointer result = mitk::PointSet::New(); mitk::PointSet::PointType pointType; PlaybackMode currentMode = this->GetCurrentPlaybackMode(); bool isRealTimeMode = currentMode == RealTimeMode; bool isSequentialMode = currentMode == SequentialMode; if( (isRealTimeMode && m_RealTimePlayer.IsNotNull()) || (isSequentialMode && m_SequentialPlayer.IsNotNull())) { int numberOfOutputs = 0; if(isRealTimeMode) numberOfOutputs = m_RealTimePlayer->GetNumberOfOutputs(); else if(isSequentialMode) numberOfOutputs = m_SequentialPlayer->GetNumberOfOutputs(); for(unsigned int i=0; i < m_RealTimePlayer->GetNumberOfOutputs(); ++i) { mitk::NavigationData::PositionType position; if(isRealTimeMode) position = m_RealTimePlayer->GetOutput(i)->GetPosition(); else if(isSequentialMode) position = m_SequentialPlayer->GetOutput(i)->GetPosition(); pointType[0] = position[0]; pointType[1] = position[1]; pointType[2] = position[2]; result->InsertPoint(i,pointType); // insert current ND as Pointtype in PointSet for return } } return result; } const mitk::PointSet::PointType QmitkIGTPlayerWidget::GetNavigationDataPoint(unsigned int index) { if( index > this->GetNumberOfTools() || index < 0 ) throw std::out_of_range("Tool Index out of range!"); PlaybackMode currentMode = this->GetCurrentPlaybackMode(); bool isRealTimeMode = currentMode == RealTimeMode; bool isSequentialMode = currentMode == SequentialMode; // create return PointType from current ND for tool index mitk::PointSet::PointType result; if( (isRealTimeMode && m_RealTimePlayer.IsNotNull()) || (isSequentialMode && m_SequentialPlayer.IsNotNull())) { mitk::NavigationData::PositionType position; if(isRealTimeMode) position = m_RealTimePlayer->GetOutput(index)->GetPosition(); else if(isSequentialMode) position = m_SequentialPlayer->GetOutput(index)->GetPosition(); result[0] = position[0]; result[1] = position[1]; result[2] = position[2]; } return result; } /*void QmitkIGTPlayerWidget::SetRealTimePlayer( mitk::NavigationDataPlayer::Pointer player ) { if(player.IsNotNull()) m_RealTimePlayer = player; } void QmitkIGTPlayerWidget::SetSequentialPlayer( mitk::NavigationDataSequentialPlayer::Pointer player ) { if(player.IsNotNull()) m_SequentialPlayer = player; }*/ void QmitkIGTPlayerWidget::OnOpenFileButtonPressed() { QString filename = QFileDialog::getOpenFileName(this, "Load tracking data", QDir::currentPath(),"XML files (*.xml)"); QFile file(filename); // if something went wrong or user pressed cancel in the save dialog if ( filename.isEmpty() || ! file.exists() ) { QMessageBox::warning(NULL, "Warning", QString("Please enter valid path. Using previous path again.")); return; } m_CmpFilename = filename; this->OnGoToEnd(); /// stops playing and resets lcd numbers m_Controls->m_ActiveFileLabel->setText(m_CmpFilename); emit SignalInputFileChanged(); mitk::NavigationDataReaderInterface::Pointer navigationDataReader = mitk::NavigationDataReaderXML::New().GetPointer(); mitk::NavigationDataSet::Pointer navigationDataSet = navigationDataReader->Read(m_CmpFilename.toStdString()); m_RealTimePlayer->SetNavigationDataSet(navigationDataSet); m_SequentialPlayer->SetNavigationDataSet(navigationDataSet); m_Controls->m_PlayerControlsGroupBox->setEnabled(true); } void QmitkIGTPlayerWidget::OnGoToEnd() { this->StopPlaying(); // reset lcd numbers this->ResetLCDNumbers(); } void QmitkIGTPlayerWidget::OnGoToBegin() { // stop player manual so no PlayingStopped() m_PlayingTimer->stop(); if(this->GetCurrentPlaybackMode() == RealTimeMode && m_RealTimePlayer.IsNotNull()) { m_RealTimePlayer->StopPlaying(); m_RealTimePlayer = NULL; // set player to NULL so it can be initialized again if playback is called afterwards } m_StartTime = -1; // set starttime back //reset view elements m_Controls->playPushButton->setChecked(false); this->ResetLCDNumbers(); } void QmitkIGTPlayerWidget::ResetLCDNumbers() { m_Controls->minLCDNumber->display(QString("00")); m_Controls->secLCDNumber->display(QString("00")); m_Controls->msecLCDNumber->display(QString("000")); } void QmitkIGTPlayerWidget::SetTrajectoryNames(const QStringList toolNames) { QComboBox* cBox = m_Controls->trajectorySelectComboBox; if(cBox->count() > 0) this->ClearTrajectorySelectCombobox(); // before making changed to QComboBox it is recommended to disconnet it's SIGNALS and SLOTS disconnect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); if(!toolNames.isEmpty()) m_Controls->trajectorySelectComboBox->insertItems(0, toolNames); // adding current tool names to combobox // reconnect after performed changes connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); } int QmitkIGTPlayerWidget::GetResolution() { return m_Controls->resolutionSpinBox->value(); // return currently selected trajectory resolution } void QmitkIGTPlayerWidget::ClearTrajectorySelectCombobox() { // before making changed to QComboBox it is recommended to disconnet it's SIGNALS and SLOTS disconnect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); m_Controls->trajectorySelectComboBox->clear(); // reconnect after performed changes connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); } void QmitkIGTPlayerWidget::OnSequencialModeToggled(bool toggled) { this->StopPlaying(); // stop playing when mode is changed if(toggled) { m_Controls->samplePositionHorizontalSlider->setEnabled(true); // enable slider if sequential mode } else if(!toggled) { m_Controls->samplePositionHorizontalSlider->setSliderPosition(0); // set back and disable slider m_Controls->samplePositionHorizontalSlider->setDisabled(true); } } void QmitkIGTPlayerWidget::OnSliderReleased() { int currentSliderValue = m_Controls->samplePositionHorizontalSlider->value(); // current slider value selected through user movement if(currentSliderValue > m_CurrentSequentialPointNumber) // at the moment only forward scrolling is possible { unsigned int snapshotNumber = currentSliderValue; m_SequentialPlayer->GoToSnapshot(snapshotNumber); // move player to selected snapshot m_CurrentSequentialPointNumber = currentSliderValue; m_Controls->sampleLCDNumber->display(currentSliderValue); // update lcdnumber in widget } else m_Controls->samplePositionHorizontalSlider->setValue(m_CurrentSequentialPointNumber); } void QmitkIGTPlayerWidget::OnSliderPressed() { if(m_Controls->playPushButton->isChecked()) // check if widget is playing m_Controls->playPushButton->click(); // perform click to pause the play -} \ No newline at end of file +} diff --git a/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.cpp index 862c3d7d3b..4c0d97e87e 100644 --- a/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.cpp @@ -1,902 +1,898 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkNDIConfigurationWidget.h" #include #include #include #include #include #include #include #include -#include #include +#include #include "QmitkCustomVariants.h" //#include #include "QmitkNDIToolDelegate.h" /* VIEW MANAGEMENT */ QmitkNDIConfigurationWidget::QmitkNDIConfigurationWidget(QWidget* parent) : QWidget(parent), m_Controls(NULL), m_Tracker(NULL), m_Source(NULL), m_Delegate(NULL), m_SROMCellDefaultText(""), m_RepresentatonCellDefaultText("") { this->CreateQtPartControl(this); } QmitkNDIConfigurationWidget::~QmitkNDIConfigurationWidget() { m_Controls = NULL; m_Tracker = NULL; m_Source = NULL; } void QmitkNDIConfigurationWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNDIConfigurationWidget; m_Controls->setupUi(parent); QStringList comPorts; #ifdef WIN32 comPorts << "COM1" << "COM2" << "COM3" << "COM4" << "COM5" << "COM6" << "COM7" << "COM8" << "COM9"; #else comPorts << "/dev/ttyS1" << "/dev/ttyS2" << "/dev/ttyS3" << "/dev/ttyS4" << "/dev/ttyS5" << "/dev/ttyUSB0" << "/dev/ttyUSB1" << "/dev/ttyUSB2" << "/dev/ttyUSB3"; #endif m_Controls->m_ComPortSelector->addItems(comPorts); m_Delegate = new QmitkNDIToolDelegate(m_Controls->m_ToolTable); m_Delegate->SetDataStorage(NULL); //needs to be set later using the setter methods m_Delegate->SetPredicate(NULL); m_Delegate->SetTypes(QStringList()); m_Controls->m_ToolTable->setItemDelegate(m_Delegate); this->CreateConnections(); this->HidePolarisOptionsGroupbox(true); this->HideAuroraOptionsGroupbox(true); } } void QmitkNDIConfigurationWidget::CreateConnections() { connect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnConnect())); connect(m_Controls->m_DiscoverToolsBtn, SIGNAL(clicked()), this, SLOT(OnDiscoverTools())); connect(m_Controls->m_AddToolBtn, SIGNAL(clicked()), this, SLOT(OnAddPassiveTool())); connect(m_Controls->m_DisoverDevicesBtn, SIGNAL(clicked()), this, SLOT(OnDiscoverDevices())); connect(m_Controls->m_ToolTable->model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateTrackerFromToolTable(const QModelIndex &, const QModelIndex &))); connect(m_Controls->m_DisoverDevicesBtnInfo, SIGNAL(clicked()), this, SLOT(OnDisoverDevicesBtnInfo())); connect(m_Controls->m_SaveToolPushButton, SIGNAL(clicked()), this, SLOT(OnSaveTool()) ); connect(m_Controls->m_LoadToolPushButton, SIGNAL(clicked()), this, SLOT(OnLoadTool()) ); } void QmitkNDIConfigurationWidget::OnConnect() { if (m_Tracker.IsNotNull()) { m_Tracker->CloseConnection(); m_Tracker = NULL; } this->CreateTracker(); this->SetupTracker(); bool okay = false; try { okay = m_Tracker->OpenConnection(); } catch(mitk::IGTException &e) { QMessageBox::warning(NULL, "Error", QString("Connection failed, error message: ") + e.GetDescription()); m_Tracker->CloseConnection(); this->m_Tracker = NULL; } if (okay) { // show/hide options according to connected device if(m_Tracker->GetType() == mitk::NDIPolaris) { this->HideAuroraOptionsGroupbox(true); this->HidePolarisOptionsGroupbox(false); } else if(m_Tracker->GetType() == mitk::NDIAurora) { this->HidePolarisOptionsGroupbox(true); this->HideAuroraOptionsGroupbox(false); } this->UpdateWidgets(); this->UpdateToolTable(); connect(m_Controls->m_ToolTable, SIGNAL(cellChanged(int,int)), this, SLOT(OnTableCellChanged(int,int))); emit ToolsAdded(this->GetToolNamesList()); emit Connected(); } else { QMessageBox::warning(NULL, "Error", QString("Connection failed due to an unknown reason!")); m_Tracker->CloseConnection(); this->m_Tracker = NULL; } } void QmitkNDIConfigurationWidget::OnDisconnect() { if (m_Tracker.IsNull()) return; m_Tracker->CloseConnection(); m_Tracker = NULL; disconnect(m_Controls->m_ToolTable, SIGNAL(cellChanged(int,int)), this, SLOT(OnTableCellChanged(int,int))); m_Controls->m_ToolSelectionComboBox->clear(); this->UpdateToolTable(); this->UpdateWidgets(); emit ToolsAdded(this->GetToolNamesList()); emit Disconnected(); this->HidePolarisOptionsGroupbox(true); this->HideAuroraOptionsGroupbox(true); } void QmitkNDIConfigurationWidget::UpdateWidgets() { m_Controls->m_DeviceStatus->setText(this->GetStatusText()); if (m_Tracker.IsNull()) // not connected to tracker { m_Controls->m_Connect->setText("Connect"); m_Controls->m_lConnection->setText("III. Enable connection to device "); disconnect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnDisconnect())); connect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnConnect())); m_Controls->m_DiscoverToolsBtn->setDisabled(true); m_Controls->m_AddToolBtn->setDisabled(true); return; } if (m_Tracker->GetState() == mitk::TrackingDevice::Setup) { m_Controls->m_Connect->setText("Connect"); m_Controls->m_lConnection->setText("III. Enable connection to device "); disconnect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnDisconnect())); connect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnConnect())); m_Controls->m_DiscoverToolsBtn->setDisabled(true); m_Controls->m_AddToolBtn->setDisabled(true); return; } if ((m_Tracker->GetState() == mitk::TrackingDevice::Ready) || (m_Tracker->GetState() == mitk::TrackingDevice::Tracking)) { m_Controls->m_Connect->setText("Disconnect"); m_Controls->m_lConnection->setText("III. Disable connection to device "); disconnect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnConnect())); connect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnDisconnect())); m_Controls->m_DiscoverToolsBtn->setEnabled(true); m_Controls->m_AddToolBtn->setEnabled(true); } } QString QmitkNDIConfigurationWidget::GetStatusText() { if (m_Tracker.IsNull()) return QString("Not connected"); QString devName; switch (m_Tracker->GetType()) { case mitk::NDIAurora: devName = "NDI Aurora"; break; case mitk::NDIPolaris: devName = "NDI Polaris"; break; case mitk::TrackingSystemNotSpecified: default: devName = "unknown tracking device"; break; } if (m_Tracker->GetState() == mitk::TrackingDevice::Ready) return QString("Connected to %1 on %2. Device is ready.").arg(devName).arg(m_Tracker->GetDeviceName()); if (m_Tracker->GetState() == mitk::TrackingDevice::Tracking) return QString("%1 is tracking.").arg(devName); return QString(""); } void QmitkNDIConfigurationWidget::OnDiscoverTools() { if (m_Tracker.IsNull()) { QMessageBox::warning(NULL, "Error", QString("Connection failed. No tracking device found.")); return; } m_Tracker->DiscoverWiredTools(); this->UpdateToolTable(); emit ToolsAdded(this->GetToolNamesList()); } void QmitkNDIConfigurationWidget::OnAddPassiveTool() { if (m_Tracker.IsNull()) this->CreateTracker(); QStringList filenames = QFileDialog::getOpenFileNames(this, "Select NDI SROM file", QDir::currentPath(),"NDI SROM files (*.rom)"); if (filenames.isEmpty()) { this->m_Tracker = NULL; return; } foreach(QString fileName, filenames) { //QString toolName = QInputDialog::getText(this, "Enter a name for the tool", "Name of the tool: ", QLineEdit::Normal, QFileInfo(filename).baseName(), &ok); //if (ok == false || toolName.isEmpty()) // return; m_Tracker->AddTool(QFileInfo(fileName).baseName().toLatin1(), fileName.toLatin1()); m_Tracker->Modified(); } emit ToolsAdded(this->GetToolNamesList()); this->UpdateToolTable(); } void QmitkNDIConfigurationWidget::CreateTracker() { m_Tracker = mitk::NDITrackingDevice::New(); } void QmitkNDIConfigurationWidget::SetupTracker() { if (m_Tracker.IsNull()) return; m_Tracker->SetDeviceName(this->GetDeviceName()); m_Tracker->SetBaudRate(mitk::SerialCommunication::BaudRate115200); } std::string QmitkNDIConfigurationWidget::GetDeviceName() const { if (m_Controls == NULL) return NULL; QString deviceName = m_Controls->m_ComPortSelector->currentText(); #if WIN32 deviceName.prepend("\\\\.\\"); // always prepend "\\.\ to all COM ports, to be able to connect to ports > 9" #endif return deviceName.toStdString(); } void QmitkNDIConfigurationWidget::SetDeviceName( const char* dev ) { if (m_Controls == NULL) return; m_Controls->m_ComPortSelector->setCurrentIndex(m_Controls->m_ComPortSelector->findText(dev)); } void QmitkNDIConfigurationWidget::UpdateToolTable() { //disconnect(m_Controls->m_ToolTable, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(OnTableItemChanged(QTableWidgetItem*))); // stop listening to table changes disconnect(m_Controls->m_ToolTable->model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateTrackerFromToolTable(const QModelIndex &, const QModelIndex &))); disconnect(m_Controls->m_ToolTable, SIGNAL( clicked ( const QModelIndex & )), this, SLOT ( OnTableItemClicked( const QModelIndex & ))); m_Controls->m_ToolTable->clearContents(); m_Controls->m_ToolTable->setRowCount(0); if (m_Tracker.IsNull() || (m_Controls == NULL)) return; m_Controls->m_ToolSelectionComboBox->clear(); m_Controls->m_ToolTable->setRowCount(m_Tracker->GetToolCount()); for (unsigned int i = 0; i < m_Tracker->GetToolCount(); ++i) { mitk::TrackingTool* t = m_Tracker->GetTool(i); if (t == NULL) { m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::IndexCol, new QTableWidgetItem("INVALID")); // Index continue; } m_Controls->m_ToolSelectionComboBox->addItem(m_Tracker->GetTool(i)->GetToolName()); m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::IndexCol, new QTableWidgetItem(QString::number(i))); // Index m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::NameCol, new QTableWidgetItem(t->GetToolName())); // Name if (dynamic_cast(t)->GetSROMDataLength() > 0) m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::SROMCol, new QTableWidgetItem("SROM file loaded")); // SROM file else m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::SROMCol, new QTableWidgetItem(m_SROMCellDefaultText)); // SROM file m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::TypeCol, new QTableWidgetItem("")); // Type if (t->IsEnabled()) m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::StatusCol, new QTableWidgetItem("Enabled")); // Status else m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::StatusCol, new QTableWidgetItem("Disabled")); // Status m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::NodeCol, new QTableWidgetItem("")); // Node m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::RepCol, new QTableWidgetItem(m_RepresentatonCellDefaultText)); // Representation /* set read-only/editable flags */ m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::IndexCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Index m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::NodeCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Name m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::SROMCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // SROM file m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::TypeCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Type m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::StatusCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Status m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::NodeCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Node m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::RepCol)->setFlags(Qt::NoItemFlags); // Representation surface file } m_Controls->m_ToolTable->resizeColumnsToContents(); //connect(m_Controls->m_ToolTable, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(OnTableItemChanged(QTableWidgetItem*))); // listen to table changes again connect(m_Controls->m_ToolTable->model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateTrackerFromToolTable(const QModelIndex &, const QModelIndex &))); connect(m_Controls->m_ToolTable, SIGNAL( clicked ( const QModelIndex & )), this, SLOT ( OnTableItemClicked( const QModelIndex & ))); } void QmitkNDIConfigurationWidget::OnDiscoverDevices() { PortDeviceMap portsAndDevices; QString status = "Scanning "; #ifdef WIN32 QString devName; for (unsigned int i = 1; i < 40; ++i) { if (i<10) devName = QString("COM%1").arg(i); else devName = QString("\\\\.\\COM%1").arg(i); // prepend "\\.\ to COM ports >9, to be able to allow connection" portsAndDevices[devName]; status += QString("COM%1").arg(i) + ", "; } #else //linux/posix systems for(unsigned int i = 1; i < 6; ++i) { QString devName = QString("/dev/ttyS%1").arg(i); portsAndDevices[devName]; status += devName + ", "; } for(unsigned int i = 0; i <7; ++i) { QString devName = QString("/dev/ttyUSB%1").arg(i); portsAndDevices[devName]; status += devName + ", "; } #endif status.chop(2); // remove last ", " status += " for NDI tracking devices..."; m_Controls->m_DeviceStatus->setText(status); ScanPortsForNDITrackingDevices(portsAndDevices); m_Controls->m_ComPortSelector->clear(); QString result = "The following tracking devices were found:
\n"; for (PortDeviceMap::const_iterator it = portsAndDevices.begin(); it != portsAndDevices.end(); ++it) { QString tmpComPort = it.key(); if (tmpComPort.startsWith("\\")) { tmpComPort.remove(0,4); // remove "\\.\" for nice ui visualisation } result += tmpComPort + ": "; switch (it.value()) { case mitk::NDIPolaris: result += "NDI Polaris
\n"; m_Controls->m_ComPortSelector->addItem(tmpComPort); break; case mitk::NDIAurora: result += "NDI Aurora
\n"; m_Controls->m_ComPortSelector->addItem(tmpComPort); break; default: result += "No NDI tracking device found
\n"; } } //QMessageBox::information(NULL, "Tracking Device Discovery", result); m_Controls->m_DeviceStatus->setText(result); } mitk::TrackingDeviceType QmitkNDIConfigurationWidget::ScanPort(QString port) { mitk::NDITrackingDevice::Pointer tracker = mitk::NDITrackingDevice::New(); tracker->SetDeviceName(port.toStdString()); return tracker->TestConnection(); } void QmitkNDIConfigurationWidget::ScanPortsForNDITrackingDevices( PortDeviceMap& portsAndDevices ) { // Iterative scanning: for (PortDeviceMap::iterator it = portsAndDevices.begin(); it != portsAndDevices.end(); ++it) it.value() = this->ScanPort(it.key()); // \Todo: use parallel scanning //QtConcurrent::blockingMap( portsAndDevices.begin(), portsAndDevices.end(), ScanPort ); //MITK_INFO << portsAndDevices; } QStringList QmitkNDIConfigurationWidget::GetToolNamesList() { QStringList toolNames; if (m_Tracker.IsNull()) return toolNames; for (unsigned int i = 0; i < m_Tracker->GetToolCount(); ++i) { mitk::TrackingTool* t = m_Tracker->GetTool(i); if (t == NULL) continue; toolNames << t->GetToolName(); } return toolNames; } mitk::NDITrackingDevice* QmitkNDIConfigurationWidget::GetTracker() const { return m_Tracker.GetPointer(); } void QmitkNDIConfigurationWidget::SetToolTypes(const QStringList& types) { m_Delegate->SetTypes(types); } void QmitkNDIConfigurationWidget::SetDataStorage(mitk::DataStorage* ds) { m_Delegate->SetDataStorage(ds); } void QmitkNDIConfigurationWidget::SetPredicate(mitk::NodePredicateBase::Pointer p) { m_Delegate->SetPredicate(p); } void QmitkNDIConfigurationWidget::SetTagPropertyName( const std::string& name ) { m_Delegate->SetTagPropertyName(name); } void QmitkNDIConfigurationWidget::SetTagProperty( mitk::BaseProperty::Pointer prop ) { m_Delegate->SetTagProperty(prop); } void QmitkNDIConfigurationWidget::OnTableItemClicked(const QModelIndex & topLeft ) { QString filename; QTableWidgetItem* filenameItem; switch (topLeft.column()) { case QmitkNDIToolDelegate::RepCol: filename = QFileDialog::getOpenFileName(this, "Select Surface File", QDir::currentPath(),"STL files (*.stl)"); filenameItem = new QTableWidgetItem(filename); m_Controls->m_ToolTable->setItem( topLeft.row(), topLeft.column(), filenameItem ); if(QFileInfo(filename).exists()) { mitk::Surface::Pointer surface = this->LoadSurfaceFromSTLFile(filename); if(surface.IsNotNull()) emit RepresentationChanged( topLeft.row(), surface); } break; default: break; } } void QmitkNDIConfigurationWidget::UpdateTrackerFromToolTable(const QModelIndex & topLeft, const QModelIndex & /*bottomRight*/) { //Colums ID doesn't have to be processed. if (topLeft.column()<1) return; if (m_Tracker.IsNull()) return; if (topLeft.row() >= (int) m_Tracker->GetToolCount()) return; QAbstractItemModel* model = m_Controls->m_ToolTable->model(); //define topleft contains row and column; row 0 is tool 0; column is index =0, Name =1, SROMFileName = 2; Type = 3; Status = 4; Node (?) = 5 //only update the changed item mitk::NDIPassiveTool* tool = dynamic_cast (m_Tracker->GetTool(topLeft.row())); if (tool == NULL) return; switch (topLeft.column()) { case QmitkNDIToolDelegate::IndexCol: //index break; case QmitkNDIToolDelegate::NameCol: //name tool->SetToolName(model->data(model->index(topLeft.row(), 1)).toString().toLatin1()); emit ToolsChanged(); break; case QmitkNDIToolDelegate::SROMCol: //SROM File Name { QString romfile = model->data(model->index(topLeft.row(), QmitkNDIToolDelegate::SROMCol)).toString(); if (QFileInfo(romfile).exists()) tool->LoadSROMFile(romfile.toLatin1()); m_Tracker->UpdateTool(tool); break; } //TODO: Add Node Status and Type here as well default: break; } } const QString QmitkNDIConfigurationWidget::GetToolType( unsigned int index ) const { if (m_Controls == NULL) return QString(""); QAbstractItemModel* model = m_Controls->m_ToolTable->model(); QModelIndex modelIndex = model->index(index, QmitkNDIToolDelegate::TypeCol); if (modelIndex.isValid() == false) return QString(""); return model->data(modelIndex).toString(); } const QString QmitkNDIConfigurationWidget::GetToolName( unsigned int index ) const { if (m_Controls == NULL) return QString(""); QAbstractItemModel* model = m_Controls->m_ToolTable->model(); QModelIndex modelIndex = model->index(index, QmitkNDIToolDelegate::NameCol); if (modelIndex.isValid() == false) return QString(""); return model->data(modelIndex).toString(); } QMap QmitkNDIConfigurationWidget::GetToolAndTypes() const { QMap map; if (m_Controls == NULL) return map; QAbstractItemModel* model = m_Controls->m_ToolTable->model(); for (int i = 0; i < model->rowCount(); ++i) { QModelIndex indexIndex = model->index(i, QmitkNDIToolDelegate::IndexCol); QModelIndex typeIndex = model->index(i, QmitkNDIToolDelegate::TypeCol); if ((indexIndex.isValid() == false) || (typeIndex.isValid() == false)) continue; map.insert(model->data(typeIndex).toString(), model->data(indexIndex).toUInt()); } return map; } QList QmitkNDIConfigurationWidget::GetToolsByToolType( QString toolType ) const { QList list; if (m_Controls == NULL) return list; QAbstractItemModel* model = m_Controls->m_ToolTable->model(); for (int i = 0; i < model->rowCount(); ++i) { QModelIndex indexIndex = model->index(i, QmitkNDIToolDelegate::IndexCol); QModelIndex typeIndex = model->index(i, QmitkNDIToolDelegate::TypeCol); if ((indexIndex.isValid() == false) || (typeIndex.isValid() == false)) continue; if (model->data(typeIndex).toString() == toolType) list.append(model->data(indexIndex).toUInt()); } return list; } mitk::DataNode* QmitkNDIConfigurationWidget::GetNode( unsigned int index ) const { if (m_Controls == NULL) return NULL; QAbstractItemModel* model = m_Controls->m_ToolTable->model(); QVariant data = model->data(model->index(index, QmitkNDIToolDelegate::NodeCol), QmitkNDIToolDelegate::OrganNodeRole); return data.value(); } void QmitkNDIConfigurationWidget::HidePolarisOptionsGroupbox( bool on ) { m_Controls->m_gbPolarisOptions->setHidden(on); } void QmitkNDIConfigurationWidget::HideAuroraOptionsGroupbox( bool on ) { m_Controls->m_gbAuroraOptions->setHidden(on); } void QmitkNDIConfigurationWidget::ShowToolRepresentationColumn() { int cols = m_Controls->m_ToolTable->columnCount(); //checking if representation column is inserted at right index if(cols != QmitkNDIToolDelegate::RepCol) { //throw std::exception("Representation Column is not inserted at it's designated index!"); return; } m_Controls->m_ToolTable->insertColumn(cols); // insert new column at end of table m_Controls->m_ToolTable->setHorizontalHeaderItem(QmitkNDIToolDelegate::RepCol, new QTableWidgetItem(QString("Representation"))); // inser column header for new colum //m_Controls->m_ToolTable->setEditTriggers(QAbstractItemView::EditTrigger::NoEditTriggers); int rows = m_Controls->m_ToolTable->rowCount(); // make all representation colum items not editable for(int i=0; i < rows; ++i) { m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::RepCol, new QTableWidgetItem("")); // Representation m_Controls->m_ToolTable->item(i,QmitkNDIToolDelegate::RepCol)->setFlags(Qt::NoItemFlags); } //connect(m_Controls->m_ToolTable, SIGNAL( clicked ( const QModelIndex & )), this, SLOT ( OnTableItemClicked( const QModelIndex & ))); } void QmitkNDIConfigurationWidget::OnDisoverDevicesBtnInfo() { QMessageBox *infoBox = new QMessageBox(this); infoBox->setText("Click \"Scan Ports\" to get a list of all connected NDI tracking devices. This will clear the selection menu below and add the ports for discovered NDI tracking devices. Use this function, if a port is not listed."); infoBox->exec(); delete infoBox; } void QmitkNDIConfigurationWidget::OnTableCellChanged(int row, int column) { if(m_Tracker.IsNull()) return; QString toolName; switch (column) { case QmitkNDIToolDelegate::NameCol: toolName = m_Controls->m_ToolTable->item(row,column)->text(); m_Controls->m_ToolSelectionComboBox->setItemText(row, toolName); emit SignalToolNameChanged(row, toolName); break; default: break; } } void QmitkNDIConfigurationWidget::OnSaveTool() { if(m_Tracker.IsNull() || m_Tracker->GetToolCount() <= 0) return; int currId = m_Controls->m_ToolSelectionComboBox->currentIndex(); QString filename = QFileDialog::getSaveFileName(NULL, "Save NDI-Tool", QString(QString(m_Tracker->GetTool(currId)->GetToolName())),"NDI Tracking Tool file(*.ntf)"); mitk::TrackingTool* selectedTool = m_Tracker->GetTool(currId); if(filename.isEmpty()) return; mitk::NavigationTool::Pointer navTool = mitk::NavigationTool::New(); mitk::NavigationToolWriter::Pointer toolWriter = mitk::NavigationToolWriter::New(); try { toolWriter->DoWrite(filename.toStdString(), this->GenerateNavigationTool(selectedTool)); } catch( ... ) { QMessageBox::warning(NULL, "Saving Tool Error", QString("An error occured! Could not save tool!\n\n")); MBI_ERROR<<"Could not save tool surface!"; MBI_ERROR<< toolWriter->GetErrorMessage(); QFile maybeCorruptFile(filename); if(maybeCorruptFile.exists()) maybeCorruptFile.remove(); } emit SignalSavedTool(currId, filename); } void QmitkNDIConfigurationWidget::OnLoadTool() { if(m_Tracker.IsNull() || m_Tracker->GetToolCount() <= 0) return; QString filename = QFileDialog::getOpenFileName(NULL, "Load NDI-Tools", QDir::currentPath(),"NDI Tracking Tool file(*.ntf)"); int currId = m_Controls->m_ToolSelectionComboBox->currentIndex(); if(filename.isEmpty()) return; mitk::DataNode::Pointer toolNode; mitk::NavigationToolReader::Pointer toolReader = mitk::NavigationToolReader::New(); mitk::NavigationTool::Pointer navTool; try { navTool = toolReader->DoRead(filename.toStdString()); } catch( ... ) { QMessageBox::warning(NULL, "Loading Tool Error", QString("An error occured! Could not load tool!\n\n")); MBI_ERROR<<"Could not load tool surface!"; MBI_ERROR<< toolReader->GetErrorMessage(); } int currSelectedToolID = m_Controls->m_ToolSelectionComboBox->currentIndex(); // name m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::NameCol)->setText(navTool->GetToolName().c_str()); dynamic_cast(m_Tracker->GetTool(currSelectedToolID))->SetToolName(navTool->GetToolName().c_str()); // also setting name to tool directly //calibration file (.srom) filename m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::SROMCol)->setText(navTool->GetCalibrationFile().c_str()); //type if(navTool->GetType() == mitk::NavigationTool::Instrument) m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->setText("Instrument"); else if(navTool->GetType() == mitk::NavigationTool::Fiducial) m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->setText("Fiducial"); else if(navTool->GetType() == mitk::NavigationTool::Skinmarker) m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->setText("Skinmarker"); else m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->setText("Unknown"); //representation m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::SROMCol)->setText(m_RepresentatonCellDefaultText); emit SignalLoadTool(currId, navTool->GetDataNode()); } mitk::NavigationTool::Pointer QmitkNDIConfigurationWidget::GenerateNavigationTool(mitk::TrackingTool* tool) { mitk::NavigationTool::Pointer navTool = mitk::NavigationTool::New(); mitk::NDIPassiveTool::Pointer passiveTool = dynamic_cast(tool); if(passiveTool.IsNull()) throw std::runtime_error("Could not cast TrackingTool to PassiveTool"); int currSelectedToolID = m_Controls->m_ToolSelectionComboBox->currentIndex(); QString sromFileName = m_Controls->m_ToolTable->item(currSelectedToolID, QmitkNDIToolDelegate::SROMCol)->text(); QString surfaceFileName = m_Controls->m_ToolTable->item(currSelectedToolID, QmitkNDIToolDelegate::RepCol)->text(); //calibration file (.srom) filename QFile sromFile(sromFileName); if(sromFile.exists()) navTool->SetCalibrationFile(sromFileName.toStdString()); //serial number navTool->SetSerialNumber(passiveTool->GetSerialNumber()); // name and surface as dataNode mitk::DataNode::Pointer node = mitk::DataNode::New(); mitk::Surface::Pointer toolSurface; try{ toolSurface = this->LoadSurfaceFromSTLFile(surfaceFileName); } catch( ... ) { QMessageBox::warning(NULL, "Loading Surface Error", QString("An error occured! Could not load surface from .stl file!\n\n")); MBI_ERROR<<"Could not load .stl tool surface!"; } if(toolSurface.IsNotNull()) { node->SetData(toolSurface); node->SetName(tool->GetToolName()); } navTool->SetDataNode(node); // type mitk::NavigationTool::NavigationToolType type; QString currentToolType = m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->text(); if(currentToolType.compare("Instrument") == 0) type = mitk::NavigationTool::Instrument; else if(currentToolType.compare("Fiducial") == 0) type = mitk::NavigationTool::Fiducial; else if(currentToolType.compare("Skinmarker") == 0) type = mitk::NavigationTool::Skinmarker; else type = mitk::NavigationTool::Unknown; navTool->SetType(type); return navTool; } mitk::Surface::Pointer QmitkNDIConfigurationWidget::LoadSurfaceFromSTLFile(QString surfaceFilename) { mitk::Surface::Pointer toolSurface; QFile surfaceFile(surfaceFilename); if(surfaceFile.exists()) { - mitk::STLFileReader::Pointer stlReader = mitk::STLFileReader::New(); - try{ - stlReader->SetFileName(surfaceFilename.toStdString().c_str()); - stlReader->Update();//load surface - toolSurface = stlReader->GetOutput(); + toolSurface = mitk::IOUtil::LoadSurface(surfaceFilename.toStdString().c_str()); } catch(std::exception& e ) { MBI_ERROR<<"Could not load surface for tool!"; MBI_ERROR<< e.what(); throw e; } } return toolSurface; } void QmitkNDIConfigurationWidget::EnableAddToolsButton(bool enable) { m_Controls->m_AddToolBtn->setEnabled(enable); } void QmitkNDIConfigurationWidget::EnableDiscoverNewToolsButton(bool enable) { m_Controls->m_DiscoverToolsBtn->setEnabled(enable); } diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp index 7afb644a11..df6e5f0fbf 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp @@ -1,346 +1,336 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkNavigationToolCreationWidget.h" //mitk headers #include -#include #include #include #include //qt headers #include #include #include +#include //poco headers #include // vtk #include #include const std::string QmitkNavigationToolCreationWidget::VIEW_ID = "org.mitk.views.navigationtoolcreationwizardwidget"; QmitkNavigationToolCreationWidget::QmitkNavigationToolCreationWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = NULL; m_AdvancedWidget = new QmitkNavigationToolCreationAdvancedWidget(this); m_AdvancedWidget->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); m_AdvancedWidget->setWindowTitle("Tool Creation Advanced Options"); m_AdvancedWidget->setModal(false); CreateQtPartControl(this); CreateConnections(); } QmitkNavigationToolCreationWidget::~QmitkNavigationToolCreationWidget() { m_Controls->m_CalibrationLandmarksList->SetPointSetNode(NULL); m_Controls->m_RegistrationLandmarksList->SetPointSetNode(NULL); delete m_AdvancedWidget; } void QmitkNavigationToolCreationWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNavigationToolCreationWidgetControls; m_Controls->setupUi(parent); } } void QmitkNavigationToolCreationWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_cancel), SIGNAL(clicked()), this, SLOT(OnCancel()) ); connect( (QObject*)(m_Controls->m_finished), SIGNAL(clicked()), this, SLOT(OnFinished()) ); connect( (QObject*)(m_Controls->m_LoadSurface), SIGNAL(clicked()), this, SLOT(OnLoadSurface()) ); connect( (QObject*)(m_Controls->m_LoadCalibrationFile), SIGNAL(clicked()), this, SLOT(OnLoadCalibrationFile()) ); connect( (QObject*)(m_Controls->m_ShowAdvancedOptionsPB), SIGNAL(toggled(bool)), this, SLOT(OnShowAdvancedOptions(bool)) ); connect( (QObject*)(m_AdvancedWidget), SIGNAL(DialogCloseRequested()), this, SLOT(OnProcessDialogCloseRequest()) ); connect( (QObject*)(m_AdvancedWidget), SIGNAL(RetrieveDataForManualToolTipManipulation()), this, SLOT(OnRetrieveDataForManualTooltipManipulation()) ); connect( m_Controls->m_Surface_Use_Other, SIGNAL(toggled(bool)), this, SLOT(OnSurfaceUseOtherToggled(bool))); } } void QmitkNavigationToolCreationWidget::Initialize(mitk::DataStorage* dataStorage, std::string supposedIdentifier, std::string supposedName) { m_DataStorage = dataStorage; //initialize UI components m_Controls->m_SurfaceChooser->SetDataStorage(m_DataStorage); m_Controls->m_SurfaceChooser->SetAutoSelectNewItems(true); m_Controls->m_SurfaceChooser->SetPredicate(mitk::NodePredicateDataType::New("Surface")); //set default data m_Controls->m_ToolNameEdit->setText(supposedName.c_str()); m_Controls->m_CalibrationFileName->setText("none"); m_Controls->m_Surface_Use_Sphere->setChecked(true); m_AdvancedWidget->SetDataStorage(m_DataStorage); m_Controls->m_IdentifierEdit->setText(supposedIdentifier.c_str()); this->InitializeUIToolLandmarkLists(); m_Controls->m_CalibrationLandmarksList->EnableEditButton(false); m_Controls->m_RegistrationLandmarksList->EnableEditButton(false); } void QmitkNavigationToolCreationWidget::SetTrackingDeviceType(mitk::TrackingDeviceType type, bool changeable) { switch(type) { case mitk::NDIAurora: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0);break; case mitk::NDIPolaris: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(1);break; case mitk::ClaronMicron: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(2);break; case mitk::NPOptitrack: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(3);break; case mitk::VirtualTracker: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(4);break; default: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(4); } m_Controls->m_TrackingDeviceTypeChooser->setEnabled(changeable); } mitk::NavigationTool::Pointer QmitkNavigationToolCreationWidget::GetCreatedTool() { return m_CreatedTool; } //################################################################################## //############################## slots ############################ //################################################################################## void QmitkNavigationToolCreationWidget::OnFinished() { //here we create a new tool m_CreatedTool = mitk::NavigationTool::New(); //create DataNode... mitk::DataNode::Pointer newNode = mitk::DataNode::New(); if(m_Controls->m_Surface_Use_Sphere->isChecked()) { //create small sphere and use it as surface mitk::Surface::Pointer mySphere = mitk::Surface::New(); vtkConeSource *vtkData = vtkConeSource::New(); vtkData->SetAngle(5.0); vtkData->SetResolution(50); vtkData->SetHeight(6.0f); vtkData->SetRadius(2.0f); vtkData->SetCenter(0.0, 0.0, 0.0); vtkData->Update(); mySphere->SetVtkPolyData(vtkData->GetOutput()); vtkData->Delete(); newNode->SetData(mySphere); } else { newNode->SetData(m_Controls->m_SurfaceChooser->GetSelectedNode()->GetData()); } newNode->SetName(m_Controls->m_ToolNameEdit->text().toLatin1()); m_CreatedTool->SetDataNode(newNode); //fill NavigationTool object m_CreatedTool->SetCalibrationFile(m_Controls->m_CalibrationFileName->text().toLatin1().data()); m_CreatedTool->SetIdentifier(m_Controls->m_IdentifierEdit->text().toLatin1().data()); m_CreatedTool->SetSerialNumber(m_Controls->m_SerialNumberEdit->text().toLatin1().data()); //Tracking Device if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="NDI Aurora") m_CreatedTool->SetTrackingDeviceType(mitk::NDIAurora); else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="NDI Polaris") m_CreatedTool->SetTrackingDeviceType(mitk::NDIPolaris); else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="CT MicronTracker") m_CreatedTool->SetTrackingDeviceType(mitk::ClaronMicron); else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="NP Optitrack") m_CreatedTool->SetTrackingDeviceType(mitk::NPOptitrack); else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="Virtual Tracker") m_CreatedTool->SetTrackingDeviceType(mitk::VirtualTracker); else m_CreatedTool->SetTrackingDeviceType(mitk::TrackingSystemNotSpecified); //ToolType if (m_Controls->m_ToolTypeChooser->currentText()=="Instrument") m_CreatedTool->SetType(mitk::NavigationTool::Instrument); else if (m_Controls->m_ToolTypeChooser->currentText()=="Fiducial") m_CreatedTool->SetType(mitk::NavigationTool::Fiducial); else if (m_Controls->m_ToolTypeChooser->currentText()=="Skinmarker") m_CreatedTool->SetType(mitk::NavigationTool::Skinmarker); else m_CreatedTool->SetType(mitk::NavigationTool::Unknown); //Tool Tip mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(m_AdvancedWidget->GetManipulatedToolTip()); m_CreatedTool->SetToolTipOrientation(tempND->GetOrientation()); m_CreatedTool->SetToolTipPosition(tempND->GetPosition()); //Tool Landmarks mitk::PointSet::Pointer toolCalLandmarks, toolRegLandmarks; GetUIToolLandmarksLists(toolCalLandmarks,toolRegLandmarks); m_CreatedTool->SetToolCalibrationLandmarks(toolCalLandmarks); m_CreatedTool->SetToolRegistrationLandmarks(toolRegLandmarks); emit NavigationToolFinished(); } void QmitkNavigationToolCreationWidget::OnCancel() { m_CreatedTool = NULL; emit Canceled(); } void QmitkNavigationToolCreationWidget::OnLoadSurface() { -std::string filename = QFileDialog::getOpenFileName(NULL,tr("Open Surface"), "/", tr("STL (*.stl)")).toLatin1().data(); -mitk::STLFileReader::Pointer stlReader = mitk::STLFileReader::New(); -try -{ -stlReader->SetFileName( filename.c_str() ); -stlReader->Update(); -} -catch (...) -{ -} - -if ( stlReader->GetOutput() == NULL ); -else -{ -mitk::DataNode::Pointer newNode = mitk::DataNode::New(); -newNode->SetName(filename); -newNode->SetData(stlReader->GetOutput()); -m_DataStorage->Add(newNode); -} + std::string filename = QFileDialog::getOpenFileName(NULL,tr("Open Surface"), "/", tr("STL (*.stl)")).toLatin1().data(); + try + { + mitk::IOUtil::Load(filename.c_str(), *m_DataStorage); + } + catch (mitk::Exception &e) + { + MITK_ERROR << "Exception occured: " << e.what(); + } } void QmitkNavigationToolCreationWidget::OnLoadCalibrationFile() { m_Controls->m_CalibrationFileName->setText(QFileDialog::getOpenFileName(NULL,tr("Open Calibration File"), "/", "*.*")); } void QmitkNavigationToolCreationWidget::SetDefaultData(mitk::NavigationTool::Pointer DefaultTool) { m_Controls->m_ToolNameEdit->setText(QString(DefaultTool->GetDataNode()->GetName().c_str())); m_Controls->m_IdentifierEdit->setText(QString(DefaultTool->GetIdentifier().c_str())); m_Controls->m_SerialNumberEdit->setText(QString(DefaultTool->GetSerialNumber().c_str())); m_AdvancedWidget->SetDefaultTooltip( DefaultTool->GetToolTipTransform() ); switch(DefaultTool->GetTrackingDeviceType()) { case mitk::NDIAurora: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0);break; case mitk::NDIPolaris: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(1);break; case mitk::ClaronMicron: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(2);break; case mitk::NPOptitrack: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(3);break; case mitk::VirtualTracker: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(4);break; default: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0); } m_Controls->m_CalibrationFileName->setText(QString(DefaultTool->GetCalibrationFile().c_str())); m_Controls->m_Surface_Use_Other->setChecked(true); switch(DefaultTool->GetType()) { case mitk::NavigationTool::Instrument: m_Controls->m_ToolTypeChooser->setCurrentIndex(0); break; case mitk::NavigationTool::Fiducial: m_Controls->m_ToolTypeChooser->setCurrentIndex(1); break; case mitk::NavigationTool::Skinmarker: m_Controls->m_ToolTypeChooser->setCurrentIndex(2); break; case mitk::NavigationTool::Unknown: m_Controls->m_ToolTypeChooser->setCurrentIndex(3); break; } m_Controls->m_SurfaceChooser->SetSelectedNode(DefaultTool->GetDataNode()); FillUIToolLandmarkLists(DefaultTool->GetToolCalibrationLandmarks(),DefaultTool->GetToolRegistrationLandmarks()); } //################################################################################## //############################## internal help methods ############################# //################################################################################## void QmitkNavigationToolCreationWidget::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } void QmitkNavigationToolCreationWidget::OnShowAdvancedOptions(bool state) { if(state) { m_AdvancedWidget->show(); m_AdvancedWidget->SetDefaultTooltip(m_AdvancedWidget->GetManipulatedToolTip()); //use the last one, if there is one m_AdvancedWidget->ReInitialize(); // reinit the views with the new nodes mitk::DataStorage::SetOfObjects::ConstPointer rs = m_DataStorage->GetAll(); mitk::TimeGeometry::Pointer bounds = m_DataStorage->ComputeBoundingGeometry3D(rs, "visible"); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } else { m_AdvancedWidget->hide(); } } void QmitkNavigationToolCreationWidget::OnProcessDialogCloseRequest() { m_AdvancedWidget->hide(); m_Controls->m_ShowAdvancedOptionsPB->setChecked(false); } void QmitkNavigationToolCreationWidget::OnRetrieveDataForManualTooltipManipulation() { if(m_Controls->m_Surface_Use_Sphere->isChecked()) { m_AdvancedWidget->SetToolTipSurface(true); } else { m_AdvancedWidget->SetToolTipSurface(false, dynamic_cast(m_Controls->m_SurfaceChooser->GetSelectedNode().GetPointer())); } } void QmitkNavigationToolCreationWidget::OnSurfaceUseOtherToggled(bool checked) { m_Controls->m_LoadSurface->setEnabled(checked); } void QmitkNavigationToolCreationWidget::FillUIToolLandmarkLists(mitk::PointSet::Pointer calLandmarks, mitk::PointSet::Pointer regLandmarks) { m_calLandmarkNode->SetData(calLandmarks); m_regLandmarkNode->SetData(regLandmarks); m_Controls->m_CalibrationLandmarksList->SetPointSetNode(m_calLandmarkNode); m_Controls->m_RegistrationLandmarksList->SetPointSetNode(m_regLandmarkNode); } void QmitkNavigationToolCreationWidget::GetUIToolLandmarksLists(mitk::PointSet::Pointer& calLandmarks, mitk::PointSet::Pointer& regLandmarks) { calLandmarks = dynamic_cast(m_calLandmarkNode->GetData()); regLandmarks = dynamic_cast(m_regLandmarkNode->GetData()); } void QmitkNavigationToolCreationWidget::InitializeUIToolLandmarkLists() { m_calLandmarkNode = mitk::DataNode::New(); m_regLandmarkNode = mitk::DataNode::New(); FillUIToolLandmarkLists(mitk::PointSet::New(),mitk::PointSet::New()); } diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp index 37d457de5d..5392564062 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp @@ -1,359 +1,358 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkNavigationToolManagementWidget.h" //mitk headers #include "mitkTrackingTypes.h" -#include #include #include #include #include #include #include //qt headers #include #include #include //poco headers #include const std::string QmitkNavigationToolManagementWidget::VIEW_ID = "org.mitk.views.navigationtoolmanagementwidget"; QmitkNavigationToolManagementWidget::QmitkNavigationToolManagementWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = NULL; CreateQtPartControl(this); CreateConnections(); } QmitkNavigationToolManagementWidget::~QmitkNavigationToolManagementWidget() { } void QmitkNavigationToolManagementWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNavigationToolManagementWidgetControls; m_Controls->setupUi(parent); } //Disable StorageControls in the beginning, because there is no storage to edit DisableStorageControls(); } void QmitkNavigationToolManagementWidget::OnLoadTool() { if(m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } mitk::NavigationToolReader::Pointer myReader = mitk::NavigationToolReader::New(); std::string filename = QFileDialog::getOpenFileName(NULL,tr("Add Navigation Tool"), "/", "*.IGTTool").toLatin1().data(); if (filename == "") return; mitk::NavigationTool::Pointer readTool = myReader->DoRead(filename); if (readTool.IsNull()) MessageBox("Error: " + myReader->GetErrorMessage()); else { if (!m_NavigationToolStorage->AddTool(readTool)) { MessageBox("Error: Can't add tool!"); m_DataStorage->Remove(readTool->GetDataNode()); } UpdateToolTable(); } } void QmitkNavigationToolManagementWidget::OnSaveTool() { //if no item is selected, show error message: if (m_Controls->m_ToolList->currentItem() == NULL) {MessageBox("Error: Please select tool first!");return;} mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); std::string filename = QFileDialog::getSaveFileName(NULL,tr("Save Navigation Tool"), "/", "*.IGTTool").toLatin1().data(); if (filename == "") return; if (!myWriter->DoWrite(filename,m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row()))) MessageBox("Error: "+ myWriter->GetErrorMessage()); } void QmitkNavigationToolManagementWidget::CreateConnections() { if ( m_Controls ) { //main widget page: connect( (QObject*)(m_Controls->m_AddTool), SIGNAL(clicked()), this, SLOT(OnAddTool()) ); connect( (QObject*)(m_Controls->m_DeleteTool), SIGNAL(clicked()), this, SLOT(OnDeleteTool()) ); connect( (QObject*)(m_Controls->m_EditTool), SIGNAL(clicked()), this, SLOT(OnEditTool()) ); connect( (QObject*)(m_Controls->m_LoadStorage), SIGNAL(clicked()), this, SLOT(OnLoadStorage()) ); connect( (QObject*)(m_Controls->m_SaveStorage), SIGNAL(clicked()), this, SLOT(OnSaveStorage()) ); connect( (QObject*)(m_Controls->m_LoadTool), SIGNAL(clicked()), this, SLOT(OnLoadTool()) ); connect( (QObject*)(m_Controls->m_SaveTool), SIGNAL(clicked()), this, SLOT(OnSaveTool()) ); connect( (QObject*)(m_Controls->m_CreateNewStorage), SIGNAL(clicked()), this, SLOT(OnCreateStorage()) ); //widget page "add tool": connect( (QObject*)(m_Controls->m_ToolCreationWidget), SIGNAL(Canceled()), this, SLOT(OnAddToolCancel()) ); connect( (QObject*)(m_Controls->m_ToolCreationWidget), SIGNAL(NavigationToolFinished()), this, SLOT(OnAddToolSave()) ); } } void QmitkNavigationToolManagementWidget::Initialize(mitk::DataStorage* dataStorage) { m_DataStorage = dataStorage; m_Controls->m_ToolCreationWidget->Initialize(m_DataStorage,"Tool0"); } void QmitkNavigationToolManagementWidget::LoadStorage(mitk::NavigationToolStorage::Pointer storageToLoad) { if(storageToLoad.IsNotNull()) { m_NavigationToolStorage = storageToLoad; m_Controls->m_StorageName->setText(m_NavigationToolStorage->GetName().c_str()); EnableStorageControls(); } else { m_NavigationToolStorage = NULL; DisableStorageControls(); } UpdateToolTable(); } //################################################################################## //############################## slots: main widget ################################ //################################################################################## void QmitkNavigationToolManagementWidget::OnAddTool() { if(m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } QString defaultIdentifier = "NavigationTool#"+QString::number(m_NavigationToolStorage->GetToolCount()); m_Controls->m_ToolCreationWidget->Initialize(m_DataStorage,defaultIdentifier.toStdString()); m_edit = false; m_Controls->m_MainWidgets->setCurrentIndex(1); } void QmitkNavigationToolManagementWidget::OnDeleteTool() { //first: some checks if(m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } else if (m_Controls->m_ToolList->currentItem() == NULL) //if no item is selected, show error message: { MessageBox("Error: Please select tool first!"); return; } m_DataStorage->Remove(m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row())->GetDataNode()); m_NavigationToolStorage->DeleteTool(m_Controls->m_ToolList->currentIndex().row()); UpdateToolTable(); } void QmitkNavigationToolManagementWidget::OnEditTool() { if(m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } else if (m_Controls->m_ToolList->currentItem() == NULL) //if no item is selected, show error message: { MessageBox("Error: Please select tool first!"); return; } mitk::NavigationTool::Pointer selectedTool = m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row()); m_Controls->m_ToolCreationWidget->SetDefaultData(selectedTool); m_edit = true; m_Controls->m_MainWidgets->setCurrentIndex(1); } void QmitkNavigationToolManagementWidget::OnCreateStorage() { QString storageName = QInputDialog::getText(NULL,"Storage Name","Name of the new tool storage:"); if (storageName.isNull()) return; m_NavigationToolStorage = mitk::NavigationToolStorage::New(this->m_DataStorage); m_NavigationToolStorage->SetName(storageName.toStdString()); m_Controls->m_StorageName->setText(m_NavigationToolStorage->GetName().c_str()); EnableStorageControls(); emit NewStorageAdded(m_NavigationToolStorage, storageName.toStdString()); } void QmitkNavigationToolManagementWidget::OnLoadStorage() { mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(m_DataStorage); std::string filename = QFileDialog::getOpenFileName(NULL, tr("Open Navigation Tool Storage"), "/", tr("IGT Tool Storage (*.IGTToolStorage)")).toStdString(); if (filename == "") return; try { mitk::NavigationToolStorage::Pointer tempStorage = myDeserializer->Deserialize(filename); if (tempStorage.IsNull()) MessageBox("Error" + myDeserializer->GetErrorMessage()); else { Poco::Path myPath = Poco::Path(filename.c_str()); tempStorage->SetName(myPath.getFileName()); //set the filename as name for the storage, so the user can identify it this->LoadStorage(tempStorage); emit NewStorageAdded(m_NavigationToolStorage,myPath.getFileName()); } } catch (const mitk::Exception& exception) { MessageBox(exception.GetDescription()); } } void QmitkNavigationToolManagementWidget::OnSaveStorage() { //read in filename QString filename = QFileDialog::getSaveFileName(NULL, tr("Save Navigation Tool Storage"), "/", tr("IGT Tool Storage (*.IGTToolStorage)")); if (filename.isEmpty()) return; //canceled by the user // add file extension if it wasn't added by the file dialog if ( filename.right(15) != ".IGTToolStorage" ) { filename += ".IGTToolStorage"; } //serialize tool storage mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); if (!mySerializer->Serialize(filename.toStdString(),m_NavigationToolStorage)) { MessageBox("Error: " + mySerializer->GetErrorMessage()); return; } Poco::Path myPath = Poco::Path(filename.toStdString()); m_Controls->m_StorageName->setText(QString::fromStdString(myPath.getFileName())); } //################################################################################## //############################## slots: add tool widget ############################ //################################################################################## void QmitkNavigationToolManagementWidget::OnAddToolSave() { mitk::NavigationTool::Pointer newTool = m_Controls->m_ToolCreationWidget->GetCreatedTool(); if (m_edit) //here we edit a existing tool { mitk::NavigationTool::Pointer editedTool = m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row()); editedTool->Graft(newTool); } else //here we create a new tool { m_NavigationToolStorage->AddTool(newTool); } UpdateToolTable(); m_Controls->m_MainWidgets->setCurrentIndex(0); } void QmitkNavigationToolManagementWidget::OnAddToolCancel() { m_Controls->m_MainWidgets->setCurrentIndex(0); } //################################################################################## //############################## private help methods ############################## //################################################################################## void QmitkNavigationToolManagementWidget::UpdateToolTable() { m_Controls->m_ToolList->clear(); if(m_NavigationToolStorage.IsNull()) return; for(int i=0; iGetToolCount(); i++) { QString currentTool = "Tool" + QString::number(i) + ": " + QString(m_NavigationToolStorage->GetTool(i)->GetDataNode()->GetName().c_str())+ " "; switch (m_NavigationToolStorage->GetTool(i)->GetTrackingDeviceType()) { case mitk::ClaronMicron: currentTool += "(MicronTracker/"; break; case mitk::NDIAurora: currentTool += "(NDI Aurora/"; break; case mitk::NDIPolaris: currentTool += "(NDI Polaris/"; break; case mitk::NPOptitrack: currentTool += "(NP Optitrack/"; break; case mitk::VirtualTracker: currentTool += "(Virtual Tracker/"; break; default: currentTool += "(unknown tracking system/"; break; } switch (m_NavigationToolStorage->GetTool(i)->GetType()) { case mitk::NavigationTool::Instrument: currentTool += "Instrument)"; break; case mitk::NavigationTool::Fiducial: currentTool += "Fiducial)"; break; case mitk::NavigationTool::Skinmarker: currentTool += "Skinmarker)"; break; default: currentTool += "Unknown)"; } m_Controls->m_ToolList->addItem(currentTool); } } void QmitkNavigationToolManagementWidget::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } void QmitkNavigationToolManagementWidget::DisableStorageControls() { m_Controls->m_StorageName->setText(""); m_Controls->m_AddTool->setEnabled(false); m_Controls->m_LoadTool->setEnabled(false); m_Controls->m_selectedLabel->setEnabled(false); m_Controls->m_DeleteTool->setEnabled(false); m_Controls->m_EditTool->setEnabled(false); m_Controls->m_SaveTool->setEnabled(false); m_Controls->m_ToolList->setEnabled(false); m_Controls->m_SaveStorage->setEnabled(false); m_Controls->m_ToolLabel->setEnabled(false); } void QmitkNavigationToolManagementWidget::EnableStorageControls() { m_Controls->m_AddTool->setEnabled(true); m_Controls->m_LoadTool->setEnabled(true); m_Controls->m_selectedLabel->setEnabled(true); m_Controls->m_DeleteTool->setEnabled(true); m_Controls->m_EditTool->setEnabled(true); m_Controls->m_SaveTool->setEnabled(true); m_Controls->m_ToolList->setEnabled(true); m_Controls->m_SaveStorage->setEnabled(true); m_Controls->m_ToolLabel->setEnabled(true); } diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolStorageSelectionWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkNavigationToolStorageSelectionWidgetControls.ui index af246a91db..2c4bc42225 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolStorageSelectionWidgetControls.ui +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolStorageSelectionWidgetControls.ui @@ -1,40 +1,38 @@ QmitkNavigationToolStorageSelectionWidgetControls 0 0 199 111 Form - + 0 0 QmitkServiceListWidget QListWidget
QmitkServiceListWidget.h
- - - +
diff --git a/Modules/ImageStatistics/Testing/mitkImageStatisticsCalculatorTest.cpp b/Modules/ImageStatistics/Testing/mitkImageStatisticsCalculatorTest.cpp index 69d7a086a9..9c4f24c6c2 100644 --- a/Modules/ImageStatistics/Testing/mitkImageStatisticsCalculatorTest.cpp +++ b/Modules/ImageStatistics/Testing/mitkImageStatisticsCalculatorTest.cpp @@ -1,418 +1,412 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "mitkTestFixture.h" -#include "mitkTestingMacros.h" - #include "mitkImageStatisticsCalculator.h" -#include "mitkPlanarPolygon.h" - -#include "mitkClassicDICOMSeriesReader.h" - -#include "vtkStreamingDemandDrivenPipeline.h" - -#include +#include +#include +#include +#include +#include #include - /** * \brief Test class for mitkImageStatisticsCalculator * * This test covers: * - instantiation of an ImageStatisticsCalculator class * - correctness of statistics when using PlanarFigures for masking */ class mitkImageStatisticsCalculatorTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkImageStatisticsCalculatorTestSuite); MITK_TEST(TestUninitializedImage); MITK_TEST(TestCase1); MITK_TEST(TestCase2); MITK_TEST(TestCase3); MITK_TEST(TestCase4); MITK_TEST(TestCase5); MITK_TEST(TestCase6); MITK_TEST(TestCase7); MITK_TEST(TestCase8); MITK_TEST(TestCase9); MITK_TEST(TestCase10); MITK_TEST(TestCase11); MITK_TEST(TestCase12); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void TestUninitializedImage(); void TestCase1(); void TestCase2(); void TestCase3(); void TestCase4(); void TestCase5(); void TestCase6(); void TestCase7(); void TestCase8(); void TestCase9(); void TestCase10(); void TestCase11(); void TestCase12(); private: mitk::Image::Pointer m_Image; mitk::PlaneGeometry::Pointer m_Geometry; // calculate statistics for the given image and planarpolygon const mitk::ImageStatisticsCalculator::Statistics ComputeStatistics( mitk::Image::Pointer image, mitk::PlanarFigure::Pointer polygon ); void VerifyStatistics(const mitk::ImageStatisticsCalculator::Statistics& stats, double testMean, double testSD); }; void mitkImageStatisticsCalculatorTestSuite::setUp() { std::string filename = this->GetTestDataFilePath("ImageStatistics/testimage.dcm"); if (filename.empty()) { MITK_TEST_FAILED_MSG( << "Could not find test file" ) } MITK_TEST_OUTPUT(<< "Loading test image '" << filename << "'") mitk::StringList files; files.push_back( filename ); mitk::ClassicDICOMSeriesReader::Pointer reader = mitk::ClassicDICOMSeriesReader::New(); reader->SetInputFiles( files ); reader->AnalyzeInputFiles(); reader->LoadImages(); MITK_TEST_CONDITION_REQUIRED( reader->GetNumberOfOutputs() == 1, "Loaded one result from file" ); m_Image = reader->GetOutput(0).GetMitkImage(); MITK_TEST_CONDITION_REQUIRED( m_Image.IsNotNull(), "Loaded an mitk::Image" ); m_Geometry = m_Image->GetSlicedGeometry()->GetPlaneGeometry(0); MITK_TEST_CONDITION_REQUIRED( m_Geometry.IsNotNull(), "Getting image geometry" ) } void mitkImageStatisticsCalculatorTestSuite::TestCase1() { /***************************** * one whole white pixel * -> mean of 255 expected ******************************/ mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New(); figure1->SetPlaneGeometry( m_Geometry ); mitk::Point2D pnt1; pnt1[0] = 10.5 ; pnt1[1] = 3.5; figure1->PlaceFigure( pnt1 ); mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5; figure1->SetControlPoint( 1, pnt2, true ); mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5; figure1->SetControlPoint( 2, pnt3, true ); mitk::Point2D pnt4; pnt4[0] = 10.5; pnt4[1] = 4.5; figure1->SetControlPoint( 3, pnt4, true ); figure1->GetPolyLine(0); this->VerifyStatistics(ComputeStatistics(m_Image, figure1.GetPointer()), 255.0, 0.0); } void mitkImageStatisticsCalculatorTestSuite::TestCase2() { /***************************** * half pixel in x-direction (white) * -> mean of 255 expected ******************************/ mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New(); figure1->SetPlaneGeometry( m_Geometry ); mitk::Point2D pnt1; pnt1[0] = 10.0 ; pnt1[1] = 3.5; figure1->PlaceFigure( pnt1 ); mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5; figure1->SetControlPoint( 1, pnt2, true ); mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5; figure1->SetControlPoint( 2, pnt3, true ); mitk::Point2D pnt4; pnt4[0] = 10.0; pnt4[1] = 4.5; figure1->SetControlPoint( 3, pnt4, true ); figure1->GetPolyLine(0); this->VerifyStatistics(ComputeStatistics(m_Image, figure1.GetPointer()), 255.0, 0.0); } void mitkImageStatisticsCalculatorTestSuite::TestCase3() { /***************************** * half pixel in diagonal-direction (white) * -> mean of 255 expected ******************************/ mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New(); figure1->SetPlaneGeometry( m_Geometry ); mitk::Point2D pnt1; pnt1[0] = 10.5 ; pnt1[1] = 3.5; figure1->PlaceFigure( pnt1 ); mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5; figure1->SetControlPoint( 1, pnt2, true ); mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5; figure1->SetControlPoint( 2, pnt3, true ); figure1->GetPolyLine(0); this->VerifyStatistics(ComputeStatistics(m_Image, figure1.GetPointer()), 255.0, 0.0); } void mitkImageStatisticsCalculatorTestSuite::TestCase4() { /***************************** * one pixel (white) + 2 half pixels (white) + 1 half pixel (black) * -> mean of 191.25 expected ******************************/ mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New(); figure1->SetPlaneGeometry( m_Geometry ); mitk::Point2D pnt1; pnt1[0] = 1.1; pnt1[1] = 1.1; figure1->PlaceFigure( pnt1 ); mitk::Point2D pnt2; pnt2[0] = 2.0; pnt2[1] = 2.0; figure1->SetControlPoint( 1, pnt2, true ); mitk::Point2D pnt3; pnt3[0] = 3.0; pnt3[1] = 1.0; figure1->SetControlPoint( 2, pnt3, true ); mitk::Point2D pnt4; pnt4[0] = 2.0; pnt4[1] = 0.0; figure1->SetControlPoint( 3, pnt4, true ); figure1->GetPolyLine(0); this->VerifyStatistics(ComputeStatistics(m_Image, figure1.GetPointer()), 191.25, 127.5); } void mitkImageStatisticsCalculatorTestSuite::TestCase5() { /***************************** * whole pixel (white) + half pixel (gray) in x-direction * -> mean of 191.5 expected ******************************/ mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New(); figure1->SetPlaneGeometry( m_Geometry ); mitk::Point2D pnt1; pnt1[0] = 11.0; pnt1[1] = 3.5; figure1->PlaceFigure( pnt1 ); mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5; figure1->SetControlPoint( 1, pnt2, true ); mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5; figure1->SetControlPoint( 2, pnt3, true ); mitk::Point2D pnt4; pnt4[0] = 11.0; pnt4[1] = 4.5; figure1->SetControlPoint( 3, pnt4, true ); figure1->GetPolyLine(0); this->VerifyStatistics(ComputeStatistics(m_Image, figure1.GetPointer()), 191.50, 89.80); } void mitkImageStatisticsCalculatorTestSuite::TestCase6() { /***************************** * quarter pixel (black) + whole pixel (white) + half pixel (gray) in x-direction * -> mean of 191.5 expected ******************************/ mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New(); figure1->SetPlaneGeometry( m_Geometry ); mitk::Point2D pnt1; pnt1[0] = 11.0; pnt1[1] = 3.5; figure1->PlaceFigure( pnt1 ); mitk::Point2D pnt2; pnt2[0] = 9.25; pnt2[1] = 3.5; figure1->SetControlPoint( 1, pnt2, true ); mitk::Point2D pnt3; pnt3[0] = 9.25; pnt3[1] = 4.5; figure1->SetControlPoint( 2, pnt3, true ); mitk::Point2D pnt4; pnt4[0] = 11.0; pnt4[1] = 4.5; figure1->SetControlPoint( 3, pnt4, true ); figure1->GetPolyLine(0); this->VerifyStatistics(ComputeStatistics(m_Image, figure1.GetPointer()), 191.5, 89.80); } void mitkImageStatisticsCalculatorTestSuite::TestCase7() { /***************************** * half pixel (black) + whole pixel (white) + half pixel (gray) in x-direction * -> mean of 127.66 expected ******************************/ mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New(); figure1->SetPlaneGeometry( m_Geometry ); mitk::Point2D pnt1; pnt1[0] = 11.0; pnt1[1] = 3.5; figure1->PlaceFigure( pnt1 ); mitk::Point2D pnt2; pnt2[0] = 9.0; pnt2[1] = 3.5; figure1->SetControlPoint( 1, pnt2, true ); mitk::Point2D pnt3; pnt3[0] = 9.0; pnt3[1] = 4.0; figure1->SetControlPoint( 2, pnt3, true ); mitk::Point2D pnt4; pnt4[0] = 11.0; pnt4[1] = 4.0; figure1->SetControlPoint( 3, pnt4, true ); figure1->GetPolyLine(0); this->VerifyStatistics(ComputeStatistics(m_Image, figure1.GetPointer()), 127.66, 127.5); } void mitkImageStatisticsCalculatorTestSuite::TestCase8() { /***************************** * whole pixel (gray) * -> mean of 128 expected ******************************/ mitk::PlanarPolygon::Pointer figure2 = mitk::PlanarPolygon::New(); figure2->SetPlaneGeometry( m_Geometry ); mitk::Point2D pnt1; pnt1[0] = 11.5; pnt1[1] = 10.5; figure2->PlaceFigure( pnt1 ); mitk::Point2D pnt2; pnt2[0] = 11.5; pnt2[1] = 11.5; figure2->SetControlPoint( 1, pnt2, true ); mitk::Point2D pnt3; pnt3[0] = 12.5; pnt3[1] = 11.5; figure2->SetControlPoint( 2, pnt3, true ); mitk::Point2D pnt4; pnt4[0] = 12.5; pnt4[1] = 10.5; figure2->SetControlPoint( 3, pnt4, true ); figure2->GetPolyLine(0); this->VerifyStatistics(ComputeStatistics(m_Image, figure2.GetPointer()), 128.0, 0.0); } void mitkImageStatisticsCalculatorTestSuite::TestCase9() { /***************************** * whole pixel (gray) + half pixel (white) in y-direction * -> mean of 191.5 expected ******************************/ mitk::PlanarPolygon::Pointer figure2 = mitk::PlanarPolygon::New(); figure2->SetPlaneGeometry( m_Geometry ); mitk::Point2D pnt1; pnt1[0] = 11.5; pnt1[1] = 10.5; figure2->PlaceFigure( pnt1 ); mitk::Point2D pnt2; pnt2[0] = 11.5; pnt2[1] = 12.0; figure2->SetControlPoint( 1, pnt2, true ); mitk::Point2D pnt3; pnt3[0] = 12.5; pnt3[1] = 12.0; figure2->SetControlPoint( 2, pnt3, true ); mitk::Point2D pnt4; pnt4[0] = 12.5; pnt4[1] = 10.5; figure2->SetControlPoint( 3, pnt4, true ); figure2->GetPolyLine(0); this->VerifyStatistics(ComputeStatistics(m_Image, figure2.GetPointer()), 191.5, 89.80); } void mitkImageStatisticsCalculatorTestSuite::TestCase10() { /***************************** * 2 whole pixel (white) + 2 whole pixel (black) in y-direction * -> mean of 127.66 expected ******************************/ mitk::PlanarPolygon::Pointer figure2 = mitk::PlanarPolygon::New(); figure2->SetPlaneGeometry( m_Geometry ); mitk::Point2D pnt1; pnt1[0] = 11.5; pnt1[1] = 10.5; figure2->PlaceFigure( pnt1 ); mitk::Point2D pnt2; pnt2[0] = 11.5; pnt2[1] = 13.5; figure2->SetControlPoint( 1, pnt2, true ); mitk::Point2D pnt3; pnt3[0] = 12.5; pnt3[1] = 13.5; figure2->SetControlPoint( 2, pnt3, true ); mitk::Point2D pnt4; pnt4[0] = 12.5; pnt4[1] = 10.5; figure2->SetControlPoint( 3, pnt4, true ); figure2->GetPolyLine(0); this->VerifyStatistics(ComputeStatistics(m_Image, figure2.GetPointer()), 127.66, 127.5); } void mitkImageStatisticsCalculatorTestSuite::TestCase11() { /***************************** * 9 whole pixels (white) + 3 half pixels (white) * + 3 whole pixel (black) [ + 3 slightly less than half pixels (black)] * -> mean of 204.0 expected ******************************/ mitk::PlanarPolygon::Pointer figure2 = mitk::PlanarPolygon::New(); figure2->SetPlaneGeometry( m_Geometry ); mitk::Point2D pnt1; pnt1[0] = 0.5; pnt1[1] = 0.5; figure2->PlaceFigure( pnt1 ); mitk::Point2D pnt2; pnt2[0] = 3.5; pnt2[1] = 3.5; figure2->SetControlPoint( 1, pnt2, true ); mitk::Point2D pnt3; pnt3[0] = 8.4999; pnt3[1] = 3.5; figure2->SetControlPoint( 2, pnt3, true ); mitk::Point2D pnt4; pnt4[0] = 5.4999; pnt4[1] = 0.5; figure2->SetControlPoint( 3, pnt4, true ); figure2->GetPolyLine(0); this->VerifyStatistics(ComputeStatistics(m_Image, figure2.GetPointer()), 204.0, 105.58 ); } void mitkImageStatisticsCalculatorTestSuite::TestCase12() { /***************************** * half pixel (white) + whole pixel (white) + half pixel (black) * -> mean of 212.66 expected ******************************/ mitk::PlanarPolygon::Pointer figure2 = mitk::PlanarPolygon::New(); figure2->SetPlaneGeometry( m_Geometry ); mitk::Point2D pnt1; pnt1[0] = 9.5; pnt1[1] = 0.5; figure2->PlaceFigure( pnt1 ); mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 2.5; figure2->SetControlPoint( 1, pnt2, true ); mitk::Point2D pnt3; pnt3[0] = 11.5; pnt3[1] = 2.5; figure2->SetControlPoint( 2, pnt3, true ); figure2->GetPolyLine(0); this->VerifyStatistics(ComputeStatistics(m_Image, figure2.GetPointer()), 212.66, 73.32); } const mitk::ImageStatisticsCalculator::Statistics mitkImageStatisticsCalculatorTestSuite::ComputeStatistics( mitk::Image::Pointer image, mitk::PlanarFigure::Pointer polygon ) { mitk::ImageStatisticsCalculator::Pointer statisticsCalculator = mitk::ImageStatisticsCalculator::New(); statisticsCalculator->SetImage( image ); statisticsCalculator->SetMaskingModeToPlanarFigure(); statisticsCalculator->SetPlanarFigure( polygon ); statisticsCalculator->ComputeStatistics(); return statisticsCalculator->GetStatistics(); } void mitkImageStatisticsCalculatorTestSuite::VerifyStatistics(const mitk::ImageStatisticsCalculator::Statistics& stats, double testMean, double testSD) { int tmpMean = stats.GetMean() * 100; double calculatedMean = tmpMean / 100.0; MITK_TEST_CONDITION( calculatedMean == testMean, "Calculated mean grayvalue '" << calculatedMean << "' is equal to the desired value '" << testMean << "'" ); int tmpSD = stats.GetSigma() * 100; double calculatedSD = tmpSD / 100.0; MITK_TEST_CONDITION( calculatedSD == testSD, "Calculated grayvalue sd '" << calculatedSD << "' is equal to the desired value '" << testSD <<"'" ); } void mitkImageStatisticsCalculatorTestSuite::TestUninitializedImage() { /***************************** * loading uninitialized image to datastorage ******************************/ MITK_TEST_FOR_EXCEPTION_BEGIN(mitk::Exception) mitk::Image::Pointer image = mitk::Image::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(image); mitk::ImageStatisticsCalculator::Pointer is = mitk::ImageStatisticsCalculator::New(); is->ComputeStatistics(); MITK_TEST_FOR_EXCEPTION_END(mitk::Exception) } MITK_TEST_SUITE_REGISTRATION(mitkImageStatisticsCalculator) diff --git a/Modules/IpPicSupportIO/CMakeLists.txt b/Modules/IpPicSupportIO/CMakeLists.txt index 7cfebb1310..dee0826aaf 100644 --- a/Modules/IpPicSupportIO/CMakeLists.txt +++ b/Modules/IpPicSupportIO/CMakeLists.txt @@ -1,10 +1,10 @@ #mitkFunctionCheckCompilerFlags("-Wno-deprecated-declarations" CMAKE_CXX_FLAGS) MITK_CREATE_MODULE( - DEPENDS MitkIpPic MitkLegacyAdaptors MitkLegacyIO + DEPENDS MitkIpPic MitkLegacyAdaptors AUTOLOAD_WITH MitkCore ) if(BUILD_TESTING) #add_subdirectory(Testing) endif() diff --git a/Modules/ModuleList.cmake b/Modules/ModuleList.cmake index 60a52d14a0..56d6182433 100644 --- a/Modules/ModuleList.cmake +++ b/Modules/ModuleList.cmake @@ -1,67 +1,69 @@ # The entries in the mitk_modules list must be # ordered according to their dependencies. set(mitk_modules Core DCMTesting RDF LegacyIO DataTypesExt Overlays LegacyGL AlgorithmsExt MapperExt DICOMReader DICOMTesting Qt4Qt5TestModule SceneSerializationBase PlanarFigure ImageDenoising ImageExtraction ImageStatistics LegacyAdaptors SceneSerialization GraphAlgorithms Multilabel ContourModel SurfaceInterpolation Segmentation PlanarFigureSegmentation OpenViewCore QmlItems QtWidgets QtWidgetsExt SegmentationUI DiffusionImaging GPGPU + OpenIGTLink IGTBase IGT CameraCalibration RigidRegistration RigidRegistrationUI DeformableRegistration DeformableRegistrationUI OpenCL OpenCVVideoSupport QtOverlays InputDevices ToFHardware ToFProcessing ToFUI US USUI DicomUI Simulation Remeshing Python Persistence + OpenIGTLinkUI IGTUI VtkShaders DicomRT IOExt XNAT ) if(MITK_ENABLE_PIC_READER) list(APPEND mitk_modules IpPicSupportIO) endif() diff --git a/Modules/OpenIGTLink/CMakeLists.txt b/Modules/OpenIGTLink/CMakeLists.txt new file mode 100644 index 0000000000..459768a580 --- /dev/null +++ b/Modules/OpenIGTLink/CMakeLists.txt @@ -0,0 +1,29 @@ +#find_package(OpenIGTLink) + +#include(${OpenIGTLink_USE_FILE}) + +#include(${OpenIGTLink_SOURCE_DIR}/Source) + +#SET(OpenIGTLink_INCLUDE_DIRS_BUILD_TREE ${OpenIGTLink_INCLUDE_DIRS_BUILD_TREE} +# ${OpenIGTLink_BINARY_DIR} +# ${OpenIGTLink_SOURCE_DIR}/Source +# ${OpenIGTLink_SOURCE_DIR}/Source/igtlutil +#) + +MITK_CREATE_MODULE( + #SUBPROJECTS MITK-IGTL + DEPENDS MitkCore + PACKAGE_DEPENDS OpenIGTLink + #WARNINGS_AS_ERRORS + #ADDITIONAL_LIBS ${OpenIGTLink_LIBRARIES} /projects/OIGTL-build/bin/libOpenIGTLink.a + #INCLUDE_DIRS ${OpenIGTLink_INCLUDE_DIRS_BUILD_TREE} + #INCLUDE_DIRS /projects/OIGTL-build ${OpenIGTLink_BINARY_DIR} ${OpenIGTLink_SOURCE_DIR}/Source + EXPORT_DEFINE MITK_OPENIGTLINK_EXPORT +) + +if(MODULE_IS_ENABLED) +## create IGT config +#configure_file(mitkIGTConfig.h.in ${PROJECT_BINARY_DIR}/mitkIGTConfig.h @ONLY) + +add_subdirectory(Testing) +endif() diff --git a/Modules/OpenIGTLink/Testing/CMakeLists.txt b/Modules/OpenIGTLink/Testing/CMakeLists.txt new file mode 100644 index 0000000000..153cd81e2e --- /dev/null +++ b/Modules/OpenIGTLink/Testing/CMakeLists.txt @@ -0,0 +1 @@ +MITK_CREATE_MODULE_TESTS() diff --git a/Modules/OpenIGTLink/Testing/files.cmake b/Modules/OpenIGTLink/Testing/files.cmake new file mode 100644 index 0000000000..8fe09ed5d9 --- /dev/null +++ b/Modules/OpenIGTLink/Testing/files.cmake @@ -0,0 +1,18 @@ +set(MODULE_TESTS + # IMPORTANT: If you plan to deactivate / comment out a test please write a bug number to the commented out line of code. + # + # Example: #mitkMyTest #this test is commented out because of bug 12345 + # + # It is important that the bug is open and that the test will be activated again before the bug is closed. This assures that + # no test is forgotten after it was commented out. If there is no bug for your current problem, please add a new one and + # mark it as critical. + + ################## ON THE FENCE TESTS ################################################# + # none + + ################## DISABLED TESTS ##################################################### + # none + + ################# RUNNING TESTS ####################################################### + #mitkNavigationDataToIGTLMessageFilterTest.cpp +) diff --git a/Modules/OpenIGTLink/Testing/mitkNavigationDataToIGTLMessageFilterTest.cpp b/Modules/OpenIGTLink/Testing/mitkNavigationDataToIGTLMessageFilterTest.cpp new file mode 100644 index 0000000000..8bb4d8d7a8 --- /dev/null +++ b/Modules/OpenIGTLink/Testing/mitkNavigationDataToIGTLMessageFilterTest.cpp @@ -0,0 +1,240 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkNavigationDataToPointSetFilter.h" +#include "mitkNavigationDataSequentialPlayer.h" +#include "mitkNavigationDataReaderXML.h" +#include +#include + +#include + +/** +* Simple example for a test for the (non-existent) class "NavigationDataToPointSetFilter". +* +* argc and argv are the command line parameters which were passed to +* the ADD_TEST command in the CMakeLists.txt file. For the automatic +* tests, argv is either empty for the simple tests or contains the filename +* of a test image for the image tests (see CMakeLists.txt). +*/ + +mitk::NavigationDataToPointSetFilter::Pointer m_NavigationDataToPointSetFilter; + +static void Setup() +{ + m_NavigationDataToPointSetFilter = mitk::NavigationDataToPointSetFilter::New(); +} + +static void TestMode3D() +{ + Setup(); + m_NavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode3D); + + //Build up test data + mitk::NavigationData::Pointer nd0 = mitk::NavigationData::New(); + mitk::NavigationData::Pointer nd1 = mitk::NavigationData::New(); + mitk::NavigationData::Pointer nd2 = mitk::NavigationData::New(); + mitk::NavigationData::Pointer nd3 = mitk::NavigationData::New(); + + mitk::NavigationData::PositionType point0; + point0[0] = 1.0; + point0[1] = 2.0; + point0[2] = 3.0; + nd0->SetPosition(point0); + nd0->SetDataValid(true); + + mitk::NavigationData::PositionType point1; + point1[0] = 4.0; + point1[1] = 5.0; + point1[2] = 6.0; + nd1->SetPosition(point1); + nd1->SetDataValid(true); + + mitk::NavigationData::PositionType point2; + point2[0] = 7.0; + point2[1] = 8.0; + point2[2] = 9.0; + nd2->SetPosition(point2); + nd2->SetDataValid(true); + + mitk::NavigationData::PositionType point3; + point3[0] = 10.0; + point3[1] = 11.0; + point3[2] = 12.0; + nd3->SetPosition(point3); + nd3->SetDataValid(true); + + m_NavigationDataToPointSetFilter->SetInput(0, nd0); + m_NavigationDataToPointSetFilter->SetInput(1, nd1); + m_NavigationDataToPointSetFilter->SetInput(2, nd2); + m_NavigationDataToPointSetFilter->SetInput(3, nd3); + + //Process + mitk::PointSet::Pointer pointSet0 = m_NavigationDataToPointSetFilter->GetOutput(); + mitk::PointSet::Pointer pointSet1 = m_NavigationDataToPointSetFilter->GetOutput(1); + mitk::PointSet::Pointer pointSet2 = m_NavigationDataToPointSetFilter->GetOutput(2); + mitk::PointSet::Pointer pointSet3 = m_NavigationDataToPointSetFilter->GetOutput(3); + + pointSet0->Update(); + + MITK_TEST_OUTPUT(<< "Testing the conversion of navigation data object to PointSets in Mode 3D:"); + MITK_TEST_CONDITION(mitk::Equal(pointSet0->GetPoint(0), point0), "Pointset 0 correct?"); + MITK_TEST_CONDITION(mitk::Equal(pointSet1->GetPoint(0), point1), "Pointset 1 correct?"); + MITK_TEST_CONDITION(mitk::Equal(pointSet2->GetPoint(0), point2), "Pointset 2 correct?"); + MITK_TEST_CONDITION(mitk::Equal(pointSet3->GetPoint(0), point3), "Pointset 3 correct?"); +} + +static void TestMode4D() +{ + Setup(); + m_NavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode4D); + m_NavigationDataToPointSetFilter->SetRingBufferSize(2); + + //Build up test data + mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); + mitk::NavigationData::Pointer nd2 = mitk::NavigationData::New(); + mitk::NavigationData::Pointer nd3 = mitk::NavigationData::New(); + mitk::NavigationData::Pointer nd4 = mitk::NavigationData::New(); + + mitk::NavigationData::PositionType point; + + point[0] = 1.0; + point[1] = 2.0; + point[2] = 3.0; + nd->SetPosition(point); + + point[0] = 4.0; + point[1] = 5.0; + point[2] = 6.0; + nd2->SetPosition(point); + + point[0] = 7.0; + point[1] = 8.0; + point[2] = 9.0; + nd3->SetPosition(point); + + point[0] = 10.0; + point[1] = 11.0; + point[2] = 12.0; + nd4->SetPosition(point); + + m_NavigationDataToPointSetFilter->SetInput(0, nd); + m_NavigationDataToPointSetFilter->SetInput(1, nd2); + + mitk::PointSet::Pointer pointSet = m_NavigationDataToPointSetFilter->GetOutput(); + pointSet->Update(); + + MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 1.0 && pointSet->GetPoint(0,0)[1] == 2.0 && pointSet->GetPoint(0,0)[2] == 3.0 && + pointSet->GetPoint(1,0)[0] == 4.0 && pointSet->GetPoint(1,0)[1] == 5.0 && pointSet->GetPoint(1,0)[2] == 6.0 + , "Testing the conversion of navigation data object to one point set in Mode 4D in first timestep" ); + + m_NavigationDataToPointSetFilter->SetInput(0, nd3); + m_NavigationDataToPointSetFilter->SetInput(1, nd4); + m_NavigationDataToPointSetFilter->Update(); + pointSet = m_NavigationDataToPointSetFilter->GetOutput(); + + MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 1.0 && pointSet->GetPoint(0,0)[1] == 2.0 && pointSet->GetPoint(0,0)[2] == 3.0 && + pointSet->GetPoint(1,0)[0] == 4.0 && pointSet->GetPoint(1,0)[1] == 5.0 && pointSet->GetPoint(1,0)[2] == 6.0 && + pointSet->GetPoint(0,1)[0] == 7.0 && pointSet->GetPoint(0,1)[1] == 8.0 && pointSet->GetPoint(0,1)[2] == 9.0 && + pointSet->GetPoint(1,1)[0] == 10.0 && pointSet->GetPoint(1,1)[1] == 11.0 && pointSet->GetPoint(1,1)[2] == 12.0 + , "Testing the conversion of navigation data object to one point set in Mode 4D in second timestep" ); + + m_NavigationDataToPointSetFilter->SetInput(0, nd3); + m_NavigationDataToPointSetFilter->SetInput(1, nd4); + pointSet = m_NavigationDataToPointSetFilter->GetOutput(); + pointSet->Update(); + + MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 7.0 && pointSet->GetPoint(0,0)[1] == 8.0 && pointSet->GetPoint(0,0)[2] == 9.0 && + pointSet->GetPoint(1,0)[0] == 10.0 && pointSet->GetPoint(1,0)[1] == 11.0 && pointSet->GetPoint(1,0)[2] == 12.0 && + pointSet->GetPoint(0,1)[0] == 7.0 && pointSet->GetPoint(0,1)[1] == 8.0 && pointSet->GetPoint(0,1)[2] == 9.0 && + pointSet->GetPoint(1,1)[0] == 10.0 && pointSet->GetPoint(1,1)[1] == 11.0 && pointSet->GetPoint(1,1)[2] == 12.0 + , "Testing the correct ring buffer behavior" ); +} + +static void TestMode3DMean() +{ + Setup(); + m_NavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode3DMean); + int numberForMean = 5; + m_NavigationDataToPointSetFilter->SetNumberForMean(numberForMean); + + MITK_TEST_CONDITION(mitk::Equal(m_NavigationDataToPointSetFilter->GetNumberForMean(), numberForMean), "Testing get/set for numberForMean"); + + mitk::NavigationDataSequentialPlayer::Pointer player = mitk::NavigationDataSequentialPlayer::New(); + + std::string file(MITK_IGT_DATA_DIR); + file.append("/NavigationDataTestData_2Tools.xml"); + + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + + player->SetNavigationDataSet( reader->Read(file) ); + + for (unsigned int i = 0; i< player->GetNumberOfOutputs(); i++) + { + m_NavigationDataToPointSetFilter->SetInput(i, player->GetOutput(i)); + } + + mitk::PointSet::Pointer pointSet0 = m_NavigationDataToPointSetFilter->GetOutput(); + mitk::PointSet::Pointer pointSet1 = m_NavigationDataToPointSetFilter->GetOutput(1); + + m_NavigationDataToPointSetFilter->Update(); + + MITK_TEST_CONDITION(pointSet0->GetPoint(0)[0]==3.0 && pointSet0->GetPoint(0)[1]==2.0 && pointSet0->GetPoint(0)[2]==5.0, + "Testing the average of first input"); + + MITK_TEST_CONDITION(pointSet1->GetPoint(0)[0]==30.0 && pointSet1->GetPoint(0)[1]==20.0 && pointSet1->GetPoint(0)[2]==50.0, + "Testing the average of second input"); +} + +static void NavigationDataToPointSetFilterContructor_DefaultCall_IsNotEmpty() +{ + Setup(); + MITK_TEST_CONDITION_REQUIRED(m_NavigationDataToPointSetFilter.IsNotNull(),"Testing instantiation"); + //I think this test is meaningless, because it will never ever fail. I keep it for know just to be save. +} + +static void NavigationDataToPointSetFilterSetInput_SimplePoint_EqualsGroundTruth() +{ + Setup(); + + mitk::NavigationData::Pointer nd_in = mitk::NavigationData::New(); + const mitk::NavigationData* nd_out = mitk::NavigationData::New(); + mitk::NavigationData::PositionType point; + + point[0] = 1.0; + point[1] = 2.0; + point[2] = 3.0; + nd_in->SetPosition(point); + + m_NavigationDataToPointSetFilter->SetInput(nd_in); + nd_out = m_NavigationDataToPointSetFilter->GetInput(); + + MITK_TEST_CONDITION( nd_out->GetPosition() == nd_in->GetPosition(), + "Testing get/set input" ); +} + +int mitkNavigationDataToPointSetFilterTest(int /* argc */, char* /*argv*/[]) +{ + MITK_TEST_BEGIN("NavigationDataToPointSetFilter"); + + NavigationDataToPointSetFilterContructor_DefaultCall_IsNotEmpty(); + NavigationDataToPointSetFilterSetInput_SimplePoint_EqualsGroundTruth(); + TestMode3D(); + TestMode4D(); +// TestMode3DMean(); //infinite loop in debug mode, see bug 17763 + + MITK_TEST_END(); +} diff --git a/Modules/OpenIGTLink/files.cmake b/Modules/OpenIGTLink/files.cmake new file mode 100644 index 0000000000..58f7e85ddd --- /dev/null +++ b/Modules/OpenIGTLink/files.cmake @@ -0,0 +1,14 @@ +set(CPP_FILES + mitkIGTLClient.cpp + mitkIGTLServer.cpp + mitkIGTLDevice.cpp + mitkIGTLMessageSource.cpp + mitkIGTLMessageCommon.cpp + mitkIGTLDeviceSource.cpp + mitkIGTLMessage.cpp + mitkIGTLMessageFactory.cpp + mitkIGTLMessageCloneHandler.h + mitkIGTLDummyMessage.cpp + mitkIGTLMessageQueue.cpp + mitkIGTLMessageProvider.cpp +) \ No newline at end of file diff --git a/Modules/OpenIGTLink/mitkIGTLClient.cpp b/Modules/OpenIGTLink/mitkIGTLClient.cpp new file mode 100644 index 0000000000..4c0cd66846 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLClient.cpp @@ -0,0 +1,128 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkIGTLClient.h" +//#include "mitkIGTTimeStamp.h" +//#include "mitkIGTHardwareException.h" +#include + +#include +#include + +#include +#include + +typedef itk::MutexLockHolder MutexLockHolder; + + +mitk::IGTLClient::IGTLClient() : +IGTLDevice() +{ +} + +mitk::IGTLClient::~IGTLClient() +{ + +} + +bool mitk::IGTLClient::OpenConnection() +{ + if (this->GetState() != Setup) + { + mitkThrowException(mitk::Exception) << + "Can only try to open the connection if in setup mode"; + return false; + } + + std::string hostname = this->GetHostname(); + int portNumber = this->GetPortNumber(); + + if (portNumber == -1 || hostname.size() <= 0) + { + //port number or hostname was not correct + return false; + } + + //create a new client socket + m_Socket = igtl::ClientSocket::New(); + + //try to connect to the igtl server + int response = dynamic_cast(m_Socket.GetPointer())-> + ConnectToServer(hostname.c_str(), portNumber); + + //check the response + if ( response != 0 ) + { + mitkThrowException(mitk::Exception) << + "The client could not connect to " << hostname << " port: " << portNumber; + return false; + } + + // everything is initialized and connected so the communication can be started + this->SetState(Ready); + + //inform observers about this new client + this->InvokeEvent(NewClientConnectionEvent()); + + return true; +} + +void mitk::IGTLClient::Receive() +{ + //try to receive a message, if the socket is not present anymore stop the + //communication + unsigned int status = this->ReceivePrivate(this->m_Socket); + if ( status == IGTL_STATUS_NOT_PRESENT ) + { + this->StopCommunicationWithSocket(this->m_Socket); + //inform observers about loosing the connection to this socket + this->InvokeEvent(LostConnectionEvent()); + MITK_WARN("IGTLClient") << "Lost connection to server socket."; + } +} + +void mitk::IGTLClient::Send() +{ + igtl::MessageBase::Pointer curMessage; + + //get the latest message from the queue + curMessage = this->m_SendQueue->PullMessage(); + + // there is no message => return + if ( curMessage.IsNull() ) + return; + + if ( this->SendMessagePrivate(curMessage.GetPointer(), this->m_Socket) ) + { + MITK_INFO("IGTLDevice") << "Successfully sent the message."; + } + else + { + MITK_WARN("IGTLDevice") << "Could not send the message."; + } +} + +void mitk::IGTLClient::StopCommunicationWithSocket(igtl::Socket* /*socket*/) +{ + m_StopCommunicationMutex->Lock(); + m_StopCommunication = true; + m_StopCommunicationMutex->Unlock(); +} + +unsigned int mitk::IGTLClient::GetNumberOfConnections() +{ + return this->m_Socket->GetConnected(); +} diff --git a/Modules/OpenIGTLink/mitkIGTLClient.h b/Modules/OpenIGTLink/mitkIGTLClient.h new file mode 100644 index 0000000000..54b2758734 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLClient.h @@ -0,0 +1,93 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKIGTLCLIENT_H +#define MITKIGTLCLIENT_H + +#include "mitkIGTLDevice.h" + +#include + + +namespace mitk +{ + + /** + * \brief Superclass for OpenIGTLink clients + * + * Implements the IGTLDevice interface for IGTLClients. In certain points it + * behaves different than the IGTLServer. The client connects directly to a + * server (it cannot connect to two different servers). Therefore, it has to + * check only this one connection. + * + * \ingroup OpenIGTLink + */ + class MITKOPENIGTLINK_EXPORT IGTLClient : public IGTLDevice + { + public: + mitkClassMacro(IGTLClient, IGTLDevice) + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + /** + * \brief Establishes the connection between this client and the IGTL server. + * + * @throw mitk::Exception Throws an exception if the client is not in Setup + * mode or if it cannot connect to the defined host. + */ + virtual bool OpenConnection(); + + /** + * \brief Returns the number of connections of this device + * + * A client can connect to one sever only, therefore, the number is either 0 + * or 1 + */ + virtual unsigned int GetNumberOfConnections(); + + protected: + /** Constructor */ + IGTLClient(); + /** Destructor */ + virtual ~IGTLClient(); + + /** + * \brief Call this method to receive a message. + * + * The message will be saved in the receive queue. If the connection is lost + * it will stop the communication. + */ + virtual void Receive(); + + /** + * \brief Call this method to send a message. + * + * The message will be read from the queue. + */ + virtual void Send(); + + /** + * \brief Stops the communication with the given socket. + * + * The client uses just one socket. Therefore, calling this function causes + * the stop of the communication. + * + */ + virtual void StopCommunicationWithSocket(igtl::Socket*); + }; +} // namespace mitk +#endif /* MITKIGTLCLIENT_H */ diff --git a/Modules/OpenIGTLink/mitkIGTLDevice.cpp b/Modules/OpenIGTLink/mitkIGTLDevice.cpp new file mode 100644 index 0000000000..7ef3757487 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLDevice.cpp @@ -0,0 +1,485 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkIGTLDevice.h" +//#include "mitkIGTTimeStamp.h" +#include +#include +#include + +#include +#include + +#include + +//remove later +#include + +#include + +static const int SOCKET_SEND_RECEIVE_TIMEOUT_MSEC = 1; + +typedef itk::MutexLockHolder MutexLockHolder; + +mitk::IGTLDevice::IGTLDevice() : +// m_Data(mitk::DeviceDataUnspecified), + m_State(mitk::IGTLDevice::Setup), + m_Name("Unspecified Device"), + m_StopCommunication(false), + m_PortNumber(-1), + m_MultiThreader(NULL), m_ThreadID(0) +{ + m_StopCommunicationMutex = itk::FastMutexLock::New(); + m_StateMutex = itk::FastMutexLock::New(); +// m_LatestMessageMutex = itk::FastMutexLock::New(); + m_CommunicationFinishedMutex = itk::FastMutexLock::New(); + // execution rights are owned by the application thread at the beginning + m_CommunicationFinishedMutex->Lock(); + m_MultiThreader = itk::MultiThreader::New(); +// m_Data = mitk::DeviceDataUnspecified; +// m_LatestMessage = igtl::MessageBase::New(); + + m_MessageFactory = mitk::IGTLMessageFactory::New(); + m_SendQueue = mitk::IGTLMessageQueue::New(); + m_ReceiveQueue = mitk::IGTLMessageQueue::New(); + m_CommandQueue = mitk::IGTLMessageQueue::New(); +} + + +mitk::IGTLDevice::~IGTLDevice() +{ + /* stop communication and disconnect from igtl device */ + if (GetState() == Running) + { + this->StopCommunication(); + } + if (GetState() == Ready) + { + this->CloseConnection(); + } + /* cleanup tracking thread */ + if ((m_ThreadID != 0) && (m_MultiThreader.IsNotNull())) + { + m_MultiThreader->TerminateThread(m_ThreadID); + } + m_MultiThreader = NULL; +} + +mitk::IGTLDevice::IGTLDeviceState mitk::IGTLDevice::GetState() const +{ + MutexLockHolder lock(*m_StateMutex); + return m_State; +} + + +void mitk::IGTLDevice::SetState( IGTLDeviceState state ) +{ + itkDebugMacro("setting m_State to " << state); + + m_StateMutex->Lock(); +// MutexLockHolder lock(*m_StateMutex); // lock and unlock the mutex + + if (m_State == state) + { + m_StateMutex->Unlock(); + return; + } + m_State = state; + m_StateMutex->Unlock(); + this->Modified(); +} + + +bool mitk::IGTLDevice::TestConnection() +{ + + return true; +} + +unsigned int mitk::IGTLDevice::ReceivePrivate(igtl::Socket* socket) +{ + // Create a message buffer to receive header + igtl::MessageHeader::Pointer headerMsg; + headerMsg = igtl::MessageHeader::New(); + + // Initialize receive buffer + headerMsg->InitPack(); + + // Receive generic header from the socket + int r = + socket->Receive(headerMsg->GetPackPointer(), headerMsg->GetPackSize(), 1); + + if (r == 0) //connection error + { + // an error was received, therefor the communication with this socket + // must be stopped + return IGTL_STATUS_NOT_PRESENT; + } + else if (r == -1 ) //timeout + { + // a timeout was received, this is no error state, thus, do nothing + return IGTL_STATUS_TIME_OUT; + } + else if (r == headerMsg->GetPackSize()) + { + // Deserialize the header and check the CRC + int crcCheck = headerMsg->Unpack(1); + if (crcCheck & igtl::MessageHeader::UNPACK_HEADER) + { + // Allocate a time stamp + igtl::TimeStamp::Pointer ts; + ts = igtl::TimeStamp::New(); + + // Get time stamp + igtlUint32 sec; + igtlUint32 nanosec; + + headerMsg->GetTimeStamp(ts); + ts->GetTimeStamp(&sec, &nanosec); + +// std::cerr << "Time stamp: " +// << sec << "." +// << nanosec << std::endl; + +// std::cerr << "Dev type and name: " << headerMsg->GetDeviceType() << " " +// << headerMsg->GetDeviceName() << std::endl; + +// headerMsg->Print(std::cout); + + //check the type of the received message + //if it is a GET_, STP_ or RTS_ command push it into the command queue + //otherwise continue reading the whole message from the socket + const char* curDevType = headerMsg->GetDeviceType(); + if ( std::strstr( curDevType, "GET_" ) != NULL || + std::strstr( curDevType, "STP_" ) != NULL || + std::strstr( curDevType, "RTS_" ) != NULL) + { + this->m_CommandQueue->PushMessage(headerMsg); + this->InvokeEvent(CommandReceivedEvent()); + return IGTL_STATUS_OK; + } + + //Create a message according to the header message + igtl::MessageBase::Pointer curMessage; + curMessage = m_MessageFactory->CreateInstance(headerMsg); + + //check if the curMessage is created properly, if not the message type is + //not supported and the message has to be skipped + if ( curMessage.IsNull() ) + { + socket->Skip(headerMsg->GetBodySizeToRead(), 0); + MITK_ERROR("IGTLDevice") << "The received type is not supported. Please " + "add it to the message factory."; + return IGTL_STATUS_NOT_FOUND; + } + + //insert the header to the message and allocate the pack + curMessage->SetMessageHeader(headerMsg); + curMessage->AllocatePack(); + + // Receive transform data from the socket + int receiveCheck = 0; + receiveCheck = socket->Receive(curMessage->GetPackBodyPointer(), + curMessage->GetPackBodySize()); + + if ( receiveCheck > 0 ) + { + int c = curMessage->Unpack(1); + if ( !(c & igtl::MessageHeader::UNPACK_BODY) ) + { +// mitkThrow() << "crc error"; + return IGTL_STATUS_CHECKSUM_ERROR; + } + + //check the type of the received message + //if it is a command push it into the command queue + //otherwise into the normal receive queue + //STP_ commands are handled here because they implemented additional + //member variables that are not stored in the header message + if ( std::strstr( curDevType, "STT_" ) != NULL ) + { + this->m_CommandQueue->PushMessage(curMessage); + this->InvokeEvent(CommandReceivedEvent()); + } + else + { + this->m_ReceiveQueue->PushMessage(curMessage); + this->InvokeEvent(MessageReceivedEvent()); + } + return IGTL_STATUS_OK; + } + else + { + MITK_ERROR("IGTLDevice") << "Received a valid header but could not " + << "read the whole message."; + return IGTL_STATUS_UNKNOWN_ERROR; + } + } + else + { + //CRC check failed + return IGTL_STATUS_CHECKSUM_ERROR; + } + } + else + { + //Message size information and actual data size don't match. + //this state is not suppossed to be reached, return unknown error + return IGTL_STATUS_UNKNOWN_ERROR; + } +} + +void mitk::IGTLDevice::SendMessage(const mitk::IGTLMessage* msg) +{ + this->SendMessage(msg->GetMessage()); +} + +void mitk::IGTLDevice::SendMessage(igtl::MessageBase::Pointer msg) +{ + //add the message to the queue + m_SendQueue->PushMessage(msg); +} + +unsigned int mitk::IGTLDevice::SendMessagePrivate(igtl::MessageBase::Pointer msg, + igtl::Socket::Pointer socket) +{ + //check the input message + if ( msg.IsNull() ) + { + MITK_ERROR("IGTLDevice") << "Could not send message because message is not " + "valid. Please check."; + return false; + } + + // add the name of this device to the message + msg->SetDeviceName(this->GetName().c_str()); + + // Pack (serialize) and send + msg->Pack(); + int sendSuccess = socket->Send(msg->GetPackPointer(), msg->GetPackSize()); + + if (sendSuccess) + return IGTL_STATUS_OK; + else + return IGTL_STATUS_UNKNOWN_ERROR; +} + + +void mitk::IGTLDevice::RunCommunication() +{ + if (this->GetState() != Running) + return; + + // keep lock until end of scope + MutexLockHolder communicationFinishedLockHolder(*m_CommunicationFinishedMutex); + + // Because m_StopCommunication is used by two threads, access has to be guarded + // by a mutex. To minimize thread locking, a local copy is used here + bool localStopCommunication; + + // update the local copy of m_StopCommunication + this->m_StopCommunicationMutex->Lock(); + localStopCommunication = this->m_StopCommunication; + this->m_StopCommunicationMutex->Unlock(); + while ((this->GetState() == Running) && (localStopCommunication == false)) + { + // Check if other igtl devices want to connect with this one. This method + // is overwritten for igtl servers but is doing nothing in case of a igtl + // client + this->Connect(); + + // Check if there is something to receive and store it in the message queue + this->Receive(); + + // Check if there is something to send + this->Send(); + + /* Update the local copy of m_StopCommunication */ + this->m_StopCommunicationMutex->Lock(); + localStopCommunication = m_StopCommunication; + this->m_StopCommunicationMutex->Unlock(); + + // time to relax +// itksys::SystemTools::Delay(1); + } + // StopCommunication was called, thus the mode should be changed back to Ready now + // that the tracking loop has ended. + this->SetState(Ready); + MITK_DEBUG("IGTLDevice::RunCommunication") << "Reached end of communication."; + // returning from this function (and ThreadStartCommunication()) + // this will end the thread + return; +} + + + + +bool mitk::IGTLDevice::StartCommunication() +{ + if (this->GetState() != Ready) + return false; + + // go to mode Running + this->SetState(Running); + + // set a timeout for the sending and receiving + this->m_Socket->SetTimeout(SOCKET_SEND_RECEIVE_TIMEOUT_MSEC); + + // update the local copy of m_StopCommunication + this->m_StopCommunicationMutex->Lock(); + this->m_StopCommunication = false; + this->m_StopCommunicationMutex->Unlock(); + + // transfer the execution rights to tracking thread + m_CommunicationFinishedMutex->Unlock(); + + // start a new thread that executes the communication + m_ThreadID = + m_MultiThreader->SpawnThread(this->ThreadStartCommunication, this); +// mitk::IGTTimeStamp::GetInstance()->Start(this); + return true; +} + +bool mitk::IGTLDevice::StopCommunication() +{ + if (this->GetState() == Running) // Only if the object is in the correct state + { + // m_StopCommunication is used by two threads, so we have to ensure correct + // thread handling + m_StopCommunicationMutex->Lock(); + m_StopCommunication = true; + m_StopCommunicationMutex->Unlock(); + // we have to wait here that the other thread recognizes the STOP-command + // and executes it + m_CommunicationFinishedMutex->Lock(); +// mitk::IGTTimeStamp::GetInstance()->Stop(this); // notify realtime clock + // StopCommunication was called, thus the mode should be changed back + // to Ready now that the tracking loop has ended. + this->SetState(Ready); + } + return true; +} + +bool mitk::IGTLDevice::CloseConnection() +{ + if (this->GetState() == Setup) + { + return true; + } + else if (this->GetState() == Running) + { + this->StopCommunication(); + } + + m_Socket->CloseSocket(); + + /* return to setup mode */ + this->SetState(Setup); + +// this->InvokeEvent(mitk::LostConnectionEvent()); + + return true; +} + +bool mitk::IGTLDevice::SendRTSMessage(const char* type) +{ + //construct the device type for the return message, it starts with RTS_ and + //continues with the requested type + std::string returnType("RTS_"); + returnType.append(type); + //create a return message + igtl::MessageBase::Pointer rtsMsg = + this->m_MessageFactory->CreateInstance(returnType); + //if retMsg is NULL there is no return message defined and thus it is not + //necessary to send one back + if ( rtsMsg.IsNotNull() ) + { + this->SendMessage(rtsMsg); + return true; + } + else + { + return false; + } +} + +void mitk::IGTLDevice::Connect() +{ + +} + +igtl::MessageBase::Pointer mitk::IGTLDevice::GetNextMessage() +{ + //copy the next message into the given msg + igtl::MessageBase::Pointer msg = this->m_ReceiveQueue->PullMessage(); + return msg; +} + +igtl::MessageBase::Pointer mitk::IGTLDevice::GetNextCommand() +{ + //copy the next command into the given msg + igtl::MessageBase::Pointer msg = this->m_CommandQueue->PullMessage(); + return msg; +} + +void mitk::IGTLDevice::EnableInfiniteBufferingMode( + mitk::IGTLMessageQueue::Pointer queue, + bool enable) +{ + queue->EnableInfiniteBuffering(enable); +} + +//std::string mitk::IGTLDevice::GetNextMessageInformation() +//{ +// return this->m_ReceiveQueue->GetNextMsgInformationString(); +//} + +//std::string mitk::IGTLDevice::GetNextMessageDeviceType() +//{ +// return this->m_ReceiveQueue->GetNextMsgDeviceType(); +//} + +//std::string mitk::IGTLDevice::GetNextCommandInformation() +//{ +// return this->m_CommandQueue->GetNextMsgInformationString(); +//} + +//std::string mitk::IGTLDevice::GetNextCommandDeviceType() +//{ +// return this->m_CommandQueue->GetNextMsgDeviceType(); +//} + +ITK_THREAD_RETURN_TYPE mitk::IGTLDevice::ThreadStartCommunication(void* pInfoStruct) +{ + /* extract this pointer from Thread Info structure */ + struct itk::MultiThreader::ThreadInfoStruct * pInfo = + (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; + if (pInfo == NULL) + { + return ITK_THREAD_RETURN_VALUE; + } + if (pInfo->UserData == NULL) + { + return ITK_THREAD_RETURN_VALUE; + } + IGTLDevice *igtlDevice = (IGTLDevice*)pInfo->UserData; + if (igtlDevice != NULL) + { + igtlDevice->RunCommunication(); + } + igtlDevice->m_ThreadID = 0; // erase thread id because thread will end. + return ITK_THREAD_RETURN_VALUE; +} diff --git a/Modules/OpenIGTLink/mitkIGTLDevice.h b/Modules/OpenIGTLink/mitkIGTLDevice.h new file mode 100644 index 0000000000..6184f45b27 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLDevice.h @@ -0,0 +1,384 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKIGTLDEVICE_H +#define MITKIGTLDEVICE_H + +#include "mitkCommon.h" + +//itk +#include "itkObject.h" +#include "itkFastMutexLock.h" +#include "itkMultiThreader.h" + +//igtl +#include "igtlSocket.h" +#include "igtlMessageBase.h" +#include "igtlTransformMessage.h" + +//mitkIGTL +#include "MitkOpenIGTLinkExports.h" +#include "mitkIGTLMessageFactory.h" +#include "mitkIGTLMessageQueue.h" +#include "mitkIGTLMessage.h" + + +namespace mitk { + /** + * \brief Interface for all OpenIGTLink Devices + * + * Defines the methods that are common for all devices using OpenIGTLink. It + * can open/close a connection, start/stop a communication and send/receive + * messages. + * + * It uses message queues to store the incoming and outgoing mails. They are + * configurable, you can set buffering on and off. + * + * The device is in one of three different states: Setup, Ready or Running. + * Setup is the initial state. From this state on you can call + * OpenConnection() and arrive in the Ready state. From the Ready state you + * call StartCommunication() to arrive in the Running state. Now the device + * is continuosly checking for new connections, receiving messages and + * sending messages. This runs in a seperate thread. To stop the communication + * call StopCommunication() (to arrive in Ready state) or CloseConnection() + * (to arrive in the Setup state). + * + * \ingroup OpenIGTLink + * + */ + class MITKOPENIGTLINK_EXPORT IGTLDevice : public itk::Object + { + public: + mitkClassMacro(IGTLDevice, itk::Object) + + /** + * \brief Type for state variable. + * The IGTLDevice is always in one of these states. + * + */ + enum IGTLDeviceState {Setup, Ready, Running}; + + /** + * \brief Opens a connection to the device + * + * This may only be called if there is currently no connection to the + * device. If OpenConnection() is successful, the object will change from + * Setup state to Ready state. + */ + virtual bool OpenConnection() = 0; + + /** + * \brief Closes the connection to the device + * + * This may only be called if there is currently a connection to the + * device, but device is not running (e.g. object is in Ready state) + */ + virtual bool CloseConnection(); + + /** + * \brief Stops the communication between the two devices + * + * This may only be called if the device is in Running state. + */ + virtual bool StopCommunication(); + + /** + * \brief Starts the communication between the two devices + * + * This may only be called if the device is in Ready state. + */ + bool StartCommunication(); + + /** + * \brief Continuously checks for new connections, receives messages and + * sends messages. + * + * This may only be called if the device is in Running state and only from + * a seperate thread. + */ + void RunCommunication(); + + /** + * \brief Adds the given message to the sending queue + * + * This may only be called after the connection to the device has been + * established with a call to OpenConnection(). Note that the message + * is not send directly. This method just adds it to the send queue. + * \param msg The message to be added to the sending queue + */ + void SendMessage(igtl::MessageBase::Pointer msg); + + /** + * \brief Adds the given message to the sending queue + * + * Convenience function to work with mitk::IGTLMessage directly. + * \param msg The message to be added to the sending queue + */ + void SendMessage(const IGTLMessage* msg); + + /** + * \brief Returns current object state (Setup, Ready or Running) + */ + IGTLDeviceState GetState() const; + + /** + * \brief Returns the oldest message in the command queue + * \return The oldest message from the command queue. + */ + igtl::MessageBase::Pointer GetNextCommand(); + + /** + * \brief Returns the oldest message in the receive queue + * \return The oldest message from the receive queue + */ + igtl::MessageBase::Pointer GetNextMessage(); + + /** + * \brief Sets the port number of the device + */ + itkSetMacro(PortNumber,int); + + /** + * \brief Returns the port number of the device + */ + itkGetMacro(PortNumber,int); + + /** + * \brief Sets the ip/hostname of the device + */ + itkSetMacro(Hostname,std::string); + + /** + * \brief Returns the ip/hostname of the device + */ + itkGetMacro(Hostname,std::string); + + /** + * \brief Returns the name of this device + */ + itkGetConstMacro(Name, std::string); + + /** + * \brief Sets the name of this device + */ + itkSetMacro(Name, std::string); + + /** + * \brief Returns a const reference to the receive queue + */ + itkGetConstMacro(ReceiveQueue, mitk::IGTLMessageQueue::Pointer); + + /** + * \brief Returns a const reference to the command queue + */ + itkGetConstMacro(CommandQueue, mitk::IGTLMessageQueue::Pointer); + + /** + * \brief Returns a const reference to the send queue + */ + itkGetConstMacro(SendQueue, mitk::IGTLMessageQueue::Pointer); + + /** + * \brief Returns the message factory + */ + itkGetMacro(MessageFactory, mitk::IGTLMessageFactory::Pointer); + + /** + * \brief static start method for the tracking thread. + * \param data a void pointer to the IGTLDevice object. + */ + static ITK_THREAD_RETURN_TYPE ThreadStartCommunication(void* data); + + /** + * \brief TestConnection() tries to connect to a IGTL device on the current + * ip and port + * + * \todo Implement this method. Send a status message and check the answer. + * + * TestConnection() tries to connect to a IGTL server on the current + * ip and port and returns which device it has found. + * \return It returns the type of the device that answers. Throws an + * exception + * if no device is available on that ip/port. + * @throw mitk::Exception Throws an exception if there are errors + * while connecting to the device. + */ + virtual bool TestConnection(); + + /** + * \brief Send RTS message of given type + */ + bool SendRTSMessage(const char* type); + + /** + * \brief Sets the buffering mode of the given queue + */ + void EnableInfiniteBufferingMode(mitk::IGTLMessageQueue::Pointer queue, + bool enable = true); + + /** + * \brief Returns the number of connections of this device + */ + virtual unsigned int GetNumberOfConnections() = 0; + + protected: + /** + * \brief Sends a message. + * + * This may only be called after the connection to the device has been + * established with a call to OpenConnection(). This method uses the given + * socket to send the given MessageReceivedEvent + * + * \param msg the message to be sent + * \param socket the socket used to communicate with the other device + * + * \retval IGTL_STATUS_OK the message was sent + * \retval IGTL_STATUS_UNKONWN_ERROR the message was not sent because an + * unknown error occurred + */ + unsigned int SendMessagePrivate(igtl::MessageBase::Pointer msg, + igtl::Socket::Pointer socket); + + + /** + * \brief Call this method to receive a message. + * + * The message will be saved in the receive queue. + */ + virtual void Receive() = 0; + + /** + * \brief Call this method to receive a message from the given device. + * + * The message will be saved in the receive queue. + * + * \param device the socket that connects this device with the other one. + * + * \retval IGTL_STATUS_OK a message or a command was received + * \retval IGTL_STATUS_NOT_PRESENT the socket is not connected anymore + * \retval IGTL_STATUS_TIME_OUT the socket timed out + * \retval IGTL_STATUS_CHECKSUM_ERROR the checksum of the received msg was + * incorrect + * \retval IGTL_STATUS_UNKNOWN_ERROR an unknown error occurred + */ + unsigned int ReceivePrivate(igtl::Socket* device); + + /** + * \brief Call this method to send a message. The message will be read from + * the queue. + */ + virtual void Send() = 0; + + /** + * \brief Call this method to check for other devices that want to connect + * to this one. + * + * In case of a client this method is doing nothing. In case of a server it + * is checking for other devices and if there is one it establishes a + * connection. + */ + virtual void Connect(); + + /** + * \brief Stops the communication with the given socket + * + */ + virtual void StopCommunicationWithSocket(igtl::Socket* socket) = 0; + + /** + * \brief change object state + */ + void SetState(IGTLDeviceState state); + + IGTLDevice(); + virtual ~IGTLDevice(); + + /** current object state (Setup, Ready or Running) */ + IGTLDeviceState m_State; + /** the name of this device */ + std::string m_Name; + + /** signal used to stop the thread*/ + bool m_StopCommunication; + /** mutex to control access to m_StopCommunication */ + itk::FastMutexLock::Pointer m_StopCommunicationMutex; + /** mutex used to make sure that the thread is just started once */ + itk::FastMutexLock::Pointer m_CommunicationFinishedMutex; + /** mutex to control access to m_State */ + itk::FastMutexLock::Pointer m_StateMutex; + /** the hostname or ip of the device */ + std::string m_Hostname; + /** the port number of the device */ + int m_PortNumber; + /** the socket used to communicate with other IGTL devices */ + igtl::Socket::Pointer m_Socket; + + /** The message receive queue */ + mitk::IGTLMessageQueue::Pointer m_ReceiveQueue; + /** The message send queue */ + mitk::IGTLMessageQueue::Pointer m_SendQueue; + /** A queue that stores just command messages received by this device */ + mitk::IGTLMessageQueue::Pointer m_CommandQueue; + + /** A message factory that provides the New() method for all msg types */ + mitk::IGTLMessageFactory::Pointer m_MessageFactory; + + private: + /** creates worker thread that continuously polls interface for new + messages */ + itk::MultiThreader::Pointer m_MultiThreader; + /** ID of polling thread */ + int m_ThreadID; + }; + + /** + * \brief connect to this Event to get noticed when a message was received + * + * \note Check if you can invoke this events like this or if you have to make + * it thread-safe. They are not invoked in the main thread!!! + * */ + itkEventMacro( MessageReceivedEvent , itk::AnyEvent ); + + /** + * \brief connect to this Event to get noticed when a command was received + * + * \note Check if you can invoke this events like this or if you have to make + * it thread-safe. They are not invoked in the main thread!!! + * */ + itkEventMacro( CommandReceivedEvent , itk::AnyEvent ); + + /** + * \brief connect to this Event to get noticed when another igtl device + * connects with this device. + * + * \note Check if you can invoke this events like this or if you have to make + * it thread-safe. They are not invoked in the main thread!!! + * */ + itkEventMacro( NewClientConnectionEvent , itk::AnyEvent ); + + /** + * \brief connect to this Event to get noticed when this device looses the + * connection to a socket. + * + * \note Check if you can invoke this events like this or if you have to make + * it thread-safe. They are not invoked in the main thread!!! + * */ + itkEventMacro( LostConnectionEvent , itk::AnyEvent ); + +} // namespace mitk + +#endif /* MITKIGTLDEVICE_H */ diff --git a/Modules/OpenIGTLink/mitkIGTLDeviceSource.cpp b/Modules/OpenIGTLink/mitkIGTLDeviceSource.cpp new file mode 100644 index 0000000000..42426e24df --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLDeviceSource.cpp @@ -0,0 +1,291 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkIGTLDeviceSource.h" + +#include "mitkIGTLDevice.h" +#include "mitkIGTLMessage.h" + +//#include "mitkIGTTimeStamp.h" +//#include "mitkIGTException.h" + +//Microservices +#include +#include +#include +#include + +//itk +#include + + +const std::string mitk::IGTLDeviceSource::US_PROPKEY_IGTLDEVICENAME = + mitk::IGTLMessageSource::US_INTERFACE_NAME + ".igtldevicename"; + +mitk::IGTLDeviceSource::IGTLDeviceSource() + : mitk::IGTLMessageSource(), m_IGTLDevice(NULL) +{ + this->SetName("IGTLDeviceSource (no defined type)"); +} + +mitk::IGTLDeviceSource::~IGTLDeviceSource() +{ + if (m_IGTLDevice.IsNotNull()) + { + if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Running) + { + this->StopCommunication(); + } + if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Ready) + { + this->Disconnect(); + } + m_IGTLDevice = NULL; + } +} + +void mitk::IGTLDeviceSource::GenerateData() +{ + if (m_IGTLDevice.IsNull()) + return; + + /* update output with message from the device */ + IGTLMessage* msgOut = this->GetOutput(); + assert(msgOut); + igtl::MessageBase::Pointer msgIn = m_IGTLDevice->GetNextMessage(); + if ( msgIn.IsNotNull() ) + { + assert(msgIn); + + msgOut->SetMessage(msgIn); + msgOut->SetName(msgIn->GetDeviceName()); + } +// else +// { +// MITK_ERROR("IGTLDeviceSource") << "Could not get the latest message."; +// } +} + +void mitk::IGTLDeviceSource::SetIGTLDevice( mitk::IGTLDevice* igtlDevice ) +{ + MITK_DEBUG << "Setting IGTLDevice to " << igtlDevice; + if (this->m_IGTLDevice.GetPointer() != igtlDevice) + { + this->m_IGTLDevice = igtlDevice; + this->CreateOutputs(); + std::stringstream name; // create a human readable name for the source + name << "OIGTL Device Source ( " << igtlDevice->GetName() << " )"; + this->SetName(name.str()); + + //setup a observer that listens to new messages and new commands + typedef itk::SimpleMemberCommand CurCommandType; + CurCommandType::Pointer msgReceivedCommand = CurCommandType::New(); + msgReceivedCommand->SetCallbackFunction( + this, &IGTLDeviceSource::OnIncomingMessage ); + this->m_IGTLDevice->AddObserver(mitk::MessageReceivedEvent(), + msgReceivedCommand); + CurCommandType::Pointer cmdReceivedCommand = CurCommandType::New(); + cmdReceivedCommand->SetCallbackFunction( + this, &IGTLDeviceSource::OnIncomingCommand ); + this->m_IGTLDevice->AddObserver(mitk::CommandReceivedEvent(), + cmdReceivedCommand); + + } +} + +void mitk::IGTLDeviceSource::CreateOutputs() +{ + //if outputs are set then delete them + if (this->GetNumberOfOutputs() > 0) + { + for (int numOP = this->GetNumberOfOutputs() - 1; numOP >= 0; numOP--) + this->RemoveOutput(numOP); + this->Modified(); + } + + //fill the outputs if a valid OpenIGTLink device is set + if (m_IGTLDevice.IsNull()) + return; + + this->SetNumberOfIndexedOutputs(1); + if (this->GetOutput(0) == NULL) + { + DataObjectPointer newOutput = this->MakeOutput(0); + this->SetNthOutput(0, newOutput); + this->Modified(); + } +} + +void mitk::IGTLDeviceSource::Connect() +{ + if (m_IGTLDevice.IsNull()) + { + throw std::invalid_argument("mitk::IGTLDeviceSource: " + "No OpenIGTLink device set"); + } + if (this->IsConnected()) + { + return; + } + try + { + m_IGTLDevice->OpenConnection(); + } + catch (mitk::Exception &e) + { + throw std::runtime_error(std::string("mitk::IGTLDeviceSource: Could not open" + "connection to OpenIGTLink device. Error: ") + e.GetDescription()); + } +} + +void mitk::IGTLDeviceSource::StartCommunication() +{ + if (m_IGTLDevice.IsNull()) + throw std::invalid_argument("mitk::IGTLDeviceSource: " + "No OpenIGTLink device set"); + if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Running) + return; + if (m_IGTLDevice->StartCommunication() == false) + throw std::runtime_error("mitk::IGTLDeviceSource: " + "Could not start communication"); +} + +void mitk::IGTLDeviceSource::Disconnect() +{ + if (m_IGTLDevice.IsNull()) + throw std::invalid_argument("mitk::IGTLDeviceSource: " + "No OpenIGTLink device set"); + if (m_IGTLDevice->CloseConnection() == false) + throw std::runtime_error("mitk::IGTLDeviceSource: Could not close connection" + " to OpenIGTLink device"); +} + +void mitk::IGTLDeviceSource::StopCommunication() +{ + if (m_IGTLDevice.IsNull()) + throw std::invalid_argument("mitk::IGTLDeviceSource: " + "No OpenIGTLink device set"); + if (m_IGTLDevice->StopCommunication() == false) + throw std::runtime_error("mitk::IGTLDeviceSource: " + "Could not stop communicating"); +} + +void mitk::IGTLDeviceSource::UpdateOutputInformation() +{ + this->Modified(); // make sure that we need to be updated + Superclass::UpdateOutputInformation(); +} + +void mitk::IGTLDeviceSource::SetInput( unsigned int idx, const IGTLMessage* msg ) +{ + if ( msg == NULL ) // if an input is set to NULL, remove it + { + this->RemoveInput(idx); + } + else + { + // ProcessObject is not const-correct so a const_cast is required here + this->ProcessObject::SetNthInput(idx, const_cast(msg)); + } +// this->CreateOutputsForAllInputs(); +} + +bool mitk::IGTLDeviceSource::IsConnected() +{ + if (m_IGTLDevice.IsNull()) + return false; + + return (m_IGTLDevice->GetState() == mitk::IGTLDevice::Ready) || + (m_IGTLDevice->GetState() == mitk::IGTLDevice::Running); +} + +bool mitk::IGTLDeviceSource::IsCommunicating() +{ + if (m_IGTLDevice.IsNull()) + return false; + + return m_IGTLDevice->GetState() == mitk::IGTLDevice::Running; +} + +void mitk::IGTLDeviceSource::RegisterAsMicroservice() +{ + // Get Context + us::ModuleContext* context = us::GetModuleContext(); + + // Define ServiceProps + us::ServiceProperties props; + mitk::UIDGenerator uidGen = + mitk::UIDGenerator ("org.mitk.services.IGTLDeviceSource.id_", 16); + props[ US_PROPKEY_ID ] = uidGen.GetUID(); + props[ US_PROPKEY_DEVICENAME ] = this->GetName(); + props[ US_PROPKEY_IGTLDEVICENAME ] = m_Name; + props[ US_PROPKEY_DEVICETYPE ] = m_Type; + m_ServiceRegistration = context->RegisterService(this, props); +} + + +void mitk::IGTLDeviceSource::OnIncomingMessage() +{ + +} + +void mitk::IGTLDeviceSource::OnIncomingCommand() +{ + +} + +const mitk::IGTLMessage* mitk::IGTLDeviceSource::GetInput( void ) const +{ + if (this->GetNumberOfInputs() < 1) + return NULL; + + return static_cast(this->ProcessObject::GetInput(0)); +} + + +const mitk::IGTLMessage* +mitk::IGTLDeviceSource::GetInput( unsigned int idx ) const +{ + if (this->GetNumberOfInputs() < 1) + return NULL; + + return static_cast(this->ProcessObject::GetInput(idx)); +} + + +const mitk::IGTLMessage* +mitk::IGTLDeviceSource::GetInput(std::string msgName) const +{ + const DataObjectPointerArray& inputs = const_cast(this)->GetInputs(); + for (DataObjectPointerArray::const_iterator it = inputs.begin(); + it != inputs.end(); ++it) + if (std::string(msgName) == + (static_cast(it->GetPointer()))->GetName()) + return static_cast(it->GetPointer()); + return NULL; +} + + +itk::ProcessObject::DataObjectPointerArraySizeType +mitk::IGTLDeviceSource::GetInputIndex( std::string msgName ) +{ + DataObjectPointerArray outputs = this->GetInputs(); + for (DataObjectPointerArray::size_type i = 0; i < outputs.size(); ++i) + if (msgName == + (static_cast(outputs.at(i).GetPointer()))->GetName()) + return i; + throw std::invalid_argument("output name does not exist"); +} diff --git a/Modules/OpenIGTLink/mitkIGTLDeviceSource.h b/Modules/OpenIGTLink/mitkIGTLDeviceSource.h new file mode 100644 index 0000000000..c292ff9960 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLDeviceSource.h @@ -0,0 +1,194 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef IGTLDEVICESOURCE_H_HEADER_INCLUDED_ +#define IGTLDEVICESOURCE_H_HEADER_INCLUDED_ + +#include "mitkIGTLDevice.h" +#include "mitkIGTLMessageSource.h" + +namespace mitk { + /** + * \brief Connects a mitk::IGTLDevice to a + * MITK-OpenIGTLink-Message-Filter-Pipeline + * + * This class is the source of most OpenIGTLink pipelines. It encapsulates a + * mitk::IGTLDevice and provides the information/messages of the connected + * OpenIGTLink devices as igtl::MessageBase objects. Note, that there is just + * one single output. + * + */ + class MITKOPENIGTLINK_EXPORT IGTLDeviceSource : public IGTLMessageSource + { + public: + mitkClassMacro(IGTLDeviceSource, IGTLMessageSource); + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + /** + *\brief These Constants are used in conjunction with Microservices + */ + static const std::string US_PROPKEY_IGTLDEVICENAME; + + /** + * \brief sets the OpenIGTLink device that will be used as a data source + */ + virtual void SetIGTLDevice(mitk::IGTLDevice* td); + + /** + * \brief returns the OpenIGTLink device that is used by this filter + */ + itkGetObjectMacro(IGTLDevice, mitk::IGTLDevice); + + /** + *\brief Registers this object as a Microservice, making it available to every + * module and/or plugin. To unregister, call UnregisterMicroservice(). + */ + virtual void RegisterAsMicroservice(); + + /** + * \brief Establishes a connection to the OpenIGTLink device. If there is + * already a connection the method does nothing. + * \warning. Will throw a std::invalid_argument exception if no OpenIGTLink + * device was set with SetIGTLDevice(). Will throw a std::runtime_error if + * the OpenIGTLink device returns an error. + */ + void Connect(); + + /** + * \brief Closes the connection to the OpenIGTLink device + * \warning. Will throw a std::invalid_argument exception if no OpenIGTLink + * device was set with SetIGTLDevice(). Will throw a std::runtime_error if + * the OpenIGTLink device returns an error. + */ + void Disconnect(); + + /** + * \brief starts the communication of the device. + * This needs to be called before Update() or GetOutput()->Update(). If the + * device is already communicating the method does nothing. + * \warning. Will throw a std::invalid_argument exception if no OpenIGTLink + * device was set with SetIGTLDevice(). Will throw a std::runtime_error if + * the OpenIGTLink device returns an error. + */ + void StartCommunication(); + + /** + * \brief stops the communication of the device. + * \warning. Will throw a std::invalid_argument exception if no OpenIGTLink + * device was set with SetIGTLDevice(). Will throw a std::runtime_error if + * the OpenIGTLink device returns an error. + */ + void StopCommunication(); + + /** + * \brief returns true if a connection to the OpenIGTLink device is established + * + */ + virtual bool IsConnected(); + + /** + * \brief returns true if communication is in progress + * + */ + virtual bool IsCommunicating(); + + /** + * \brief Used for pipeline update + */ + virtual void UpdateOutputInformation(); + + protected: + IGTLDeviceSource(); + virtual ~IGTLDeviceSource(); + + /** + * \brief filter execute method + * + * queries the OpenIGTLink device for new messages and updates its output + * igtl::MessageBase objects with it. + * \warning Will raise a std::out_of_range exception, if tools were added to + * the OpenIGTLink device after it was set as input for this filter + */ + virtual void GenerateData(); + + /** + * \brief Create the necessary outputs for the m_IGTLDevice + * + * This Method is called internally whenever outputs need to be reset. Old + * Outputs are deleted when called. + **/ + void CreateOutputs(); + + /** + * \brief This method is called when the IGTL device hold by this class + * receives a new message + **/ + virtual void OnIncomingMessage(); + + /** + * \brief This method is called when the IGTL device hold by this class + * receives a new command + **/ + virtual void OnIncomingCommand(); + + + using Superclass::SetInput; + + /** + * \brief Set input with id idx of this filter + * + */ + virtual void SetInput( unsigned int idx, const IGTLMessage* msg ); + + /** + * \brief Get the input of this filter + */ + const IGTLMessage* GetInput(void) const; + + /** + * \brief Get the input with id idx of this filter + */ + const IGTLMessage* GetInput(unsigned int idx) const; + + /** + * \brief Get the input with name messageName of this filter + */ + const IGTLMessage* GetInput(std::string msgName) const; + + /** + *\brief return the index of the input with name msgName, throw + * std::invalid_argument exception if that name was not found + * + * \warning if a subclass has inputs that have different data type than + * mitk::IGTLMessage, they have to overwrite this method + */ + DataObjectPointerArraySizeType GetInputIndex(std::string msgName); + + /** + *\brief return the index of the output with name msgName, -1 if no output + * with that name was found + * + * \warning if a subclass has outputs that have different data type than + * mitk::IGTLMessage, they have to overwrite this method + */ + DataObjectPointerArraySizeType GetOutputIndex(std::string msgName); + + /** the OpenIGTLink device that is used as a source for this filter object*/ + mitk::IGTLDevice::Pointer m_IGTLDevice; + }; +} // namespace mitk +#endif /* MITKIGTLDeviceSource_H_HEADER_INCLUDED_ */ diff --git a/Modules/OpenIGTLink/mitkIGTLDeviceSourceTest.cpp b/Modules/OpenIGTLink/mitkIGTLDeviceSourceTest.cpp new file mode 100644 index 0000000000..5a22ebcc7b --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLDeviceSourceTest.cpp @@ -0,0 +1,137 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTrackingDeviceSource.h" +#include "mitkVirtualTrackingDevice.h" + +#include "mitkTestingMacros.h" +#include +#include "itksys/SystemTools.hxx" + +/**Documentation + * test for the class "NavigationDataSource". + */ +int mitkTrackingDeviceSourceTest(int /* argc */, char* /*argv*/[]) +{ + MITK_TEST_BEGIN("TrackingDeviceSource"); + + // let's create an object of our class + mitk::TrackingDeviceSource::Pointer mySource = mitk::TrackingDeviceSource::New(); + + // first test: did this work? + // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since + // it makes no sense to continue without an object. + MITK_TEST_CONDITION_REQUIRED(mySource.IsNotNull(), "Testing instantiation"); + + mySource->SetTrackingDevice(NULL); + MITK_TEST_CONDITION(mySource->GetTrackingDevice() == NULL, "Testing Set/GetTrackingDevice(NULL)"); + MITK_TEST_CONDITION(mySource->GetNumberOfOutputs() == 0, "Testing GetNumberOfOutputs with NULL td"); + MITK_TEST_FOR_EXCEPTION(std::invalid_argument, mySource->Connect()); + MITK_TEST_FOR_EXCEPTION(std::invalid_argument, mySource->StartTracking()); + + mitk::VirtualTrackingDevice::Pointer tracker = mitk::VirtualTrackingDevice::New(); + tracker->SetRefreshRate(10); + + + mySource->SetTrackingDevice(tracker); + MITK_TEST_CONDITION(mySource->GetTrackingDevice() == tracker.GetPointer(), "Testing Set/GetTrackingDevice(tracker)"); + MITK_TEST_CONDITION(mySource->GetNumberOfOutputs() == 0, "Testing GetNumberOfOutputs with no tool tracker"); + tracker = mitk::VirtualTrackingDevice::New(); + mitk::ReferenceCountWatcher::Pointer watch = new mitk::ReferenceCountWatcher(tracker); + + tracker->AddTool("T0"); + tracker->AddTool("T1"); + mySource->SetTrackingDevice(tracker); + MITK_TEST_CONDITION(mySource->GetTrackingDevice() == tracker.GetPointer(), "Testing Set/GetTrackingDevice(tracker2)"); + MITK_TEST_CONDITION(mySource->GetNumberOfOutputs() == 2, "Testing GetNumberOfOutputs with 2 tools tracker"); + MITK_TEST_CONDITION(mySource->IsConnected() == false, "Testing IsConnected()"); + mySource->Connect(); + MITK_TEST_CONDITION(mySource->IsConnected() == true, "Testing Connect()/IsConnected()"); + MITK_TEST_CONDITION(tracker->GetState() == mitk::TrackingDevice::Ready, "Testing Connect()/IsConnected() 2"); + mySource->Disconnect(); + MITK_TEST_CONDITION(mySource->IsConnected() == false, "Testing Disconnect()/IsConnected()"); + MITK_TEST_CONDITION(tracker->GetState() == mitk::TrackingDevice::Setup, "Testing Disconnect()/IsConnected() 2"); + + mySource->Connect(); + mySource->StartTracking(); + MITK_TEST_CONDITION(mySource->IsConnected() == true, "Testing StartTracking()/IsConnected()"); + MITK_TEST_CONDITION(mySource->IsTracking() == true, "Testing StartTracking()/IsTracking()"); + MITK_TEST_CONDITION(tracker->GetState() == mitk::TrackingDevice::Tracking, "Testing StartTracking()/IsTracking() 2"); + + unsigned long modTime = mySource->GetMTime(); + mySource->UpdateOutputInformation(); + MITK_TEST_CONDITION(mySource->GetMTime() != modTime, "Testing if UpdateOutputInformation() modifies the object"); + + //test getOutput() + mitk::NavigationData* nd0 = mySource->GetOutput(); + MITK_TEST_CONDITION_REQUIRED(nd0!=NULL,"Testing GetOutput() [1]"); + nd0 = mySource->GetOutput(nd0->GetName()); + MITK_TEST_CONDITION_REQUIRED(nd0!=NULL,"Testing GetOutput() [2]"); + + //test getOutputIndex() + MITK_TEST_CONDITION(mySource->GetOutputIndex(nd0->GetName())==0,"Testing GetOutputIndex()"); + + //test GraftNthOutput() + mitk::NavigationData::Pointer ndCopy = mitk::NavigationData::New(); + mySource->GraftNthOutput(1,nd0); + ndCopy = mySource->GetOutput(1); + MITK_TEST_CONDITION(std::string(ndCopy->GetName())==std::string(nd0->GetName()),"Testing GraftNthOutput()"); + + //test GetParameters() + mitk::PropertyList::ConstPointer p = mySource->GetParameters(); + MITK_TEST_CONDITION(p.IsNotNull(),"Testing GetParameters()"); + + nd0->Update(); + mitk::NavigationData::PositionType pos = nd0->GetPosition(); + unsigned long tmpMTime0 = nd0->GetMTime(); + itksys::SystemTools::Delay(500); // allow the tracking thread to advance the tool position + nd0->Update(); + mitk::NavigationData::PositionType newPos = nd0->GetPosition(); + if(nd0->GetMTime() == tmpMTime0) //tool not modified yet + { + MITK_TEST_CONDITION(mitk::Equal(newPos, pos) == true, "Testing if output changes on each update"); + } + else + { + MITK_TEST_CONDITION(mitk::Equal(newPos, pos) == false, "Testing if output changes on each update"); + } + + mySource->StopTracking(); + mySource->Disconnect(); + + tracker = mitk::VirtualTrackingDevice::New(); + mySource->SetTrackingDevice(tracker); + MITK_TEST_CONDITION(watch->GetReferenceCount() == 0, "Testing if reference to previous tracker object is released"); + watch = NULL; + + MITK_TEST_FOR_EXCEPTION(std::runtime_error, mySource->StartTracking()); // new tracker, needs Connect() before StartTracking() + + mySource->Connect(); + mySource->StartTracking(); + // itksys::SystemTools::Delay(800); // wait for tracking thread to start properly //DEBUG ONLY --> race condition. will the thread start before the object is destroyed? --> maybe hold a smartpointer? + try + { + mySource = NULL; // delete source + tracker = NULL; // delete tracker --> both should not result in any exceptions or deadlocks + } + catch (...) + { + MITK_TEST_FAILED_MSG(<< "exception during destruction of source or tracker!"); + } + + // always end with this! + MITK_TEST_END(); +} diff --git a/Modules/OpenIGTLink/mitkIGTLDummyMessage.cpp b/Modules/OpenIGTLink/mitkIGTLDummyMessage.cpp new file mode 100644 index 0000000000..753f5336b8 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLDummyMessage.cpp @@ -0,0 +1,66 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#include "mitkIGTLDummyMessage.h" + +#include "igtlutil/igtl_header.h" +#include "igtlutil/igtl_util.h" + + +mitk::IGTLDummyMessage::IGTLDummyMessage() : StringMessage() +{ + this->m_DefaultBodyType = "DUMMY"; +} + +mitk::IGTLDummyMessage::~IGTLDummyMessage() +{ +} + +void mitk::IGTLDummyMessage::SetDummyString( const std::string& dummyString ) +{ + this->m_dummyString = dummyString; + this->m_String = "This is a dummy string"; +} + +std::string mitk::IGTLDummyMessage::GetDummyString() +{ + return this->m_dummyString; +} + +igtl::MessageBase::Pointer mitk::IGTLDummyMessage::Clone() +{ + //initialize the clone + mitk::IGTLDummyMessage::Pointer clone = mitk::IGTLDummyMessage::New(); + + //copy the data + clone->SetString(this->GetString()); + clone->SetDummyString(this->GetDummyString()); + + return igtl::MessageBase::Pointer(clone.GetPointer()); +} + +/** + * \brief Clones the original message interpreted as transform message + * \param original_ The original message that will be interpreted as transform + * message + * \return The clone of the input message + */ +igtl::MessageBase::Pointer mitk::DummyMsgCloneHandler::Clone(igtl::MessageBase* original_) +{ + mitk::IGTLDummyMessage* original = (mitk::IGTLDummyMessage*)original_; + return original->Clone(); +} diff --git a/Modules/OpenIGTLink/mitkIGTLDummyMessage.h b/Modules/OpenIGTLink/mitkIGTLDummyMessage.h new file mode 100644 index 0000000000..f03efd4246 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLDummyMessage.h @@ -0,0 +1,74 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKIGTLDUMMYMESSAGE_H +#define MITKIGTLDUMMYMESSAGE_H + +#include "MitkOpenIGTLinkExports.h" + +#include "igtlObject.h" +#include "igtlStringMessage.h" +#include "mitkIGTLMessageCloneHandler.h" + +namespace mitk +{ + +/** Documentation +* \class IGTLDummyMessage +* \brief This class is a dummy message to show the how to implement a new message +* type +*/ +class MITKOPENIGTLINK_EXPORT IGTLDummyMessage: public igtl::StringMessage +{ +public: + typedef IGTLDummyMessage Self; + typedef StringMessage Superclass; + typedef igtl::SmartPointer Pointer; + typedef igtl::SmartPointer ConstPointer; + + igtlTypeMacro( mitk::IGTLDummyMessage, igtl::StringMessage ); + igtlNewMacro( mitk::IGTLDummyMessage ); + +public: + /** + * Set dummy string + */ + void SetDummyString( const std::string& dummyString ); + + /** + * Get dummy string + */ + std::string GetDummyString(); + + /** + * Returns a clone of itself + */ + igtl::MessageBase::Pointer Clone(); + +protected: + IGTLDummyMessage(); + ~IGTLDummyMessage(); + + std::string m_dummyString; +}; + + +mitkIGTMessageCloneClassMacro(IGTLDummyMessage, DummyMsgCloneHandler); + + +} // namespace mitk + +#endif diff --git a/Modules/OpenIGTLink/mitkIGTLMessage.cpp b/Modules/OpenIGTLink/mitkIGTLMessage.cpp new file mode 100644 index 0000000000..e6b8034019 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLMessage.cpp @@ -0,0 +1,170 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkIGTLMessage.h" +#include "mitkException.h" +#include "mitkIGTLMessageCommon.h" + +mitk::IGTLMessage::IGTLMessage() : itk::DataObject(), +m_DataValid(false), m_IGTTimeStamp(0.0), m_Name() +{ + m_Message = igtl::MessageBase::New(); +} + + +mitk::IGTLMessage::IGTLMessage(const mitk::IGTLMessage& toCopy) : + itk::DataObject() +{ + // TODO SW: Graft does the same, remove code duplications, set Graft to + // deprecated, remove duplication in tescode + this->Graft(&toCopy); +} + +mitk::IGTLMessage::~IGTLMessage() +{ +} + +mitk::IGTLMessage::IGTLMessage(igtl::MessageBase::Pointer message, + std::string name) +{ + this->SetMessage(message); + this->SetName(name); +} + +void mitk::IGTLMessage::Graft( const DataObject *data ) +{ + // Attempt to cast data to an IGTLMessage + const Self* nd; + try + { + nd = dynamic_cast( data ); + } + catch( ... ) + { + itkExceptionMacro( << "mitk::IGTLMessage::Graft cannot cast " + << typeid(data).name() << " to " + << typeid(const Self *).name() ); + return; + } + if (!nd) + { + // pointer could not be cast back down + itkExceptionMacro( << "mitk::IGTLMessage::Graft cannot cast " + << typeid(data).name() << " to " + << typeid(const Self *).name() ); + return; + } + // Now copy anything that is needed + this->SetMessage(nd->GetMessage()); + this->SetDataValid(nd->IsDataValid()); + this->SetIGTTimeStamp(nd->GetIGTTimeStamp()); + this->SetName(nd->GetName()); +} + +void mitk::IGTLMessage::SetMessage(igtl::MessageBase::Pointer msg) +{ + m_Message = msg; + unsigned int ts = 0; + unsigned int frac = 0; + m_Message->GetTimeStamp(&ts, &frac); + this->SetIGTTimeStamp((double)ts); + this->SetDataValid(true); +} + +bool mitk::IGTLMessage::IsDataValid() const +{ + return m_DataValid; +} + + +void mitk::IGTLMessage::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "name: " << this->GetName() << std::endl; + os << indent << "data valid: " << this->IsDataValid() << std::endl; + os << indent << "TimeStamp: " << this->GetIGTTimeStamp() << std::endl; + os << indent << "OpenIGTLinkMessage: " << std::endl; + m_Message->Print(os); +} + + +void mitk::IGTLMessage::CopyInformation( const DataObject* data ) +{ + this->Superclass::CopyInformation( data ); + + const Self * nd = NULL; + try + { + nd = dynamic_cast(data); + } + catch( ... ) + { + // data could not be cast back down + itkExceptionMacro(<< "mitk::IGTLMessage::CopyInformation() cannot cast " + << typeid(data).name() << " to " + << typeid(Self*).name() ); + } + if ( !nd ) + { + // pointer could not be cast back down + itkExceptionMacro(<< "mitk::IGTLMessage::CopyInformation() cannot cast " + << typeid(data).name() << " to " + << typeid(Self*).name() ); + } + /* copy all meta data */ +} + +bool mitk::Equal(const mitk::IGTLMessage& leftHandSide, + const mitk::IGTLMessage& rightHandSide, + ScalarType /*eps*/, bool verbose) +{ + bool returnValue = true; + + if( std::string(rightHandSide.GetName()) != std::string(leftHandSide.GetName()) ) + { + if(verbose) + { + MITK_INFO << "[( IGTLMessage )] Name differs."; + MITK_INFO << "leftHandSide is " << leftHandSide.GetName() + << "rightHandSide is " << rightHandSide.GetName(); + } + returnValue = false; + } + + if( rightHandSide.GetIGTTimeStamp() != leftHandSide.GetIGTTimeStamp() ) + { + if(verbose) + { + MITK_INFO << "[( IGTLMessage )] IGTTimeStamp differs."; + MITK_INFO << "leftHandSide is " << leftHandSide.GetIGTTimeStamp() + << "rightHandSide is " << rightHandSide.GetIGTTimeStamp(); + } + returnValue = false; + } + + return returnValue; +} + +const char* mitk::IGTLMessage::GetIGTLMessageType() const +{ + return this->m_Message->GetDeviceType(); +} + +template < typename IGTLMessageType > +IGTLMessageType* mitk::IGTLMessage::GetMessage() const +{ + return dynamic_cast(this->m_Message); +} diff --git a/Modules/OpenIGTLink/mitkIGTLMessage.h b/Modules/OpenIGTLink/mitkIGTLMessage.h new file mode 100644 index 0000000000..8ff385eb36 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLMessage.h @@ -0,0 +1,197 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKIGTLMESSAGEH_HEADER_INCLUDED_ +#define MITKIGTLMESSAGEH_HEADER_INCLUDED_ + +#include +#include "MitkOpenIGTLinkExports.h" +#include +#include + +#include "igtlMessageBase.h" + +namespace mitk { + + /**Documentation + * \brief A wrapper for the OpenIGTLink message type + * + * This class represents the data object that is passed through the + * MITK-OpenIGTLink filter pipeline. It wraps the OpenIGTLink message type. + * Additionally, it contains a data structure that contains error/plausibility + * information. + * + */ + class MITKOPENIGTLINK_EXPORT IGTLMessage : public itk::DataObject + { + public: + mitkClassMacro(IGTLMessage, itk::DataObject); + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + mitkNewMacro2Param(Self, igtl::MessageBase::Pointer,std::string); + + /** + * \brief type that holds the time at which the data was recorded + */ + typedef double TimeStampType; + + /** + * \brief Sets the OpenIGTLink message + */ + void SetMessage(igtl::MessageBase::Pointer msg); + /** + * \brief returns the OpenIGTLink message + */ + itkGetConstMacro(Message, igtl::MessageBase::Pointer); + /** + * \brief returns true if the object contains valid data + */ + virtual bool IsDataValid() const; + /** + * \brief sets the dataValid flag of the IGTLMessage object indicating if + * the object contains valid data + */ + itkSetMacro(DataValid, bool); + /** + * \brief gets the IGT timestamp of the IGTLMessage object + */ + itkGetConstMacro(IGTTimeStamp, TimeStampType); + /** + * \brief set the name of the IGTLMessage object + */ + itkSetStringMacro(Name); + /** + * \brief returns the name of the IGTLMessage object + */ + itkGetStringMacro(Name); + + /** + * \brief Graft the data and information from one IGTLMessage to another. + * + * Copies the content of data into this object. + * This is a convenience method to setup a second IGTLMessage object with + * all the meta information of another IGTLMessage object. + * Note that this method is different than just using two + * SmartPointers to the same IGTLMessage object since separate DataObjects + * are still maintained. + */ + virtual void Graft(const DataObject *data); + + /** + * \brief copy meta data of a IGTLMessage object + * + * copies all meta data from IGTLMessage data to this object + */ + virtual void CopyInformation(const DataObject* data); + + /** + * \brief Prints the object information to the given stream os. + * \param os The stream which is used to print the output. + * \param indent Defines the indentation of the output. + */ + void PrintSelf(std::ostream& os, itk::Indent indent) const; + + /** Compose with another IGTLMessage + * + * This method composes self with another IGTLMessage of the + * same dimension, modifying self to be the composition of self + * and other. If the argument pre is true, then other is + * precomposed with self; that is, the resulting transformation + * consists of first applying other to the source, followed by + * self. If pre is false or omitted, then other is post-composed + * with self; that is the resulting transformation consists of + * first applying self to the source, followed by other. */ + void Compose(const mitk::IGTLMessage::Pointer n, const bool pre = false); + + /** Returns the OpenIGTL Message type + **/ + const char* GetIGTLMessageType() const; + + template < typename IGTLMessageType > IGTLMessageType* GetMessage() const; + + protected: + mitkCloneMacro(Self); + + IGTLMessage(); + + /** + * Copy constructor internally used. + */ + IGTLMessage(const mitk::IGTLMessage& toCopy); + + /** + * Creates a IGTLMessage object from an igtl::MessageBase and a given name. + */ + IGTLMessage(igtl::MessageBase::Pointer message, std::string name = ""); + + virtual ~IGTLMessage(); + + /** + * \brief holds the actual OpenIGTLink message + */ + igtl::MessageBase::Pointer m_Message; + + /** + * \brief defines if the object contains valid values + */ + bool m_DataValid; + /** + * \brief contains the time at which the tracking data was recorded + */ + TimeStampType m_IGTTimeStamp; + /** + * \brief name of the navigation data + */ + std::string m_Name; + + private: + + // pre = false + static mitk::IGTLMessage::Pointer getComposition( + const mitk::IGTLMessage::Pointer nd1, + const mitk::IGTLMessage::Pointer nd2); + + /** + * \brief sets the IGT timestamp of the IGTLMessage object + */ + itkSetMacro(IGTTimeStamp, TimeStampType); + + }; + + /** + * @brief Equal A function comparing two OpenIGTLink message objects for + * being equal in meta- and imagedata + * + * @ingroup MITKTestingAPI + * + * Following aspects are tested for equality: + * - TBD + * + * @param rightHandSide An IGTLMessage to be compared + * @param leftHandSide An IGTLMessage to be compared + * @param eps Tolarence for comparison. You can use mitk::eps in most cases. + * @param verbose Flag indicating if the user wants detailed console output + * or not. + * @return true, if all subsequent comparisons are true, false otherwise + */ + MITKOPENIGTLINK_EXPORT bool Equal( const mitk::IGTLMessage& leftHandSide, + const mitk::IGTLMessage& rightHandSide, + ScalarType eps = mitk::eps, + bool verbose = false ); + +} // namespace mitk +#endif /* MITKIGTLMESSAGEH_HEADER_INCLUDED_ */ diff --git a/Modules/OpenIGTLink/mitkIGTLMessageCloneHandler.h b/Modules/OpenIGTLink/mitkIGTLMessageCloneHandler.h new file mode 100644 index 0000000000..c27cde179a --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLMessageCloneHandler.h @@ -0,0 +1,87 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKIGTLMESSAGECLONE_H_ +#define MITKIGTLMESSAGECLONE_H_ + +#include "itkObject.h" +#include "mitkCommon.h" + +#include "igtlObject.h" +#include "igtlMacro.h" +#include "igtlSocket.h" +#include "igtlMessageBase.h" + +#include "MitkOpenIGTLinkExports.h" + +namespace mitk +{ + /**Documentation + * \brief Base class for clone handlers for igtl::MessageBase derived message + * types + * + * To enable new message types a clone function must be defined and added to the + * message factory. + * + */ + class MITKOPENIGTLINK_EXPORT IGTLMessageCloneHandler: public itk::Object + { + public: + mitkClassMacro(IGTLMessageCloneHandler, itk::Object); + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + public: + virtual igtl::MessageBase::Pointer Clone(igtl::MessageBase*) { return 0; } + + protected: + IGTLMessageCloneHandler() {} + ~IGTLMessageCloneHandler() {} +}; + +/** + * Description: + * The mitkIGTMessageCloneClassMacro() macro is to help developers to + * define message clone handler classes. It generates a chlid class of + * mitk::IGTLMessageCloneHandler. + * The developer only needs to implement Clone() after calling this macro. + * The following code shows how to define a handler that processes IMAGE message: + * + * mitkIGTMessageCloneClassMacro(igtl::ImageMessage, TestImageMessageHandler); + * igtl::MessageBase::Pointer + * TestImageMessageHandler::Clone(igtl::MessageBase * message) + * { + * // do something + * } + **/ +#define mitkIGTMessageCloneClassMacro(messagetype, classname) \ + class classname : public ::mitk::IGTLMessageCloneHandler \ + { \ + public: \ + mitkClassMacro(classname, mitk::IGTLMessageCloneHandler); \ + itkFactorylessNewMacro(Self); \ + itkCloneMacro(Self); \ + public: \ + virtual igtl::MessageBase::Pointer Clone(igtl::MessageBase*); \ + protected: \ + classname(){} \ + ~classname() {} \ + }; + + +} // namespace mitk + +#endif // MITKIGTLMESSAGECLONE_H_ diff --git a/Modules/OpenIGTLink/mitkIGTLMessageCommon.cpp b/Modules/OpenIGTLink/mitkIGTLMessageCommon.cpp new file mode 100644 index 0000000000..238da87839 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLMessageCommon.cpp @@ -0,0 +1,92 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkIGTLMessageCommon.h" +#include "mitkException.h" + +mitk::IGTLMessageCommon::IGTLMessageCommon() : itk::DataObject() +{ +} + + +mitk::IGTLMessageCommon::~IGTLMessageCommon() +{ +} + +//bool mitk::IGTLMessageCommon::Clone(igtl::TransformMessage::Pointer clone, +// igtl::TransformMessage::Pointer original) +//{ +// bool copySuccess = false; + +// //copy all meta data +// copySuccess = clone->Copy(original); + +// if ( !copySuccess ) +// return false; + +// //copy all data that is important for this class +// //copy the matrix +// igtl::Matrix4x4 mat; +// original->GetMatrix(mat); +// clone->SetMatrix(mat); + +// //copy the normals +// float normals[3][3]; +// original->GetNormals(normals); +// clone->SetNormals(normals); + +// //copy the position +// float position[3]; +// original->GetPosition(position); +// clone->SetPosition(position); + +// return true; +//} + +//igtl::MessageBase::Pointer mitk::IGTLMessageCommon::Clone(igtl::TransformMessage::Pointer original) +//{ +// bool copySuccess = false; +// igtl::TransformMessage::Pointer clone_ = igtl::TransformMessage::New(); + +// //initialize the clone +//// clone = igtl::MessageBase::New(); + +// //copy all meta data +// copySuccess = clone_->Copy(original); + +// if ( !copySuccess ) +// return false; + +// //copy all data that is important for this class +// //copy the matrix +// igtl::Matrix4x4 mat; +// original->GetMatrix(mat); +// clone_->SetMatrix(mat); + +// //copy the normals +// float normals[3][3]; +// original->GetNormals(normals); +// clone_->SetNormals(normals); + +// //copy the position +// float position[3]; +// original->GetPosition(position); +// clone_->SetPosition(position); + +// return igtl::MessageBase::Pointer(clone_.GetPointer()); + +//// return true; +//} diff --git a/Modules/OpenIGTLink/mitkIGTLMessageCommon.h b/Modules/OpenIGTLink/mitkIGTLMessageCommon.h new file mode 100644 index 0000000000..99da21714a --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLMessageCommon.h @@ -0,0 +1,73 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKIGTLMESSAGECOMMONH_HEADER_INCLUDED_ +#define MITKIGTLMESSAGECOMMONH_HEADER_INCLUDED_ + +#include +#include "MitkOpenIGTLinkExports.h" +#include +#include + +#include "igtlMessageBase.h" +#include "igtlTransformMessage.h" + +namespace mitk { + + /**Documentation + * \brief Helper class for copying OpenIGTLink messages. + * + * This class is a helper class for copying OpenIGTLink messages. + * + */ + class MITKOPENIGTLINK_EXPORT IGTLMessageCommon : public itk::DataObject + { + public: + mitkClassMacro(IGTLMessageCommon, itk::DataObject); + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + /** + * \brief Clones the input message and returns a igtl::MessageBase::Pointer + * to the clone + */ +// static igtl::MessageBase::Pointer Clone(igtl::TransformMessage::Pointer original); + + /** + * \brief Clones the input message and returns a igtl::MessageBase::Pointer + * to the clone + */ +// static igtl::MessageBase::Pointer Clone(igtl::MessageBase::Pointer original); + + + protected: + IGTLMessageCommon(); + + /** + * Copy constructor internally used. + */ +// IGTLMessageCommon(const mitk::IGTLMessageCommon& toCopy); + + virtual ~IGTLMessageCommon(); + + private: + + }; + + +} // namespace mitk +#endif /* MITKIGTLMESSAGECOMMONH_HEADER_INCLUDED_ */ diff --git a/Modules/OpenIGTLink/mitkIGTLMessageFactory.cpp b/Modules/OpenIGTLink/mitkIGTLMessageFactory.cpp new file mode 100644 index 0000000000..6b7637df12 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLMessageFactory.cpp @@ -0,0 +1,297 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkIGTLMessageFactory.h" + +// IGT message types +#include "igtlImageMessage.h" +#include "igtlTransformMessage.h" +#include "igtlPositionMessage.h" +#include "igtlStatusMessage.h" +#include "igtlImageMetaMessage.h" +#include "igtlPointMessage.h" +#include "igtlTrajectoryMessage.h" +#include "igtlStringMessage.h" +#include "igtlSensorMessage.h" +#include "igtlBindMessage.h" +#include "igtlPolyDataMessage.h" +#include "igtlQuaternionTrackingDataMessage.h" +#include "igtlCapabilityMessage.h" +#include "igtlNDArrayMessage.h" +#include "igtlTrackingDataMessage.h" +#include "igtlColorTableMessage.h" +#include "igtlLabelMetaMessage.h" + +//own types +#include "mitkIGTLDummyMessage.h" + +#include "mitkIGTLMessageCommon.h" + +#include "itksys/SystemTools.hxx" + + +//------------------------------------------------------------ +// Define message clone classes +// igtlMessageHandlerClassMacro() defines a child class of +// igtl::MessageHandler to handle OpenIGTLink messages for +// the message type specified as the first argument. The +// second argument will be used for the name of this +// message handler class, while the third argument specifies +// a type of data that will be shared with the message functions +// of this handler class. + +mitkIGTMessageCloneClassMacro(igtl::TransformMessage, TransformMsgCloneHandler); + +/** + * \brief Clones the original message interpreted as transform message + * \param original_ The original message that will be interpreted as transform + * message + * \return The clone of the input message + */ +igtl::MessageBase::Pointer TransformMsgCloneHandler::Clone(igtl::MessageBase* original_) +{ + bool copySuccess = false; + igtl::TransformMessage::Pointer clone_ = igtl::TransformMessage::New(); + + //initialize the clone + // clone = igtl::MessageBase::New(); + + igtl::TransformMessage* original = (igtl::TransformMessage*)original_; + + //copy all meta data + copySuccess = clone_->Copy(original); + + if ( !copySuccess ) + return NULL; + + //copy all data that is important for this class + //copy the matrix + igtl::Matrix4x4 mat; + original->GetMatrix(mat); + clone_->SetMatrix(mat); + + //copy the normals + float normals[3][3]; + original->GetNormals(normals); + clone_->SetNormals(normals); + + //copy the position + float position[3]; + original->GetPosition(position); + clone_->SetPosition(position); + + return igtl::MessageBase::Pointer(clone_.GetPointer()); +} + + +mitk::IGTLMessageFactory::IGTLMessageFactory() +{ + //create clone handlers +// mitk::IGTLMessageCloneHandler::Pointer tmch = ; + + this->AddMessageNewMethod("NONE", NULL); + + //OpenIGTLink Types V1 + this->AddMessageNewMethod("IMAGE", (PointerToMessageBaseNew)&igtl::ImageMessage::New); + this->AddMessageNewMethod("TRANSFORM", (PointerToMessageBaseNew)&igtl::TransformMessage::New); + this->AddMessageNewMethod("POSITION", (PointerToMessageBaseNew)&igtl::PositionMessage::New); + this->AddMessageNewMethod("STATUS", (PointerToMessageBaseNew)&igtl::StatusMessage::New); + this->AddMessageNewMethod("CAPABILITY", (PointerToMessageBaseNew)&igtl::StatusMessage::New); + + this->AddMessageNewMethod("GET_IMAGE", (PointerToMessageBaseNew)&igtl::GetImageMessage::New); + this->AddMessageNewMethod("GET_TRANS", (PointerToMessageBaseNew)&igtl::GetTransformMessage::New); +// this->AddMessageNewMethod("GET_POS", (PointerToMessageBaseNew)&igtl::GetPositionMessage::New); //not available??? + this->AddMessageNewMethod("GET_STATUS", (PointerToMessageBaseNew)&igtl::GetStatusMessage::New); + this->AddMessageNewMethod("GET_CAPABIL", (PointerToMessageBaseNew)&igtl::GetCapabilityMessage::New); + +// //OpenIGTLink Types V2 + this->AddMessageNewMethod("IMGMETA", (PointerToMessageBaseNew)&igtl::ImageMetaMessage::New); + this->AddMessageNewMethod("LBMETA", (PointerToMessageBaseNew)&igtl::LabelMetaMessage::New); + this->AddMessageNewMethod("COLORT", (PointerToMessageBaseNew)&igtl::ColorTableMessage::New); + this->AddMessageNewMethod("POINT", (PointerToMessageBaseNew)&igtl::PointMessage::New); + this->AddMessageNewMethod("TRAJ", (PointerToMessageBaseNew)&igtl::TrajectoryMessage::New); + this->AddMessageNewMethod("TDATA", (PointerToMessageBaseNew)&igtl::TrackingDataMessage::New); + this->AddMessageNewMethod("QTDATA", (PointerToMessageBaseNew)&igtl::QuaternionTrackingDataMessage::New); + this->AddMessageNewMethod("SENSOR", (PointerToMessageBaseNew)&igtl::SensorMessage::New); + this->AddMessageNewMethod("STRING", (PointerToMessageBaseNew)&igtl::StringMessage::New); + this->AddMessageNewMethod("NDARRAY", (PointerToMessageBaseNew)&igtl::NDArrayMessage::New); + this->AddMessageNewMethod("BIND", (PointerToMessageBaseNew)&igtl::BindMessage::New); + this->AddMessageNewMethod("POLYDATA", (PointerToMessageBaseNew)&igtl::PolyDataMessage::New); + + this->AddMessageNewMethod("GET_IMGMETA", (PointerToMessageBaseNew)&igtl::GetImageMetaMessage::New); + this->AddMessageNewMethod("GET_LBMETA", (PointerToMessageBaseNew)&igtl::GetLabelMetaMessage::New); + this->AddMessageNewMethod("GET_COLORT", (PointerToMessageBaseNew)&igtl::GetColorTableMessage::New); + this->AddMessageNewMethod("GET_POINT", (PointerToMessageBaseNew)&igtl::GetPointMessage::New); + this->AddMessageNewMethod("GET_TRAJ", (PointerToMessageBaseNew)&igtl::GetTrajectoryMessage::New); +// this->AddMessageNewMethod("GET_TDATA", (PointerToMessageBaseNew)&igtl::GetTrackingDataMessage::New); //not available??? +// this->AddMessageNewMethod("GET_QTDATA", (PointerToMessageBaseNew)&igtl::GetQuaternionTrackingDataMessage::New); +// this->AddMessageNewMethod("GET_SENSOR", (PointerToMessageBaseNew)&igtl::GetSensorMessage::New); +// this->AddMessageNewMethod("GET_STRING", (PointerToMessageBaseNew)&igtl::GetStringMessage::New); +// this->AddMessageNewMethod("GET_NDARRAY", (PointerToMessageBaseNew)&igtl::GetNDArrayMessage::New); + this->AddMessageNewMethod("GET_BIND", (PointerToMessageBaseNew)&igtl::GetBindMessage::New); + this->AddMessageNewMethod("GET_POLYDATA", (PointerToMessageBaseNew)&igtl::GetPolyDataMessage::New); + + this->AddMessageNewMethod("RTS_BIND", (PointerToMessageBaseNew)&igtl::RTSBindMessage::New); + this->AddMessageNewMethod("RTS_QTDATA", (PointerToMessageBaseNew)&igtl::RTSQuaternionTrackingDataMessage::New); + this->AddMessageNewMethod("RTS_TDATA", (PointerToMessageBaseNew)&igtl::RTSTrackingDataMessage::New); + //todo: check if there are more RTS messages + + this->AddMessageNewMethod("STT_BIND", (PointerToMessageBaseNew)&igtl::StartBindMessage::New); + this->AddMessageNewMethod("STT_TDATA", (PointerToMessageBaseNew)&igtl::StartTrackingDataMessage::New); + this->AddMessageNewMethod("STT_QTDATA", (PointerToMessageBaseNew)&igtl::StartQuaternionTrackingDataMessage::New); + //todo: check if there are more STT messages + + this->AddMessageNewMethod("STP_BIND", (PointerToMessageBaseNew)&igtl::StopBindMessage::New); + this->AddMessageNewMethod("STP_TDATA", (PointerToMessageBaseNew)&igtl::StopTrackingDataMessage::New); + this->AddMessageNewMethod("STP_QTDATA", (PointerToMessageBaseNew)&igtl::StopQuaternionTrackingDataMessage::New); + //todo: check if there are more STP messages + + //Own Types + this->AddMessageNewMethod("DUMMY", (PointerToMessageBaseNew)&mitk::IGTLDummyMessage::New); +} + +mitk::IGTLMessageFactory::~IGTLMessageFactory() +{ +} + +void mitk::IGTLMessageFactory::AddMessageType(std::string messageTypeName, + IGTLMessageFactory::PointerToMessageBaseNew messageTypeNewPointer, + mitk::IGTLMessageCloneHandler::Pointer cloneHandler) +{ + this->AddMessageNewMethod(messageTypeName, messageTypeNewPointer); + this->AddMessageCloneHandler(messageTypeName, cloneHandler); +} + +void mitk::IGTLMessageFactory::AddMessageNewMethod(std::string messageTypeName, + IGTLMessageFactory::PointerToMessageBaseNew messageTypeNewPointer ) +{ + this->m_NewMethods[messageTypeName] = messageTypeNewPointer; +} + +void mitk::IGTLMessageFactory::AddMessageCloneHandler(std::string msgTypeName, + mitk::IGTLMessageCloneHandler::Pointer cloneHandler ) +{ + this->m_CloneHandlers[msgTypeName] = cloneHandler; +} + +mitk::IGTLMessageCloneHandler::Pointer +mitk::IGTLMessageFactory::GetCloneHandler(std::string messageTypeName) +{ + if ( this->m_CloneHandlers.find(messageTypeName) != + this->m_CloneHandlers.end() ) + { + return m_CloneHandlers[messageTypeName]; + } + + MITK_ERROR("IGTLMessageFactory") << messageTypeName << + " message type is not registered to factory!"; + + mitkThrow() << messageTypeName << " message type is not registered to factory!"; + + return NULL; +} + +igtl::MessageBase::Pointer +mitk::IGTLMessageFactory::Clone(igtl::MessageBase::Pointer msg) +{ + return this->GetCloneHandler(msg->GetDeviceType())->Clone(msg); +} + +mitk::IGTLMessageFactory::PointerToMessageBaseNew +mitk::IGTLMessageFactory::GetMessageTypeNewPointer(std::string messageTypeName) +{ + if ( this->m_NewMethods.find(messageTypeName) != this->m_NewMethods.end() ) + { + return m_NewMethods[messageTypeName]; + } + + MITK_ERROR("IGTLMessageFactory") << messageTypeName << + " message type is not registered to factory!"; + return NULL; +} + +igtl::MessageBase::Pointer +mitk::IGTLMessageFactory::CreateInstance(std::string messageTypeName) +{ + mitk::IGTLMessageFactory::PointerToMessageBaseNew newPointer = + this->GetMessageTypeNewPointer(messageTypeName); + if ( newPointer != NULL ) + { + return newPointer(); + } + else + { + return NULL; + } +} + +std::list +mitk::IGTLMessageFactory::GetAvailableMessageRequestTypes() +{ + std::list allGetMessages; + for ( std::map::const_iterator it = + this->m_NewMethods.begin(); + it != this->m_NewMethods.end(); ++it) + { + if ( it->first.find("GET_") != std::string::npos || + it->first.find("STT_") != std::string::npos || + it->first.find("STP_") != std::string::npos || + it->first.find("RTS_") != std::string::npos) + { + allGetMessages.push_back(it->first); + } + } + + return allGetMessages; +} + +igtl::MessageBase::Pointer +mitk::IGTLMessageFactory::CreateInstance(igtl::MessageHeader::Pointer msgHeader) +{ + std::string messageType; + + //check the header + if ( msgHeader.IsNull() ) + { + messageType = "NONE"; + } + else + { + messageType = msgHeader->GetDeviceType(); + } + + //make message type uppercase + messageType = itksys::SystemTools::UpperCase(messageType); + + //find the according new method + if ( this->m_NewMethods.find( messageType ) + != this->m_NewMethods.end() ) + { + if ( this->m_NewMethods[messageType] != NULL) + { + // Call tracker New() function if tracker not NULL + return (*this->m_NewMethods[messageType])(); + } + else + return NULL; + } + else + { + MITK_ERROR("IGTLMessageFactory") << "Unknown IGT message type: " + << messageType; + return NULL; + } +} diff --git a/Modules/OpenIGTLink/mitkIGTLMessageFactory.h b/Modules/OpenIGTLink/mitkIGTLMessageFactory.h new file mode 100644 index 0000000000..dc8f1807f8 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLMessageFactory.h @@ -0,0 +1,152 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKIGTLMESSAGEFACTORYH_HEADER_INCLUDED_ +#define MITKIGTLMESSAGEFACTORYH_HEADER_INCLUDED_ + +#include "MitkOpenIGTLinkExports.h" +#include "mitkCommon.h" + +#include "igtlMessageBase.h" +#include "igtlMessageHeader.h" + +#include "mitkIGTLMessageCloneHandler.h" + +namespace mitk { + /** + * \brief Factory class of supported OpenIGTLink message types + * + * This class is a factory for the creation of OpenIGTLink messages. It stores + * pairs of type and pointer to the message new method. Available standard types + * are already added but you can also add your custom types at runtime. + * + */ + class MITKOPENIGTLINK_EXPORT IGTLMessageFactory : public itk::Object + { + public: + mitkClassMacro(IGTLMessageFactory, itk::Object) + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + /** + * \brief Function pointer for storing New() static methods of + * igtl::MessageBase classes + */ + typedef igtl::MessageBase::Pointer (*PointerToMessageBaseNew)(); + + /** + * \brief Add message type name and pointer to IGTL message new function and + * the clone handler + * \param messageTypeName The name of the message type + * \param messageTypeNewPointer Function pointer to the message type new + * function (e.g. (PointerToMessageBaseNew)&igtl::ImageMessage::New ) + * \param cloneHandler pointer to the message clone object + */ + void AddMessageType(std::string messageTypeName, + IGTLMessageFactory::PointerToMessageBaseNew messageTypeNewPointer, + mitk::IGTLMessageCloneHandler::Pointer cloneHandler); + + /** + * \brief Add message type name and pointer to IGTL message new function + * Usage: + * AddMessageType("IMAGE", (PointerToMessageBaseNew)&igtl::ImageMessage::New); + * \param messageTypeName The name of the message type + * \param messageTypeNewPointer Function pointer to the message type new + * function (e.g. (PointerToMessageBaseNew)&igtl::ImageMessage::New ) + */ + virtual void AddMessageNewMethod(std::string messageTypeName, + IGTLMessageFactory::PointerToMessageBaseNew messageTypeNewPointer); + + /** + * \brief Get pointer to message type new function, or NULL if the message + * type not registered + * Usage: + * igtl::MessageBase::Pointer message = GetMessageTypeNewPointer("IMAGE")(); + */ + virtual IGTLMessageFactory::PointerToMessageBaseNew GetMessageTypeNewPointer( + std::string messageTypeName); + + /** + * \brief Creates a new message instance fitting to the given type. + * + * If this type is not registered it returns NULL + * Usage: + * igtl::MessageBase::Pointer message = CreateInstance("IMAGE"); + */ + igtl::MessageBase::Pointer CreateInstance(std::string messageTypeName); + + /** + * \brief Creates a new message according to the given header + * \param msg The message header that defines the type of the message + * This method checks the data type and creates a new message according to the + * type. + */ + igtl::MessageBase::Pointer CreateInstance(igtl::MessageHeader::Pointer msg); + + /** + * \brief Adds a clone function for the specified message type + * \param msgTypeName The name of the message type + * \param msgCloneHandler Function pointer to the message clone function + * (e.g. TBD ) + */ + virtual void AddMessageCloneHandler(std::string msgTypeName, + mitk::IGTLMessageCloneHandler::Pointer msgCloneHandler); + + /** + * \brief Get pointer to message type clone function, or NULL if the message + * type is not registered + * Usage: + * igtl::TransformMessage::Pointer original = igtl::TransformMessage::New(); + * igtl::MessageBase::Pointer message = + * GetCloneHandler("IMAGE")->Clone(original); + */ + virtual mitk::IGTLMessageCloneHandler::Pointer + GetCloneHandler(std::string messageTypeName); + + /** + * \brief Clones the given message according to the available clone methods + * \param msg The message that has to be cloned + * This method checks the data type and clones the message according to this + * type. + */ + igtl::MessageBase::Pointer Clone(igtl::MessageBase::Pointer msg); + + /** + * \brief Returns available get messages + */ + std::list GetAvailableMessageRequestTypes(); + + protected: + IGTLMessageFactory(); + virtual ~IGTLMessageFactory(); + + /** + * \brief Map igt message types and the Clone() methods + */ + std::map m_CloneHandlers; + + /** + * \brief Map igt message types and the New() static methods of igtl::MessageBase + * classes + */ + std::map m_NewMethods; + + private: + IGTLMessageFactory(const IGTLMessageFactory&); + }; +} + +#endif diff --git a/Modules/OpenIGTLink/mitkIGTLMessageProvider.cpp b/Modules/OpenIGTLink/mitkIGTLMessageProvider.cpp new file mode 100644 index 0000000000..69942a3288 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLMessageProvider.cpp @@ -0,0 +1,371 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkIGTLMessageProvider.h" + +#include "mitkIGTLDevice.h" +#include "mitkIGTLMessage.h" +#include "mitkIGTLMessageFactory.h" + +#include "mitkCallbackFromGUIThread.h" + +//Microservices +#include "usServiceReference.h" +#include "usModuleContext.h" +#include "usServiceEvent.h" +#include "mitkServiceInterface.h" +#include "usGetModuleContext.h" + +//igt (remove this later) +#include "igtlBindMessage.h" +#include "igtlQuaternionTrackingDataMessage.h" +#include "igtlTrackingDataMessage.h" + +#ifndef WIN32 +#include +#endif + +mitk::IGTLMessageProvider::IGTLMessageProvider() + : mitk::IGTLDeviceSource() +{ + this->SetName("IGTLMessageProvider"); + m_MultiThreader = itk::MultiThreader::New(); + m_StreamingTimeMutex = itk::FastMutexLock::New(); + m_StopStreamingThreadMutex = itk::FastMutexLock::New(); + m_ThreadId = 0; + m_IsStreaming = false; +} + +mitk::IGTLMessageProvider::~IGTLMessageProvider() +{ + // terminate worker thread on destruction + this->m_StopStreamingThreadMutex->Lock(); + this->m_StopStreamingThread = true; + this->m_StopStreamingThreadMutex->Unlock(); + if ( m_ThreadId >= 0) + { + this->m_MultiThreader->TerminateThread(m_ThreadId); + } +} + +void mitk::IGTLMessageProvider::GenerateData() +{ + if (this->m_IGTLDevice.IsNull()) + return; + + for (unsigned int index = 0; index < this->GetNumberOfIndexedInputs(); index++) + { + const IGTLMessage* msg = this->GetInput(index); + assert(msg); + + if ( !msg->IsDataValid() ) + { + continue; + } + + igtl::MessageBase::Pointer igtlMsg = msg->GetMessage(); + + if ( igtlMsg.IsNotNull() ) + { + //send the message + this->m_IGTLDevice->SendMessage(igtlMsg); + } + } +} + +void mitk::IGTLMessageProvider::CreateOutputs() +{ + //if outputs are set then delete them + if (this->GetNumberOfOutputs() > 0) + { + for (int numOP = this->GetNumberOfOutputs() - 1; numOP >= 0; numOP--) + this->RemoveOutput(numOP); + this->Modified(); + } + + //fill the outputs if a valid OpenIGTLink device is set + if (m_IGTLDevice.IsNull()) + return; + + this->SetNumberOfIndexedOutputs(1); + if (this->GetOutput(0) == NULL) + { + DataObjectPointer newOutput = this->MakeOutput(0); + this->SetNthOutput(0, newOutput); + this->Modified(); + } +} + +//void mitk::IGTLMessageProvider::UpdateOutputInformation() +//{ +// this->Modified(); // make sure that we need to be updated +// Superclass::UpdateOutputInformation(); +//} + + +void mitk::IGTLMessageProvider::OnIncomingMessage() +{ + +} + +std::string RemoveRequestPrefixes(std::string requestType) +{ + return requestType.substr(4); +} + +void mitk::IGTLMessageProvider::OnIncomingCommand() +{ + //get the next command + igtl::MessageBase::Pointer curCommand = this->m_IGTLDevice->GetNextCommand(); + //extract the type + const char * requestType = curCommand->GetDeviceType(); + //check the type + std::string reqType(requestType); + bool isGetMsg = !reqType.find("GET_"); + bool isSTTMsg = !reqType.find("STT_"); + bool isSTPMsg = !reqType.find("STP_"); + bool isRTSMsg = !reqType.find("RTS_"); + //get the type from the request type (remove STT_, STP_, GET_, RTS_) + std::string type = RemoveRequestPrefixes(requestType); + //check all microservices if there is a fitting source for the requested type + mitk::IGTLMessageSource::Pointer source = this->GetFittingSource(type.c_str()); + //if there is no fitting source return a RTS message, if there is a RTS + //type defined in the message factory send it + if ( source.IsNull() ) + { + if ( !this->GetIGTLDevice()->SendRTSMessage(type.c_str()) ) + { + //sending RTS message failed, probably because the type is not in the + //message factory + MITK_WARN("IGTLMessageProvider") << "Tried to send a RTS message but did " + "not succeed. Check if this type ( " + << type << " ) was added to the message " + "factory. "; + } + } + else + { + if ( isGetMsg ) //if it is a single value push it into sending queue + { + //first it is necessary to update the source. This needs additional time + //but is necessary. But are we really allowed to call this here? In which + //thread are we? Is the source thread safe? + source->Update(); + mitk::IGTLMessage::Pointer sourceOutput = source->GetOutput(); + if (sourceOutput.IsNotNull() && sourceOutput->IsDataValid()) + { + igtl::MessageBase::Pointer sourceMsg = sourceOutput->GetMessage(); + if ( source.IsNotNull() ) + { + this->GetIGTLDevice()->SendMessage(sourceMsg); + } + } + } + else if ( isSTTMsg ) + { + //read the requested frames per second + int fps = 10; + + //read the fps from the command + igtl::MessageBase* curCommandPt = curCommand.GetPointer(); + if ( std::strcmp( curCommand->GetDeviceType(), "STT_BIND" ) == 0 ) + { + fps = ((igtl::StartBindMessage*)curCommandPt)->GetResolution(); + } + else if ( std::strcmp( curCommand->GetDeviceType(), "STT_QTDATA" ) == 0 ) + { + fps = ((igtl::StartQuaternionTrackingDataMessage*)curCommandPt)->GetResolution(); + } + else if ( std::strcmp( curCommand->GetDeviceType(), "STT_TDATA" ) == 0 ) + { + fps = ((igtl::StartTrackingDataMessage*)curCommandPt)->GetResolution(); + } + + this->StartStreamingOfSource(source, fps); + } + else if ( isSTPMsg ) + { + this->StopStreamingOfSource(source); + } + else + { + //do nothing + } + } +} + +bool mitk::IGTLMessageProvider::IsStreaming() +{ + return m_IsStreaming; +} + +void mitk::IGTLMessageProvider::StartStreamingOfSource(IGTLMessageSource* src, + unsigned int fps) +{ + if ( src == NULL ) + return; + + //so far the provider allows the streaming of a single source only + //if the streaming thread is already running return a RTS message + if ( !m_IsStreaming ) + { + //if it is a stream establish a connection between the provider and the + //source + this->ConnectTo(src); + + // calculate the streaming time + this->m_StreamingTimeMutex->Lock(); + this->m_StreamingTime = 1.0 / (double) fps * 1000.0; + this->m_StreamingTimeMutex->Unlock(); + + // Create a command object. The function will be called later from the + // main thread + this->m_StreamingCommand = ProviderCommand::New(); + m_StreamingCommand->SetCallbackFunction(this, + &mitk::IGTLMessageProvider::Update); + + // For streaming we need a continues time signal, since there is no timer + // available we start a thread that generates a timing signal + // This signal is invoked from the other thread the update of the pipeline + // has to be executed from the main thread. Thus, we use the + // callbackfromGUIThread class to pass the execution to the main thread + this->m_ThreadId = m_MultiThreader->SpawnThread(this->TimerThread, this); + this->m_IsStreaming = true; + } + else + { + MITK_WARN("IGTLMessageProvider") << "This provider just supports the " + "streaming of one source."; + } +} + +void mitk::IGTLMessageProvider::StopStreamingOfSource(IGTLMessageSource* src) +{ + //this is something bad!!! The streaming thread has to be stopped before the + //source is disconnected otherwise it can cause a crash. This has to be added!! + this->DisconnectFrom(src); + + this->m_StopStreamingThreadMutex->Lock(); + this->m_StopStreamingThread = true; + this->m_StopStreamingThreadMutex->Unlock(); + + //does this flag needs a mutex??? + this->m_IsStreaming = false; +} + +mitk::IGTLMessageSource::Pointer mitk::IGTLMessageProvider::GetFittingSource(const char* requestedType) +{ + //get the context + us::ModuleContext* context = us::GetModuleContext(); + //define the interface name + std::string interface = mitk::IGTLMessageSource::US_INTERFACE_NAME; + //specify a filter that defines the requested type + std::string filter = "(" + mitk::IGTLMessageSource::US_PROPKEY_DEVICETYPE + + "=" + requestedType + ")"; + //find the fitting service + std::vector serviceReferences = + context->GetServiceReferences(interface, filter); + + //check if a service reference was found. It is also possible that several + //services were found. This is not checked here, just the first one is taken. + if ( serviceReferences.size() ) + { + mitk::IGTLMessageSource::Pointer curSource = + context->GetService(serviceReferences.front()); + + if ( curSource.IsNotNull() ) + return curSource; + } + //no service reference was found or found service reference has no valid source + return NULL; +} + +void mitk::IGTLMessageProvider::Send(const mitk::IGTLMessage* msg) +{ + if (msg != NULL) + this->m_IGTLDevice->SendMessage(msg); +} + +void +mitk::IGTLMessageProvider::ConnectTo( mitk::IGTLMessageSource* UpstreamFilter ) +{ + for (DataObjectPointerArraySizeType i = 0; + i < UpstreamFilter->GetNumberOfOutputs(); i++) + { + this->SetInput(i, UpstreamFilter->GetOutput(i)); + } +} + +void +mitk::IGTLMessageProvider::DisconnectFrom( mitk::IGTLMessageSource* UpstreamFilter ) +{ + for (DataObjectPointerArraySizeType i = 0; + i < UpstreamFilter->GetNumberOfOutputs(); i++) + { + this->RemoveInput(UpstreamFilter->GetOutput(i)); + } +} + +ITK_THREAD_RETURN_TYPE mitk::IGTLMessageProvider::TimerThread(void* pInfoStruct) +{ + // extract this pointer from thread info structure + struct itk::MultiThreader::ThreadInfoStruct * pInfo = + (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; + mitk::IGTLMessageProvider* thisObject = + static_cast(pInfo->UserData); + + itk::SimpleMutexLock mutex; + mutex.Lock(); + + thisObject->m_StopStreamingThreadMutex->Lock(); + thisObject->m_StopStreamingThread = false; + thisObject->m_StopStreamingThreadMutex->Unlock(); + + thisObject->m_StreamingTimeMutex->Lock(); + unsigned int waitingTime = thisObject->m_StreamingTime; + thisObject->m_StreamingTimeMutex->Unlock(); + + while (true) + { + thisObject->m_StopStreamingThreadMutex->Lock(); + bool stopThread = thisObject->m_StopStreamingThread; + thisObject->m_StopStreamingThreadMutex->Unlock(); + + if (stopThread) + { + break; + } + + //wait for the time given + //I know it is not the nicest solution but we just need an approximate time + //sleeps for 20 ms + #if defined (WIN32) || defined (_WIN32) + Sleep(waitingTime); + #else + usleep(waitingTime * 1000); + #endif + + // Ask to execute that command from the GUI thread + mitk::CallbackFromGUIThread::GetInstance()->CallThisFromGUIThread( + thisObject->m_StreamingCommand); + } + + thisObject->m_ThreadId = 0; + + mutex.Unlock(); + + return ITK_THREAD_RETURN_VALUE; +} diff --git a/Modules/OpenIGTLink/mitkIGTLMessageProvider.h b/Modules/OpenIGTLink/mitkIGTLMessageProvider.h new file mode 100644 index 0000000000..bef9bbdad1 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLMessageProvider.h @@ -0,0 +1,178 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef IGTLMESSAGEPROVIDER_H_HEADER_INCLUDED_ +#define IGTLMESSAGEPROVIDER_H_HEADER_INCLUDED_ + +#include "mitkIGTLDevice.h" +#include "mitkIGTLDeviceSource.h" + +//itk +#include "itkCommand.h" + +namespace mitk { + /** + * \brief Provides information/objects from a MITK-Pipeline to other OpenIGTLink + * devices + * + * This class is intended as the drain of the pipeline. Other OpenIGTLink + * devices connect with the IGTLDevice hold by this provider. The other device + * asks for a certain data type. The provider checks if there are other + * IGTLMessageSources available that provide this data type. If yes the provider + * connects with this source and sends the message to the requesting device. + * + * If a STT message was received the provider looks for fitting messageSources. + * Once found it connects with it, starts a timing thread (which updates the + * pipeline) and sends the result to the requesting device. + * + * If a GET message was received the provider just calls an update of the + * found source and sends the result without connecting to the source. + * + * If a STP message was received it stops the thread and disconnects from the + * previous source. + * + * So far the provider can just connect with one source. + * + * \ingroup OpenIGTLink + */ + class MITKOPENIGTLINK_EXPORT IGTLMessageProvider : public IGTLDeviceSource + { + public: + mitkClassMacro(IGTLMessageProvider, IGTLDeviceSource); + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + typedef itk::SimpleMemberCommand ProviderCommand; + + /** + * \brief sends the msg to the requesting client + * + * Note: so far it broadcasts the message to all registered clients + */ + void Send(const IGTLMessage* msg); + + /** + * \brief Starts the streaming of the given message source with the given fps. + */ + void StartStreamingOfSource(mitk::IGTLMessageSource* src, + unsigned int fps); + + /** + * \brief Stops the streaming of the given message source. + */ + void StopStreamingOfSource(mitk::IGTLMessageSource* src); + + /** + * \brief Returns the streaming state. + */ + bool IsStreaming(); + + protected: + IGTLMessageProvider(); + virtual ~IGTLMessageProvider(); + + /** + * \brief filter execute method + * + * queries the OpenIGTLink device for new messages and updates its output + * igtl::MessageBase objects with it. + * \warning Will raise a std::out_of_range exception, if tools were added to + * the OpenIGTLink device after it was set as input for this filter + */ + virtual void GenerateData(); + + /** + * \brief Create the necessary outputs for the m_IGTLDevice + * + * This Method is called internally whenever outputs need to be reset. Old + * Outputs are deleted when called. + **/ + void CreateOutputs(); + + /** + * \brief This method is called when the IGTL device hold by this class + * receives a new message + **/ + virtual void OnIncomingMessage(); + + /** + * \brief This method is called when the IGTL device hold by this class + * receives a new command + **/ + virtual void OnIncomingCommand(); + + /** + *\brief Connects the input of this filter to the outputs of the given + * IGTLMessageSource + * + * This method does not support smartpointer. use FilterX.GetPointer() to + * retrieve a dumbpointer. + */ + void ConnectTo( mitk::IGTLMessageSource* UpstreamFilter ); + + /** + *\brief Disconnects this filter from the outputs of the given + * IGTLMessageSource + * + * This method does not support smartpointer. use FilterX.GetPointer() to + * retrieve a dumbpointer. + */ + void DisconnectFrom( mitk::IGTLMessageSource* UpstreamFilter ); + + /** + * \brief Looks for microservices that provide messages with the requested + * type. + **/ + mitk::IGTLMessageSource::Pointer GetFittingSource(const char* requestedType); + + private: + /** + * \brief a command that has to be executed in the main thread + */ + ProviderCommand::Pointer m_StreamingCommand; + + /** + * \brief Timer thread for generating a continuous time signal for the stream + * + * Everyt time the time is passed a time signal is invoked. + * + * \param pInfoStruct pointer to the mitkIGTLMessageProvider object + * \return + */ + static ITK_THREAD_RETURN_TYPE TimerThread(void* pInfoStruct); + + int m_ThreadId; + + /** \brief timer thread will terminate after the next wakeup if set to true */ + bool m_StopStreamingThread; + + itk::SmartPointer m_MultiThreader; + + /** \brief the time used for streaming */ + unsigned int m_StreamingTime; + + /** \brief mutex for guarding m_Time */ + itk::SmartPointer m_StreamingTimeMutex; + + /** \brief mutex for guarding m_StopStreamingThread */ + itk::SmartPointer m_StopStreamingThreadMutex; + + /** \brief flag to indicate if the provider is streaming */ + bool m_IsStreaming; + + }; +} // namespace mitk +#endif /* MITKIGTLMESSAGEPROVIDER_H_HEADER_INCLUDED_ */ diff --git a/Modules/OpenIGTLink/mitkIGTLMessageQueue.cpp b/Modules/OpenIGTLink/mitkIGTLMessageQueue.cpp new file mode 100644 index 0000000000..26f3e91d81 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLMessageQueue.cpp @@ -0,0 +1,142 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkIGTLMessageQueue.h" +#include +#include "igtlMessageBase.h" + + + +void mitk::IGTLMessageQueue::PushMessage( igtl::MessageBase::Pointer message ) +{ + this->m_Mutex->Lock(); + if ( this->m_BufferingType == IGTLMessageQueue::Infinit ) + { + this->m_Queue.push_back( message ); + } + else //NoBuffering + { + this->m_Queue.clear(); + this->m_Queue.push_back( message ); + } + this->m_Mutex->Unlock(); +} + +igtl::MessageBase::Pointer mitk::IGTLMessageQueue::PullMessage() +{ + this->m_Mutex->Lock(); + igtl::MessageBase::Pointer ret = NULL; + if ( this->m_Queue.size() > 0 ) + { + ret = this->m_Queue.front(); + this->m_Queue.pop_front(); + } + this->m_Mutex->Unlock(); + + return ret; +} + +std::string mitk::IGTLMessageQueue::GetNextMsgInformationString() +{ + this->m_Mutex->Lock(); + std::stringstream s; + if ( this->m_Queue.size() > 0 ) + { + s << "Device Type: " << this->m_Queue.front()->GetDeviceType() << std::endl; + s << "Device Name: " << this->m_Queue.front()->GetDeviceName() << std::endl; + } + else + { + s << "No Msg"; + } + this->m_Mutex->Unlock(); + return s.str(); +} + +std::string mitk::IGTLMessageQueue::GetNextMsgDeviceType() +{ + this->m_Mutex->Lock(); + std::stringstream s; + if ( this->m_Queue.size() > 0 ) + { + s << this->m_Queue.front()->GetDeviceType(); + } + else + { + s << ""; + } + this->m_Mutex->Unlock(); + return s.str(); +} + +std::string mitk::IGTLMessageQueue::GetLatestMsgInformationString() +{ + this->m_Mutex->Lock(); + std::stringstream s; + if ( this->m_Queue.size() > 0 ) + { + s << "Device Type: " << this->m_Queue.back()->GetDeviceType() << std::endl; + s << "Device Name: " << this->m_Queue.back()->GetDeviceName() << std::endl; + } + else + { + s << "No Msg"; + } + this->m_Mutex->Unlock(); + return s.str(); +} + +std::string mitk::IGTLMessageQueue::GetLatestMsgDeviceType() +{ + this->m_Mutex->Lock(); + std::stringstream s; + if ( this->m_Queue.size() > 0 ) + { + s << this->m_Queue.back()->GetDeviceType(); + } + else + { + s << ""; + } + this->m_Mutex->Unlock(); + return s.str(); +} + +int mitk::IGTLMessageQueue::GetSize() +{ + return this->m_Queue.size(); +} + +void mitk::IGTLMessageQueue::EnableInfiniteBuffering(bool enable) +{ + this->m_Mutex->Lock(); + if ( enable ) + this->m_BufferingType = IGTLMessageQueue::Infinit; + else + this->m_BufferingType = IGTLMessageQueue::NoBuffering; + this->m_Mutex->Unlock(); +} + +mitk::IGTLMessageQueue::IGTLMessageQueue() +{ + this->m_Mutex = itk::FastMutexLock::New(); + this->m_BufferingType = IGTLMessageQueue::Infinit; +} + +mitk::IGTLMessageQueue::~IGTLMessageQueue() +{ + this->m_Mutex->Unlock(); +} diff --git a/Modules/OpenIGTLink/mitkIGTLMessageQueue.h b/Modules/OpenIGTLink/mitkIGTLMessageQueue.h new file mode 100644 index 0000000000..8caccc6c5f --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLMessageQueue.h @@ -0,0 +1,118 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef IGTLMessageQueue_H +#define IGTLMessageQueue_H + +#include "MitkOpenIGTLinkExports.h" + +#include "itkObject.h" +#include "itkFastMutexLock.h" +#include "mitkCommon.h" + +#include + +#include "igtlMessageBase.h" + + +namespace mitk { + /** + * \class IGTLMessageQueue + * \brief Thread safe message queue to store OpenIGTLink messages. + * + * \ingroup OpenIGTLink + */ + class MITKOPENIGTLINK_EXPORT IGTLMessageQueue : public itk::Object + { + public: + mitkClassMacro(mitk::IGTLMessageQueue, itk::Object) + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + /** + * \brief Different buffering types + * Infinit buffering means that you can push as many messages as you want + * NoBuffering means that the queue just stores a single message + */ + enum BufferingType {Infinit, NoBuffering}; + + /** + * \brief Adds the message to the queue + */ + void PushMessage( igtl::MessageBase::Pointer message ); + /** + * \brief Returns and removes the oldest message from the queue + */ + igtl::MessageBase::Pointer PullMessage(); + + /** + * \brief Get the number of messages in the queue + */ + int GetSize(); + + /** + * \brief Returns a string with information about the oldest message in the + * queue + */ + std::string GetNextMsgInformationString(); + + /** + * \brief Returns the device type of the oldest message in the queue + */ + std::string GetNextMsgDeviceType(); + + /** + * \brief Returns a string with information about the oldest message in the + * queue + */ + std::string GetLatestMsgInformationString(); + + /** + * \brief Returns the device type of the oldest message in the queue + */ + std::string GetLatestMsgDeviceType(); + + /** + * \brief Sets infinite buffering on/off. + * Initiale value is enabled. + */ + void EnableInfiniteBuffering(bool enable); + + protected: + IGTLMessageQueue(); + virtual ~IGTLMessageQueue(); + + + protected: + /** + * \brief Mutex to take car of the queue + */ + itk::FastMutexLock::Pointer m_Mutex; + + /** + * \brief the queue that stores pointer to the inserted messages + */ + std::deque< igtl::MessageBase::Pointer > m_Queue; + + /** + * \brief defines the kind of buffering + */ + BufferingType m_BufferingType; + }; +} + + +#endif diff --git a/Modules/OpenIGTLink/mitkIGTLMessageSource.cpp b/Modules/OpenIGTLink/mitkIGTLMessageSource.cpp new file mode 100644 index 0000000000..0ff2b4ae5a --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLMessageSource.cpp @@ -0,0 +1,196 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkIGTLMessageSource.h" +#include "mitkUIDGenerator.h" + +//Microservices +#include +#include +#include +#include + +const std::string mitk::IGTLMessageSource::US_INTERFACE_NAME = + "org.mitk.services.IGTLMessageSource"; +const std::string mitk::IGTLMessageSource::US_PROPKEY_DEVICENAME = + US_INTERFACE_NAME + ".devicename"; +const std::string mitk::IGTLMessageSource::US_PROPKEY_DEVICETYPE = + US_INTERFACE_NAME + ".devicetype"; +const std::string mitk::IGTLMessageSource::US_PROPKEY_ID = + US_INTERFACE_NAME + ".id"; +const std::string mitk::IGTLMessageSource::US_PROPKEY_ISACTIVE = + US_INTERFACE_NAME + ".isActive"; + +mitk::IGTLMessageSource::IGTLMessageSource() + : itk::ProcessObject(), m_Name("IGTLMessageSource (no defined type)"), + m_Type("NONE"), m_StreamingFPS(0) +{ + m_StreamingFPSMutex = itk::FastMutexLock::New(); +} + +mitk::IGTLMessageSource::~IGTLMessageSource() +{ + this->UnRegisterMicroservice(); +} + +mitk::IGTLMessage* mitk::IGTLMessageSource::GetOutput() +{ + if (this->GetNumberOfIndexedOutputs() < 1) + return NULL; + + return static_cast(this->ProcessObject::GetPrimaryOutput()); +} + +mitk::IGTLMessage* mitk::IGTLMessageSource::GetOutput( + DataObjectPointerArraySizeType idx) +{ + IGTLMessage* out = + dynamic_cast( this->ProcessObject::GetOutput(idx) ); + if ( out == NULL && this->ProcessObject::GetOutput(idx) != NULL ) + { + itkWarningMacro (<< "Unable to convert output number " << idx << " to type " + << typeid( IGTLMessage ).name () ); + } + return out; +} + +mitk::IGTLMessage* mitk::IGTLMessageSource::GetOutput( + const std::string& messageName) +{ + DataObjectPointerArray outputs = this->GetOutputs(); + for (DataObjectPointerArray::iterator it = outputs.begin(); + it != outputs.end(); + ++it) + { + if (messageName == + (static_cast(it->GetPointer()))->GetName()) + { + return static_cast(it->GetPointer()); + } + } + return NULL; +} + +itk::ProcessObject::DataObjectPointerArraySizeType +mitk::IGTLMessageSource::GetOutputIndex( std::string messageName ) +{ + DataObjectPointerArray outputs = this->GetOutputs(); + for (DataObjectPointerArray::size_type i = 0; i < outputs.size(); ++i) + { + if (messageName == + (static_cast(outputs.at(i).GetPointer()))->GetName()) + { + return i; + } + } + throw std::invalid_argument("output name does not exist"); +} + +void mitk::IGTLMessageSource::RegisterAsMicroservice() +{ + // Get Context + us::ModuleContext* context = us::GetModuleContext(); + + // Define ServiceProps + us::ServiceProperties props; + mitk::UIDGenerator uidGen = + mitk::UIDGenerator ("org.mitk.services.IGTLMessageSource.id_", 16); + props[ US_PROPKEY_ID ] = uidGen.GetUID(); + props[ US_PROPKEY_DEVICENAME ] = m_Name; + props[ US_PROPKEY_DEVICETYPE ] = m_Type; + m_ServiceRegistration = context->RegisterService(this, props); +} + +void mitk::IGTLMessageSource::UnRegisterMicroservice() +{ + if (m_ServiceRegistration != NULL) m_ServiceRegistration.Unregister(); + m_ServiceRegistration = 0; +} + +std::string mitk::IGTLMessageSource::GetMicroserviceID() +{ + us::Any referenceProperty = + this->m_ServiceRegistration.GetReference().GetProperty(US_PROPKEY_ID); + return referenceProperty.ToString(); +} + +void mitk::IGTLMessageSource::GraftOutput(itk::DataObject *graft) +{ + this->GraftNthOutput(0, graft); +} + +void mitk::IGTLMessageSource::GraftNthOutput(unsigned int idx, + itk::DataObject *graft) +{ + if ( idx >= this->GetNumberOfIndexedOutputs() ) + { + itkExceptionMacro(<<"Requested to graft output " << idx << " but this filter" + "only has " << this->GetNumberOfIndexedOutputs() << " Outputs."); + } + + if ( !graft ) + { + itkExceptionMacro(<<"Requested to graft output with a NULL pointer object" ); + } + + itk::DataObject* output = this->GetOutput(idx); + if ( !output ) + { + itkExceptionMacro(<<"Requested to graft output that is a NULL pointer" ); + } + // Call Graft on IGTLMessage to copy member data + output->Graft( graft ); +} + +itk::DataObject::Pointer mitk::IGTLMessageSource::MakeOutput ( DataObjectPointerArraySizeType /*idx*/ ) +{ + return IGTLMessage::New().GetPointer(); +} + +itk::DataObject::Pointer mitk::IGTLMessageSource::MakeOutput( const DataObjectIdentifierType & name ) +{ + itkDebugMacro("MakeOutput(" << name << ")"); + if( this->IsIndexedOutputName(name) ) + { + return this->MakeOutput( this->MakeIndexFromOutputName(name) ); + } + return static_cast(IGTLMessage::New().GetPointer()); +} + +mitk::PropertyList::ConstPointer mitk::IGTLMessageSource::GetParameters() const +{ + mitk::PropertyList::Pointer p = mitk::PropertyList::New(); + // add properties to p like this: + //p->SetProperty("MyFilter_MyParameter", mitk::PropertyDataType::New(m_MyParameter)); + return mitk::PropertyList::ConstPointer(p); +} + +void mitk::IGTLMessageSource::SetFPS(unsigned int fps) +{ + this->m_StreamingFPSMutex->Lock(); + this->m_StreamingFPS = fps; + this->m_StreamingFPSMutex->Unlock(); +} + + +unsigned int mitk::IGTLMessageSource::GetFPS() +{ + unsigned int fps = 0; + this->m_StreamingFPSMutex->Lock(); + fps = this->m_StreamingFPS; + this->m_StreamingFPSMutex->Unlock(); + return fps; +} diff --git a/Modules/OpenIGTLink/mitkIGTLMessageSource.h b/Modules/OpenIGTLink/mitkIGTLMessageSource.h new file mode 100644 index 0000000000..656c07239d --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLMessageSource.h @@ -0,0 +1,212 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKIGTLMESSAGESOURCE_H_HEADER_INCLUDED_ +#define MITKIGTLMESSAGESOURCE_H_HEADER_INCLUDED_ + +#include +#include "mitkPropertyList.h" +#include "MitkOpenIGTLinkExports.h" +#include "mitkIGTLMessage.h" + +// Microservices +#include +#include + +//itk +#include + +namespace mitk { + + /** + * \brief OpenIGTLink message source + * + * Base class for all OpenIGTLink filters that produce OpenIGTLink message + * objects as output. This class defines the output-interface for + * OpenIGTLinkMessageFilters. + * \warning: if Update() is called on any output object, all IGTLMessage filters + * will generate new output data for all outputs, not just the one on which + * Update() was called. + * + */ + class MITKOPENIGTLINK_EXPORT IGTLMessageSource : public itk::ProcessObject + { + public: + mitkClassMacro(IGTLMessageSource, itk::ProcessObject); + + /** @return Returns a human readable name of this source. There will be a + * default name, or you can set the name with the method SetName() if you + * want to change it. + */ + itkGetMacro(Name,std::string); + + /** @brief Sets the human readable name of this source. There is also a + * default name, but you can use this method if you need to define it on your + * own. + */ + itkSetMacro(Name,std::string); + + /** @return Returns a human readable type of this source. There will be a + * default type, or you can set the name with the method SetType(). You have + * to set this parameter otherwise it will not be found by the message + * provider. + */ + itkGetMacro(Type,std::string); + + /** @return Returns a human readable type of this source. There will be a + * default type, or you can set the name with the method SetType(). You have + * to set this parameter otherwise it will not be found by the message + * provider. + */ + itkSetMacro(Type,std::string); + + /** + *\brief return the output (output with id 0) of the filter + */ + IGTLMessage* GetOutput(void); + + /** + *\brief return the output with id idx of the filter + */ + IGTLMessage* GetOutput(DataObjectPointerArraySizeType idx); + + /** + *\brief return the output with name messageName of the filter + */ + IGTLMessage* GetOutput(const std::string& messageName); + + /** + *\brief return the index of the output with name messageName, -1 if no output + * with that name was found + * + * \warning if a subclass has outputs that have different data type than + * igtl::MessageBase, they have to overwrite this method + */ + DataObjectPointerArraySizeType GetOutputIndex(std::string messageName); + + /** + *\brief Registers this object as a Microservice, making it available to every + * module and/or plugin. To unregister, call UnregisterMicroservice(). + */ + virtual void RegisterAsMicroservice(); + + /** + *\brief Registers this object as a Microservice, making it available to every + * module and/or plugin. + */ + virtual void UnRegisterMicroservice(); + + /** + *\brief Returns the id that this device is registered with. The id will only + * be valid, if the IGTLMessageSource has been registered using + * RegisterAsMicroservice(). + */ + std::string GetMicroserviceID(); + + /** + *\brief These Constants are used in conjunction with Microservices + */ + static const std::string US_INTERFACE_NAME; + static const std::string US_PROPKEY_DEVICENAME; + static const std::string US_PROPKEY_DEVICETYPE; + static const std::string US_PROPKEY_ID; + static const std::string US_PROPKEY_ISACTIVE; //NOT IMPLEMENTED YET! + + /** + *\brief Graft the specified DataObject onto this ProcessObject's output. + * + * See itk::ImageSource::GraftNthOutput for details + */ + virtual void GraftNthOutput(unsigned int idx, itk::DataObject *graft); + + /** + * \brief Graft the specified DataObject onto this ProcessObject's output. + * + * See itk::ImageSource::Graft Output for details + */ + virtual void GraftOutput(itk::DataObject *graft); + + /** + * Allocates a new output object and returns it. Currently the + * index idx is not evaluated. + * @param idx the index of the output for which an object should be created + * @returns the new object + */ + virtual itk::DataObject::Pointer MakeOutput ( DataObjectPointerArraySizeType idx ); + + /** + * This is a default implementation to make sure we have something. + * Once all the subclasses of ProcessObject provide an appopriate + * MakeOutput(), then ProcessObject::MakeOutput() can be made pure + * virtual. + */ + virtual itk::DataObject::Pointer MakeOutput(const DataObjectIdentifierType &name); + + /** + * \brief Set all filter parameters as the PropertyList p + * + * This method allows to set all parameters of a filter with one + * method call. For the names of the parameters, take a look at + * the GetParameters method of the filter + * This method has to be overwritten by each MITK-IGT filter. + */ + virtual void SetParameters(const mitk::PropertyList*){}; + + /** + * \brief Get all filter parameters as a PropertyList + * + * This method allows to get all parameters of a filter with one + * method call. The returned PropertyList must be assigned to a + * SmartPointer immediately, or else it will get destroyed. + * Every filter must overwrite this method to create a filter-specific + * PropertyList. Note that property names must be unique over all + * MITK-IGT filters. Therefore each filter should use its name as a prefix + * for each property name. + * Secondly, each filter should list the property names and data types + * in the method documentation. + */ + virtual mitk::PropertyList::ConstPointer GetParameters() const; + + /** + *\brief Sets the fps used for streaming this source + */ + void SetFPS(unsigned int fps); + + /** + *\brief Gets the fps used for streaming this source + */ + unsigned int GetFPS(); + + protected: + IGTLMessageSource(); + virtual ~IGTLMessageSource(); + + std::string m_Name; + std::string m_Type; + + + /** mutex to control access to m_StreamingFPS */ + itk::FastMutexLock::Pointer m_StreamingFPSMutex; + /** The frames per second used for streaming */ + unsigned int m_StreamingFPS; + + us::ServiceRegistration m_ServiceRegistration; + }; +} // namespace mitk +// This is the microservice declaration. Do not meddle! +MITK_DECLARE_SERVICE_INTERFACE(mitk::IGTLMessageSource, "org.mitk.services.IGTLMessageSource") +#endif /* MITKIGTLMESSAGESOURCE_H_HEADER_INCLUDED_ */ diff --git a/Modules/OpenIGTLink/mitkIGTLMessageSourceTest.cpp b/Modules/OpenIGTLink/mitkIGTLMessageSourceTest.cpp new file mode 100644 index 0000000000..a5d810e0f8 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLMessageSourceTest.cpp @@ -0,0 +1,175 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkNavigationDataSource.h" +#include "mitkNavigationData.h" + +#include "mitkTestingMacros.h" + + /**Documentation + * \brief test class that only adds a public New() method to NavigationDataSource, so that it can be tested + * + */ +class MyNavigationDataSourceTest : public mitk::NavigationDataSource + { + public: + mitkClassMacro(MyNavigationDataSourceTest, mitk::NavigationDataSource); + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + void CreateOutput() + { + this->SetNumberOfIndexedOutputs(1); + this->SetNthOutput(0, this->MakeOutput(0)); + }; + }; + +/** Class that holds static test methods to structure the test. */ +class mitkNavigationDataSourceTestClass + { + public: + + static void TestInstantiation() + { + // let's create an object of our class + MyNavigationDataSourceTest::Pointer myFilter = MyNavigationDataSourceTest::New(); + + // first test: did this work? + // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since + // it makes no sense to continue without an object. + MITK_TEST_CONDITION_REQUIRED(myFilter.IsNotNull(), "Testing instantiation"); + + // testing create outputs + MITK_TEST_CONDITION(myFilter->GetNumberOfInputs() == 0, "testing initial number of inputs"); + MITK_TEST_CONDITION(myFilter->GetNumberOfOutputs() == 0, "testing initial number of outputs"); + myFilter->CreateOutput(); + MITK_TEST_CONDITION(myFilter->GetNumberOfOutputs() == 1, "testing SetNumberOfOutputs() and MakeOutput()"); + MITK_TEST_CONDITION(dynamic_cast(myFilter->GetOutput()) != NULL, "test GetOutput() returning valid output object"); + } + + static void TestMethodsNormalCases() + { + //create and initialize test objects + MyNavigationDataSourceTest::Pointer myFilter = MyNavigationDataSourceTest::New(); + myFilter->CreateOutput(); + mitk::NavigationData::PositionType initialPos; + mitk::FillVector3D(initialPos, 1.0, 2.0, 3.0); + mitk::NavigationData::OrientationType initialOri(0.1, 0.2, 0.3, 0.4); + mitk::ScalarType initialError(22.22); + bool initialValid(true); + mitk::NavigationData::Pointer nd1 = mitk::NavigationData::New(); + nd1->SetPosition(initialPos); + nd1->SetOrientation(initialOri); + nd1->SetPositionAccuracy(initialError); + nd1->SetDataValid(initialValid); + + //test method graft + MITK_TEST_OUTPUT(<< "testing Graftoutput()"); + myFilter->GraftOutput(nd1); + mitk::NavigationData::Pointer out = myFilter->GetOutput(); + MITK_TEST_CONDITION(out.GetPointer() != nd1.GetPointer(), "testing if output is same object as source of graft"); + MITK_TEST_CONDITION(mitk::Equal(out->GetPosition(), nd1->GetPosition()),"testing position equality after graft") + MITK_TEST_CONDITION(mitk::Equal(out->GetOrientation(), nd1->GetOrientation()),"testing orientation equality after graft") + MITK_TEST_CONDITION((out->GetCovErrorMatrix() == nd1->GetCovErrorMatrix()),"testing error matrix equality after graft") + MITK_TEST_CONDITION((out->IsDataValid() == nd1->IsDataValid()),"testing data valid equality after graft") + MITK_TEST_CONDITION(mitk::Equal(out->GetIGTTimeStamp(), nd1->GetIGTTimeStamp()), "testing timestamp equality after graft"); + + //test method GetParameters() + mitk::PropertyList::ConstPointer list = myFilter->GetParameters(); + MITK_TEST_CONDITION(list.IsNotNull(), "testing GetParameters()"); + } + + static void TestMethodsInvalidCases() + { + //test invalid call of methods + MyNavigationDataSourceTest::Pointer myFilter = MyNavigationDataSourceTest::New(); + + mitk::NavigationData::Pointer testOutput = myFilter->GetOutput(); + MITK_TEST_CONDITION(testOutput.IsNull(), "testing GetOutput(int) before initialization"); + + testOutput = myFilter->GetOutput("test"); + MITK_TEST_CONDITION(testOutput.IsNull(), "testing GetOutput(string) before initialization"); + + //test GetOutputIndex() with invalid output name + myFilter->CreateOutput(); + bool exceptionThrown=false; + try + { + myFilter->GetOutputIndex("nonsense name"); + } + catch(std::invalid_argument e) + { + exceptionThrown=true; + } + MITK_TEST_CONDITION(exceptionThrown,"Testing method GetOutputIndex with invalid navigation data name"); + + //test method GraftNthOutput with invalid index + exceptionThrown=false; + try + { + mitk::NavigationData::Pointer graftObject; + myFilter->GraftNthOutput(100,graftObject); + } + catch(itk::ExceptionObject e) + { + exceptionThrown=true; + } + MITK_TEST_CONDITION(exceptionThrown,"Testing method GraftNthOutput with invalid index"); + } + + static void TestMicroserviceRegister() + { + MyNavigationDataSourceTest::Pointer myFilter = MyNavigationDataSourceTest::New(); + myFilter->CreateOutput(); + mitk::NavigationData::PositionType initialPos; + mitk::FillVector3D(initialPos, 1.0, 2.0, 3.0); + mitk::NavigationData::OrientationType initialOri(0.1, 0.2, 0.3, 0.4); + mitk::ScalarType initialError(22.22); + bool initialValid(true); + mitk::NavigationData::Pointer nd1 = mitk::NavigationData::New(); + nd1->SetPosition(initialPos); + nd1->SetOrientation(initialOri); + nd1->SetPositionAccuracy(initialError); + nd1->SetDataValid(initialValid); + myFilter->RegisterAsMicroservice(); + MITK_TEST_CONDITION(myFilter->GetMicroserviceID()!="","Testing if microservice was registered successfully."); + } + static void TestMicroserviceAvailabilityAndUnregister() + { + //TODO: test if Microservice is available + + //TODO: remove Microservice + + //TODO: test if Microservice is not available any more + + } + }; + +/**Documentation + * test for the class "NavigationDataSource". + */ +int mitkNavigationDataSourceTest(int /* argc */, char* /*argv*/[]) +{ + MITK_TEST_BEGIN("NavigationDataSource"); + + mitkNavigationDataSourceTestClass::TestInstantiation(); + mitkNavigationDataSourceTestClass::TestMethodsNormalCases(); + mitkNavigationDataSourceTestClass::TestMethodsInvalidCases(); + mitkNavigationDataSourceTestClass::TestMicroserviceRegister(); + mitkNavigationDataSourceTestClass::TestMicroserviceAvailabilityAndUnregister(); + + // always end with this! + MITK_TEST_END(); +} diff --git a/Modules/OpenIGTLink/mitkIGTLServer.cpp b/Modules/OpenIGTLink/mitkIGTLServer.cpp new file mode 100644 index 0000000000..c747e27cb0 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLServer.cpp @@ -0,0 +1,194 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkIGTLServer.h" +#include + +#include +#include + +#include +#include + + +mitk::IGTLServer::IGTLServer() : +IGTLDevice() +{ +} + +mitk::IGTLServer::~IGTLServer() +{ + +} + +bool mitk::IGTLServer::OpenConnection() +{ + if (this->GetState() != Setup) + { + mitkThrowException(mitk::Exception) << + "Can only try to create a server if in setup mode"; + return false; + } + + int portNumber = this->GetPortNumber(); + + if (portNumber == -1 ) + { + //port number was not correct + return false; + } + + //create a new server socket + m_Socket = igtl::ServerSocket::New(); + + //try to create the igtl server + int response = dynamic_cast(m_Socket.GetPointer())-> + CreateServer(portNumber); + + //check the response + if ( response != 0 ) + { + mitkThrowException(mitk::Exception) << + "The server could not be created. Port: " << portNumber; + return false; + } + + // everything is initialized and connected so the communication can be started + this->SetState(Ready); + + return true; +} + +bool mitk::IGTLServer::CloseConnection() +{ + //remove all registered clients + SocketListType allRegisteredSockets = m_RegisteredClients; + this->StopCommunicationWithSocket(allRegisteredSockets); + + return mitk::IGTLDevice::CloseConnection(); +} + +void mitk::IGTLServer::Connect() +{ + igtl::Socket::Pointer socket; + //check if another igtl device wants to connect to this socket + socket = + ((igtl::ServerSocket*)(this->m_Socket.GetPointer()))->WaitForConnection(1); + //if there is a new connection the socket is not null + if ( socket.IsNotNull() ) + { + //add the new client socket to the list of registered clients + this->m_RegisteredClients.push_back(socket); + //inform observers about this new client + this->InvokeEvent(NewClientConnectionEvent()); + MITK_INFO("IGTLServer") << "Connected to a new client."; + } +} + +void mitk::IGTLServer::Receive() +{ + unsigned int status = IGTL_STATUS_OK; + SocketListType socketsToBeRemoved; + + //the server can be connected with several clients, therefore it has to check + //all registered clients + SocketListIteratorType it; + SocketListIteratorType it_end = this->m_RegisteredClients.end(); + for ( it = this->m_RegisteredClients.begin(); it != it_end; ++it ) + { + //it is possible that ReceivePrivate detects that the current socket is + //already disconnected. Therefore, it is necessary to remove this socket + //from the registered clients list + status = this->ReceivePrivate(*it); + if ( status == IGTL_STATUS_NOT_PRESENT ) + { + //remember this socket for later, it is not a good idea to remove it + //from the list directly because we iterator over the list at this point + socketsToBeRemoved.push_back(*it); + MITK_WARN("IGTLServer") << "Lost connection to a client socket. "; + } + } + if ( socketsToBeRemoved.size() > 0 ) + { + //remove the sockets that are not connected anymore + this->StopCommunicationWithSocket(socketsToBeRemoved); + //inform observers about loosing the connection to these sockets + this->InvokeEvent(LostConnectionEvent()); + } +} + +void mitk::IGTLServer::Send() +{ + igtl::MessageBase::Pointer curMessage; + + //get the latest message from the queue + curMessage = this->m_SendQueue->PullMessage(); + + // there is no message => return + if ( curMessage.IsNull() ) + return; + + //the server can be connected with several clients, therefore it has to check + //all registered clients + //sending a message to all registered clients might not be the best solution, + //it could be better to store the client together with the requested type. Then + //the data would be send to the appropriate client and to noone else. + //(I know it is no excuse but PLUS is doing exactly the same, they broadcast + //everything) + SocketListIteratorType it; + SocketListIteratorType it_end = + this->m_RegisteredClients.end(); + for ( it = this->m_RegisteredClients.begin(); it != it_end; ++it ) + { + //maybe there should be a check here if the current socket is still active + this->SendMessagePrivate(curMessage.GetPointer(), *it); + } +} + +void mitk::IGTLServer::StopCommunicationWithSocket( + SocketListType& toBeRemovedSockets) +{ + SocketListIteratorType it = toBeRemovedSockets.begin(); + SocketListIteratorType itEnd = toBeRemovedSockets.end(); + for (; it != itEnd; ++it ) + { + this->StopCommunicationWithSocket(*it); + } +} + +void mitk::IGTLServer::StopCommunicationWithSocket(igtl::Socket* client) +{ + SocketListIteratorType it = this->m_RegisteredClients.begin(); + SocketListIteratorType itEnd = this->m_RegisteredClients.end(); + + for (; it != itEnd; ++it ) + { + if ( (*it) == client ) + { + //close the socket + (*it)->CloseSocket(); + //and remove it from the list + this->m_RegisteredClients.remove(*it); + break; + } + } + MITK_INFO("IGTLServer") << "Removed client socket from server client list."; +} + +unsigned int mitk::IGTLServer::GetNumberOfConnections() +{ + return this->m_RegisteredClients.size(); +} diff --git a/Modules/OpenIGTLink/mitkIGTLServer.h b/Modules/OpenIGTLink/mitkIGTLServer.h new file mode 100644 index 0000000000..ea5a128186 --- /dev/null +++ b/Modules/OpenIGTLink/mitkIGTLServer.h @@ -0,0 +1,125 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKIGTLSERVER_H +#define MITKIGTLSERVER_H + +#include "mitkIGTLDevice.h" + +#include + + +namespace mitk +{ + + /** + * \brief Superclass for OpenIGTLink server + * + * Implements the IGTLDevice interface for IGTLServers. In certain points it + * behaves different than the IGTLClient. The client connects directly to a + * server (it cannot connect to two different servers) while the server can + * connect to several clients. Therefore, it is necessary for the server to + * have a list with registered sockets. + * + * \ingroup OpenIGTLink + */ + class MITKOPENIGTLINK_EXPORT IGTLServer : public IGTLDevice + { + public: + mitkClassMacro(IGTLServer, IGTLDevice) + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + typedef std::list SocketListType; + typedef SocketListType::iterator SocketListIteratorType; + + /** + * \brief Initialize the connection for the IGTLServer + * + * + * OpenConnection() starts the IGTLServer socket so that clients can connect + * to it. + * @throw mitk::Exception Throws an exception if the given port is occupied. + */ + virtual bool OpenConnection(); + + /** + * \brief Closes the connection to the device + * + * This may only be called if there is currently a connection to the + * device, but device is not running (e.g. object is in Ready state) + */ + virtual bool CloseConnection(); + + /** + * \brief Returns the number of client connections of this device + */ + virtual unsigned int GetNumberOfConnections(); + + protected: + /** Constructor */ + IGTLServer(); + /** Destructor */ + virtual ~IGTLServer(); + + /** + * \brief Call this method to check for other devices that want to connect + * to this one. + * + * In case of a client this method is doing nothing. In case of a server it + * is checking for other devices and if there is one it establishes a + * connection and adds the socket to m_RegisteredClients. + */ + virtual void Connect(); + + /** + * \brief Call this method to receive a message. + * + * The message will be saved in the receive queue. + */ + virtual void Receive(); + + /** + * \brief Call this method to send a message. + * The message will be read from the queue. So far the message is send to all + * connected sockets (broadcast). + */ + virtual void Send(); + + /** + * \brief Stops the communication with the given sockets. + * + * This method removes the given sockets from the registered clients list + * + */ + virtual void StopCommunicationWithSocket(SocketListType& toBeRemovedSockets); + + /** + * \brief Stops the communication with the given socket. + * + * This method removes the given socket from the registered clients list + * + */ + virtual void StopCommunicationWithSocket(igtl::Socket* client); + + /** + * \brief A list with all registered clients + */ + SocketListType m_RegisteredClients; + }; +} // namespace mitk +#endif /* MITKIGTLSERVER_H */ diff --git a/Modules/OpenIGTLinkUI/CMakeLists.txt b/Modules/OpenIGTLinkUI/CMakeLists.txt new file mode 100644 index 0000000000..b693ea20ab --- /dev/null +++ b/Modules/OpenIGTLinkUI/CMakeLists.txt @@ -0,0 +1,9 @@ +MITK_CREATE_MODULE( + #SUBPROJECTS MITKOpenIGTLink + INCLUDE_DIRS Qmitk + DEPENDS MitkOpenIGTLink MitkQtWidgetsExt MitkPersistence + #GENERATED_CPP ${TOOL_GUI_CPPS} ${TOOL_CPPS} +) + +## create IGTUI config +#configure_file(mitkIGTUIConfig.h.in ${PROJECT_BINARY_DIR}/mitkIGTUIConfig.h @ONLY) diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.cpp new file mode 100644 index 0000000000..74e8505e67 --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.cpp @@ -0,0 +1,282 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkIGTLDeviceCommandWidget.h" + +//mitk headers +#include +#include +#include +#include + +//qt headers +#include +#include +#include +#include + +//igtl +#include +#include +#include +#include + +//poco headers +#include + +const std::string QmitkIGTLDeviceCommandWidget::VIEW_ID = + "org.mitk.views.igtldevicesourcemanagementwidget"; + +QmitkIGTLDeviceCommandWidget::QmitkIGTLDeviceCommandWidget( + QWidget* parent, Qt::WindowFlags f) + : QWidget(parent, f), m_IsClient(false) +{ + m_Controls = NULL; + this->m_IGTLDevice = NULL; + CreateQtPartControl(this); +} + + +QmitkIGTLDeviceCommandWidget::~QmitkIGTLDeviceCommandWidget() +{ +} + +void QmitkIGTLDeviceCommandWidget::CreateQtPartControl(QWidget *parent) +{ + if (!m_Controls) + { + // create GUI widgets + m_Controls = new Ui::QmitkIGTLDeviceCommandWidgetControls; + // setup GUI widgets + m_Controls->setupUi(parent); + } + + //connect slots with signals + CreateConnections(); +} + +void QmitkIGTLDeviceCommandWidget::CreateConnections() +{ + if (m_Controls) + { + // connect the widget items with the methods + connect( m_Controls->butSendCommand, SIGNAL(clicked()), + this, SLOT(OnSendCommand())); + connect( m_Controls->commandsComboBox, + SIGNAL(currentIndexChanged(const QString &)), + this, SLOT(OnCommandChanged(const QString &))); + } +} + + +void QmitkIGTLDeviceCommandWidget::OnDeviceStateChanged() +{ + this->AdaptGUIToState(); +} + +void QmitkIGTLDeviceCommandWidget::AdaptGUIToState() +{ + if (this->m_IGTLDevice.IsNotNull()) + { + //check the state of the device + mitk::IGTLDevice::IGTLDeviceState state = this->m_IGTLDevice->GetState(); + + switch (state) { + case mitk::IGTLDevice::Setup: + this->m_Controls->commandsComboBox->setEnabled(false); + this->m_Controls->butSendCommand->setEnabled(false); + this->m_Controls->fpsSpinBox->setEnabled(false); + break; + case mitk::IGTLDevice::Ready: + this->m_Controls->commandsComboBox->setEnabled(true); + this->m_Controls->butSendCommand->setEnabled(true); + this->m_Controls->fpsSpinBox->setEnabled(false); + break; + case mitk::IGTLDevice::Running: + if ( this->m_IGTLDevice->GetNumberOfConnections() == 0 ) + { + //just a server can run and have 0 connections + this->m_Controls->butSendCommand->setEnabled(false); + this->m_Controls->fpsSpinBox->setEnabled(false); + this->m_Controls->commandsComboBox->setEnabled(false); + } + else + { + this->m_Controls->commandsComboBox->setEnabled(true); + this->m_Controls->butSendCommand->setEnabled(true); + // this->m_Controls->fpsSpinBox->setEnabled(true); + } + break; + default: + mitkThrow() << "Invalid Device State"; + break; + } + } + else + { + this->DisableSourceControls(); + } +} + +void QmitkIGTLDeviceCommandWidget::Initialize(mitk::IGTLDevice::Pointer device) +{ + //reset the GUI + DisableSourceControls(); + //reset the observers + if ( this->m_IGTLDevice.IsNotNull() ) + { + this->m_IGTLDevice->RemoveObserver(m_MessageReceivedObserverTag); + this->m_IGTLDevice->RemoveObserver(m_CommandReceivedObserverTag); + this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); + } + + if(device.IsNotNull()) + { + //get the device + this->m_IGTLDevice = device; + + //check if the device is a server or a client + if ( dynamic_cast( + this->m_IGTLDevice.GetPointer()) == NULL ) + { + m_IsClient = false; + } + else + { + m_IsClient = true; + } + + typedef itk::SimpleMemberCommand< QmitkIGTLDeviceCommandWidget > CurCommandType; +// CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); +// messageReceivedCommand->SetCallbackFunction( +// this, &QmitkIGTLDeviceCommandWidget::OnMessageReceived ); +// this->m_MessageReceivedObserverTag = +// this->m_IGTLDevice->AddObserver(mitk::MessageReceivedEvent(), messageReceivedCommand); + +// CurCommandType::Pointer commandReceivedCommand = CurCommandType::New(); +// commandReceivedCommand->SetCallbackFunction( +// this, &QmitkIGTLDeviceCommandWidget::OnCommandReceived ); +// this->m_CommandReceivedObserverTag = +// this->m_IGTLDevice->AddObserver(mitk::CommandReceivedEvent(), commandReceivedCommand); + + CurCommandType::Pointer connectionLostCommand = CurCommandType::New(); + connectionLostCommand->SetCallbackFunction( + this, &QmitkIGTLDeviceCommandWidget::OnLostConnection ); + this->m_LostConnectionObserverTag = this->m_IGTLDevice->AddObserver( + mitk::LostConnectionEvent(), connectionLostCommand); + + CurCommandType::Pointer newConnectionCommand = CurCommandType::New(); + newConnectionCommand->SetCallbackFunction( + this, &QmitkIGTLDeviceCommandWidget::OnNewConnection ); + this->m_NewConnectionObserverTag = this->m_IGTLDevice->AddObserver( + mitk::NewClientConnectionEvent(), newConnectionCommand); + + CurCommandType::Pointer stateModifiedCommand = CurCommandType::New(); + stateModifiedCommand->SetCallbackFunction( + this, &QmitkIGTLDeviceCommandWidget::OnDeviceStateChanged ); + this->m_StateModifiedObserverTag = this->m_IGTLDevice->AddObserver( + itk::ModifiedEvent(), stateModifiedCommand); + + //Fill the commands combo box with all available commands + FillCommandsComboBox(); + } + else + { + m_IGTLDevice = NULL; + } + + this->AdaptGUIToState(); +} + +void QmitkIGTLDeviceCommandWidget::DisableSourceControls() +{ + this->m_Controls->commandsComboBox->setEnabled(false); + this->m_Controls->butSendCommand->setEnabled(false); + this->m_Controls->fpsSpinBox->setEnabled(false); +} + + + + +void QmitkIGTLDeviceCommandWidget::OnSendCommand() +{ + //Set the frames per second of the current command in case of a STT_ command + if ( std::strcmp( m_CurrentCommand->GetDeviceType(), "STT_BIND" ) == 0 ) + { + ((igtl::StartBindMessage*)this->m_CurrentCommand.GetPointer())-> + SetResolution(this->m_Controls->fpsSpinBox->value()); + } + else if ( std::strcmp( m_CurrentCommand->GetDeviceType(), "STT_QTDATA" ) == 0 ) + { + ((igtl::StartQuaternionTrackingDataMessage*)m_CurrentCommand.GetPointer())-> + SetResolution(this->m_Controls->fpsSpinBox->value()); + } + else if ( std::strcmp( m_CurrentCommand->GetDeviceType(), "STT_TDATA" ) == 0 ) + { + ((igtl::StartTrackingDataMessage*)this->m_CurrentCommand.GetPointer())-> + SetResolution(this->m_Controls->fpsSpinBox->value()); + } + + m_IGTLDevice->SendMessage(m_CurrentCommand.GetPointer()); +} + +void QmitkIGTLDeviceCommandWidget::OnCommandChanged( + const QString & curCommand) +{ + if ( curCommand.isEmpty() ) + return; + + mitk::IGTLMessageFactory::Pointer msgFactory = + this->m_IGTLDevice->GetMessageFactory(); + //create a new message that fits to the selected get message type command + this->m_CurrentCommand = msgFactory->CreateInstance( curCommand.toStdString()); + //enable/disable the FPS spinbox + this->m_Controls->fpsSpinBox->setEnabled(curCommand.contains("STT_")); +} + +void QmitkIGTLDeviceCommandWidget::OnLostConnection() +{ + //get the IGTL device that invoked this event +// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; + + this->AdaptGUIToState(); +} + +void QmitkIGTLDeviceCommandWidget::OnNewConnection() +{ + this->AdaptGUIToState(); +} + +void QmitkIGTLDeviceCommandWidget::FillCommandsComboBox() +{ + //load the msg factory from the client (maybe this will be moved later on) + mitk::IGTLMessageFactory::Pointer msgFactory = + this->m_IGTLDevice->GetMessageFactory(); + //get the available commands as std::list + std::list commandsList_ = + msgFactory->GetAvailableMessageRequestTypes(); + //create a string list to convert the std::list + this->m_Controls->commandsComboBox->clear(); + while ( commandsList_.size() ) + { + //fill the combo box with life + this->m_Controls->commandsComboBox->addItem( + QString::fromStdString(commandsList_.front())); + commandsList_.pop_front(); + } +} diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.h b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.h new file mode 100644 index 0000000000..6327c6e75a --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.h @@ -0,0 +1,132 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QMITKIGTLDeviceCommandWIDGET_H +#define QMITKIGTLDeviceCommandWIDGET_H + +//QT headers +#include +#include + +//mitk headers +#include "MitkOpenIGTLinkUIExports.h" +#include "mitkIGTLDeviceSource.h" +#include "mitkIGTLClient.h" +#include "mitkDataStorage.h" + +//itk +#include + +//ui header +#include "ui_QmitkIGTLDeviceCommandWidgetControls.h" + + /** Documentation: + * \brief An object of this class offers an UI to send OpenIGTLink commands. + * + * + * \ingroup OpenIGTLinkUI + */ +class MITKOPENIGTLINKUI_EXPORT QmitkIGTLDeviceCommandWidget : public QWidget +{ + Q_OBJECT + + public: + static const std::string VIEW_ID; + + /** + * \brief Initializes the widget with the given device. + * + * The old device is + * dropped, so be careful, if the source is not saved somewhere else it might + * be lost. You might want to ask the user if he wants to save the changes + * before calling this method. + * \param device The widget will be initialized corresponding to the state of + * this device. + */ + void Initialize(mitk::IGTLDevice::Pointer device); + + QmitkIGTLDeviceCommandWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); + ~QmitkIGTLDeviceCommandWidget(); + + /** + * \brief Is called when the current device received a message + */ + void OnMessageReceived(); + + /** + * \brief Is called when the current device received a command + */ + void OnCommandReceived(); + + /** + * \brief Is called when the current device lost a connection to one of its + * sockets + */ + void OnLostConnection(); + + /** + * \brief Is called when the current device connected to another device + */ + void OnNewConnection(); + + + protected slots: + void OnCommandChanged(const QString& curCommand); + + void OnSendCommand(); + + protected: + + /** + * \brief Adapts the GUI to the state of the device + */ + void AdaptGUIToState(); + + /** + * \brief Calls AdaptGUIToState() + */ + void OnDeviceStateChanged(); + + /// \brief Fills the commands combo box with available commands + void FillCommandsComboBox(); + + /// \brief Creation of the connections + virtual void CreateConnections(); + + virtual void CreateQtPartControl(QWidget *parent); + + Ui::QmitkIGTLDeviceCommandWidgetControls* m_Controls; + + /** @brief holds the OpenIGTLink device */ + mitk::IGTLDevice::Pointer m_IGTLDevice; + + igtl::MessageBase::Pointer m_CurrentCommand; + + + /** @brief flag to indicate if the IGTL device is a client or a server */ + bool m_IsClient; + + unsigned long m_MessageReceivedObserverTag; + unsigned long m_CommandReceivedObserverTag; + unsigned long m_LostConnectionObserverTag; + unsigned long m_NewConnectionObserverTag; + unsigned long m_StateModifiedObserverTag; + + //############## private help methods ####################### + void DisableSourceControls(); + void EnableSourceControls(); +}; +#endif diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidgetControls.ui b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidgetControls.ui new file mode 100644 index 0000000000..c9959071ab --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidgetControls.ui @@ -0,0 +1,83 @@ + + + QmitkIGTLDeviceCommandWidgetControls + + + + 0 + 0 + 443 + 80 + + + + Form + + + + + + + + false + + + Choose Command Message Type + + + + + + + + 0 + 0 + + + + Frames per second + + + FPS: + + + + + + + false + + + + 0 + 0 + + + + Set the frames per second of the stream + + + 10 + + + + + + + + + false + + + Send the command + + + Send Command + + + + + + + + diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.cpp new file mode 100644 index 0000000000..e5c130a026 --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.cpp @@ -0,0 +1,363 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkIGTLDeviceSetupConnectionWidget.h" + +//mitk headers +#include +#include +#include +#include + +//qt headers +#include +#include +#include +#include + +//igtl +#include +#include +#include +#include + +//poco headers +#include + +const std::string QmitkIGTLDeviceSetupConnectionWidget::VIEW_ID = + "org.mitk.views.igtldevicesetupconnectionwidget"; + +QmitkIGTLDeviceSetupConnectionWidget::QmitkIGTLDeviceSetupConnectionWidget( + QWidget* parent, Qt::WindowFlags f) + : QWidget(parent, f), m_IsClient(false) +{ + m_Controls = NULL; + this->m_IGTLDevice = NULL; + CreateQtPartControl(this); +} + + +QmitkIGTLDeviceSetupConnectionWidget::~QmitkIGTLDeviceSetupConnectionWidget() +{ +} + +void QmitkIGTLDeviceSetupConnectionWidget::CreateQtPartControl(QWidget *parent) +{ + if (!m_Controls) + { + // create GUI widgets + m_Controls = new Ui::QmitkIGTLDeviceSetupConnectionWidgetControls; + // setup GUI widgets + m_Controls->setupUi(parent); + } + + // set the validator for the ip edit box (values must be between 0 and 255 and + // there are four of them, seperated with a point + QRegExpValidator *v = new QRegExpValidator(this); + QRegExp rx("((1{0,1}[0-9]{0,2}|2[0-4]{1,1}[0-9]{1,1}|25[0-5]{1,1})\\.){3,3}(1{0,1}[0-9]{0,2}|2[0-4]{1,1}[0-9]{1,1}|25[0-5]{1,1})"); + v->setRegExp(rx); + m_Controls->editIP->setValidator(v); + // set the validator for the port edit box (values must be between 1 and 65535) + m_Controls->editPort->setValidator(new QIntValidator(1, 65535, this)); + + //connect slots with signals + CreateConnections(); +} + +void QmitkIGTLDeviceSetupConnectionWidget::CreateConnections() +{ + if (m_Controls) + { + // connect the widget items with the methods + connect( m_Controls->butConnect, SIGNAL(clicked()), + this, SLOT(OnConnect())); + connect( m_Controls->editPort, SIGNAL(editingFinished()), + this, SLOT(OnPortChanged()) ); + connect( m_Controls->editIP, SIGNAL(editingFinished()), + this, SLOT(OnHostnameChanged()) ); + connect( m_Controls->bufferMsgCheckBox, SIGNAL(stateChanged(int)), + this, SLOT(OnBufferIncomingMessages(int))); + } +} + +void QmitkIGTLDeviceSetupConnectionWidget::OnDeviceStateChanged() +{ + this->AdaptGUIToState(); +} + +void QmitkIGTLDeviceSetupConnectionWidget::AdaptGUIToState() +{ + //check the validity of the device + if ( this->m_IGTLDevice.IsNull() ) + { + return; + } + + //check the state of the device + mitk::IGTLDevice::IGTLDeviceState state = this->m_IGTLDevice->GetState(); + + switch (state) { + case mitk::IGTLDevice::Setup: + if ( !m_IsClient ) + { + m_Controls->butConnect->setText("Go Online"); + this->m_Controls->editIP->setEnabled(false); + } + else + { + m_Controls->butConnect->setText("Connect"); + this->m_Controls->editIP->setEnabled(true); + } + this->m_Controls->editPort->setEnabled(true); + this->m_Controls->logSendReceiveMsg->setEnabled(false); + this->m_Controls->bufferMsgCheckBox->setEnabled(false); + this->m_Controls->butConnect->setEnabled(true); + break; + case mitk::IGTLDevice::Ready: + this->m_Controls->butConnect->setText("Disconnect"); + this->m_Controls->editIP->setEnabled(false); + this->m_Controls->editPort->setEnabled(false); + this->m_Controls->logSendReceiveMsg->setEnabled(true); + this->m_Controls->bufferMsgCheckBox->setEnabled(true); + this->m_Controls->butConnect->setEnabled(true); + break; + case mitk::IGTLDevice::Running: + this->m_Controls->butConnect->setText("Disconnect"); + this->m_Controls->editIP->setEnabled(false); + this->m_Controls->editPort->setEnabled(false); + this->m_Controls->logSendReceiveMsg->setEnabled(true); + this->m_Controls->bufferMsgCheckBox->setEnabled(true); + this->m_Controls->butConnect->setEnabled(true); + break; + default: + mitkThrow() << "Invalid Device State"; + break; + } +} + +void QmitkIGTLDeviceSetupConnectionWidget::Initialize( + mitk::IGTLDevice::Pointer device) +{ + //reset the GUI + DisableSourceControls(); + //reset the observers + if ( this->m_IGTLDevice.IsNotNull() ) + { + this->m_IGTLDevice->RemoveObserver(m_MessageReceivedObserverTag); + this->m_IGTLDevice->RemoveObserver(m_CommandReceivedObserverTag); + this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); + } + + if(device.IsNotNull()) + { + this->m_IGTLDevice = device; + + //check if the device is a server or a client + if ( dynamic_cast( + this->m_IGTLDevice.GetPointer()) == NULL ) + { + m_IsClient = false; + } + else + { + m_IsClient = true; + } + + this->AdaptGUIToState(); + + typedef itk::SimpleMemberCommand< QmitkIGTLDeviceSetupConnectionWidget > CurCommandType; + CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); + messageReceivedCommand->SetCallbackFunction( + this, &QmitkIGTLDeviceSetupConnectionWidget::OnMessageReceived ); + this->m_MessageReceivedObserverTag = this->m_IGTLDevice->AddObserver( + mitk::MessageReceivedEvent(), messageReceivedCommand); + + CurCommandType::Pointer commandReceivedCommand = CurCommandType::New(); + commandReceivedCommand->SetCallbackFunction( + this, &QmitkIGTLDeviceSetupConnectionWidget::OnCommandReceived ); + this->m_CommandReceivedObserverTag = this->m_IGTLDevice->AddObserver( + mitk::CommandReceivedEvent(), commandReceivedCommand); + + CurCommandType::Pointer connectionLostCommand = CurCommandType::New(); + connectionLostCommand->SetCallbackFunction( + this, &QmitkIGTLDeviceSetupConnectionWidget::OnLostConnection ); + this->m_LostConnectionObserverTag = this->m_IGTLDevice->AddObserver( + mitk::LostConnectionEvent(), connectionLostCommand); + + CurCommandType::Pointer newConnectionCommand = CurCommandType::New(); + newConnectionCommand->SetCallbackFunction( + this, &QmitkIGTLDeviceSetupConnectionWidget::OnNewConnection ); + this->m_NewConnectionObserverTag = this->m_IGTLDevice->AddObserver( + mitk::NewClientConnectionEvent(), newConnectionCommand); + + CurCommandType::Pointer stateModifiedCommand = CurCommandType::New(); + stateModifiedCommand->SetCallbackFunction( + this, &QmitkIGTLDeviceSetupConnectionWidget::OnDeviceStateChanged ); + this->m_StateModifiedObserverTag = this->m_IGTLDevice->AddObserver( + itk::ModifiedEvent(), stateModifiedCommand); + } + else + { + m_IGTLDevice = NULL; + } +} + +void QmitkIGTLDeviceSetupConnectionWidget::DisableSourceControls() +{ + m_Controls->editIP->setEnabled(false); + m_Controls->editPort->setEnabled(false); + m_Controls->butConnect->setEnabled(false); + m_Controls->bufferMsgCheckBox->setEnabled(false); + m_Controls->logSendReceiveMsg->setEnabled(false); +} + +void QmitkIGTLDeviceSetupConnectionWidget::OnConnect() +{ + if(m_Controls->butConnect->text() == "Connect" || + m_Controls->butConnect->text() == "Go Online" ) + { + QString port = m_Controls->editPort->text(); + m_IGTLDevice->SetPortNumber(port.toInt()); + std::string hostname = m_Controls->editIP->text().toStdString(); + m_IGTLDevice->SetHostname(hostname); + //connect with the other OpenIGTLink device => changes the state from Setup + //to Ready + if ( m_IGTLDevice->OpenConnection() ) + { + //starts the communication thread => changes the state from Ready to + //Running + if ( m_IGTLDevice->StartCommunication() ) + { + if ( this->m_IsClient ) + { + MITK_INFO("IGTLDeviceSourceManagementWidget") + << "Successfully connected to " << hostname + << " on port " << port.toStdString(); + } + } + else + { + MITK_ERROR("QmitkIGTLDeviceSetupConnectionWidget") << + "Could not start a communication with the" + "server because the client is in the wrong state"; + } + } + else + { + MITK_ERROR("QmitkIGTLDeviceSetupConnectionWidget") << + "Could not connect to the server. " + "Please check the hostname and port."; + } + } + else + { + m_IGTLDevice->CloseConnection(); + MITK_INFO("QmitkIGTLDeviceSetupConnectionWidget") << "Closed connection"; + } + this->AdaptGUIToState(); +} + + +void QmitkIGTLDeviceSetupConnectionWidget::OnPortChanged() +{ + +} + + +void QmitkIGTLDeviceSetupConnectionWidget::OnHostnameChanged() +{ + +} + +void QmitkIGTLDeviceSetupConnectionWidget::OnLostConnection() +{ + //get the IGTL device that invoked this event +// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; + + this->AdaptGUIToState(); + +// unsigned int numConnections = dev->GetNumberOfConnections(); + +// if ( numConnections == 0 ) +// { +// if ( this->m_IsClient ) +// { +// //Setup connection groupbox +// m_Controls->editIP->setEnabled(true); +// m_Controls->editPort->setEnabled(true); +// m_Controls->butConnect->setText("Connect"); +// m_Controls->logSendReceiveMsg->setEnabled(false); +// m_Controls->bufferMsgCheckBox->setEnabled(false); +// } +// } +} + +void QmitkIGTLDeviceSetupConnectionWidget::OnNewConnection() +{ + this->AdaptGUIToState(); + + //get the IGTL device that invoked this event +// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; + +// unsigned int numConnections = dev->GetNumberOfConnections(); + +// if ( numConnections != 0 ) +// { +// //Setup connection groupbox +// m_Controls->editIP->setEnabled(false); +// m_Controls->editPort->setEnabled(false); +// m_Controls->butConnect->setText("Disconnect"); +// m_Controls->logSendReceiveMsg->setEnabled(true); +// m_Controls->bufferMsgCheckBox->setEnabled(true); +// } +} + +void QmitkIGTLDeviceSetupConnectionWidget::OnMessageReceived() +{ +// //get the IGTL device that invoked this event +// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; + + if ( this->m_Controls->logSendReceiveMsg->isChecked() ) + { + MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Received a message: " + << this->m_IGTLDevice->GetReceiveQueue()->GetLatestMsgInformationString(); + } +} + +void QmitkIGTLDeviceSetupConnectionWidget::OnCommandReceived() +{ +// //get the IGTL device that invoked this event +// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; + + if ( this->m_Controls->logSendReceiveMsg->isChecked() ) + { + MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Received a command: " + << this->m_IGTLDevice->GetCommandQueue()->GetLatestMsgInformationString(); + } +} + + + +void QmitkIGTLDeviceSetupConnectionWidget::OnBufferIncomingMessages(int state) +{ + if ( this->m_IGTLDevice ) + { + this->m_IGTLDevice->EnableInfiniteBufferingMode( + this->m_IGTLDevice->GetReceiveQueue(), (bool)state); + } +} diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.h b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.h new file mode 100644 index 0000000000..b5edab6886 --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.h @@ -0,0 +1,142 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkIGTLDeviceSetupConnectionWidget_H +#define QmitkIGTLDeviceSetupConnectionWidget_H + +//QT headers +#include +#include + +//mitk headers +#include "MitkOpenIGTLinkUIExports.h" +#include "mitkIGTLDeviceSource.h" +#include "mitkIGTLClient.h" +#include "mitkDataStorage.h" + +//itk +#include + +//ui header +#include "ui_QmitkIGTLDeviceSetupConnectionWidgetControls.h" + + /** Documentation: + * \brief An object of this class offers an UI to setup the connection of an + * OpenIGTLink device. + * + * + * \ingroup OpenIGTLinkUI + */ +class MITKOPENIGTLINKUI_EXPORT QmitkIGTLDeviceSetupConnectionWidget : public QWidget +{ + Q_OBJECT + + public: + static const std::string VIEW_ID; + + /** + * \brief Initializes the widget with the given device. + * + * The old device is + * dropped, so be careful, if the source is not saved somewhere else it might + * be lost. You might want to ask the user if he wants to save the changes + * before calling this method. + * \param device The widget will be initialized corresponding to the state of + * this device. + */ + void Initialize(mitk::IGTLDevice::Pointer device); + + QmitkIGTLDeviceSetupConnectionWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); + ~QmitkIGTLDeviceSetupConnectionWidget(); + +// /** +// * \brief Is called when the current device received a message +// */ +// void OnMessageReceived(itk::Object* caller, const itk::EventObject&); + +// /** +// * \brief Is called when the current device received a command +// */ +// void OnCommandReceived(itk::Object* caller, const itk::EventObject&); + + /** + * \brief Is called when the current device lost a connection to one of its + * sockets + */ + void OnLostConnection(); + + /** + * \brief Is called when the current device connected to another device + */ + void OnNewConnection(); + + /** + * \brief Is called when the current device received a message + */ + void OnMessageReceived(); + + /** + * \brief Is called when the current device received a command + */ + void OnCommandReceived(); + + protected slots: + + void OnConnect(); + void OnPortChanged(); + void OnHostnameChanged(); + + /** + * \brief Enables/Disables the buffering of incoming messages + */ + void OnBufferIncomingMessages(int state); + + protected: + + /** + * \brief Adapts the GUI to the state of the device + */ + void AdaptGUIToState(); + + /** + * \brief Calls AdaptGUIToState() + */ + void OnDeviceStateChanged(); + + /** \brief Creation of the connections */ + virtual void CreateConnections(); + + virtual void CreateQtPartControl(QWidget *parent); + + Ui::QmitkIGTLDeviceSetupConnectionWidgetControls* m_Controls; + + /** @brief holds the OpenIGTLink device */ + mitk::IGTLDevice::Pointer m_IGTLDevice; + + /** @brief flag to indicate if the IGTL device is a client or a server */ + bool m_IsClient; + + unsigned long m_MessageReceivedObserverTag; + unsigned long m_CommandReceivedObserverTag; + unsigned long m_LostConnectionObserverTag; + unsigned long m_NewConnectionObserverTag; + unsigned long m_StateModifiedObserverTag; + + //############## private help methods ####################### + void DisableSourceControls(); +// void EnableSourceControls(); +}; +#endif diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidgetControls.ui b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidgetControls.ui new file mode 100644 index 0000000000..ab9774356a --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidgetControls.ui @@ -0,0 +1,137 @@ + + + QmitkIGTLDeviceSetupConnectionWidgetControls + + + + 0 + 0 + 443 + 169 + + + + Form + + + + + + false + + + Connect with the host/Start server + + + Connect + + + false + + + false + + + false + + + false + + + false + + + + + + + false + + + Enable this checkbox to log the send and receive message events + + + Log Send and Receive Messages + + + + + + + + + Port + + + + + + + Server-IP + + + + + + + false + + + Enter the port number of the host + + + 18944 + + + 5 + + + true + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Port + + + + + + + false + + + Enter the IP address of the host + + + 127.0.0.1 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + false + + + If this checkbox is set the device stores all incoming messages in the queue. If it is not set it always overwrites the current value. + + + Buffer Incoming Messages + + + true + + + + + + + + diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.cpp new file mode 100644 index 0000000000..7fdd56d625 --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.cpp @@ -0,0 +1,307 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkIGTLDeviceSourceManagementWidget.h" + +//mitk headers +#include +#include +#include +#include + +//qt headers +#include +#include +#include +#include + +//igtl +#include +#include +#include +#include + +//poco headers +#include + +const std::string QmitkIGTLDeviceSourceManagementWidget::VIEW_ID = + "org.mitk.views.igtldevicesourcemanagementwidget"; + +QmitkIGTLDeviceSourceManagementWidget::QmitkIGTLDeviceSourceManagementWidget( + QWidget* parent, Qt::WindowFlags f) + : QWidget(parent, f), m_IsClient(false) +{ + m_Controls = NULL; + this->m_IGTLDevice = NULL; + CreateQtPartControl(this); +} + + +QmitkIGTLDeviceSourceManagementWidget::~QmitkIGTLDeviceSourceManagementWidget() +{ +} + +void QmitkIGTLDeviceSourceManagementWidget::CreateQtPartControl(QWidget *parent) +{ + if (!m_Controls) + { + // create GUI widgets + m_Controls = new Ui::QmitkIGTLDeviceSourceManagementWidgetControls; + // setup GUI widgets + m_Controls->setupUi(parent); + } + + //connect slots with signals + CreateConnections(); +} + +void QmitkIGTLDeviceSourceManagementWidget::CreateConnections() +{ + if (m_Controls) + { + connect( m_Controls->butSend, SIGNAL(clicked()), + this, SLOT(OnSendMessage())); + } +} + +void QmitkIGTLDeviceSourceManagementWidget::OnDeviceStateChanged() +{ + this->AdaptGUIToState(); +} + +void QmitkIGTLDeviceSourceManagementWidget::AdaptGUIToState() +{ + if (this->m_IGTLDeviceSource.IsNotNull()) + { + //check the state of the device + mitk::IGTLDevice::IGTLDeviceState state = + this->m_IGTLDeviceSource->GetIGTLDevice()->GetState(); + + switch (state) { + case mitk::IGTLDevice::Setup: + this->m_Controls->editSend->setEnabled(false); + this->m_Controls->butSend->setEnabled(false); + break; + case mitk::IGTLDevice::Ready: + this->m_Controls->editSend->setEnabled(false); + this->m_Controls->butSend->setEnabled(false); + break; + case mitk::IGTLDevice::Running: + if ( this->m_IGTLDevice->GetNumberOfConnections() == 0 ) + { + //just a server can run and have 0 connections + this->m_Controls->editSend->setEnabled(false); + this->m_Controls->butSend->setEnabled(false); + } + else + { + this->m_Controls->editSend->setEnabled(true); + this->m_Controls->butSend->setEnabled(true); + } + break; + default: + mitkThrow() << "Invalid Device State"; + break; + } + m_Controls->selectedSourceLabel->setText( + m_IGTLDeviceSource->GetName().c_str()); + } + else + { + this->DisableSourceControls(); + } +} + +void QmitkIGTLDeviceSourceManagementWidget::LoadSource( + mitk::IGTLDeviceSource::Pointer sourceToLoad) +{ + //reset the GUI + DisableSourceControls(); + //reset the observers + if ( this->m_IGTLDevice.IsNotNull() ) + { + this->m_IGTLDevice->RemoveObserver(m_MessageReceivedObserverTag); + this->m_IGTLDevice->RemoveObserver(m_CommandReceivedObserverTag); + this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); + } + + if(sourceToLoad.IsNotNull()) + { + this->m_IGTLDeviceSource = sourceToLoad; + + //get the device + this->m_IGTLDevice = this->m_IGTLDeviceSource->GetIGTLDevice(); + + //initialize the other GUI elements + this->m_Controls->connectionSetupWidget->Initialize(this->m_IGTLDevice); + this->m_Controls->commandWidget->Initialize(this->m_IGTLDevice); + + //check if the device is a server or a client + if ( dynamic_cast( + this->m_IGTLDeviceSource->GetIGTLDevice()) == NULL ) + { + m_IsClient = false; + } + else + { + m_IsClient = true; + } + + typedef itk::SimpleMemberCommand< QmitkIGTLDeviceSourceManagementWidget > CurCommandType; + CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); + messageReceivedCommand->SetCallbackFunction( + this, &QmitkIGTLDeviceSourceManagementWidget::OnMessageReceived ); + this->m_MessageReceivedObserverTag = + this->m_IGTLDevice->AddObserver(mitk::MessageReceivedEvent(), messageReceivedCommand); + + CurCommandType::Pointer commandReceivedCommand = CurCommandType::New(); + commandReceivedCommand->SetCallbackFunction( + this, &QmitkIGTLDeviceSourceManagementWidget::OnCommandReceived ); + this->m_CommandReceivedObserverTag = + this->m_IGTLDevice->AddObserver(mitk::CommandReceivedEvent(), commandReceivedCommand); + + CurCommandType::Pointer connectionLostCommand = CurCommandType::New(); + connectionLostCommand->SetCallbackFunction( + this, &QmitkIGTLDeviceSourceManagementWidget::OnLostConnection ); + this->m_LostConnectionObserverTag = this->m_IGTLDevice->AddObserver( + mitk::LostConnectionEvent(), connectionLostCommand); + + CurCommandType::Pointer newConnectionCommand = CurCommandType::New(); + newConnectionCommand->SetCallbackFunction( + this, &QmitkIGTLDeviceSourceManagementWidget::OnNewConnection ); + this->m_NewConnectionObserverTag = this->m_IGTLDevice->AddObserver( + mitk::NewClientConnectionEvent(), newConnectionCommand); + + CurCommandType::Pointer stateModifiedCommand = CurCommandType::New(); + stateModifiedCommand->SetCallbackFunction( + this, &QmitkIGTLDeviceSourceManagementWidget::OnDeviceStateChanged ); + this->m_StateModifiedObserverTag = this->m_IGTLDevice->AddObserver( + itk::ModifiedEvent(), stateModifiedCommand); + } + else + { + m_IGTLDeviceSource = NULL; + } + this->AdaptGUIToState(); +} + +void QmitkIGTLDeviceSourceManagementWidget::DisableSourceControls() +{ + m_Controls->selectedSourceLabel->setText(""); + m_Controls->editSend->setEnabled(false); + m_Controls->butSend->setEnabled(false); +} + + +void QmitkIGTLDeviceSourceManagementWidget::OnSendMessage() +{ + std::string toBeSend = m_Controls->editSend->text().toStdString(); + + igtl::StringMessage::Pointer msg = igtl::StringMessage::New(); + msg->SetString(toBeSend); + this->m_IGTLDevice->SendMessage(msg.GetPointer()); +} + +void QmitkIGTLDeviceSourceManagementWidget::OnMessageReceived() +{ +// //get the IGTL device that invoked this event +// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; + +// if ( this->m_Controls->logSendReceiveMsg->isChecked() ) +// { +// MITK_INFO("IGTLDeviceSourceManagementWidget") << "Received a message: " +// << dev->GetReceiveQueue()->GetLatestMsgInformationString(); +// } +} + +void QmitkIGTLDeviceSourceManagementWidget::OnCommandReceived() +{ +// //get the IGTL device that invoked this event +// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; + +// if ( this->m_Controls->logSendReceiveMsg->isChecked() ) +// { +// MITK_INFO("IGTLDeviceSourceManagementWidget") << "Received a command: " +// << dev->GetCommandQueue()->GetLatestMsgInformationString(); +// } +} + +void QmitkIGTLDeviceSourceManagementWidget::OnLostConnection() +{ + this->AdaptGUIToState(); +// //get the IGTL device that invoked this event +// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; + +// unsigned int numConnections = dev->GetNumberOfConnections(); + +// if ( numConnections == 0 ) +// { +// if ( this->m_IsClient ) +// { +// //Setup connection groupbox +// m_Controls->editIP->setEnabled(true); +// m_Controls->editPort->setEnabled(true); +// m_Controls->butConnect->setText("Connect"); +// m_Controls->logSendReceiveMsg->setEnabled(false); +// m_Controls->bufferMsgCheckBox->setEnabled(false); +// //send string messages groupbox +// m_Controls->editSend->setEnabled(false); +// m_Controls->butSend->setEnabled(false); +// //send command messages groupbox +// m_Controls->butSendCommand->setEnabled(false); +// m_Controls->fpsSpinBox->setEnabled(false); +// m_Controls->commandsComboBox->setEnabled(false); +// } +// else +// { +// //send string messages groupbox +// m_Controls->editSend->setEnabled(false); +// m_Controls->butSend->setEnabled(false); +// //send command messages groupbox +// m_Controls->butSendCommand->setEnabled(false); +// m_Controls->fpsSpinBox->setEnabled(false); +// m_Controls->commandsComboBox->setEnabled(false); +// } +// } +} + +void QmitkIGTLDeviceSourceManagementWidget::OnNewConnection() +{ + this->AdaptGUIToState(); +// //get the IGTL device that invoked this event +// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; + +// unsigned int numConnections = dev->GetNumberOfConnections(); + +// if ( numConnections != 0 ) +// { +// //Setup connection groupbox +// m_Controls->editIP->setEnabled(false); +// m_Controls->editPort->setEnabled(false); +// m_Controls->butConnect->setText("Disconnect"); +// m_Controls->logSendReceiveMsg->setEnabled(true); +// m_Controls->bufferMsgCheckBox->setEnabled(true); +// //send string messages groupbox +// m_Controls->editSend->setEnabled(true); +// m_Controls->butSend->setEnabled(true); +// //send command messages groupbox +// m_Controls->butSendCommand->setEnabled(true); +//// m_Controls->fpsSpinBox->setEnabled(false); +// m_Controls->commandsComboBox->setEnabled(true); +// } +} diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.h b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.h new file mode 100644 index 0000000000..48693d33ad --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.h @@ -0,0 +1,126 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QMITKIGTLDeviceSourceMANAGEMENTWIDGET_H +#define QMITKIGTLDeviceSourceMANAGEMENTWIDGET_H + +//QT headers +#include +#include + +//mitk headers +#include "MitkOpenIGTLinkUIExports.h" +#include "mitkIGTLDeviceSource.h" +#include "mitkIGTLClient.h" +#include "mitkDataStorage.h" + +//itk +#include + +//ui header +#include "ui_QmitkIGTLDeviceSourceManagementWidgetControls.h" + + /** Documentation: + * \brief An object of this class offers an UI to manage OpenIGTLink Device + * Sources and OpenIGTLink Devices. + * + * + * \ingroup OpenIGTLinkUI + */ +class MITKOPENIGTLINKUI_EXPORT QmitkIGTLDeviceSourceManagementWidget : public QWidget +{ + Q_OBJECT + + public: + static const std::string VIEW_ID; + + /** Loads a source to the widget. The old source is dropped, so be careful, + * if the source is not saved somewhere else it might be lost. You might + * want to ask the user if he wants to save the changes before calling this + * method. + * @param sourceToLoad This source will be loaded and might be modified + * by the user. + */ + void LoadSource(mitk::IGTLDeviceSource::Pointer sourceToLoad); + + QmitkIGTLDeviceSourceManagementWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); + ~QmitkIGTLDeviceSourceManagementWidget(); + + /** + * \brief Is called when the current device received a message + */ + void OnMessageReceived(); + + /** + * \brief Is called when the current device received a command + */ + void OnCommandReceived(); + + /** + * \brief Is called when the current device lost a connection to one of its + * sockets + */ + void OnLostConnection(); + + /** + * \brief Is called when the current device connected to another device + */ + void OnNewConnection(); + + + protected slots: + void OnSendMessage(); + + protected: + /** + * \brief Adapts the GUI to the state of the device + */ + void AdaptGUIToState(); + + /** + * \brief Calls AdaptGUIToState() + */ + void OnDeviceStateChanged(); + + /// \brief Fills the commands combo box with available commands + void FillCommandsComboBox(); + + /// \brief Creation of the connections + virtual void CreateConnections(); + + virtual void CreateQtPartControl(QWidget *parent); + + Ui::QmitkIGTLDeviceSourceManagementWidgetControls* m_Controls; + + /** @brief holds the OpenIGTLink device */ + mitk::IGTLDevice::Pointer m_IGTLDevice; + + /** @brief holds the IGTLDeviceSource we are working with. */ + mitk::IGTLDeviceSource::Pointer m_IGTLDeviceSource; + + /** @brief flag to indicate if the IGTL device is a client or a server */ + bool m_IsClient; + + unsigned long m_MessageReceivedObserverTag; + unsigned long m_CommandReceivedObserverTag; + unsigned long m_LostConnectionObserverTag; + unsigned long m_NewConnectionObserverTag; + unsigned long m_StateModifiedObserverTag; + + //############## private help methods ####################### + void DisableSourceControls(); +}; +#endif diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidgetControls.ui b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidgetControls.ui new file mode 100644 index 0000000000..a848361a9a --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidgetControls.ui @@ -0,0 +1,125 @@ + + + QmitkIGTLDeviceSourceManagementWidgetControls + + + + 0 + 0 + 443 + 781 + + + + Form + + + + + + + + The selected IGTL device source + + + Selected IGTL Device Source: + + + + + + + <none> + + + + + + + + + Setup Connection + + + + + + + + + + + + Send String Messages + + + + + + false + + + Enter the string to be sent + + + + + + + false + + + Sends a message with the given string to the connected device + + + Send String + + + + + + + + + + Send Command Messages + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + QmitkIGTLDeviceCommandWidget + QWidget +
QmitkIGTLDeviceCommandWidget.h
+ 1 +
+ + QmitkIGTLDeviceSetupConnectionWidget + QWidget +
QmitkIGTLDeviceSetupConnectionWidget.h
+ 1 +
+
+ + +
diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceSelectionWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceSelectionWidget.cpp new file mode 100644 index 0000000000..13a6df754d --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceSelectionWidget.cpp @@ -0,0 +1,86 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkIGTLDeviceSourceSelectionWidget.h" + +//mitk headers +#include +#include + + + +QmitkIGTLDeviceSourceSelectionWidget::QmitkIGTLDeviceSourceSelectionWidget(QWidget* parent, Qt::WindowFlags f) +: QWidget(parent, f) +{ + m_Controls = NULL; + CreateQtPartControl(this); +} + + +QmitkIGTLDeviceSourceSelectionWidget::~QmitkIGTLDeviceSourceSelectionWidget() +{ + +} + +void QmitkIGTLDeviceSourceSelectionWidget::CreateQtPartControl(QWidget *parent) +{ + if ( !m_Controls ) + { + // create GUI widgets + m_Controls = new Ui::QmitkIGTLDeviceSourceSelectionWidgetControls; + // setup GUI widgets + m_Controls->setupUi(parent); + } + + CreateConnections(); +} + +void QmitkIGTLDeviceSourceSelectionWidget::CreateConnections() +{ + if ( m_Controls ) + { + connect( m_Controls->m_ServiceListWidget, + SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), + this, SLOT(IGTLDeviceSourceSelected(us::ServiceReferenceU)) ); + + //initialize service list widget + std::string empty = ""; + m_Controls->m_ServiceListWidget->Initialize( + mitk::IGTLDeviceSource::US_PROPKEY_IGTLDEVICENAME,empty); + } +} + +void QmitkIGTLDeviceSourceSelectionWidget::IGTLDeviceSourceSelected(us::ServiceReferenceU s) + { + if (!s) //nothing selected + { + //reset everything + this->m_CurrentIGTLDeviceSource = NULL; + emit IGTLDeviceSourceSelected(this->m_CurrentIGTLDeviceSource); + return; + } + + // Get storage + us::ModuleContext* context = us::GetModuleContext(); + this->m_CurrentIGTLDeviceSource = + context->GetService(s); + emit IGTLDeviceSourceSelected(this->m_CurrentIGTLDeviceSource); + } + +mitk::IGTLDeviceSource::Pointer QmitkIGTLDeviceSourceSelectionWidget::GetSelectedIGTLDeviceSource() + { + return this->m_CurrentIGTLDeviceSource; + } diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceSelectionWidget.h b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceSelectionWidget.h new file mode 100644 index 0000000000..7947da098b --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceSelectionWidget.h @@ -0,0 +1,84 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkIGTLDeviceSourceSelectionWidget_H +#define QmitkIGTLDeviceSourceSelectionWidget_H + +//QT headers +#include + +//mitk headers +#include "MitkOpenIGTLinkUIExports.h" +#include "mitkIGTLDeviceSource.h" +//#include +//#include +#include +//ui header +#include "ui_QmitkIGTLDeviceSourceSelectionWidgetControls.h" + + + /** Documentation: + * \brief This widget allows the user to select a OpenIGTLink device source. + * + * The widget lists all OpenIGTLink device sources which are available + * as microservice via the module context. + * + * A signal is emmited whenever the device selection changes. + * + * \ingroup OpenIGTLinkUI + */ +class MITKOPENIGTLINKUI_EXPORT QmitkIGTLDeviceSourceSelectionWidget : public QWidget +{ + Q_OBJECT + + public: + static const std::string VIEW_ID; + + QmitkIGTLDeviceSourceSelectionWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); + ~QmitkIGTLDeviceSourceSelectionWidget(); + + /** @return Returns the currently selected OpenIGTLink device source. + * Returns null if no source is selected at the moment. */ + mitk::IGTLDeviceSource::Pointer GetSelectedIGTLDeviceSource(); + + signals: + /** @brief This signal is emitted when a new OpenIGTLink device source is + * selected. + * @param source Holds the new selected OpenIGTLink device source. Is null + * if the old source is deselected and no new source is selected. + */ + void IGTLDeviceSourceSelected(mitk::IGTLDeviceSource::Pointer source); + + protected slots: + + void IGTLDeviceSourceSelected(us::ServiceReferenceU s); + + + protected: + + /// \brief Creation of the connections + virtual void CreateConnections(); + + virtual void CreateQtPartControl(QWidget *parent); + + Ui::QmitkIGTLDeviceSourceSelectionWidgetControls* m_Controls; + + mitk::IGTLDeviceSource::Pointer m_CurrentIGTLDeviceSource; + + + +}; +#endif diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolStorageSelectionWidgetControls.ui b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceSelectionWidgetControls.ui similarity index 74% copy from Modules/IGTUI/Qmitk/QmitkNavigationToolStorageSelectionWidgetControls.ui copy to Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceSelectionWidgetControls.ui index af246a91db..33d036f579 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolStorageSelectionWidgetControls.ui +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceSelectionWidgetControls.ui @@ -1,40 +1,38 @@ - QmitkNavigationToolStorageSelectionWidgetControls - + QmitkIGTLDeviceSourceSelectionWidgetControls + 0 0 199 111 Form - + 0 0 QmitkServiceListWidget QListWidget
QmitkServiceListWidget.h
- - - +
diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.cpp new file mode 100644 index 0000000000..234992bc88 --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.cpp @@ -0,0 +1,87 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkIGTLMessageSourceSelectionWidget.h" + +//mitk headers +#include +#include + + + +QmitkIGTLMessageSourceSelectionWidget::QmitkIGTLMessageSourceSelectionWidget( + QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) +{ + m_Controls = NULL; + m_CurrentIGTLMessageSource = NULL; + CreateQtPartControl(this); +} + + +QmitkIGTLMessageSourceSelectionWidget::~QmitkIGTLMessageSourceSelectionWidget() +{ + +} + +void QmitkIGTLMessageSourceSelectionWidget::CreateQtPartControl(QWidget *parent) +{ + if ( !m_Controls ) + { + // create GUI widgets + m_Controls = new Ui::QmitkIGTLMessageSourceSelectionWidgetControls; + // setup GUI widgets + m_Controls->setupUi(parent); + } + + CreateConnections(); +} + +void QmitkIGTLMessageSourceSelectionWidget::CreateConnections() +{ + if ( m_Controls ) + { + connect( m_Controls->m_ServiceListWidget, + SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), + this, SLOT(IGTLMessageSourceSelected(us::ServiceReferenceU)) ); + + //initialize service list widget + std::string empty = ""; + m_Controls->m_ServiceListWidget->Initialize( + mitk::IGTLMessageSource::US_PROPKEY_DEVICENAME, empty); + } +} + +void QmitkIGTLMessageSourceSelectionWidget::IGTLMessageSourceSelected(us::ServiceReferenceU s) + { + if (!s) //nothing selected + { + //reset everything + this->m_CurrentIGTLMessageSource = NULL; + emit IGTLMessageSourceSelected(this->m_CurrentIGTLMessageSource); + return; + } + + // Get storage + us::ModuleContext* context = us::GetModuleContext(); + this->m_CurrentIGTLMessageSource = + context->GetService(s); + emit IGTLMessageSourceSelected(this->m_CurrentIGTLMessageSource); + } + +mitk::IGTLMessageSource::Pointer QmitkIGTLMessageSourceSelectionWidget::GetSelectedIGTLMessageSource() +{ + return this->m_CurrentIGTLMessageSource; +} diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.h b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.h new file mode 100644 index 0000000000..96231b70cf --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.h @@ -0,0 +1,87 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkIGTLMessageSourceSelectionWidget_H +#define QmitkIGTLMessageSourceSelectionWidget_H + +//QT headers +#include + +//mitk headers +#include "MitkOpenIGTLinkUIExports.h" +#include "mitkIGTLMessageSource.h" + +//us +#include + +//ui header +#include "ui_QmitkIGTLMessageSourceSelectionWidgetControls.h" + + + /** Documentation: + * \brief This widget allows the user to select a OpenIGTLink message source. + * + * The widget lists all OpenIGTLink message sources which are available + * as microservice via the module context. + * + * A signal is emmited whenever the selection changes. + * + * \ingroup OpenIGTLinkUI + */ +class MITKOPENIGTLINKUI_EXPORT QmitkIGTLMessageSourceSelectionWidget : + public QWidget +{ + Q_OBJECT + + public: + static const std::string VIEW_ID; + + QmitkIGTLMessageSourceSelectionWidget(QWidget* parent = 0, + Qt::WindowFlags f = 0); + ~QmitkIGTLMessageSourceSelectionWidget(); + + /** @return Returns the currently selected OpenIGTLink message source. + * Returns null if no source is selected at the moment. */ + mitk::IGTLMessageSource::Pointer GetSelectedIGTLMessageSource(); + + signals: + /** @brief This signal is emitted when a new OpenIGTLink message source is + * selected. + * @param source Holds the new selected OpenIGTLink device source. Is null + * if the old source is deselected and no new source is selected. + */ + void IGTLMessageSourceSelected(mitk::IGTLMessageSource::Pointer source); + + protected slots: + + void IGTLMessageSourceSelected(us::ServiceReferenceU s); + + + protected: + + /// \brief Creation of the connections + virtual void CreateConnections(); + + virtual void CreateQtPartControl(QWidget *parent); + + Ui::QmitkIGTLMessageSourceSelectionWidgetControls* m_Controls; + + mitk::IGTLMessageSource::Pointer m_CurrentIGTLMessageSource; + + + +}; +#endif diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolStorageSelectionWidgetControls.ui b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidgetControls.ui similarity index 74% copy from Modules/IGTUI/Qmitk/QmitkNavigationToolStorageSelectionWidgetControls.ui copy to Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidgetControls.ui index af246a91db..ec8cc34ada 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolStorageSelectionWidgetControls.ui +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidgetControls.ui @@ -1,40 +1,38 @@ - QmitkNavigationToolStorageSelectionWidgetControls - + QmitkIGTLMessageSourceSelectionWidgetControls + 0 0 199 111 Form - + 0 0 QmitkServiceListWidget QListWidget
QmitkServiceListWidget.h
- - - +
diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingConnector.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingConnector.cpp new file mode 100644 index 0000000000..565e56d0f4 --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingConnector.cpp @@ -0,0 +1,108 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkIGTLStreamingConnector.h" + +//mitk headers +#include +#include +#include +#include + +//qt headers +#include +#include +#include +#include + +//igtl +#include +#include +#include +#include + +//poco headers +//#include + +const std::string QmitkIGTLStreamingConnector::VIEW_ID = + "org.mitk.views.igtldevicesourcemanagementwidget"; + +const unsigned int +QmitkIGTLStreamingConnector::MILISECONDS_BETWEEN_FPS_CHECK = 50; + +QmitkIGTLStreamingConnector::QmitkIGTLStreamingConnector( + QObject* parent) + : QObject(parent) +{ +} + + +QmitkIGTLStreamingConnector::~QmitkIGTLStreamingConnector() +{ +} + +void QmitkIGTLStreamingConnector::Initialize( + mitk::IGTLMessageSource::Pointer msgSource, + mitk::IGTLMessageProvider::Pointer msgProvider) +{ + this->m_IGTLMessageProvider = msgProvider; + this->m_IGTLMessageSource = msgSource; + + connect(&this->m_CheckFPSTimer, SIGNAL(timeout()), + this, SLOT(OnCheckFPS())); + connect(&this->m_StreamingTimer, SIGNAL(timeout()), + this, SLOT(OnUpdateSource())); + + this->m_CheckFPSTimer.start(MILISECONDS_BETWEEN_FPS_CHECK); +} + +void QmitkIGTLStreamingConnector::OnCheckFPS() +{ + //get the fps from the source + unsigned int fps = this->m_IGTLMessageSource->GetFPS(); + + //check if the fps is set + if ( fps > 0 ) + { + if (!this->m_StreamingTimer.isActive()) + { + //it is set, so the streaming has to be started + int ms = 1.0 / (double)fps * 1000; + this->m_StreamingTimer.start( ms ); + } + } + else + { + //stop the streaming + this->m_StreamingTimer.stop(); + } +} + +void QmitkIGTLStreamingConnector::OnUpdateSource() +{ + //update the message source + this->m_IGTLMessageSource->Update(); + + //get the latest message + mitk::IGTLMessage* curMsg = this->m_IGTLMessageSource->GetOutput(); + + //check if this message is valid + if ( curMsg->IsDataValid() ) + { + //send the latest output to the message provider + this->m_IGTLMessageProvider->Send(curMsg); + } +} diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingConnector.h b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingConnector.h new file mode 100644 index 0000000000..95a4023aa3 --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingConnector.h @@ -0,0 +1,87 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QMITKIGTLSTREAMINGCONNECTOR_H +#define QMITKIGTLSTREAMINGCONNECTOR_H + +//QT headers +#include + +//mitk headers +#include "MitkOpenIGTLinkUIExports.h" +#include "mitkIGTLMessageSource.h" +#include "mitkIGTLMessageProvider.h" + + /** Documentation: + * \brief This class is used to stream messages from a IGTL message source + * into the sending queue of a message provider. + * + * The data from the queue will be send to the requesting device. + * + * This class is just needed because of the qtimer functionality. Check also + * the MessageProvider for more information. + * + * \ingroup OpenIGTLinkUI + */ +class MITKOPENIGTLINKUI_EXPORT QmitkIGTLStreamingConnector : public QObject +{ + Q_OBJECT + + public: + static const std::string VIEW_ID; + + QmitkIGTLStreamingConnector(QObject* parent = 0); + ~QmitkIGTLStreamingConnector(); + + /** @brief Sets the message source that is the end of the pipeline and the + * message provider which will send the message + */ + void Initialize(mitk::IGTLMessageSource::Pointer msgSource, + mitk::IGTLMessageProvider::Pointer msgProvider); + + protected slots: + /** @brief checks the fps of the message source, if it is unequal 0 the + * streaming is started. + */ + void OnCheckFPS(); + /** @brief updates the message source and sends the latest output to the + * provider + */ + void OnUpdateSource(); + + protected: + /** @brief holds the message source that has to stream its data */ + mitk::IGTLMessageSource::Pointer m_IGTLMessageSource; + + /** @brief holds the message provider that will send the stream data from the + * source + */ + mitk::IGTLMessageProvider::Pointer m_IGTLMessageProvider; + + /** @brief the timer that is configured depending on the fps, if it is + * fired the pipeline is updated and the IGTLMessage added to the sending + * queue + */ + QTimer m_StreamingTimer; + + /** @brief Everytime this timer is fired the fps of the message source are + * checked and the streaming is started or stopped + */ + QTimer m_CheckFPSTimer; + + static const unsigned int MILISECONDS_BETWEEN_FPS_CHECK; +}; +#endif diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.cpp new file mode 100644 index 0000000000..f4608eb86f --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.cpp @@ -0,0 +1,307 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkIGTLStreamingManagementWidget.h" + +//mitk headers +#include +#include +#include +#include + +//qt headers +#include +#include +#include +#include + +//igtl +#include +#include +#include +#include + +//poco headers +#include + +const std::string QmitkIGTLStreamingManagementWidget::VIEW_ID = + "org.mitk.views.igtldevicesourcemanagementwidget"; + +QmitkIGTLStreamingManagementWidget::QmitkIGTLStreamingManagementWidget( + QWidget* parent, Qt::WindowFlags f) + : QWidget(parent, f), m_IsClient(false) +{ + m_Controls = NULL; + this->m_IGTLDevice = NULL; + CreateQtPartControl(this); +} + + +QmitkIGTLStreamingManagementWidget::~QmitkIGTLStreamingManagementWidget() +{ +} + +void QmitkIGTLStreamingManagementWidget::CreateQtPartControl(QWidget *parent) +{ + if (!m_Controls) + { + // create GUI widgets + m_Controls = new Ui::QmitkIGTLStreamingManagementWidgetControls; + // setup GUI widgets + m_Controls->setupUi(parent); + } + + //connect slots with signals + CreateConnections(); +} + +void QmitkIGTLStreamingManagementWidget::CreateConnections() +{ + if (m_Controls) + { + connect( (QObject*)(m_Controls->messageSourceSelectionWidget), + SIGNAL(IGTLMessageSourceSelected(mitk::IGTLMessageSource::Pointer)), + this, + SLOT(SourceSelected(mitk::IGTLMessageSource::Pointer)) ); + connect( m_Controls->startStreamPushButton, SIGNAL(clicked()), + this, SLOT(OnStartStreaming())); + connect( m_Controls->stopStreamPushButton, SIGNAL(clicked()), + this, SLOT(OnStopStreaming())); + } +} + +void QmitkIGTLStreamingManagementWidget::AdaptGUIToState() +{ + if (this->m_IGTLMsgProvider.IsNotNull()) + { + //get the state of the device + mitk::IGTLDevice::IGTLDeviceState state = + this->m_IGTLDevice->GetState(); + + switch (state) + { + case mitk::IGTLDevice::Setup: + case mitk::IGTLDevice::Ready: + m_Controls->messageSourceSelectionWidget->setEnabled(false); + m_Controls->selectedSourceLabel->setText(""); + m_Controls->startStreamPushButton->setEnabled(false); + m_Controls->selectedSourceLabel->setEnabled(false); + m_Controls->label->setEnabled(false); + m_Controls->stopStreamPushButton->setEnabled(false); + m_Controls->fpsLabel->setEnabled(false); + m_Controls->fpsSpinBox->setEnabled(false); + break; + case mitk::IGTLDevice::Running: + //check the number of connections of the device, a server can be in + //the running state even if there is no connected device, this part of + //the GUI shall just be available when there is a connection + if ( this->m_IGTLDevice->GetNumberOfConnections() == 0 ) + { + m_Controls->messageSourceSelectionWidget->setEnabled(false); + m_Controls->selectedSourceLabel->setText(""); + m_Controls->startStreamPushButton->setEnabled(false); + m_Controls->selectedSourceLabel->setEnabled(false); + m_Controls->label->setEnabled(false); + m_Controls->stopStreamPushButton->setEnabled(false); + m_Controls->fpsLabel->setEnabled(false); + m_Controls->fpsSpinBox->setEnabled(false); + } + else //there is a connection + { + //check if the user already selected a source to stream + if ( this->m_IGTLMsgSource.IsNull() ) // he did not so far + { + m_Controls->messageSourceSelectionWidget->setEnabled(true); + m_Controls->selectedSourceLabel->setText(""); + m_Controls->startStreamPushButton->setEnabled(false); + m_Controls->selectedSourceLabel->setEnabled(false); + m_Controls->label->setEnabled(false); + m_Controls->stopStreamPushButton->setEnabled(false); + m_Controls->fpsLabel->setEnabled(false); + m_Controls->fpsSpinBox->setEnabled(false); + } + else //user already selected a source + { + QString nameOfSource = + QString::fromStdString(m_IGTLMsgSource->GetName()); + m_Controls->messageSourceSelectionWidget->setEnabled(true); + m_Controls->selectedSourceLabel->setText(nameOfSource); + m_Controls->selectedSourceLabel->setEnabled(true); + m_Controls->label->setEnabled(true); + + //check if the streaming is already running + if (this->m_IGTLMsgProvider->IsStreaming()) + { + m_Controls->startStreamPushButton->setEnabled(false); + m_Controls->stopStreamPushButton->setEnabled(true); + m_Controls->fpsLabel->setEnabled(false); + m_Controls->fpsSpinBox->setEnabled(false); + } + else + { + m_Controls->startStreamPushButton->setEnabled(true); + m_Controls->stopStreamPushButton->setEnabled(false); + m_Controls->fpsLabel->setEnabled(true); + m_Controls->fpsSpinBox->setEnabled(true); + } + } + } + break; + default: + mitkThrow() << "Invalid Device State"; + break; + } + } + else + { + this->DisableSourceControls(); + } +} + +void QmitkIGTLStreamingManagementWidget::LoadSource( + mitk::IGTLMessageProvider::Pointer provider) +{ + //reset the GUI + DisableSourceControls(); + + if ( provider.IsNull() ) + return; + + //reset the observers + if ( this->m_IGTLDevice.IsNotNull() ) + { +// this->m_IGTLDevice->RemoveObserver(m_MessageReceivedObserverTag); +// this->m_IGTLDevice->RemoveObserver(m_CommandReceivedObserverTag); + this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); + } + + + this->m_IGTLMsgProvider = provider; + + //get the device + this->m_IGTLDevice = this->m_IGTLMsgProvider->GetIGTLDevice(); + + //check if the device is a server or a client + if ( dynamic_cast( + this->m_IGTLDevice.GetPointer()) == NULL ) + { + m_IsClient = false; + } + else + { + m_IsClient = true; + } + + typedef itk::SimpleMemberCommand< QmitkIGTLStreamingManagementWidget > CurCommandType; +// CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); +// messageReceivedCommand->SetCallbackFunction( +// this, &QmitkIGTLStreamingManagementWidget::OnMessageReceived ); +// this->m_MessageReceivedObserverTag = +// this->m_IGTLDevice->AddObserver(mitk::MessageReceivedEvent(), messageReceivedCommand); + +// CurCommandType::Pointer commandReceivedCommand = CurCommandType::New(); +// commandReceivedCommand->SetCallbackFunction( +// this, &QmitkIGTLStreamingManagementWidget::OnCommandReceived ); +// this->m_CommandReceivedObserverTag = +// this->m_IGTLDevice->AddObserver(mitk::CommandReceivedEvent(), commandReceivedCommand); + + CurCommandType::Pointer connectionLostCommand = CurCommandType::New(); + connectionLostCommand->SetCallbackFunction( + this, &QmitkIGTLStreamingManagementWidget::OnLostConnection ); + this->m_LostConnectionObserverTag = this->m_IGTLDevice->AddObserver( + mitk::LostConnectionEvent(), connectionLostCommand); + + CurCommandType::Pointer newConnectionCommand = CurCommandType::New(); + newConnectionCommand->SetCallbackFunction( + this, &QmitkIGTLStreamingManagementWidget::OnNewConnection ); + this->m_NewConnectionObserverTag = this->m_IGTLDevice->AddObserver( + mitk::NewClientConnectionEvent(), newConnectionCommand); + + CurCommandType::Pointer stateModifiedCommand = CurCommandType::New(); + stateModifiedCommand->SetCallbackFunction( + this, &QmitkIGTLStreamingManagementWidget::OnDeviceStateChanged ); + this->m_StateModifiedObserverTag = this->m_IGTLDevice->AddObserver( + itk::ModifiedEvent(), stateModifiedCommand); + + this->AdaptGUIToState(); +} + +void QmitkIGTLStreamingManagementWidget::DisableSourceControls() +{ + m_Controls->selectedSourceLabel->setText(""); + m_Controls->startStreamPushButton->setEnabled(false); + m_Controls->stopStreamPushButton->setEnabled(false); + m_Controls->fpsLabel->setEnabled(false); + m_Controls->fpsSpinBox->setEnabled(false); + m_Controls->selectedSourceLabel->setEnabled(false); + m_Controls->label->setEnabled(false); + m_Controls->messageSourceSelectionWidget->setEnabled(false); +} + +void QmitkIGTLStreamingManagementWidget::SourceSelected( + mitk::IGTLMessageSource::Pointer source) +{ + //reset everything + this->DisableSourceControls(); + + if (source.IsNotNull()) //no source selected + { + this->m_IGTLMsgSource = source; + } + + this->AdaptGUIToState(); +} + +void QmitkIGTLStreamingManagementWidget::OnStartStreaming() +{ + unsigned int fps = this->m_Controls->fpsSpinBox->value(); + this->m_IGTLMsgProvider->StartStreamingOfSource(this->m_IGTLMsgSource, fps); + this->AdaptGUIToState(); +} + +void QmitkIGTLStreamingManagementWidget::OnStopStreaming() +{ + this->m_IGTLMsgProvider->StopStreamingOfSource(this->m_IGTLMsgSource); + this->AdaptGUIToState(); +} + +void QmitkIGTLStreamingManagementWidget::OnMessageReceived() +{ +} + +void QmitkIGTLStreamingManagementWidget::OnCommandReceived() +{ +} + +void QmitkIGTLStreamingManagementWidget::OnDeviceStateChanged() +{ + this->AdaptGUIToState(); +} + +void QmitkIGTLStreamingManagementWidget::OnLostConnection() +{ + this->AdaptGUIToState(); +} + +void QmitkIGTLStreamingManagementWidget::OnNewConnection() +{ + //get the current selection and call SourceSelected which will call AdaptGUI + mitk::IGTLMessageSource::Pointer curSelSrc = + m_Controls->messageSourceSelectionWidget->GetSelectedIGTLMessageSource(); + SourceSelected(curSelSrc); +} diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.h b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.h new file mode 100644 index 0000000000..c024a4ba02 --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.h @@ -0,0 +1,135 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QMITKIGTLStreamingMANAGEMENTWIDGET_H +#define QMITKIGTLStreamingMANAGEMENTWIDGET_H + +//QT headers +#include +#include + +//mitk headers +#include "MitkOpenIGTLinkUIExports.h" +#include "mitkIGTLMessageProvider.h" +#include "mitkIGTLClient.h" +#include "mitkDataStorage.h" + +//itk +#include + +//ui header +#include "ui_QmitkIGTLStreamingManagementWidgetControls.h" + + /** Documentation: + * \brief An object of this class offers an UI to manage the streaming of + * message sources. + * + * + * \ingroup OpenIGTLinkUI + */ +class MITKOPENIGTLINKUI_EXPORT QmitkIGTLStreamingManagementWidget : public QWidget +{ + Q_OBJECT + + public: + static const std::string VIEW_ID; + + /** Loads a provider to the widget. The old source is dropped, so be careful, + * if the source is not saved somewhere else it might be lost. You might + * want to ask the user if he wants to save the changes before calling this + * method. + * @param provider This provider will be loaded and might be modified + * by the user. + */ + void LoadSource(mitk::IGTLMessageProvider::Pointer provider); + + QmitkIGTLStreamingManagementWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); + ~QmitkIGTLStreamingManagementWidget(); + + /** + * \brief Is called when the current device received a message + */ + void OnMessageReceived(); + + /** + * \brief Is called when the current device received a command + */ + void OnCommandReceived(); + + /** + * \brief Is called when the current device lost a connection to one of its + * sockets + */ + void OnLostConnection(); + + /** + * \brief Is called when the current device connected to another device + */ + void OnNewConnection(); + + + protected slots: + void OnStartStreaming(); + void OnStopStreaming(); + + /** \brief Is called when a new source is selected. + * @param source the newly selected source + */ + void SourceSelected(mitk::IGTLMessageSource::Pointer source); + + protected: + /** + * \brief Adapts the GUI to the state of the device + */ + void AdaptGUIToState(); + + /** + * \brief Calls AdaptGUIToState() + */ + void OnDeviceStateChanged(); + + /// \brief Fills the commands combo box with available commands + void FillCommandsComboBox(); + + /// \brief Creation of the connections + virtual void CreateConnections(); + + virtual void CreateQtPartControl(QWidget *parent); + + Ui::QmitkIGTLStreamingManagementWidgetControls* m_Controls; + + /** @brief holds the OpenIGTLink device */ + mitk::IGTLDevice::Pointer m_IGTLDevice; + + /** @brief holds the IGTL Message Provider that will send the stream */ + mitk::IGTLMessageProvider::Pointer m_IGTLMsgProvider; + + /** @brief holds the IGTLDeviceSource we are working with. */ + mitk::IGTLMessageSource::Pointer m_IGTLMsgSource; + + /** @brief flag to indicate if the IGTL device is a client or a server */ + bool m_IsClient; + + unsigned long m_MessageReceivedObserverTag; + unsigned long m_CommandReceivedObserverTag; + unsigned long m_LostConnectionObserverTag; + unsigned long m_NewConnectionObserverTag; + unsigned long m_StateModifiedObserverTag; + + //############## private help methods ####################### + void DisableSourceControls(); +}; +#endif diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidgetControls.ui b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidgetControls.ui new file mode 100644 index 0000000000..7ec546085a --- /dev/null +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidgetControls.ui @@ -0,0 +1,134 @@ + + + QmitkIGTLStreamingManagementWidgetControls + + + + 0 + 0 + 443 + 371 + + + + Form + + + + + + false + + + + + + + + + false + + + The selected IGTL device source + + + Selected IGTL Message Source: + + + + + + + false + + + <none> + + + + + + + + + + + false + + + Start Stream + + + + + + + false + + + Stop Stream + + + + + + + false + + + + 0 + 0 + + + + FPS: + + + + + + + false + + + + 0 + 0 + + + + 150 + + + 10 + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + QmitkIGTLMessageSourceSelectionWidget + QTextEdit +
QmitkIGTLMessageSourceSelectionWidget.h
+
+
+ + +
diff --git a/Modules/OpenIGTLinkUI/files.cmake b/Modules/OpenIGTLinkUI/files.cmake new file mode 100644 index 0000000000..186d97d944 --- /dev/null +++ b/Modules/OpenIGTLinkUI/files.cmake @@ -0,0 +1,32 @@ +set(CPP_FILES + Qmitk/QmitkIGTLDeviceSourceSelectionWidget.cpp + Qmitk/QmitkIGTLMessageSourceSelectionWidget.cpp + Qmitk/QmitkIGTLDeviceSourceManagementWidget.cpp + Qmitk/QmitkIGTLStreamingManagementWidget.cpp + Qmitk/QmitkIGTLStreamingConnector.cpp + Qmitk/QmitkIGTLDeviceSetupConnectionWidget.cpp + Qmitk/QmitkIGTLDeviceCommandWidget.cpp +) + +set(UI_FILES + Qmitk/QmitkIGTLDeviceSourceSelectionWidgetControls.ui + Qmitk/QmitkIGTLMessageSourceSelectionWidgetControls.ui + Qmitk/QmitkIGTLDeviceSourceManagementWidgetControls.ui + Qmitk/QmitkIGTLStreamingManagementWidgetControls.ui + Qmitk/QmitkIGTLDeviceSetupConnectionWidgetControls.ui + Qmitk/QmitkIGTLDeviceCommandWidgetControls.ui +) + +set(MOC_H_FILES + Qmitk/QmitkIGTLDeviceSourceSelectionWidget.h + Qmitk/QmitkIGTLMessageSourceSelectionWidget.h + Qmitk/QmitkIGTLDeviceSourceManagementWidget.h + Qmitk/QmitkIGTLStreamingManagementWidget.h + Qmitk/QmitkIGTLStreamingConnector.h + Qmitk/QmitkIGTLDeviceSetupConnectionWidget.h + Qmitk/QmitkIGTLDeviceCommandWidget.h +) + +set(QRC_FILES + #resources/OpenIGTLinkUI.qrc +) diff --git a/Modules/OpenIGTLinkUI/mitkIGTUIConfig.h.in b/Modules/OpenIGTLinkUI/mitkIGTUIConfig.h.in new file mode 100644 index 0000000000..17365e6892 --- /dev/null +++ b/Modules/OpenIGTLinkUI/mitkIGTUIConfig.h.in @@ -0,0 +1,4 @@ +/* + mitkIGTUIConfig.h + this file is generated. Do not change! +*/ diff --git a/Modules/OpenIGTLinkUI/resources/OpenIGTLinkUI.qrc b/Modules/OpenIGTLinkUI/resources/OpenIGTLinkUI.qrc new file mode 100644 index 0000000000..816d0858ba --- /dev/null +++ b/Modules/OpenIGTLinkUI/resources/OpenIGTLinkUI.qrc @@ -0,0 +1,19 @@ + + + + + diff --git a/Modules/Overlays/files.cmake b/Modules/Overlays/files.cmake index 4f128aa132..f561d168c0 100644 --- a/Modules/Overlays/files.cmake +++ b/Modules/Overlays/files.cmake @@ -1,13 +1,14 @@ set(H_FILES ) set(CPP_FILES mitkTextOverlay2D.cpp mitkTextOverlay3D.cpp mitkLabelOverlay3D.cpp + mitkColorBarOverlay.cpp mitkOverlay2DLayouter.cpp mitkScaleLegendOverlay.cpp mitkLogoOverlay.cpp mitkVtkLogoRepresentation.cxx ) diff --git a/Modules/Overlays/mitkColorBarOverlay.cpp b/Modules/Overlays/mitkColorBarOverlay.cpp new file mode 100644 index 0000000000..7e12808596 --- /dev/null +++ b/Modules/Overlays/mitkColorBarOverlay.cpp @@ -0,0 +1,183 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkColorBarOverlay.h" +#include "mitkLookupTable.h" +#include "mitkLookupTableProperty.h" +#include + +mitk::ColorBarOverlay::ColorBarOverlay() +{ + SetDrawAnnotations(true); + + SetDrawTickLabels(true); + + SetOrientationToVertical(); + + SetMaxNumberOfColors(100); + SetNumberOfLabels(4); + + SetAnnotationTextScaling(false); + + SetLookupTable(NULL); +} + + +mitk::ColorBarOverlay::~ColorBarOverlay() +{ +} + +mitk::ColorBarOverlay::LocalStorage::~LocalStorage() +{ +} + +mitk::ColorBarOverlay::LocalStorage::LocalStorage() +{ + m_ScalarBarActor = vtkSmartPointer::New(); +} + +void mitk::ColorBarOverlay::UpdateVtkOverlay(mitk::BaseRenderer *renderer) +{ + LocalStorage* ls = this->m_LSH.GetLocalStorage(renderer); + + if(ls->IsGenerateDataRequired(renderer,this)) + { + ls->m_ScalarBarActor->SetDrawAnnotations(this->GetDrawAnnotations()); + ls->m_ScalarBarActor->SetLookupTable(this->GetLookupTable()); + ls->m_ScalarBarActor->SetOrientation(this->GetOrientation()); + ls->m_ScalarBarActor->SetDrawTickLabels(this->GetDrawTickLabels()); + ls->m_ScalarBarActor->SetMaximumNumberOfColors(this->GetMaxNumberOfColors()); + ls->m_ScalarBarActor->SetNumberOfLabels(this->GetNumberOfLabels()); + ls->m_ScalarBarActor->SetAnnotationTextScaling(this->GetAnnotationTextScaling()); + //manually set position so there is no overlap with mitk logo in 3d renderwindow + if (this->GetOrientation()==1) + { + ls->m_ScalarBarActor->SetPosition(0.80,0.15); + ls->m_ScalarBarActor->SetWidth(0.15); + ls->m_ScalarBarActor->SetHeight(0.85); + }else + { + ls->m_ScalarBarActor->SetPosition(0.03,0.03); + ls->m_ScalarBarActor->SetWidth(0.8); + ls->m_ScalarBarActor->SetHeight(0.15); + } + } + +} + +vtkProp* mitk::ColorBarOverlay::GetVtkProp(BaseRenderer *renderer) const +{ + LocalStorage* ls = this->m_LSH.GetLocalStorage(renderer); + return ls->m_ScalarBarActor; +} + +void mitk::ColorBarOverlay::SetDrawAnnotations(bool annotations) +{ + SetBoolProperty("ColorBarOverlay.DrawAnnotations", annotations); +} + +bool mitk::ColorBarOverlay::GetDrawAnnotations() const +{ + bool annotations; + GetPropertyList()->GetBoolProperty("ColorBarOverlay.DrawAnnotations", annotations); + return annotations; +} + +void mitk::ColorBarOverlay::SetLookupTable(vtkSmartPointer table) +{ + mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); + mitk::LookupTableProperty::Pointer prop = mitk::LookupTableProperty::New(lut); + lut->SetVtkLookupTable(table); + prop->SetLookupTable(lut); + SetProperty("ColorBarOverlay.LookupTable", prop.GetPointer()); +} + +vtkSmartPointer mitk::ColorBarOverlay::GetLookupTable() const +{ + mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); + lut = dynamic_cast(GetPropertyList()->GetProperty("ColorBarOverlay.LookupTable"))->GetLookupTable(); + return lut->GetVtkLookupTable(); +} + +void mitk::ColorBarOverlay::SetOrientation(int orientation) +{ + SetIntProperty("ColorBarOverlay.Orientation", orientation); +} + +int mitk::ColorBarOverlay::GetOrientation() const +{ + int orientation; + GetPropertyList()->GetIntProperty("ColorBarOverlay.Orientation", orientation); + return orientation; +} + +void mitk::ColorBarOverlay::SetDrawTickLabels(bool ticks) +{ + SetBoolProperty("ColorBarOverlay.DrawTicks", ticks); +} + +bool mitk::ColorBarOverlay::GetDrawTickLabels() const +{ + bool ticks; + GetPropertyList()->GetBoolProperty("ColorBarOverlay.DrawTicks", ticks); + return ticks; +} + +void mitk::ColorBarOverlay::SetOrientationToHorizontal() +{ + SetOrientation(0); +} + +void mitk::ColorBarOverlay::SetOrientationToVertical() +{ + SetOrientation(1); +} + +void mitk::ColorBarOverlay::SetMaxNumberOfColors(int numberOfColors) +{ + SetIntProperty("ColorBarOverlay.MaximumNumberOfColors", numberOfColors); +} + +int mitk::ColorBarOverlay::GetMaxNumberOfColors() const +{ + int numberOfColors; + GetPropertyList()->GetIntProperty("ColorBarOverlay.MaximumNumberOfColors", numberOfColors); + return numberOfColors; +} + +void mitk::ColorBarOverlay::SetNumberOfLabels(int numberOfLabels) +{ + SetIntProperty("ColorBarOverlay.NumberOfLabels", numberOfLabels); +} + +int mitk::ColorBarOverlay::GetNumberOfLabels() const +{ + int numberOfLabels; + GetPropertyList()->GetIntProperty("ColorBarOverlay.NumberOfLabels", numberOfLabels); + return numberOfLabels; +} + +void mitk::ColorBarOverlay::SetAnnotationTextScaling(bool scale) +{ + SetBoolProperty("ColorBarOverlay.ScaleAnnotationText", scale); +} + +bool mitk::ColorBarOverlay::GetAnnotationTextScaling() const +{ + bool scale; + GetPropertyList()->GetBoolProperty("ColorBarOverlay.ScaleAnnotationText", scale); + return scale; +} diff --git a/Modules/Overlays/mitkColorBarOverlay.h b/Modules/Overlays/mitkColorBarOverlay.h new file mode 100644 index 0000000000..e02a4e8868 --- /dev/null +++ b/Modules/Overlays/mitkColorBarOverlay.h @@ -0,0 +1,101 @@ +/*=================================================================== + + The Medical Imaging Interaction Toolkit (MITK) + + Copyright (c) German Cancer Research Center, + Division of Medical and Biological Informatics. + All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. + + See LICENSE.txt or http://www.mitk.org for details. + + ===================================================================*/ + +#ifndef COLORBAROVERLAY_H +#define COLORBAROVERLAY_H + +#include +#include +#include +#include +#include "MitkOverlaysExports.h" + +class vtkScalarBarActor; + +namespace mitk { + +/** \brief Displays configurable scales on the renderwindow. The scale is determined by the image spacing. */ +class MITKOVERLAYS_EXPORT ColorBarOverlay : public mitk::VtkOverlay { +public: + + class LocalStorage : public mitk::Overlay::BaseLocalStorage + { + public: + /** \brief Actor of a 2D render window. */ + vtkSmartPointer m_ScalarBarActor; + + /** \brief Timestamp of last update of stored data. */ + itk::TimeStamp m_LastUpdateTime; + + /** \brief Default constructor of the local storage. */ + LocalStorage(); + /** \brief Default deconstructor of the local storage. */ + ~LocalStorage(); + }; + + mitkClassMacro(ColorBarOverlay, mitk::VtkOverlay); + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + void SetDrawAnnotations(bool annotations); + bool GetDrawAnnotations() const; + + void SetOrientationToHorizontal(); + void SetOrientationToVertical(); + void SetOrientation(int orientation); + int GetOrientation() const; + + void SetMaxNumberOfColors(int numberOfColors); + int GetMaxNumberOfColors() const; + + void SetNumberOfLabels(int numberOfLabels); + int GetNumberOfLabels() const; + + void SetLookupTable(vtkSmartPointer table); + vtkSmartPointer GetLookupTable() const; + + void SetDrawTickLabels(bool ticks); + bool GetDrawTickLabels() const; + + void SetAnnotationTextScaling(bool scale); + bool GetAnnotationTextScaling() const; + +protected: + + /** \brief The LocalStorageHandler holds all LocalStorages for the render windows. */ + mutable mitk::LocalStorageHandler m_LSH; + + virtual vtkProp* GetVtkProp(BaseRenderer *renderer) const; + virtual void UpdateVtkOverlay(BaseRenderer *renderer); + + /** \brief explicit constructor which disallows implicit conversions */ + explicit ColorBarOverlay(); + + /** \brief virtual destructor in order to derive from this class */ + virtual ~ColorBarOverlay(); + +private: + + /** \brief copy constructor */ + ColorBarOverlay( const ColorBarOverlay &); + + /** \brief assignment operator */ + ColorBarOverlay &operator=(const ColorBarOverlay &); + +}; + +} // namespace mitk +#endif // COLORBAROVERLAY_H diff --git a/Modules/PlanarFigure/CMakeLists.txt b/Modules/PlanarFigure/CMakeLists.txt index 6dfb7341aa..2f2b359e3c 100644 --- a/Modules/PlanarFigure/CMakeLists.txt +++ b/Modules/PlanarFigure/CMakeLists.txt @@ -1,8 +1,8 @@ MITK_CREATE_MODULE( INCLUDE_DIRS PRIVATE src/Algorithms src/DataManagement src/Interactions src/IO src/Rendering - DEPENDS MitkLegacyIO MitkSceneSerializationBase MitkLegacyGL MitkOverlays + DEPENDS MitkSceneSerializationBase MitkLegacyGL MitkOverlays WARNINGS_AS_ERRORS ) add_subdirectory(test) diff --git a/Modules/PlanarFigureSegmentation/src/mitkPlanarFigureSegmentationController.cpp b/Modules/PlanarFigureSegmentation/src/mitkPlanarFigureSegmentationController.cpp index 6e44b799c5..2e61685e59 100644 --- a/Modules/PlanarFigureSegmentation/src/mitkPlanarFigureSegmentationController.cpp +++ b/Modules/PlanarFigureSegmentation/src/mitkPlanarFigureSegmentationController.cpp @@ -1,315 +1,301 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPlanarFigureSegmentationController.h" -#include "mitkSurfaceToImageFilter.h" - #include #include #include #include - #include #include -#include "mitkImageWriter.h" -#include "mitkSurfaceVtkWriter.h" -#include "mitkImageToSurfaceFilter.h" - -#include "mitkImageAccessByItk.h" - -#include "mitkImageCast.h" +#include +#include +#include +#include +#include mitk::PlanarFigureSegmentationController::PlanarFigureSegmentationController() : itk::Object() , m_ReduceFilter( NULL ) , m_NormalsFilter( NULL ) , m_DistanceImageCreator( NULL ) , m_ReferenceImage( NULL ) , m_SegmentationAsImage( NULL ) { InitializeFilters(); } mitk::PlanarFigureSegmentationController::~PlanarFigureSegmentationController() { } void mitk::PlanarFigureSegmentationController::SetReferenceImage( mitk::Image::Pointer referenceImage ) { m_ReferenceImage = referenceImage; } void mitk::PlanarFigureSegmentationController::AddPlanarFigure( mitk::PlanarFigure::Pointer planarFigure ) { if ( planarFigure.IsNull() ) return; bool newFigure = true; std::size_t indexOfFigure = 0; for( std::size_t i=0; iCreateSurfaceFromPlanarFigure( planarFigure ); m_SurfaceList.push_back( figureAsSurface ); if (!m_PlanarFigureList.empty()) { indexOfFigure = m_PlanarFigureList.size() -1 ; } } else { figureAsSurface = this->CreateSurfaceFromPlanarFigure( planarFigure ); m_SurfaceList.at(indexOfFigure) = figureAsSurface; } if ( m_ReduceFilter.IsNull() ) { InitializeFilters(); } m_ReduceFilter->SetInput( indexOfFigure, figureAsSurface ); m_NormalsFilter->SetInput( indexOfFigure, m_ReduceFilter->GetOutput( indexOfFigure ) ); m_DistanceImageCreator->SetInput( indexOfFigure, m_NormalsFilter->GetOutput( indexOfFigure ) ); } void mitk::PlanarFigureSegmentationController::RemovePlanarFigure( mitk::PlanarFigure::Pointer planarFigure ) { if ( planarFigure.IsNull() ) return; bool figureFound = false; std::size_t indexOfFigure = 0; for( std::size_t i=0; iRemoveInputs( m_NormalsFilter->GetOutput( indexOfFigure ) ); // m_NormalsFilter->RemoveInput( m_ReduceFilter->GetOutput( indexOfFigure ) ); // m_ReduceFilter->RemoveInput( const_cast(m_ReduceFilter->GetInput(indexOfFigure)) ); } else { // this is not very nice! If the figure that has been removed is NOT the last // one in the list we have to create new filters and add all remaining // inputs again. // // Has to be done as the filters do not work when removing an input // other than the last one. // create new filters InitializeFilters(); // and add all existing surfaces SurfaceListType::iterator surfaceIter = m_SurfaceList.begin(); int index = 0; for ( surfaceIter = m_SurfaceList.begin(); surfaceIter!=m_SurfaceList.end(); surfaceIter++ ) { m_ReduceFilter->SetInput( index, (*surfaceIter) ); m_NormalsFilter->SetInput( index, m_ReduceFilter->GetOutput( index ) ); m_DistanceImageCreator->SetInput( index, m_NormalsFilter->GetOutput( index ) ); ++index; } } } template void mitk::PlanarFigureSegmentationController::GetImageBase(itk::Image* input, itk::ImageBase<3>::Pointer& result) { result = input; } mitk::Image::Pointer mitk::PlanarFigureSegmentationController::GetInterpolationResult() { m_SegmentationAsImage = NULL; if ( m_PlanarFigureList.size() == 0 ) { m_SegmentationAsImage = mitk::Image::New(); m_SegmentationAsImage->Initialize(mitk::MakeScalarPixelType() , *m_ReferenceImage->GetTimeGeometry()); return m_SegmentationAsImage; } itk::ImageBase<3>::Pointer itkImage; AccessFixedDimensionByItk_1( m_ReferenceImage.GetPointer(), GetImageBase, 3, itkImage ); m_DistanceImageCreator->SetReferenceImage( itkImage.GetPointer() ); m_ReduceFilter->Update(); m_NormalsFilter->Update(); m_DistanceImageCreator->Update(); mitk::Image::Pointer distanceImage = m_DistanceImageCreator->GetOutput(); // Cleanup the pipeline distanceImage->DisconnectPipeline(); m_DistanceImageCreator = NULL; m_NormalsFilter = NULL; m_ReduceFilter = NULL; itkImage = NULL; // If this bool flag is true, the distanceImage will be written to the // filesystem as nrrd-image and as surface-representation. bool debugOutput(false); if ( debugOutput ) { - mitk::ImageWriter::Pointer imageWriter = mitk::ImageWriter::New(); - imageWriter->SetInput( distanceImage ); - imageWriter->SetExtension( ".nrrd" ); - imageWriter->SetFileName( "v:/DistanceImage" ); - imageWriter->Update(); + mitk::IOUtil::Save(distanceImage, "v:/DistanceImage.nrrd"); } mitk::ImageToSurfaceFilter::Pointer imageToSurfaceFilter = mitk::ImageToSurfaceFilter::New(); imageToSurfaceFilter->SetInput( distanceImage ); imageToSurfaceFilter->SetThreshold( 0 ); imageToSurfaceFilter->Update(); mitk::Surface::Pointer segmentationAsSurface = imageToSurfaceFilter->GetOutput(); // Cleanup the pipeline segmentationAsSurface->DisconnectPipeline(); imageToSurfaceFilter = NULL; if ( debugOutput ) { - mitk::SurfaceVtkWriter::Pointer surfaceWriter = mitk::SurfaceVtkWriter::New(); - surfaceWriter->SetInput( segmentationAsSurface ); - surfaceWriter->SetExtension( ".vtk" ); - surfaceWriter->SetFileName( "v:/DistanceImageAsSurface.vtk" ); - surfaceWriter->Update(); + mitk::IOUtil::Save( segmentationAsSurface, "v:/DistanceImageAsSurface.vtk" ); } - mitk::SurfaceToImageFilter::Pointer surfaceToImageFilter = mitk::SurfaceToImageFilter::New(); surfaceToImageFilter->SetInput( segmentationAsSurface ); surfaceToImageFilter->SetImage( m_ReferenceImage ); surfaceToImageFilter->SetMakeOutputBinary(true); surfaceToImageFilter->Update(); m_SegmentationAsImage = surfaceToImageFilter->GetOutput(); // Cleanup the pipeline m_SegmentationAsImage->DisconnectPipeline(); return m_SegmentationAsImage; } mitk::Surface::Pointer mitk::PlanarFigureSegmentationController::CreateSurfaceFromPlanarFigure( mitk::PlanarFigure::Pointer figure ) { if ( figure.IsNull() ) { MITK_ERROR << "Given PlanarFigure is NULL. Please provide valid PlanarFigure."; return NULL; } mitk::Surface::Pointer newSurface = mitk::Surface::New(); vtkSmartPointer points = vtkSmartPointer::New(); vtkSmartPointer polygon = vtkSmartPointer::New(); vtkSmartPointer cells = vtkSmartPointer::New(); vtkSmartPointer polyData = vtkSmartPointer::New(); const mitk::PlaneGeometry* figureGeometry = figure->GetPlaneGeometry(); // Get the polyline mitk::PlanarFigure::PolyLineType planarPolyLine = figure->GetPolyLine(0); mitk::PlanarFigure::PolyLineType::iterator iter; // iterate over the polyline, ... int pointCounter = 0; for( iter = planarPolyLine.begin(); iter != planarPolyLine.end(); iter++ ) { // ... determine the world-coordinates mitk::Point3D pointInWorldCoordiantes; figureGeometry->Map( *iter, pointInWorldCoordiantes ); // and add them as new points to the vtkPoints points->InsertNextPoint( pointInWorldCoordiantes[0], pointInWorldCoordiantes[1], pointInWorldCoordiantes[2] ); ++pointCounter; } // create a polygon with the points of the polyline polygon->GetPointIds()->SetNumberOfIds( pointCounter ); for(int i = 0; i < pointCounter; i++) { polygon->GetPointIds()->SetId(i,i); } // initialize the vtkCellArray and vtkPolyData cells->InsertNextCell(polygon); polyData->SetPoints(points); polyData->SetPolys( cells ); // set the polydata to the surface newSurface->SetVtkPolyData( polyData ); return newSurface; } mitk::PlanarFigureSegmentationController::PlanarFigureListType mitk::PlanarFigureSegmentationController::GetAllPlanarFigures() { return m_PlanarFigureList; } void mitk::PlanarFigureSegmentationController::InitializeFilters() { m_ReduceFilter = mitk::ReduceContourSetFilter::New(); m_ReduceFilter->SetReductionType(ReduceContourSetFilter::NTH_POINT); m_ReduceFilter->SetStepSize( 10 ); m_NormalsFilter = mitk::ComputeContourSetNormalsFilter::New(); m_DistanceImageCreator = mitk::CreateDistanceImageFromSurfaceFilter::New(); } diff --git a/Modules/QtWidgets/src/QmitkIOUtil.cpp b/Modules/QtWidgets/src/QmitkIOUtil.cpp index 8d170d27cb..3a63b77eed 100644 --- a/Modules/QtWidgets/src/QmitkIOUtil.cpp +++ b/Modules/QtWidgets/src/QmitkIOUtil.cpp @@ -1,548 +1,547 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkIOUtil.h" #include -#include #include #include "mitkCoreServices.h" #include "mitkIMimeTypeProvider.h" #include "mitkMimeType.h" #include "mitkCustomMimeType.h" #include "mitkFileReaderRegistry.h" #include "mitkFileWriterRegistry.h" #include "QmitkFileReaderOptionsDialog.h" #include "QmitkFileWriterOptionsDialog.h" // QT #include #include #include #include //ITK #include #include struct QmitkIOUtil::Impl { struct ReaderOptionsDialogFunctor : public ReaderOptionsFunctorBase { virtual bool operator()(LoadInfo& loadInfo) { QmitkFileReaderOptionsDialog dialog(loadInfo); if (dialog.exec() == QDialog::Accepted) { return !dialog.ReuseOptions(); } else { loadInfo.m_Cancel = true; return true; } } }; struct WriterOptionsDialogFunctor : public WriterOptionsFunctorBase { virtual bool operator()(SaveInfo& saveInfo) { QmitkFileWriterOptionsDialog dialog(saveInfo); if (dialog.exec() == QDialog::Accepted) { return !dialog.ReuseOptions(); } else { saveInfo.m_Cancel = true; return true; } } }; }; struct MimeTypeComparison : public std::unary_function { MimeTypeComparison(const std::string& mimeTypeName) : m_Name(mimeTypeName) {} bool operator()(const mitk::MimeType& mimeType) const { return mimeType.GetName() == m_Name; } const std::string m_Name; }; QString QmitkIOUtil::GetFileOpenFilterString() { QString filters; mitk::CoreServicePointer mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider()); std::vector categories = mimeTypeProvider->GetCategories(); for (std::vector::iterator cat = categories.begin(); cat != categories.end(); ++cat) { QSet filterExtensions; std::vector mimeTypes = mimeTypeProvider->GetMimeTypesForCategory(*cat); for (std::vector::iterator mt = mimeTypes.begin(); mt != mimeTypes.end(); ++mt) { std::vector extensions = mt->GetExtensions(); for (std::vector::iterator ext = extensions.begin(); ext != extensions.end(); ++ext) { filterExtensions << QString::fromStdString(*ext); } } QString filter = QString::fromStdString(*cat) + " ("; foreach(const QString& extension, filterExtensions) { filter += "*." + extension + " "; } filter = filter.replace(filter.size()-1, 1, ')'); filters += ";;" + filter; } filters.prepend("All (*)"); return filters; } QList QmitkIOUtil::Load(const QStringList& paths, QWidget* parent) { std::vector loadInfos; foreach(const QString& file, paths) { loadInfos.push_back(LoadInfo(file.toStdString())); } Impl::ReaderOptionsDialogFunctor optionsCallback; std::string errMsg = Load(loadInfos, NULL, NULL, &optionsCallback); if (!errMsg.empty()) { QMessageBox::warning(parent, "Error reading files", QString::fromStdString(errMsg)); mitkThrow() << errMsg; } QList qResult; for(std::vector::const_iterator iter = loadInfos.begin(), iterEnd = loadInfos.end(); iter != iterEnd; ++iter) { for (std::vector::const_iterator dataIter = iter->m_Output.begin(), dataIterEnd = iter->m_Output.end(); dataIter != dataIterEnd; ++dataIter) { qResult << *dataIter; } } return qResult; } mitk::DataStorage::SetOfObjects::Pointer QmitkIOUtil::Load(const QStringList& paths, mitk::DataStorage& storage, QWidget* parent) { std::vector loadInfos; foreach(const QString& file, paths) { loadInfos.push_back(LoadInfo(QFile::encodeName(file).constData())); } mitk::DataStorage::SetOfObjects::Pointer nodeResult = mitk::DataStorage::SetOfObjects::New(); Impl::ReaderOptionsDialogFunctor optionsCallback; std::string errMsg = Load(loadInfos, nodeResult, &storage, &optionsCallback); if (!errMsg.empty()) { QMessageBox::warning(parent, "Error reading files", QString::fromStdString(errMsg)); mitkThrow() << errMsg; } return nodeResult; } QList QmitkIOUtil::Load(const QString& path, QWidget* parent) { QStringList paths; paths << path; return Load(paths, parent); } mitk::DataStorage::SetOfObjects::Pointer QmitkIOUtil::Load(const QString& path, mitk::DataStorage& storage, QWidget* parent) { QStringList paths; paths << path; return Load(paths, storage, parent); } QString QmitkIOUtil::Save(const mitk::BaseData* data, const QString& defaultBaseName, const QString& defaultPath, QWidget* parent) { std::vector dataVector; dataVector.push_back(data); QStringList defaultBaseNames; defaultBaseNames.push_back(defaultBaseName); return Save(dataVector, defaultBaseNames, defaultPath, parent).back(); } QStringList QmitkIOUtil::Save(const std::vector& data, const QStringList& defaultBaseNames, const QString& defaultPath, QWidget* parent) { QStringList fileNames; QString currentPath = defaultPath; std::vector saveInfos; int counter = 0; for(std::vector::const_iterator dataIter = data.begin(), dataIterEnd = data.end(); dataIter != dataIterEnd; ++dataIter, ++counter) { SaveInfo saveInfo(*dataIter, mitk::MimeType(), std::string()); SaveFilter filters(saveInfo); // If there is only the "__all__" filter string, it means there is no writer for this base data if (filters.Size() < 2) { QMessageBox::warning(parent, "Saving not possible", QString("No writer available for type \"%1\"").arg( QString::fromStdString((*dataIter)->GetNameOfClass()))); continue; } // Construct a default path and file name QString filterString = filters.ToString(); QString selectedFilter = filters.GetDefaultFilter(); QString fileName = currentPath; QString dialogTitle = "Save " + QString::fromStdString((*dataIter)->GetNameOfClass()); if (counter < defaultBaseNames.size()) { dialogTitle += " \"" + defaultBaseNames[counter] + "\""; fileName += QDir::separator() + defaultBaseNames[counter]; // We do not append an extension to the file name by default. The extension // is chosen by the user by either selecting a filter or writing the // extension in the file name himself (in the file save dialog). /* QString defaultExt = filters.GetDefaultExtension(); if (!defaultExt.isEmpty()) { fileName += "." + defaultExt; } */ } // Ask the user for a file name QString nextName = QFileDialog::getSaveFileName(parent, dialogTitle, fileName, filterString, &selectedFilter); if (nextName.isEmpty()) { // We stop asking for further file names, but we still save the // data where the user already confirmed the save dialog. break; } fileName = nextName; std::string stdFileName = QFile::encodeName(fileName).constData(); QFileInfo fileInfo(fileName); currentPath = fileInfo.absolutePath(); QString suffix = fileInfo.completeSuffix(); mitk::MimeType filterMimeType = filters.GetMimeTypeForFilter(selectedFilter); mitk::MimeType selectedMimeType; if (fileInfo.exists() && !fileInfo.isFile()) { QMessageBox::warning(parent, "Saving not possible", QString("The path \"%1\" is not a file").arg(fileName)); continue; } // Check if one of the available mime-types match the filename std::vector filterMimeTypes = filters.GetMimeTypes(); for (std::vector::const_iterator mimeTypeIter = filterMimeTypes.begin(), mimeTypeIterEnd = filterMimeTypes.end(); mimeTypeIter != mimeTypeIterEnd; ++mimeTypeIter) { if (mimeTypeIter->AppliesTo(stdFileName)) { selectedMimeType = *mimeTypeIter; break; } } if (!selectedMimeType.IsValid()) { // The file name either does not contain an extension or the // extension is unknown. // If the file already exists, we stop here because we are not able // to (over)write the file without adding a custom suffix. If the file // does not exist, we add the default extension from the currently // selected filter. If the "All" filter was selected, we only add the // default extensions if the file name itself does not already contain // an extension. if (!fileInfo.exists()) { if (filterMimeType == SaveFilter::ALL_MIMETYPE()) { if (suffix.isEmpty()) { // Use the highest ranked mime-type from the list selectedMimeType = filters.GetDefaultMimeType(); } } else { selectedMimeType = filterMimeType; } if (selectedMimeType.IsValid()) { suffix = QString::fromStdString(selectedMimeType.GetExtensions().front()); fileName += "." + suffix; stdFileName = QFile::encodeName(fileName).constData(); // We changed the file name (added a suffix) so ask in case // the file aready exists. fileInfo = QFileInfo(fileName); if (fileInfo.exists()) { if (!fileInfo.isFile()) { QMessageBox::warning(parent, "Saving not possible", QString("The path \"%1\" is not a file").arg(fileName)); continue; } if (QMessageBox::question(parent, "Replace File", QString("A file named \"%1\" already exists. Do you want to replace it?").arg(fileName)) == QMessageBox::No) { continue; } } } } } if (!selectedMimeType.IsValid()) { // The extension/filename is not valid (no mime-type found), bail out QMessageBox::warning(parent, "Saving not possible", QString("No mime-type available which can handle \"%1\".") .arg(fileName)); continue; } if (!QFileInfo(fileInfo.absolutePath()).isWritable()) { QMessageBox::warning(parent, "Saving not possible", QString("The path \"%1\" is not writable").arg(fileName)); continue; } fileNames.push_back(fileName); saveInfo.m_Path = stdFileName; saveInfo.m_MimeType = selectedMimeType; // pre-select the best writer for the chosen mime-type saveInfo.m_WriterSelector.Select(selectedMimeType.GetName()); saveInfos.push_back(saveInfo); } if (!saveInfos.empty()) { Impl::WriterOptionsDialogFunctor optionsCallback; std::string errMsg = Save(saveInfos, &optionsCallback); if (!errMsg.empty()) { QMessageBox::warning(parent, "Error writing files", QString::fromStdString(errMsg)); mitkThrow() << errMsg; } } return fileNames; } void QmitkIOUtil::SaveBaseDataWithDialog(mitk::BaseData* data, std::string fileName, QWidget* /*parent*/) { Save(data, fileName); } void QmitkIOUtil::SaveSurfaceWithDialog(mitk::Surface::Pointer surface, std::string fileName, QWidget* /*parent*/) { Save(surface, fileName); } void QmitkIOUtil::SaveImageWithDialog(mitk::Image::Pointer image, std::string fileName, QWidget* /*parent*/) { Save(image, fileName); } void QmitkIOUtil::SavePointSetWithDialog(mitk::PointSet::Pointer pointset, std::string fileName, QWidget* /*parent*/) { Save(pointset, fileName); } struct QmitkIOUtil::SaveFilter::Impl { Impl(const mitk::IOUtil::SaveInfo& saveInfo) : m_SaveInfo(saveInfo) { // Add an artifical filter for "All" m_MimeTypes.push_back(ALL_MIMETYPE()); m_FilterStrings.push_back("All (*.*)"); // Get all writers and their mime types for the given base data type // (this is sorted already) std::vector mimeTypes = saveInfo.m_WriterSelector.GetMimeTypes(); for (std::vector::const_reverse_iterator iter = mimeTypes.rbegin(), iterEnd = mimeTypes.rend(); iter != iterEnd; ++iter) { QList filterExtensions; mitk::MimeType mimeType = *iter; std::vector extensions = mimeType.GetExtensions(); for (std::vector::iterator extIter = extensions.begin(), extIterEnd = extensions.end(); extIter != extIterEnd; ++extIter) { filterExtensions << QString::fromStdString(*extIter); } if (m_DefaultExtension.isEmpty()) { m_DefaultExtension = QString::fromStdString(extensions.front()); } QString filter = QString::fromStdString(mimeType.GetComment()) + " ("; foreach(const QString& extension, filterExtensions) { filter += "*." + extension + " "; } filter = filter.replace(filter.size()-1, 1, ')'); m_MimeTypes.push_back(mimeType); m_FilterStrings.push_back(filter); } } const mitk::IOUtil::SaveInfo m_SaveInfo; std::vector m_MimeTypes; QStringList m_FilterStrings; QString m_DefaultExtension; }; mitk::MimeType QmitkIOUtil::SaveFilter::ALL_MIMETYPE() { static mitk::CustomMimeType allMimeType(std::string("__all__")); return mitk::MimeType(allMimeType, -1, -1); } QmitkIOUtil::SaveFilter::SaveFilter(const QmitkIOUtil::SaveFilter& other) : d(new Impl(*other.d)) { } QmitkIOUtil::SaveFilter::SaveFilter(const SaveInfo& saveInfo) : d(new Impl(saveInfo)) { } QmitkIOUtil::SaveFilter& QmitkIOUtil::SaveFilter::operator=(const QmitkIOUtil::SaveFilter& other) { d.reset(new Impl(*other.d)); return *this; } std::vector QmitkIOUtil::SaveFilter::GetMimeTypes() const { return d->m_MimeTypes; } QString QmitkIOUtil::SaveFilter::GetFilterForMimeType(const std::string& mimeType) const { std::vector::const_iterator iter = std::find_if(d->m_MimeTypes.begin(), d->m_MimeTypes.end(), MimeTypeComparison(mimeType)); if (iter == d->m_MimeTypes.end()) { return QString(); } int index = static_cast(iter - d->m_MimeTypes.begin()); if (index < 0 || index >= d->m_FilterStrings.size()) { return QString(); } return d->m_FilterStrings[index]; } mitk::MimeType QmitkIOUtil::SaveFilter::GetMimeTypeForFilter(const QString& filter) const { int index = d->m_FilterStrings.indexOf(filter); if (index < 0) { return mitk::MimeType(); } return d->m_MimeTypes[index]; } QString QmitkIOUtil::SaveFilter::GetDefaultFilter() const { if (d->m_FilterStrings.size() > 1) { return d->m_FilterStrings.at(1); } else if (d->m_FilterStrings.size() > 0) { return d->m_FilterStrings.front(); } return QString(); } QString QmitkIOUtil::SaveFilter::GetDefaultExtension() const { return d->m_DefaultExtension; } mitk::MimeType QmitkIOUtil::SaveFilter::GetDefaultMimeType() const { if (d->m_MimeTypes.size() > 1) { return d->m_MimeTypes.at(1); } else if (d->m_MimeTypes.size() > 0) { return d->m_MimeTypes.front(); } return mitk::MimeType(); } QString QmitkIOUtil::SaveFilter::ToString() const { return d->m_FilterStrings.join(";;"); } int QmitkIOUtil::SaveFilter::Size() const { return d->m_FilterStrings.size(); } bool QmitkIOUtil::SaveFilter::IsEmpty() const { return d->m_FilterStrings.isEmpty(); } bool QmitkIOUtil::SaveFilter::ContainsMimeType(const std::string& mimeType) { return std::find_if(d->m_MimeTypes.begin(), d->m_MimeTypes.end(), MimeTypeComparison(mimeType)) != d->m_MimeTypes.end(); } diff --git a/Modules/QtWidgetsExt/src/QmitkPointListWidget.cpp b/Modules/QtWidgetsExt/src/QmitkPointListWidget.cpp index 0a07e936f7..9210692070 100644 --- a/Modules/QtWidgetsExt/src/QmitkPointListWidget.cpp +++ b/Modules/QtWidgetsExt/src/QmitkPointListWidget.cpp @@ -1,498 +1,489 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkPointListWidget.h" #include -#include -#include #include #include #include #include +#include #include #include #include QmitkPointListWidget::QmitkPointListWidget(QWidget *parent, int orientation): QWidget(parent), m_PointListView(NULL), m_MultiWidget(NULL), m_PointSetNode(NULL), m_Orientation(0), m_MovePointUpBtn(NULL), m_MovePointDownBtn(NULL), m_RemovePointBtn(NULL), m_SavePointsBtn(NULL), m_LoadPointsBtn(NULL), m_ToggleAddPoint(NULL), m_AddPoint(NULL), m_Snc1(NULL), m_Snc2(NULL), m_Snc3(NULL), m_DataInteractor(NULL), m_TimeStep(0), m_EditAllowed(true), m_NodeObserverTag(0) { m_PointListView = new QmitkPointListView(); if(orientation != 0) m_Orientation = orientation; SetupUi(); SetupConnections(); ObserveNewNode(NULL); } QmitkPointListWidget::~QmitkPointListWidget() { m_DataInteractor = NULL; if(m_PointSetNode && m_NodeObserverTag) { m_PointSetNode->RemoveObserver(m_NodeObserverTag); m_NodeObserverTag = 0; } m_MultiWidget = NULL; delete m_PointListView; } void QmitkPointListWidget::SetupConnections() { connect(this->m_LoadPointsBtn, SIGNAL(clicked()), this, SLOT(OnBtnLoadPoints())); connect(this->m_SavePointsBtn, SIGNAL(clicked()), this, SLOT(OnBtnSavePoints())); connect(this->m_MovePointUpBtn, SIGNAL(clicked()), this, SLOT(MoveSelectedPointUp())); connect(this->m_MovePointDownBtn, SIGNAL(clicked()), this, SLOT(MoveSelectedPointDown())); connect(this->m_RemovePointBtn, SIGNAL(clicked()), this, SLOT(RemoveSelectedPoint())); connect(this->m_ToggleAddPoint, SIGNAL(toggled(bool)), this, SLOT(OnBtnAddPoint(bool))); connect(this->m_AddPoint, SIGNAL(clicked()), this, SLOT(OnBtnAddPointManually())); connect(this->m_PointListView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnListDoubleClick())); connect(this->m_PointListView, SIGNAL(SignalPointSelectionChanged()), this, SLOT(OnPointSelectionChanged())); } void QmitkPointListWidget::SetupUi() { //Setup the buttons m_ToggleAddPoint = new QPushButton(); m_ToggleAddPoint->setMaximumSize(25,25); m_ToggleAddPoint->setCheckable(true); m_ToggleAddPoint->setToolTip("Toggle point editing (use SHIFT + Left Mouse Button to add Points)"); QIcon iconAdd(":/QtWidgetsExt/btnSetPoints.xpm"); m_ToggleAddPoint->setIcon(iconAdd); m_AddPoint = new QPushButton(); m_AddPoint->setMaximumSize(25,25); m_AddPoint->setToolTip("Manually add point"); QIcon iconAddManually(":/QtWidgetsExt/btnSetPointsManually.xpm"); m_AddPoint->setIcon(iconAddManually); m_RemovePointBtn = new QPushButton(); m_RemovePointBtn->setMaximumSize(25, 25); const QIcon iconDel(":/QtWidgetsExt/btnClear.xpm"); m_RemovePointBtn->setIcon(iconDel); m_RemovePointBtn->setToolTip("Erase one point from list (Hotkey: DEL)"); m_MovePointUpBtn = new QPushButton(); m_MovePointUpBtn->setMaximumSize(25, 25); const QIcon iconUp(":/QtWidgetsExt/btnUp.xpm"); m_MovePointUpBtn->setIcon(iconUp); m_MovePointUpBtn->setToolTip("Swap selected point upwards (Hotkey: F2)"); m_MovePointDownBtn = new QPushButton(); m_MovePointDownBtn->setMaximumSize(25, 25); const QIcon iconDown(":/QtWidgetsExt/btnDown.xpm"); m_MovePointDownBtn->setIcon(iconDown); m_MovePointDownBtn->setToolTip("Swap selected point downwards (Hotkey: F3)"); m_SavePointsBtn = new QPushButton(); m_SavePointsBtn->setMaximumSize(25, 25); QIcon iconSave(":/QtWidgetsExt/btnSave.xpm"); m_SavePointsBtn->setIcon(iconSave); m_SavePointsBtn->setToolTip("Save points to file"); m_LoadPointsBtn = new QPushButton(); m_LoadPointsBtn->setMaximumSize(25, 25); QIcon iconLoad(":/QtWidgetsExt/btnLoad.xpm"); m_LoadPointsBtn->setIcon(iconLoad); m_LoadPointsBtn->setToolTip("Load list of points from file (REPLACES current content)"); int i; QBoxLayout* lay1; QBoxLayout* lay2; switch (m_Orientation) { case 0: lay1 = new QVBoxLayout(this); lay2 = new QHBoxLayout(); i = 0; break; case 1: lay1 = new QHBoxLayout(this); lay2 = new QVBoxLayout(); i=-1; break; case 2: lay1 = new QHBoxLayout(this); lay2 = new QVBoxLayout(); i=0; break; default: lay1 = new QVBoxLayout(this); lay2 = new QHBoxLayout(); i=-1; break; } //setup Layouts this->setLayout(lay1); lay1->addLayout(lay2); lay2->stretch(true); lay2->addWidget(m_ToggleAddPoint); lay2->addWidget(m_AddPoint); lay2->addWidget(m_RemovePointBtn); lay2->addWidget(m_MovePointUpBtn); lay2->addWidget(m_MovePointDownBtn); lay2->addWidget(m_SavePointsBtn); lay2->addWidget(m_LoadPointsBtn); lay1->insertWidget(i,m_PointListView); this->setLayout(lay1); } void QmitkPointListWidget::SetPointSet(mitk::PointSet* newPs) { if(newPs == NULL) return; this->m_PointSetNode->SetData(newPs); dynamic_cast(this->m_PointListView->model())->SetPointSetNode(m_PointSetNode); ObserveNewNode(m_PointSetNode); } void QmitkPointListWidget::SetPointSetNode(mitk::DataNode *newNode) { if (m_DataInteractor.IsNotNull()) m_DataInteractor->SetDataNode(newNode); ObserveNewNode(newNode); dynamic_cast(this->m_PointListView->model())->SetPointSetNode(newNode); } void QmitkPointListWidget::OnBtnSavePoints() { if ((dynamic_cast(m_PointSetNode->GetData())) == NULL) return; // don't write empty point sets. If application logic requires something else then do something else. if ((dynamic_cast(m_PointSetNode->GetData()))->GetSize() == 0) return; // take the previously defined name of node as proposal for filename std::string nodeName = m_PointSetNode->GetName(); nodeName = "/" + nodeName + ".mps"; QString fileNameProposal = QString(); fileNameProposal.append(nodeName.c_str()); QString aFilename = QFileDialog::getSaveFileName( NULL, "Save point set", QDir::currentPath() + fileNameProposal, "MITK Pointset (*.mps)" ); if ( aFilename.isEmpty() ) return; try { - // instantiate the writer and add the point-sets to write - mitk::PointSetWriter::Pointer writer = mitk::PointSetWriter::New(); - writer->SetInput( dynamic_cast(m_PointSetNode->GetData()) ); - writer->SetFileName( aFilename.toLatin1() ); - writer->Update(); + mitk::IOUtil::Save(m_PointSetNode->GetData(), aFilename.toStdString() ); } catch(...) { QMessageBox::warning( this, "Save point set", QString("File writer reported problems writing %1\n\n" "PLEASE CHECK output file!").arg(aFilename) ); } } void QmitkPointListWidget::OnBtnLoadPoints() { // get the name of the file to load QString filename = QFileDialog::getOpenFileName( NULL, "Open MITK Pointset", "", "MITK Point Sets (*.mps)"); if ( filename.isEmpty() ) return; // attempt to load file try { - mitk::PointSetReader::Pointer reader = mitk::PointSetReader::New(); - reader->SetFileName( filename.toLatin1() ); - reader->Update(); - - mitk::PointSet::Pointer pointSet = reader->GetOutput(); + mitk::PointSet::Pointer pointSet = mitk::IOUtil::LoadPointSet(filename.toStdString()); if ( pointSet.IsNull() ) { QMessageBox::warning( this, "Load point set", QString("File reader could not read %1").arg(filename) ); return; } // loading successful this->SetPointSet(pointSet); } catch(...) { QMessageBox::warning( this, "Load point set", QString("File reader collapsed while reading %1").arg(filename) ); } emit PointListChanged(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } mitk::PointSet* QmitkPointListWidget::GetPointSet() { return dynamic_cast(m_PointSetNode->GetData()); } mitk::DataNode* QmitkPointListWidget::GetPointSetNode() { return m_PointSetNode; } void QmitkPointListWidget::SetMultiWidget(QmitkStdMultiWidget *multiWidget) { this->m_MultiWidget = multiWidget; m_PointListView->SetMultiWidget(multiWidget); } void QmitkPointListWidget::RemoveSelectedPoint() { if (!m_PointSetNode) return; mitk::PointSet* pointSet = dynamic_cast( m_PointSetNode->GetData() ); if (!pointSet) return; if (pointSet->GetSize() == 0) return; QmitkPointListModel* pointListModel = dynamic_cast( m_PointListView->model() ); pointListModel->RemoveSelectedPoint(); emit PointListChanged(); } void QmitkPointListWidget::MoveSelectedPointDown() { if (!m_PointSetNode) return; mitk::PointSet* pointSet = dynamic_cast( m_PointSetNode->GetData() ); if (!pointSet) return; if (pointSet->GetSize() == 0) return; QmitkPointListModel* pointListModel = dynamic_cast( m_PointListView->model() ); pointListModel->MoveSelectedPointDown(); emit PointListChanged(); } void QmitkPointListWidget::MoveSelectedPointUp() { if (!m_PointSetNode) return; mitk::PointSet* pointSet = dynamic_cast( m_PointSetNode->GetData() ); if (!pointSet) return; if (pointSet->GetSize() == 0) return; QmitkPointListModel* pointListModel = dynamic_cast( m_PointListView->model() ); pointListModel->MoveSelectedPointUp(); emit PointListChanged(); } void QmitkPointListWidget::OnBtnAddPoint(bool checked) { if (m_PointSetNode.IsNotNull()) { if (checked) { m_DataInteractor = m_PointSetNode->GetDataInteractor(); // If no data Interactor is present create a new one if (m_DataInteractor.IsNull()) { // Create PointSetData Interactor m_DataInteractor = mitk::PointSetDataInteractor::New(); // Load the according state machine for regular point set interaction m_DataInteractor->LoadStateMachine("PointSet.xml"); // Set the configuration file that defines the triggers for the transitions m_DataInteractor->SetEventConfig("PointSetConfig.xml"); // set the DataNode (which already is added to the DataStorage m_DataInteractor->SetDataNode(m_PointSetNode); } } else { m_PointSetNode->SetDataInteractor(NULL); m_DataInteractor=NULL; } emit EditPointSets(checked); } } void QmitkPointListWidget::OnBtnAddPointManually() { mitk::PointSet* pointSet = this->GetPointSet(); int currentPosition = pointSet->GetSize(); QmitkEditPointDialog editPointDialog(this); editPointDialog.SetPoint(pointSet, currentPosition, m_TimeStep); editPointDialog.exec(); } void QmitkPointListWidget::OnListDoubleClick() { } void QmitkPointListWidget::OnPointSelectionChanged() { emit this->PointSelectionChanged(); } void QmitkPointListWidget::DeactivateInteractor(bool) { } void QmitkPointListWidget::EnableEditButton(bool enabled) { m_EditAllowed = enabled; if (enabled == false) m_ToggleAddPoint->setEnabled(false); else m_ToggleAddPoint->setEnabled(true); OnBtnAddPoint(enabled); } void QmitkPointListWidget::ObserveNewNode(mitk::DataNode* node) { if (m_DataInteractor.IsNotNull()) m_DataInteractor->SetDataNode(node); // remove old observer if ( m_PointSetNode ) { if (m_DataInteractor) { m_DataInteractor = NULL; m_ToggleAddPoint->setChecked( false ); } m_PointSetNode->RemoveObserver(m_NodeObserverTag); m_NodeObserverTag = 0; } m_PointSetNode = node; // add new observer if necessary if ( m_PointSetNode ) { itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkPointListWidget::OnNodeDeleted ); m_NodeObserverTag = m_PointSetNode->AddObserver( itk::DeleteEvent(), command ); } else { m_NodeObserverTag = 0; } if (m_EditAllowed == true) m_ToggleAddPoint->setEnabled( m_PointSetNode ); else m_ToggleAddPoint->setEnabled( false ); m_RemovePointBtn->setEnabled( m_PointSetNode ); m_LoadPointsBtn->setEnabled( m_PointSetNode ); m_SavePointsBtn->setEnabled(m_PointSetNode); m_AddPoint->setEnabled(m_PointSetNode); } void QmitkPointListWidget::OnNodeDeleted(const itk::EventObject&) { if(m_PointSetNode.IsNotNull() && ! m_NodeObserverTag) m_PointSetNode->RemoveObserver( m_NodeObserverTag ); m_NodeObserverTag = 0; m_PointSetNode = NULL; m_PointListView->SetPointSetNode(NULL); m_ToggleAddPoint->setEnabled(false); m_RemovePointBtn->setEnabled( false ); m_LoadPointsBtn->setEnabled( false ); m_SavePointsBtn->setEnabled(false); m_AddPoint->setEnabled(false); } void QmitkPointListWidget::SetSnc1(mitk::SliceNavigationController* snc) { if (snc == NULL) { m_PointListView->RemoveSliceNavigationController(m_Snc1); } else { m_PointListView->AddSliceNavigationController(snc); } m_Snc1 = snc; } void QmitkPointListWidget::SetSnc2(mitk::SliceNavigationController* snc) { if (snc == NULL) { m_PointListView->RemoveSliceNavigationController(m_Snc2); } else { m_PointListView->AddSliceNavigationController(snc); } m_Snc2 = snc; } void QmitkPointListWidget::SetSnc3(mitk::SliceNavigationController* snc) { if (snc == NULL) { m_PointListView->RemoveSliceNavigationController(m_Snc3); } else { m_PointListView->AddSliceNavigationController(snc); } m_Snc3 = snc; } void QmitkPointListWidget::AddSliceNavigationController(mitk::SliceNavigationController* snc) { m_PointListView->AddSliceNavigationController(snc); } void QmitkPointListWidget::RemoveSliceNavigationController(mitk::SliceNavigationController* snc) { m_PointListView->RemoveSliceNavigationController(snc); } void QmitkPointListWidget::UnselectEditButton() { m_ToggleAddPoint->setChecked(false); } diff --git a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkTranslationTransformView.cpp b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkTranslationTransformView.cpp index c1f4ae29e8..4e29cf064e 100644 --- a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkTranslationTransformView.cpp +++ b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkTranslationTransformView.cpp @@ -1,142 +1,143 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkTranslationTransformView.h" #include "mitkImageAccessByItk.h" -#include +#include #include QmitkTranslationTransformView::QmitkTranslationTransformView(QWidget* parent, Qt::WindowFlags f ) : QmitkRigidRegistrationTransformsGUIBase(parent, f) { } QmitkTranslationTransformView::~QmitkTranslationTransformView() { } itk::Object::Pointer QmitkTranslationTransformView::GetTransform() { if (m_FixedImage.IsNotNull()) { AccessByItk(m_FixedImage, GetTransform2); return m_TransformObject; } return NULL; } mitk::TransformParameters::TransformType QmitkTranslationTransformView::GetTransformType() { return mitk::TransformParameters::TRANSLATIONTRANSFORM; } template < class TPixelType, unsigned int VImageDimension > itk::Object::Pointer QmitkTranslationTransformView::GetTransform2(itk::Image* /*itkImage1*/) { typedef typename itk::Image< TPixelType, VImageDimension > FixedImageType; typedef typename itk::Image< TPixelType, VImageDimension > MovingImageType; - typename itk::TranslationTransform< double, VImageDimension>::Pointer TransformPointer = itk::TranslationTransform< double, VImageDimension>::New(); - TransformPointer->SetIdentity(); - m_TransformObject = TransformPointer.GetPointer(); - return TransformPointer.GetPointer(); + typedef itk::AffineTransform TransformType; + typename TransformType::Pointer transform = TransformType::New(); + transform->SetIdentity(); + m_TransformObject = transform; + return transform.GetPointer(); } itk::Array QmitkTranslationTransformView::GetTransformParameters() { itk::Array transformValues; transformValues.SetSize(4); transformValues.fill(0); transformValues[0] = m_Controls.m_UseOptimizerScalesTranslation->isChecked(); transformValues[1] = m_Controls.m_ScalesTranslationTransformTranslationX->text().toDouble(); transformValues[2] = m_Controls.m_ScalesTranslationTransformTranslationY->text().toDouble(); transformValues[3] = m_Controls.m_ScalesTranslationTransformTranslationZ->text().toDouble(); return transformValues; } void QmitkTranslationTransformView::SetTransformParameters(itk::Array transformValues) { m_Controls.m_UseOptimizerScalesTranslation->setChecked(transformValues[0]); m_Controls.m_ScalesTranslationTransformTranslationX->setText(QString::number(transformValues[1])); m_Controls.m_ScalesTranslationTransformTranslationY->setText(QString::number(transformValues[2])); m_Controls.m_ScalesTranslationTransformTranslationZ->setText(QString::number(transformValues[3])); } QString QmitkTranslationTransformView::GetName() { return "Translation"; } void QmitkTranslationTransformView::SetupUI(QWidget* parent) { m_Controls.setupUi(parent); QValidator* validatorLineEditInputFloat = new QDoubleValidator(0, 20000000, 8, this); m_Controls.m_ScalesTranslationTransformTranslationX->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesTranslationTransformTranslationY->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesTranslationTransformTranslationZ->setValidator(validatorLineEditInputFloat); } itk::Array QmitkTranslationTransformView::GetScales() { itk::Array scales; scales.SetSize(3); scales.Fill(1.0); if (m_Controls.m_UseOptimizerScalesTranslation->isChecked()) { scales[0] = m_Controls.m_ScalesTranslationTransformTranslationX->text().toDouble(); scales[1] = m_Controls.m_ScalesTranslationTransformTranslationY->text().toDouble(); scales[2] = m_Controls.m_ScalesTranslationTransformTranslationZ->text().toDouble(); } return scales; } vtkTransform* QmitkTranslationTransformView::Transform(vtkMatrix4x4* /*vtkmatrix*/, vtkTransform* vtktransform, itk::Array transformParams) { if (m_MovingImage.IsNotNull()) { if (transformParams.size() == 2) { vtktransform->Translate(transformParams[0], transformParams[1], 0); } else if (transformParams.size() == 3) { vtktransform->Translate(transformParams[0], transformParams[1], transformParams[2]); std::cout<<"Translation is: "<GetDimension() == 2) { m_Controls.m_ScalesTranslationTransformTranslationZ->hide(); m_Controls.textLabel4_4_2->hide(); return 2; } else { m_Controls.m_ScalesTranslationTransformTranslationZ->show(); m_Controls.textLabel4_4_2->show(); return 3; } } else return 0; } diff --git a/Modules/Segmentation/Algorithms/mitkShowSegmentationAsSurface.cpp b/Modules/Segmentation/Algorithms/mitkShowSegmentationAsSurface.cpp index 2768e31b05..6f645835fc 100644 --- a/Modules/Segmentation/Algorithms/mitkShowSegmentationAsSurface.cpp +++ b/Modules/Segmentation/Algorithms/mitkShowSegmentationAsSurface.cpp @@ -1,234 +1,233 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkShowSegmentationAsSurface.h" #include "mitkManualSegmentationToSurfaceFilter.h" -#include "mitkDataNodeFactory.h" #include "mitkVtkRepresentationProperty.h" #include #include namespace mitk { ShowSegmentationAsSurface::ShowSegmentationAsSurface() :m_UIDGeneratorSurfaces("Surface_"), m_AddToTree(false) { } ShowSegmentationAsSurface::~ShowSegmentationAsSurface() { } void ShowSegmentationAsSurface::Initialize(const NonBlockingAlgorithm* other) { Superclass::Initialize(other); bool syncVisibility(false); if (other) { other->GetParameter("Sync visibility", syncVisibility); } SetParameter("Sync visibility", syncVisibility ); SetParameter("Median kernel size", 3u); SetParameter("Apply median", true ); SetParameter("Smooth", true ); SetParameter("Gaussian SD", 1.5f ); SetParameter("Decimate mesh", true ); SetParameter("Decimation rate", 0.8f ); SetParameter("Wireframe", false ); } bool ShowSegmentationAsSurface::ReadyToRun() { try { Image::Pointer image; GetPointerParameter("Input", image); return image.IsNotNull() && GetGroupNode(); } catch (std::invalid_argument&) { return false; } } bool ShowSegmentationAsSurface::ThreadedUpdateFunction() { Image::Pointer image; GetPointerParameter("Input", image); bool smooth(true); GetParameter("Smooth", smooth); bool applyMedian(true); GetParameter("Apply median", applyMedian); bool decimateMesh(true); GetParameter("Decimate mesh", decimateMesh); unsigned int medianKernelSize(3); GetParameter("Median kernel size", medianKernelSize); float gaussianSD(1.5); GetParameter("Gaussian SD", gaussianSD ); float reductionRate(0.8); GetParameter("Decimation rate", reductionRate ); MITK_INFO << "Creating polygon model with smoothing " << smooth << " gaussianSD " << gaussianSD << " median " << applyMedian << " median kernel " << medianKernelSize << " mesh reduction " << decimateMesh << " reductionRate " << reductionRate; ManualSegmentationToSurfaceFilter::Pointer surfaceFilter = ManualSegmentationToSurfaceFilter::New(); surfaceFilter->SetInput( image ); surfaceFilter->SetThreshold( 0.5 ); //expects binary image with zeros and ones surfaceFilter->SetUseGaussianImageSmooth(smooth); // apply gaussian to thresholded image ? surfaceFilter->SetSmooth(smooth); if (smooth) { surfaceFilter->InterpolationOn(); surfaceFilter->SetGaussianStandardDeviation( gaussianSD ); } surfaceFilter->SetMedianFilter3D(applyMedian); // apply median to segmentation before marching cubes ? if (applyMedian) { surfaceFilter->SetMedianKernelSize(medianKernelSize, medianKernelSize, medianKernelSize); // apply median to segmentation before marching cubes } //fix to avoid vtk warnings see bug #5390 if ( image->GetDimension() > 3 ) decimateMesh = false; if (decimateMesh) { surfaceFilter->SetDecimate( ImageToSurfaceFilter::QuadricDecimation ); surfaceFilter->SetTargetReduction( reductionRate ); } else { surfaceFilter->SetDecimate( ImageToSurfaceFilter::NoDecimation ); } surfaceFilter->UpdateLargestPossibleRegion(); // calculate normals for nicer display m_Surface = surfaceFilter->GetOutput(); vtkPolyData* polyData = m_Surface->GetVtkPolyData(); if (!polyData) throw std::logic_error("Could not create polygon model"); polyData->SetVerts(0); polyData->SetLines(0); if ( smooth || applyMedian || decimateMesh) { vtkPolyDataNormals* normalsGen = vtkPolyDataNormals::New(); normalsGen->SetInputData( polyData ); normalsGen->Update(); m_Surface->SetVtkPolyData( normalsGen->GetOutput() ); normalsGen->Delete(); } else { m_Surface->SetVtkPolyData( polyData ); } return true; } void ShowSegmentationAsSurface::ThreadedUpdateSuccessful() { m_Node = DataNode::New(); bool wireframe(false); GetParameter("Wireframe", wireframe ); if (wireframe) { VtkRepresentationProperty *np = dynamic_cast(m_Node->GetProperty("material.representation")); if (np) np->SetRepresentationToWireframe(); } m_Node->SetProperty("opacity", FloatProperty::New(0.3) ); m_Node->SetProperty("line width", IntProperty::New(1) ); m_Node->SetProperty("scalar visibility", BoolProperty::New(false) ); std::string groupNodesName ("surface"); DataNode* groupNode = GetGroupNode(); if (groupNode) { groupNode->GetName( groupNodesName ); //if parameter smooth is set add extension to node name bool smooth(true); GetParameter("Smooth", smooth); if(smooth) groupNodesName.append("_smoothed"); } m_Node->SetProperty( "name", StringProperty::New(groupNodesName) ); // synchronize this object's color with the parent's color //surfaceNode->SetProperty( "color", parentNode->GetProperty( "color" ) ); //surfaceNode->SetProperty( "visible", parentNode->GetProperty( "visible" ) ); m_Node->SetData( m_Surface ); BaseProperty* colorProp = groupNode->GetProperty("color"); if (colorProp) m_Node->ReplaceProperty("color", colorProp->Clone()); else m_Node->SetProperty("color", ColorProperty::New(1.0, 1.0, 0.0)); bool showResult(true); GetParameter("Show result", showResult ); bool syncVisibility(false); GetParameter("Sync visibility", syncVisibility ); Image::Pointer image; GetPointerParameter("Input", image); BaseProperty* organTypeProp = image->GetProperty("organ type"); if (organTypeProp) m_Surface->SetProperty("organ type", organTypeProp); BaseProperty* visibleProp = groupNode->GetProperty("visible"); if (visibleProp && syncVisibility) m_Node->ReplaceProperty("visible", visibleProp->Clone()); else m_Node->SetProperty("visible", BoolProperty::New(showResult)); InsertBelowGroupNode(m_Node); Superclass::ThreadedUpdateSuccessful(); } } // namespace diff --git a/Modules/Segmentation/Interactions/mitkExtrudedContourInteractor.cpp b/Modules/Segmentation/Interactions/mitkExtrudedContourInteractor.cpp index ee7cf45a26..111cc1f5e2 100644 --- a/Modules/Segmentation/Interactions/mitkExtrudedContourInteractor.cpp +++ b/Modules/Segmentation/Interactions/mitkExtrudedContourInteractor.cpp @@ -1,201 +1,200 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkExtrudedContourInteractor.h" #include #include #include #include #include #include #include #include #include #include #include #include -#include #include #include #include mitk::ExtrudedContourInteractor::ExtrudedContourInteractor(const char * type, mitk::DataNode* dataNode) : mitk::Interactor(type, dataNode), m_Started(false) { assert(m_DataNode != NULL); m_DataNode->SetProperty( "material.representation", mitk::VtkRepresentationProperty::New("surface") ); m_Contour = mitk::Contour::New(); m_ContourNode = mitk::DataNode::New(); m_ContourNode->SetData(m_Contour); m_ContourNode->SetProperty("layer", mitk::IntProperty::New(100) ); m_ContourNode->SetProperty("name", mitk::StringProperty::New("InteractiveFeedbackData") ); m_ContourNode->SetOpacity(1); m_ContourNode->SetColor(0.4,0.9,0.0); m_ContourNode->SetProperty( "Width", mitk::FloatProperty::New(2.0) ); m_Started = false; } mitk::ExtrudedContourInteractor::~ExtrudedContourInteractor() { } //mitk::Contour::Pointer ExtrudedContourInteractor::ExtractContour(mitkIpPicDescriptor* pic) //{ // int idx; // int size = _mitkIpPicElements (pic); // for (idx = 0; idx < size; idx++) // if ( ((mitkIpUInt1_t*) pic->data)[idx]> 0) break; // // int sizePoints; // size of the _points buffer (number of coordinate pairs that fit in) // int numPoints; // number of coordinate pairs stored in _points buffer // float *points = 0; // // points = ipSegmentationGetContour8N( pic, idx, numPoints, sizePoints, points ); // // mitk::Contour::Pointer m_Contour = mitk::Contour::New(); // m_Contour->Initialize(); // mitk::Point3D pointInMM, pointInUnits; // mitk::Point3D itkPoint; // for (int pointIdx = 0; pointIdx < numPoints; pointIdx++) // { // pointInUnits[0] = points[2*pointIdx]; // pointInUnits[1] = points[2*pointIdx+1]; // pointInUnits[2] = m_ZCoord; // m_SelectedImageGeometry->IndexToWorld(CorrectPointCoordinates(pointInUnits),pointInMM); // m_Contour->AddVertex(pointInMM); // } // return m_Contour; //} bool mitk::ExtrudedContourInteractor::ExecuteAction(mitk::Action* action, mitk::StateEvent const* stateEvent) { mitk::Point3D eventPoint; mitk::Vector3D eventPlaneNormal; const mitk::PositionEvent* posEvent = dynamic_cast(stateEvent->GetEvent()); if(posEvent==NULL) { const mitk::DisplayPositionEvent* displayPosEvent = dynamic_cast(stateEvent->GetEvent()); mitk::VtkPropRenderer* sender = (mitk::VtkPropRenderer*) stateEvent->GetEvent()->GetSender(); if((displayPosEvent == NULL) || (sender == NULL)) return false; eventPoint[0] = displayPosEvent->GetDisplayPosition()[0]; eventPoint[1] = displayPosEvent->GetDisplayPosition()[1]; eventPoint[2] = 0; typedef itk::Point DoublePoint3D; DoublePoint3D p; p.CastFrom(eventPoint); sender->GetVtkRenderer()->SetDisplayPoint(p.GetDataPointer()); sender->GetVtkRenderer()->DisplayToWorld(); double *vtkwp = sender->GetVtkRenderer()->GetWorldPoint(); vtk2itk(vtkwp, eventPoint); double *vtkvpn = sender->GetVtkRenderer()->GetActiveCamera()->GetViewPlaneNormal(); vtk2itk(vtkvpn, eventPlaneNormal); eventPlaneNormal = -eventPlaneNormal; } else { eventPoint = posEvent->GetWorldPosition(); mitk::BaseRenderer* sender = (mitk::BaseRenderer*) stateEvent->GetEvent()->GetSender(); eventPlaneNormal = sender->GetCurrentWorldPlaneGeometry()->GetAxisVector(2); } bool ok = false; switch (action->GetActionId()) { case mitk::AcNEWPOINT: { Press(eventPoint); ok = true; m_Started = true; break; } case mitk::AcINITMOVEMENT: { if (m_Started) { Move(eventPoint); ok = true; break; } } case mitk::AcMOVEPOINT: { if (m_Started) { Move(eventPoint); ok = true; break; } } case mitk::AcFINISHMOVEMENT: { if (m_Started) { mitk::ExtrudedContour* extrudedcontour = dynamic_cast(m_DataNode->GetData()); extrudedcontour->SetContour(m_Contour); extrudedcontour->SetVector(eventPlaneNormal); Release(eventPoint); ok = true; m_Started = false; InvokeEvent(itk::EndEvent()); } break; } default: ok = false; break; } return ok; } void mitk::ExtrudedContourInteractor::Press(mitk::Point3D& point) { if (!m_Positive) m_ContourNode->SetColor(1.0,0.0,0.0); m_Contour->Initialize(); m_Contour->AddVertex( point ); } void mitk::ExtrudedContourInteractor::Move(mitk::Point3D& point) { assert(m_Contour.IsNotNull()); m_Contour->AddVertex( point ); // m_Parent->UpdateWidgets(); } void mitk::ExtrudedContourInteractor::Release(mitk::Point3D& /*point*/) { //vermutlich m_Parent->UpdateWidgets(); } diff --git a/Modules/Segmentation/Interactions/mitkTool.cpp b/Modules/Segmentation/Interactions/mitkTool.cpp index 5ddee30199..51cb0f5803 100644 --- a/Modules/Segmentation/Interactions/mitkTool.cpp +++ b/Modules/Segmentation/Interactions/mitkTool.cpp @@ -1,256 +1,255 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTool.h" -#include "mitkDataNodeFactory.h" #include "mitkProperties.h" #include "mitkImageWriteAccessor.h" #include "mitkLevelWindowProperty.h" #include "mitkVtkResliceInterpolationProperty.h" #include "mitkImageReadAccessor.h" // us #include #include #include mitk::Tool::Tool(const char* type) : m_PredicateImages(NodePredicateDataType::New("Image")) // for reference images , m_PredicateDim3(NodePredicateDimension::New(3, 1)) , m_PredicateDim4(NodePredicateDimension::New(4, 1)) , m_PredicateDimension( mitk::NodePredicateOr::New(m_PredicateDim3, m_PredicateDim4) ) , m_PredicateImage3D( NodePredicateAnd::New(m_PredicateImages, m_PredicateDimension) ) , m_PredicateBinary(NodePredicateProperty::New("binary", BoolProperty::New(true))) , m_PredicateNotBinary( NodePredicateNot::New(m_PredicateBinary) ) , m_PredicateSegmentation(NodePredicateProperty::New("segmentation", BoolProperty::New(true))) , m_PredicateNotSegmentation( NodePredicateNot::New(m_PredicateSegmentation) ) , m_PredicateHelper(NodePredicateProperty::New("helper object", BoolProperty::New(true))) , m_PredicateNotHelper( NodePredicateNot::New(m_PredicateHelper) ) , m_PredicateImageColorful( NodePredicateAnd::New(m_PredicateNotBinary, m_PredicateNotSegmentation) ) , m_PredicateImageColorfulNotHelper( NodePredicateAnd::New(m_PredicateImageColorful, m_PredicateNotHelper) ) , m_PredicateReference( NodePredicateAnd::New(m_PredicateImage3D, m_PredicateImageColorfulNotHelper) ) , m_IsSegmentationPredicate(NodePredicateAnd::New(NodePredicateOr::New(m_PredicateBinary, m_PredicateSegmentation), m_PredicateNotHelper)) , m_InteractorType( type ) { } mitk::Tool::~Tool() { } bool mitk::Tool::CanHandle(BaseData* referenceData) const { return true; } void mitk::Tool::InitializeStateMachine() { if (m_InteractorType.empty()) return; m_InteractorType += ".xml"; try { LoadStateMachine( m_InteractorType, us::GetModuleContext()->GetModule() ); SetEventConfig( "SegmentationToolsConfig.xml", us::GetModuleContext()->GetModule() ); } catch( const std::exception& e ) { MITK_ERROR << "Could not load statemachine pattern " << m_InteractorType << " with exception: " << e.what(); } } void mitk::Tool::Notify( InteractionEvent* interactionEvent, bool isHandled ) { // to use the state machine pattern, // the event is passed to the state machine interface to be handled if ( !isHandled ) { this->HandleEvent(interactionEvent, NULL); } } void mitk::Tool::ConnectActionsAndFunctions() { } bool mitk::Tool::FilterEvents(InteractionEvent* , DataNode* ) { return true; } const char* mitk::Tool::GetGroup() const { return "default"; } void mitk::Tool::SetToolManager(ToolManager* manager) { m_ToolManager = manager; } void mitk::Tool::Activated() { } void mitk::Tool::Deactivated() { // ToDo: reactivate this feature! //StateMachine::ResetStatemachineToStartState(); // forget about the past } itk::Object::Pointer mitk::Tool::GetGUI(const std::string& toolkitPrefix, const std::string& toolkitPostfix) { itk::Object::Pointer object; std::string classname = this->GetNameOfClass(); std::string guiClassname = toolkitPrefix + classname + toolkitPostfix; std::list allGUIs = itk::ObjectFactoryBase::CreateAllInstance(guiClassname.c_str()); for( std::list::iterator iter = allGUIs.begin(); iter != allGUIs.end(); ++iter ) { if (object.IsNull()) { object = dynamic_cast( iter->GetPointer() ); } else { MITK_ERROR << "There is more than one GUI for " << classname << " (several factories claim ability to produce a " << guiClassname << " ) " << std::endl; return NULL; // people should see and fix this error } } return object; } mitk::NodePredicateBase::ConstPointer mitk::Tool::GetReferenceDataPreference() const { return m_PredicateReference.GetPointer(); } mitk::NodePredicateBase::ConstPointer mitk::Tool::GetWorkingDataPreference() const { return m_IsSegmentationPredicate.GetPointer(); } mitk::DataNode::Pointer mitk::Tool::CreateEmptySegmentationNode( Image* original, const std::string& organName, const mitk::Color& color ) { // we NEED a reference image for size etc. if (!original) return NULL; // actually create a new empty segmentation PixelType pixelType(mitk::MakeScalarPixelType() ); Image::Pointer segmentation = Image::New(); if (original->GetDimension() == 2) { const unsigned int dimensions[] = { original->GetDimension(0), original->GetDimension(1), 1 }; segmentation->Initialize(pixelType, 3, dimensions); } else { segmentation->Initialize(pixelType, original->GetDimension(), original->GetDimensions()); } unsigned int byteSize = sizeof(DefaultSegmentationDataType); if(segmentation->GetDimension() < 4) { for (unsigned int dim = 0; dim < segmentation->GetDimension(); ++dim) { byteSize *= segmentation->GetDimension(dim); } mitk::ImageWriteAccessor writeAccess(segmentation, segmentation->GetVolumeData(0)); memset( writeAccess.GetData(), 0, byteSize ); } else {//if we have a time-resolved image we need to set memory to 0 for each time step for (unsigned int dim = 0; dim < 3; ++dim) { byteSize *= segmentation->GetDimension(dim); } for( unsigned int volumeNumber = 0; volumeNumber < segmentation->GetDimension(3); volumeNumber++) { mitk::ImageWriteAccessor writeAccess(segmentation, segmentation->GetVolumeData(volumeNumber)); memset( writeAccess.GetData(), 0, byteSize ); } } if (original->GetTimeGeometry() ) { TimeGeometry::Pointer originalGeometry = original->GetTimeGeometry()->Clone(); segmentation->SetTimeGeometry( originalGeometry ); } else { Tool::ErrorMessage("Original image does not have a 'Time sliced geometry'! Cannot create a segmentation."); return NULL; } return CreateSegmentationNode( segmentation, organName, color ); } mitk::DataNode::Pointer mitk::Tool::CreateSegmentationNode( Image* image, const std::string& organName, const mitk::Color& color ) { if (!image) return NULL; // decorate the datatreenode with some properties DataNode::Pointer segmentationNode = DataNode::New(); segmentationNode->SetData( image ); // name segmentationNode->SetProperty( "name", StringProperty::New( organName ) ); // visualization properties segmentationNode->SetProperty( "binary", BoolProperty::New(true) ); segmentationNode->SetProperty( "color", ColorProperty::New(color) ); segmentationNode->SetProperty( "texture interpolation", BoolProperty::New(false) ); segmentationNode->SetProperty( "layer", IntProperty::New(10) ); segmentationNode->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow(0.5, 1) ) ); segmentationNode->SetProperty( "opacity", FloatProperty::New(0.3) ); segmentationNode->SetProperty( "segmentation", BoolProperty::New(true) ); segmentationNode->SetProperty( "reslice interpolation", VtkResliceInterpolationProperty::New() ); // otherwise -> segmentation appears in 2 slices sometimes (only visual effect, not different data) // For MITK-3M3 release, the volume of all segmentations should be shown segmentationNode->SetProperty( "showVolume", BoolProperty::New( true ) ); return segmentationNode; } us::ModuleResource mitk::Tool::GetIconResource() const { // Each specific tool should load its own resource. This one will be invalid return us::ModuleResource(); } us::ModuleResource mitk::Tool::GetCursorIconResource() const { // Each specific tool should load its own resource. This one will be invalid return us::ModuleResource(); } diff --git a/Modules/Segmentation/Testing/files.cmake b/Modules/Segmentation/Testing/files.cmake index cee738df69..b7d0da917d 100644 --- a/Modules/Segmentation/Testing/files.cmake +++ b/Modules/Segmentation/Testing/files.cmake @@ -1,34 +1,34 @@ set(MODULE_TESTS mitkContourMapper2DTest.cpp mitkContourTest.cpp mitkContourModelSetToImageFilterTest.cpp mitkDataNodeSegmentationTest.cpp mitkImageToContourFilterTest.cpp # mitkSegmentationInterpolationTest.cpp mitkOverwriteSliceFilterTest.cpp mitkOverwriteSliceFilterObliquePlaneTest.cpp # mitkToolManagerTest.cpp mitkToolManagerProviderTest.cpp + mitkManualSegmentationToSurfaceFilterTest.cpp #new cpp unit style ) if(MITK_ENABLE_RENDERING_TESTING) #since mitkInteractionTestHelper is currently creating a vtkRenderWindow set(MODULE_TESTS ${MODULE_TESTS} mitkToolInteractionTest.cpp ) endif() set(MODULE_IMAGE_TESTS - mitkManualSegmentationToSurfaceFilterTest.cpp #only runs on images mitkOverwriteSliceImageFilterTest.cpp #only runs on images ) set(MODULE_CUSTOM_TESTS ) set(MODULE_TESTIMAGES US4DCyl.nrrd Pic3D.nrrd Pic2DplusT.nrrd BallBinary30x30x30.nrrd Png2D-bw.png ) diff --git a/Modules/Segmentation/Testing/mitkManualSegmentationToSurfaceFilterTest.cpp b/Modules/Segmentation/Testing/mitkManualSegmentationToSurfaceFilterTest.cpp index 7d6de1d0e2..b3f359e422 100644 --- a/Modules/Segmentation/Testing/mitkManualSegmentationToSurfaceFilterTest.cpp +++ b/Modules/Segmentation/Testing/mitkManualSegmentationToSurfaceFilterTest.cpp @@ -1,178 +1,93 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ +#include +#include +#include +#include +#include -#include "mitkManualSegmentationToSurfaceFilter.h" -#include -#include "mitkDataNodeFactory.h" -#include -#include - -#include -/** -* Test class for ManualSegmentationToSurfaceFilter and ImageToSurface -* 1. Read an image -* 2. Create a surface -* 3. Create a Surface with all image processing facillities -*/ -int mitkManualSegmentationToSurfaceFilterTest(int argc, char* argv[]) +class mitkManualSegmentationToSurfaceFilterTestSuite : public mitk::TestFixture { - - if(argc==0) - { - std::cout<<"no file specified [FAILED]"<SetFileName( fileIn.c_str() ); - factory->Update(); - - if(factory->GetNumberOfOutputs()<1) + std::vector parameter = GetTestParameter(); + m_Filter = mitk::ManualSegmentationToSurfaceFilter::New(); + if(parameter.size() == 2) { - std::cout<<"file could not be loaded [FAILED]"<SetInput(mitk::IOUtil::LoadImage(GetTestDataFilePath(parameter.at(0)))); + //For the tests which have reference data + m_ReferenceSurface = mitk::IOUtil::LoadSurface(GetTestDataFilePath(parameter.at(1))); } - mitk::DataNode::Pointer node = factory->GetOutput( 0 ); - image = dynamic_cast(node->GetData()); - if(image.IsNull()) + else { - std::cout<<"file not an image - test will not be applied [PASSED]"<::Pointer writer = mitk::SurfaceVtkWriter::New(); - if (filter.IsNull()) + void Update_BallBinary_OutputEqualsReference() { - std::cout<<"Instantiat SurfaceVtkWirter: [FAILED]"<GlobalWarningDisplayOn(); - writer->SetFileName(fileOut.c_str()); - writer->GetVtkWriter()->SetFileTypeToBinary(); - + m_Filter->Update(); + mitk::Surface::Pointer computedOutput = m_Filter->GetOutput(); + MITK_ASSERT_EQUAL(computedOutput, m_ReferenceSurface, "Computed equals the reference?"); } - std::cout << "Create surface with default settings: "; - if (image->GetDimension()==3) - { - filter->SetInput(image); - filter->Update(); - writer->SetInput(filter->GetOutput()); - writer->Write(); - - if( writer->GetNumberOfInputs() < 1 ) - { - std::cout<<"[FAILED]"<Delete(); - return EXIT_FAILURE; - } - else - { - std::cout<<"[PASSED]"<MedianFilter3DOn(); - filter->SetGaussianStandardDeviation(1.5); - filter->InterpolationOn(); - filter->UseGaussianImageSmoothOn(); - filter->SetThreshold( 1 ); //if( Gauss ) --> TH manipulated for vtkMarchingCube - filter->SetDecimate( mitk::ImageToSurfaceFilter::DecimatePro ); - filter->SetTargetReduction(0.05f); - filter->SmoothOn(); - - try - { - filter->Update(); - } - catch( itk::ExceptionObject & err ) - { - MITK_INFO << " ERROR!" << std::endl; - MITK_ERROR << "ExceptionObject caught!" << std::endl; - MITK_ERROR << err << std::endl; - return EXIT_FAILURE; - } - - writer->SetInput( filter->GetOutput() ); - if( writer->GetNumberOfInputs() < 1 ) - { - std::cout<<"[FAILED]"<Write(); - } - catch( itk::ExceptionObject e) - { - std::cout<<"caught exception: "<MedianFilter3DOn(); + m_Filter->SetGaussianStandardDeviation(1.5); + m_Filter->InterpolationOn(); + m_Filter->UseGaussianImageSmoothOn(); + m_Filter->SetThreshold( 1 ); + m_Filter->SetDecimate( mitk::ImageToSurfaceFilter::DecimatePro ); + m_Filter->SetTargetReduction(0.05f); + m_Filter->SmoothOn(); + m_Filter->Update(); + mitk::Surface::Pointer computedOutput = m_Filter->GetOutput(); + + MITK_ASSERT_EQUAL(computedOutput, m_ReferenceSurface, "Computed equals the reference?"); } - - std::cout<<"[TEST DONE]"<Delete(); - - return EXIT_SUCCESS; -} - - +}; +MITK_TEST_SUITE_REGISTRATION(mitkManualSegmentationToSurfaceFilter) diff --git a/Modules/Segmentation/Testing/mitkOverwriteSliceImageFilterTest.cpp b/Modules/Segmentation/Testing/mitkOverwriteSliceImageFilterTest.cpp index ed57b4964f..3f8846d71a 100644 --- a/Modules/Segmentation/Testing/mitkOverwriteSliceImageFilterTest.cpp +++ b/Modules/Segmentation/Testing/mitkOverwriteSliceImageFilterTest.cpp @@ -1,394 +1,386 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkExtractImageFilter.h" #include "mitkOverwriteSliceImageFilter.h" #include "mitkCoreObjectFactory.h" -#include "mitkDataNodeFactory.h" #include "mitkCompareImageSliceTestHelper.h" +#include + unsigned int CompareImageSliceTestHelper::m_Dimension0 = 0; unsigned int CompareImageSliceTestHelper::m_Dimension1 = 0; unsigned int CompareImageSliceTestHelper::m_SliceDimension = 0; unsigned int CompareImageSliceTestHelper::m_SliceIndex = 0; bool CompareImageSliceTestHelper::m_ComparisonResult = false; mitk::Image* CompareImageSliceTestHelper::m_SliceImage = NULL; class mitkOverwriteSliceImageFilterTestClass { public: static void Test3D( mitk::OverwriteSliceImageFilter* filter, mitk::Image* image, unsigned int& numberFailed ) { assert(filter); assert(image); filter->SetInput( image ); unsigned int initialNumberFailed = numberFailed; bool exception = false; // first extract slices and rewrite them for ( unsigned int sliceDimension = 0; sliceDimension < 3; ++sliceDimension ) { mitk::ExtractImageFilter::Pointer extractor = mitk::ExtractImageFilter::New(); extractor->SetInput( image ); extractor->SetSliceDimension( sliceDimension ); extractor->SetSliceIndex( 2 ); // third slice in that direction try { extractor->Update(); } catch(...) { if ( sliceDimension < 3 ) { // probably no sliceindex 2 there or extractor just doesn't work (check the corresponding test) std::cout << " (WW) Couldn't extract slice number 3 from a 3D image. This could be a problem if the image is not only two slices big." << std::endl; continue; } else { continue; // good } } mitk::Image::Pointer slice = extractor->GetOutput()->Clone(); filter->SetSliceDimension( sliceDimension ); filter->SetSliceIndex( 1 ); // second slice in that direction filter->SetSliceImage( slice ); try { filter->Update(); // try to overwrite } catch(...) { if ( sliceDimension < 3 ) { ++numberFailed; std::cerr << " (EE) Couln't overwrite a slice with data from a neigbor in a " << image->GetDimension() << "-dimensional image, sliceDimension " << sliceDimension << " sliceIndex 1-2." << "(l. " << __LINE__ << ")" << std::endl; } else { // this was expected and is nice to see continue; } } mitk::Image::Pointer output = filter->GetOutput(); if (output.IsNull()) { ++numberFailed; std::cerr << " (EE) Overwrite filter has output NULL and gave no exception for an " << image->GetDimension() << "-dimensional image, sliceDimension " << sliceDimension << " sliceIndex 1-2." << "(l. " << __LINE__ << ")" << std::endl; continue; } if (!CompareImageSliceTestHelper::CompareSlice( image, sliceDimension , 1 , slice )) { ++numberFailed; std::cerr << " (EE) Overwriting a slice seemed to work, but the pixels are not correct for an " << image->GetDimension() << "-dimensional image, sliceDimension " << sliceDimension << " sliceIndex 1-2." << "(l. " << __LINE__ << ")" << std::endl; } // try inserting at a position outside the image filter->SetSliceDimension( sliceDimension ); filter->SetSliceIndex( image->GetDimension(sliceDimension) ); // last possible slice index + 1 filter->SetSliceImage( slice ); exception = false; try { filter->Update(); // try to overwrite } catch(...) { exception = true; } if (!exception) { ++numberFailed; std::cerr << " (EE) Inserting a slice outside the 3D volume did NOT throw an exception for an " << image->GetDimension() << "-dimensional image, sliceDimension " << sliceDimension << " sliceIndex 1-2." << "(l. " << __LINE__ << ")" << std::endl; } mitk::Image::Pointer originalSlice = slice; // now test slices that just don't fit (slice too big) { unsigned int dim[]={ slice->GetDimension(0) + 2, slice->GetDimension(1) + 2 }; slice = mitk::Image::New(); slice-> Initialize(mitk::MakeScalarPixelType() , 2, dim); unsigned int i; mitk::ImageWriteAccessor accessor(slice); signed int *p = (signed int*)accessor.GetData(); unsigned int size = dim[0]*dim[1]; for(i=0; iSetSliceImage( slice ); exception = false; try { filter->Update(); // try to overwrite } catch(...) { exception = true; } if (!exception) { ++numberFailed; std::cerr << " (EE) Trying to insert a slice of bad dimensions (larger) did NOT throw an exception in an " << image->GetDimension() << "-dimensional image, sliceDimension " << sliceDimension << " sliceIndex 1-2." << "(l. " << __LINE__ << ")" << std::endl; } } // now test slices that just don't fit (slice too small) { slice = originalSlice; if ( (slice->GetDimension(0) <3) || (slice->GetDimension(1) <3) ) continue; // not possible shrink the image much further unsigned int dim[]={ slice->GetDimension(0) - 2, slice->GetDimension(1) - 2 }; slice = mitk::Image::New(); slice-> Initialize(mitk::MakeScalarPixelType(), 2, dim); unsigned int i; mitk::ImageWriteAccessor accessor(slice); signed int *p = (signed int*)accessor.GetData(); unsigned int size = dim[0]*dim[1]; for(i=0; iSetSliceImage( slice ); exception = false; try { filter->Update(); // try to overwrite } catch(...) { exception = true; } if (!exception) { ++numberFailed; std::cerr << " (EE) Trying to insert a slice of bad dimensions (smaller) did NOT throw an exception in an " << image->GetDimension() << "-dimensional image, sliceDimension " << sliceDimension << " sliceIndex 1-2." << "(l. " << __LINE__ << ")" << std::endl; } } } if ( numberFailed == initialNumberFailed ) { std::cout << " (II) Overwriting works nicely (gives result, pixels are good) " << image->GetDimension() << "-dimensional image." << "(l. " << __LINE__ << ")" << std::endl; } } static void Test2D( mitk::OverwriteSliceImageFilter* filter, mitk::Image* image, unsigned int& numberFailed ) { assert(filter); assert(image); filter->SetInput( image ); filter->SetSliceImage( image ); bool exception = false; try { filter->Update(); } catch(...) { exception = true; } if (!exception) { std::cerr << " (EE) Using OverwriteImageFilter for 2D -> 2D did not throw an exception " << "(l. " << __LINE__ << ")" << std::endl; } unsigned int initialNumberFailed = numberFailed; if ( numberFailed == initialNumberFailed ) { std::cout << " (II) Overwriting works nicely (gives result, pixels are good) " << image->GetDimension() << "-dimensional image." << "(l. " << __LINE__ << ")" << std::endl; } } static void TestOtherD( mitk::OverwriteSliceImageFilter* filter, mitk::Image* image, unsigned int& numberFailed ) { assert(filter); assert(image); filter->SetInput( image ); filter->SetSliceImage( image ); bool exception = false; try { filter->Update(); } catch(...) { exception = true; } if (!exception) { std::cerr << " (EE) Using OverwriteImageFilter did not throw an exception " << "(l. " << __LINE__ << ")" << std::endl; } unsigned int initialNumberFailed = numberFailed; if ( numberFailed == initialNumberFailed ) { std::cout << " (II) Overwriting works nicely (gives result, pixels are good) " << image->GetDimension() << "-dimensional image." << "(l. " << __LINE__ << ")" << std::endl; } } }; /// ctest entry point int mitkOverwriteSliceImageFilterTest(int argc, char* argv[]) { // one big variable to tell if anything went wrong unsigned int numberFailed(0); // need one parameter (image filename) if(argc==0) { std::cerr<<"No file specified [FAILED]"<SetFileName( argv[1] ); - factory->Update(); + MITK_INFO << "Testing with parameter '" << argv[1] << "'"; - if(factory->GetNumberOfOutputs()<1) - { - std::cerr<<"File could not be loaded [FAILED]"<GetOutput( 0 ); - image = dynamic_cast(node->GetData()); + std::string pathToImage(argv[1]); + image = mitk::IOUtil::LoadImage( pathToImage ); if(image.IsNull()) { - std::cout<<"File not an image - test will not be applied [PASSED]"<GetDimension() == 2 ) { mitkOverwriteSliceImageFilterTestClass::Test2D( filter, image, numberFailed ); } else if ( image->GetDimension() == 3 ) { mitkOverwriteSliceImageFilterTestClass::Test3D( filter, image, numberFailed ); } else { mitkOverwriteSliceImageFilterTestClass::TestOtherD( filter, image, numberFailed ); } std::cout << "Testing filter destruction" << std::endl; // freeing filter = NULL; std::cout << " (II) Freeing works." << std::endl; if (numberFailed > 0) { std::cerr << numberFailed << " tests failed." << std::endl; return EXIT_FAILURE; } else { std::cout << "PASSED all tests." << std::endl; return EXIT_SUCCESS; } } diff --git a/Modules/SegmentationUI/Qmitk/QmitkNewSegmentationDialog.cpp b/Modules/SegmentationUI/Qmitk/QmitkNewSegmentationDialog.cpp index b93cc4e567..92936281f2 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkNewSegmentationDialog.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkNewSegmentationDialog.cpp @@ -1,192 +1,190 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkNewSegmentationDialog.h" #include "mitkOrganTypeProperty.h" #include #include #include #include #include #include #include #include -#include - QmitkNewSegmentationDialog::QmitkNewSegmentationDialog(QWidget* parent) :QDialog(parent), // true, modal selectedOrgan("undefined"), newOrganEntry(false) { QDialog::setFixedSize(250, 105); QBoxLayout * verticalLayout = new QVBoxLayout( this ); verticalLayout->setMargin(5); verticalLayout->setSpacing(5); mitk::OrganTypeProperty::Pointer organTypes = mitk::OrganTypeProperty::New(); // to enter a name for the segmentation lblPrompt = new QLabel( "Name and color of the segmentation", this ); verticalLayout->addWidget( lblPrompt ); // to choose a color btnColor = new QPushButton( "", this ); btnColor->setFixedWidth(25); btnColor->setAutoFillBackground(true); btnColor->setStyleSheet("background-color:rgb(255,0,0)"); connect( btnColor, SIGNAL(clicked()), this, SLOT(onColorBtnClicked()) ); edtName = new QLineEdit( "", this ); QStringList completionList; completionList << ""; completer = new QCompleter(completionList); completer->setCaseSensitivity(Qt::CaseInsensitive); edtName->setCompleter(completer); connect( completer, SIGNAL(activated(const QString&)), this, SLOT(onColorChange(const QString&)) ); QBoxLayout * horizontalLayout2 = new QHBoxLayout(); verticalLayout->addLayout(horizontalLayout2); horizontalLayout2->addWidget( btnColor ); horizontalLayout2->addWidget( edtName ); //buttons for closing the dialog btnOk = new QPushButton( tr("Ok"), this ); btnOk->setDefault(true); connect( btnOk, SIGNAL(clicked()), this, SLOT(onAcceptClicked()) ); QPushButton* btnCancel = new QPushButton( tr("Cancel"), this ); connect( btnCancel, SIGNAL(clicked()), this, SLOT(reject()) ); QBoxLayout * horizontalLayout = new QHBoxLayout(); verticalLayout->addLayout(horizontalLayout); horizontalLayout->setSpacing(5); horizontalLayout->addStretch(); horizontalLayout->addWidget( btnOk ); horizontalLayout->addWidget( btnCancel ); edtName->setFocus(); } QmitkNewSegmentationDialog::~QmitkNewSegmentationDialog() { } void QmitkNewSegmentationDialog::onAcceptClicked() { m_SegmentationName = edtName->text(); this->accept(); } const QString QmitkNewSegmentationDialog::GetSegmentationName() { return m_SegmentationName; } const char* QmitkNewSegmentationDialog::GetOrganType() { return selectedOrgan.toLocal8Bit().constData(); } void QmitkNewSegmentationDialog::onNewOrganNameChanged(const QString& newText) { if (!newText.isEmpty()) { btnOk->setEnabled( true ); } selectedOrgan = newText; this->setSegmentationName( newText ); } void QmitkNewSegmentationDialog::onColorBtnClicked() { m_Color = QColorDialog::getColor(); if (m_Color.spec() == 0) { m_Color.setRed(255); m_Color.setGreen(0); m_Color.setBlue(0); } btnColor->setStyleSheet(QString("background-color:rgb(%1,%2, %3)").arg(m_Color.red()).arg(m_Color.green()).arg(m_Color.blue())); } void QmitkNewSegmentationDialog::setPrompt( const QString& prompt ) { lblPrompt->setText( prompt ); } void QmitkNewSegmentationDialog::setSegmentationName( const QString& name ) { edtName->setText( name ); m_SegmentationName = name; } mitk::Color QmitkNewSegmentationDialog::GetColor() { mitk::Color colorProperty; if (m_Color.spec() == 0) { colorProperty.SetRed(1); colorProperty.SetGreen(0); colorProperty.SetBlue(0); } else { colorProperty.SetRed(m_Color.redF()); colorProperty.SetGreen(m_Color.greenF()); colorProperty.SetBlue(m_Color.blueF()); } return colorProperty; } void QmitkNewSegmentationDialog::SetSuggestionList(QStringList organColorList) { QStringList::iterator iter; for (iter = organColorList.begin(); iter != organColorList.end(); ++iter) { QString& element = *iter; QString colorName = element.right(7); QColor color(colorName); QString organName = element.left(element.size() - 7); organList.push_back(organName); colorList.push_back(color); } QStringListModel* completeModel = static_cast (completer->model()); completeModel->setStringList(organList); } void QmitkNewSegmentationDialog::onColorChange(const QString& completedWord) { if (organList.contains(completedWord)) { int j = organList.indexOf(completedWord); m_Color = colorList.at(j); btnColor->setStyleSheet(QString("background-color:rgb(%1,%2, %3)").arg(m_Color.red()).arg(m_Color.green()).arg(m_Color.blue())); } } diff --git a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp index 2547550e39..7d2448eef5 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp @@ -1,1163 +1,1162 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "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 "mitkSliceNavigationController.h" #include #include #include #include #include #include #include #include #include #include #include //#define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a))) float SURFACE_COLOR_RGB [3] = {0.49f, 1.0f, 0.16f}; const std::map QmitkSlicesInterpolator::createActionToSliceDimension() { std::map actionToSliceDimension; foreach(mitk::SliceNavigationController* slicer, m_ControllerToDeleteObserverTag.keys()) { actionToSliceDimension[new QAction(QString::fromStdString(slicer->GetViewDirectionAsString()),0)] = slicer; } return actionToSliceDimension; } QmitkSlicesInterpolator::QmitkSlicesInterpolator(QWidget* parent, const char* /*name*/) :QWidget(parent), // ACTION_TO_SLICEDIMENSION( createActionToSliceDimension() ), m_Interpolator( mitk::SegmentationInterpolationController::New() ), m_SurfaceInterpolator(mitk::SurfaceInterpolationController::GetInstance()), m_ToolManager(NULL), m_Initialized(false), m_LastSNC(0), m_LastSliceIndex(0), m_2DInterpolationEnabled(false), m_3DInterpolationEnabled(false) { m_GroupBoxEnableExclusiveInterpolationMode = new QGroupBox("Interpolation", this); QVBoxLayout* vboxLayout = new QVBoxLayout(m_GroupBoxEnableExclusiveInterpolationMode); m_CmbInterpolation = new QComboBox(m_GroupBoxEnableExclusiveInterpolationMode); m_CmbInterpolation->addItem("Disabled"); m_CmbInterpolation->addItem("2-Dimensional"); m_CmbInterpolation->addItem("3-Dimensional"); vboxLayout->addWidget(m_CmbInterpolation); m_BtnApply2D = new QPushButton("Confirm for single slice", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_BtnApply2D); m_BtnApplyForAllSlices2D = new QPushButton("Confirm for all slices", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_BtnApplyForAllSlices2D); m_BtnApply3D = new QPushButton("Confirm", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_BtnApply3D); m_BtnReinit3DInterpolation = new QPushButton("Reinit Interpolation", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_BtnReinit3DInterpolation); m_ChkShowPositionNodes = new QCheckBox("Show Position Nodes", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_ChkShowPositionNodes); this->HideAllInterpolationControls(); connect(m_CmbInterpolation, SIGNAL(currentIndexChanged(int)), this, SLOT(OnInterpolationMethodChanged(int))); connect(m_BtnApply2D, SIGNAL(clicked()), this, SLOT(OnAcceptInterpolationClicked())); connect(m_BtnApplyForAllSlices2D, SIGNAL(clicked()), this, SLOT(OnAcceptAllInterpolationsClicked())); connect(m_BtnApply3D, SIGNAL(clicked()), this, SLOT(OnAccept3DInterpolationClicked())); connect(m_BtnReinit3DInterpolation, SIGNAL(clicked()), this, SLOT(OnReinit3DInterpolation())); connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SLOT(OnShowMarkers(bool))); connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SIGNAL(SignalShowMarkerNodes(bool))); QHBoxLayout* layout = new QHBoxLayout(this); 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(SURFACE_COLOR_RGB) ); m_InterpolatedSurfaceNode->SetProperty( "name", mitk::StringProperty::New("Surface Interpolation feedback") ); m_InterpolatedSurfaceNode->SetProperty( "opacity", mitk::FloatProperty::New(0.5) ); m_InterpolatedSurfaceNode->SetProperty( "line width", mitk::IntProperty::New(4) ); 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("hidden 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(OnSurfaceInterpolationFinished())); 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::Pointer 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, const QList &controllers) { Q_ASSERT(!controllers.empty()); if (m_Initialized) { // remove old observers Uninitialize(); } 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 slice navigation controller. after each change, call the interpolator foreach(mitk::SliceNavigationController* slicer, controllers) { //Has to be initialized m_LastSNC = slicer; m_TimeStep.insert(slicer, slicer->GetTime()->GetPos()); itk::MemberCommand::Pointer deleteCommand = itk::MemberCommand::New(); deleteCommand->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted); m_ControllerToDeleteObserverTag.insert(slicer, slicer->AddObserver(itk::DeleteEvent(), deleteCommand)); itk::MemberCommand::Pointer timeChangedCommand = itk::MemberCommand::New(); timeChangedCommand->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnTimeChanged); m_ControllerToTimeObserverTag.insert(slicer, slicer->AddObserver(mitk::SliceNavigationController::TimeGeometryEvent(NULL,0), timeChangedCommand)); itk::MemberCommand::Pointer sliceChangedCommand = itk::MemberCommand::New(); sliceChangedCommand->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSliceChanged); m_ControllerToSliceObserverTag.insert(slicer, slicer->AddObserver(mitk::SliceNavigationController::GeometrySliceEvent(NULL,0), sliceChangedCommand)); } ACTION_TO_SLICEDIMENSION = createActionToSliceDimension(); } m_Initialized = true; } void QmitkSlicesInterpolator::Uninitialize() { if (m_ToolManager.IsNotNull()) { m_ToolManager->WorkingDataChanged -= mitk::MessageDelegate(this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified); m_ToolManager->ReferenceDataChanged -= mitk::MessageDelegate(this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified); } foreach(mitk::SliceNavigationController* slicer, m_ControllerToSliceObserverTag.keys()) { slicer->RemoveObserver(m_ControllerToDeleteObserverTag.take(slicer)); slicer->RemoveObserver(m_ControllerToTimeObserverTag.take(slicer)); slicer->RemoveObserver(m_ControllerToSliceObserverTag.take(slicer)); } ACTION_TO_SLICEDIMENSION.clear(); m_ToolManager = NULL; m_Initialized = false; } QmitkSlicesInterpolator::~QmitkSlicesInterpolator() { if (m_Initialized) { // remove old observers Uninitialize(); } if(m_DataStorage->Exists(m_3DContourNode)) m_DataStorage->Remove(m_3DContourNode); if(m_DataStorage->Exists(m_InterpolatedSurfaceNode)) m_DataStorage->Remove(m_InterpolatedSurfaceNode); // remove observer m_Interpolator->RemoveObserver( InterpolationInfoChangedObserverTag ); m_SurfaceInterpolator->RemoveObserver( SurfaceInterpolationInfoChangedObserverTag ); delete m_Timer; } /** External enableization... */ void QmitkSlicesInterpolator::setEnabled( bool enable ) { QWidget::setEnabled(enable); //Set the gui elements of the different interpolation modi enabled if (enable) { if (m_2DInterpolationEnabled) { this->Show2DInterpolationControls(true); m_Interpolator->Activate2DInterpolation(true); } else if (m_3DInterpolationEnabled) { this->Show3DInterpolationControls(true); this->Show3DInterpolationResult(true); } } //Set all gui elements of the interpolation disabled else { this->HideAllInterpolationControls(); this->Show3DInterpolationResult(false); } } void QmitkSlicesInterpolator::On2DInterpolationEnabled(bool status) { OnInterpolationActivated(status); m_Interpolator->Activate2DInterpolation(status); } void QmitkSlicesInterpolator::On3DInterpolationEnabled(bool status) { On3DInterpolationActivated(status); } void QmitkSlicesInterpolator::OnInterpolationDisabled(bool status) { if (status) { OnInterpolationActivated(!status); On3DInterpolationActivated(!status); this->Show3DInterpolationResult(false); } } void QmitkSlicesInterpolator::HideAllInterpolationControls() { this->Show2DInterpolationControls(false); this->Show3DInterpolationControls(false); } void QmitkSlicesInterpolator::Show2DInterpolationControls(bool show) { m_BtnApply2D->setVisible(show); m_BtnApplyForAllSlices2D->setVisible(show); } void QmitkSlicesInterpolator::Show3DInterpolationControls(bool show) { m_BtnApply3D->setVisible(show); m_ChkShowPositionNodes->setVisible(show); m_BtnReinit3DInterpolation->setVisible(show); } void QmitkSlicesInterpolator::OnInterpolationMethodChanged(int index) { switch(index) { case 0: // Disabled m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation"); this->HideAllInterpolationControls(); this->OnInterpolationActivated(false); this->On3DInterpolationActivated(false); this->Show3DInterpolationResult(false); m_Interpolator->Activate2DInterpolation(false); break; case 1: // 2D m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)"); this->HideAllInterpolationControls(); this->Show2DInterpolationControls(true); this->OnInterpolationActivated(true); this->On3DInterpolationActivated(false); m_Interpolator->Activate2DInterpolation(true); break; case 2: // 3D m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)"); this->HideAllInterpolationControls(); this->Show3DInterpolationControls(true); this->OnInterpolationActivated(false); this->On3DInterpolationActivated(true); m_Interpolator->Activate2DInterpolation(false); break; default: MITK_ERROR << "Unknown interpolation method!"; m_CmbInterpolation->setCurrentIndex(0); break; } } 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_ToolManager->GetWorkingData(0) != 0) { m_Segmentation = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData()); m_BtnReinit3DInterpolation->setEnabled(true); } else { //If no workingdata is set, remove the interpolation feedback this->GetDataStorage()->Remove(m_FeedbackNode); m_FeedbackNode->SetData(NULL); this->GetDataStorage()->Remove(m_3DContourNode); m_3DContourNode->SetData(NULL); this->GetDataStorage()->Remove(m_InterpolatedSurfaceNode); m_InterpolatedSurfaceNode->SetData(NULL); m_BtnReinit3DInterpolation->setEnabled(false); return; } //Updating the current selected segmentation for the 3D interpolation SetCurrentContourListID(); if (m_2DInterpolationEnabled) { OnInterpolationActivated( true ); // re-initialize if needed } this->CheckSupportedImageDimension(); } void QmitkSlicesInterpolator::OnToolManagerReferenceDataModified() { } void QmitkSlicesInterpolator::OnTimeChanged(itk::Object* sender, const itk::EventObject& e) { //Check if we really have a GeometryTimeEvent if (!dynamic_cast(&e)) return; mitk::SliceNavigationController* slicer = dynamic_cast(sender); Q_ASSERT(slicer); m_TimeStep[slicer]; if (m_LastSNC == slicer) { slicer->SendSlice();//will trigger a new interpolation } } void QmitkSlicesInterpolator::OnSliceChanged(itk::Object *sender, const itk::EventObject &e) { //Check whether we really have a GeometrySliceEvent if (!dynamic_cast(&e)) return; mitk::SliceNavigationController* slicer = dynamic_cast(sender); if (TranslateAndInterpolateChangedSlice(e, slicer)) { slicer->GetRenderer()->RequestUpdate(); } } bool QmitkSlicesInterpolator::TranslateAndInterpolateChangedSlice(const itk::EventObject& e, mitk::SliceNavigationController* slicer) { if (!m_2DInterpolationEnabled) return false; try { const mitk::SliceNavigationController::GeometrySliceEvent& event = dynamic_cast(e); mitk::TimeGeometry* tsg = event.GetTimeGeometry(); if (tsg && m_TimeStep.contains(slicer)) { mitk::SlicedGeometry3D* slicedGeometry = dynamic_cast(tsg->GetGeometryForTimeStep(m_TimeStep[slicer]).GetPointer()); if (slicedGeometry) { m_LastSNC = slicer; mitk::PlaneGeometry* plane = dynamic_cast(slicedGeometry->GetPlaneGeometry( event.GetPos() )); if (plane) Interpolate( plane, m_TimeStep[slicer], slicer ); return true; } } } catch(std::bad_cast) { return false; // so what } return false; } void QmitkSlicesInterpolator::Interpolate( mitk::PlaneGeometry* plane, unsigned int timeStep, mitk::SliceNavigationController* slicer ) { 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, plane, timeStep ); m_FeedbackNode->SetData( interpolation ); m_LastSNC = slicer; m_LastSliceIndex = clickedSliceIndex; } } } } void QmitkSlicesInterpolator::OnSurfaceInterpolationFinished() { mitk::Surface::Pointer interpolatedSurface = m_SurfaceInterpolator->GetInterpolationResult(); mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); if(interpolatedSurface.IsNotNull() && workingNode && workingNode->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3")))) { m_BtnApply3D->setEnabled(true); m_InterpolatedSurfaceNode->SetData(interpolatedSurface); m_3DContourNode->SetData(m_SurfaceInterpolator->GetContoursAsSurface()); this->Show3DInterpolationResult(true); if( !m_DataStorage->Exists(m_InterpolatedSurfaceNode) ) { m_DataStorage->Add(m_InterpolatedSurfaceNode); } if (!m_DataStorage->Exists(m_3DContourNode)) { m_DataStorage->Add(m_3DContourNode, workingNode); } } else if (interpolatedSurface.IsNull()) { m_BtnApply3D->setEnabled(false); if (m_DataStorage->Exists(m_InterpolatedSurfaceNode)) { this->Show3DInterpolationResult(false); } } m_BtnReinit3DInterpolation->setEnabled(true); foreach (mitk::SliceNavigationController* slicer, m_ControllerToTimeObserverTag.keys()) { slicer->GetRenderer()->RequestUpdate(); } } void QmitkSlicesInterpolator::OnAcceptInterpolationClicked() { if (m_Segmentation && m_FeedbackNode->GetData()) { //making interpolation separately undoable mitk::UndoStackItem::IncCurrObjectEventId(); mitk::UndoStackItem::IncCurrGroupEventId(); mitk::UndoStackItem::ExecuteIncrement(); //Make sure that for reslicing and overwriting the same alogrithm is used. We can specify the mode of the vtk reslicer vtkSmartPointer reslice = vtkSmartPointer::New(); // Set slice as input mitk::Image::Pointer slice = dynamic_cast(m_FeedbackNode->GetData()); reslice->SetInputSlice(slice->GetSliceData()->GetVtkImageAccessor(slice)->GetVtkImageData()); //set overwrite mode to true to write back to the image volume reslice->SetOverwriteMode(true); reslice->Modified(); mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice); extractor->SetInput( m_Segmentation ); unsigned int timestep = m_LastSNC->GetTime()->GetPos(); extractor->SetTimeStep( timestep ); extractor->SetWorldGeometry( m_LastSNC->GetCurrentPlaneGeometry() ); extractor->SetVtkOutputRequest(true); extractor->SetResliceTransformByGeometry( m_Segmentation->GetTimeGeometry()->GetGeometryForTimeStep( timestep ) ); extractor->Modified(); extractor->Update(); //the image was modified within the pipeline, but not marked so m_Segmentation->Modified(); m_Segmentation->GetVtkImageData()->Modified(); m_FeedbackNode->SetData(NULL); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSlicesInterpolator::AcceptAllInterpolations(mitk::SliceNavigationController* slicer) { /* * What exactly is done here: * 1. We create an empty diff image for the current segmentation * 2. All interpolated slices are written into the diff image * 3. Then the diffimage is applied to the original segmentation */ if (m_Segmentation) { //making interpolation separately undoable mitk::UndoStackItem::IncCurrObjectEventId(); mitk::UndoStackItem::IncCurrGroupEventId(); mitk::UndoStackItem::ExecuteIncrement(); mitk::Image::Pointer image3D = m_Segmentation; unsigned int timeStep( slicer->GetTime()->GetPos() ); if (m_Segmentation->GetDimension() == 4) { mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New(); timeSelector->SetInput( m_Segmentation ); timeSelector->SetTimeNr( timeStep ); timeSelector->Update(); image3D = timeSelector->GetOutput(); } // create a empty diff image for the undo operation mitk::Image::Pointer diffImage = mitk::Image::New(); diffImage->Initialize( image3D ); // Create scope for ImageWriteAccessor so that the accessor is destroyed // after the image is initialized. Otherwise later image access will lead to an error { mitk::ImageWriteAccessor imAccess(diffImage); // Set all pixels to zero mitk::PixelType pixelType( mitk::MakeScalarPixelType() ); memset( imAccess.GetData(), 0, (pixelType.GetBpe() >> 3) * diffImage->GetDimension(0) * diffImage->GetDimension(1) * diffImage->GetDimension(2) ); } // Since we need to shift the plane it must be clone so that the original plane isn't altered mitk::PlaneGeometry::Pointer reslicePlane = slicer->GetCurrentPlaneGeometry()->Clone(); int sliceDimension(-1); int sliceIndex(-1); mitk::SegTool2D::DetermineAffectedImageSlice( m_Segmentation, reslicePlane, sliceDimension, sliceIndex ); unsigned int zslices = m_Segmentation->GetDimension( sliceDimension ); mitk::ProgressBar::GetInstance()->AddStepsToDo(zslices); mitk::Point3D origin = reslicePlane->GetOrigin(); unsigned int totalChangedSlices(0); for (unsigned int sliceIndex = 0; sliceIndex < zslices; ++sliceIndex) { // Transforming the current origin of the reslice plane // so that it matches the one of the next slice m_Segmentation->GetSlicedGeometry()->WorldToIndex(origin, origin); origin[sliceDimension] = sliceIndex; m_Segmentation->GetSlicedGeometry()->IndexToWorld(origin, origin); reslicePlane->SetOrigin(origin); //Set the slice as 'input' mitk::Image::Pointer interpolation = m_Interpolator->Interpolate( sliceDimension, sliceIndex, reslicePlane, timeStep ); if (interpolation.IsNotNull()) // we don't check if interpolation is necessary/sensible - but m_Interpolator does { //Setting up the reslicing pipeline which allows us to write the interpolation results back into //the image volume vtkSmartPointer reslice = vtkSmartPointer::New(); //set overwrite mode to true to write back to the image volume reslice->SetInputSlice(interpolation->GetSliceData()->GetVtkImageAccessor(interpolation)->GetVtkImageData()); reslice->SetOverwriteMode(true); reslice->Modified(); mitk::ExtractSliceFilter::Pointer diffslicewriter = mitk::ExtractSliceFilter::New(reslice); diffslicewriter->SetInput( diffImage ); diffslicewriter->SetTimeStep( timeStep ); diffslicewriter->SetWorldGeometry(reslicePlane); diffslicewriter->SetVtkOutputRequest(true); diffslicewriter->SetResliceTransformByGeometry( diffImage->GetTimeGeometry()->GetGeometryForTimeStep( timeStep ) ); diffslicewriter->Modified(); diffslicewriter->Update(); ++totalChangedSlices; } mitk::ProgressBar::GetInstance()->Progress(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); if (totalChangedSlices > 0) { // store undo stack items if ( true ) { // create do/undo operations 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 << "Confirm 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 to the original image mitk::DiffImageApplier::GetInstanceForUndo()->ExecuteOperation( doOp ); } } m_FeedbackNode->SetData(NULL); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSlicesInterpolator::FinishInterpolation(mitk::SliceNavigationController* slicer) { //this redirect is for calling from outside if (slicer == NULL) OnAcceptAllInterpolationsClicked(); else AcceptAllInterpolations( slicer ); } 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())); // check if ToolManager holds valid ReferenceData if (m_ToolManager->GetReferenceData(0) == NULL || m_ToolManager->GetWorkingData(0) == NULL) { return; } s2iFilter->SetImage(dynamic_cast(m_ToolManager->GetReferenceData(0)->GetData())); s2iFilter->Update(); mitk::DataNode* segmentationNode = m_ToolManager->GetWorkingData(0); mitk::Image* oldSeg = dynamic_cast(segmentationNode->GetData()); mitk::Image::Pointer newSeg = s2iFilter->GetOutput(); if (oldSeg) m_SurfaceInterpolator->ReplaceInterpolationSession(oldSeg, newSeg); else return; segmentationNode->SetData(newSeg); m_CmbInterpolation->setCurrentIndex(0); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); mitk::DataNode::Pointer segSurface = mitk::DataNode::New(); float rgb[3]; segmentationNode->GetColor(rgb); segSurface->SetColor(rgb); segSurface->SetData(m_InterpolatedSurfaceNode->GetData()); std::stringstream stream; stream << segmentationNode->GetName(); stream << "_"; stream << "3D-interpolation"; segSurface->SetName(stream.str()); segSurface->SetProperty( "opacity", mitk::FloatProperty::New(0.7) ); segSurface->SetProperty( "includeInBoundingBox", mitk::BoolProperty::New(true)); segSurface->SetProperty( "3DInterpolationResult", mitk::BoolProperty::New(true)); m_DataStorage->Add(segSurface, segmentationNode); this->Show3DInterpolationResult(false); } } void QmitkSlicesInterpolator::OnReinit3DInterpolation() { mitk::NodePredicateProperty::Pointer pred = mitk::NodePredicateProperty::New("3DContourContainer", mitk::BoolProperty::New(true)); mitk::DataStorage::SetOfObjects::ConstPointer contourNodes = m_DataStorage->GetDerivations( m_ToolManager->GetWorkingData(0), pred); if (contourNodes->Size() != 0) { m_3DContourNode = contourNodes->at(0); } else { QMessageBox errorInfo; errorInfo.setWindowTitle("Reinitialize surface interpolation"); errorInfo.setIcon(QMessageBox::Information); errorInfo.setText("No contours available for the selected segmentation!"); errorInfo.exec(); } mitk::Surface::Pointer contours = dynamic_cast(m_3DContourNode->GetData()); if (contours) mitk::SurfaceInterpolationController::GetInstance()->ReinitializeInterpolation(contours); m_BtnReinit3DInterpolation->setEnabled(false); } void QmitkSlicesInterpolator::OnAcceptAllPopupActivated(QAction* action) { try { std::map::const_iterator iter = ACTION_TO_SLICEDIMENSION.find( action ); if (iter != ACTION_TO_SLICEDIMENSION.end()) { mitk::SliceNavigationController* slicer = iter->second; AcceptAllInterpolations( slicer ); } } 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 ); } } } 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_BtnApply2D->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(SURFACE_COLOR_RGB)); mitk::RenderingManager::GetInstance()->RequestUpdate(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetRenderWindow()); } void QmitkSlicesInterpolator::ChangeSurfaceColor() { float currentColor[3]; m_InterpolatedSurfaceNode->GetColor(currentColor); if( currentColor[2] == SURFACE_COLOR_RGB[2]) { m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(1.0f,1.0f,1.0f)); } else { m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(SURFACE_COLOR_RGB)); } m_InterpolatedSurfaceNode->Update(); mitk::RenderingManager::GetInstance()->RequestUpdate(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetRenderWindow()); } void QmitkSlicesInterpolator::On3DInterpolationActivated(bool on) { m_3DInterpolationEnabled = on; this->CheckSupportedImageDimension(); try { if ( m_DataStorage.IsNotNull() && m_ToolManager && m_3DInterpolationEnabled) { mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); if (workingNode) { bool isInterpolationResult(false); workingNode->GetBoolProperty("3DInterpolationResult",isInterpolationResult); mitk::NodePredicateAnd::Pointer pred = mitk::NodePredicateAnd::New(mitk::NodePredicateProperty::New("3DInterpolationResult", mitk::BoolProperty::New(true)), mitk::NodePredicateDataType::New("Surface")); mitk::DataStorage::SetOfObjects::ConstPointer interpolationResults = m_DataStorage->GetDerivations(workingNode, pred); for (unsigned int i = 0; i < interpolationResults->Size(); ++i) { mitk::DataNode::Pointer currNode = interpolationResults->at(i); if (currNode.IsNotNull()) m_DataStorage->Remove(currNode); } if ((workingNode->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3")))) && !isInterpolationResult && m_3DInterpolationEnabled) { int ret = QMessageBox::Yes; if (m_SurfaceInterpolator->EstimatePortionOfNeededMemory() > 0.5) { QMessageBox msgBox; msgBox.setText("Due to short handed system memory the 3D interpolation may be very slow!"); msgBox.setInformativeText("Are you sure you want to activate the 3D interpolation?"); msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes); ret = msgBox.exec(); } if (m_Watcher.isRunning()) m_Watcher.waitForFinished(); if (ret == QMessageBox::Yes) { m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation); m_Watcher.setFuture(m_Future); } else { m_CmbInterpolation->setCurrentIndex(0); } } else if (!m_3DInterpolationEnabled) { this->Show3DInterpolationResult(false); m_BtnApply3D->setEnabled(m_3DInterpolationEnabled); } } else { QWidget::setEnabled( false ); m_ChkShowPositionNodes->setEnabled(m_3DInterpolationEnabled); } } if (!m_3DInterpolationEnabled) { this->Show3DInterpolationResult(false); m_BtnApply3D->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 && m_LastSNC) { // determine which one is the current view, try to do an initial interpolation mitk::BaseRenderer* renderer = m_LastSNC->GetRenderer(); if (renderer && renderer->GetMapperID() == mitk::BaseRenderer::Standard2D) { const mitk::TimeGeometry* timeGeometry = dynamic_cast( renderer->GetWorldGeometry() ); if (timeGeometry) { mitk::SliceNavigationController::GeometrySliceEvent event( const_cast(timeGeometry), renderer->GetSlice() ); TranslateAndInterpolateChangedSlice(event, m_LastSNC); } } } 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); } } void QmitkSlicesInterpolator:: SetCurrentContourListID() { // New ContourList = hide current interpolation Show3DInterpolationResult(false); if ( m_DataStorage.IsNotNull() && m_ToolManager && m_LastSNC ) { mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); if (workingNode) { bool isInterpolationResult(false); workingNode->GetBoolProperty("3DInterpolationResult",isInterpolationResult); if (!isInterpolationResult) { QWidget::setEnabled( true ); // In case the time is not valid use 0 to access the time geometry of the working node unsigned int time_position = 0; if( m_LastSNC->GetTime() != NULL ) time_position = m_LastSNC->GetTime()->GetPos(); mitk::Vector3D spacing = workingNode->GetData()->GetGeometry( time_position )->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->SetMaxSpacing(maxSpacing); m_SurfaceInterpolator->SetMinSpacing(minSpacing); m_SurfaceInterpolator->SetDistanceImageVolume(50000); mitk::Image* segmentationImage = dynamic_cast(workingNode->GetData()); if (segmentationImage->GetDimension() == 3) m_SurfaceInterpolator->SetCurrentInterpolationSession(segmentationImage); else MITK_INFO<<"3D Interpolation is only supported for 3D images at the moment!"; if (m_3DInterpolationEnabled) { if (m_Watcher.isRunning()) m_Watcher.waitForFinished(); m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation); m_Watcher.setFuture(m_Future); } } } else { QWidget::setEnabled(false); } } } void QmitkSlicesInterpolator::Show3DInterpolationResult(bool status) { if (m_InterpolatedSurfaceNode.IsNotNull()) m_InterpolatedSurfaceNode->SetVisibility(status); if (m_3DContourNode.IsNotNull()) m_3DContourNode->SetVisibility(status, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSlicesInterpolator::CheckSupportedImageDimension() { if (m_ToolManager->GetWorkingData(0)) m_Segmentation = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData()); if (m_3DInterpolationEnabled && m_Segmentation && m_Segmentation->GetDimension() != 3) { QMessageBox info; info.setWindowTitle("3D Interpolation Process"); info.setIcon(QMessageBox::Information); info.setText("3D Interpolation is only supported for 3D images at the moment!"); info.exec(); m_CmbInterpolation->setCurrentIndex(0); } } void QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted(const itk::Object *sender, const itk::EventObject& /*e*/) { //Don't know how to avoid const_cast here?! mitk::SliceNavigationController* slicer = dynamic_cast(const_cast(sender)); if (slicer) { m_ControllerToTimeObserverTag.remove(slicer); m_ControllerToSliceObserverTag.remove(slicer); m_ControllerToDeleteObserverTag.remove(slicer); } } diff --git a/Modules/Simulation/mitkExportMitkVisitor.cpp b/Modules/Simulation/mitkExportMitkVisitor.cpp index 4d9ef80592..c0645954c3 100644 --- a/Modules/Simulation/mitkExportMitkVisitor.cpp +++ b/Modules/Simulation/mitkExportMitkVisitor.cpp @@ -1,230 +1,230 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkExportMitkVisitor.h" #include #include #include #include #include #include #include #include #include -static void ApplyMaterial(mitk::DataNode::Pointer dataNode, const sofa::core::loader::Material& material) +void ApplyMaterial(mitk::DataNode::Pointer dataNode, const sofa::core::loader::Material& material) { using sofa::defaulttype::Vec4f; if (dataNode.IsNull() || dynamic_cast(dataNode->GetData()) == NULL) return; if (material.useDiffuse) dataNode->SetFloatProperty("opacity", material.diffuse[3]); Vec4f ambient = material.useAmbient ? material.ambient : Vec4f(); Vec4f diffuse = material.useDiffuse ? material.diffuse : Vec4f(); Vec4f specular = material.useSpecular ? material.specular : Vec4f(); float shininess = material.useShininess ? std::min(material.shininess, 128.0f) : 45.0f; if (shininess == 0.0f) { specular.clear(); shininess = 1.0f; } dataNode->SetFloatProperty("material.ambientCoefficient", 1.0f); - dataNode->SetProperty("material.ambientColor", mitk::ColorProperty::New(material.ambient.elems)); + dataNode->SetProperty("material.ambientColor", mitk::ColorProperty::New(ambient.elems)); dataNode->SetFloatProperty("material.diffuseCoefficient", 1.0f); - dataNode->SetProperty("color", mitk::ColorProperty::New(material.diffuse.elems)); + dataNode->SetProperty("color", mitk::ColorProperty::New(diffuse.elems)); dataNode->SetFloatProperty("material.specularCoefficient", 1.0f); dataNode->SetProperty("material.specularColor", mitk::ColorProperty::New(specular.elems)); dataNode->SetFloatProperty("material.specularPower", shininess); } static mitk::DataNode::Pointer GetSimulationDataNode(mitk::DataStorage::Pointer dataStorage, sofa::core::objectmodel::BaseNode::SPtr rootNode) { if (dataStorage.IsNull()) return NULL; if (!rootNode) return NULL; mitk::TNodePredicateDataType::Pointer predicate = mitk::TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer subset = dataStorage->GetSubset(predicate); for (mitk::DataStorage::SetOfObjects::ConstIterator it = subset->Begin(); it != subset->End(); ++it) { mitk::DataNode::Pointer dataNode = it.Value(); mitk::Simulation::Pointer simulation = static_cast(dataNode->GetData()); if (simulation->GetRootNode() == rootNode) return dataNode; } return NULL; } mitk::ExportMitkVisitor::ExportMitkVisitor(DataStorage::Pointer dataStorage, const sofa::core::ExecParams* params) : Visitor(params), m_DataStorage(dataStorage) { } mitk::ExportMitkVisitor::ExportMitkVisitor(DataStorage::Pointer dataStorage, const std::string& visualModelName, const sofa::core::ExecParams* params) : Visitor(params), m_DataStorage(dataStorage), m_VisualModelName(visualModelName) { } mitk::ExportMitkVisitor::~ExportMitkVisitor() { } sofa::simulation::Visitor::Result mitk::ExportMitkVisitor::processNodeTopDown(sofa::simulation::Node* node) { if (m_DataStorage.IsNotNull()) { for_each(this, node, node->visualModel, &ExportMitkVisitor::processVisualModel); return RESULT_CONTINUE; } return RESULT_PRUNE; } void mitk::ExportMitkVisitor::processVisualModel(sofa::simulation::Node* node, sofa::core::visual::VisualModel* visualModel) { using sofa::defaulttype::ResizableExtVector; typedef sofa::component::visualmodel::VisualModelImpl::VecCoord VecCoord; typedef sofa::component::visualmodel::VisualModelImpl::Triangle Triangle; typedef sofa::component::visualmodel::VisualModelImpl::Quad Quad; typedef sofa::component::visualmodel::VisualModelImpl::Deriv Deriv; typedef sofa::component::visualmodel::VisualModelImpl::VecTexCoord VecTexCoord; sofa::component::visualmodel::VisualModelImpl* visualModelImpl = dynamic_cast(visualModel); if (visualModelImpl == NULL) return; if (!m_VisualModelName.empty() && m_VisualModelName != visualModelImpl->name.getValue()) return; vtkSmartPointer polyData = vtkSmartPointer::New(); vtkSmartPointer points = vtkSmartPointer::New(); const VecCoord& vertices = visualModelImpl->m_vertices2.getValue().empty() ? visualModelImpl->m_positions.getValue() : visualModelImpl->m_vertices2.getValue(); size_t numPoints = vertices.size(); points->SetNumberOfPoints(numPoints); for (size_t i = 0; i < numPoints; ++i) points->SetPoint(i, vertices[i].elems); polyData->SetPoints(points); vtkSmartPointer polys = vtkSmartPointer::New(); const ResizableExtVector& triangles = visualModelImpl->m_triangles.getValue(); if (!triangles.empty()) { ResizableExtVector::const_iterator trianglesEnd = triangles.end(); for (ResizableExtVector::const_iterator it = triangles.begin(); it != trianglesEnd; ++it) { const Triangle& triangle = *it; polys->InsertNextCell(3); polys->InsertCellPoint(triangle[0]); polys->InsertCellPoint(triangle[1]); polys->InsertCellPoint(triangle[2]); } } const ResizableExtVector& quads = visualModelImpl->m_quads.getValue(); if (!quads.empty()) { ResizableExtVector::const_iterator quadsEnd = quads.end(); for (ResizableExtVector::const_iterator it = quads.begin(); it != quadsEnd; ++it) { const Quad& quad = *it; polys->InsertNextCell(4); polys->InsertCellPoint(quad[0]); polys->InsertCellPoint(quad[1]); polys->InsertCellPoint(quad[2]); polys->InsertCellPoint(quad[3]); } } polyData->SetPolys(polys); const ResizableExtVector& normals = visualModelImpl->m_vnormals.getValue(); if (!normals.empty()) { size_t numNormals = normals.size(); vtkSmartPointer vtkNormals = vtkSmartPointer::New(); vtkNormals->SetNumberOfComponents(3); vtkNormals->SetNumberOfTuples(numNormals); for (size_t i = 0; i < numNormals; ++i) vtkNormals->SetTuple(i, normals[i].elems); polyData->GetPointData()->SetNormals(vtkNormals); } const VecTexCoord& texCoords = visualModelImpl->m_vtexcoords.getValue(); if (!texCoords.empty()) { size_t numTexCoords = texCoords.size(); vtkSmartPointer vtkTexCoords = vtkSmartPointer::New(); vtkTexCoords->SetNumberOfComponents(2); vtkTexCoords->SetNumberOfTuples(numTexCoords); for (size_t i = 0; i < numTexCoords; ++i) vtkTexCoords->SetTuple(i, texCoords[i].elems); polyData->GetPointData()->SetTCoords(vtkTexCoords); } Surface::Pointer surface = Surface::New(); surface->SetVtkPolyData(polyData); DataNode::Pointer dataNode = DataNode::New(); dataNode->SetName(visualModelImpl->name.getValue()); dataNode->SetData(surface); ApplyMaterial(dataNode, visualModelImpl->material.getValue()); DataNode::Pointer parentDataNode = GetSimulationDataNode(m_DataStorage, node->getRoot()); if (parentDataNode.IsNotNull()) surface->SetGeometry(parentDataNode->GetData()->GetGeometry()); m_DataStorage->Add(dataNode, parentDataNode); } diff --git a/Modules/Simulation/mitkExportMitkVisitor.h b/Modules/Simulation/mitkExportMitkVisitor.h index 62f91084c2..8f72c3c9bd 100644 --- a/Modules/Simulation/mitkExportMitkVisitor.h +++ b/Modules/Simulation/mitkExportMitkVisitor.h @@ -1,46 +1,47 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkExportMitkVisitor_h #define mitkExportMitkVisitor_h #include #include #include namespace mitk { class MITKSIMULATION_EXPORT ExportMitkVisitor : public sofa::simulation::Visitor { public: explicit ExportMitkVisitor(DataStorage::Pointer dataStorage, const sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance()); ExportMitkVisitor(DataStorage::Pointer dataStorage, const std::string& visualModelName, const sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance()); ~ExportMitkVisitor(); + using sofa::simulation::Visitor::processNodeTopDown; Result processNodeTopDown(sofa::simulation::Node* node); private: ExportMitkVisitor(const ExportMitkVisitor&); ExportMitkVisitor& operator=(const ExportMitkVisitor&); void processVisualModel(sofa::simulation::Node* node, sofa::core::visual::VisualModel* visualModel); DataStorage::Pointer m_DataStorage; std::string m_VisualModelName; }; } #endif diff --git a/Modules/Simulation/mitkPlaneIntersectionVisitor.h b/Modules/Simulation/mitkPlaneIntersectionVisitor.h index 433eecca16..ef734ba703 100644 --- a/Modules/Simulation/mitkPlaneIntersectionVisitor.h +++ b/Modules/Simulation/mitkPlaneIntersectionVisitor.h @@ -1,62 +1,63 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkPlaneIntersectionVisitor_h #define mitkPlaneIntersectionVisitor_h #include #include #include #include namespace mitk { class MITKSIMULATION_EXPORT PlaneIntersectionVisitor : public sofa::simulation::Visitor { public: struct Edge { Point3D v0; Point3D v1; }; struct Intersection { float color[4]; std::vector edges; }; PlaneIntersectionVisitor(const Point3D& point, const Vector3D& normal, const sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance()); ~PlaneIntersectionVisitor(); const std::vector& GetIntersections() const; + using sofa::simulation::Visitor::processNodeTopDown; Result processNodeTopDown(sofa::simulation::Node* node); private: PlaneIntersectionVisitor(const PlaneIntersectionVisitor&); PlaneIntersectionVisitor& operator=(const PlaneIntersectionVisitor&); void processVisualModel(sofa::simulation::Node*, sofa::core::visual::VisualModel* visualModel); Point3D m_Point; Vector3D m_Normal; std::vector m_Intersections; }; } #endif diff --git a/Modules/Simulation/mitkSetVtkRendererVisitor.h b/Modules/Simulation/mitkSetVtkRendererVisitor.h index ae96c6b352..25bad8b59f 100644 --- a/Modules/Simulation/mitkSetVtkRendererVisitor.h +++ b/Modules/Simulation/mitkSetVtkRendererVisitor.h @@ -1,45 +1,46 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkSetVtkRendererVisitor_h #define mitkSetVtkRendererVisitor_h #include #include class vtkRenderer; namespace mitk { class MITKSIMULATION_EXPORT SetVtkRendererVisitor : public sofa::simulation::Visitor { public: explicit SetVtkRendererVisitor(vtkRenderer* renderer, const sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance()); ~SetVtkRendererVisitor(); + using sofa::simulation::Visitor::processNodeTopDown; Result processNodeTopDown(sofa::simulation::Node* node); private: SetVtkRendererVisitor(const SetVtkRendererVisitor&); SetVtkRendererVisitor& operator=(const SetVtkRendererVisitor&); void processVisualModel(sofa::simulation::Node*, sofa::core::visual::VisualModel* visualModel); vtkRenderer* m_VtkRenderer; }; } #endif diff --git a/Modules/Simulation/mitkSimulationVtkMapper3D.cpp b/Modules/Simulation/mitkSimulationVtkMapper3D.cpp index bb0013078c..51c7e3914b 100644 --- a/Modules/Simulation/mitkSimulationVtkMapper3D.cpp +++ b/Modules/Simulation/mitkSimulationVtkMapper3D.cpp @@ -1,164 +1,164 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSetVtkRendererVisitor.h" #include "mitkSimulation.h" #include "mitkSimulationVtkMapper3D.h" #include "mitkVtkSimulationPolyDataMapper3D.h" #include #include mitk::SimulationVtkMapper3D::LocalStorage::LocalStorage() : m_Actor(vtkSmartPointer::New()) { } mitk::SimulationVtkMapper3D::LocalStorage::~LocalStorage() { } void mitk::SimulationVtkMapper3D::SetDefaultProperties(DataNode* node, BaseRenderer* renderer, bool overwrite) { if (node != NULL) { Simulation* simulation = dynamic_cast(node->GetData()); if (simulation != NULL) { sofa::simulation::Node::SPtr rootNode = simulation->GetRootNode(); sofa::component::visualmodel::VisualStyle::SPtr visualStyle; rootNode->get(visualStyle); if (!visualStyle) { visualStyle = sofa::core::objectmodel::New(); sofa::core::visual::DisplayFlags* displayFlags = visualStyle->displayFlags.beginEdit(); displayFlags->setShowVisualModels(); visualStyle->displayFlags.endEdit(); rootNode->addObject(visualStyle); } const sofa::core::visual::DisplayFlags& displayFlags = visualStyle->displayFlags.getValue(); node->AddProperty("Simulation.Behavior.Behavior Models", BoolProperty::New(displayFlags.getShowBehaviorModels()), renderer, overwrite); node->AddProperty("Simulation.Behavior.Force Fields", BoolProperty::New(displayFlags.getShowForceFields()), renderer, overwrite); node->AddProperty("Simulation.Behavior.Interactions", BoolProperty::New(displayFlags.getShowInteractionForceFields()), renderer, overwrite); node->AddProperty("Simulation.Collision.Bounding Trees", BoolProperty::New(displayFlags.getShowBoundingCollisionModels()), renderer, overwrite); node->AddProperty("Simulation.Collision.Collision Models", BoolProperty::New(displayFlags.getShowCollisionModels()), renderer, overwrite); node->AddProperty("Simulation.Mapping.Mechanical Mappings", BoolProperty::New(displayFlags.getShowMechanicalMappings()), renderer, overwrite); node->AddProperty("Simulation.Mapping.Visual Mappings", BoolProperty::New(displayFlags.getShowMappings()), renderer, overwrite); node->AddProperty("Simulation.Options.Normals", BoolProperty::New(displayFlags.getShowNormals()), renderer, overwrite); node->AddProperty("Simulation.Options.Wire Frame", BoolProperty::New(displayFlags.getShowWireFrame()), renderer, overwrite); node->AddProperty("Simulation.Visual.Visual Models", BoolProperty::New(displayFlags.getShowVisualModels() != sofa::core::visual::tristate::false_value), renderer, overwrite); } Superclass::SetDefaultProperties(node, renderer, overwrite); } } mitk::SimulationVtkMapper3D::SimulationVtkMapper3D() { } mitk::SimulationVtkMapper3D::~SimulationVtkMapper3D() { } void mitk::SimulationVtkMapper3D::ApplyColorAndOpacityProperties(BaseRenderer*, vtkActor*) { } void mitk::SimulationVtkMapper3D::ApplySimulationProperties(BaseRenderer* renderer) { DataNode* node = this->GetDataNode(); bool showBehaviorModels; bool showForceFields; bool showInteractionForceFields; bool showBoundingCollisionModels; bool showCollisionModels; bool showMechanicalMappings; bool showMappings; bool showNormals; bool showWireFrame; bool showVisualModels; node->GetBoolProperty("Simulation.Behavior.Behavior Models", showBehaviorModels, renderer); node->GetBoolProperty("Simulation.Behavior.Force Fields", showForceFields, renderer); node->GetBoolProperty("Simulation.Behavior.Interactions", showInteractionForceFields, renderer); node->GetBoolProperty("Simulation.Collision.Bounding Trees", showBoundingCollisionModels, renderer); node->GetBoolProperty("Simulation.Collision.Collision Models", showCollisionModels, renderer); node->GetBoolProperty("Simulation.Mapping.Mechanical Mappings", showMechanicalMappings, renderer); node->GetBoolProperty("Simulation.Mapping.Visual Mappings", showMappings, renderer); node->GetBoolProperty("Simulation.Options.Normals", showNormals, renderer); node->GetBoolProperty("Simulation.Options.Wire Frame", showWireFrame, renderer); node->GetBoolProperty("Simulation.Visual.Visual Models", showVisualModels, renderer); - Simulation* simulation = static_cast(this->GetData()); + Simulation* simulation = static_cast(node->GetData()); sofa::component::visualmodel::VisualStyle::SPtr visualStyle; simulation->GetRootNode()->get(visualStyle); sofa::core::visual::DisplayFlags* displayFlags = visualStyle->displayFlags.beginEdit(); displayFlags->setShowBehaviorModels(showBehaviorModels); displayFlags->setShowForceFields(showForceFields); displayFlags->setShowInteractionForceFields(showInteractionForceFields); displayFlags->setShowBoundingCollisionModels(showBoundingCollisionModels); displayFlags->setShowCollisionModels(showCollisionModels); displayFlags->setShowMechanicalMappings(showMechanicalMappings); displayFlags->setShowMappings(showMappings); displayFlags->setShowNormals(showNormals); displayFlags->setShowWireFrame(showWireFrame); displayFlags->setShowVisualModels(showVisualModels); visualStyle->displayFlags.endEdit(); } void mitk::SimulationVtkMapper3D::GenerateDataForRenderer(BaseRenderer* renderer) { DataNode* dataNode = this->GetDataNode(); if (dataNode == NULL) return; Simulation* simulation = dynamic_cast(dataNode->GetData()); if (simulation == NULL) return; LocalStorage* localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); if (localStorage->m_Mapper == NULL) { localStorage->m_Mapper = vtkSmartPointer::New(); localStorage->m_Mapper->SetSimulation(simulation); localStorage->m_Actor->SetMapper(localStorage->m_Mapper); SetVtkRendererVisitor setVtkRendererVisitor(renderer->GetVtkRenderer()); simulation->GetRootNode()->executeVisitor(&setVtkRendererVisitor); } this->ApplySimulationProperties(renderer); } vtkProp* mitk::SimulationVtkMapper3D::GetVtkProp(BaseRenderer* renderer) { return m_LocalStorageHandler.GetLocalStorage(renderer)->m_Actor; } diff --git a/Modules/Simulation/mitkVtkModel.cpp b/Modules/Simulation/mitkVtkModel.cpp index 2fe091b485..5dadba56c1 100644 --- a/Modules/Simulation/mitkVtkModel.cpp +++ b/Modules/Simulation/mitkVtkModel.cpp @@ -1,613 +1,633 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkVtkModel.h" #include #include #include #include #include #include #include #include #include #include #include +// Defined in mitkExportMitkVisitor.cpp +void ApplyMaterial(mitk::DataNode::Pointer dataNode, const sofa::core::loader::Material& material); + static bool InitGLEW() { static bool isInitialized = false; // If no render window is shown, OpenGL is potentially not initialized, e.g., the // Display tab of the Workbench might be closed while loading a SOFA scene file. // In this case initialization is deferred (see mitk::VtkModel::internalDraw()). if (mitk::RenderingManager::GetInstance()->GetAllRegisteredRenderWindows().empty()) return false; if (!isInitialized) { GLenum error = glewInit(); if (error != GLEW_OK) { MITK_ERROR("glewInit") << glewGetErrorString(error); } else { isInitialized = true; } } return isInitialized; } mitk::VtkModel::VtkModel() : m_GlewIsInitialized(InitGLEW()), m_BuffersWereCreated(false), m_LastNumberOfVertices(0), m_LastNumberOfTriangles(0), m_LastNumberOfQuads(0), m_VertexBuffer(0), m_IndexBuffer(0), m_VtkRenderer(NULL), m_Mode(OpenGL) { } mitk::VtkModel::~VtkModel() { if (m_Mode == OpenGL && m_BuffersWereCreated) { glDeleteBuffers(1, &m_IndexBuffer); glDeleteBuffers(1, &m_VertexBuffer); } } void mitk::VtkModel::CreateIndexBuffer() { if (m_Mode == OpenGL) { glGenBuffers(1, &m_IndexBuffer); } else if (m_Mode == Surface) { m_Polys = vtkSmartPointer::New(); } this->InitIndexBuffer(); } void mitk::VtkModel::CreateVertexBuffer() { if (m_Mode == OpenGL) { glGenBuffers(1, &m_VertexBuffer); } else if (m_Mode == Surface) { m_Points = vtkSmartPointer::New(); m_Normals = vtkSmartPointer::New(); m_TexCoords = vtkSmartPointer::New(); } this->InitVertexBuffer(); } -void mitk::VtkModel::DrawGroup(int group, bool) +void mitk::VtkModel::DrawGroup(int group, bool transparent) +{ + if (m_Mode == OpenGL) + { + this->DrawOpenGLGroup(group, transparent); + } + else if (m_Mode == Surface) + { + this->DrawSurfaceGroup(group, transparent); + } +} + +void mitk::VtkModel::DrawOpenGLGroup(int group, bool) { using sofa::core::loader::Material; using sofa::defaulttype::ResizableExtVector; using sofa::defaulttype::Vec4f; - if (m_Mode == OpenGL) - { - const VecCoord& vertices = this->getVertices(); - const ResizableExtVector& normals = this->getVnormals(); - const ResizableExtVector& triangles = this->getTriangles(); - const ResizableExtVector& quads = this->getQuads(); + const VecCoord& vertices = this->getVertices(); + const ResizableExtVector& normals = this->getVnormals(); + const ResizableExtVector& triangles = this->getTriangles(); + const ResizableExtVector& quads = this->getQuads(); - FaceGroup faceGroup; + FaceGroup faceGroup; - if (group == -1) - { - faceGroup.nbt = triangles.size(); - faceGroup.nbq = quads.size(); - } - else - { - faceGroup = groups.getValue()[group]; - } + if (group == -1) + { + faceGroup.nbt = triangles.size(); + faceGroup.nbq = quads.size(); + } + else + { + faceGroup = groups.getValue()[group]; + } - Material material = faceGroup.materialId != -1 - ? materials.getValue()[faceGroup.materialId] - : this->material.getValue(); + Material material = faceGroup.materialId != -1 + ? materials.getValue()[faceGroup.materialId] + : this->material.getValue(); - if (material.useTexture && material.activated) - { - m_Textures[faceGroup.materialId]->Load(m_VtkRenderer); - - glEnable(GL_TEXTURE_2D); - glTexCoordPointer(2, GL_FLOAT, 0, reinterpret_cast(vertices.size() * sizeof(VecCoord::value_type) + normals.size() * sizeof(Deriv))); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - } + if (material.useTexture && material.activated) + { + m_Textures[faceGroup.materialId]->Load(m_VtkRenderer); - Vec4f ambient = material.useAmbient ? material.ambient : Vec4f(); - Vec4f diffuse = material.useDiffuse ? material.diffuse : Vec4f(); - Vec4f specular = material.useSpecular ? material.specular : Vec4f(); - Vec4f emissive = material.useEmissive ? material.emissive : Vec4f(); - float shininess = material.useShininess ? std::min(material.shininess, 128.0f) : 45.0f; + glEnable(GL_TEXTURE_2D); + glTexCoordPointer(2, GL_FLOAT, 0, reinterpret_cast(vertices.size() * sizeof(VecCoord::value_type) + normals.size() * sizeof(Deriv))); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } - if (shininess == 0.0f) - { - specular.clear(); - shininess = 1.0f; - } + Vec4f ambient = material.useAmbient ? material.ambient : Vec4f(); + Vec4f diffuse = material.useDiffuse ? material.diffuse : Vec4f(); + Vec4f specular = material.useSpecular ? material.specular : Vec4f(); + Vec4f emissive = material.useEmissive ? material.emissive : Vec4f(); + float shininess = material.useShininess ? std::min(material.shininess, 128.0f) : 45.0f; - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient.ptr()); - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.ptr()); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular.ptr()); - glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emissive.ptr()); - glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); + if (shininess == 0.0f) + { + specular.clear(); + shininess = 1.0f; + } - if (faceGroup.nbt != 0) - glDrawElements(GL_TRIANGLES, faceGroup.nbt * 3, GL_UNSIGNED_INT, reinterpret_cast(faceGroup.tri0 * sizeof(Triangle))); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient.ptr()); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.ptr()); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular.ptr()); + glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emissive.ptr()); + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); - if (faceGroup.nbq != 0) - glDrawElements(GL_QUADS, faceGroup.nbq * 4, GL_UNSIGNED_INT, reinterpret_cast(triangles.size() * sizeof(Triangle) + faceGroup.quad0 * sizeof(Quad))); + if (faceGroup.nbt != 0) + glDrawElements(GL_TRIANGLES, faceGroup.nbt * 3, GL_UNSIGNED_INT, reinterpret_cast(faceGroup.tri0 * sizeof(Triangle))); - if (material.useTexture && material.activated) - { - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_TEXTURE_2D); + if (faceGroup.nbq != 0) + glDrawElements(GL_QUADS, faceGroup.nbq * 4, GL_UNSIGNED_INT, reinterpret_cast(triangles.size() * sizeof(Triangle) + faceGroup.quad0 * sizeof(Quad))); - m_Textures[faceGroup.materialId]->PostRender(m_VtkRenderer); - } - } - else if (m_Mode == Surface) + if (material.useTexture && material.activated) { - m_PolyData->SetPoints(m_Points); - m_PolyData->SetPolys(m_Polys); - m_PolyData->GetPointData()->SetNormals(m_Normals); - m_PolyData->GetPointData()->SetTCoords(m_TexCoords); - m_PolyData->Modified(); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisable(GL_TEXTURE_2D); + + m_Textures[faceGroup.materialId]->PostRender(m_VtkRenderer); } } +void mitk::VtkModel::DrawSurfaceGroup(int group, bool) +{ + m_PolyData->SetPoints(m_Points); + m_PolyData->SetPolys(m_Polys); + + vtkPointData* pointData = m_PolyData->GetPointData(); + + pointData->SetNormals(m_Normals->GetSize() != 0 + ? m_Normals + : NULL); + + pointData->SetTCoords(m_TexCoords->GetSize() != 0 + ? m_TexCoords + : NULL); + + m_PolyData->Modified(); +} + void mitk::VtkModel::DrawGroups(bool transparent) { using sofa::core::objectmodel::Data; using sofa::helper::ReadAccessor; using sofa::helper::vector; ReadAccessor > > groups = this->groups; if (groups.empty()) { this->DrawGroup(-1, transparent); } else { int numGroups = static_cast(groups.size()); for (int i = 0; i < numGroups; ++i) this->DrawGroup(i, transparent); } } void mitk::VtkModel::InitIndexBuffer() { using sofa::defaulttype::ResizableExtVector; const ResizableExtVector& triangles = this->getTriangles(); const ResizableExtVector& quads = this->getQuads(); if (m_Mode == OpenGL) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IndexBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, triangles.size() * sizeof(Triangle) + quads.size() * sizeof(Quad), NULL, GL_DYNAMIC_DRAW); } - else if (m_Mode == Surface) - { - m_Polys->Initialize(); - } this->UpdateIndexBuffer(); } void mitk::VtkModel::InitVertexBuffer() { using sofa::defaulttype::ResizableExtVector; const VecCoord& vertices = this->getVertices(); const ResizableExtVector normals = this->getVnormals(); const VecTexCoord& texCoords = this->getVtexcoords(); if (m_Mode == OpenGL) { glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(VecCoord::value_type) + normals.size() * sizeof(Deriv) + texCoords.size() * sizeof(VecTexCoord::value_type), NULL, GL_DYNAMIC_DRAW); } else if (m_Mode == Surface) { m_Points->SetNumberOfPoints(vertices.size()); m_Normals->SetNumberOfComponents(3); m_Normals->SetNumberOfTuples(normals.size()); m_TexCoords->SetNumberOfComponents(2); m_TexCoords->SetNumberOfTuples(texCoords.size()); } this->UpdateVertexBuffer(); } void mitk::VtkModel::internalDraw(const sofa::core::visual::VisualParams* vparams, bool transparent) { using sofa::core::visual::DisplayFlags; using sofa::defaulttype::ResizableExtVector; if (m_Mode == OpenGL && !m_GlewIsInitialized) { // Try lazy initialization since initialization potentially failed so far // due to missing render windows (see InitGLEW()). m_GlewIsInitialized = InitGLEW(); if (m_GlewIsInitialized) { this->updateBuffers(); } else { return; } } const DisplayFlags& displayFlags = vparams->displayFlags(); if (!displayFlags.getShowVisualModels()) return; if (m_BuffersWereCreated == false) return; if (m_Mode == OpenGL) { glEnable(GL_LIGHTING); glColor3f(1.0f, 1.0f, 1.0f); glPolygonMode(GL_FRONT_AND_BACK, displayFlags.getShowWireFrame() ? GL_LINE : GL_FILL); const VecCoord& vertices = this->getVertices(); glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IndexBuffer); this->ValidateBoundBuffers(); glVertexPointer(3, GL_FLOAT, 0, NULL); glNormalPointer(GL_FLOAT, 0, reinterpret_cast(vertices.size() * sizeof(VecCoord::value_type))); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); } this->DrawGroups(transparent); if (m_Mode == OpenGL) { glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); if (displayFlags.getShowWireFrame()) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDisable(GL_LIGHTING); } if (displayFlags.getShowNormals()) this->DrawNormals(); } void mitk::VtkModel::DrawNormals() { using sofa::defaulttype::ResizableExtVector; if (m_Mode == OpenGL) { const VecCoord& vertices = this->getVertices(); const ResizableExtVector& normals = this->getVnormals(); size_t numVertices = vertices.size(); Coord normal; glBegin(GL_LINES); for (size_t i = 0; i < numVertices; ++i) { glVertex3fv(vertices[i].ptr()); normal = vertices[i] + normals[i]; glVertex3fv(normal.ptr()); } glEnd(); } } bool mitk::VtkModel::loadTextures() { using sofa::helper::system::DataRepository; using sofa::helper::vector; using sofa::core::loader::Material; m_Textures.clear(); std::vector materialIndices; const vector& materials = this->materials.getValue(); unsigned int numMaterials = materials.size(); for (unsigned int i = 0; i < numMaterials; ++i) { const Material& material = materials[i]; if (material.useTexture && material.activated) materialIndices.push_back(i); } bool retValue = true; size_t numTextures = materialIndices.size(); for (size_t i = 0; i < numTextures; ++i) { std::string filename = materials[materialIndices[i]].textureFilename; if (!DataRepository.findFile(filename)) { MITK_ERROR("VtkModel") << "File \"" << filename << "\" not found!"; retValue = false; continue; } vtkSmartPointer imageReader = vtkSmartPointer::Take(vtkImageReader2Factory::CreateImageReader2(filename.c_str())); if (imageReader == NULL) { MITK_ERROR("VtkModel") << "File \"" << filename << "\" has unknown image format!"; retValue = false; continue; } imageReader->SetFileName(filename.c_str()); imageReader->UpdateWholeExtent(); vtkSmartPointer texture = vtkSmartPointer::New(); texture->SetInputConnection(imageReader->GetOutputPort()); texture->InterpolateOn(); m_Textures.insert(std::make_pair(materialIndices[i], texture)); } return retValue; } mitk::DataNode::Pointer mitk::VtkModel::GetDataNode() const { return m_DataNode; } mitk::VtkModel::Mode mitk::VtkModel::GetMode() const { return m_Mode; } void mitk::VtkModel::SetMode(Mode mode) { if (m_Mode == mode) return; if (mode == OpenGL) { m_DataNode = NULL; m_Surface = NULL; m_PolyData = NULL; m_TexCoords = NULL; m_Normals = NULL; m_Polys = NULL; m_Points = NULL; } else if (mode == Surface) { if (m_Mode == OpenGL && m_BuffersWereCreated) { glDeleteBuffers(1, &m_IndexBuffer); m_IndexBuffer = 0; glDeleteBuffers(1, &m_VertexBuffer); m_VertexBuffer = 0; } m_PolyData = vtkSmartPointer::New(); m_Surface = Surface::New(); m_Surface->SetVtkPolyData(m_PolyData); m_DataNode = DataNode::New(); m_DataNode->SetName(name.getValue()); m_DataNode->SetData(m_Surface); + + ApplyMaterial(m_DataNode, this->material.getValue()); } m_Mode = mode; m_BuffersWereCreated = false; this->updateBuffers(); } void mitk::VtkModel::SetVtkRenderer(vtkRenderer* renderer) { m_VtkRenderer = renderer; } void mitk::VtkModel::updateBuffers() { using sofa::defaulttype::ResizableExtVector; if (m_Mode == OpenGL && !m_GlewIsInitialized) return; const VecCoord& vertices = this->getVertices(); const ResizableExtVector& triangles = this->getTriangles(); const ResizableExtVector& quads = this->getQuads(); if (!m_BuffersWereCreated) { this->CreateVertexBuffer(); this->CreateIndexBuffer(); m_BuffersWereCreated = true; } else { if (m_LastNumberOfVertices != vertices.size()) this->InitVertexBuffer(); else this->UpdateVertexBuffer(); if (m_LastNumberOfTriangles != triangles.size() || m_LastNumberOfQuads != quads.size()) this->InitIndexBuffer(); else this->UpdateIndexBuffer(); } m_LastNumberOfVertices = vertices.size(); m_LastNumberOfTriangles = triangles.size(); m_LastNumberOfQuads = quads.size(); } void mitk::VtkModel::UpdateIndexBuffer() { using sofa::defaulttype::ResizableExtVector; const ResizableExtVector& triangles = this->getTriangles(); const ResizableExtVector& quads = this->getQuads(); GLsizeiptr sizeOfTriangleIndices = triangles.size() * sizeof(Triangle); GLsizeiptr sizeOfQuadIndices = quads.size() * sizeof(Quad); if (m_Mode == OpenGL) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IndexBuffer); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeOfTriangleIndices, triangles.getData()); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, sizeOfTriangleIndices, sizeOfQuadIndices, quads.getData()); } else if (m_Mode == Surface) { m_Polys->Initialize(); if (!triangles.empty()) { ResizableExtVector::const_iterator trianglesEnd = triangles.end(); for (ResizableExtVector::const_iterator it = triangles.begin(); it != trianglesEnd; ++it) { const Triangle& triangle = *it; m_Polys->InsertNextCell(3); m_Polys->InsertCellPoint(triangle[0]); m_Polys->InsertCellPoint(triangle[1]); m_Polys->InsertCellPoint(triangle[2]); } } if (!quads.empty()) { ResizableExtVector::const_iterator quadsEnd = quads.end(); for (ResizableExtVector::const_iterator it = quads.begin(); it != quadsEnd; ++it) { const Quad& quad = *it; m_Polys->InsertNextCell(4); m_Polys->InsertCellPoint(quad[0]); m_Polys->InsertCellPoint(quad[1]); m_Polys->InsertCellPoint(quad[2]); m_Polys->InsertCellPoint(quad[3]); } } } } void mitk::VtkModel::UpdateVertexBuffer() { using sofa::defaulttype::ResizableExtVector; const VecCoord& vertices = this->getVertices(); const ResizableExtVector normals = this->getVnormals(); const VecTexCoord& texCoords = this->getVtexcoords(); if (m_Mode == OpenGL) { GLsizeiptr sizeOfVertices = vertices.size() * sizeof(VecCoord::value_type); GLsizeiptr sizeOfNormals = normals.size() * sizeof(Deriv); glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeOfVertices, vertices.getData()); glBufferSubData(GL_ARRAY_BUFFER, sizeOfVertices, sizeOfNormals, normals.getData()); if (!m_Textures.empty()) { GLsizeiptr sizeOfTexCoords = texCoords.size() * sizeof(VecTexCoord::value_type); glBufferSubData(GL_ARRAY_BUFFER, sizeOfVertices + sizeOfNormals, sizeOfTexCoords, texCoords.getData()); } } else if (m_Mode == Surface) { size_t numPoints = vertices.size(); for (size_t i = 0; i < numPoints; ++i) m_Points->SetPoint(i, vertices[i].elems); if (!normals.empty()) { size_t numNormals = normals.size(); for (size_t i = 0; i < numNormals; ++i) m_Normals->SetTuple(i, normals[i].elems); } if (!texCoords.empty()) { size_t numTexCoords = texCoords.size(); for (size_t i = 0; i < numTexCoords; ++i) m_TexCoords->SetTuple(i, normals[i].elems); } } } void mitk::VtkModel::ValidateBoundBuffers() { if (m_Mode != OpenGL) return; GLint indexBufferSize; glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &indexBufferSize); if (indexBufferSize == 0) { glDeleteBuffers(1, &m_IndexBuffer); this->CreateIndexBuffer(); glDeleteBuffers(1, &m_VertexBuffer); this->CreateVertexBuffer(); } } diff --git a/Modules/Simulation/mitkVtkModel.h b/Modules/Simulation/mitkVtkModel.h index 68a9c37758..8f2d531d05 100644 --- a/Modules/Simulation/mitkVtkModel.h +++ b/Modules/Simulation/mitkVtkModel.h @@ -1,97 +1,99 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkVtkModel_h #define mitkVtkModel_h #include #include #include #include #include #include #include #include #include #include #include #include class vtkOpenGLTexture; class vtkRenderer; namespace mitk { class MITKSIMULATION_EXPORT VtkModel : public sofa::component::visualmodel::VisualModelImpl { public: enum Mode { OpenGL, Surface }; SOFA_CLASS(VtkModel, sofa::component::visualmodel::VisualModelImpl); void internalDraw(const sofa::core::visual::VisualParams* vparams, bool transparent); bool loadTextures(); void SetVtkRenderer(vtkRenderer* renderer); void updateBuffers(); DataNode::Pointer GetDataNode() const; Mode GetMode() const; void SetMode(Mode mode); private: VtkModel(); ~VtkModel(); VtkModel(MyType&); MyType& operator=(const MyType&); void CreateIndexBuffer(); void CreateVertexBuffer(); - void DrawGroup(int group, bool); + void DrawGroup(int group, bool transparent); + void DrawOpenGLGroup(int group, bool transparent); + void DrawSurfaceGroup(int group, bool transparent); void DrawGroups(bool transparent); void DrawNormals(); void InitIndexBuffer(); void InitVertexBuffer(); void UpdateIndexBuffer(); void UpdateVertexBuffer(); void ValidateBoundBuffers(); bool m_GlewIsInitialized; bool m_BuffersWereCreated; size_t m_LastNumberOfVertices; size_t m_LastNumberOfTriangles; size_t m_LastNumberOfQuads; GLuint m_VertexBuffer; GLuint m_IndexBuffer; std::map > m_Textures; vtkRenderer* m_VtkRenderer; Mode m_Mode; vtkSmartPointer m_Points; vtkSmartPointer m_Polys; vtkSmartPointer m_Normals; vtkSmartPointer m_TexCoords; vtkSmartPointer m_PolyData; Surface::Pointer m_Surface; DataNode::Pointer m_DataNode; }; } #endif diff --git a/Modules/Simulation/mitkVtkSimulationPolyDataMapper2D.cpp b/Modules/Simulation/mitkVtkSimulationPolyDataMapper2D.cpp index fe2fa687a5..773fdb9177 100644 --- a/Modules/Simulation/mitkVtkSimulationPolyDataMapper2D.cpp +++ b/Modules/Simulation/mitkVtkSimulationPolyDataMapper2D.cpp @@ -1,139 +1,139 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkGetSimulationService.h" #include "mitkISimulationService.h" #include "mitkPlaneIntersectionVisitor.h" #include "mitkVtkSimulationPolyDataMapper2D.h" #include #include #include #include #include #include namespace mitk { vtkStandardNewMacro(vtkSimulationPolyDataMapper2D); } mitk::vtkSimulationPolyDataMapper2D::vtkSimulationPolyDataMapper2D() : m_SimulationService(GetSimulationService()) { } mitk::vtkSimulationPolyDataMapper2D::~vtkSimulationPolyDataMapper2D() { } -void mitk::vtkSimulationPolyDataMapper2D::Render(vtkRenderer* renderer, vtkActor* actor) +void mitk::vtkSimulationPolyDataMapper2D::Render(vtkRenderer* renderer, vtkActor*) { typedef PlaneIntersectionVisitor::Edge Edge; typedef PlaneIntersectionVisitor::Intersection Intersection; vtkRenderWindow* renderWindow = renderer->GetRenderWindow(); if (renderWindow->CheckAbortStatus() == 1) return; if (renderWindow->SupportsOpenGL() == 0) return; if (m_Simulation.IsNull()) return; if (!renderWindow->IsCurrent()) renderWindow->MakeCurrent(); BaseRenderer* mitkRenderer = BaseRenderer::GetInstance(renderer->GetRenderWindow()); if (mitkRenderer == NULL) return; SliceNavigationController* sliceNavigationController = mitkRenderer->GetSliceNavigationController(); if (sliceNavigationController == NULL) return; const PlaneGeometry* planeGeometry = sliceNavigationController->GetCurrentPlaneGeometry(); if (planeGeometry == NULL) return; renderer->GetRenderWindow()->MakeCurrent(); m_SimulationService->SetActiveSimulation(m_Simulation); PlaneIntersectionVisitor planeIntersectionVisitor(planeGeometry->GetOrigin(), planeGeometry->GetNormal()); m_Simulation->GetRootNode()->executeVisitor(&planeIntersectionVisitor); mitk::DisplayGeometry::Pointer displayGeometry = mitkRenderer->GetDisplayGeometry(); Point2D point2D; glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); glEnable(GL_COLOR_MATERIAL); const std::vector& intersections = planeIntersectionVisitor.GetIntersections(); std::vector::const_iterator intersectionsEnd = intersections.end(); for (std::vector::const_iterator intersectionIt = intersections.begin(); intersectionIt != intersectionsEnd; ++intersectionIt) { const std::vector& edges = intersectionIt->edges; std::vector::const_iterator edgesEnd = edges.end(); glColor4fv(intersectionIt->color); glBegin(GL_LINES); for (std::vector::const_iterator edgeIt = edges.begin(); edgeIt != edgesEnd; ++edgeIt) { glVertex3dv(edgeIt->v0.GetDataPointer()); glVertex3dv(edgeIt->v1.GetDataPointer()); } glEnd(); } glDisable(GL_COLOR_MATERIAL); } void mitk::vtkSimulationPolyDataMapper2D::RenderPiece(vtkRenderer*, vtkActor*) { } void mitk::vtkSimulationPolyDataMapper2D::SetSimulation(Simulation::Pointer simulation) { m_Simulation = simulation; } double* mitk::vtkSimulationPolyDataMapper2D::GetBounds() { if (m_Simulation.IsNull()) return Superclass::GetBounds(); sofa::simulation::Node::SPtr rootNode = m_Simulation->GetRootNode(); const sofa::defaulttype::BoundingBox& bbox = rootNode->f_bbox.getValue(); const sofa::defaulttype::Vector3& min = bbox.minBBox(); const sofa::defaulttype::Vector3& max = bbox.maxBBox(); Bounds[0] = min.x(); Bounds[1] = max.x(); Bounds[2] = min.y(); Bounds[3] = max.y(); Bounds[4] = min.z(); Bounds[5] = max.z(); return this->Bounds; } diff --git a/Modules/Simulation/mitkVtkSimulationPolyDataMapper3D.cpp b/Modules/Simulation/mitkVtkSimulationPolyDataMapper3D.cpp index 2d242e5e14..6d6e7c528b 100644 --- a/Modules/Simulation/mitkVtkSimulationPolyDataMapper3D.cpp +++ b/Modules/Simulation/mitkVtkSimulationPolyDataMapper3D.cpp @@ -1,95 +1,95 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkGetSimulationService.h" #include "mitkISimulationService.h" #include "mitkVtkSimulationPolyDataMapper3D.h" #include #include #include #include namespace mitk { vtkStandardNewMacro(vtkSimulationPolyDataMapper3D); } mitk::vtkSimulationPolyDataMapper3D::vtkSimulationPolyDataMapper3D() : m_SimulationService(GetSimulationService()) { } mitk::vtkSimulationPolyDataMapper3D::~vtkSimulationPolyDataMapper3D() { } -void mitk::vtkSimulationPolyDataMapper3D::Render(vtkRenderer* renderer, vtkActor* actor) +void mitk::vtkSimulationPolyDataMapper3D::Render(vtkRenderer* renderer, vtkActor*) { vtkRenderWindow* renderWindow = renderer->GetRenderWindow(); if (renderWindow->CheckAbortStatus() == 1) return; if (renderWindow->SupportsOpenGL() == 0) return; if (m_Simulation.IsNull()) return; if (!renderWindow->IsCurrent()) renderWindow->MakeCurrent(); m_SimulationService->SetActiveSimulation(m_Simulation); sofa::core::visual::VisualParams* vParams = sofa::core::visual::VisualParams::defaultInstance(); sofa::simulation::Simulation::SPtr sofaSimulation = m_Simulation->GetSOFASimulation(); sofa::simulation::Node::SPtr rootNode = m_Simulation->GetRootNode(); sofaSimulation->updateVisual(rootNode.get()); sofaSimulation->draw(vParams, rootNode.get()); // SOFA potentially disables GL_BLEND but VTK relies on it. glEnable(GL_BLEND); } void mitk::vtkSimulationPolyDataMapper3D::RenderPiece(vtkRenderer*, vtkActor*) { } void mitk::vtkSimulationPolyDataMapper3D::SetSimulation(Simulation::Pointer simulation) { m_Simulation = simulation; } double* mitk::vtkSimulationPolyDataMapper3D::GetBounds() { if (m_Simulation.IsNull()) return Superclass::GetBounds(); sofa::simulation::Node::SPtr rootNode = m_Simulation->GetRootNode(); const sofa::defaulttype::BoundingBox& bbox = rootNode->f_bbox.getValue(); const sofa::defaulttype::Vector3& min = bbox.minBBox(); const sofa::defaulttype::Vector3& max = bbox.maxBBox(); Bounds[0] = min.x(); Bounds[1] = max.x(); Bounds[2] = min.y(); Bounds[3] = max.y(); Bounds[4] = min.z(); Bounds[5] = max.z(); return this->Bounds; } diff --git a/Modules/SurfaceInterpolation/Testing/files.cmake b/Modules/SurfaceInterpolation/Testing/files.cmake index 4dc47a7217..79c0696ef9 100644 --- a/Modules/SurfaceInterpolation/Testing/files.cmake +++ b/Modules/SurfaceInterpolation/Testing/files.cmake @@ -1,9 +1,10 @@ set(MODULE_TESTS mitkComputeContourSetNormalsFilterTest.cpp + mitkPointCloudScoringFilterTest mitkReduceContourSetFilterTest.cpp mitkSurfaceInterpolationControllerTest.cpp ) if(NOT WIN32) set(MODULE_TESTS ${MODULE_TESTS} mitkCreateDistanceImageFromSurfaceFilterTest.cpp) endif() diff --git a/Modules/SurfaceInterpolation/Testing/mitkPointCloudScoringFilterTest.cpp b/Modules/SurfaceInterpolation/Testing/mitkPointCloudScoringFilterTest.cpp new file mode 100644 index 0000000000..7282fe2e2d --- /dev/null +++ b/Modules/SurfaceInterpolation/Testing/mitkPointCloudScoringFilterTest.cpp @@ -0,0 +1,122 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTestingMacros.h" +#include +#include +#include + +#include + +#include +#include +#include + +class mitkPointCloudScoringFilterTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkPointCloudScoringFilterTestSuite); + MITK_TEST(testPointCloudScoringFilterInitialization); + MITK_TEST(testInputs); + MITK_TEST(testOutput); + MITK_TEST(testScoring); + CPPUNIT_TEST_SUITE_END(); + +private: + + mitk::UnstructuredGrid::Pointer m_UnstructuredGrid1; + mitk::UnstructuredGrid::Pointer m_UnstructuredGrid2; + +public: + + void setUp() + { + m_UnstructuredGrid1 = mitk::UnstructuredGrid::New(); + m_UnstructuredGrid2 = mitk::UnstructuredGrid::New(); + + vtkSmartPointer vtkGrid1 = vtkSmartPointer::New(); + vtkSmartPointer vtkGrid2 = vtkSmartPointer::New(); + vtkSmartPointer points1 = vtkSmartPointer::New(); + vtkSmartPointer points2 = vtkSmartPointer::New(); + + for(int i=0; i<3; i++) + { + for(int j=0; j<3; j++) + { + for(int k=0; k<3; k++) + { + mitk::Point3D point; + point[0]=i; + point[1]=j; + point[2]=k; + + points1->InsertNextPoint(point[0],point[1],point[2]); + points2->InsertNextPoint(point[0]+i,point[1]+i,point[2]+i); + } + } + } + + vtkGrid1->SetPoints(points1); + vtkGrid2->SetPoints(points2); + m_UnstructuredGrid1->SetVtkUnstructuredGrid(vtkGrid1); + m_UnstructuredGrid2->SetVtkUnstructuredGrid(vtkGrid2); + } + + void testPointCloudScoringFilterInitialization() + { + mitk::PointCloudScoringFilter::Pointer testFilter = mitk::PointCloudScoringFilter::New(); + CPPUNIT_ASSERT_MESSAGE("Testing instantiation of test object", testFilter.IsNotNull()); + } + + void testInputs() + { + mitk::PointCloudScoringFilter::Pointer testFilter = mitk::PointCloudScoringFilter::New(); + testFilter->SetInput(0, m_UnstructuredGrid1); + testFilter->SetInput(1, m_UnstructuredGrid2); + + mitk::UnstructuredGrid::Pointer uGrid1 = dynamic_cast(testFilter->GetInputs().at(0).GetPointer()); + mitk::UnstructuredGrid::Pointer uGrid2 = dynamic_cast(testFilter->GetInputs().at(1).GetPointer()); + + CPPUNIT_ASSERT_MESSAGE("Testing the first input", uGrid1 == m_UnstructuredGrid1); + CPPUNIT_ASSERT_MESSAGE("Testing the second input", uGrid2 == m_UnstructuredGrid2); + } + + void testOutput() + { + mitk::PointCloudScoringFilter::Pointer testFilter = mitk::PointCloudScoringFilter::New(); + testFilter->SetInput(0, m_UnstructuredGrid1); + testFilter->SetInput(1, m_UnstructuredGrid2); + testFilter->Update(); + CPPUNIT_ASSERT_MESSAGE("Testing mitkUnstructuredGrid generation!", testFilter->GetOutput() != NULL); + } + + void testScoring() + { + mitk::PointCloudScoringFilter::Pointer testFilter = mitk::PointCloudScoringFilter::New(); + testFilter->SetInput(0, m_UnstructuredGrid2); + testFilter->SetInput(1, m_UnstructuredGrid1); + testFilter->Update(); + + mitk::UnstructuredGrid::Pointer outpGrid = testFilter->GetOutput(); + + int numBefore = m_UnstructuredGrid1->GetVtkUnstructuredGrid()->GetNumberOfPoints(); + int numAfter = outpGrid->GetVtkUnstructuredGrid()->GetNumberOfPoints(); + + CPPUNIT_ASSERT_MESSAGE("Testing grid scoring", numBefore > numAfter); + } + +}; + +MITK_TEST_SUITE_REGISTRATION(mitkPointCloudScoringFilter) diff --git a/Modules/SurfaceInterpolation/files.cmake b/Modules/SurfaceInterpolation/files.cmake index 0dd9c14810..f3339c5be6 100644 --- a/Modules/SurfaceInterpolation/files.cmake +++ b/Modules/SurfaceInterpolation/files.cmake @@ -1,6 +1,7 @@ set(CPP_FILES mitkComputeContourSetNormalsFilter.cpp mitkCreateDistanceImageFromSurfaceFilter.cpp + mitkPointCloudScoringFilter.cpp mitkReduceContourSetFilter.cpp mitkSurfaceInterpolationController.cpp -) \ No newline at end of file +) diff --git a/Modules/SurfaceInterpolation/mitkComputeContourSetNormalsFilter.cpp b/Modules/SurfaceInterpolation/mitkComputeContourSetNormalsFilter.cpp index 66a3de9fb3..c4dcdea82e 100644 --- a/Modules/SurfaceInterpolation/mitkComputeContourSetNormalsFilter.cpp +++ b/Modules/SurfaceInterpolation/mitkComputeContourSetNormalsFilter.cpp @@ -1,331 +1,330 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkComputeContourSetNormalsFilter.h" #include "mitkImagePixelReadAccessor.h" mitk::ComputeContourSetNormalsFilter::ComputeContourSetNormalsFilter() : m_SegmentationBinaryImage(NULL) , m_MaxSpacing(5) , m_NegativeNormalCounter(0) , m_PositiveNormalCounter(0) , m_UseProgressBar(false) , m_ProgressStepSize(1) { mitk::Surface::Pointer output = mitk::Surface::New(); this->SetNthOutput(0, output.GetPointer()); } mitk::ComputeContourSetNormalsFilter::~ComputeContourSetNormalsFilter() { } void mitk::ComputeContourSetNormalsFilter::GenerateData() { unsigned int numberOfInputs = this->GetNumberOfIndexedInputs(); - this->CreateOutputsForAllInputs(numberOfInputs); //Iterating over each input for(unsigned int i = 0; i < numberOfInputs; i++) { //Getting the inputs polydata and polygons Surface* currentSurface = const_cast( this->GetInput(i) ); vtkPolyData* polyData = currentSurface->GetVtkPolyData(); vtkSmartPointer existingPolys = polyData->GetPolys(); vtkSmartPointer existingPoints = polyData->GetPoints(); existingPolys->InitTraversal(); vtkIdType* cell (NULL); vtkIdType cellSize (0); //The array that contains all the vertex normals of the current polygon vtkSmartPointer normals = vtkSmartPointer::New(); normals->SetNumberOfComponents(3); normals->SetNumberOfTuples(polyData->GetNumberOfPoints()); //If the current contour is an inner contour then the direction is -1 //A contour lies inside another one if the pixel values in the direction of the normal is 1 m_NegativeNormalCounter = 0; m_PositiveNormalCounter = 0; vtkIdType offSet (0); //Iterating over each polygon for( existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);) { if(cellSize < 3)continue; //First we calculate the current polygon's normal double polygonNormal[3] = {0.0}; double p1[3]; double p2[3]; double v1[3]; double v2[3]; existingPoints->GetPoint(cell[0], p1); unsigned int index = cellSize*0.5; existingPoints->GetPoint(cell[index], p2); v1[0] = p2[0]-p1[0]; v1[1] = p2[1]-p1[1]; v1[2] = p2[2]-p1[2]; for (vtkIdType k = 2; k < cellSize; k++) { index = cellSize*0.25; existingPoints->GetPoint(cell[index], p1); index = cellSize*0.75; existingPoints->GetPoint(cell[index], p2); v2[0] = p2[0]-p1[0]; v2[1] = p2[1]-p1[1]; v2[2] = p2[2]-p1[2]; vtkMath::Cross(v1,v2,polygonNormal); if (vtkMath::Norm(polygonNormal) != 0) break; } vtkMath::Normalize(polygonNormal); //Now we start computing the normal for each vertex double vertexNormalTemp[3]; existingPoints->GetPoint(cell[0], p1); existingPoints->GetPoint(cell[1], p2); v1[0] = p2[0]-p1[0]; v1[1] = p2[1]-p1[1]; v1[2] = p2[2]-p1[2]; vtkMath::Cross(v1,polygonNormal,vertexNormalTemp); vtkMath::Normalize(vertexNormalTemp); double vertexNormal[3]; for (vtkIdType j = 0; j < cellSize-2; j++) { existingPoints->GetPoint(cell[j+1], p1); existingPoints->GetPoint(cell[j+2], p2); v1[0] = p2[0]-p1[0]; v1[1] = p2[1]-p1[1]; v1[2] = p2[2]-p1[2]; vtkMath::Cross(v1,polygonNormal,vertexNormal); vtkMath::Normalize(vertexNormal); double finalNormal[3]; finalNormal[0] = (vertexNormal[0] + vertexNormalTemp[0])*0.5; finalNormal[1] = (vertexNormal[1] + vertexNormalTemp[1])*0.5; finalNormal[2] = (vertexNormal[2] + vertexNormalTemp[2])*0.5; //Here we determine the direction of the normal if (m_SegmentationBinaryImage) { Point3D worldCoord; worldCoord[0] = p1[0]+finalNormal[0]*m_MaxSpacing; worldCoord[1] = p1[1]+finalNormal[1]*m_MaxSpacing; worldCoord[2] = p1[2]+finalNormal[2]*m_MaxSpacing; double val = 0.0; mitk::ImagePixelReadAccessor readAccess(m_SegmentationBinaryImage); itk::Index<3> idx; m_SegmentationBinaryImage->GetGeometry()->WorldToIndex(worldCoord, idx); try { val = readAccess.GetPixelByIndexSafe(idx); } catch (mitk::Exception e) { // If value is outside the image's region ignore it } if (val == 0.0) { ++m_PositiveNormalCounter; } else { ++m_NegativeNormalCounter; } } vertexNormalTemp[0] = vertexNormal[0]; vertexNormalTemp[1] = vertexNormal[1]; vertexNormalTemp[2] = vertexNormal[2]; vtkIdType id = cell[j+1]; normals->SetTuple(id,finalNormal); } existingPoints->GetPoint(cell[0], p1); existingPoints->GetPoint(cell[1], p2); v1[0] = p2[0]-p1[0]; v1[1] = p2[1]-p1[1]; v1[2] = p2[2]-p1[2]; vtkMath::Cross(v1,polygonNormal,vertexNormal); vtkMath::Normalize(vertexNormal); vertexNormal[0] = (vertexNormal[0] + vertexNormalTemp[0])*0.5; vertexNormal[1] = (vertexNormal[1] + vertexNormalTemp[1])*0.5; vertexNormal[2] = (vertexNormal[2] + vertexNormalTemp[2])*0.5; vtkIdType id = cell[0]; normals->SetTuple(id,vertexNormal); id = cell[cellSize-1]; normals->SetTuple(id,vertexNormal); if(m_NegativeNormalCounter > m_PositiveNormalCounter) { for(vtkIdType n = 0; n < cellSize; n++) { double normal[3]; normals->GetTuple(offSet+n, normal); normal[0] = (-1)*normal[0]; normal[1] = (-1)*normal[1]; normal[2] = (-1)*normal[2]; normals->SetTuple(offSet+n, normal); } } m_NegativeNormalCounter = 0; m_PositiveNormalCounter = 0; offSet += cellSize; }//end for all cells Surface::Pointer surface = this->GetOutput(i); surface->GetVtkPolyData()->GetCellData()->SetNormals(normals); }//end for all inputs //Setting progressbar if (this->m_UseProgressBar) mitk::ProgressBar::GetInstance()->Progress(this->m_ProgressStepSize); } mitk::Surface::Pointer mitk::ComputeContourSetNormalsFilter::GetNormalsAsSurface() { //Just for debugging: vtkSmartPointer newPolyData = vtkSmartPointer::New(); vtkSmartPointer newLines = vtkSmartPointer::New(); vtkSmartPointer newPoints = vtkSmartPointer::New(); unsigned int idCounter (0); //Debug end for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs(); i++) { Surface* currentSurface = const_cast( this->GetOutput(i) ); vtkPolyData* polyData = currentSurface->GetVtkPolyData(); vtkSmartPointer currentCellNormals = vtkDoubleArray::SafeDownCast(polyData->GetCellData()->GetNormals()); vtkSmartPointer existingPolys = polyData->GetPolys(); vtkSmartPointer existingPoints = polyData->GetPoints(); existingPolys->InitTraversal(); vtkIdType* cell (NULL); vtkIdType cellSize (0); for( existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);) { for ( vtkIdType j = 0; j < cellSize; j++ ) { double currentNormal[3]; currentCellNormals->GetTuple(cell[j], currentNormal); vtkSmartPointer line = vtkSmartPointer::New(); line->GetPointIds()->SetNumberOfIds(2); double newPoint[3]; double p0[3]; existingPoints->GetPoint(cell[j], p0); newPoint[0] = p0[0] + currentNormal[0]; newPoint[1] = p0[1] + currentNormal[1]; newPoint[2] = p0[2] + currentNormal[2]; line->GetPointIds()->SetId(0, idCounter); newPoints->InsertPoint(idCounter, p0); idCounter++; line->GetPointIds()->SetId(1, idCounter); newPoints->InsertPoint(idCounter, newPoint); idCounter++; newLines->InsertNextCell(line); }//end for all points }//end for all cells }//end for all outputs newPolyData->SetPoints(newPoints); newPolyData->SetLines(newLines); newPolyData->BuildCells(); mitk::Surface::Pointer surface = mitk::Surface::New(); surface->SetVtkPolyData(newPolyData); return surface; } void mitk::ComputeContourSetNormalsFilter::SetMaxSpacing(double maxSpacing) { m_MaxSpacing = maxSpacing; } void mitk::ComputeContourSetNormalsFilter::GenerateOutputInformation() { Superclass::GenerateOutputInformation(); } void mitk::ComputeContourSetNormalsFilter::Reset() { for (unsigned int i = 0; i < this->GetNumberOfIndexedInputs(); i++) { this->PopBackInput(); } this->SetNumberOfIndexedInputs(0); this->SetNumberOfIndexedOutputs(0); mitk::Surface::Pointer output = mitk::Surface::New(); this->SetNthOutput(0, output.GetPointer()); } void mitk::ComputeContourSetNormalsFilter::SetUseProgressBar(bool status) { this->m_UseProgressBar = status; } void mitk::ComputeContourSetNormalsFilter::SetProgressStepSize(unsigned int stepSize) { this->m_ProgressStepSize = stepSize; } diff --git a/Modules/SurfaceInterpolation/mitkPointCloudScoringFilter.cpp b/Modules/SurfaceInterpolation/mitkPointCloudScoringFilter.cpp new file mode 100644 index 0000000000..ba07f1ff6e --- /dev/null +++ b/Modules/SurfaceInterpolation/mitkPointCloudScoringFilter.cpp @@ -0,0 +1,134 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkPointCloudScoringFilter.h" + +#include +#include +#include +#include +#include + +mitk::PointCloudScoringFilter::PointCloudScoringFilter(): + m_NumberOfOutpPoints(0) +{ + m_OutpGrid = mitk::UnstructuredGrid::New(); + + this->SetNthOutput(0, m_OutpGrid); +} + +mitk::PointCloudScoringFilter::~PointCloudScoringFilter(){} + +void mitk::PointCloudScoringFilter::GenerateData() +{ + if(UnstructuredGridToUnstructuredGridFilter::GetNumberOfInputs()!=2) + { + MITK_ERROR << "Not enough input arguments for PointCloudScoringFilter" << std::endl; + return; + } + + DataObjectPointerArray inputs = UnstructuredGridToUnstructuredGridFilter::GetInputs(); + mitk::UnstructuredGrid::Pointer edgeGrid = dynamic_cast(inputs.at(0).GetPointer()); + mitk::UnstructuredGrid::Pointer segmGrid = dynamic_cast(inputs.at(1).GetPointer()); + + if(edgeGrid->IsEmpty() || segmGrid->IsEmpty()) + { + if(edgeGrid->IsEmpty()) + MITK_ERROR << "Cannot convert edgeGrid into Surfaces" << std::endl; + if(segmGrid->IsEmpty()) + MITK_ERROR << "Cannot convert segmGrid into Surfaces" << std::endl; + } + + vtkSmartPointer edgevtkGrid = edgeGrid->GetVtkUnstructuredGrid(); + vtkSmartPointer segmvtkGrid = segmGrid->GetVtkUnstructuredGrid(); + + // KdTree from here + vtkSmartPointer kdPoints = vtkSmartPointer::New(); + vtkSmartPointer kdTree = vtkSmartPointer::New(); + + for(int i=0; iGetNumberOfPoints(); i++) + { + kdPoints->InsertNextPoint(edgevtkGrid->GetPoint(i)); + } + + kdTree->BuildLocatorFromPoints(kdPoints); + // KdTree until here + + vtkSmartPointer points = vtkSmartPointer::New(); + + for(int i=0; iGetNumberOfPoints(); i++) + { + points->InsertNextPoint(segmvtkGrid->GetPoint(i)); + } + + std::vector< ScorePair > score; + + double dist_glob = 0.0; + double dist = 0.0; + + for(int i=0; iGetNumberOfPoints(); i++) + { + double point[3]; + points->GetPoint(i,point); + kdTree->FindClosestPoint(point[0],point[1],point[2],dist); + dist_glob+=dist; + score.push_back(std::make_pair(i,dist)); + } + + double avg = dist_glob / points->GetNumberOfPoints(); + + for(unsigned int i=0; i avg) + { + m_FilteredScores.push_back(std::make_pair(score.at(i).first,score.at(i).second)); + } + } + + m_NumberOfOutpPoints = m_FilteredScores.size(); + + vtkSmartPointer filteredPoints = vtkSmartPointer::New(); + + for(unsigned int i=0; iGetPoint(m_FilteredScores.at(i).first); + filteredPoints->InsertNextPoint(point[0],point[1],point[2]); + } + + unsigned int numPoints = filteredPoints->GetNumberOfPoints(); + + vtkSmartPointer verts = vtkSmartPointer::New(); + + verts->GetPointIds()->SetNumberOfIds(numPoints); + for(unsigned int i=0; iGetPointIds()->SetId(i,i); + } + + vtkSmartPointer uGrid = vtkSmartPointer::New(); + uGrid->Allocate(1); + + uGrid->InsertNextCell(verts->GetCellType(), verts->GetPointIds()); + uGrid->SetPoints(filteredPoints); + + m_OutpGrid->SetVtkUnstructuredGrid(uGrid); +} + +void mitk::PointCloudScoringFilter::GenerateOutputInformation() +{ + Superclass::GenerateOutputInformation(); +} diff --git a/Modules/SurfaceInterpolation/mitkPointCloudScoringFilter.h b/Modules/SurfaceInterpolation/mitkPointCloudScoringFilter.h new file mode 100644 index 0000000000..0bc3ba55cf --- /dev/null +++ b/Modules/SurfaceInterpolation/mitkPointCloudScoringFilter.h @@ -0,0 +1,89 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef mitkPointCloudScoringFilter_h_Included +#define mitkPointCloudScoringFilter_h_Included + +#include +#include + + +namespace mitk +{ + +class UnstructuredGrid; + +/** + * @brief Scores an UnstructuredGrid as good as one matches to the other. + * + * The result UnstructureGrid of the filter are the points where the distance to + * the closest point of the other UnstructuredGrid is higher than the average + * distance from all points to their closest neighbours of the other + * UnstructuredGrid. + * The second input is the UnstructuredGrid, which you want to score. All Points + * of the output UnstructuredGrid are from the second input. + */ +class MITKSURFACEINTERPOLATION_EXPORT PointCloudScoringFilter: + public UnstructuredGridToUnstructuredGridFilter +{ + +public: + + typedef std::pair ScorePair; + + mitkClassMacro( PointCloudScoringFilter, UnstructuredGridToUnstructuredGridFilter) + + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + /** Number of Points of the scored UnstructuredGrid. These points are far away + * from their neighbours */ + itkGetMacro(NumberOfOutpPoints, int) + + /** A vector in which the point IDs and their distance to their neighbours + * is stored */ + itkGetMacro(FilteredScores, std::vector< ScorePair >) + +protected: + + /** is called by the Update() method */ + virtual void GenerateData(); + + /** Defines the output */ + virtual void GenerateOutputInformation(); + + /** Constructor */ + PointCloudScoringFilter(); + + /** Destructor */ + virtual ~PointCloudScoringFilter(); + +private: + + /** The output UnstructuredGrid containing the scored points, which are far + * aways from their neighbours */ + mitk::UnstructuredGrid::Pointer m_OutpGrid; + + /** The Point IDs and their distance to their neighbours */ + std::vector< ScorePair > m_FilteredScores; + + /** The number of points which are far aways from their neighbours */ + int m_NumberOfOutpPoints; + +}; + +} +#endif diff --git a/Modules/ToFHardware/mitkToFCameraMITKPlayerController.cpp b/Modules/ToFHardware/mitkToFCameraMITKPlayerController.cpp index 09eb056459..48f10e8959 100644 --- a/Modules/ToFHardware/mitkToFCameraMITKPlayerController.cpp +++ b/Modules/ToFHardware/mitkToFCameraMITKPlayerController.cpp @@ -1,338 +1,337 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include // mitk includes -#include "mitkItkImageFileReader.h" #include "mitkIOUtil.h" #include #include "mitkImageReadAccessor.h" namespace mitk { ToFCameraMITKPlayerController::ToFCameraMITKPlayerController() : m_PixelNumber(0), m_RGBPixelNumber(0), m_NumberOfBytes(0), m_NumberOfRGBBytes(0), m_CaptureWidth(0), m_CaptureHeight(0), m_RGBCaptureWidth(0), m_RGBCaptureHeight(0), m_ConnectionCheck(false), m_InputFileName(""), m_ToFImageType(ToFImageType3D), m_DistanceImage(0), m_AmplitudeImage(0), m_IntensityImage(0), m_RGBImage(0), m_DistanceInfile(NULL), m_AmplitudeInfile(NULL), m_IntensityInfile(NULL), m_RGBInfile(NULL), m_IntensityArray(NULL), m_DistanceArray(NULL), m_AmplitudeArray(NULL), m_RGBArray(NULL), m_DistanceImageFileName(""), m_AmplitudeImageFileName(""), m_IntensityImageFileName(""), m_RGBImageFileName(""), m_PixelStartInFile(0), m_CurrentFrame(-1), m_NumOfFrames(0) { m_ImageStatus = std::vector(4,true); } ToFCameraMITKPlayerController::~ToFCameraMITKPlayerController() { this->CleanUp(); } void ToFCameraMITKPlayerController::CleanUp() { if(m_DistanceImage.IsNotNull()) { m_DistanceImage->ReleaseData(); m_DistanceImage = NULL; } if(m_AmplitudeImage.IsNotNull()) { m_AmplitudeImage->ReleaseData(); m_AmplitudeImage = NULL; } if(m_IntensityImage.IsNotNull()) { m_IntensityImage->ReleaseData(); m_IntensityImage = NULL; } if(m_RGBImage.IsNotNull()) { m_RGBImage->ReleaseData(); m_RGBImage = NULL; } delete[] this->m_DistanceArray; this->m_DistanceArray = NULL; delete[] this->m_AmplitudeArray; this->m_AmplitudeArray = NULL; delete[] this->m_IntensityArray; this->m_IntensityArray = NULL; delete[] this->m_RGBArray; this->m_RGBArray = NULL; this->m_DistanceImageFileName = ""; this->m_AmplitudeImageFileName = ""; this->m_IntensityImageFileName = ""; this->m_RGBImageFileName = ""; } bool ToFCameraMITKPlayerController::OpenCameraConnection() { if(!this->m_ConnectionCheck) { // reset the image status before connection m_ImageStatus = std::vector(4,true); try { if (this->m_DistanceImageFileName.empty() && this->m_AmplitudeImageFileName.empty() && this->m_IntensityImageFileName.empty() && this->m_RGBImageFileName.empty()) { throw std::logic_error("No image data file names set"); } if (!this->m_DistanceImageFileName.empty()) { m_DistanceImage = mitk::IOUtil::LoadImage(this->m_DistanceImageFileName); } else { MITK_ERROR << "ToF distance image data file empty"; } if (!this->m_AmplitudeImageFileName.empty()) { m_AmplitudeImage = mitk::IOUtil::LoadImage(this->m_AmplitudeImageFileName); } else { MITK_WARN << "ToF amplitude image data file empty"; } if (!this->m_IntensityImageFileName.empty()) { m_IntensityImage = mitk::IOUtil::LoadImage(this->m_IntensityImageFileName); } else { MITK_WARN << "ToF intensity image data file empty"; } if (!this->m_RGBImageFileName.empty()) { m_RGBImage = mitk::IOUtil::LoadImage(this->m_RGBImageFileName); } else { MITK_WARN << "ToF RGB image data file empty"; } // check if the opened files contained data if(m_DistanceImage.IsNull()) { m_ImageStatus.at(0) = false; } if(m_AmplitudeImage.IsNull()) { m_ImageStatus.at(1) = false; } if(m_IntensityImage.IsNull()) { m_ImageStatus.at(2) = false; } if(m_RGBImage.IsNull()) { m_ImageStatus.at(3) = false; } // Check for dimension type mitk::Image::Pointer infoImage = NULL; if(m_ImageStatus.at(0)) { infoImage = m_DistanceImage; } else if (m_ImageStatus.at(1)) { infoImage = m_AmplitudeImage; } else if(m_ImageStatus.at(2)) { infoImage = m_IntensityImage; } else if(m_ImageStatus.at(3)) { infoImage = m_RGBImage; } if (infoImage->GetDimension() == 2) this->m_ToFImageType = ToFImageType2DPlusT; else if (infoImage->GetDimension() == 3) this->m_ToFImageType = ToFImageType3D; else if (infoImage->GetDimension() == 4) this->m_ToFImageType = ToFImageType2DPlusT; else throw std::logic_error("Error opening ToF data file: Invalid dimension."); this->m_CaptureWidth = infoImage->GetDimension(0); this->m_CaptureHeight = infoImage->GetDimension(1); this->m_PixelNumber = this->m_CaptureWidth*this->m_CaptureHeight; this->m_NumberOfBytes = this->m_PixelNumber * sizeof(float); if(m_RGBImage) { m_RGBCaptureWidth = m_RGBImage->GetDimension(0); m_RGBCaptureHeight = m_RGBImage->GetDimension(1); m_RGBPixelNumber = m_RGBCaptureWidth * m_RGBCaptureHeight; m_NumberOfRGBBytes = m_RGBPixelNumber * 3; } if (this->m_ToFImageType == ToFImageType2DPlusT) { this->m_NumOfFrames = infoImage->GetDimension(3); } else { this->m_NumOfFrames = infoImage->GetDimension(2); } // allocate buffer this->m_DistanceArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_DistanceArray[i]=0.0;} this->m_AmplitudeArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_AmplitudeArray[i]=0.0;} this->m_IntensityArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_IntensityArray[i]=0.0;} this->m_RGBArray = new unsigned char[m_NumberOfRGBBytes]; for(int i=0; im_RGBArray[i]=0.0;} MITK_INFO << "NumOfFrames: " << this->m_NumOfFrames; this->m_ConnectionCheck = true; return this->m_ConnectionCheck; } catch(std::exception& e) { MITK_ERROR << "Error opening ToF data file " << this->m_InputFileName << " " << e.what(); throw std::logic_error("Error opening ToF data file"); return false; } } else return this->m_ConnectionCheck; } bool ToFCameraMITKPlayerController::CloseCameraConnection() { if (this->m_ConnectionCheck) { this->CleanUp(); this->m_ConnectionCheck = false; return true; } return false; } void ToFCameraMITKPlayerController::UpdateCamera() { this->m_CurrentFrame++; if(this->m_CurrentFrame >= this->m_NumOfFrames) { this->m_CurrentFrame = 0; } if(this->m_ImageStatus.at(0)) { this->AccessData(this->m_CurrentFrame, this->m_DistanceImage, this->m_DistanceArray); } if(this->m_ImageStatus.at(1)) { this->AccessData(this->m_CurrentFrame, this->m_AmplitudeImage, this->m_AmplitudeArray); } if(this->m_ImageStatus.at(2)) { this->AccessData(this->m_CurrentFrame, this->m_IntensityImage, this->m_IntensityArray); } if(this->m_ImageStatus.at(3)) { if(!this->m_ToFImageType) { ImageReadAccessor rgbAcc(m_RGBImage, m_RGBImage->GetSliceData(m_CurrentFrame)); memcpy(m_RGBArray, rgbAcc.GetData(), m_NumberOfRGBBytes ); } else if(this->m_ToFImageType) { ImageReadAccessor rgbAcc(m_RGBImage, m_RGBImage->GetVolumeData(m_CurrentFrame)); memcpy(m_RGBArray, rgbAcc.GetData(), m_NumberOfRGBBytes); } } itksys::SystemTools::Delay(50); } void ToFCameraMITKPlayerController::AccessData(int frame, Image::Pointer image, float* &data) { if(!this->m_ToFImageType) { ImageReadAccessor imgAcc(image, image->GetSliceData(frame)); memcpy(data, imgAcc.GetData(), this->m_NumberOfBytes ); } else if(this->m_ToFImageType) { ImageReadAccessor imgAcc(image, image->GetVolumeData(frame)); memcpy(data, imgAcc.GetData(), this->m_NumberOfBytes); } } void ToFCameraMITKPlayerController::GetAmplitudes(float* amplitudeArray) { memcpy(amplitudeArray, this->m_AmplitudeArray, this->m_NumberOfBytes); } void ToFCameraMITKPlayerController::GetIntensities(float* intensityArray) { memcpy(intensityArray, this->m_IntensityArray, this->m_NumberOfBytes); } void ToFCameraMITKPlayerController::GetDistances(float* distanceArray) { memcpy(distanceArray, this->m_DistanceArray, this->m_NumberOfBytes); } void ToFCameraMITKPlayerController::GetRgb(unsigned char* rgbArray) { memcpy(rgbArray, this->m_RGBArray, m_NumberOfRGBBytes); } void ToFCameraMITKPlayerController::SetInputFileName(std::string inputFileName) { this->m_InputFileName = inputFileName; } } diff --git a/Modules/US/Testing/mitkUSImageLoggingFilterTest.cpp b/Modules/US/Testing/mitkUSImageLoggingFilterTest.cpp index 113df66d9e..560f43cbf7 100644 --- a/Modules/US/Testing/mitkUSImageLoggingFilterTest.cpp +++ b/Modules/US/Testing/mitkUSImageLoggingFilterTest.cpp @@ -1,184 +1,212 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkUSImageLoggingFilter.h" #include #include #include #include +#include +#include +#include + #include "mitkImageGenerator.h" #include "itksys/SystemTools.hxx" #include "Poco/File.h" class mitkUSImageLoggingFilterTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkUSImageLoggingFilterTestSuite); MITK_TEST(TestInstantiation); + MITK_TEST(TestSetFileExtension); + MITK_TEST(TestSetWrongFileExtension); MITK_TEST(TestSavingValidTestImage); MITK_TEST(TestSavingAfterMupltipleUpdateCalls); MITK_TEST(TestFilterWithEmptyImages); MITK_TEST(TestFilterWithInvalidPath); - MITK_TEST(TestWrongImageFileExtensions); MITK_TEST(TestJpgFileExtension); CPPUNIT_TEST_SUITE_END(); private: mitk::USImageLoggingFilter::Pointer m_TestFilter; std::string m_TemporaryTestDirectory; mitk::Image::Pointer m_RandomRestImage1; mitk::Image::Pointer m_RandomRestImage2; mitk::Image::Pointer m_RandomSingleSliceImage; mitk::Image::Pointer m_RealTestImage; public: void setUp() { m_TestFilter = mitk::USImageLoggingFilter::New(); m_TemporaryTestDirectory = mitk::IOUtil::GetTempPath(); m_RandomRestImage1 = mitk::ImageGenerator::GenerateRandomImage(100, 100, 100, 1, 0.2, 0.3, 0.4); m_RandomRestImage2 = mitk::ImageGenerator::GenerateRandomImage(100, 100, 100, 1, 0.2, 0.3, 0.4); m_RandomSingleSliceImage = mitk::ImageGenerator::GenerateRandomImage(100, 100, 1, 1, 0.2, 0.3, 0.4); m_RealTestImage = mitk::IOUtil::LoadImage(GetTestDataFilePath("Pic3D.nrrd")); } void tearDown() { m_TestFilter = NULL; m_RandomRestImage1 = NULL; m_RandomRestImage2 = NULL; m_RealTestImage = NULL; m_RandomSingleSliceImage = NULL; } void TestInstantiation() { CPPUNIT_ASSERT_MESSAGE("Testing instantiation",m_TestFilter.IsNotNull()); } void TestSavingValidTestImage() { //######################## Test with valid test images ################################ m_TestFilter->SetInput(m_RandomRestImage1); m_TestFilter->SetInput("secondImage",m_RandomRestImage2); m_TestFilter->Update(); MITK_TEST_OUTPUT(<<"Tested method Update() with valid data."); std::vector filenames; std::string csvFileName; m_TestFilter->SaveImages(m_TemporaryTestDirectory,filenames,csvFileName); MITK_TEST_OUTPUT(<<"Tested method SaveImages(...)."); CPPUNIT_ASSERT_MESSAGE("Testing if correct number of images was saved",filenames.size() == 1); CPPUNIT_ASSERT_MESSAGE("Testing if image file exists",Poco::File(filenames.at(0).c_str()).exists()); CPPUNIT_ASSERT_MESSAGE("Testing if csv file exists",Poco::File(csvFileName.c_str()).exists()); //clean up std::remove(filenames.at(0).c_str()); std::remove(csvFileName.c_str()); } void TestSavingAfterMupltipleUpdateCalls() { //######################## Test multiple calls of update ################################ m_TestFilter->SetInput(m_RandomRestImage1); m_TestFilter->SetInput("secondImage",m_RandomRestImage2); for(int i=0; i<5; i++) { m_TestFilter->Update(); std::stringstream testmessage; testmessage << "testmessage" << i; m_TestFilter->AddMessageToCurrentImage(testmessage.str()); itksys::SystemTools::Delay(50); } MITK_TEST_OUTPUT(<<"Call Update() 5 times."); std::vector filenames; std::string csvFileName; m_TestFilter->SaveImages(m_TemporaryTestDirectory,filenames,csvFileName); MITK_TEST_OUTPUT(<<"Tested method SaveImages(...)."); CPPUNIT_ASSERT_MESSAGE("Testing if correct number of images was saved",filenames.size() == 5); CPPUNIT_ASSERT_MESSAGE("Testing if file 1 exists",Poco::File(filenames.at(0).c_str()).exists()); CPPUNIT_ASSERT_MESSAGE("Testing if file 2 exists",Poco::File(filenames.at(1).c_str()).exists()); CPPUNIT_ASSERT_MESSAGE("Testing if file 3 exists",Poco::File(filenames.at(2).c_str()).exists()); CPPUNIT_ASSERT_MESSAGE("Testing if file 4 exists",Poco::File(filenames.at(3).c_str()).exists()); CPPUNIT_ASSERT_MESSAGE("Testing if file 5 exists",Poco::File(filenames.at(4).c_str()).exists()); CPPUNIT_ASSERT_MESSAGE("Testing if csv file exists",Poco::File(csvFileName.c_str()).exists()); //clean up for(size_t i=0; iSetInput(testImage); CPPUNIT_ASSERT_MESSAGE("Testing SetInput(...) for first input.",m_TestFilter->GetNumberOfInputs()==1); m_TestFilter->SetInput("secondImage",testImage2); CPPUNIT_ASSERT_MESSAGE("Testing SetInput(...) for second input.",m_TestFilter->GetNumberOfInputs()==2); //images are empty, but update method should not crash CPPUNIT_ASSERT_NO_THROW_MESSAGE("Tested method Update() with invalid data.",m_TestFilter->Update()); } void TestFilterWithInvalidPath() { #ifdef WIN32 std::string filename = "XV:/342INVALID<>"; //invalid filename for windows #else std::string filename = "/dsfdsf:$�$342INVALID"; //invalid filename for linux #endif m_TestFilter->SetInput(m_RealTestImage); m_TestFilter->Update(); CPPUNIT_ASSERT_THROW_MESSAGE("Testing if correct exception if thrown if an invalid path is given.", m_TestFilter->SaveImages(filename), mitk::Exception); } - void TestWrongImageFileExtensions() - { - CPPUNIT_ASSERT_MESSAGE("Testing invalid extension.",!m_TestFilter->SetImageFilesExtension(".INVALID")); - } - void TestJpgFileExtension() { CPPUNIT_ASSERT_MESSAGE("Testing setting of jpg extension.",m_TestFilter->SetImageFilesExtension(".jpg")); m_TestFilter->SetInput(m_RandomSingleSliceImage); m_TestFilter->Update(); std::vector filenames; std::string csvFileName; m_TestFilter->SaveImages(m_TemporaryTestDirectory,filenames,csvFileName); CPPUNIT_ASSERT_MESSAGE("Testing if correct number of images was saved",filenames.size() == 1); CPPUNIT_ASSERT_MESSAGE("Testing if jpg image file exists",Poco::File(filenames.at(0).c_str()).exists()); CPPUNIT_ASSERT_MESSAGE("Testing if csv file exists",Poco::File(csvFileName.c_str()).exists()); //clean up std::remove(filenames.at(0).c_str()); std::remove(csvFileName.c_str()); } + + void TestSetFileExtension() + { + CPPUNIT_ASSERT_MESSAGE("Testing if PIC extension can be set.",m_TestFilter->SetImageFilesExtension("PIC")); + CPPUNIT_ASSERT_MESSAGE("Testing if bmp extension can be set.",m_TestFilter->SetImageFilesExtension("bmp")); + CPPUNIT_ASSERT_MESSAGE("Testing if gdc extension can be set.",m_TestFilter->SetImageFilesExtension("gdcm")); + CPPUNIT_ASSERT_MESSAGE("Testing if dcm extension can be set.",m_TestFilter->SetImageFilesExtension("dcm")); + CPPUNIT_ASSERT_MESSAGE("Testing if dc3 extension can be set.",m_TestFilter->SetImageFilesExtension("dc3")); + CPPUNIT_ASSERT_MESSAGE("Testing if ima extension can be set.",m_TestFilter->SetImageFilesExtension(".ima")); + CPPUNIT_ASSERT_MESSAGE("Testing if img extension can be set.",m_TestFilter->SetImageFilesExtension("img")); + CPPUNIT_ASSERT_MESSAGE("Testing if gip extension can be set.",m_TestFilter->SetImageFilesExtension("gipl")); + CPPUNIT_ASSERT_MESSAGE("Testing if gipl.gz extension can be set.",m_TestFilter->SetImageFilesExtension(".gipl.gz")); + CPPUNIT_ASSERT_MESSAGE("Testing if jpg extension can be set.",m_TestFilter->SetImageFilesExtension("jpg")); + CPPUNIT_ASSERT_MESSAGE("Testing if jpe extension can be set.",m_TestFilter->SetImageFilesExtension("jpeg")); + CPPUNIT_ASSERT_MESSAGE("Testing if pic extension can be set.",m_TestFilter->SetImageFilesExtension("pic")); + } + + void TestSetWrongFileExtension() + { + + CPPUNIT_ASSERT_MESSAGE("Testing if wrong obj extension is recognized",!m_TestFilter->SetImageFilesExtension("obj ")); + CPPUNIT_ASSERT_MESSAGE("Testing if wrong stl extension is recognized",!m_TestFilter->SetImageFilesExtension("stl ")); + CPPUNIT_ASSERT_MESSAGE("Testing if wrong pvtp extension is recognized",!m_TestFilter->SetImageFilesExtension("pvtp")); + CPPUNIT_ASSERT_MESSAGE("Testing if wrong vtp extension is recognized",!m_TestFilter->SetImageFilesExtension("vtp ")); + CPPUNIT_ASSERT_MESSAGE("Testing if wrong vtk extension is recognized",!m_TestFilter->SetImageFilesExtension("vtk ")); + + } + }; MITK_TEST_SUITE_REGISTRATION(mitkUSImageLoggingFilter) diff --git a/Modules/US/USFilters/mitkUSImageLoggingFilter.cpp b/Modules/US/USFilters/mitkUSImageLoggingFilter.cpp index 13c039ca4a..ad7da4d079 100644 --- a/Modules/US/USFilters/mitkUSImageLoggingFilter.cpp +++ b/Modules/US/USFilters/mitkUSImageLoggingFilter.cpp @@ -1,154 +1,165 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkUSImageLoggingFilter.h" #include -#include #include #include +#include +#include +#include +#include + + mitk::USImageLoggingFilter::USImageLoggingFilter() : m_SystemTimeClock(RealTimeClock::New()), m_ImageExtension(".nrrd") { } mitk::USImageLoggingFilter::~USImageLoggingFilter() { } void mitk::USImageLoggingFilter::GenerateData() { mitk::Image::ConstPointer inputImage = this->GetInput(); mitk::Image::Pointer outputImage = this->GetOutput(); if(inputImage.IsNull() || inputImage->IsEmpty()) { MITK_WARN << "Input image is not valid. Cannot save image!"; return; } //a clone is needed for a output and to store it. mitk::Image::Pointer inputClone = inputImage->Clone(); //simply redirecy the input to the output //this->SetNumberOfRequiredOutputs(1); //this->SetNthOutput(0, inputClone->Clone()); //outputImage->Graft(inputImage); //this->SetOutput(this->GetInput()); /*if (!this->GetOutput()->IsInitialized()) { this->SetNumberOfRequiredOutputs(1); mitk::Image::Pointer newOutput = mitk::Image::New(); this->SetNthOutput(0, newOutput); } memcpy(this->GetOutput(),this->GetInput());*/ //this->SetNthOutput(0,inputImage.); //this->AllocateOutputs(); //this->GraftOutput(inputClone); /* if (!this->GetOutput()->IsInitialized()) { mitk::Image::Pointer newOutput = mitk::Image::New(); this->SetNthOutput(0, newOutput); } this->GetOutput()Graft(this->GetInput()); */ m_LoggedImages.push_back(inputClone); m_LoggedMITKSystemTimes.push_back(m_SystemTimeClock->GetCurrentStamp()); } void mitk::USImageLoggingFilter::AddMessageToCurrentImage(std::string message) { m_LoggedMessages.insert(std::make_pair(static_cast(m_LoggedImages.size()-1),message)); } void mitk::USImageLoggingFilter::SaveImages(std::string path) { std::vector dummy1; std::string dummy2; this->SaveImages(path,dummy1,dummy2); } void mitk::USImageLoggingFilter::SaveImages(std::string path, std::vector& filenames, std::string& csvFileName) { filenames = std::vector(); //test if path is valid Poco::Path testPath(path); if(!testPath.isDirectory()) { mitkThrow() << "Attemting to write to directory " << path << " which is not valid! Aborting!"; } //generate a unique ID which is used as part of the filenames, so we avoid to overwrite old files by mistake. mitk::UIDGenerator myGen = mitk::UIDGenerator("",5); std::string uniqueID = myGen.GetUID(); //first: write the images for(size_t i=0; i::iterator it = m_LoggedMessages.find(i); if (m_LoggedMessages.empty() || (it == m_LoggedMessages.end())) os << filenames.at(i) << ";" << m_LoggedMITKSystemTimes.at(i) << ";" << "" << "\n"; else os << filenames.at(i) << ";" << m_LoggedMITKSystemTimes.at(i) << ";" << it->second << "\n"; } //close file fb.close(); } bool mitk::USImageLoggingFilter::SetImageFilesExtension(std::string extension) { - mitk::ImageWriter::Pointer imageWriter = mitk::ImageWriter::New(); - if(!imageWriter->IsExtensionValid(extension)) - { - MITK_WARN << "Extension " << extension << " is not supported; still using " << m_ImageExtension << " as before."; - return false; - } - else + if(extension.compare(0,1,".") == 0) + extension = extension.substr(1,extension.size()-1); + + CoreServicePointer mimeTypeProvider(CoreServices::GetMimeTypeProvider()); + + std::vector mimeTypes = mimeTypeProvider->GetMimeTypesForCategory(IOMimeTypes::CATEGORY_IMAGES()); + + for(std::vector::size_type i = 0 ; i< mimeTypes.size() ; ++i) { - m_ImageExtension = extension; - return true; + std::vector extensions = mimeTypes[i].GetExtensions(); + if (std::find(extensions.begin(), extensions.end(), extension) != extensions.end()) + { + m_ImageExtension = "."+extension; + return true; + } } + return false; } diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake index b4ff345857..907e217cb2 100644 --- a/Plugins/PluginList.cmake +++ b/Plugins/PluginList.cmake @@ -1,51 +1,52 @@ # Plug-ins must be ordered according to their dependencies set(MITK_EXT_PLUGINS org.mitk.core.services:ON org.mitk.gui.common:ON org.mitk.planarfigure:ON org.mitk.core.ext:OFF org.mitk.core.jobs:OFF org.mitk.diffusionimaging:OFF org.mitk.simulation:OFF org.mitk.gui.qt.application:ON org.mitk.gui.qt.coreapplication:OFF org.mitk.gui.qt.ext:OFF org.mitk.gui.qt.extapplication:OFF org.mitk.gui.qt.common:ON org.mitk.gui.qt.stdmultiwidgeteditor:ON org.mitk.gui.qt.common.legacy:OFF org.mitk.gui.qt.cmdlinemodules:OFF org.mitk.gui.qt.diffusionimagingapp:OFF org.mitk.gui.qt.datamanager:ON org.mitk.gui.qt.datamanagerlight:OFF org.mitk.gui.qt.properties:ON org.mitk.gui.qt.basicimageprocessing:OFF org.mitk.gui.qt.dicom:OFF org.mitk.gui.qt.diffusionimaging:OFF org.mitk.gui.qt.dtiatlasapp:OFF org.mitk.gui.qt.geometrytools:OFF org.mitk.gui.qt.igtexamples:OFF org.mitk.gui.qt.igttracking:OFF + org.mitk.gui.qt.igtlplugin:OFF org.mitk.gui.qt.imagecropper:OFF org.mitk.gui.qt.imagenavigator:ON org.mitk.gui.qt.viewnavigator:OFF org.mitk.gui.qt.materialeditor:OFF org.mitk.gui.qt.measurementtoolbox:OFF org.mitk.gui.qt.moviemaker:OFF org.mitk.gui.qt.pointsetinteraction:OFF org.mitk.gui.qt.python:OFF org.mitk.gui.qt.registration:OFF org.mitk.gui.qt.remeshing:OFF org.mitk.gui.qt.segmentation:OFF org.mitk.gui.qt.simulation:OFF org.mitk.gui.qt.aicpregistration:OFF org.mitk.gui.qt.toftutorial:OFF org.mitk.gui.qt.tofutil:OFF org.mitk.gui.qt.ugvisualization:OFF org.mitk.gui.qt.ultrasound:OFF org.mitk.gui.qt.volumevisualization:OFF org.mitk.gui.qt.eventrecorder:OFF org.mitk.gui.qt.xnat:OFF ) diff --git a/Plugins/org.mitk.diffusionimaging/src/internal/mitkDiffusionImagingActivator.cpp b/Plugins/org.mitk.diffusionimaging/src/internal/mitkDiffusionImagingActivator.cpp index 210aa03fc6..45dc13083a 100644 --- a/Plugins/org.mitk.diffusionimaging/src/internal/mitkDiffusionImagingActivator.cpp +++ b/Plugins/org.mitk.diffusionimaging/src/internal/mitkDiffusionImagingActivator.cpp @@ -1,64 +1,61 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDiffusionImagingActivator.h" #include "QmitkNodeDescriptorManager.h" #include "mitkNodePredicateDataType.h" #include "mitkNodePredicateProperty.h" #include "mitkNodePredicateIsDWI.h" #include #include void mitk::DiffusionImagingActivator::start(ctkPluginContext* context) { Q_UNUSED(context) QmitkNodeDescriptorManager* manager = QmitkNodeDescriptorManager::GetInstance(); mitk::NodePredicateIsDWI::Pointer isDiffusionImage = mitk::NodePredicateIsDWI::New(); 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) } #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) Q_EXPORT_PLUGIN2(org_mitk_diffusionimaging, mitk::DiffusionImagingActivator) #endif diff --git a/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingView.cpp b/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingView.cpp index 60d3d933e7..a9c13105ce 100644 --- a/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingView.cpp +++ b/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingView.cpp @@ -1,1355 +1,1355 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkBasicImageProcessingView.h" // QT includes (GUI) #include #include #include #include #include #include #include // Berry includes (selection service) #include #include // MITK includes (GUI) #include "QmitkStdMultiWidget.h" #include "QmitkDataNodeSelectionProvider.h" #include "mitkDataNodeObject.h" // MITK includes (general) #include "mitkNodePredicateDataType.h" #include "mitkNodePredicateDimension.h" #include "mitkNodePredicateAnd.h" #include "mitkImageTimeSelector.h" #include "mitkVectorImageMapper2D.h" #include "mitkProperties.h" // Includes for image casting between ITK and MITK #include "mitkImageCast.h" #include "mitkITKImageImport.h" // ITK includes (general) #include #include // Morphological Operations #include #include #include #include #include // Smoothing #include #include #include // Threshold #include // Inversion #include // Derivatives #include #include #include // Resampling #include #include #include #include // Image Arithmetics #include #include #include #include // Boolean operations #include #include #include // Flip Image #include #include // Convenient Definitions typedef itk::Image ImageType; typedef itk::Image SegmentationImageType; typedef itk::Image FloatImageType; typedef itk::Image, 3> VectorImageType; typedef itk::BinaryBallStructuringElement BallType; typedef itk::GrayscaleDilateImageFilter DilationFilterType; typedef itk::GrayscaleErodeImageFilter ErosionFilterType; typedef itk::GrayscaleMorphologicalOpeningImageFilter OpeningFilterType; typedef itk::GrayscaleMorphologicalClosingImageFilter ClosingFilterType; typedef itk::MedianImageFilter< ImageType, ImageType > MedianFilterType; typedef itk::DiscreteGaussianImageFilter< ImageType, ImageType> GaussianFilterType; typedef itk::TotalVariationDenoisingImageFilter TotalVariationFilterType; typedef itk::TotalVariationDenoisingImageFilter VectorTotalVariationFilterType; typedef itk::BinaryThresholdImageFilter< ImageType, ImageType > ThresholdFilterType; typedef itk::InvertIntensityImageFilter< ImageType, ImageType > InversionFilterType; typedef itk::GradientMagnitudeRecursiveGaussianImageFilter< ImageType, ImageType > GradientFilterType; typedef itk::LaplacianImageFilter< FloatImageType, FloatImageType > LaplacianFilterType; typedef itk::SobelEdgeDetectionImageFilter< FloatImageType, FloatImageType > SobelFilterType; typedef itk::ResampleImageFilter< ImageType, ImageType > ResampleImageFilterType; typedef itk::ResampleImageFilter< ImageType, ImageType > ResampleImageFilterType2; typedef itk::CastImageFilter< ImageType, FloatImageType > ImagePTypeToFloatPTypeCasterType; typedef itk::AddImageFilter< ImageType, ImageType, ImageType > AddFilterType; typedef itk::SubtractImageFilter< ImageType, ImageType, ImageType > SubtractFilterType; typedef itk::MultiplyImageFilter< ImageType, ImageType, ImageType > MultiplyFilterType; typedef itk::DivideImageFilter< ImageType, ImageType, FloatImageType > DivideFilterType; typedef itk::OrImageFilter< ImageType, ImageType > OrImageFilterType; typedef itk::AndImageFilter< ImageType, ImageType > AndImageFilterType; typedef itk::XorImageFilter< ImageType, ImageType > XorImageFilterType; typedef itk::FlipImageFilter< ImageType > FlipImageFilterType; typedef itk::LinearInterpolateImageFunction< ImageType, double > LinearInterpolatorType; typedef itk::NearestNeighborInterpolateImageFunction< ImageType, double > NearestInterpolatorType; QmitkBasicImageProcessing::QmitkBasicImageProcessing() : QmitkFunctionality(), m_Controls(NULL), m_SelectedImageNode(NULL), m_TimeStepperAdapter(NULL), m_SelectionListener(NULL) { } QmitkBasicImageProcessing::~QmitkBasicImageProcessing() { //berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService(); //if(s) // s->RemoveSelectionListener(m_SelectionListener); } void QmitkBasicImageProcessing::CreateQtPartControl(QWidget *parent) { if (m_Controls == NULL) { m_Controls = new Ui::QmitkBasicImageProcessingViewControls; m_Controls->setupUi(parent); this->CreateConnections(); //setup predictaes for combobox mitk::NodePredicateDimension::Pointer dimensionPredicate = mitk::NodePredicateDimension::New(3); mitk::NodePredicateDataType::Pointer imagePredicate = mitk::NodePredicateDataType::New("Image"); m_Controls->m_ImageSelector2->SetDataStorage(this->GetDefaultDataStorage()); m_Controls->m_ImageSelector2->SetPredicate(mitk::NodePredicateAnd::New(dimensionPredicate, imagePredicate)); } m_Controls->gbTwoImageOps->hide(); m_SelectedImageNode = mitk::DataStorageSelection::New(this->GetDefaultDataStorage(), false); } void QmitkBasicImageProcessing::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->cbWhat1), SIGNAL( activated(int) ), this, SLOT( SelectAction(int) ) ); connect( (QObject*)(m_Controls->btnDoIt), SIGNAL(clicked()),(QObject*) this, SLOT(StartButtonClicked())); connect( (QObject*)(m_Controls->cbWhat2), SIGNAL( activated(int) ), this, SLOT( SelectAction2(int) ) ); connect( (QObject*)(m_Controls->btnDoIt2), SIGNAL(clicked()),(QObject*) this, SLOT(StartButton2Clicked())); connect( (QObject*)(m_Controls->rBOneImOp), SIGNAL( clicked() ), this, SLOT( ChangeGUI() ) ); connect( (QObject*)(m_Controls->rBTwoImOp), SIGNAL( clicked() ), this, SLOT( ChangeGUI() ) ); connect( (QObject*)(m_Controls->cbParam4), SIGNAL( activated(int) ), this, SLOT( SelectInterpolator(int) ) ); } m_TimeStepperAdapter = new QmitkStepperAdapter((QObject*) m_Controls->sliceNavigatorTime, GetActiveStdMultiWidget()->GetTimeNavigationController()->GetTime(), "sliceNavigatorTimeFromBIP"); } void QmitkBasicImageProcessing::Activated() { QmitkFunctionality::Activated(); this->m_Controls->cbWhat1->clear(); this->m_Controls->cbWhat1->insertItem( NOACTIONSELECTED, "Please select operation"); this->m_Controls->cbWhat1->insertItem( CATEGORY_DENOISING, "--- Denoising ---"); this->m_Controls->cbWhat1->insertItem( GAUSSIAN, "Gaussian"); this->m_Controls->cbWhat1->insertItem( MEDIAN, "Median"); this->m_Controls->cbWhat1->insertItem( TOTALVARIATION, "Total Variation"); this->m_Controls->cbWhat1->insertItem( CATEGORY_MORPHOLOGICAL, "--- Morphological ---"); this->m_Controls->cbWhat1->insertItem( DILATION, "Dilation"); this->m_Controls->cbWhat1->insertItem( EROSION, "Erosion"); this->m_Controls->cbWhat1->insertItem( OPENING, "Opening"); this->m_Controls->cbWhat1->insertItem( CLOSING, "Closing"); this->m_Controls->cbWhat1->insertItem( CATEGORY_EDGE_DETECTION, "--- Edge Detection ---"); this->m_Controls->cbWhat1->insertItem( GRADIENT, "Gradient"); this->m_Controls->cbWhat1->insertItem( LAPLACIAN, "Laplacian (2nd Derivative)"); this->m_Controls->cbWhat1->insertItem( SOBEL, "Sobel Operator"); this->m_Controls->cbWhat1->insertItem( CATEGORY_MISC, "--- Misc ---"); this->m_Controls->cbWhat1->insertItem( THRESHOLD, "Threshold"); this->m_Controls->cbWhat1->insertItem( INVERSION, "Image Inversion"); this->m_Controls->cbWhat1->insertItem( DOWNSAMPLING, "Downsampling"); this->m_Controls->cbWhat1->insertItem( FLIPPING, "Flipping"); this->m_Controls->cbWhat1->insertItem( RESAMPLING, "Resample to"); this->m_Controls->cbWhat1->insertItem( RESCALE, "Rescale image values"); this->m_Controls->cbWhat2->clear(); this->m_Controls->cbWhat2->insertItem( TWOIMAGESNOACTIONSELECTED, "Please select on operation" ); this->m_Controls->cbWhat2->insertItem( CATEGORY_ARITHMETIC, "--- Arithmetric operations ---" ); this->m_Controls->cbWhat2->insertItem( ADD, "Add to Image 1:" ); this->m_Controls->cbWhat2->insertItem( SUBTRACT, "Subtract from Image 1:" ); this->m_Controls->cbWhat2->insertItem( MULTIPLY, "Multiply with Image 1:" ); this->m_Controls->cbWhat2->insertItem( RESAMPLE_TO, "Resample Image 1 to fit geometry:" ); this->m_Controls->cbWhat2->insertItem( DIVIDE, "Divide Image 1 by:" ); this->m_Controls->cbWhat2->insertItem( CATEGORY_BOOLEAN, "--- Boolean operations ---" ); this->m_Controls->cbWhat2->insertItem( AND, "AND" ); this->m_Controls->cbWhat2->insertItem( OR, "OR" ); this->m_Controls->cbWhat2->insertItem( XOR, "XOR" ); this->m_Controls->cbParam4->clear(); this->m_Controls->cbParam4->insertItem( LINEAR, "Linear" ); this->m_Controls->cbParam4->insertItem( NEAREST, "Nearest neighbor" ); m_Controls->dsbParam1->hide(); m_Controls->dsbParam2->hide(); m_Controls->dsbParam3->hide(); m_Controls->tlParam3->hide(); m_Controls->tlParam4->hide(); m_Controls->cbParam4->hide(); } //datamanager selection changed void QmitkBasicImageProcessing::OnSelectionChanged(std::vector nodes) { //any nodes there? if (!nodes.empty()) { // reset GUI // this->ResetOneImageOpPanel(); m_Controls->sliceNavigatorTime->setEnabled(false); m_Controls->leImage1->setText("Select an Image in Data Manager"); m_Controls->tlWhat1->setEnabled(false); m_Controls->cbWhat1->setEnabled(false); m_Controls->tlWhat2->setEnabled(false); m_Controls->cbWhat2->setEnabled(false); m_SelectedImageNode->RemoveAllNodes(); //get the selected Node mitk::DataNode* _DataNode = nodes.front(); *m_SelectedImageNode = _DataNode; //try to cast to image mitk::Image::Pointer tempImage = dynamic_cast(m_SelectedImageNode->GetNode()->GetData()); //no image if( tempImage.IsNull() || (tempImage->IsInitialized() == false) ) { m_Controls->leImage1->setText("Not an image."); return; } //2D image if( tempImage->GetDimension() < 3) { m_Controls->leImage1->setText("2D images are not supported."); return; } //image m_Controls->leImage1->setText(QString(m_SelectedImageNode->GetNode()->GetName().c_str())); // button coding if ( tempImage->GetDimension() > 3 ) { m_Controls->sliceNavigatorTime->setEnabled(true); m_Controls->tlTime->setEnabled(true); } m_Controls->tlWhat1->setEnabled(true); m_Controls->cbWhat1->setEnabled(true); m_Controls->tlWhat2->setEnabled(true); m_Controls->cbWhat2->setEnabled(true); } } void QmitkBasicImageProcessing::ChangeGUI() { if(m_Controls->rBOneImOp->isChecked()) { m_Controls->gbTwoImageOps->hide(); m_Controls->gbOneImageOps->show(); } else if(m_Controls->rBTwoImOp->isChecked()) { m_Controls->gbOneImageOps->hide(); m_Controls->gbTwoImageOps->show(); } } void QmitkBasicImageProcessing::ResetOneImageOpPanel() { m_Controls->tlParam1->setText("Param1"); m_Controls->tlParam2->setText("Param2"); m_Controls->cbWhat1->setCurrentIndex(0); m_Controls->tlTime->setEnabled(false); this->ResetParameterPanel(); m_Controls->btnDoIt->setEnabled(false); m_Controls->cbHideOrig->setEnabled(false); } void QmitkBasicImageProcessing::ResetParameterPanel() { m_Controls->tlParam->setEnabled(false); m_Controls->tlParam1->setEnabled(false); m_Controls->tlParam2->setEnabled(false); m_Controls->tlParam3->setEnabled(false); m_Controls->tlParam4->setEnabled(false); m_Controls->sbParam1->setEnabled(false); m_Controls->sbParam2->setEnabled(false); m_Controls->dsbParam1->setEnabled(false); m_Controls->dsbParam2->setEnabled(false); m_Controls->dsbParam3->setEnabled(false); m_Controls->cbParam4->setEnabled(false); m_Controls->sbParam1->setValue(0); m_Controls->sbParam2->setValue(0); m_Controls->dsbParam1->setValue(0); m_Controls->dsbParam2->setValue(0); m_Controls->dsbParam3->setValue(0); m_Controls->sbParam1->show(); m_Controls->sbParam2->show(); m_Controls->dsbParam1->hide(); m_Controls->dsbParam2->hide(); m_Controls->dsbParam3->hide(); m_Controls->cbParam4->hide(); m_Controls->tlParam3->hide(); m_Controls->tlParam4->hide(); } void QmitkBasicImageProcessing::ResetTwoImageOpPanel() { m_Controls->cbWhat2->setCurrentIndex(0); m_Controls->tlImage2->setEnabled(false); m_Controls->m_ImageSelector2->setEnabled(false); m_Controls->btnDoIt2->setEnabled(false); } void QmitkBasicImageProcessing::SelectAction(int action) { if ( ! m_SelectedImageNode->GetNode() ) return; // Prepare GUI this->ResetParameterPanel(); m_Controls->btnDoIt->setEnabled(false); m_Controls->cbHideOrig->setEnabled(false); QString text1 = "No Parameters"; QString text2 = "No Parameters"; QString text3 = "No Parameters"; QString text4 = "No Parameters"; if (action != 19) { m_Controls->dsbParam1->hide(); m_Controls->dsbParam2->hide(); m_Controls->dsbParam3->hide(); m_Controls->tlParam3->hide(); m_Controls->tlParam4->hide(); m_Controls->sbParam1->show(); m_Controls->sbParam2->show(); m_Controls->cbParam4->hide(); } // check which operation the user has selected and set parameters and GUI accordingly switch (action) { case 2: { m_SelectedAction = GAUSSIAN; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "&Variance:"; m_Controls->sbParam1->setMinimum( 0 ); m_Controls->sbParam1->setMaximum( 200 ); m_Controls->sbParam1->setValue( 2 ); break; } case 3: { m_SelectedAction = MEDIAN; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "&Radius:"; m_Controls->sbParam1->setMinimum( 0 ); m_Controls->sbParam1->setMaximum( 200 ); m_Controls->sbParam1->setValue( 3 ); break; } case 4: { m_SelectedAction = TOTALVARIATION; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); m_Controls->tlParam2->setEnabled(true); m_Controls->sbParam2->setEnabled(true); text1 = "Number Iterations:"; text2 = "Regularization\n(Lambda/1000):"; m_Controls->sbParam1->setMinimum( 1 ); m_Controls->sbParam1->setMaximum( 1000 ); m_Controls->sbParam1->setValue( 40 ); m_Controls->sbParam2->setMinimum( 0 ); m_Controls->sbParam2->setMaximum( 100000 ); m_Controls->sbParam2->setValue( 1 ); break; } case 6: { m_SelectedAction = DILATION; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "&Radius:"; m_Controls->sbParam1->setMinimum( 0 ); m_Controls->sbParam1->setMaximum( 200 ); m_Controls->sbParam1->setValue( 3 ); break; } case 7: { m_SelectedAction = EROSION; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "&Radius:"; m_Controls->sbParam1->setMinimum( 0 ); m_Controls->sbParam1->setMaximum( 200 ); m_Controls->sbParam1->setValue( 3 ); break; } case 8: { m_SelectedAction = OPENING; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "&Radius:"; m_Controls->sbParam1->setMinimum( 0 ); m_Controls->sbParam1->setMaximum( 200 ); m_Controls->sbParam1->setValue( 3 ); break; } case 9: { m_SelectedAction = CLOSING; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "&Radius:"; m_Controls->sbParam1->setMinimum( 0 ); m_Controls->sbParam1->setMaximum( 200 ); m_Controls->sbParam1->setValue( 3 ); break; } case 11: { m_SelectedAction = GRADIENT; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "Sigma of Gaussian Kernel:\n(in Image Spacing Units)"; m_Controls->sbParam1->setMinimum( 0 ); m_Controls->sbParam1->setMaximum( 200 ); m_Controls->sbParam1->setValue( 2 ); break; } case 12: { m_SelectedAction = LAPLACIAN; break; } case 13: { m_SelectedAction = SOBEL; break; } case 15: { m_SelectedAction = THRESHOLD; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); m_Controls->tlParam2->setEnabled(true); m_Controls->sbParam2->setEnabled(true); text1 = "Lower threshold:"; text2 = "Upper threshold:"; m_Controls->sbParam1->setMinimum( -100000 ); m_Controls->sbParam1->setMaximum( 100000 ); m_Controls->sbParam1->setValue( 0 ); m_Controls->sbParam2->setMinimum( -100000 ); m_Controls->sbParam2->setMaximum( 100000 ); m_Controls->sbParam2->setValue( 300 ); break; } case 16: { m_SelectedAction = INVERSION; break; } case 17: { m_SelectedAction = DOWNSAMPLING; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "Downsampling by Factor:"; m_Controls->sbParam1->setMinimum( 1 ); m_Controls->sbParam1->setMaximum( 100 ); m_Controls->sbParam1->setValue( 2 ); break; } case 18: { m_SelectedAction = FLIPPING; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "Flip across axis:"; m_Controls->sbParam1->setMinimum( 0 ); m_Controls->sbParam1->setMaximum( 2 ); m_Controls->sbParam1->setValue( 1 ); break; } case 19: { m_SelectedAction = RESAMPLING; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(false); m_Controls->sbParam1->hide(); m_Controls->dsbParam1->show(); m_Controls->dsbParam1->setEnabled(true); m_Controls->tlParam2->setEnabled(true); m_Controls->sbParam2->setEnabled(false); m_Controls->sbParam2->hide(); m_Controls->dsbParam2->show(); m_Controls->dsbParam2->setEnabled(true); m_Controls->tlParam3->show(); m_Controls->tlParam3->setEnabled(true); m_Controls->dsbParam3->show(); m_Controls->dsbParam3->setEnabled(true); m_Controls->tlParam4->show(); m_Controls->tlParam4->setEnabled(true); m_Controls->cbParam4->show(); m_Controls->cbParam4->setEnabled(true); m_Controls->dsbParam1->setMinimum(0.01); m_Controls->dsbParam1->setMaximum(10.0); m_Controls->dsbParam1->setSingleStep(0.1); m_Controls->dsbParam1->setValue(0.3); m_Controls->dsbParam2->setMinimum(0.01); m_Controls->dsbParam2->setMaximum(10.0); m_Controls->dsbParam2->setSingleStep(0.1); m_Controls->dsbParam2->setValue(0.3); m_Controls->dsbParam3->setMinimum(0.01); m_Controls->dsbParam3->setMaximum(10.0); m_Controls->dsbParam3->setSingleStep(0.1); m_Controls->dsbParam3->setValue(1.5); text1 = "x-spacing:"; text2 = "y-spacing:"; text3 = "z-spacing:"; text4 = "Interplation:"; break; } case 20: { m_SelectedAction = RESCALE; m_Controls->dsbParam1->show(); m_Controls->tlParam1->show(); m_Controls->dsbParam1->setEnabled(true); m_Controls->tlParam1->setEnabled(true); m_Controls->dsbParam2->show(); m_Controls->tlParam2->show(); m_Controls->dsbParam2->setEnabled(true); m_Controls->tlParam2->setEnabled(true); text1 = "Output minimum:"; text2 = "Output maximum:"; break; } default: return; } m_Controls->tlParam->setEnabled(true); m_Controls->tlParam1->setText(text1); m_Controls->tlParam2->setText(text2); m_Controls->tlParam3->setText(text3); m_Controls->tlParam4->setText(text4); m_Controls->btnDoIt->setEnabled(true); m_Controls->cbHideOrig->setEnabled(true); } void QmitkBasicImageProcessing::StartButtonClicked() { if(!m_SelectedImageNode->GetNode()) return; this->BusyCursorOn(); mitk::Image::Pointer newImage; try { newImage = dynamic_cast(m_SelectedImageNode->GetNode()->GetData()); } catch ( std::exception &e ) { QString exceptionString = "An error occured during image loading:\n"; exceptionString.append( e.what() ); QMessageBox::warning( NULL, "Basic Image Processing", exceptionString , QMessageBox::Ok, QMessageBox::NoButton ); this->BusyCursorOff(); return; } // check if input image is valid, casting does not throw exception when casting from 'NULL-Object' if ( (! newImage) || (newImage->IsInitialized() == false) ) { this->BusyCursorOff(); QMessageBox::warning( NULL, "Basic Image Processing", "Input image is broken or not initialized. Returning.", QMessageBox::Ok, QMessageBox::NoButton ); return; } // check if operation is done on 4D a image time step if(newImage->GetDimension() > 3) { mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New(); timeSelector->SetInput(newImage); timeSelector->SetTimeNr( ((QmitkSliderNavigatorWidget*)m_Controls->sliceNavigatorTime)->GetPos() ); timeSelector->Update(); newImage = timeSelector->GetOutput(); } // check if image or vector image ImageType::Pointer itkImage = ImageType::New(); VectorImageType::Pointer itkVecImage = VectorImageType::New(); int isVectorImage = newImage->GetPixelType().GetNumberOfComponents(); if(isVectorImage > 1) { CastToItkImage( newImage, itkVecImage ); } else { CastToItkImage( newImage, itkImage ); } std::stringstream nameAddition(""); int param1 = m_Controls->sbParam1->value(); int param2 = m_Controls->sbParam2->value(); double dparam1 = m_Controls->dsbParam1->value(); double dparam2 = m_Controls->dsbParam2->value(); double dparam3 = m_Controls->dsbParam3->value(); try{ switch (m_SelectedAction) { case GAUSSIAN: { GaussianFilterType::Pointer gaussianFilter = GaussianFilterType::New(); gaussianFilter->SetInput( itkImage ); gaussianFilter->SetVariance( param1 ); gaussianFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(gaussianFilter->GetOutput())->Clone(); nameAddition << "_Gaussian_var_" << param1; std::cout << "Gaussian filtering successful." << std::endl; break; } case MEDIAN: { MedianFilterType::Pointer medianFilter = MedianFilterType::New(); MedianFilterType::InputSizeType size; size.Fill(param1); medianFilter->SetRadius( size ); medianFilter->SetInput(itkImage); medianFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(medianFilter->GetOutput())->Clone(); nameAddition << "_Median_radius_" << param1; std::cout << "Median Filtering successful." << std::endl; break; } case TOTALVARIATION: { if(isVectorImage > 1) { VectorTotalVariationFilterType::Pointer TVFilter = VectorTotalVariationFilterType::New(); TVFilter->SetInput( itkVecImage.GetPointer() ); TVFilter->SetNumberIterations(param1); TVFilter->SetLambda(double(param2)/1000.); TVFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(TVFilter->GetOutput())->Clone(); } else { ImagePTypeToFloatPTypeCasterType::Pointer floatCaster = ImagePTypeToFloatPTypeCasterType::New(); floatCaster->SetInput( itkImage ); floatCaster->Update(); FloatImageType::Pointer fImage = floatCaster->GetOutput(); TotalVariationFilterType::Pointer TVFilter = TotalVariationFilterType::New(); TVFilter->SetInput( fImage.GetPointer() ); TVFilter->SetNumberIterations(param1); TVFilter->SetLambda(double(param2)/1000.); TVFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(TVFilter->GetOutput())->Clone(); } nameAddition << "_TV_Iter_" << param1 << "_L_" << param2; std::cout << "Total Variation Filtering successful." << std::endl; break; } case DILATION: { BallType binaryBall; binaryBall.SetRadius( param1 ); binaryBall.CreateStructuringElement(); DilationFilterType::Pointer dilationFilter = DilationFilterType::New(); dilationFilter->SetInput( itkImage ); dilationFilter->SetKernel( binaryBall ); dilationFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(dilationFilter->GetOutput())->Clone(); nameAddition << "_Dilated_by_" << param1; std::cout << "Dilation successful." << std::endl; break; } case EROSION: { BallType binaryBall; binaryBall.SetRadius( param1 ); binaryBall.CreateStructuringElement(); ErosionFilterType::Pointer erosionFilter = ErosionFilterType::New(); erosionFilter->SetInput( itkImage ); erosionFilter->SetKernel( binaryBall ); erosionFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(erosionFilter->GetOutput())->Clone(); nameAddition << "_Eroded_by_" << param1; std::cout << "Erosion successful." << std::endl; break; } case OPENING: { BallType binaryBall; binaryBall.SetRadius( param1 ); binaryBall.CreateStructuringElement(); OpeningFilterType::Pointer openFilter = OpeningFilterType::New(); openFilter->SetInput( itkImage ); openFilter->SetKernel( binaryBall ); openFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(openFilter->GetOutput())->Clone(); nameAddition << "_Opened_by_" << param1; std::cout << "Opening successful." << std::endl; break; } case CLOSING: { BallType binaryBall; binaryBall.SetRadius( param1 ); binaryBall.CreateStructuringElement(); ClosingFilterType::Pointer closeFilter = ClosingFilterType::New(); closeFilter->SetInput( itkImage ); closeFilter->SetKernel( binaryBall ); closeFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(closeFilter->GetOutput())->Clone(); nameAddition << "_Closed_by_" << param1; std::cout << "Closing successful." << std::endl; break; } case GRADIENT: { GradientFilterType::Pointer gradientFilter = GradientFilterType::New(); gradientFilter->SetInput( itkImage ); gradientFilter->SetSigma( param1 ); gradientFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(gradientFilter->GetOutput())->Clone(); nameAddition << "_Gradient_sigma_" << param1; std::cout << "Gradient calculation successful." << std::endl; break; } case LAPLACIAN: { // the laplace filter requires a float type image as input, we need to cast the itkImage // to correct type ImagePTypeToFloatPTypeCasterType::Pointer caster = ImagePTypeToFloatPTypeCasterType::New(); caster->SetInput( itkImage ); caster->Update(); FloatImageType::Pointer fImage = caster->GetOutput(); LaplacianFilterType::Pointer laplacianFilter = LaplacianFilterType::New(); laplacianFilter->SetInput( fImage ); laplacianFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(laplacianFilter->GetOutput())->Clone(); nameAddition << "_Second_Derivative"; std::cout << "Laplacian filtering successful." << std::endl; break; } case SOBEL: { // the sobel filter requires a float type image as input, we need to cast the itkImage // to correct type ImagePTypeToFloatPTypeCasterType::Pointer caster = ImagePTypeToFloatPTypeCasterType::New(); caster->SetInput( itkImage ); caster->Update(); FloatImageType::Pointer fImage = caster->GetOutput(); SobelFilterType::Pointer sobelFilter = SobelFilterType::New(); sobelFilter->SetInput( fImage ); sobelFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(sobelFilter->GetOutput())->Clone(); nameAddition << "_Sobel"; std::cout << "Edge Detection successful." << std::endl; break; } case THRESHOLD: { ThresholdFilterType::Pointer thFilter = ThresholdFilterType::New(); thFilter->SetLowerThreshold(param1 < param2 ? param1 : param2); thFilter->SetUpperThreshold(param2 > param1 ? param2 : param1); thFilter->SetInsideValue(1); thFilter->SetOutsideValue(0); thFilter->SetInput(itkImage); thFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(thFilter->GetOutput())->Clone(); nameAddition << "_Threshold"; std::cout << "Thresholding successful." << std::endl; break; } case INVERSION: { InversionFilterType::Pointer invFilter = InversionFilterType::New(); mitk::ScalarType min = newImage->GetScalarValueMin(); mitk::ScalarType max = newImage->GetScalarValueMax(); invFilter->SetMaximum( max + min ); invFilter->SetInput(itkImage); invFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(invFilter->GetOutput())->Clone(); nameAddition << "_Inverted"; std::cout << "Image inversion successful." << std::endl; break; } case DOWNSAMPLING: { ResampleImageFilterType::Pointer downsampler = ResampleImageFilterType::New(); downsampler->SetInput( itkImage ); NearestInterpolatorType::Pointer interpolator = NearestInterpolatorType::New(); downsampler->SetInterpolator( interpolator ); downsampler->SetDefaultPixelValue( 0 ); ResampleImageFilterType::SpacingType spacing = itkImage->GetSpacing(); spacing *= (double) param1; downsampler->SetOutputSpacing( spacing ); downsampler->SetOutputOrigin( itkImage->GetOrigin() ); downsampler->SetOutputDirection( itkImage->GetDirection() ); ResampleImageFilterType::SizeType size = itkImage->GetLargestPossibleRegion().GetSize(); for ( int i = 0; i < 3; ++i ) { size[i] /= param1; } downsampler->SetSize( size ); downsampler->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(downsampler->GetOutput())->Clone(); nameAddition << "_Downsampled_by_" << param1; std::cout << "Downsampling successful." << std::endl; break; } case FLIPPING: { FlipImageFilterType::Pointer flipper = FlipImageFilterType::New(); flipper->SetInput( itkImage ); itk::FixedArray flipAxes; for(int i=0; i<3; ++i) { if(i == param1) { flipAxes[i] = true; } else { flipAxes[i] = false; } } flipper->SetFlipAxes(flipAxes); flipper->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(flipper->GetOutput())->Clone(); std::cout << "Image flipping successful." << std::endl; break; } case RESAMPLING: { std::string selectedInterpolator; ResampleImageFilterType::Pointer resampler = ResampleImageFilterType::New(); switch (m_SelectedInterpolation) { case LINEAR: { LinearInterpolatorType::Pointer interpolator = LinearInterpolatorType::New(); resampler->SetInterpolator(interpolator); selectedInterpolator = "Linear"; break; } case NEAREST: { NearestInterpolatorType::Pointer interpolator = NearestInterpolatorType::New(); resampler->SetInterpolator(interpolator); selectedInterpolator = "Nearest"; break; } default: { LinearInterpolatorType::Pointer interpolator = LinearInterpolatorType::New(); resampler->SetInterpolator(interpolator); selectedInterpolator = "Linear"; break; } } resampler->SetInput( itkImage ); resampler->SetOutputOrigin( itkImage->GetOrigin() ); ImageType::SizeType input_size = itkImage->GetLargestPossibleRegion().GetSize(); ImageType::SpacingType input_spacing = itkImage->GetSpacing(); ImageType::SizeType output_size; ImageType::SpacingType output_spacing; output_size[0] = input_size[0] * (input_spacing[0] / dparam1); output_size[1] = input_size[1] * (input_spacing[1] / dparam2); output_size[2] = input_size[2] * (input_spacing[2] / dparam3); output_spacing [0] = dparam1; output_spacing [1] = dparam2; output_spacing [2] = dparam3; resampler->SetSize( output_size ); resampler->SetOutputSpacing( output_spacing ); resampler->SetOutputDirection( itkImage->GetDirection() ); resampler->UpdateLargestPossibleRegion(); ImageType::Pointer resampledImage = resampler->GetOutput(); - newImage = mitk::ImportItkImage( resampledImage ); + newImage = mitk::ImportItkImage( resampledImage )->Clone(); nameAddition << "_Resampled_" << selectedInterpolator; std::cout << "Resampling successful." << std::endl; break; } case RESCALE: { FloatImageType::Pointer floatImage = FloatImageType::New(); CastToItkImage( newImage, floatImage ); itk::RescaleIntensityImageFilter::Pointer filter = itk::RescaleIntensityImageFilter::New(); filter->SetInput(0, floatImage); filter->SetOutputMinimum(dparam1); filter->SetOutputMaximum(dparam2); filter->Update(); floatImage = filter->GetOutput(); newImage = mitk::Image::New(); newImage->InitializeByItk(floatImage.GetPointer()); newImage->SetVolume(floatImage->GetBufferPointer()); nameAddition << "_Rescaled"; std::cout << "Rescaling successful." << std::endl; break; } default: this->BusyCursorOff(); return; } } catch (...) { this->BusyCursorOff(); QMessageBox::warning(NULL, "Warning", "Problem when applying filter operation. Check your input..."); return; } newImage->DisconnectPipeline(); // adjust level/window to new image mitk::LevelWindow levelwindow; levelwindow.SetAuto( newImage ); mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); levWinProp->SetLevelWindow( levelwindow ); // compose new image name std::string name = m_SelectedImageNode->GetNode()->GetName(); if (name.find(".pic.gz") == name.size() -7 ) { name = name.substr(0,name.size() -7); } name.append( nameAddition.str() ); // create final result MITK data storage node mitk::DataNode::Pointer result = mitk::DataNode::New(); result->SetProperty( "levelwindow", levWinProp ); result->SetProperty( "name", mitk::StringProperty::New( name.c_str() ) ); result->SetData( newImage ); // for vector images, a different mapper is needed if(isVectorImage > 1) { mitk::VectorImageMapper2D::Pointer mapper = mitk::VectorImageMapper2D::New(); result->SetMapper(1,mapper); } // reset GUI to ease further processing // this->ResetOneImageOpPanel(); // add new image to data storage and set as active to ease further processing GetDefaultDataStorage()->Add( result, m_SelectedImageNode->GetNode() ); if ( m_Controls->cbHideOrig->isChecked() == true ) m_SelectedImageNode->GetNode()->SetProperty( "visible", mitk::BoolProperty::New(false) ); // TODO!! m_Controls->m_ImageSelector1->SetSelectedNode(result); // show the results mitk::RenderingManager::GetInstance()->RequestUpdateAll(); this->BusyCursorOff(); } void QmitkBasicImageProcessing::SelectAction2(int operation) { // check which operation the user has selected and set parameters and GUI accordingly switch (operation) { case 2: m_SelectedOperation = ADD; break; case 3: m_SelectedOperation = SUBTRACT; break; case 4: m_SelectedOperation = MULTIPLY; break; case 5: m_SelectedOperation = DIVIDE; break; case 6: m_SelectedOperation = RESAMPLE_TO; break; case 8: m_SelectedOperation = AND; break; case 9: m_SelectedOperation = OR; break; case 10: m_SelectedOperation = XOR; break; default: // this->ResetTwoImageOpPanel(); return; } m_Controls->tlImage2->setEnabled(true); m_Controls->m_ImageSelector2->setEnabled(true); m_Controls->btnDoIt2->setEnabled(true); } void QmitkBasicImageProcessing::StartButton2Clicked() { mitk::Image::Pointer newImage1 = dynamic_cast (m_SelectedImageNode->GetNode()->GetData()); mitk::Image::Pointer newImage2 = dynamic_cast (m_Controls->m_ImageSelector2->GetSelectedNode()->GetData()); // check if images are valid if( (!newImage1) || (!newImage2) || (newImage1->IsInitialized() == false) || (newImage2->IsInitialized() == false) ) { itkGenericExceptionMacro(<< "At least one of the input images are broken or not initialized. Returning"); return; } this->BusyCursorOn(); // this->ResetTwoImageOpPanel(); // check if 4D image and use filter on correct time step int time = ((QmitkSliderNavigatorWidget*)m_Controls->sliceNavigatorTime)->GetPos(); if(newImage1->GetDimension() > 3) { mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New(); timeSelector->SetInput(newImage1); timeSelector->SetTimeNr( time ); timeSelector->UpdateLargestPossibleRegion(); newImage1 = timeSelector->GetOutput(); newImage1->DisconnectPipeline(); timeSelector->SetInput(newImage2); timeSelector->SetTimeNr( time ); timeSelector->UpdateLargestPossibleRegion(); newImage2 = timeSelector->GetOutput(); newImage2->DisconnectPipeline(); } // reset GUI for better usability // this->ResetTwoImageOpPanel(); ImageType::Pointer itkImage1 = ImageType::New(); ImageType::Pointer itkImage2 = ImageType::New(); CastToItkImage( newImage1, itkImage1 ); CastToItkImage( newImage2, itkImage2 ); // Remove temp image newImage2 = NULL; std::string nameAddition = ""; try { switch (m_SelectedOperation) { case ADD: { AddFilterType::Pointer addFilter = AddFilterType::New(); addFilter->SetInput1( itkImage1 ); addFilter->SetInput2( itkImage2 ); addFilter->UpdateLargestPossibleRegion(); newImage1 = mitk::ImportItkImage(addFilter->GetOutput())->Clone(); nameAddition = "_Added"; } break; case SUBTRACT: { SubtractFilterType::Pointer subFilter = SubtractFilterType::New(); subFilter->SetInput1( itkImage1 ); subFilter->SetInput2( itkImage2 ); subFilter->UpdateLargestPossibleRegion(); newImage1 = mitk::ImportItkImage(subFilter->GetOutput())->Clone(); nameAddition = "_Subtracted"; } break; case MULTIPLY: { MultiplyFilterType::Pointer multFilter = MultiplyFilterType::New(); multFilter->SetInput1( itkImage1 ); multFilter->SetInput2( itkImage2 ); multFilter->UpdateLargestPossibleRegion(); newImage1 = mitk::ImportItkImage(multFilter->GetOutput())->Clone(); nameAddition = "_Multiplied"; } break; case DIVIDE: { DivideFilterType::Pointer divFilter = DivideFilterType::New(); divFilter->SetInput1( itkImage1 ); divFilter->SetInput2( itkImage2 ); divFilter->UpdateLargestPossibleRegion(); newImage1 = mitk::ImportItkImage(divFilter->GetOutput())->Clone(); nameAddition = "_Divided"; } break; case AND: { AndImageFilterType::Pointer andFilter = AndImageFilterType::New(); andFilter->SetInput1( itkImage1 ); andFilter->SetInput2( itkImage2 ); andFilter->UpdateLargestPossibleRegion(); newImage1 = mitk::ImportItkImage(andFilter->GetOutput())->Clone(); nameAddition = "_AND"; break; } case OR: { OrImageFilterType::Pointer orFilter = OrImageFilterType::New(); orFilter->SetInput1( itkImage1 ); orFilter->SetInput2( itkImage2 ); orFilter->UpdateLargestPossibleRegion(); newImage1 = mitk::ImportItkImage(orFilter->GetOutput())->Clone(); nameAddition = "_OR"; break; } case XOR: { XorImageFilterType::Pointer xorFilter = XorImageFilterType::New(); xorFilter->SetInput1( itkImage1 ); xorFilter->SetInput2( itkImage2 ); xorFilter->UpdateLargestPossibleRegion(); newImage1 = mitk::ImportItkImage(xorFilter->GetOutput())->Clone(); nameAddition = "_XOR"; break; } case RESAMPLE_TO: { itk::NearestNeighborInterpolateImageFunction::Pointer nn_interpolator = itk::NearestNeighborInterpolateImageFunction::New(); ResampleImageFilterType2::Pointer resampleFilter = ResampleImageFilterType2::New(); resampleFilter->SetInput( itkImage1 ); resampleFilter->SetReferenceImage( itkImage2 ); resampleFilter->SetUseReferenceImage( true ); resampleFilter->SetInterpolator( nn_interpolator ); resampleFilter->SetDefaultPixelValue( 0 ); try { resampleFilter->UpdateLargestPossibleRegion(); } catch( const itk::ExceptionObject &e) { MITK_WARN << "Updating resampling filter failed. "; MITK_WARN << "REASON: " << e.what(); } ImageType::Pointer resampledImage = resampleFilter->GetOutput(); newImage1 = mitk::ImportItkImage( resampledImage )->Clone(); nameAddition = "_Resampled"; break; } default: std::cout << "Something went wrong..." << std::endl; this->BusyCursorOff(); return; } } catch (const itk::ExceptionObject& e ) { this->BusyCursorOff(); QMessageBox::warning(NULL, "ITK Exception", e.what() ); QMessageBox::warning(NULL, "Warning", "Problem when applying arithmetic operation to two images. Check dimensions of input images."); return; } // disconnect pipeline; images will not be reused newImage1->DisconnectPipeline(); itkImage1 = NULL; itkImage2 = NULL; // adjust level/window to new image and compose new image name mitk::LevelWindow levelwindow; levelwindow.SetAuto( newImage1 ); mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); levWinProp->SetLevelWindow( levelwindow ); std::string name = m_SelectedImageNode->GetNode()->GetName(); if (name.find(".pic.gz") == name.size() -7 ) { name = name.substr(0,name.size() -7); } // create final result MITK data storage node mitk::DataNode::Pointer result = mitk::DataNode::New(); result->SetProperty( "levelwindow", levWinProp ); result->SetProperty( "name", mitk::StringProperty::New( (name + nameAddition ).c_str() )); result->SetData( newImage1 ); GetDefaultDataStorage()->Add( result, m_SelectedImageNode->GetNode() ); // show only the newly created image m_SelectedImageNode->GetNode()->SetProperty( "visible", mitk::BoolProperty::New(false) ); m_Controls->m_ImageSelector2->GetSelectedNode()->SetProperty( "visible", mitk::BoolProperty::New(false) ); // show the newly created image mitk::RenderingManager::GetInstance()->RequestUpdateAll(); this->BusyCursorOff(); } void QmitkBasicImageProcessing::SelectInterpolator(int interpolator) { switch (interpolator) { case 0: { m_SelectedInterpolation = LINEAR; break; } case 1: { m_SelectedInterpolation = NEAREST; break; } } } diff --git a/Plugins/org.mitk.gui.qt.cmdlinemodules/documentation/UserManual/cmdlinemodules.dox b/Plugins/org.mitk.gui.qt.cmdlinemodules/documentation/UserManual/cmdlinemodules.dox index 079451836f..9e485fd10f 100644 --- a/Plugins/org.mitk.gui.qt.cmdlinemodules/documentation/UserManual/cmdlinemodules.dox +++ b/Plugins/org.mitk.gui.qt.cmdlinemodules/documentation/UserManual/cmdlinemodules.dox @@ -1,172 +1,172 @@ /** \page org_mitk_views_cmdlinemodules The Command Line Modules View \imageMacro{cmdlinemodules_Icon.png,"Icon of the Command Line Modules View",2.00} \tableofcontents \section CLIPrefix Contribution This plugin was developed at the Centre For Medical Image Computing (CMIC), part of University College London (UCL) and contributed back to the MITK community with thanks. \section CLIIntroduction Introduction This view provides the facility to run third party command line programs, and load the data back into the DataManager for immediate visualisation. All that is required is that the command line application can be called with an argument of --xml and respond with a valid XML description of the necessary parameters, and currently, that if the program requires images, they must be NifTI images. This view can then generate a Graphical User Interface (GUI) dynamically from the XML to enable the user to interact with the command line application. This provides an easy to use, and potentially very flexible way to integrate almost any third party, medical imaging, command line application. As a high level introduction, this view performs the following steps: \li The view searches for available programs to run, and for each valid module, stores the XML document describing the interface, and populates a searchable list of available programs. \li When a program is selected, the GUI is generated. \li The user can then set the necessary parameters and run the program. \li Multiple programs can be launched in succession and run simultaneously, and where available on the host platform, the user can pause, resume or cancel running jobs and see console output for each job. As a consequence of the very flexible nature of this plugin, these instructions can only describe how to launch command line modules in a general sense. The examples shown have been constructed by downloading the latest version (subversion commit 329) of the NiftyReg package, available here, and described further here. NiftyReg provides valid XML descriptors to enable the integration of the NiftyReg affine (RegAladin) and and non-rigid (RegF3D) image registration algorithms, as well as utility programs to resample an image, and calculate a Jacobian image. These same XML descriptors work within Slicer and MITK based applications. \section CLIPreferences Preferences The first time that the Command Line Modules View is launched, it is advisable to set the user preferences for the view. Please refer to Figure 1. \imageMacro{cmdlinemodules_Preferences.png,"Figure 1. The Command Line Modules Preferences Page",16.00} Each of these preferences is now explained in some detail. \li show debug output: If checked will output more messages to the console for debugging purposes. \li XML validation mode: The user may select a different mode for XML validation. If this is changed, the application will need to be restarted. There are 3 modes available. If the user selects "strict" mode, the XML schema produced by the command line application must exactly conform to this definition. For "none", there will be no validation. For "weak" validation, the application will report errors, but try to carry on and load as many modules as possible. The XML validation errors are available as tool-tips on the tab widget when the module is launched. Many third party modules included with Slicer currently have incorrect XML (typically, mis-ordered XML tags), and so the "weak" or "none" mode may assist in loading them. -By default the "strict" mode is chosen so that only valid modules are loaded. +By default the "weak" mode is chosen so that only valid modules are loaded. \li max concurrent processes: Sets the maximum number of concurrent jobs that can be run via this interface. The default is 4. When the maximum number is reached, the green "Run" button is disabled until a job finishes. The next 7 preferences are to control where the view will search for valid command line programs. By default these are off as the searching process can take a long time and slow down the startup time of the GUI. The options provided are: \li scan home directory: Scan the users home directory. (See QDir::homePath().) \li scan home directory/cli-modules: Scans the sub-directory called cli-modules under the users home directory. \li scan current directory: Scan the current working directory. (See QDir::homePath().) \li scan current directory/cli-modules: Scans the sub-directory called cli-modules under the current working directory. \li scan installation directory: This is the directory where the actual application is stored. \li scan installation directory/cli-modules: Scans the sub-directory called cli-modules under the application installation directory. \li scan CTK_MODULE_LOAD_PATH: Scans the directory or list of directories defined by the environment variable CTK_MODULE_LOAD_PATH. A list is colon separated on Linux/Mac, and semi-colon separated on Windows. In most cases, it is suggested that the user will leave these options unchecked, as the user can also specify custom directories, and even cherry-pick specific command line programs to load. Figure 2 shows a selection box that enables the user to specify custom directories to scan, and Figure 3. shows a selection box that enables the user to select specific modules. Picking specific directories, and specific executables will most likely make the application quicker to launch. \imageMacro{cmdlinemodules_PreferencesAdditionalDirectories.png,"Figure 2. The User can specify specific directories to scan".",7.90} \imageMacro{cmdlinemodules_PreferencesAdditionalModules.png,"Figure 3. The User can specify specific command line programs to load".",7.92} These directory and file selection boxes enable directories or files to be added, removed and updated in a similar fashion. The user must make sure that the list of files selected in the "additional modules" section are not already contained within the directories specified in the "additional module directories" section. In addition, the preferences page provides: \li temporary directory: Images stored in the DataManager are first written to a temporary folder as Nifti images before being passed to each command line program. This temporary directory will default to a platform specific temporary folder, but the user may select their preferred choice of temporary workspace. \section CLIUsage Usage When the view is launched, a simple interface is presented, as shown in Figure 4. \imageMacro{cmdlinemodules_Initial.png,"Figure 4. The initial interface\, with no command line programs available.",8.66} In this example, all the above check-box preferences were off, and the "additional module directories" was empty, and the "additional modules" list was empty so no command line applications were found. The "Search" box displays zero entries, and there is nothing to search. If the available search paths contain programs that are compatible (i.e. runnable) with this view, the name of the programs are displayed in the "Search" box in a nested menu, shown in Figure 5. \imageMacro{cmdlinemodules_WithPrograms.png,"Figure 5. When valid paths are set\, and programs are discovered\, the menu is recalculated to show available programs.",10.54} When a program is selected, the relevant interface is displayed, by default as collapsed group boxes to save space. Each section can be individually expanded if necessary to see the parameters. \imageMacro{cmdlinemodules_NiftyReg.png,"Figure 6. An example program\, showing parameters for NiftyReg's program RegAladin.",10.24} In this example, the parameters are displayed for NiftyReg produced at UCL, and more specifically for the affine registration program called RegAladin. The interface can contain a wide variety of controls. If a parameter for a command line program is an input image, then the widget displayed is linked to the DataManager, so that as new images are loaded, the correct image can be easily selected from the combo box. At this stage, multiple tabs can be opened, with one tab for each command line program. Figure 7 shows 2 tabs, for the RegAladin and RegF3D programs. \imageMacro{cmdlinemodules_F3D.png,"Figure 7. Multiple tabs can be opened\, one for each command line program.",10.24} The main view provides some simple controls: \li Green arrow: Launch (run) the command line executable of the currently selected tab. \li Yellow undo arrow: Resets the GUI controls of the currently selected tab to default values, if and only if the original XML specified a default value. At this stage, nothing has been launched. When the user hits the green arrow button, a job is launched. Each running job is shown as a new progress reporting widget under the main tabbed widget, as shown in Figure 8. \imageMacro{cmdlinemodules_NiftyRegRunning2.png,"Figure 8. Multiple programs can be run\, each with individual controls and console output.",10.24} The controls for each running job are: \li Blue pause button: If supported on the host platform, this button will be enabled and can be toggled off (pause) or on (resume). \li Red square: If supported on the host platform, this button will kill the command line program. \li Black cross: Will remove the progress reporting widget from the GUI. When the user hits the green arrow in the main view: \li The currently selected tab is designated the "current" job, and contains the "current" set of parameters. \li A new progress reporting widget is created. \li The current parameters are copied to the progress reporting widget. In Figure 8. a parameters section is visible, and by default is collapsed, as they are simply for referring back to. \li All the output for the command line program is shown in the console widget, with a separate console for each job. \li Each new progress reporting widget is simply stacked vertically (newest is top-most), and it is up to the user to delete them when they are finished. It is easy to run multiple jobs. The green button simply launches the job corresponding to the current tab repeatedly. It is up to the user to make sure that any output file names are changed between successive invocations of the same command line module to avoid overwritting output data. In addition, each set of parameters contains an "About" section containing details of the contributors, the licence and acknowledgements and also a "Help" section containing a description and a link to any on-line documentation. These documentation features are provided by the developers of the third party plugin, and not by the host program. If information is missing, the user must contact the third party developers. \section CLITechnicalNotes Technical Notes From a technical perspective, the Command Line Modules View is a simple view, harnessing the power of the CTK command line modules framework. For technical information see: \li The doxygen generated manual page. \li The wiki page. and obviously the CTK code base. */ diff --git a/Plugins/org.mitk.gui.qt.cmdlinemodules/src/internal/CommandLineModulesPreferencesPage.cpp b/Plugins/org.mitk.gui.qt.cmdlinemodules/src/internal/CommandLineModulesPreferencesPage.cpp index 6f1a6b01c2..cc9f0de959 100644 --- a/Plugins/org.mitk.gui.qt.cmdlinemodules/src/internal/CommandLineModulesPreferencesPage.cpp +++ b/Plugins/org.mitk.gui.qt.cmdlinemodules/src/internal/CommandLineModulesPreferencesPage.cpp @@ -1,262 +1,262 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) University College London (UCL). All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "CommandLineModulesPreferencesPage.h" #include "CommandLineModulesViewConstants.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "QmitkDirectoryListWidget.h" #include "QmitkFileListWidget.h" //----------------------------------------------------------------------------- CommandLineModulesPreferencesPage::CommandLineModulesPreferencesPage() : m_MainControl(0) , m_DebugOutput(0) , m_ShowAdvancedWidgets(0) , m_OutputDirectory(0) , m_TemporaryDirectory(0) , m_ModulesDirectories(0) , m_ModulesFiles(0) , m_GridLayoutForLoadCheckboxes(0) , m_LoadFromHomeDir(0) , m_LoadFromHomeDirCliModules(0) , m_LoadFromCurrentDir(0) , m_LoadFromCurrentDirCliModules(0) , m_LoadFromApplicationDir(0) , m_LoadFromApplicationDirCliModules(0) , m_LoadFromAutoLoadPathDir(0) , m_ValidationMode(0) , m_MaximumNumberProcesses(0) , m_CLIPreferencesNode(0) { } //----------------------------------------------------------------------------- CommandLineModulesPreferencesPage::~CommandLineModulesPreferencesPage() { } //----------------------------------------------------------------------------- void CommandLineModulesPreferencesPage::Init(berry::IWorkbench::Pointer ) { } //----------------------------------------------------------------------------- void CommandLineModulesPreferencesPage::CreateQtControl(QWidget* parent) { berry::IPreferencesService::Pointer prefService = berry::Platform::GetServiceRegistry() .GetServiceById(berry::IPreferencesService::ID); std::string id = "/" + CommandLineModulesViewConstants::VIEW_ID; m_CLIPreferencesNode = prefService->GetSystemPreferences()->Node(id); m_MainControl = new QWidget(parent); m_TemporaryDirectory = new ctkDirectoryButton(m_MainControl); m_TemporaryDirectory->setCaption("Select a directory for temporary files ... "); m_OutputDirectory = new ctkDirectoryButton(m_MainControl); m_OutputDirectory->setCaption("Select a default directory for output files ... "); m_ModulesDirectories = new QmitkDirectoryListWidget(m_MainControl); m_ModulesDirectories->m_Label->setText("Select directories to scan:"); m_ModulesFiles = new QmitkFileListWidget(m_MainControl); m_ModulesFiles->m_Label->setText("Select additional executables:"); m_DebugOutput = new QCheckBox(m_MainControl); m_DebugOutput->setToolTip("Output debugging information to the console."); m_ShowAdvancedWidgets = new QCheckBox(m_MainControl); m_ShowAdvancedWidgets->setToolTip("If selected, additional widgets appear\nin front-end for advanced users."); m_LoadFromAutoLoadPathDir = new QCheckBox(m_MainControl); m_LoadFromAutoLoadPathDir->setText("CTK_MODULE_LOAD_PATH"); m_LoadFromAutoLoadPathDir->setToolTip("Scan the directory specified by\nthe environment variable CTK_MODULE_LOAD_PATH."); m_LoadFromAutoLoadPathDir->setLayoutDirection(Qt::RightToLeft); m_LoadFromApplicationDir = new QCheckBox(m_MainControl); m_LoadFromApplicationDir->setText("install dir"); m_LoadFromApplicationDir->setToolTip("Scan the directory where\nthe application is installed."); m_LoadFromApplicationDir->setLayoutDirection(Qt::RightToLeft); m_LoadFromApplicationDirCliModules = new QCheckBox(m_MainControl); m_LoadFromApplicationDirCliModules->setText("install dir/cli-modules"); m_LoadFromApplicationDirCliModules->setToolTip("Scan the 'cli-modules' sub-directory\nwithin the installation directory."); m_LoadFromApplicationDirCliModules->setLayoutDirection(Qt::RightToLeft); m_LoadFromHomeDir = new QCheckBox(m_MainControl); m_LoadFromHomeDir->setText("home dir"); m_LoadFromHomeDir->setToolTip("Scan the users home directory."); m_LoadFromHomeDir->setLayoutDirection(Qt::RightToLeft); m_LoadFromHomeDirCliModules = new QCheckBox(m_MainControl); m_LoadFromHomeDirCliModules->setText("home dir/cli-modules"); m_LoadFromHomeDirCliModules->setToolTip("Scan the 'cli-modules' sub-directory\nwithin the users home directory."); m_LoadFromHomeDirCliModules->setLayoutDirection(Qt::RightToLeft); m_LoadFromCurrentDir = new QCheckBox(m_MainControl); m_LoadFromCurrentDir->setText("current dir"); m_LoadFromCurrentDir->setToolTip("Scan the current working directory\nfrom where the application was launched."); m_LoadFromCurrentDir->setLayoutDirection(Qt::RightToLeft); m_LoadFromCurrentDirCliModules = new QCheckBox(m_MainControl); m_LoadFromCurrentDirCliModules->setText("current dir/cli-modules"); m_LoadFromCurrentDirCliModules->setToolTip("Scan the 'cli-modules' sub-directory\nwithin the current working directory \n from where the application was launched."); m_LoadFromCurrentDirCliModules->setLayoutDirection(Qt::RightToLeft); m_GridLayoutForLoadCheckboxes = new QGridLayout; m_GridLayoutForLoadCheckboxes->addWidget(m_LoadFromApplicationDir, 0, 0); m_GridLayoutForLoadCheckboxes->addWidget(m_LoadFromApplicationDirCliModules, 0, 1); m_GridLayoutForLoadCheckboxes->addWidget(m_LoadFromHomeDir, 1, 0); m_GridLayoutForLoadCheckboxes->addWidget(m_LoadFromHomeDirCliModules, 1, 1); m_GridLayoutForLoadCheckboxes->addWidget(m_LoadFromCurrentDir, 2, 0); m_GridLayoutForLoadCheckboxes->addWidget(m_LoadFromCurrentDirCliModules, 2, 1); m_GridLayoutForLoadCheckboxes->addWidget(m_LoadFromAutoLoadPathDir, 3, 1); m_ValidationMode = new QComboBox(m_MainControl); m_ValidationMode->addItem("strict", ctkCmdLineModuleManager::STRICT_VALIDATION); m_ValidationMode->addItem("none", ctkCmdLineModuleManager::SKIP_VALIDATION); m_ValidationMode->addItem("weak", ctkCmdLineModuleManager::WEAK_VALIDATION); m_ValidationMode->setCurrentIndex(0); m_MaximumNumberProcesses = new QSpinBox(m_MainControl); m_MaximumNumberProcesses->setMinimum(1); m_MaximumNumberProcesses->setMaximum(1000000); m_XmlTimeoutInSeconds = new QSpinBox(m_MainControl); m_XmlTimeoutInSeconds->setMinimum(1); m_XmlTimeoutInSeconds->setMaximum(3600); QFormLayout *formLayout = new QFormLayout; formLayout->addRow("show debug output:", m_DebugOutput); formLayout->addRow("show advanced widgets:", m_ShowAdvancedWidgets); formLayout->addRow("XML time-out (secs):", m_XmlTimeoutInSeconds); formLayout->addRow("XML validation mode:", m_ValidationMode); formLayout->addRow("max. concurrent processes:", m_MaximumNumberProcesses); formLayout->addRow("scan:", m_GridLayoutForLoadCheckboxes); formLayout->addRow("additional module directories:", m_ModulesDirectories); formLayout->addRow("additional modules:", m_ModulesFiles); formLayout->addRow("temporary directory:", m_TemporaryDirectory); formLayout->addRow("default output directory:", m_OutputDirectory); m_MainControl->setLayout(formLayout); this->Update(); } //----------------------------------------------------------------------------- QWidget* CommandLineModulesPreferencesPage::GetQtControl() const { return m_MainControl; } //----------------------------------------------------------------------------- std::string CommandLineModulesPreferencesPage::ConvertToStdString(const QStringList& list) { std::string output; for (int i = 0; i < list.count(); i++) { QString path = list[i] + ";"; output += path.toStdString(); } return output; } //----------------------------------------------------------------------------- bool CommandLineModulesPreferencesPage::PerformOk() { m_CLIPreferencesNode->Put(CommandLineModulesViewConstants::TEMPORARY_DIRECTORY_NODE_NAME, m_TemporaryDirectory->directory().toStdString()); m_CLIPreferencesNode->Put(CommandLineModulesViewConstants::OUTPUT_DIRECTORY_NODE_NAME, m_OutputDirectory->directory().toStdString()); m_CLIPreferencesNode->PutBool(CommandLineModulesViewConstants::DEBUG_OUTPUT_NODE_NAME, m_DebugOutput->isChecked()); m_CLIPreferencesNode->PutBool(CommandLineModulesViewConstants::SHOW_ADVANCED_WIDGETS_NAME, m_ShowAdvancedWidgets->isChecked()); m_CLIPreferencesNode->PutBool(CommandLineModulesViewConstants::LOAD_FROM_APPLICATION_DIR, m_LoadFromApplicationDir->isChecked()); m_CLIPreferencesNode->PutBool(CommandLineModulesViewConstants::LOAD_FROM_APPLICATION_DIR_CLI_MODULES, m_LoadFromApplicationDirCliModules->isChecked()); m_CLIPreferencesNode->PutBool(CommandLineModulesViewConstants::LOAD_FROM_HOME_DIR, m_LoadFromHomeDir->isChecked()); m_CLIPreferencesNode->PutBool(CommandLineModulesViewConstants::LOAD_FROM_HOME_DIR_CLI_MODULES, m_LoadFromHomeDirCliModules->isChecked()); m_CLIPreferencesNode->PutBool(CommandLineModulesViewConstants::LOAD_FROM_CURRENT_DIR, m_LoadFromCurrentDir->isChecked()); m_CLIPreferencesNode->PutBool(CommandLineModulesViewConstants::LOAD_FROM_CURRENT_DIR_CLI_MODULES, m_LoadFromCurrentDirCliModules->isChecked()); m_CLIPreferencesNode->PutBool(CommandLineModulesViewConstants::LOAD_FROM_AUTO_LOAD_DIR, m_LoadFromAutoLoadPathDir->isChecked()); std::string paths = this->ConvertToStdString(m_ModulesDirectories->directories()); m_CLIPreferencesNode->Put(CommandLineModulesViewConstants::MODULE_DIRECTORIES_NODE_NAME, paths); std::string modules = this->ConvertToStdString(m_ModulesFiles->files()); m_CLIPreferencesNode->Put(CommandLineModulesViewConstants::MODULE_FILES_NODE_NAME, modules); - int currentValidationMode = m_CLIPreferencesNode->GetInt(CommandLineModulesViewConstants::XML_VALIDATION_MODE, 0); + int currentValidationMode = m_CLIPreferencesNode->GetInt(CommandLineModulesViewConstants::XML_VALIDATION_MODE, 2); if (currentValidationMode != m_ValidationMode->currentIndex()) { QMessageBox msgBox; msgBox.setText("Changing the XML validation mode will require a restart of the application."); msgBox.exec(); } m_CLIPreferencesNode->PutInt(CommandLineModulesViewConstants::XML_VALIDATION_MODE, m_ValidationMode->currentIndex()); m_CLIPreferencesNode->PutInt(CommandLineModulesViewConstants::XML_TIMEOUT_SECS, m_XmlTimeoutInSeconds->value()); m_CLIPreferencesNode->PutInt(CommandLineModulesViewConstants::MAX_CONCURRENT, m_MaximumNumberProcesses->value()); return true; } //----------------------------------------------------------------------------- void CommandLineModulesPreferencesPage::PerformCancel() { } //----------------------------------------------------------------------------- void CommandLineModulesPreferencesPage::Update() { QString fallbackTmpDir = QDir::tempPath(); m_TemporaryDirectory->setDirectory(QString::fromStdString(m_CLIPreferencesNode->Get(CommandLineModulesViewConstants::TEMPORARY_DIRECTORY_NODE_NAME, fallbackTmpDir.toStdString()))); QString fallbackOutputDir = QDir::homePath(); m_OutputDirectory->setDirectory(QString::fromStdString(m_CLIPreferencesNode->Get(CommandLineModulesViewConstants::OUTPUT_DIRECTORY_NODE_NAME, fallbackOutputDir.toStdString()))); m_ShowAdvancedWidgets->setChecked(m_CLIPreferencesNode->GetBool(CommandLineModulesViewConstants::SHOW_ADVANCED_WIDGETS_NAME, false)); m_DebugOutput->setChecked(m_CLIPreferencesNode->GetBool(CommandLineModulesViewConstants::DEBUG_OUTPUT_NODE_NAME, false)); m_LoadFromApplicationDir->setChecked(m_CLIPreferencesNode->GetBool(CommandLineModulesViewConstants::LOAD_FROM_APPLICATION_DIR, false)); m_LoadFromApplicationDirCliModules->setChecked(m_CLIPreferencesNode->GetBool(CommandLineModulesViewConstants::LOAD_FROM_APPLICATION_DIR_CLI_MODULES, true)); m_LoadFromHomeDir->setChecked(m_CLIPreferencesNode->GetBool(CommandLineModulesViewConstants::LOAD_FROM_HOME_DIR, false)); m_LoadFromHomeDirCliModules->setChecked(m_CLIPreferencesNode->GetBool(CommandLineModulesViewConstants::LOAD_FROM_HOME_DIR_CLI_MODULES, false)); m_LoadFromCurrentDir->setChecked(m_CLIPreferencesNode->GetBool(CommandLineModulesViewConstants::LOAD_FROM_CURRENT_DIR, false)); m_LoadFromCurrentDirCliModules->setChecked(m_CLIPreferencesNode->GetBool(CommandLineModulesViewConstants::LOAD_FROM_CURRENT_DIR_CLI_MODULES, false)); m_LoadFromAutoLoadPathDir->setChecked(m_CLIPreferencesNode->GetBool(CommandLineModulesViewConstants::LOAD_FROM_AUTO_LOAD_DIR, false)); QString paths = QString::fromStdString(m_CLIPreferencesNode->Get(CommandLineModulesViewConstants::MODULE_DIRECTORIES_NODE_NAME, "")); QStringList directoryList = paths.split(";", QString::SkipEmptyParts); m_ModulesDirectories->setDirectories(directoryList); QString files = QString::fromStdString(m_CLIPreferencesNode->Get(CommandLineModulesViewConstants::MODULE_FILES_NODE_NAME, "")); QStringList fileList = files.split(";", QString::SkipEmptyParts); m_ModulesFiles->setFiles(fileList); - m_ValidationMode->setCurrentIndex(m_CLIPreferencesNode->GetInt(CommandLineModulesViewConstants::XML_VALIDATION_MODE, 0)); + m_ValidationMode->setCurrentIndex(m_CLIPreferencesNode->GetInt(CommandLineModulesViewConstants::XML_VALIDATION_MODE, 2)); m_XmlTimeoutInSeconds->setValue(m_CLIPreferencesNode->GetInt(CommandLineModulesViewConstants::XML_TIMEOUT_SECS, 30)); // 30 secs = QProcess default timeout m_MaximumNumberProcesses->setValue(m_CLIPreferencesNode->GetInt(CommandLineModulesViewConstants::MAX_CONCURRENT, 4)); } diff --git a/Plugins/org.mitk.gui.qt.cmdlinemodules/src/internal/CommandLineModulesView.cpp b/Plugins/org.mitk.gui.qt.cmdlinemodules/src/internal/CommandLineModulesView.cpp index 049842aaff..562bc66d84 100644 --- a/Plugins/org.mitk.gui.qt.cmdlinemodules/src/internal/CommandLineModulesView.cpp +++ b/Plugins/org.mitk.gui.qt.cmdlinemodules/src/internal/CommandLineModulesView.cpp @@ -1,552 +1,552 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) University College London (UCL). All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include #include // Qmitk #include "CommandLineModulesView.h" #include "CommandLineModulesViewConstants.h" #include "CommandLineModulesViewControls.h" #include "CommandLineModulesPreferencesPage.h" #include "QmitkCmdLineModuleFactoryGui.h" #include "QmitkCmdLineModuleGui.h" #include "QmitkCmdLineModuleRunner.h" // Qt #include #include #include #include #include #include #include #include // CTK #include #include #include #include #include #include #include #include #include #include //----------------------------------------------------------------------------- CommandLineModulesView::CommandLineModulesView() : m_Controls(NULL) , m_Parent(NULL) , m_Layout(NULL) , m_ModuleManager(NULL) , m_ModuleBackend(NULL) , m_DirectoryWatcher(NULL) , m_TemporaryDirectoryName("") , m_MaximumConcurrentProcesses(4) , m_CurrentlyRunningProcesses(0) , m_DebugOutput(false) , m_XmlTimeoutSeconds(30) // 30 seconds = QProcess default timeout. { } //----------------------------------------------------------------------------- CommandLineModulesView::~CommandLineModulesView() { if (m_ModuleManager != NULL) { delete m_ModuleManager; } if (m_ModuleBackend != NULL) { delete m_ModuleBackend; } if (m_DirectoryWatcher != NULL) { delete m_DirectoryWatcher; } if (m_Layout != NULL) { delete m_Layout; } for (int i = 0; i < m_ListOfModules.size(); i++) { delete m_ListOfModules[i]; } } //----------------------------------------------------------------------------- void CommandLineModulesView::SetFocus() { this->m_Controls->m_ComboBox->setFocus(); } //----------------------------------------------------------------------------- void CommandLineModulesView::CreateQtPartControl( QWidget *parent ) { m_Parent = parent; if (!m_Controls) { // We create CommandLineModulesViewControls, which derives from the Qt generated class. m_Controls = new CommandLineModulesViewControls(parent); // Create a layout to contain a display of QmitkCmdLineModuleRunner. m_Layout = new QVBoxLayout(m_Controls->m_RunningWidgets); m_Layout->setContentsMargins(0,0,0,0); m_Layout->setSpacing(0); // This must be done independent of other preferences, as we need it before // we create the ctkCmdLineModuleManager to initialise the Cache. this->RetrieveAndStoreTemporaryDirectoryPreferenceValues(); this->RetrieveAndStoreValidationMode(); // Start to create the command line module infrastructure. m_ModuleBackend = new ctkCmdLineModuleBackendLocalProcess(); m_ModuleManager = new ctkCmdLineModuleManager(m_ValidationMode, m_TemporaryDirectoryName); // Set the main object, the ctkCmdLineModuleManager onto all the objects that need it. m_Controls->m_ComboBox->SetManager(m_ModuleManager); m_DirectoryWatcher = new ctkCmdLineModuleDirectoryWatcher(m_ModuleManager); connect(this->m_DirectoryWatcher, SIGNAL(errorDetected(QString)), this, SLOT(OnDirectoryWatcherErrorsDetected(QString))); m_ModuleManager->registerBackend(m_ModuleBackend); // Setup the remaining preferences. this->RetrieveAndStorePreferenceValues(); // Connect signals to slots after we have set up GUI. connect(this->m_Controls->m_RunButton, SIGNAL(pressed()), this, SLOT(OnRunButtonPressed())); connect(this->m_Controls->m_RestoreDefaults, SIGNAL(pressed()), this, SLOT(OnRestoreButtonPressed())); connect(this->m_Controls->m_ComboBox, SIGNAL(actionChanged(QAction*)), this, SLOT(OnActionChanged(QAction*))); connect(this->m_Controls->m_TabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(OnTabCloseRequested(int))); connect(this->m_Controls->m_ClearXMLCache, SIGNAL(pressed()), this, SLOT(OnClearCache())); connect(this->m_Controls->m_ReloadModules, SIGNAL(pressed()), this, SLOT(OnReloadModules())); this->UpdateRunButtonEnabledStatus(); } } //----------------------------------------------------------------------------- berry::IBerryPreferences::Pointer CommandLineModulesView::RetrievePreferences() { berry::IPreferencesService::Pointer prefService = berry::Platform::GetServiceRegistry() .GetServiceById(berry::IPreferencesService::ID); assert( prefService ); std::string id = "/" + CommandLineModulesViewConstants::VIEW_ID; berry::IBerryPreferences::Pointer prefs = (prefService->GetSystemPreferences()->Node(id)) .Cast(); assert( prefs ); return prefs; } //----------------------------------------------------------------------------- void CommandLineModulesView::RetrieveAndStoreTemporaryDirectoryPreferenceValues() { berry::IBerryPreferences::Pointer prefs = this->RetrievePreferences(); QString fallbackTmpDir = QDir::tempPath(); m_TemporaryDirectoryName = QString::fromStdString( prefs->Get(CommandLineModulesViewConstants::TEMPORARY_DIRECTORY_NODE_NAME, fallbackTmpDir.toStdString())); } //----------------------------------------------------------------------------- void CommandLineModulesView::RetrieveAndStoreValidationMode() { berry::IBerryPreferences::Pointer prefs = this->RetrievePreferences(); - int value = prefs->GetInt(CommandLineModulesViewConstants::XML_VALIDATION_MODE, 0); + int value = prefs->GetInt(CommandLineModulesViewConstants::XML_VALIDATION_MODE, 2); if (value == 0) { m_ValidationMode = ctkCmdLineModuleManager::STRICT_VALIDATION; } else if (value == 1) { m_ValidationMode = ctkCmdLineModuleManager::SKIP_VALIDATION; } else { m_ValidationMode = ctkCmdLineModuleManager::WEAK_VALIDATION; } } //----------------------------------------------------------------------------- void CommandLineModulesView::RetrieveAndStorePreferenceValues() { berry::IBerryPreferences::Pointer prefs = this->RetrievePreferences(); QString fallbackHomeDir = QDir::homePath(); m_OutputDirectoryName = QString::fromStdString( prefs->Get(CommandLineModulesViewConstants::OUTPUT_DIRECTORY_NODE_NAME, fallbackHomeDir.toStdString())); m_MaximumConcurrentProcesses = prefs->GetInt(CommandLineModulesViewConstants::MAX_CONCURRENT, 4); m_XmlTimeoutSeconds = prefs->GetInt(CommandLineModulesViewConstants::XML_TIMEOUT_SECS, 30); m_ModuleManager->setTimeOutForXMLRetrieval(m_XmlTimeoutSeconds * 1000); // preference is in seconds, underlying CTK library in milliseconds. // Get the flag for debug output, useful when parsing all the XML. m_DebugOutput = prefs->GetBool(CommandLineModulesViewConstants::DEBUG_OUTPUT_NODE_NAME, false); m_DirectoryWatcher->setDebug(m_DebugOutput); // Show/Hide the advanced widgets this->m_Controls->SetAdvancedWidgetsVisible(prefs->GetBool(CommandLineModulesViewConstants::SHOW_ADVANCED_WIDGETS_NAME, false)); bool loadApplicationDir = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_APPLICATION_DIR, false); bool loadApplicationDirCliModules = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_APPLICATION_DIR_CLI_MODULES, true); bool loadHomeDir = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_HOME_DIR, false); bool loadHomeDirCliModules = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_HOME_DIR_CLI_MODULES, false); bool loadCurrentDir = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_CURRENT_DIR, false); bool loadCurrentDirCliModules = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_CURRENT_DIR_CLI_MODULES, false); bool loadAutoLoadDir = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_AUTO_LOAD_DIR, false); // Get some default application paths. // Here we can use the preferences to set up the builder, ctkCmdLineModuleDefaultPathBuilder builder; if (loadApplicationDir) builder.addApplicationDir(); if (loadApplicationDirCliModules) builder.addApplicationDir("cli-modules"); if (loadHomeDir) builder.addHomeDir(); if (loadHomeDirCliModules) builder.addHomeDir("cli-modules"); if (loadCurrentDir) builder.addCurrentDir(); if (loadCurrentDirCliModules) builder.addCurrentDir("cli-modules"); if (loadAutoLoadDir) builder.addCtkModuleLoadPath(); // and then we ask the builder to set up the paths. QStringList defaultPaths = builder.getDirectoryList(); // We get additional directory paths from preferences. QString pathString = QString::fromStdString(prefs->Get(CommandLineModulesViewConstants::MODULE_DIRECTORIES_NODE_NAME, "")); QStringList additionalPaths = pathString.split(";", QString::SkipEmptyParts); // Combine the sets of directory paths. QStringList totalPaths; totalPaths << defaultPaths; totalPaths << additionalPaths; QString additionalModulesString = QString::fromStdString(prefs->Get(CommandLineModulesViewConstants::MODULE_FILES_NODE_NAME, "")); QStringList additionalModules = additionalModulesString.split(";", QString::SkipEmptyParts); // OnPreferencesChanged can be called for each preference in a dialog box, so // when you hit "OK", it is called repeatedly, whereas we want to only call these only once. if (m_DirectoryPaths != totalPaths) { m_DirectoryPaths = totalPaths; m_DirectoryWatcher->setDirectories(totalPaths); } if (m_ModulePaths != additionalModules) { m_ModulePaths = additionalModules; m_DirectoryWatcher->setAdditionalModules(additionalModules); } } //----------------------------------------------------------------------------- void CommandLineModulesView::OnPreferencesChanged(const berry::IBerryPreferences* /*prefs*/) { this->RetrieveAndStoreTemporaryDirectoryPreferenceValues(); this->RetrieveAndStoreValidationMode(); this->RetrieveAndStorePreferenceValues(); } //----------------------------------------------------------------------------- ctkCmdLineModuleReference CommandLineModulesView::GetReferenceByFullName(QString fullName) { ctkCmdLineModuleReference result; QList references = this->m_ModuleManager->moduleReferences(); ctkCmdLineModuleReference ref; foreach(ref, references) { QString name = ref.description().categoryDotTitle(); if (name == fullName) { result = ref; } } return result; } //----------------------------------------------------------------------------- void CommandLineModulesView::OnActionChanged(QAction* action) { QString fullName = action->objectName(); ctkCmdLineModuleReference ref = this->GetReferenceByFullName(fullName); // ref should never be invalid, as the menu was generated from each ctkCmdLineModuleReference. // But just to be sure ... if invalid, don't do anything. if (ref) { // Check if we already have the reference. int tabIndex = -1; for (int i = 0; i < m_ListOfModules.size(); i++) { ctkCmdLineModuleReference tabsReference = m_ListOfModules[i]->moduleReference(); if (ref.location() == tabsReference.location()) { tabIndex = i; break; } } // i.e. we found a matching tab, so just switch to it. if (tabIndex != -1) { m_Controls->m_TabWidget->setCurrentIndex(tabIndex); } else // i.e. we did not find a matching tab { // In this case, we need to create a new tab, and give // it a GUI for the user to setup the parameters with. QmitkCmdLineModuleFactoryGui factory(this->GetDataStorage()); ctkCmdLineModuleFrontend *frontEnd = factory.create(ref); QmitkCmdLineModuleGui *theGui = dynamic_cast(frontEnd); // Add to list and tab wigdget m_ListOfModules.push_back(frontEnd); int tabIndex = m_Controls->m_TabWidget->addTab(theGui->getGui(), ref.description().title()); m_Controls->m_TabWidget->setTabToolTip(tabIndex, ref.description().title() + ":" + ref.xmlValidationErrorString()); // Here lies a small caveat. // // The XML may specify a default output file name. // However, this will probably have no file path, so we should probably add one. // Otherwise you will likely be trying to write in the application installation folder // eg. C:/Program Files (Windows) or /Applications/ (Mac) // // Also, we may find that 3rd party apps crash when they can't write. // So lets plan for the worst and hope for the best :-) QString parameterName; QList parameters; parameters = frontEnd->parameters("image", ctkCmdLineModuleFrontend::Output); parameters << frontEnd->parameters("file", ctkCmdLineModuleFrontend::Output); parameters << frontEnd->parameters("geometry", ctkCmdLineModuleFrontend::Output); foreach (ctkCmdLineModuleParameter parameter, parameters) { parameterName = parameter.name(); QString outputFileName = frontEnd->value(parameterName, ctkCmdLineModuleFrontend::DisplayRole).toString(); QFileInfo outputFileInfo(outputFileName); if (outputFileInfo.absoluteFilePath() != outputFileName) { QDir defaultOutputDir(m_OutputDirectoryName); QFileInfo replacementFileInfo(defaultOutputDir, outputFileName); frontEnd->setValue(parameterName, replacementFileInfo.absoluteFilePath(), ctkCmdLineModuleFrontend::DisplayRole); } } } } } //----------------------------------------------------------------------------- void CommandLineModulesView::OnTabCloseRequested(int tabNumber) { ctkCmdLineModuleFrontend *frontEnd = m_ListOfModules[tabNumber]; m_Controls->m_TabWidget->removeTab(tabNumber); m_ListOfModules.removeAt(tabNumber); delete frontEnd; } //----------------------------------------------------------------------------- void CommandLineModulesView::AskUserToSelectAModule() const { QMessageBox msgBox; msgBox.setText("Please select a module!"); msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); } //----------------------------------------------------------------------------- void CommandLineModulesView::OnRestoreButtonPressed() { int tabNumber = m_Controls->m_TabWidget->currentIndex(); if (tabNumber >= 0) { ctkCmdLineModuleFrontend *frontEnd = m_ListOfModules[tabNumber]; frontEnd->resetValues(); } else { this->AskUserToSelectAModule(); } } //----------------------------------------------------------------------------- void CommandLineModulesView::OnRunButtonPressed() { int tabNumber = m_Controls->m_TabWidget->currentIndex(); if (tabNumber >= 0) { // 1. Create a new QmitkCmdLineModuleRunner to represent the running widget. QmitkCmdLineModuleRunner *widget = new QmitkCmdLineModuleRunner(m_Controls->m_RunningWidgets); widget->SetDataStorage(this->GetDataStorage()); widget->SetManager(m_ModuleManager); widget->SetOutputDirectory(m_OutputDirectoryName); // 2. Create a new front end. QmitkCmdLineModuleFactoryGui factory(this->GetDataStorage()); ctkCmdLineModuleFrontend *frontEndOnCurrentTab = m_ListOfModules[tabNumber]; QmitkCmdLineModuleGui *frontEndGuiOnCurrentTab = dynamic_cast(frontEndOnCurrentTab); ctkCmdLineModuleReference currentTabFrontendReferences = frontEndGuiOnCurrentTab->moduleReference(); ctkCmdLineModuleFrontend *newFrontEnd = factory.create(currentTabFrontendReferences); QmitkCmdLineModuleGui *newFrontEndGui = dynamic_cast(newFrontEnd); widget->SetFrontend(newFrontEndGui); m_Layout->insertWidget(0, widget); // 3. Copy parameters. This MUST come after widget->SetFrontEnd newFrontEndGui->copyParameters(*frontEndGuiOnCurrentTab); newFrontEndGui->setParameterContainerEnabled(false); // 4. Connect widget signals to here, to count how many jobs running. connect(widget, SIGNAL(started()), this, SLOT(OnJobStarted())); connect(widget, SIGNAL(finished()), this, SLOT(OnJobFinished())); // 5. GO. widget->Run(); } else { this->AskUserToSelectAModule(); } } //----------------------------------------------------------------------------- void CommandLineModulesView::UpdateRunButtonEnabledStatus() { if (m_CurrentlyRunningProcesses >= m_MaximumConcurrentProcesses) { m_Controls->m_RunButton->setEnabled(false); } else { m_Controls->m_RunButton->setEnabled(true); } } //----------------------------------------------------------------------------- void CommandLineModulesView::OnJobStarted() { m_CurrentlyRunningProcesses++; this->UpdateRunButtonEnabledStatus(); } //----------------------------------------------------------------------------- void CommandLineModulesView::OnJobFinished() { m_CurrentlyRunningProcesses--; this->UpdateRunButtonEnabledStatus(); } //----------------------------------------------------------------------------- void CommandLineModulesView::OnDirectoryWatcherErrorsDetected(const QString& errorMsg) { ctkCmdLineModuleUtils::messageBoxForModuleRegistration(errorMsg); } //----------------------------------------------------------------------------- void CommandLineModulesView::OnClearCache() { if (this->m_DebugOutput) { qDebug() << "CommandLineModulesView::OnClearCache(): starting"; } m_ModuleManager->clearCache(); if (this->m_DebugOutput) { qDebug() << "CommandLineModulesView::OnClearCache(): finishing"; } } //----------------------------------------------------------------------------- void CommandLineModulesView::OnReloadModules() { QList urls; QList moduleRefs = m_ModuleManager->moduleReferences(); foreach (ctkCmdLineModuleReference ref, moduleRefs) { urls.push_back(ref.location()); } if (this->m_DebugOutput) { qDebug() << "CommandLineModulesView::OnReloadModules(): unloading:" << urls; } foreach (ctkCmdLineModuleReference ref, moduleRefs) { m_ModuleManager->unregisterModule(ref); } if (this->m_DebugOutput) { qDebug() << "CommandLineModulesView::OnReloadModules(): reloading."; } QList refResults = QtConcurrent::blockingMapped(urls, ctkCmdLineModuleConcurrentRegister(m_ModuleManager, m_DebugOutput)); if (this->m_DebugOutput) { qDebug() << "CommandLineModulesView::OnReloadModules(): finished."; } QString errorMessages = ctkCmdLineModuleUtils::errorMessagesFromModuleRegistration(refResults, m_ModuleManager->validationMode()); ctkCmdLineModuleUtils::messageBoxForModuleRegistration(errorMessages); } diff --git a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp index 664dd36a3e..9ad07b3796 100644 --- a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp +++ b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp @@ -1,1063 +1,1062 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkDataManagerView.h" #include //# Own Includes //## mitk #include "mitkDataStorageEditorInput.h" #include "mitkIDataStorageReference.h" #include "mitkNodePredicateDataType.h" #include "mitkCoreObjectFactory.h" -#include "mitkDataNodeFactory.h" #include "mitkColorProperty.h" #include "mitkCommon.h" #include "mitkNodePredicateData.h" #include "mitkNodePredicateNot.h" #include "mitkNodePredicateOr.h" #include "mitkNodePredicateProperty.h" #include "mitkEnumerationProperty.h" #include "mitkLookupTableProperty.h" #include "mitkProperties.h" #include #include #include #include #include //## Qmitk #include #include #include #include #include #include #include #include "src/internal/QmitkNodeTableViewKeyFilter.h" #include "src/internal/QmitkInfoDialog.h" #include "src/internal/QmitkDataManagerItemDelegate.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" #include "mitkRenderingModeProperty.h" const std::string QmitkDataManagerView::VIEW_ID = "org.mitk.views.datamanager"; QmitkDataManagerView::QmitkDataManagerView() : m_GlobalReinitOnNodeDelete(true), m_ItemDelegate(NULL) { } 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_SurfaceDecimation = prefs->GetBool("Use surface decimation", false); // Prepare filters m_HelperObjectFilterPredicate = mitk::NodePredicateOr::New( mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true)), mitk::NodePredicateProperty::New("hidden object", mitk::BoolProperty::New(true))); m_NodeWithNoDataFilterPredicate = mitk::NodePredicateData::New(0); m_FilterModel = new QmitkDataStorageFilterProxyModel(); m_FilterModel->setSourceModel(m_NodeTreeModel); m_FilterModel->AddFilterPredicate(m_HelperObjectFilterPredicate); m_FilterModel->AddFilterPredicate(m_NodeWithNoDataFilterPredicate); //# Tree View (experimental) m_NodeTreeView = new QTreeView; m_NodeTreeView->setHeaderHidden(true); 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_FilterModel); m_NodeTreeView->setTextElideMode(Qt::ElideMiddle); m_NodeTreeView->installEventFilter(new QmitkNodeTableViewKeyFilter(this)); m_ItemDelegate = new QmitkDataManagerItemDelegate(m_NodeTreeView); m_NodeTreeView->setItemDelegate(m_ItemDelegate); 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* diffusionImageDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("DiffusionImage"); 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 QmitkFileSaveAction(QIcon(":/org.mitk.gui.qt.datamanager/Save_48.png"), this->GetSite()->GetWorkbenchWindow()); 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)) { // 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; } // check if the user specified an icon attribute if ( (*cmActionsIt)->GetAttribute("icon", cmIcon) ) { contextMenuAction = new QAction( QIcon( QString::fromStdString(cmIcon)), QString::fromStdString(cmLabel), parent); } else { 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_ComponentSlider = new QmitkNumberPropertySlider; m_ComponentSlider->setOrientation(Qt::Horizontal); //QObject::connect( m_OpacitySlider, SIGNAL( valueChanged(int) ) // , this, SLOT( OpacityChanged(int) ) ); QLabel* _ComponentLabel = new QLabel("Component: "); QHBoxLayout* _ComponentWidgetLayout = new QHBoxLayout; _ComponentWidgetLayout->setContentsMargins(4,4,4,4); _ComponentWidgetLayout->addWidget(_ComponentLabel); _ComponentWidgetLayout->addWidget(m_ComponentSlider); QLabel* _ComponentValueLabel = new QLabel(); _ComponentWidgetLayout->addWidget(_ComponentValueLabel); connect(m_ComponentSlider, SIGNAL(valueChanged(int)), _ComponentValueLabel, SLOT(setNum(int))); QWidget* _ComponentWidget = new QWidget; _ComponentWidget->setLayout(_ComponentWidgetLayout); QWidgetAction* componentAction = new QWidgetAction(this); componentAction->setDefaultWidget(_ComponentWidget); QObject::connect( componentAction , SIGNAL( changed() ) , this, SLOT( ComponentActionChanged() ) ); imageDataNodeDescriptor->AddAction(componentAction, false); m_DescriptorActionList.push_back(std::pair(imageDataNodeDescriptor,componentAction)); if (diffusionImageDataNodeDescriptor!=NULL) { diffusionImageDataNodeDescriptor->AddAction(componentAction, false); m_DescriptorActionList.push_back(std::pair(diffusionImageDataNodeDescriptor,componentAction)); } 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)); if (diffusionImageDataNodeDescriptor!=NULL) { diffusionImageDataNodeDescriptor->AddAction(m_TextureInterpolation, false); m_DescriptorActionList.push_back(std::pair(diffusionImageDataNodeDescriptor,m_TextureInterpolation)); } m_ColormapAction = new QAction("Colormap", this); m_ColormapAction->setMenu(new QMenu); QObject::connect( m_ColormapAction->menu(), SIGNAL( aboutToShow() ) , this, SLOT( ColormapMenuAboutToShow() ) ); imageDataNodeDescriptor->AddAction(m_ColormapAction, false); m_DescriptorActionList.push_back(std::pair(imageDataNodeDescriptor, m_ColormapAction)); if (diffusionImageDataNodeDescriptor!=NULL) { diffusionImageDataNodeDescriptor->AddAction(m_ColormapAction, false); m_DescriptorActionList.push_back(std::pair(diffusionImageDataNodeDescriptor, m_ColormapAction)); } 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)); //obsolete... //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 == "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); } else if(className == "QmitkCreateSimulationAction") { contextMenuAction->SetDataStorage(this->GetDataStorage()); } 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() ); bool hideHelperObjects = !prefs->GetBool("Show helper objects", false); if (m_FilterModel->HasFilterPredicate(m_HelperObjectFilterPredicate) != hideHelperObjects) { if (hideHelperObjects) { m_FilterModel->AddFilterPredicate(m_HelperObjectFilterPredicate); } else { m_FilterModel->RemoveFilterPredicate(m_HelperObjectFilterPredicate); } } bool hideNodesWithNoData = !prefs->GetBool("Show nodes containing no data", false); if (m_FilterModel->HasFilterPredicate(m_NodeWithNoDataFilterPredicate) != hideNodesWithNoData) { if (hideNodesWithNoData) { m_FilterModel->AddFilterPredicate(m_NodeWithNoDataFilterPredicate); } else { m_FilterModel->RemoveFilterPredicate(m_NodeWithNoDataFilterPredicate); } } m_GlobalReinitOnNodeDelete = prefs->GetBool("Call global reinit if node is deleted", true); m_NodeTreeView->expandAll(); m_SurfaceDecimation = prefs->GetBool("Use surface decimation", false); this->GlobalReinit(); } void QmitkDataManagerView::NodeTableViewContextMenuRequested( const QPoint & pos ) { QModelIndex selectedProxy = m_NodeTreeView->indexAt ( pos ); QModelIndex selected = m_FilterModel->mapToSource(selectedProxy); 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_FilterModel->mapToSource(m_NodeTreeView->selectionModel()->currentIndex())); if(node) { float opacity = static_cast(value)/100.0f; node->SetFloatProperty("opacity", opacity); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkDataManagerView::OpacityActionChanged() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(m_NodeTreeView->selectionModel()->currentIndex())); if(node) { float opacity = 0.0; if(node->GetFloatProperty("opacity", opacity)) { m_OpacitySlider->setValue(static_cast(opacity*100)); } } } void QmitkDataManagerView::ComponentActionChanged() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(m_NodeTreeView->selectionModel()->currentIndex())); mitk::IntProperty* componentProperty = NULL; int numComponents = 0; if(node) { componentProperty = dynamic_cast(node->GetProperty("Image.Displayed Component")); mitk::Image* img = dynamic_cast(node->GetData()); if (img != NULL) { numComponents = img->GetPixelType().GetNumberOfComponents(); } } if (componentProperty && numComponents > 1) { m_ComponentSlider->SetProperty(componentProperty); m_ComponentSlider->setMinValue(0); m_ComponentSlider->setMaxValue(numComponents-1); } else { m_ComponentSlider->SetProperty(static_cast(NULL)); } } void QmitkDataManagerView::ColorChanged() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(m_NodeTreeView->selectionModel()->currentIndex())); if(node) { mitk::Color color; mitk::ColorProperty::Pointer colorProp; node->GetProperty(colorProp,"color"); if(colorProp.IsNull()) return; color = colorProp->GetValue(); QColor initial(color.GetRed()*255,color.GetGreen()*255,color.GetBlue()*255); QColor qcolor = QColorDialog::getColor(initial,0,QString("Change color")); if (!qcolor.isValid()) return; m_ColorButton->setAutoFillBackground(true); node->SetProperty("color",mitk::ColorProperty::New(qcolor.red()/255.0,qcolor.green()/255.0,qcolor.blue()/255.0)); if (node->GetProperty("binaryimage.selectedcolor")) { node->SetProperty("binaryimage.selectedcolor",mitk::ColorProperty::New(qcolor.red()/255.0,qcolor.green()/255.0,qcolor.blue()/255.0)); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkDataManagerView::ColorActionChanged() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(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); } } void QmitkDataManagerView::TextureInterpolationChanged() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(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_FilterModel->mapToSource(m_NodeTreeView->selectionModel()->currentIndex())); if(node) { node->SetBoolProperty("texture interpolation", checked); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkDataManagerView::ColormapActionToggled( bool /*checked*/ ) { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(m_NodeTreeView->selectionModel()->currentIndex())); if(!node) return; mitk::LookupTableProperty::Pointer lookupTableProperty = dynamic_cast(node->GetProperty("LookupTable")); if (!lookupTableProperty) return; QAction* senderAction = qobject_cast(QObject::sender()); if(!senderAction) return; std::string activatedItem = senderAction->text().toStdString(); mitk::LookupTable::Pointer lookupTable = lookupTableProperty->GetValue(); if (!lookupTable) return; lookupTable->SetType(activatedItem); lookupTableProperty->SetValue(lookupTable); mitk::RenderingModeProperty::Pointer renderingMode = dynamic_cast(node->GetProperty("Image Rendering.Mode")); renderingMode->SetValue(mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataManagerView::ColormapMenuAboutToShow() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(m_NodeTreeView->selectionModel()->currentIndex())); if(!node) return; mitk::LookupTableProperty::Pointer lookupTableProperty = dynamic_cast(node->GetProperty("LookupTable")); if (!lookupTableProperty) { mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); lookupTableProperty = mitk::LookupTableProperty::New(); lookupTableProperty->SetLookupTable(mitkLut); node->SetProperty("LookupTable", lookupTableProperty); } mitk::LookupTable::Pointer lookupTable = lookupTableProperty->GetValue(); if (!lookupTable) return; m_ColormapAction->menu()->clear(); QAction* tmp; int i = 0; std::string lutType = lookupTable->typenameList[i]; while (lutType != "END_OF_ARRAY") { tmp = m_ColormapAction->menu()->addAction(QString::fromStdString(lutType)); tmp->setCheckable(true); if (lutType == lookupTable->GetActiveTypeAsString()) { tmp->setChecked(true); } QObject::connect(tmp, SIGNAL(triggered(bool)), this, SLOT(ColormapActionToggled(bool))); lutType = lookupTable->typenameList[++i]; } } void QmitkDataManagerView::SurfaceRepresentationMenuAboutToShow() { mitk::DataNode* node = m_NodeTreeModel->GetNode(m_FilterModel->mapToSource(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_FilterModel->mapToSource(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::ReinitSelectedNodes( bool ) { mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart(); if (renderWindow == NULL) renderWindow = this->OpenRenderWindowPart(false); QList selectedNodes = this->GetCurrentSelection(); foreach(mitk::DataNode::Pointer node, selectedNodes) { mitk::BaseData::Pointer basedata = node->GetData(); if ( basedata.IsNotNull() && basedata->GetTimeGeometry()->IsValid() ) { renderWindow->GetRenderingManager()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); renderWindow->GetRenderingManager()->RequestUpdateAll(); } } } void QmitkDataManagerView::RemoveSelectedNodes( bool ) { QModelIndexList indexesOfSelectedRowsFiltered = m_NodeTreeView->selectionModel()->selectedRows(); QModelIndexList indexesOfSelectedRows; for (int i = 0; i < indexesOfSelectedRowsFiltered.size(); ++i) { indexesOfSelectedRows.push_back(m_FilterModel->mapToSource(indexesOfSelectedRowsFiltered[i])); } 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(), "PlaneGeometryData") != 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); if (m_GlobalReinitOnNodeDelete) 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::NodeChanged(const mitk::DataNode* /*node*/) { // m_FilterModel->invalidate(); // fix as proposed by R. Khlebnikov in the mitk-users mail from 02.09.2014 QMetaObject::invokeMethod( m_FilterModel, "invalidate", Qt::QueuedConnection ); } QItemSelectionModel *QmitkDataManagerView::GetDataNodeSelectionModel() const { return m_NodeTreeView->selectionModel(); } void QmitkDataManagerView::GlobalReinit( bool ) { mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart(); if (renderWindow == NULL) renderWindow = this->OpenRenderWindowPart(false); // no render window available if (renderWindow == NULL) return; mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); } 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())->Clone()); this->GetDataStorage()->Add(resultNode, node); } catch( std::exception& err ) { MITK_ERROR(this->GetClassName()) << err.what(); } } } 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(); } } 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(bool activatedEditor) { if (activatedEditor) { return this->GetRenderWindowPart(QmitkAbstractView::ACTIVATE | QmitkAbstractView::OPEN); } else { return this->GetRenderWindowPart(QmitkAbstractView::BRING_TO_FRONT | QmitkAbstractView::OPEN); } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/resources/FiberBundleX.png b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/FiberBundleX.png deleted file mode 100644 index 76ee67c6e7..0000000000 Binary files a/Plugins/org.mitk.gui.qt.diffusionimaging/resources/FiberBundleX.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkDiffusionImaging.qrc b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkDiffusionImaging.qrc index 433010c36f..68ea118057 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkDiffusionImaging.qrc +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/QmitkDiffusionImaging.qrc @@ -1,64 +1,64 @@ 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 + FiberBundle.png connectomics/ConnectomicsNetwork.png connectomics/QmitkRandomParcellationIcon.png rectangle.png circle.png polygon.png color24.gif color48.gif color64.gif crosshair.png paint2.png IVIM_48.png reset.png MapperEfx2D.png refresh.xpm odf.png general_icons/download.ico general_icons/play.ico general_icons/plus.ico general_icons/refresh.ico general_icons/right.ico general_icons/save.ico general_icons/undo.ico general_icons/upload.ico general_icons/abort.ico general_icons/copy1.ico general_icons/copy2.ico general_icons/cut.ico general_icons/deny1.ico general_icons/deny2.ico general_icons/down.ico general_icons/left.ico general_icons/magn_minus.ico general_icons/magn_plus.ico general_icons/search.ico general_icons/stop.ico general_icons/up.ico general_icons/help.ico general_icons/pencil.ico general_icons/edit.ico denoisingicon.png diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTbssRoiAnalysisWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTbssRoiAnalysisWidget.cpp index 372a08f150..f25b4d7561 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTbssRoiAnalysisWidget.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTbssRoiAnalysisWidget.cpp @@ -1,967 +1,967 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkTbssRoiAnalysisWidget.h" #include "mitkImagePixelReadAccessor.h" #include "mitkPixelTypeMultiplex.h" #include #include #include #include QmitkTbssRoiAnalysisWidget::QmitkTbssRoiAnalysisWidget( QWidget * parent ) : QmitkPlotWidget(parent) { m_PlotPicker = new QwtPlotPicker(m_Plot->canvas()); m_PlotPicker->setStateMachine(new QwtPickerDragPointMachine()); m_PlotPicker->setTrackerMode(QwtPicker::ActiveOnly); m_PlottingFiberBundle = false; } -void QmitkTbssRoiAnalysisWidget::DoPlotFiberBundles(mitk::FiberBundleX *fib, mitk::Image* img, +void QmitkTbssRoiAnalysisWidget::DoPlotFiberBundles(mitk::FiberBundle *fib, mitk::Image* img, mitk::PlanarFigure* startRoi, mitk::PlanarFigure* endRoi, bool avg, int number) { TractContainerType tracts = CreateTracts(fib, startRoi, endRoi); TractContainerType resampledTracts = ParameterizeTracts(tracts, number); // Now we have the resampled tracts. Next we should use these points to read out the values mitkPixelTypeMultiplex3(PlotFiberBundles,img->GetImageDescriptor()->GetChannelTypeById(0),resampledTracts, img, avg); m_CurrentTracts = resampledTracts; } -TractContainerType QmitkTbssRoiAnalysisWidget::CreateTracts(mitk::FiberBundleX *fib, +TractContainerType QmitkTbssRoiAnalysisWidget::CreateTracts(mitk::FiberBundle *fib, mitk::PlanarFigure *startRoi, mitk::PlanarFigure *endRoi) { mitk::PlaneGeometry* startGeometry2D = const_cast(startRoi->GetPlaneGeometry()); mitk::PlaneGeometry* endGeometry2D = const_cast(endRoi->GetPlaneGeometry()); mitk::Point3D startCenter = startRoi->GetWorldControlPoint(0); //center Point of start roi mitk::Point3D endCenter = endRoi->GetWorldControlPoint(0); //center Point of end roi - mitk::FiberBundleX::Pointer inStart = fib->ExtractFiberSubset(startRoi); - mitk::FiberBundleX::Pointer inBoth = inStart->ExtractFiberSubset(endRoi); + mitk::FiberBundle::Pointer inStart = fib->ExtractFiberSubset(startRoi); + mitk::FiberBundle::Pointer inBoth = inStart->ExtractFiberSubset(endRoi); int num = inBoth->GetNumFibers(); TractContainerType tracts; vtkSmartPointer fiberPolyData = inBoth->GetFiberPolyData(); vtkCellArray* lines = fiberPolyData->GetLines(); lines->InitTraversal(); // Now find out for each fiber which ROI is encountered first. If this is the startRoi, the direction is ok // Otherwise the plot should be in the reverse direction for( int fiberID( 0 ); fiberID < num; fiberID++ ) { vtkIdType numPointsInCell(0); vtkIdType* pointsInCell(NULL); lines->GetNextCell ( numPointsInCell, pointsInCell ); int startId = 0; int endId = 0; mitk::ScalarType minDistStart = std::numeric_limits::max(); mitk::ScalarType minDistEnd = std::numeric_limits::max(); for( int pointInCellID( 0 ); pointInCellID < numPointsInCell ; pointInCellID++) { mitk::ScalarType *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] ); mitk::Point3D point; point[0] = p[0]; point[1] = p[1]; point[2] = p[2]; mitk::ScalarType distanceToStart = point.EuclideanDistanceTo(startCenter); mitk::ScalarType distanceToEnd = point.EuclideanDistanceTo(endCenter); if(distanceToStart < minDistStart) { minDistStart = distanceToStart; startId = pointInCellID; } if(distanceToEnd < minDistEnd) { minDistEnd = distanceToEnd; endId = pointInCellID; } } /* We found the start and end points of of the part that should be plottet for the current fiber. now we need to plot them. If the endId is smaller than the startId the plot order must be reversed*/ TractType singleTract; PointType point; if(startId < endId) { // Calculate the intersection of the ROI with the startRoi and decide if the startId is part of the roi or must be cut of mitk::ScalarType *p = fiberPolyData->GetPoint( pointsInCell[ startId ] ); mitk::Vector3D p0; p0[0] = p[0]; p0[1] = p[1]; p0[2] = p[2]; p = fiberPolyData->GetPoint( pointsInCell[ startId+1 ] ); mitk::Vector3D p1; p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2]; // Check if p and p2 are both on the same side of the plane mitk::Vector3D normal = startGeometry2D->GetNormal(); mitk::Point3D pStart; pStart[0] = p0[0]; pStart[1] = p0[1]; pStart[2] = p0[2]; mitk::Point3D pSecond; pSecond[0] = p1[0]; pSecond[1] = p1[1]; pSecond[2] = p1[2]; bool startOnPositive = startGeometry2D->IsAbove(pStart); bool secondOnPositive = startGeometry2D->IsAbove(pSecond); mitk::Vector3D onPlane; onPlane[0] = startCenter[0]; onPlane[1] = startCenter[1]; onPlane[2] = startCenter[2]; if(! (secondOnPositive ^ startOnPositive) ) { /* startId and startId+1 lie on the same side of the plane, so we need need startId-1 to calculate the intersection with the planar figure*/ p = fiberPolyData->GetPoint( pointsInCell[ startId-1 ] ); p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2]; } mitk::ScalarType d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal ); mitk::Vector3D newPoint = (p0-p1); point[0] = d*newPoint[0] + p0[0]; point[1] = d*newPoint[1] + p0[1]; point[2] = d*newPoint[2] + p0[2]; singleTract.push_back(point); if(! (secondOnPositive ^ startOnPositive) ) { /* StartId and startId+1 lie on the same side of the plane so startId is also part of the ROI*/ mitk::ScalarType *start = fiberPolyData->GetPoint( pointsInCell[startId] ); point[0] = start[0]; point[1] = start[1]; point[2] = start[2]; singleTract.push_back(point); } for( int pointInCellID( startId+1 ); pointInCellID < endId ; pointInCellID++) { // push back point mitk::ScalarType *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] ); point[0] = p[0]; point[1] = p[1]; point[2] = p[2]; singleTract.push_back( point ); } /* endId must be included if endId and endId-1 lie on the same side of the plane defined by endRoi*/ p = fiberPolyData->GetPoint( pointsInCell[ endId ] ); p0[0] = p[0]; p0[1] = p[1]; p0[2] = p[2]; p = fiberPolyData->GetPoint( pointsInCell[ endId-1 ] ); p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2]; mitk::Point3D pLast; pLast[0] = p0[0]; pLast[1] = p0[1]; pLast[2] = p0[2]; mitk::Point3D pBeforeLast; pBeforeLast[0] = p1[0]; pBeforeLast[1] = p1[1]; pBeforeLast[2] = p1[2]; normal = endGeometry2D->GetNormal(); bool lastOnPositive = endGeometry2D->IsAbove(pLast); bool secondLastOnPositive = endGeometry2D->IsAbove(pBeforeLast); onPlane[0] = endCenter[0]; onPlane[1] = endCenter[1]; onPlane[2] = endCenter[2]; if(! (lastOnPositive ^ secondLastOnPositive) ) { /* endId and endId-1 lie on the same side of the plane, so we need need endId+1 to calculate the intersection with the planar figure. this should exist since we know that the fiber crosses the planar figure endId is also part of the tract and can be inserted here */ p = fiberPolyData->GetPoint( pointsInCell[ endId ] ); point[0] = p[0]; point[1] = p[1]; point[2] = p[2]; singleTract.push_back( point ); p = fiberPolyData->GetPoint( pointsInCell[ endId+1 ] ); } d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal ); newPoint = (p0-p1); point[0] = d*newPoint[0] + p0[0]; point[1] = d*newPoint[1] + p0[1]; point[2] = d*newPoint[2] + p0[2]; singleTract.push_back(point); } else{ // Calculate the intersection of the ROI with the startRoi and decide if the startId is part of the roi or must be cut of mitk::ScalarType *p = fiberPolyData->GetPoint( pointsInCell[ startId ] ); mitk::Vector3D p0; p0[0] = p[0]; p0[1] = p[1]; p0[2] = p[2]; p = fiberPolyData->GetPoint( pointsInCell[ startId-1 ] ); mitk::Vector3D p1; p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2]; // Check if p and p2 are both on the same side of the plane mitk::Vector3D normal = startGeometry2D->GetNormal(); mitk::Point3D pStart; pStart[0] = p0[0]; pStart[1] = p0[1]; pStart[2] = p0[2]; mitk::Point3D pSecond; pSecond[0] = p1[0]; pSecond[1] = p1[1]; pSecond[2] = p1[2]; bool startOnPositive = startGeometry2D->IsAbove(pStart); bool secondOnPositive = startGeometry2D->IsAbove(pSecond); mitk::Vector3D onPlane; onPlane[0] = startCenter[0]; onPlane[1] = startCenter[1]; onPlane[2] = startCenter[2]; if(! (secondOnPositive ^ startOnPositive) ) { /* startId and startId+1 lie on the same side of the plane, so we need need startId-1 to calculate the intersection with the planar figure*/ p = fiberPolyData->GetPoint( pointsInCell[ startId-1 ] ); p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2]; } mitk::ScalarType d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal ); mitk::Vector3D newPoint = (p0-p1); point[0] = d*newPoint[0] + p0[0]; point[1] = d*newPoint[1] + p0[1]; point[2] = d*newPoint[2] + p0[2]; singleTract.push_back(point); if(! (secondOnPositive ^ startOnPositive) ) { /* StartId and startId+1 lie on the same side of the plane so startId is also part of the ROI*/ mitk::ScalarType *start = fiberPolyData->GetPoint( pointsInCell[startId] ); point[0] = start[0]; point[1] = start[1]; point[2] = start[2]; singleTract.push_back(point); } for( int pointInCellID( startId-1 ); pointInCellID > endId ; pointInCellID--) { // push back point mitk::ScalarType *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] ); point[0] = p[0]; point[1] = p[1]; point[2] = p[2]; singleTract.push_back( point ); } /* endId must be included if endId and endI+1 lie on the same side of the plane defined by endRoi*/ p = fiberPolyData->GetPoint( pointsInCell[ endId ] ); p0[0] = p[0]; p0[1] = p[1]; p0[2] = p[2]; p = fiberPolyData->GetPoint( pointsInCell[ endId+1 ] ); p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2]; mitk::Point3D pLast; pLast[0] = p0[0]; pLast[1] = p0[1]; pLast[2] = p0[2]; mitk::Point3D pBeforeLast; pBeforeLast[0] = p1[0]; pBeforeLast[1] = p1[1]; pBeforeLast[2] = p1[2]; bool lastOnPositive = endGeometry2D->IsAbove(pLast); bool secondLastOnPositive = endGeometry2D->IsAbove(pBeforeLast); normal = endGeometry2D->GetNormal(); onPlane[0] = endCenter[0]; onPlane[1] = endCenter[1]; onPlane[2] = endCenter[2]; if(! (lastOnPositive ^ secondLastOnPositive) ) { /* endId and endId+1 lie on the same side of the plane, so we need need endId-1 to calculate the intersection with the planar figure. this should exist since we know that the fiber crosses the planar figure endId is also part of the tract and can be inserted here */ p = fiberPolyData->GetPoint( pointsInCell[ endId ] ); point[0] = p[0]; point[1] = p[1]; point[2] = p[2]; singleTract.push_back( point ); p = fiberPolyData->GetPoint( pointsInCell[ endId-1 ] ); } d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal ); newPoint = (p0-p1); point[0] = d*newPoint[0] + p0[0]; point[1] = d*newPoint[1] + p0[1]; point[2] = d*newPoint[2] + p0[2]; singleTract.push_back(point); } tracts.push_back(singleTract); } return tracts; } -void QmitkTbssRoiAnalysisWidget::PlotFiberBetweenRois(mitk::FiberBundleX *fib, mitk::Image* img, +void QmitkTbssRoiAnalysisWidget::PlotFiberBetweenRois(mitk::FiberBundle *fib, mitk::Image* img, mitk::PlanarFigure* startRoi, mitk::PlanarFigure* endRoi, bool avg, int number) { if(fib == NULL || img == NULL || startRoi == NULL || endRoi == NULL) return; m_Fib = fib; m_CurrentImage = img; m_CurrentStartRoi = startRoi; m_CurrentEndRoi = endRoi; DoPlotFiberBundles(fib, img, startRoi, endRoi, avg, number); } void QmitkTbssRoiAnalysisWidget::ModifyPlot(int number, bool avg) { if(m_Fib == NULL || m_CurrentTbssImage == NULL || m_CurrentStartRoi == NULL || m_CurrentEndRoi == NULL) return; if(m_PlottingFiberBundle) { DoPlotFiberBundles(m_Fib, m_CurrentImage, m_CurrentStartRoi, m_CurrentEndRoi, avg, number); } else { PlotFiber4D(m_CurrentTbssImage, m_Fib, m_CurrentStartRoi, m_CurrentEndRoi, number); } } TractContainerType QmitkTbssRoiAnalysisWidget::ParameterizeTracts(TractContainerType tracts, int number) { TractContainerType resampledTracts; for(TractContainerType::iterator it = tracts.begin(); it != tracts.end(); ++it) { TractType resampledTract; TractType tract = *it; // Calculate the total length mitk::ScalarType totalLength = 0; if(tract.size() < 2) continue; PointType p0 = tract.at(0); for(unsigned int i = 1; i distance+0.001) { if(tractCounter == tract.size()) std::cout << "problem"; // Determine by what distance we are no on the next segment locationBetween = locationBetween - distance; p0 = p1; p1 = tract.at(tractCounter); tractCounter++; distance = p0.EuclideanDistanceTo(p1); } // Direction PointType::VectorType direction = p1-p0; direction.Normalize(); PointType newSample = p0 + direction*locationBetween; resampledTract.push_back(newSample); locationBetween += stepSize; } resampledTracts.push_back(resampledTract); } return resampledTracts; } mitk::Point3D QmitkTbssRoiAnalysisWidget::GetPositionInWorld(int index) { mitk::ScalarType xSum = 0.0; mitk::ScalarType ySum = 0.0; mitk::ScalarType zSum = 0.0; for(TractContainerType::iterator it = m_CurrentTracts.begin(); it!=m_CurrentTracts.end(); ++it) { TractType tract = *it; PointType p = tract.at(index); xSum += p[0]; ySum += p[1]; zSum += p[2]; } int number = m_CurrentTracts.size(); mitk::ScalarType xPos = xSum / number; mitk::ScalarType yPos = ySum / number; mitk::ScalarType zPos = zSum / number; mitk::Point3D pos; pos[0] = xPos; pos[1] = yPos; pos[2] = zPos; return pos; } std::vector< std::vector > QmitkTbssRoiAnalysisWidget::CalculateGroupProfiles() { MITK_INFO << "make profiles!"; std::vector< std::vector > profiles; int size = m_Projections->GetVectorLength(); for(int s=0; s profile; RoiType::iterator it; it = m_Roi.begin(); while(it != m_Roi.end()) { itk::Index<3> ix = *it; profile.push_back(m_Projections->GetPixel(ix).GetElement(s)); it++; } profiles.push_back(profile); } m_IndividualProfiles = profiles; // Calculate the averages // Here a check could be build in to check whether all profiles have // the same length, but this should normally be the case if the input // data were corrected with the TBSS Module. std::vector< std::vector > groupProfiles; std::vector< std::pair >::iterator it; it = m_Groups.begin(); int c = 0; //the current profile number while(it != m_Groups.end() && profiles.size() > 0) { std::pair p = *it; int size = p.second; //initialize a vector of the right length with zeroes std::vector averageProfile; for(unsigned int i=0; i > groupProfiles = CalculateGroupProfiles(); Plot(groupProfiles); } void QmitkTbssRoiAnalysisWidget::Plot(std::vector > groupProfiles) { this->Clear(); m_Vals.clear(); std::vector v1; std::vector xAxis; for(unsigned int i=0; iSetPlotTitle( title.c_str() ); QPen pen( Qt::SolidLine ); pen.setWidth(2); std::vector< std::pair >::iterator it; it = m_Groups.begin(); int c = 0; //the current profile number QColor colors[4] = {Qt::green, Qt::blue, Qt::yellow, Qt::red}; while(it != m_Groups.end() && groupProfiles.size() > 0) { std::pair< std::string, int > group = *it; pen.setColor(colors[c]); int curveId = this->InsertCurve( group.first.c_str() ); this->SetCurveData( curveId, xAxis, groupProfiles.at(c) ); this->SetCurvePen( curveId, pen ); c++; it++; } QwtLegend *legend = new QwtLegend; this->SetLegend(legend, QwtPlot::RightLegend, 0.5); std::cout << m_Measure << std::endl; this->m_Plot->setAxisTitle(0, m_Measure.c_str()); this->m_Plot->setAxisTitle(3, "Position"); this->Replot(); } std::vector< std::vector > QmitkTbssRoiAnalysisWidget::CalculateGroupProfilesFibers(mitk::TbssImage::Pointer tbssImage, - mitk::FiberBundleX *fib, + mitk::FiberBundle *fib, mitk::PlanarFigure* startRoi, mitk::PlanarFigure* endRoi, int number) { TractContainerType tracts = CreateTracts(fib, startRoi, endRoi); TractContainerType resampledTracts = ParameterizeTracts(tracts, number); int nTracts = resampledTracts.size(); this->Clear(); // For every group we have m fibers * n subjects of profiles to fill std::vector< std::vector > profiles; // calculate individual profiles by going through all n subjects int size = m_Projections->GetVectorLength(); for(int s=0; s profile; TractType::iterator it = resampledTracts[t].begin(); while(it != resampledTracts[t].end()) { PointType p = *it; PointType index; tbssImage->GetGeometry()->WorldToIndex(p, index); itk::Index<3> ix; ix[0] = index[0]; ix[1] = index[1]; ix[2] = index[2]; // Get value from image profile.push_back(m_Projections->GetPixel(ix).GetElement(s)); it++; } profiles.push_back(profile); } } m_IndividualProfiles = profiles; // Now create the group averages (every group contains m fibers * n_i group members std::vector< std::pair >::iterator it; it = m_Groups.begin(); int c = 0; //the current profile number // Calculate the group averages std::vector< std::vector > groupProfiles; while(it != m_Groups.end() && profiles.size() > 0) { std::pair p = *it; int size = p.second; //initialize a vector of the right length with zeroes std::vector averageProfile; for(unsigned int i=0; i > groupProfiles = CalculateGroupProfilesFibers(tbssImage, fib, startRoi, endRoi, number); Plot(groupProfiles); } template void QmitkTbssRoiAnalysisWidget::PlotFiberBundles(const mitk::PixelType ptype, TractContainerType tracts, mitk::Image *img, bool avg) { m_PlottingFiberBundle = true; this->Clear(); std::vector::iterator it = tracts.begin(); std::vector< std::vector > profiles; mitk::ImagePixelReadAccessor imAccess(img,img->GetVolumeData(0)); it = tracts.begin(); while(it != tracts.end()) { TractType tract = *it; TractType::iterator tractIt = tract.begin(); std::vector profile; while(tractIt != tract.end()) { PointType p = *tractIt; // Get value from image profile.push_back( (mitk::ScalarType) imAccess.GetPixelByWorldCoordinates(p) ); ++tractIt; } profiles.push_back(profile); std::cout << std::endl; ++it; } if(profiles.size() == 0) return; m_IndividualProfiles = profiles; std::string title = "Fiber bundle plot"; this->SetPlotTitle( title.c_str() ); // initialize average profile std::vector averageProfile; std::vector profile = profiles.at(0); // can do this because we checked the size of profiles before for(unsigned int i=0; i >::iterator profit = profiles.begin(); int id=0; while(profit != profiles.end()) { std::vector profile = *profit; std::vector xAxis; for(unsigned int i=0; iInsertCurve( "" ); this->SetCurveData( curveId, xAxis, profile ); ++profit; id++; } m_Average = averageProfile; if(avg) { // Draw the average profile std::vector xAxis; for(unsigned int i=0; iInsertCurve( "" ); this->SetCurveData( curveId, xAxis, averageProfile ); QPen pen( Qt::SolidLine ); pen.setWidth(3); pen.setColor(Qt::red); this->SetCurvePen( curveId, pen ); id++; } this->Replot(); } void QmitkTbssRoiAnalysisWidget::drawBar(int x) { m_Plot->detachItems(QwtPlotItem::Rtti_PlotMarker, true); QwtPlotMarker *mX = new QwtPlotMarker(); //mX->setLabel(QString::fromLatin1("selected point")); mX->setLabelAlignment(Qt::AlignLeft | Qt::AlignBottom); mX->setLabelOrientation(Qt::Vertical); mX->setLineStyle(QwtPlotMarker::VLine); mX->setLinePen(QPen(Qt::black, 0, Qt::SolidLine)); mX->setXValue(x); mX->attach(m_Plot); this->Replot(); } QmitkTbssRoiAnalysisWidget::~QmitkTbssRoiAnalysisWidget() { delete m_PlotPicker; } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTbssRoiAnalysisWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTbssRoiAnalysisWidget.h index 162ce829d8..8e020ed842 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTbssRoiAnalysisWidget.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTbssRoiAnalysisWidget.h @@ -1,230 +1,230 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkTbssRoiAnalysisWidget_H_ #define QmitkTbssRoiAnalysisWidget_H_ #include "QmitkPlotWidget.h" #include -#include +#include #include #include typedef itk::VectorImage VectorImageType; typedef std::vector< itk::Index<3> > RoiType; typedef mitk::Point3D PointType; typedef std::vector< PointType> TractType; typedef std::vector< TractType > TractContainerType; class QwtPlotPicker; /** * \brief Plot widget for TBSS Data * This widget can plot regions of interest on TBSS projection data. The projection data is created by importing FSL TBSS subject data and * completing it with patient data using the QmitkTractbasedSpatialStatisticsView. * The region of interest is a vector of indices from which data for plotting should be obtained. */ class DIFFUSIONIMAGING_EXPORT QmitkTbssRoiAnalysisWidget : public QmitkPlotWidget { Q_OBJECT public: QmitkTbssRoiAnalysisWidget( QWidget * parent); virtual ~QmitkTbssRoiAnalysisWidget(); /* \brief Set group information as a vector of pairs of group name and number of group members */ void SetGroups(std::vector< std::pair > groups) { m_Groups = groups; } /* \brief Draws the group averaged profiles */ void DrawProfiles(); void PlotFiber4D(mitk::TbssImage::Pointer tbssImage, - mitk::FiberBundleX *fib, + mitk::FiberBundle *fib, mitk::PlanarFigure* startRoi, mitk::PlanarFigure* endRoi, int number); template void PlotFiberBundles(const mitk::PixelType, TractContainerType tracts, mitk::Image* img, bool avg=false); /* \brief Sets the projections of the individual subjects */ void SetProjections(VectorImageType::Pointer projections) { m_Projections = projections; } /* \brief Set the region of interest*/ void SetRoi(RoiType roi) { m_Roi = roi; } /* \brief Set structure information to display in the plot */ void SetStructure(std::string structure) { m_Structure = structure; } /* \brief Set measurement type for display in the plot */ void SetMeasure(std::string measure) { m_Measure = measure; } /* \brief Draws a bar to indicate were the user clicked in the plot */ void drawBar(int x); /* \brief Returns the values of the group averaged profiles */ std::vector > GetVals() { return m_Vals; } /* \brief Returns the values of the individual subjects profiles */ std::vector > GetIndividualProfiles() { return m_IndividualProfiles; } std::vector GetAverageProfile() { return m_Average; } void SetPlottingFiber(bool b) { m_PlottingFiberBundle = b; } bool IsPlottingFiber() { return m_PlottingFiberBundle; } - void PlotFiberBetweenRois(mitk::FiberBundleX *fib, mitk::Image* img, + void PlotFiberBetweenRois(mitk::FiberBundle *fib, mitk::Image* img, mitk::PlanarFigure* startRoi, mitk::PlanarFigure* endRoi, bool avg=-1, int number=25); // Takes an index which is an x coordinate from the plot and finds the corresponding position in world space mitk::Point3D GetPositionInWorld(int index); void ModifyPlot(int number, bool avg); QwtPlotPicker* m_PlotPicker; protected: - mitk::FiberBundleX* m_Fib; + mitk::FiberBundle* m_Fib; std::vector< std::vector > m_Vals; std::vector< std::vector > m_IndividualProfiles; std::vector< double > m_Average; std::vector< std::vector > CalculateGroupProfiles(); std::vector< std::vector > CalculateGroupProfilesFibers(mitk::TbssImage::Pointer tbssImage, - mitk::FiberBundleX *fib, + mitk::FiberBundle *fib, mitk::PlanarFigure* startRoi, mitk::PlanarFigure* endRoi, int number); void Plot(std::vector > groupProfiles); 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); } } std::vector< std::pair > m_Groups; VectorImageType::Pointer m_Projections; RoiType m_Roi; std::string m_Structure; std::string m_Measure; bool m_PlottingFiberBundle; // true when the plot results from a fiber tracking result (vtk .fib file) // Resample a collection of tracts so that every tract contains #number equidistant samples TractContainerType ParameterizeTracts(TractContainerType tracts, int number); TractContainerType m_CurrentTracts; mitk::Image* m_CurrentImage; mitk::TbssImage* m_CurrentTbssImage; mitk::PlanarFigure* m_CurrentStartRoi; mitk::PlanarFigure* m_CurrentEndRoi; - void DoPlotFiberBundles(mitk::FiberBundleX *fib, mitk::Image* img, + void DoPlotFiberBundles(mitk::FiberBundle *fib, mitk::Image* img, mitk::PlanarFigure* startRoi, mitk::PlanarFigure* endRoi, bool avg=false, int number=25); - /* \brief Creates tracts from a mitk::FiberBundleX and two planar figures indicating the start end end point */ - TractContainerType CreateTracts(mitk::FiberBundleX *fib, mitk::PlanarFigure* startRoi, mitk::PlanarFigure* endRoi); + /* \brief Creates tracts from a mitk::FiberBundle and two planar figures indicating the start end end point */ + TractContainerType CreateTracts(mitk::FiberBundle *fib, mitk::PlanarFigure* startRoi, mitk::PlanarFigure* endRoi); }; #endif diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkConnectomicsDataView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkConnectomicsDataView.cpp index ec259e9142..7a2eb21bfa 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkConnectomicsDataView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Connectomics/QmitkConnectomicsDataView.cpp @@ -1,404 +1,404 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // ####### Blueberry includes ####### #include #include // ####### Qmitk includes ####### #include "QmitkConnectomicsDataView.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 QmitkConnectomicsDataView::VIEW_ID = "org.mitk.views.connectomicsdata"; QmitkConnectomicsDataView::QmitkConnectomicsDataView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) , m_ConnectomicsNetworkCreator( mitk::ConnectomicsNetworkCreator::New() ) , m_demomode( false ) , m_currentIndex( 0 ) { } QmitkConnectomicsDataView::~QmitkConnectomicsDataView() { } void QmitkConnectomicsDataView::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::QmitkConnectomicsDataViewControls; m_Controls->setupUi( parent ); 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)) ); } // GUI is different for developer and demo mode m_demomode = true; if( m_demomode ) { this->m_Controls->networkifyPushButton->show(); this->m_Controls->networkifyPushButton->setText( "Create Network" ); 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->mappingStrategyComboBox->insertItem(m_ConnectomicsNetworkCreator->EndElementPosition, "Use label of end position of fibers"); this->m_Controls->mappingStrategyComboBox->insertItem(m_ConnectomicsNetworkCreator->EndElementPositionAvoidingWhiteMatter, "Extrapolate label"); } else { this->m_Controls->networkifyPushButton->show(); this->m_Controls->networkifyPushButton->setText( "Networkify" ); 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"); this->m_Controls->mappingStrategyComboBox->insertItem(m_ConnectomicsNetworkCreator->EndElementPosition, "Use label of end position of fibers"); this->m_Controls->mappingStrategyComboBox->insertItem(m_ConnectomicsNetworkCreator->EndElementPositionAvoidingWhiteMatter, "Extrapolate label"); this->m_Controls->mappingStrategyComboBox->insertItem(m_ConnectomicsNetworkCreator->JustEndPointVerticesNoLabel, "Use end position of fibers, no label"); } this->WipeDisplay(); } void QmitkConnectomicsDataView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkConnectomicsDataView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkConnectomicsDataView::WipeDisplay() { m_Controls->lblWarning->setVisible( true ); m_Controls->inputImageOneNameLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH ); m_Controls->inputImageOneNameLabel->setVisible( false ); m_Controls->inputImageOneLabel->setVisible( false ); m_Controls->inputImageTwoNameLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH ); m_Controls->inputImageTwoNameLabel->setVisible( false ); m_Controls->inputImageTwoLabel->setVisible( false ); } void QmitkConnectomicsDataView::OnSelectionChanged( std::vector nodes ) { this->WipeDisplay(); // Valid options are either // 1 image (parcellation) // // 1 image (parcellation) // 1 fiber bundle // // 1 network if( nodes.size() > 2 ) { return; } bool alreadyFiberBundleSelected( false ), alreadyImageSelected( false ), currentFormatUnknown( true ); // iterate all selected objects, adjust warning visibility for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; currentFormatUnknown = true; if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { currentFormatUnknown = false; if( alreadyImageSelected ) { this->WipeDisplay(); return; } alreadyImageSelected = true; m_Controls->lblWarning->setVisible( false ); m_Controls->inputImageOneNameLabel->setText(node->GetName().c_str()); m_Controls->inputImageOneNameLabel->setVisible( true ); m_Controls->inputImageOneLabel->setVisible( true ); } - if( node.IsNotNull() && dynamic_cast(node->GetData()) ) + if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { currentFormatUnknown = false; // a fiber bundle has to be in conjunction with a parcellation if( nodes.size() != 2 || alreadyFiberBundleSelected ) { this->WipeDisplay(); return; } alreadyFiberBundleSelected = true; m_Controls->lblWarning->setVisible( false ); m_Controls->inputImageTwoNameLabel->setText(node->GetName().c_str()); m_Controls->inputImageTwoNameLabel->setVisible( true ); m_Controls->inputImageTwoLabel->setVisible( true ); } { // network section mitk::ConnectomicsNetwork* network = dynamic_cast( node->GetData() ); if( node.IsNotNull() && network ) { currentFormatUnknown = false; if( nodes.size() != 1 ) { // only valid option is a single network this->WipeDisplay(); return; } m_Controls->lblWarning->setVisible( false ); m_Controls->inputImageOneNameLabel->setText(node->GetName().c_str()); m_Controls->inputImageOneNameLabel->setVisible( true ); m_Controls->inputImageOneLabel->setVisible( true ); } } // end network section if ( currentFormatUnknown ) { this->WipeDisplay(); return; } } // end for loop } void QmitkConnectomicsDataView::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 QmitkConnectomicsDataView::OnSyntheticNetworkCreationPushButtonClicked() { // warn if trying to create a very big network // big network is a network with > 5000 nodes (estimate) // this might fill up the memory to the point it freezes int numberOfNodes( 0 ); switch (m_currentIndex) { case 0: numberOfNodes = this->m_Controls->parameterOneSpinBox->value() * this->m_Controls->parameterOneSpinBox->value() * this->m_Controls->parameterOneSpinBox->value(); break; case 1: numberOfNodes = this->m_Controls->parameterOneSpinBox->value(); break; case 2: numberOfNodes = this->m_Controls->parameterOneSpinBox->value(); break; case 3: // not implemented yet break; case 4: // not implemented yet break; default: break; } if( numberOfNodes > 5000 ) { QMessageBox msgBox; msgBox.setText("Trying to generate very large network."); msgBox.setIcon( QMessageBox::Warning ); msgBox.setInformativeText("You are trying to generate a network with more than 5000 nodes, this is very resource intensive and might lead to program instability. Proceed with network generation?"); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); int ret = msgBox.exec(); switch (ret) { case QMessageBox::Yes: // continue break; case QMessageBox::No: // stop return; break; default: // should never be reached break; } } // proceed 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 ); if( generator->WasGenerationSuccessfull() ) { this->GetDefaultDataStorage()->Add( networkNode ); } else { MITK_WARN << "Problem occured during synthetic network generation."; } mitk::RenderingManager::GetInstance()->InitializeViews( networkNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return; } void QmitkConnectomicsDataView::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* firstNode = nodes.front(); mitk::DataNode* secondNode = nodes.at(1); 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* 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( firstData ); - mitk::FiberBundleX* fiberBundle = dynamic_cast( secondData ); + mitk::FiberBundle* fiberBundle = dynamic_cast( secondData ); // check whether order was switched if (! (image && fiberBundle) ) { image = dynamic_cast( secondData ); - fiberBundle = dynamic_cast( firstData ); + fiberBundle = dynamic_cast( firstData ); } if (image && fiberBundle) { mitk::ConnectomicsNetworkCreator::MappingStrategy mappingStrategy = static_cast(this->m_Controls->mappingStrategyComboBox->currentIndex()); m_ConnectomicsNetworkCreator->SetSegmentation( image ); m_ConnectomicsNetworkCreator->SetFiberBundle( fiberBundle ); m_ConnectomicsNetworkCreator->CalculateCenterOfMass(); m_ConnectomicsNetworkCreator->SetEndPointSearchRadius( 15 ); m_ConnectomicsNetworkCreator->SetMappingStrategy( mappingStrategy ); 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(); } \ No newline at end of file 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 0ce6c56d4a..869cce17b8 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp @@ -1,1036 +1,1036 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "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 "mitkFiberBundle.h" #include "QmitkDataStorageComboBox.h" #include "QmitkStdMultiWidget.h" #include "mitkFiberBundleInteractor.h" #include "mitkPlanarFigureInteractor.h" #include #include #include #include #include #include "mitkGlobalInteraction.h" #include "usModuleRegistry.h" #include "mitkPlaneGeometry.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" #include #include #define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a))) const std::string QmitkControlVisualizationPropertiesView::VIEW_ID = "org.mitk.views.controlvisualizationpropertiesview"; using namespace berry; 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_FiberBundleObserverTag(0), m_FiberBundleObserveOpacityTag(0), m_Color(NULL) { currentThickSlicesMode = 1; m_MyMenu = NULL; int numThread = itk::MultiThreader::GetGlobalMaximumNumberOfThreads(); if (numThread > 12) numThread = 12; itk::MultiThreader::SetGlobalDefaultNumberOfThreads(numThread); } QmitkControlVisualizationPropertiesView::QmitkControlVisualizationPropertiesView(const QmitkControlVisualizationPropertiesView& other) { Q_UNUSED(other) throw std::runtime_error("Copy constructor not implemented"); } QmitkControlVisualizationPropertiesView::~QmitkControlVisualizationPropertiesView() { if(m_SlicesRotationObserverTag1 ) { mitk::SlicesCoordinator::Pointer coordinator = m_MultiWidget->GetSlicesRotator(); if( coordinator.IsNotNull() ) coordinator->RemoveObserver(m_SlicesRotationObserverTag1); } if( m_SlicesRotationObserverTag2) { mitk::SlicesCoordinator::Pointer coordinator = m_MultiWidget->GetSlicesRotator(); if( coordinator.IsNotNull() ) 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 ) ); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) ); if(n) n->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( false ) ); n = this->m_MultiWidget->GetWidgetPlane2(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 0 ) ); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) ); if(n) n->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( false ) ); n = this->m_MultiWidget->GetWidgetPlane3(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 0 ) ); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) ); if(n) n->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( false ) ); } else { mitk::DataNode* n; n = this->m_MultiWidget->GetWidgetPlane1(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) ); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) ); if(n) n->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( (num>0) ) ); n = this->m_MultiWidget->GetWidgetPlane2(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) ); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) ); if(n) n->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( (num>0) ) ); n = this->m_MultiWidget->GetWidgetPlane3(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) ); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) ); if(n) n->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( (num>0) ) ); } 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); m_Controls->m_TSMenu->setMenu( m_MyMenu ); QIcon iconFiberFade(":/QmitkDiffusionImaging/MapperEfx2D.png"); m_Controls->m_FiberFading2D->setIcon(iconFiberFade); #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_ScalingFrame->setVisible(false); m_Controls->m_NormalizationFrame->setVisible(false); } } 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::NodeRemoved(const mitk::DataNode* node) { } #include void QmitkControlVisualizationPropertiesView::CreateConnections() { if ( m_Controls ) { 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_ScalingCheckbox), SIGNAL(clicked()), this, SLOT(ScalingCheckbox()) ); connect((QObject*) m_Controls->m_ResetColoring, SIGNAL(clicked()), (QObject*) this, SLOT(BundleRepresentationResetColoring())); 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_LineWidth, SIGNAL(editingFinished()), (QObject*) this, SLOT(LineWidthChanged())); connect((QObject*) m_Controls->m_TubeWidth, SIGNAL(editingFinished()), (QObject*) this, SLOT(TubeRadiusChanged())); } } void QmitkControlVisualizationPropertiesView::Activated() { } void QmitkControlVisualizationPropertiesView::Deactivated() { } // set diffusion image channel to b0 volume void QmitkControlVisualizationPropertiesView::NodeAdded(const mitk::DataNode *node) { mitk::DataNode* notConst = const_cast(node); bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(node->GetData())) ); if (isDiffusionImage) { mitk::Image::Pointer dimg = dynamic_cast(notConst->GetData()); // if there is no b0 image in the dataset, the GetB0Indices() returns a vector of size 0 // and hence we cannot set the Property directly to .front() int displayChannelPropertyValue = 0; mitk::BValueMapProperty* bmapproperty = static_cast(dimg->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ); mitk::DiffusionPropertyHelper::BValueMapType map = bmapproperty->GetBValueMap(); if( map[0].size() > 0) displayChannelPropertyValue = map[0].front(); notConst->SetIntProperty("DisplayChannel", displayChannelPropertyValue ); } } /* OnSelectionChanged is registered to SelectionService, therefore no need to implement SelectionService Listener explicitly */ void QmitkControlVisualizationPropertiesView::OnSelectionChanged( std::vector nodes ) { m_Controls->m_BundleControlsFrame->setVisible(false); m_Controls->m_ImageControlsFrame->setVisible(false); if (nodes.size()>1) // only do stuff if one node is selected return; m_Controls->m_NumberGlyphsFrame->setVisible(false); m_Controls->m_GlyphFrame->setVisible(false); m_Controls->m_TSMenu->setVisible(false); m_SelectedNode = NULL; int numOdfImages = 0; for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if(node.IsNull()) continue; mitk::BaseData* nodeData = node->GetData(); if(nodeData == NULL) continue; m_SelectedNode = node; - if (dynamic_cast(nodeData)) + if (dynamic_cast(nodeData)) { // handle fiber bundle property observers 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 ); if (m_Opacity.IsNotNull()) m_Opacity->RemoveObserver(m_FiberBundleObserveOpacityTag); itk::ReceptorMemberCommand::Pointer command2 = itk::ReceptorMemberCommand::New(); command2->SetCallbackFunction( this, &QmitkControlVisualizationPropertiesView::SetFiberBundleOpacity ); m_Opacity = dynamic_cast(node->GetProperty("opacity", NULL)); if (m_Opacity.IsNotNull()) m_FiberBundleObserveOpacityTag = m_Opacity->AddObserver( itk::ModifiedEvent(), command2 ); m_Controls->m_BundleControlsFrame->setVisible(true); // ??? if(m_CurrentPickingNode != 0 && node.GetPointer() != m_CurrentPickingNode) m_Controls->m_Crosshair->setEnabled(false); else m_Controls->m_Crosshair->setEnabled(true); int width; node->GetIntProperty("LineWidth", width); m_Controls->m_LineWidth->setValue(width); float radius; node->GetFloatProperty("TubeRadius", radius); m_Controls->m_TubeWidth->setValue(radius); float range; node->GetFloatProperty("Fiber2DSliceThickness",range); - mitk::FiberBundleX::Pointer fib = dynamic_cast(node->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); mitk::BaseGeometry::Pointer geo = fib->GetGeometry(); mitk::ScalarType max = geo->GetExtentInMM(0); max = std::max(max, geo->GetExtentInMM(1)); max = std::max(max, geo->GetExtentInMM(2)); m_Controls->m_FiberThicknessSlider->setMaximum(max * 10); m_Controls->m_FiberThicknessSlider->setValue(range * 10); m_Controls->m_FiberThicknessSlider->setFocus(); } else if(dynamic_cast(nodeData) || dynamic_cast(nodeData)) { m_Controls->m_ImageControlsFrame->setVisible(true); m_Controls->m_NumberGlyphsFrame->setVisible(true); m_Controls->m_GlyphFrame->setVisible(true); 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); int val; node->GetIntProperty("ShowMaxNumber", val); m_Controls->m_ShowMaxNumber->setValue(val); m_Controls->m_NormalizationDropdown->setCurrentIndex(dynamic_cast(node->GetProperty("Normalization"))->GetValueAsId()); float fval; node->GetFloatProperty("Scaling",fval); m_Controls->m_ScalingFactor->setValue(fval); m_Controls->m_AdditionalScaling->setCurrentIndex(dynamic_cast(node->GetProperty("ScaleBy"))->GetValueAsId()); numOdfImages++; } else if(dynamic_cast(nodeData)) { PlanarFigureFocus(); } else if( dynamic_cast(nodeData) ) { m_Controls->m_ImageControlsFrame->setVisible(true); m_Controls->m_TSMenu->setVisible(true); } } if( nodes.empty() ) return; mitk::DataNode::Pointer node = nodes.at(0); if( node.IsNull() ) return; QMenu *myMenu = m_MyMenu; myMenu->clear(); QActionGroup* thickSlicesActionGroup = new QActionGroup(myMenu); thickSlicesActionGroup->setExclusive(true); int currentTSMode = 0; { mitk::ResliceMethodProperty::Pointer m = dynamic_cast(node->GetProperty( "reslice.thickslices" )); if( m.IsNotNull() ) currentTSMode = m->GetValueAsId(); } int maxTS = 30; for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::Image* image = dynamic_cast((*it)->GetData()); if (image) { int size = std::max(image->GetDimension(0), std::max(image->GetDimension(1), image->GetDimension(2))); if (size>maxTS) maxTS=size; } } maxTS /= 2; int currentNum = 0; { mitk::IntProperty::Pointer m = dynamic_cast(node->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::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); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } 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); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } 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); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } bool QmitkControlVisualizationPropertiesView::IsPlaneRotated() { mitk::Image* currentImage = dynamic_cast( m_NodeUsedForOdfVisualization->GetData() ); if( currentImage == NULL ) { MITK_ERROR << " Casting problems. Returning false"; return false; } mitk::Vector3D imageNormal0 = currentImage->GetSlicedGeometry()->GetAxisVector(0); mitk::Vector3D imageNormal1 = currentImage->GetSlicedGeometry()->GetAxisVector(1); mitk::Vector3D imageNormal2 = currentImage->GetSlicedGeometry()->GetAxisVector(2); imageNormal0.Normalize(); imageNormal1.Normalize(); imageNormal2.Normalize(); double eps = 0.000001; // 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::Vector3D normal = displayPlane->GetNormal(); normal.Normalize(); int test = 0; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal0.GetVnlVector()))-1) > eps ) test++; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal1.GetVnlVector()))-1) > eps ) test++; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal2.GetVnlVector()))-1) > eps ) test++; if (test==3) return true; } { mitk::PlaneGeometry::ConstPointer displayPlane = dynamic_cast( m_MultiWidget->GetRenderWindow2()->GetRenderer()->GetCurrentWorldGeometry2D() ); if (displayPlane.IsNull()) return false; mitk::Vector3D normal = displayPlane->GetNormal(); normal.Normalize(); int test = 0; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal0.GetVnlVector()))-1) > eps ) test++; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal1.GetVnlVector()))-1) > eps ) test++; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal2.GetVnlVector()))-1) > eps ) test++; if (test==3) return true; } { mitk::PlaneGeometry::ConstPointer displayPlane = dynamic_cast( m_MultiWidget->GetRenderWindow3()->GetRenderer()->GetCurrentWorldGeometry2D() ); if (displayPlane.IsNull()) return false; mitk::Vector3D normal = displayPlane->GetNormal(); normal.Normalize(); int test = 0; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal0.GetVnlVector()))-1) > eps ) test++; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal1.GetVnlVector()))-1) > eps ) test++; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal2.GetVnlVector()))-1) > eps ) test++; if (test==3) return true; } return false; } void QmitkControlVisualizationPropertiesView::ShowMaxNumberChanged() { int maxNr = m_Controls->m_ShowMaxNumber->value(); if ( maxNr < 1 ) { m_Controls->m_ShowMaxNumber->setValue( 1 ); maxNr = 1; } if (dynamic_cast(m_SelectedNode->GetData()) || dynamic_cast(m_SelectedNode->GetData())) m_SelectedNode->SetIntProperty("ShowMaxNumber", maxNr); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } 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(); } if (dynamic_cast(m_SelectedNode->GetData()) || dynamic_cast(m_SelectedNode->GetData())) m_SelectedNode->SetProperty("Normalization", normMeth.GetPointer()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkControlVisualizationPropertiesView::ScalingFactorChanged(double scalingFactor) { if (dynamic_cast(m_SelectedNode->GetData()) || dynamic_cast(m_SelectedNode->GetData())) m_SelectedNode->SetFloatProperty("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(); } if (dynamic_cast(m_SelectedNode->GetData()) || dynamic_cast(m_SelectedNode->GetData())) m_SelectedNode->SetProperty("Normalization", scaleBy.GetPointer()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } 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 && dynamic_cast(m_SelectedNode->GetData()) ) + if (m_SelectedNode && dynamic_cast(m_SelectedNode->GetData()) ) { bool currentMode; m_SelectedNode->GetBoolProperty("Fiber2DfadeEFX", currentMode); m_SelectedNode->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(!currentMode)); - dynamic_cast(m_SelectedNode->GetData())->RequestUpdate2D(); + dynamic_cast(m_SelectedNode->GetData())->RequestUpdate2D(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::FiberSlicingThickness2D() { - if (m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) + if (m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) { float fibThickness = m_Controls->m_FiberThicknessSlider->value() * 0.1; float currentThickness = 0; m_SelectedNode->GetFloatProperty("Fiber2DSliceThickness", currentThickness); if (fabs(fibThickness-currentThickness)<0.001) return; m_SelectedNode->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(fibThickness)); - dynamic_cast(m_SelectedNode->GetData())->RequestUpdate2D(); + dynamic_cast(m_SelectedNode->GetData())->RequestUpdate2D(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::FiberSlicingUpdateLabel(int value) { QString label = "Range %1 mm"; label = label.arg(value * 0.1); m_Controls->label_range->setText(label); FiberSlicingThickness2D(); } void QmitkControlVisualizationPropertiesView::SetFiberBundleOpacity(const itk::EventObject& /*e*/) { if(m_SelectedNode) { - mitk::FiberBundleX::Pointer fib = dynamic_cast(m_SelectedNode->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedNode->GetData()); fib->RequestUpdate(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::SetFiberBundleCustomColor(const itk::EventObject& /*e*/) { - if(m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) + if(m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) { float color[3]; m_SelectedNode->GetColor(color); - mitk::FiberBundleX::Pointer fib = dynamic_cast(m_SelectedNode->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedNode->GetData()); fib->SetFiberColors(color[0]*255, color[1]*255, color[2]*255); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::BundleRepresentationResetColoring() { - if(m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) + if(m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) { - mitk::FiberBundleX::Pointer fib = dynamic_cast(m_SelectedNode->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedNode->GetData()); fib->DoColorCodingOrientationBased(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::PlanarFigureFocus() { if(m_SelectedNode) { mitk::PlanarFigure* _PlanarFigure = 0; _PlanarFigure = dynamic_cast (m_SelectedNode->GetData()); if (_PlanarFigure && _PlanarFigure->GetPlaneGeometry()) { 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 = _PlanarFigure->GetPlaneGeometry(); 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) { const mitk::Point3D& centerP = _PlaneGeometry->GetOrigin(); selectedRenderWindow->GetSliceNavigationController()->ReorientSlices( centerP, _PlaneGeometry->GetNormal()); } } // set interactor for new node (if not already set) mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(m_SelectedNode->GetDataInteractor().GetPointer()); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( m_SelectedNode ); } 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::FiberBundle* 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()); + 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::TubeRadiusChanged() { - if(m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) + if(m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) { float newRadius = m_Controls->m_TubeWidth->value(); m_SelectedNode->SetFloatProperty("TubeRadius", newRadius); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::LineWidthChanged() { - if(m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) + if(m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) { int newWidth = m_Controls->m_LineWidth->value(); int currentWidth = 0; m_SelectedNode->GetIntProperty("LineWidth", currentWidth); if (currentWidth==newWidth) return; m_SelectedNode->SetIntProperty("LineWidth", newWidth); - dynamic_cast(m_SelectedNode->GetData())->RequestUpdate(); + dynamic_cast(m_SelectedNode->GetData())->RequestUpdate(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::Welcome() { berry::PlatformUI::GetWorkbench()->GetIntroManager()->ShowIntro( GetSite()->GetWorkbenchWindow(), false); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDwiSoftwarePhantomView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDwiSoftwarePhantomView.cpp index ff342de343..339079fe8e 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDwiSoftwarePhantomView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDwiSoftwarePhantomView.cpp @@ -1,499 +1,499 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Qmitk #include "QmitkDwiSoftwarePhantomView.h" // MITK #include #include #include #include #include #include #define _USE_MATH_DEFINES #include const std::string QmitkDwiSoftwarePhantomView::VIEW_ID = "org.mitk.views.dwisoftwarephantomview"; QmitkDwiSoftwarePhantomView::QmitkDwiSoftwarePhantomView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) { } // Destructor QmitkDwiSoftwarePhantomView::~QmitkDwiSoftwarePhantomView() { } void QmitkDwiSoftwarePhantomView::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::QmitkDwiSoftwarePhantomViewControls; m_Controls->setupUi( parent ); m_Controls->m_SignalRegionBox->setVisible(false); connect((QObject*) m_Controls->m_GeneratePhantomButton, SIGNAL(clicked()), (QObject*) this, SLOT(GeneratePhantom())); connect((QObject*) m_Controls->m_SimulateBaseline, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnSimulateBaselineToggle(int))); } } QmitkDwiSoftwarePhantomView::GradientListType QmitkDwiSoftwarePhantomView::GenerateHalfShell(int NPoints) { NPoints *= 2; vnl_vector theta; theta.set_size(NPoints); vnl_vector phi; phi.set_size(NPoints); double C = sqrt(4*M_PI); phi(0) = 0.0; phi(NPoints-1) = 0.0; for(int i=0; i0 && i std::vector > QmitkDwiSoftwarePhantomView::MakeGradientList() { std::vector > retval; vnl_matrix_fixed* U = itk::PointShell >::DistributePointShell(); // Add 0 vector for B0 int numB0 = ndirs/10; if (numB0==0) numB0=1; itk::Vector v; v.Fill(0.0); 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); } return retval; } void QmitkDwiSoftwarePhantomView::OnSimulateBaselineToggle(int state) { if (state) { m_Controls->m_NoiseLabel->setText("Noise Variance:"); m_Controls->m_NoiseLevel->setValue(1.0/(m_Controls->m_NoiseLevel->value()*m_Controls->m_NoiseLevel->value())); m_Controls->m_NoiseLevel->setToolTip("Variance of Rician noise."); } else { m_Controls->m_NoiseLabel->setText("SNR:"); if (m_Controls->m_NoiseLevel->value()>0) m_Controls->m_NoiseLevel->setValue(1.0/(sqrt(m_Controls->m_NoiseLevel->value()))); else m_Controls->m_NoiseLevel->setValue(0.0001); m_Controls->m_NoiseLevel->setToolTip("Signal to noise ratio (for values > 99, no noise at all is added to the image)."); } } void QmitkDwiSoftwarePhantomView::GeneratePhantom() { typedef itk::DwiPhantomGenerationFilter< short > FilterType; FilterType::GradientListType gradientList; m_SignalRegions.clear(); for (int i=0; i(m_SignalRegionNodes.at(i)->GetData()); ItkUcharImgType::Pointer signalRegion = ItkUcharImgType::New(); mitk::CastToItkImage(mitkBinaryImg, signalRegion); m_SignalRegions.push_back(signalRegion); } gradientList = GenerateHalfShell(m_Controls->m_NumGradientsBox->value()); // switch(m_Controls->m_NumGradientsBox->value()) // { // 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->value(); itk::ImageRegion<3> imageRegion; imageRegion.SetSize(0, m_Controls->m_SizeX->value()); imageRegion.SetSize(1, m_Controls->m_SizeY->value()); imageRegion.SetSize(2, m_Controls->m_SizeZ->value()); mitk::Vector3D spacing; spacing[0] = m_Controls->m_SpacingX->value(); spacing[1] = m_Controls->m_SpacingY->value(); spacing[2] = m_Controls->m_SpacingZ->value(); FilterType::Pointer filter = FilterType::New(); filter->SetGradientList(gradientList); filter->SetBValue(bVal); filter->SetNoiseVariance(m_Controls->m_NoiseLevel->value()); filter->SetImageRegion(imageRegion); filter->SetSpacing(spacing); filter->SetSignalRegions(m_SignalRegions); filter->SetGreyMatterAdc(m_Controls->m_GmAdc->value()); std::vector< float > tensorFA; std::vector< float > tensorADC; std::vector< float > tensorWeight; std::vector< vnl_vector_fixed > tensorDirection; for (int i=0; ivalue()); tensorADC.push_back(m_SpinAdc.at(i)->value()); vnl_vector_fixed dir; dir[0] = m_SpinX.at(i)->value(); dir[1] = m_SpinY.at(i)->value(); dir[2] = m_SpinZ.at(i)->value(); dir.normalize(); tensorDirection.push_back(dir); tensorWeight.push_back(m_SpinWeight.at(i)->value()); } filter->SetTensorFA(tensorFA); filter->SetTensorADC(tensorADC); filter->SetTensorWeight(tensorWeight); filter->SetTensorDirection(tensorDirection); if (!m_Controls->m_SimulateBaseline->isChecked()) filter->SetSimulateBaseline(false); else filter->SetSimulateBaseline(true); filter->Update(); mitk::Image::Pointer image = mitk::GrabItkImageMemory(filter->GetOutput()); image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( gradientList ) ); image->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( bVal ) ); mitk::DiffusionPropertyHelper propertyHelper( image ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName(m_Controls->m_ImageName->text().toStdString()); GetDataStorage()->Add(node); mitk::BaseData::Pointer basedata = node->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } if (m_Controls->m_OutputNumDirectionsBox->isChecked()) { ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage(); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk( numDirImage.GetPointer() ); image->SetVolume( numDirImage->GetBufferPointer() ); mitk::DataNode::Pointer node2 = mitk::DataNode::New(); node2->SetData(image); QString name(m_Controls->m_ImageName->text()); name += "_NumDirections"; node2->SetName(name.toStdString().c_str()); GetDataStorage()->Add(node2); } if (m_Controls->m_OutputSnrImageBox->isChecked()) { ItkFloatImgType::Pointer snrImage = filter->GetSNRImage(); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk( snrImage.GetPointer() ); image->SetVolume( snrImage->GetBufferPointer() ); mitk::DataNode::Pointer node2 = mitk::DataNode::New(); node2->SetData(image); QString name(m_Controls->m_ImageName->text()); name += "_SNR"; node2->SetName(name.toStdString().c_str()); GetDataStorage()->Add(node2); } if (m_SignalRegionNodes.size()==0) return; if (m_Controls->m_OutputDirectionImagesBox->isChecked()) { typedef FilterType::ItkDirectionImageContainer ItkDirectionImageContainer; ItkDirectionImageContainer::Pointer container = filter->GetDirectionImageContainer(); for (int i=0; iSize(); i++) { FilterType::ItkDirectionImage::Pointer itkImg = container->GetElement(i); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk( itkImg.GetPointer() ); img->SetVolume( itkImg->GetBufferPointer() ); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(img); QString name(m_Controls->m_ImageName->text()); name += "_Direction"; name += QString::number(i+1); node->SetName(name.toStdString().c_str()); GetDataStorage()->Add(node); } } if (m_Controls->m_OutputVectorFieldBox->isChecked()) { mitk::BaseGeometry::Pointer geometry = image->GetGeometry(); mitk::Vector3D outImageSpacing = geometry->GetSpacing(); float minSpacing = 1; if(outImageSpacing[0]GetOutputFiberBundle(); + mitk::FiberBundle::Pointer directions = filter->GetOutputFiberBundle(); directions->SetGeometry(geometry); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(directions); QString name(m_Controls->m_ImageName->text()); name += "_VectorField"; node->SetName(name.toStdString().c_str()); node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(minSpacing)); node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false)); GetDataStorage()->Add(node); } } void QmitkDwiSoftwarePhantomView::UpdateGui() { if (!m_SignalRegionNodes.empty()) { m_Controls->m_SignalRegionBox->setVisible(true); m_Controls->m_Instruction->setVisible(false); } else { m_Controls->m_SignalRegionBox->setVisible(false); m_Controls->m_Instruction->setVisible(true); } QLayout* layout = m_Controls->m_SignalRegionBox->layout(); for (int i=0; im_SignalRegionBox->setLayout(newlayout); if (!m_SignalRegionNodes.empty()) { QLabel* label1 = new QLabel("Image"); newlayout->addWidget(label1,0,0); m_Labels.push_back(label1); QLabel* label2 = new QLabel("FA"); newlayout->addWidget(label2,0,1); m_Labels.push_back(label2); QLabel* label3 = new QLabel("ADC"); newlayout->addWidget(label3,0,2); m_Labels.push_back(label3); QLabel* label4 = new QLabel("X"); newlayout->addWidget(label4,0,03); m_Labels.push_back(label4); QLabel* label5 = new QLabel("Y"); newlayout->addWidget(label5,0,4); m_Labels.push_back(label5); QLabel* label6 = new QLabel("Z"); newlayout->addWidget(label6,0,5); m_Labels.push_back(label6); QLabel* label7 = new QLabel("Weight"); newlayout->addWidget(label7,0,6); m_Labels.push_back(label7); } for (int i=0; iGetName().c_str()); newlayout->addWidget(label,i+1,0); m_Labels.push_back(label); QDoubleSpinBox* spinFa = new QDoubleSpinBox(); spinFa->setValue(0.7); spinFa->setMinimum(0); spinFa->setMaximum(1); spinFa->setSingleStep(0.1); newlayout->addWidget(spinFa,i+1,1); m_SpinFa.push_back(spinFa); QDoubleSpinBox* spinAdc = new QDoubleSpinBox(); newlayout->addWidget(spinAdc,i+1,2); spinAdc->setMinimum(0); spinAdc->setMaximum(1); spinAdc->setSingleStep(0.001); spinAdc->setDecimals(3); spinAdc->setValue(0.001); ///// ??????????????????????????? m_SpinAdc.push_back(spinAdc); QDoubleSpinBox* spinX = new QDoubleSpinBox(); newlayout->addWidget(spinX,i+1,3); spinX->setValue(1); spinX->setMinimum(-1); spinX->setMaximum(1); spinX->setSingleStep(0.1); m_SpinX.push_back(spinX); QDoubleSpinBox* spinY = new QDoubleSpinBox(); newlayout->addWidget(spinY,i+1,4); spinY->setMinimum(-1); spinY->setMaximum(1); spinY->setSingleStep(0.1); m_SpinY.push_back(spinY); QDoubleSpinBox* spinZ = new QDoubleSpinBox(); newlayout->addWidget(spinZ,i+1,5); spinZ->setMinimum(-1); spinZ->setMaximum(1); spinZ->setSingleStep(0.1); m_SpinZ.push_back(spinZ); QDoubleSpinBox* spinWeight = new QDoubleSpinBox(); newlayout->addWidget(spinWeight,i+1,6); spinWeight->setMinimum(0); spinWeight->setMaximum(1); spinWeight->setSingleStep(0.1); spinWeight->setValue(1.0); m_SpinWeight.push_back(spinWeight); } } void QmitkDwiSoftwarePhantomView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkDwiSoftwarePhantomView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkDwiSoftwarePhantomView::OnSelectionChanged( std::vector nodes ) { m_SignalRegionNodes.clear(); // 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()) ) { bool isBinary = false; node->GetPropertyValue("binary", isBinary); if (isBinary) m_SignalRegionNodes.push_back(node); } } UpdateGui(); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.cpp index 021b60383f..3f78250193 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.cpp @@ -1,1816 +1,1816 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //=========FOR TESTING========== //random generation, number of points equal requested points // Blueberry application and interaction service #include #include // Qmitk #include "QmitkFiberBundleDeveloperView.h" #include // Qt #include // MITK #include #include #include //===needed when timeGeometry is null to invoke rendering mechansims ==== #include #include #include "mitkModuleRegistry.h" // VTK #include //for randomized FiberStructure #include //for fiberStructure #include //for fiberStructure #include //for geometry //ITK #include //============================================== //======== W O R K E R S ____ S T A R T ======== //============================================== /*=================================================================================== * THIS METHOD IMPLEMENTS THE ACTIONS WHICH SHALL BE EXECUTED by the according THREAD * --generate FiberIDs--*/ QmitkFiberIDWorker::QmitkFiberIDWorker(QThread* hostingThread, Package4WorkingThread itemPackage) : m_itemPackage(itemPackage), m_hostingThread(hostingThread) { } void QmitkFiberIDWorker::run() { if(m_itemPackage.st_Controls->checkBoxMonitorFiberThreads->isChecked()) m_itemPackage.st_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_RUNNING); /* MEASUREMENTS AND FANCY GUI EFFECTS * accurate time measurement using ITK timeProbe*/ itk::TimeProbe clock; clock.Start(); //set GUI representation of timer to 0, is essential for correct timer incrementation m_itemPackage.st_Controls->infoTimerGenerateFiberIds->setText(QString::number(0)); m_itemPackage.st_FancyGUITimer1->start(); //do processing m_itemPackage.st_FBX->GenerateFiberIds(); /* MEASUREMENTS AND FANCY GUI EFFECTS CLEANUP */ clock.Stop(); m_itemPackage.st_FancyGUITimer1->stop(); m_itemPackage.st_Controls->infoTimerGenerateFiberIds->setText( QString::number(clock.GetTotal()) ); delete m_itemPackage.st_FancyGUITimer1; // fancy timer is not needed anymore m_hostingThread->quit(); } /*=================================================================================== * THIS METHOD IMPLEMENTS THE ACTIONS WHICH SHALL BE EXECUTED by the according THREAD * -- extract fibers by given PlanarFigure --*/ QmitkFiberExtractorWorker::QmitkFiberExtractorWorker(QThread* hostingThread, Package4WorkingThread itemPackage) : m_itemPackage(itemPackage), m_hostingThread(hostingThread) { } void QmitkFiberExtractorWorker::run() { if(m_itemPackage.st_Controls->checkBoxMonitorFiberThreads->isChecked()) m_itemPackage.st_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_RUNNING); /* MEASUREMENTS AND FANCY GUI EFFECTS * accurate time measurement using ITK timeProbe*/ itk::TimeProbe clock; clock.Start(); //set GUI representation of timer to 0, is essential for correct timer incrementation m_itemPackage.st_Controls->infoTimerExtractFibers->setText(QString::number(0)); m_itemPackage.st_FancyGUITimer1->start(); //do processing std::vector fibIds = m_itemPackage.st_FBX->ExtractFiberIdSubset(m_itemPackage.st_PlanarFigure); //generate new fiberbundle by fiber iDs vtkSmartPointer newFBPolyData = m_itemPackage.st_FBX->GeneratePolyDataByIds(fibIds); - // call function to convert fiberstructure into fiberbundleX and pass it to datastorage + // call function to convert fiberstructure into FiberBundle and pass it to datastorage (m_itemPackage.st_host->*m_itemPackage.st_pntr_to_Method_PutFibersToDataStorage)(newFBPolyData); /* MEASUREMENTS AND FANCY GUI EFFECTS CLEANUP */ clock.Stop(); m_itemPackage.st_FancyGUITimer1->stop(); m_itemPackage.st_Controls->infoTimerExtractFibers->setText( QString::number(clock.GetTotal()) ); delete m_itemPackage.st_FancyGUITimer1; // fancy timer is not needed anymore m_hostingThread->quit(); } /*=================================================================================== * THIS METHOD IMPLEMENTS THE ACTIONS WHICH SHALL BE EXECUTED by the according THREAD * --set FA values to fiberbundle--*/ QmitkFiberColoringWorker::QmitkFiberColoringWorker(QThread* hostingThread, Package4WorkingThread itemPackage) : m_itemPackage(itemPackage) , m_hostingThread(hostingThread) { } void QmitkFiberColoringWorker::run() { if(m_itemPackage.st_Controls->checkBoxMonitorFiberThreads->isChecked()) m_itemPackage.st_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_RUNNING); /* MEASUREMENTS AND FANCY GUI EFFECTS * accurate time measurement using ITK timeProbe*/ itk::TimeProbe clock; clock.Start(); //set GUI representation of timer to 0, is essential for correct timer incrementation m_itemPackage.st_Controls->infoTimerColorCoding->setText(QString::number(0)); m_itemPackage.st_FancyGUITimer1->start(); //do processing if(m_itemPackage.st_Controls->radioButton_ColorOrient->isChecked()) { m_itemPackage.st_FBX->DoColorCodingOrientationBased(); } else if(m_itemPackage.st_Controls->radioButton_ColorFA->isChecked()) { m_itemPackage.st_FBX->DoColorCodingFaBased(); } else if(m_itemPackage.st_Controls->radioButton_OpacityFA->isChecked()) { // m_itemPackage.st_FBX->SetColorCoding(""); m_itemPackage.st_PassedDataNode->SetOpacity(0.999); m_itemPackage.st_FBX->DoUseFaFiberOpacity(); } else if(m_itemPackage.st_Controls->radioButton_ColorCustom->isChecked()){ - m_itemPackage.st_FBX->SetColorCoding(mitk::FiberBundleX::COLORCODING_CUSTOM); + m_itemPackage.st_FBX->SetColorCoding(mitk::FiberBundle::COLORCODING_CUSTOM); } /* MEASUREMENTS AND FANCY GUI EFFECTS CLEANUP */ clock.Stop(); m_itemPackage.st_FancyGUITimer1->stop(); m_itemPackage.st_Controls->infoTimerColorCoding->setText( QString::number(clock.GetTotal()) ); delete m_itemPackage.st_FancyGUITimer1; // fancy timer is not needed anymore m_hostingThread->quit(); } QmitkFiberFeederFAWorker::QmitkFiberFeederFAWorker(QThread* hostingThread, Package4WorkingThread itemPackage) : m_itemPackage(itemPackage), m_hostingThread(hostingThread) { } void QmitkFiberFeederFAWorker::run() { if(m_itemPackage.st_Controls->checkBoxMonitorFiberThreads->isChecked()) m_itemPackage.st_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_RUNNING); /* MEASUREMENTS AND FANCY GUI EFFECTS * accurate time measurement using ITK timeProbe */ itk::TimeProbe clock; clock.Start(); //set GUI representation of timer to 0, is essential for correct timer incrementation m_itemPackage.st_Controls->infoTimerSetFA->setText(QString::number(0)); m_itemPackage.st_FancyGUITimer1->start(); //do processing mitk::Image::Pointer FAImg = dynamic_cast(m_itemPackage.st_PassedDataNode->GetData()); if(FAImg.IsNotNull()) m_itemPackage.st_FBX->SetFAMap(FAImg); /* MEASUREMENTS AND FANCY GUI EFFECTS CLEANUP */ clock.Stop(); m_itemPackage.st_FancyGUITimer1->stop(); m_itemPackage.st_Controls->infoTimerSetFA->setText( QString::number(clock.GetTotal()) ); disconnect(m_itemPackage.st_FancyGUITimer1); delete m_itemPackage.st_FancyGUITimer1; // fancy timer is not needed anymore m_hostingThread->quit(); } /*=================================================================================== * THIS METHOD IMPLEMENTS THE ACTIONS WHICH SHALL BE EXECUTED by the according THREAD * --generate random fibers--*/ QmitkFiberGenerateRandomWorker::QmitkFiberGenerateRandomWorker(QThread* hostingThread, Package4WorkingThread itemPackage) : m_itemPackage(itemPackage), m_hostingThread(hostingThread) { } void QmitkFiberGenerateRandomWorker::run() { if(m_itemPackage.st_Controls->checkBoxMonitorFiberThreads->isChecked()) m_itemPackage.st_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_RUNNING); /* MEASUREMENTS AND FANCY GUI EFFECTS */ //MAKE SURE by yourself THAT NOTHING ELSE THAN A NUMBER IS SET IN THAT LABEL m_itemPackage.st_Controls->infoTimerGenerateFiberBundle->setText(QString::number(0)); m_itemPackage.st_FancyGUITimer1->start(); //do processing, generateRandomFibers int numOfFibers = m_itemPackage.st_Controls->boxFiberNumbers->value(); int distrRadius = m_itemPackage.st_Controls->boxDistributionRadius->value(); int numOfPoints = numOfFibers * distrRadius; std::vector< std::vector > fiberStorage; for (int i=0; i a; fiberStorage.push_back( a ); } /* Generate Point Cloud */ vtkSmartPointer randomPoints = vtkSmartPointer::New(); randomPoints->SetCenter(0.0, 0.0, 0.0); randomPoints->SetNumberOfPoints(numOfPoints); randomPoints->SetRadius(distrRadius); randomPoints->Update(); vtkPoints* pnts = randomPoints->GetOutput()->GetPoints(); /* ASSIGN EACH POINT TO A RANDOM FIBER */ srand((unsigned)time(0)); // init randomizer for (int i=0; iGetNumberOfPoints(); ++i) { //generate random number between 0 and numOfFibers-1 int random_integer; random_integer = (rand()%numOfFibers); //add current point to random fiber fiberStorage.at(random_integer).push_back(i); // MITK_INFO << "point" << i << " |" << pnts->GetPoint(random_integer)[0] << "|" << pnts->GetPoint(random_integer)[1]<< "|" << pnts->GetPoint(random_integer)[2] << "| into fiber" << random_integer; } // initialize accurate time measurement itk::TimeProbe clock; clock.Start(); /* GENERATE VTK POLYLINES OUT OF FIBERSTORAGE */ vtkSmartPointer linesCell = vtkSmartPointer::New(); // Host vtkPolyLines linesCell->Allocate(pnts->GetNumberOfPoints()*2); //allocate for each cellindex also space for the pointId, e.g. [idx | pntID] for (long i=0; i singleFiber = fiberStorage.at(i); vtkSmartPointer fiber = vtkSmartPointer::New(); fiber->GetPointIds()->SetNumberOfIds((int)singleFiber.size()); for (long si=0; siGetPointIds()->SetId( si, singleFiber.at(si) ); } linesCell->InsertNextCell(fiber); } /* checkpoint for cellarray allocation */ if ( (linesCell->GetSize()/pnts->GetNumberOfPoints()) != 2 ) //e.g. size: 12, number of points:6 .... each cell hosts point ids (6 ids) + cell index for each idPoint. 6 * 2 = 12 { MITK_INFO << "RANDOM FIBER ALLOCATION CAN NOT BE TRUSTED ANYMORE! Correct leak or remove command: linesCell->Allocate(pnts->GetNumberOfPoints()*2) but be aware of possible loss in performance."; } /* HOSTING POLYDATA FOR RANDOM FIBERSTRUCTURE */ vtkSmartPointer PDRandom = vtkSmartPointer::New(); //could also be a standard pointer instead of smartpointer cuz ther is no need to delete because data is managed in datastorage. PDRandom->SetPoints(pnts); PDRandom->SetLines(linesCell); // accurate timer measurement stop clock.Stop(); //MITK_INFO << "=====Assambling random Fibers to Polydata======\nMean: " << clock.GetMean() << " Total: " << clock.GetTotal() << std::endl; - // call function to convert fiberstructure into fiberbundleX and pass it to datastorage + // call function to convert fiberstructure into FiberBundle and pass it to datastorage (m_itemPackage.st_host->*m_itemPackage.st_pntr_to_Method_PutFibersToDataStorage)(PDRandom); /* MEASUREMENTS AND FANCY GUI EFFECTS CLEANUP */ m_itemPackage.st_FancyGUITimer1->stop(); m_itemPackage.st_Controls->infoTimerGenerateFiberBundle->setText( QString::number(clock.GetTotal()) ); delete m_itemPackage.st_FancyGUITimer1; // fancy timer is not needed anymore m_hostingThread->quit(); } /*=================================================================================== * THIS METHOD IMPLEMENTS THE ACTIONS WHICH SHALL BE EXECUTED by the according THREAD * --update GUI elements of thread monitor-- * implementation not thread safe, not needed so far because * there exists only 1 thread for fiberprocessing * for threadsafety, you need to implement checking mechanisms in methods "::threadFor...." */ QmitkFiberThreadMonitorWorker::QmitkFiberThreadMonitorWorker( QThread* hostingThread, Package4WorkingThread itemPackage ) : m_itemPackage(itemPackage) , m_hostingThread(hostingThread) , m_pixelstepper(10) //for next rendering call, move object 10px , m_steppingDistance(220) //use only a multiple value of pixelstepper, x-axis border for fancy stuff { //set timers m_thtimer_initMonitor = new QTimer; m_thtimer_initMonitor->setInterval(10); m_thtimer_initMonitorSetFinalPosition = new QTimer; m_thtimer_initMonitorSetFinalPosition->setInterval(10); m_thtimer_initMonitorSetMasks = new QTimer; m_thtimer_initMonitorSetFinalPosition->setInterval(10); m_thtimer_threadStarted = new QTimer; m_thtimer_threadStarted->setInterval(50); m_thtimer_threadFinished = new QTimer; m_thtimer_threadFinished->setInterval(50); m_thtimer_threadTerminated = new QTimer; m_thtimer_threadTerminated->setInterval(50); connect (m_thtimer_initMonitor, SIGNAL( timeout()), this, SLOT( fancyMonitorInitialization() ) ); connect ( m_thtimer_initMonitorSetFinalPosition, SIGNAL( timeout() ), this, SLOT( fancyMonitorInitializationFinalPos() ) ); connect ( m_thtimer_initMonitorSetMasks, SIGNAL( timeout() ), this, SLOT( fancyMonitorInitializationMask() ) ); connect (m_thtimer_threadStarted, SIGNAL( timeout()), this, SLOT( fancyTextFading_threadStarted() ) ); connect (m_thtimer_threadFinished, SIGNAL( timeout()), this, SLOT( fancyTextFading_threadFinished() ) ); connect (m_thtimer_threadTerminated, SIGNAL( timeout()), this, SLOT( fancyTextFading_threadTerminated() ) ); //first, the current text shall turn transparent m_decreaseOpacity_threadStarted = true; m_decreaseOpacity_threadFinished = true; m_decreaseOpacity_threadTerminated = true; } void QmitkFiberThreadMonitorWorker::run() { } void QmitkFiberThreadMonitorWorker::initializeMonitor() { //fancy configuration of animation start mitk::Point2D pntOpen; pntOpen[0] = 118; pntOpen[1] = 10; mitk::Point2D headPos; headPos[0] = 19; headPos[1] = 10; mitk::Point2D statusPos; statusPos[0] = 105; statusPos[1] = 23; mitk::Point2D startedPos; startedPos[0] = 68; startedPos[1] = 10; mitk::Point2D finishedPos; finishedPos[0] = 143; finishedPos[1] = 10; mitk::Point2D terminatedPos; terminatedPos[0] = 240; terminatedPos[1] = 10; m_itemPackage.st_FBX_Monitor->setBracketClosePosition(pntOpen); m_itemPackage.st_FBX_Monitor->setBracketOpenPosition(pntOpen); m_itemPackage.st_FBX_Monitor->setHeadingPosition(headPos); m_itemPackage.st_FBX_Monitor->setMaskPosition(headPos); m_itemPackage.st_FBX_Monitor->setStatusPosition(statusPos); m_itemPackage.st_FBX_Monitor->setStartedPosition(startedPos); m_itemPackage.st_FBX_Monitor->setFinishedPosition(finishedPos); m_itemPackage.st_FBX_Monitor->setTerminatedPosition(terminatedPos); m_thtimer_initMonitor->start(); } void QmitkFiberThreadMonitorWorker::setThreadStatus(QString status) { m_itemPackage.st_FBX_Monitor->setStatus(status); m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } /* Methods to set status of running threads * Following three methods are usually called - before a thread starts and - a thread is finished or terminated */ void QmitkFiberThreadMonitorWorker::threadForFiberProcessingStarted() { if(!m_thtimer_threadStarted->isActive()) { m_thtimer_threadStarted->start(); } else { //fast change without fancy stuff, needed to keep threaddebugger info up to date int counter = m_itemPackage.st_FBX_Monitor->getStarted(); m_itemPackage.st_FBX_Monitor->setStarted(++counter); } } void QmitkFiberThreadMonitorWorker::threadForFiberProcessingFinished() { if(!m_thtimer_threadFinished->isActive()) { m_thtimer_threadFinished->start(); } else { //fast change without fancy stuff int counter = m_itemPackage.st_FBX_Monitor->getFinished(); m_itemPackage.st_FBX_Monitor->setFinished(++counter); } } void QmitkFiberThreadMonitorWorker::threadForFiberProcessingTerminated() { if(!m_thtimer_threadTerminated->isActive()) { m_thtimer_threadTerminated->start(); } else { //fast change without fancy stuff int counter = m_itemPackage.st_FBX_Monitor->getTerminated(); m_itemPackage.st_FBX_Monitor->setTerminated(++counter); } } /* Helper methods for fancy fading efx for thread monitor */ void QmitkFiberThreadMonitorWorker::fancyTextFading_threadStarted() { if (m_decreaseOpacity_threadStarted) { int startedOpacity = m_itemPackage.st_FBX_Monitor->getStartedOpacity(); m_itemPackage.st_FBX_Monitor->setStartedOpacity( --startedOpacity ); if (startedOpacity == 0) { int counter = m_itemPackage.st_FBX_Monitor->getStarted(); m_itemPackage.st_FBX_Monitor->setStarted(++counter); m_decreaseOpacity_threadStarted = false; } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } else { int startedOpacity = m_itemPackage.st_FBX_Monitor->getStartedOpacity(); m_itemPackage.st_FBX_Monitor->setStartedOpacity( ++startedOpacity ); if (startedOpacity >= 10) { m_thtimer_threadStarted->stop(); m_decreaseOpacity_threadStarted = true; //set back to true, cuz next iteration shall decrease opacity as well } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } } void QmitkFiberThreadMonitorWorker::fancyTextFading_threadFinished() { if (m_decreaseOpacity_threadFinished) { int finishedOpacity = m_itemPackage.st_FBX_Monitor->getFinishedOpacity(); m_itemPackage.st_FBX_Monitor->setFinishedOpacity( --finishedOpacity ); if (finishedOpacity == 0) { int counter = m_itemPackage.st_FBX_Monitor->getFinished(); m_itemPackage.st_FBX_Monitor->setFinished(++counter); m_decreaseOpacity_threadFinished = false; } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } else { int finishedOpacity = m_itemPackage.st_FBX_Monitor->getFinishedOpacity(); m_itemPackage.st_FBX_Monitor->setFinishedOpacity( ++finishedOpacity ); if (finishedOpacity >= 10) { m_thtimer_threadFinished->stop(); m_decreaseOpacity_threadFinished = true; //set back to true, cuz next iteration shall decrease opacity as well } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } } void QmitkFiberThreadMonitorWorker::fancyTextFading_threadTerminated() { if (m_decreaseOpacity_threadTerminated) { int terminatedOpacity = m_itemPackage.st_FBX_Monitor->getTerminatedOpacity(); m_itemPackage.st_FBX_Monitor->setTerminatedOpacity( --terminatedOpacity ); if (terminatedOpacity == 0) { int counter = m_itemPackage.st_FBX_Monitor->getTerminated(); m_itemPackage.st_FBX_Monitor->setTerminated(++counter); m_decreaseOpacity_threadTerminated = false; } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } else { int terminatedOpacity = m_itemPackage.st_FBX_Monitor->getTerminatedOpacity(); m_itemPackage.st_FBX_Monitor->setTerminatedOpacity( ++terminatedOpacity ); if (terminatedOpacity >= 10) { m_thtimer_threadTerminated->stop(); m_decreaseOpacity_threadTerminated = true; //set back to true, cuz next iteration shall decrease opacity as well } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } } void QmitkFiberThreadMonitorWorker::fancyMonitorInitialization() { mitk::Point2D pntClose = m_itemPackage.st_FBX_Monitor->getBracketClosePosition(); //possible bottleneck, set pntClose to member mitk::Point2D pntOpen = m_itemPackage.st_FBX_Monitor->getBracketOpenPosition(); //possible bottleneck, set pntClose to member pntClose[0] += m_pixelstepper; pntOpen[0] -= m_pixelstepper; //MITK_INFO << pntClose[0] << " " << pntOpen[0]; m_itemPackage.st_FBX_Monitor->setBracketClosePosition(pntClose); m_itemPackage.st_FBX_Monitor->setBracketOpenPosition(pntOpen); int opacity = m_itemPackage.st_FBX_Monitor->getHeadingOpacity() + 1; if (opacity > 10) opacity = 10; m_itemPackage.st_FBX_Monitor->setHeadingOpacity(opacity); if (pntClose[0] >= m_steppingDistance) { if (m_itemPackage.st_FBX_Monitor->getHeadingOpacity() != 10 ) { m_itemPackage.st_FBX_Monitor->setHeadingOpacity(10); m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } m_thtimer_initMonitor->stop(); //position them to obt y=25 m_thtimer_initMonitorSetFinalPosition->start(); } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } void QmitkFiberThreadMonitorWorker::fancyMonitorInitializationFinalPos() { //get y pos of mitk::Point2D pntClose = m_itemPackage.st_FBX_Monitor->getBracketClosePosition(); mitk::Point2D pntOpen = m_itemPackage.st_FBX_Monitor->getBracketOpenPosition(); mitk::Point2D pntHead = m_itemPackage.st_FBX_Monitor->getHeadingPosition(); pntClose[1] += 5; pntOpen[1] += 5; pntHead[1] += 5; m_itemPackage.st_FBX_Monitor->setBracketClosePosition(pntClose); m_itemPackage.st_FBX_Monitor->setBracketOpenPosition(pntOpen); m_itemPackage.st_FBX_Monitor->setHeadingPosition(pntHead); if (pntClose[1] >= 35) { //35 = y position m_thtimer_initMonitorSetFinalPosition->stop(); //now init mask of labels m_thtimer_initMonitorSetMasks->start(); } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } void QmitkFiberThreadMonitorWorker::fancyMonitorInitializationMask() { //increase opacity int opacity = m_itemPackage.st_FBX_Monitor->getMaskOpacity(); opacity++; m_itemPackage.st_FBX_Monitor->setMaskOpacity(opacity); m_itemPackage.st_FBX_Monitor->setStartedOpacity(opacity); m_itemPackage.st_FBX_Monitor->setFinishedOpacity(opacity); m_itemPackage.st_FBX_Monitor->setTerminatedOpacity(opacity); m_itemPackage.st_FBX_Monitor->setStatusOpacity(opacity); if (opacity >=10) { m_thtimer_initMonitorSetMasks->stop(); } m_itemPackage.st_ThreadMonitorDataNode->Modified(); m_itemPackage.st_MultiWidget->RequestUpdate(); } //============================================== //======== W O R K E R S ________ E N D ======== //============================================== //========#########################===============###########################=====================######################### //========#########################===============###########################=====================######################### //========#########################===============###########################=====================######################### //========#########################===============###########################=====================######################### //========#########################===============###########################=====================######################### // HERE STARTS THE ACTUAL FIBERBUNDLE DEVELOPER VIEW IMPLEMENTATION //========#########################===============###########################=====================######################### //========#########################===============###########################=====================######################### //========#########################===============###########################=====================######################### //========#########################===============###########################=====================######################### const std::string QmitkFiberBundleDeveloperView::VIEW_ID = "org.mitk.views.fiberbundledeveloper"; const std::string id_DataManager = "org.mitk.views.datamanager"; using namespace berry; QmitkFiberBundleDeveloperView::QmitkFiberBundleDeveloperView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) , m_FiberIDGenerator( NULL) , m_GeneratorFibersRandom( NULL ) , m_FiberFeederFASlave( NULL ) , m_FiberColoringSlave(NULL) , m_FiberExtractor(NULL) , m_fiberMonitorIsOn( false ) , m_CircleCounter( 0 ) , m_suppressSignal(false) { m_hostThread = new QThread; m_threadInProgress = false; } // Destructor QmitkFiberBundleDeveloperView::~QmitkFiberBundleDeveloperView() { - //m_FiberBundleX->Delete(); using weakPointer, therefore no delete necessary + //m_FiberBundle->Delete(); using weakPointer, therefore no delete necessary delete m_hostThread; } void QmitkFiberBundleDeveloperView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done in QtDesigner, etc. if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkFiberBundleDeveloperViewControls; m_Controls->setupUi( parent ); /*=========INITIALIZE BUTTON CONFIGURATION ================*/ m_Controls->radioButton_directionX->setEnabled(false); m_Controls->radioButton_directionY->setEnabled(false); m_Controls->radioButton_directionZ->setEnabled(false); m_Controls->buttonGenerateFiberIds->setEnabled(false); m_Controls->buttonGenerateFibers->setEnabled(true); m_Controls->buttonColorFibers->setEnabled(false); m_Controls->ddAvailableColorcodings->setEnabled(false); m_Controls->buttonExtractFibers->setEnabled(false); m_Controls->button_FAMap->setEnabled(true); m_Controls->buttonSMFibers->setEnabled(false);//not yet implemented m_Controls->buttonVtkDecimatePro->setEnabled(false);//not yet implemented m_Controls->buttonVtkSmoothPD->setEnabled(false);//not yet implemented m_Controls->buttonGenerateTubes->setEnabled(false);//not yet implemented connect( m_Controls->buttonGenerateFibers, SIGNAL(clicked()), this, SLOT(DoGenerateFibers()) ); connect( m_Controls->buttonGenerateFiberIds, SIGNAL(clicked()), this, SLOT(DoGenerateFiberIDs()) ); connect( m_Controls->button_FAMapExecute, SIGNAL(clicked()), this, SLOT(DoSetFAValues()) ); connect( m_Controls->button_FAMap, SIGNAL(clicked()), this, SLOT(DoSetFAMap()) ); connect( m_Controls->buttonExtractFibers, SIGNAL(clicked()), this, SLOT(DoExtractFibers()) ); connect( m_Controls->radioButton_directionRandom, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) ); connect( m_Controls->radioButton_directionX, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) ); connect( m_Controls->radioButton_directionY, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) ); connect( m_Controls->radioButton_directionZ, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) ); connect( m_Controls->toolBox, SIGNAL(currentChanged ( int ) ), this, SLOT(SelectionChangedToolBox(int)) ); connect( m_Controls->m_CircleButton, SIGNAL( clicked() ), this, SLOT( ActionDrawEllipseTriggered() ) ); connect( m_Controls->buttonColorFibers, SIGNAL(clicked()), this, SLOT(DoColorFibers()) ); // connect( m_Controls->ddAvailableColorcodings, SIGNAL(currentIndexChanged(int)), this, SLOT(SetCurrentColorCoding(int) )); connect( m_Controls->ddAvailableColorcodings, SIGNAL(currentIndexChanged(int)), this, SLOT(SetCurrentColorCoding(int) )); connect( m_Controls->checkBoxMonitorFiberThreads, SIGNAL(stateChanged(int)), this, SLOT(DoMonitorFiberThreads(int)) ); } // Checkpoint for fiber ORIENTATION if ( m_DirectionRadios.empty() ) { m_DirectionRadios.insert(0, m_Controls->radioButton_directionRandom); m_DirectionRadios.insert(1, m_Controls->radioButton_directionX); m_DirectionRadios.insert(2, m_Controls->radioButton_directionY); m_DirectionRadios.insert(3, m_Controls->radioButton_directionZ); } // set GUI elements of FiberGenerator to according configuration DoUpdateGenerateFibersWidget(); } /* THIS METHOD UPDATES ALL GUI ELEMENTS OF QGroupBox DEPENDING ON CURRENTLY SELECTED * RADIO BUTTONS */ void QmitkFiberBundleDeveloperView::DoUpdateGenerateFibersWidget() { //get selected radioButton QString fibDirection; //stores the object_name of selected radiobutton QVector::const_iterator i; for (i = m_DirectionRadios.begin(); i != m_DirectionRadios.end(); ++i) { QRadioButton* rdbtn = *i; if (rdbtn->isChecked()) fibDirection = rdbtn->objectName(); } if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_RANDOM ) { // disable radiobuttons if (m_Controls->boxFiberMinLength->isEnabled()) m_Controls->boxFiberMinLength->setEnabled(false); if (m_Controls->labelFiberMinLength->isEnabled()) m_Controls->labelFiberMinLength->setEnabled(false); if (m_Controls->boxFiberMaxLength->isEnabled()) m_Controls->boxFiberMaxLength->setEnabled(false); if (m_Controls->labelFiberMaxLength->isEnabled()) m_Controls->labelFiberMaxLength->setEnabled(false); //enable radiobuttons if (!m_Controls->labelFibersTotal->isEnabled()) m_Controls->labelFibersTotal->setEnabled(true); if (!m_Controls->boxFiberNumbers->isEnabled()) m_Controls->boxFiberNumbers->setEnabled(true); if (!m_Controls->labelDistrRadius->isEnabled()) m_Controls->labelDistrRadius->setEnabled(true); if (!m_Controls->boxDistributionRadius->isEnabled()) m_Controls->boxDistributionRadius->setEnabled(true); } else { // disable radiobuttons if (m_Controls->labelDistrRadius->isEnabled()) m_Controls->labelDistrRadius->setEnabled(false); if (m_Controls->boxDistributionRadius->isEnabled()) m_Controls->boxDistributionRadius->setEnabled(false); //enable radiobuttons if (!m_Controls->labelFibersTotal->isEnabled()) m_Controls->labelFibersTotal->setEnabled(true); if (!m_Controls->boxFiberNumbers->isEnabled()) m_Controls->boxFiberNumbers->setEnabled(true); if (!m_Controls->boxFiberMinLength->isEnabled()) m_Controls->boxFiberMinLength->setEnabled(true); if (!m_Controls->labelFiberMinLength->isEnabled()) m_Controls->labelFiberMinLength->setEnabled(true); if (!m_Controls->boxFiberMaxLength->isEnabled()) m_Controls->boxFiberMaxLength->setEnabled(true); if (!m_Controls->labelFiberMaxLength->isEnabled()) m_Controls->labelFiberMaxLength->setEnabled(true); } } void QmitkFiberBundleDeveloperView::DoGenerateFibers() { // GET SELECTED FIBER DIRECTION QString fibDirection; //stores the object_name of selected radiobutton QVector::const_iterator i; for (i = m_DirectionRadios.begin(); i != m_DirectionRadios.end(); ++i) { QRadioButton* rdbtn = *i; if (rdbtn->isChecked()) fibDirection = rdbtn->objectName(); } // vtkPolyData* output; // FiberPD stores the generated PolyData... going to be generated in thread if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_RANDOM ) { // build polydata with random lines and fibers // output = GenerateVtkFibersRandom(); } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_X ) { // build polydata with XDirection fibers //output = GenerateVtkFibersDirectionX(); } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Y ) { // build polydata with YDirection fibers // output = GenerateVtkFibersDirectionY(); } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Z ) { // build polydata with ZDirection fibers // output = GenerateVtkFibersDirectionZ(); } } void QmitkFiberBundleDeveloperView::DoExtractFibers() { /* ===== TIMER CONFIGURATIONS for visual effect ====== * start and stop is called in Thread */ QTimer *localTimer = new QTimer; // timer must be initialized here, otherwise timer is not fancy enough localTimer->setInterval( 10 ); connect( localTimer, SIGNAL(timeout()), this, SLOT( UpdateExtractFibersTimer()) ); struct Package4WorkingThread ItemPackageForExtractor; - ItemPackageForExtractor.st_FBX = m_FiberBundleX; + ItemPackageForExtractor.st_FBX = m_FiberBundle; ItemPackageForExtractor.st_Controls = m_Controls; ItemPackageForExtractor.st_FancyGUITimer1 = localTimer; ItemPackageForExtractor.st_host = this; //needed to access method "PutFibersToDataStorage()" ItemPackageForExtractor.st_pntr_to_Method_PutFibersToDataStorage = &QmitkFiberBundleDeveloperView::PutFibersToDataStorage; //actual functor calling method putFibersToDataStorage ItemPackageForExtractor.st_PlanarFigure = m_PlanarFigure; //set element for thread monitoring if (m_fiberMonitorIsOn) ItemPackageForExtractor.st_fiberThreadMonitorWorker = m_fiberThreadMonitorWorker; if (m_threadInProgress) return; //maybe popup window saying, working thread still in progress...pls wait m_FiberExtractor = new QmitkFiberExtractorWorker(m_hostThread, ItemPackageForExtractor); m_FiberExtractor->moveToThread(m_hostThread); //connections connect(m_hostThread, SIGNAL(started()), this, SLOT( BeforeThread_FiberExtraction() )); connect(m_hostThread, SIGNAL(started()), m_FiberExtractor, SLOT( run() )); connect(m_hostThread, SIGNAL(finished()), this, SLOT( AfterThread_FiberExtraction() )); connect(m_hostThread, SIGNAL(terminated()), this, SLOT( AfterThread_FiberExtraction() )); m_hostThread->start(QThread::HighestPriority) ; } void QmitkFiberBundleDeveloperView::UpdateExtractFibersTimer() { // Make sure that thread has set according info-label to number! here we do not check if value is numeric! shall be done in beforeThreadstarted() QString crntValue = m_Controls->infoTimerExtractFibers->text(); int tmpVal = crntValue.toInt(); m_Controls->infoTimerExtractFibers->setText(QString::number(++tmpVal)); m_Controls->infoTimerExtractFibers->update(); } void QmitkFiberBundleDeveloperView::BeforeThread_FiberExtraction() { m_threadInProgress = true; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingStarted(); //m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_STARTED); } } void QmitkFiberBundleDeveloperView::AfterThread_FiberExtraction() { m_threadInProgress = false; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingFinished(); m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_IDLE); } // disconnect(m_hostThread, 0, 0, 0); m_hostThread->disconnect(); // m_FiberExtractor->disconnect(); delete m_FiberExtractor; m_FiberBundleNode->Modified(); m_MultiWidget->RequestUpdate(); } void QmitkFiberBundleDeveloperView::PutFibersToDataStorage( vtkSmartPointer threadOutput) { MITK_INFO << "lines: " << threadOutput->GetNumberOfLines() << "pnts: " << threadOutput->GetNumberOfPoints(); //qthread mutex lock - mitk::FiberBundleX::Pointer FB = mitk::FiberBundleX::New(threadOutput); + mitk::FiberBundle::Pointer FB = mitk::FiberBundle::New(threadOutput); mitk::DataNode::Pointer FBNode; FBNode = mitk::DataNode::New(); - FBNode->SetName("FiberBundleX"); + FBNode->SetName("FiberBundle"); FBNode->SetData(FB); FBNode->SetVisibility(true); FBNode->SetOpacity(1.0); GetDataStorage()->Add(FBNode); FBNode->Modified(); const mitk::PlaneGeometry * tsgeo = m_MultiWidget->GetTimeNavigationController()->GetCurrentPlaneGeometry(); if (tsgeo == NULL) { /* GetDataStorage()->Modified etc. have no effect, therefore proceed as followed below */ // 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 = GetDataStorage()->GetSubset(pred); // calculate bounding geometry of these nodes mitk::TimeGeometry::Pointer bounds = GetDataStorage()->ComputeBoundingGeometry3D(rs); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } else { GetDataStorage()->Modified(); m_MultiWidget->RequestUpdate(); //necessary?? } //qthread mutex unlock } void QmitkFiberBundleDeveloperView::PutFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name) { mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetName(name.toStdString()); newNode->SetData(figure); std::vector selectedNodes = GetDataManagerSelection(); for(unsigned int i = 0; i < selectedNodes.size(); i++) { selectedNodes[i]->SetSelected(false); } newNode->SetSelected(true); 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) ); 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 this->GetDataStorage()->Add(newNode); } /* * Generate polydata of random fibers */ void QmitkFiberBundleDeveloperView::GenerateVtkFibersRandom() { /* ===== TIMER CONFIGURATIONS for visual effect ====== * start and stop is called in Thread */ QTimer *localTimer = new QTimer; // timer must be initialized here, otherwise timer is not fancy enough localTimer->setInterval( 10 ); connect( localTimer, SIGNAL(timeout()), this, SLOT(UpdateGenerateRandomFibersTimer()) ); struct Package4WorkingThread ItemPackageForRandomGenerator; - ItemPackageForRandomGenerator.st_FBX = m_FiberBundleX; + ItemPackageForRandomGenerator.st_FBX = m_FiberBundle; ItemPackageForRandomGenerator.st_Controls = m_Controls; ItemPackageForRandomGenerator.st_FancyGUITimer1 = localTimer; ItemPackageForRandomGenerator.st_host = this; //needed to access method "PutFibersToDataStorage()" ItemPackageForRandomGenerator.st_pntr_to_Method_PutFibersToDataStorage = &QmitkFiberBundleDeveloperView::PutFibersToDataStorage; //actual functor calling method putFibersToDataStorage //set element for thread monitoring if (m_fiberMonitorIsOn) ItemPackageForRandomGenerator.st_fiberThreadMonitorWorker = m_fiberThreadMonitorWorker; if (m_threadInProgress) return; //maybe popup window saying, working thread still in progress...pls wait m_GeneratorFibersRandom = new QmitkFiberGenerateRandomWorker(m_hostThread, ItemPackageForRandomGenerator); m_GeneratorFibersRandom->moveToThread(m_hostThread); connect(m_hostThread, SIGNAL(started()), this, SLOT( BeforeThread_GenerateFibersRandom()) ); connect(m_hostThread, SIGNAL(started()), m_GeneratorFibersRandom, SLOT(run()) ); connect(m_hostThread, SIGNAL(finished()), this, SLOT(AfterThread_GenerateFibersRandom()) ); connect(m_hostThread, SIGNAL(terminated()), this, SLOT(AfterThread_GenerateFibersRandom()) ); m_hostThread->start(QThread::LowestPriority); } void QmitkFiberBundleDeveloperView::UpdateColorFibersTimer() { // Make sure that thread has set according info-label to number! here we do not check if value is numeric! QString crntValue = m_Controls->infoTimerColorCoding->text(); int tmpVal = crntValue.toInt(); m_Controls->infoTimerColorCoding->setText(QString::number(++tmpVal)); m_Controls->infoTimerColorCoding->update(); } void QmitkFiberBundleDeveloperView::UpdateGenerateRandomFibersTimer() { // Make sure that thread has set according info-label to number! here we do not check if value is numeric! QString crntValue = m_Controls->infoTimerGenerateFiberBundle->text(); int tmpVal = crntValue.toInt(); m_Controls->infoTimerGenerateFiberBundle->setText(QString::number(++tmpVal)); m_Controls->infoTimerGenerateFiberBundle->update(); } void QmitkFiberBundleDeveloperView::UpdateSetFAValuesTimer() { // Make sure that thread has set according info-label to number! here we do not check if value is numeric! QString crntValue = m_Controls->infoTimerSetFA->text(); int tmpVal = crntValue.toInt(); m_Controls->infoTimerSetFA->setText(QString::number(++tmpVal)); m_Controls->infoTimerSetFA->update(); } void QmitkFiberBundleDeveloperView::BeforeThread_GenerateFibersRandom() { m_threadInProgress = true; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingStarted(); //m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_STARTED); } } void QmitkFiberBundleDeveloperView::AfterThread_GenerateFibersRandom() { m_threadInProgress = false; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingFinished(); m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_IDLE); } // disconnect(m_hostThread, 0, 0, 0); m_hostThread->disconnect(); delete m_GeneratorFibersRandom; } vtkSmartPointer QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionX() { int numOfFibers = m_Controls->boxFiberNumbers->value(); vtkSmartPointer linesCell = vtkSmartPointer::New(); vtkSmartPointer points = vtkSmartPointer::New(); //insert Origin point, this point has index 0 in point array double originX = 0.0; double originY = 0.0; double originZ = 0.0; //after each iteration the origin of the new fiber increases //here you set which direction is affected. double increaseX = 0.0; double increaseY = 1.0; double increaseZ = 0.0; //walk along X axis //length of fibers increases in each iteration for (int i=0; i newFiber = vtkSmartPointer::New(); newFiber->GetPointIds()->SetNumberOfIds(i+2); //create starting point and add it to pointset points->InsertNextPoint(originX + (double)i * increaseX , originY + (double)i * increaseY, originZ + (double)i * increaseZ); //add starting point to fiber newFiber->GetPointIds()->SetId(0,points->GetNumberOfPoints()-1); //insert remaining points for fiber for (int pj=0; pj<=i ; ++pj) { //generate next point on X axis points->InsertNextPoint( originX + (double)pj+1 , originY + (double)i * increaseY, originZ + (double)i * increaseZ ); newFiber->GetPointIds()->SetId(pj+1,points->GetNumberOfPoints()-1); } linesCell->InsertNextCell(newFiber); } vtkSmartPointer PDX = vtkSmartPointer::New(); PDX->SetPoints(points); PDX->SetLines(linesCell); return PDX; } vtkSmartPointer QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionY() { vtkSmartPointer PDY = vtkSmartPointer::New(); //todo return PDY; } vtkSmartPointer QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionZ() { vtkSmartPointer PDZ = vtkSmartPointer::New(); //todo return PDZ; } void QmitkFiberBundleDeveloperView::DoSetFAValues() { QTimer *localTimer = new QTimer; // timer must be initialized here, otherwise timer is not fancy enough localTimer->setInterval( 10 ); connect( localTimer, SIGNAL(timeout()), this, SLOT( UpdateSetFAValuesTimer() ) ); // pack items which are needed by thread processing struct Package4WorkingThread ItemPackageToSetFAMap; - ItemPackageToSetFAMap.st_FBX = m_FiberBundleX; + ItemPackageToSetFAMap.st_FBX = m_FiberBundle; ItemPackageToSetFAMap.st_FancyGUITimer1 = localTimer; ItemPackageToSetFAMap.st_PassedDataNode = m_FANode; ItemPackageToSetFAMap.st_Controls = m_Controls; if (m_fiberMonitorIsOn) ItemPackageToSetFAMap.st_fiberThreadMonitorWorker = m_fiberThreadMonitorWorker; if (m_threadInProgress) return; //maybe popup window saying, working thread still in progress...pls wait m_FiberFeederFASlave = new QmitkFiberFeederFAWorker(m_hostThread, ItemPackageToSetFAMap); m_FiberFeederFASlave->moveToThread(m_hostThread); connect(m_hostThread, SIGNAL(started()), this, SLOT( BeforeThread_FiberSetFA()) ); connect(m_hostThread, SIGNAL(started()), m_FiberFeederFASlave, SLOT(run()) ); connect(m_hostThread, SIGNAL(finished()), this, SLOT(AfterThread_FiberSetFA())); connect(m_hostThread, SIGNAL(terminated()), this, SLOT(AfterThread_FiberSetFA())); m_hostThread->start(QThread::LowestPriority); } void QmitkFiberBundleDeveloperView::DoSetFAMap() { std::vector nodes = GetDataManagerSelection(); if (nodes.empty()) { m_Controls->lineEdit_FAMap->setText("N/A"); return; } for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if (node.IsNotNull() && dynamic_cast(node->GetData())) { // this node is what we want m_FANode = node; m_Controls->lineEdit_FAMap->setText(node->GetName().c_str()); return; } } } void QmitkFiberBundleDeveloperView::BeforeThread_FiberSetFA() { m_threadInProgress = true; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingStarted(); } } void QmitkFiberBundleDeveloperView::AfterThread_FiberSetFA() { m_threadInProgress = false; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingFinished(); m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_IDLE); } disconnect(m_hostThread, 0, 0, 0); m_hostThread->disconnect(); //update renderer m_FiberBundleNode->Modified(); m_MultiWidget->ForceImmediateUpdate(); //update QComboBox(dropDown menu) in view of available ColorCodings this->DoGatherColorCodings(); delete m_FiberFeederFASlave; } void QmitkFiberBundleDeveloperView::DoColorFibers() { // - MITK_INFO << "call fibercoloring in fiberBundleX"; + MITK_INFO << "call fibercoloring in FiberBundle"; QTimer *localTimer = new QTimer; // timer must be initialized here, otherwise timer is not fancy enough localTimer->setInterval( 10 ); connect( localTimer, SIGNAL(timeout()), this, SLOT( UpdateColorFibersTimer() ) ); // pack items which are needed by thread processing struct Package4WorkingThread ItemPackageForFiberColoring; - ItemPackageForFiberColoring.st_FBX = m_FiberBundleX; + ItemPackageForFiberColoring.st_FBX = m_FiberBundle; ItemPackageForFiberColoring.st_PassedDataNode = m_FiberBundleNode; ItemPackageForFiberColoring.st_FancyGUITimer1 = localTimer; ItemPackageForFiberColoring.st_Controls = m_Controls; //needed to catch up some selections and set options in GUI if (m_fiberMonitorIsOn) ItemPackageForFiberColoring.st_fiberThreadMonitorWorker = m_fiberThreadMonitorWorker; if (m_threadInProgress) return; //maybe popup window saying, working thread still in progress...pls wait m_FiberColoringSlave = new QmitkFiberColoringWorker(m_hostThread, ItemPackageForFiberColoring); m_FiberColoringSlave->moveToThread(m_hostThread); connect(m_hostThread, SIGNAL(started()), this, SLOT( BeforeThread_FiberColorCoding()) ); connect(m_hostThread, SIGNAL(started()), m_FiberColoringSlave, SLOT(run()) ); connect(m_hostThread, SIGNAL(finished()), this, SLOT(AfterThread_FiberColorCoding())); connect(m_hostThread, SIGNAL(terminated()), this, SLOT(AfterThread_FiberColorCoding())); m_hostThread->start(QThread::LowestPriority); } void QmitkFiberBundleDeveloperView::BeforeThread_FiberColorCoding() { m_threadInProgress = true; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingStarted(); } } void QmitkFiberBundleDeveloperView::AfterThread_FiberColorCoding() { m_threadInProgress = false; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingFinished(); m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_IDLE); } disconnect(m_hostThread, 0, 0, 0); m_hostThread->disconnect(); //update renderer m_FiberBundleNode->Modified(); m_MultiWidget->ForceImmediateUpdate(); //update QComboBox(dropDown menu) in view of available ColorCodings this->DoGatherColorCodings(); delete m_FiberColoringSlave; } void QmitkFiberBundleDeveloperView::DoGatherColorCodings() { - QStringList fbxColorCodings = m_FiberBundleX->GetAvailableColorCodings(); + QStringList fbxColorCodings = m_FiberBundle->GetAvailableColorCodings(); //update dropDown Menu //remove all items from menu m_suppressSignal = true; int ddItems = m_Controls->ddAvailableColorcodings->count(); for(int i=ddItems-1; i>=0; i--) { //note, after each item remove, index in QComboBox is updated. sending signal: index changed m_Controls->ddAvailableColorcodings->removeItem(i); } //fill new data into menu m_Controls->ddAvailableColorcodings->addItems(fbxColorCodings); - m_Controls->ddAvailableColorcodings->addItem(m_FiberBundleX->COLORCODING_CUSTOM); + m_Controls->ddAvailableColorcodings->addItem(m_FiberBundle->COLORCODING_CUSTOM); //highlight current colorcoding - QString cc = m_FiberBundleX->GetCurrentColorCoding(); + QString cc = m_FiberBundle->GetCurrentColorCoding(); MITK_INFO << cc.toStdString().c_str() << " is at idx: " << m_Controls->ddAvailableColorcodings->findText(cc); m_Controls->ddAvailableColorcodings->setCurrentIndex( m_Controls->ddAvailableColorcodings->findText(cc) ); m_Controls->ddAvailableColorcodings->update(); m_suppressSignal = false; } void QmitkFiberBundleDeveloperView::SetCurrentColorCoding(int idx) { if(!m_suppressSignal){ QString selectedColorCoding = m_Controls->ddAvailableColorcodings->itemText(idx); - m_FiberBundleX->SetColorCoding(selectedColorCoding.toStdString().c_str() ); //QString to char + m_FiberBundle->SetColorCoding(selectedColorCoding.toStdString().c_str() ); //QString to char // update rendering m_FiberBundleNode->Modified(); m_MultiWidget->ForceImmediateUpdate(); } } /* === OutSourcedMethod: THIS METHOD GENERATES ESSENTIAL GEOMETRY PARAMETERS FOR THE MITK FRAMEWORK === * WITHOUT, the rendering mechanism will ignore objects without valid Geometry * for each object, MITK requires: ORIGIN, SPACING, TRANSFORM MATRIX, BOUNDING-BOX */ mitk::Geometry3D::Pointer QmitkFiberBundleDeveloperView::GenerateStandardGeometryForMITK() { mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); // generate origin mitk::Point3D origin; origin[0] = 0; origin[1] = 0; origin[2] = 0; geometry->SetOrigin(origin); // generate spacing float spacing[3] = {1,1,1}; geometry->SetSpacing(spacing); // generate identity transform-matrix vtkSmartPointer m = vtkSmartPointer::New(); geometry->SetIndexToWorldTransformByVtkMatrix(m); // generate boundingbox // for an usable bounding-box use gui parameters to estimate the boundingbox float bounds[] = {500, 500, 500, -500, -500, -500}; // GET SELECTED FIBER DIRECTION QString fibDirection; //stores the object_name of selected radiobutton QVector::const_iterator i; for (i = m_DirectionRadios.begin(); i != m_DirectionRadios.end(); ++i) { QRadioButton* rdbtn = *i; if (rdbtn->isChecked()) fibDirection = rdbtn->objectName(); } if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_RANDOM ) { // use information about distribution parameter to calculate bounding box int distrRadius = m_Controls->boxDistributionRadius->value(); bounds[0] = distrRadius; bounds[1] = distrRadius; bounds[2] = distrRadius; bounds[3] = -distrRadius; bounds[4] = -distrRadius; bounds[5] = -distrRadius; } else { // so far only X,Y,Z directions are available MITK_INFO << "_______GEOMETRY ISSUE_____\n***BoundingBox for X, Y, Z fiber directions are not optimized yet!***"; int maxFibLength = m_Controls->boxFiberMaxLength->value(); bounds[0] = maxFibLength; bounds[1] = maxFibLength; bounds[2] = maxFibLength; bounds[3] = -maxFibLength; bounds[4] = -maxFibLength; bounds[5] = -maxFibLength; } geometry->SetFloatBounds(bounds); geometry->SetImageGeometry(true); //?? return geometry; } void QmitkFiberBundleDeveloperView::UpdateFiberIDTimer() { //MAKE SURE by yourself THAT NOTHING ELSE THAN A NUMBER IS SET IN THAT LABEL QString crntValue = m_Controls->infoTimerGenerateFiberIds->text(); int tmpVal = crntValue.toInt(); m_Controls->infoTimerGenerateFiberIds->setText(QString::number(++tmpVal)); m_Controls->infoTimerGenerateFiberIds->update(); } -/* Initialie ID dataset in FiberBundleX */ +/* Initialie ID dataset in FiberBundle */ void QmitkFiberBundleDeveloperView::DoGenerateFiberIDs() { /* ===== TIMER CONFIGURATIONS for visual effect ====== * start and stop is called in Thread */ QTimer *localTimer = new QTimer; // timer must be initialized here, otherwise timer is not fancy enough localTimer->setInterval( 10 ); connect( localTimer, SIGNAL(timeout()), this, SLOT(UpdateFiberIDTimer()) ); // pack items which are needed by thread processing struct Package4WorkingThread FiberIdPackage; - FiberIdPackage.st_FBX = m_FiberBundleX; + FiberIdPackage.st_FBX = m_FiberBundle; FiberIdPackage.st_FancyGUITimer1 = localTimer; FiberIdPackage.st_Controls = m_Controls; //set element for thread monitoring if (m_fiberMonitorIsOn) FiberIdPackage.st_fiberThreadMonitorWorker = m_fiberThreadMonitorWorker; if (m_threadInProgress) return; //maybe popup window saying, working thread still in progress...pls wait // THREAD CONFIGURATION m_FiberIDGenerator = new QmitkFiberIDWorker(m_hostThread, FiberIdPackage); m_FiberIDGenerator->moveToThread(m_hostThread); connect(m_hostThread, SIGNAL(started()), this, SLOT( BeforeThread_IdGenerate()) ); connect(m_hostThread, SIGNAL(started()), m_FiberIDGenerator, SLOT(run())); connect(m_hostThread, SIGNAL(finished()), this, SLOT(AfterThread_IdGenerate())); connect(m_hostThread, SIGNAL(terminated()), this, SLOT(AfterThread_IdGenerate())); m_hostThread->start(QThread::LowestPriority); // m_Controls->infoTimerGenerateFiberIds->setText(QString::number(clock.GetTotal())); } void QmitkFiberBundleDeveloperView::BeforeThread_IdGenerate() { m_threadInProgress = true; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingStarted(); m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_STARTED); } } void QmitkFiberBundleDeveloperView::AfterThread_IdGenerate() { m_threadInProgress = false; if (m_fiberMonitorIsOn){ m_fiberThreadMonitorWorker->threadForFiberProcessingFinished(); m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_IDLE); } disconnect(m_hostThread, 0, 0, 0); m_hostThread->disconnect(); delete m_FiberIDGenerator; } void QmitkFiberBundleDeveloperView::ResetFiberInfoWidget() { if (m_Controls->infoAnalyseNumOfFibers->isEnabled()) { m_Controls->infoAnalyseNumOfFibers->setText("-"); m_Controls->infoAnalyseNumOfPoints->setText("-"); m_Controls->infoAnalyseNumOfFibers->setEnabled(false); } } void QmitkFiberBundleDeveloperView::FeedFiberInfoWidget() { if (!m_Controls->infoAnalyseNumOfFibers->isEnabled()) m_Controls->infoAnalyseNumOfFibers->setEnabled(true); QString numOfFibers; - numOfFibers.setNum( m_FiberBundleX->GetFiberPolyData()->GetNumberOfLines() ); + numOfFibers.setNum( m_FiberBundle->GetFiberPolyData()->GetNumberOfLines() ); QString numOfPoints; - numOfPoints.setNum( m_FiberBundleX->GetFiberPolyData()->GetNumberOfPoints() ); + numOfPoints.setNum( m_FiberBundle->GetFiberPolyData()->GetNumberOfPoints() ); m_Controls->infoAnalyseNumOfFibers->setText( numOfFibers ); m_Controls->infoAnalyseNumOfPoints->setText( numOfPoints ); } void QmitkFiberBundleDeveloperView::SelectionChangedToolBox(int idx) { // show/reset items of selected toolbox page FiberInfo if (m_Controls->page_FiberInfo->isVisible()) { - if (m_FiberBundleX != NULL) { + if (m_FiberBundle != NULL) { FeedFiberInfoWidget(); } else { //if infolables are disabled: return //else set info back to - and set label and info to disabled ResetFiberInfoWidget(); } } // show/reset items of selected toolbox page FiberProcessing if (m_Controls->page_FiberProcessing->isVisible()) { - if (m_FiberBundleX.IsNotNull() && m_PlanarFigure.IsNotNull() ) + if (m_FiberBundle.IsNotNull() && m_PlanarFigure.IsNotNull() ) { //show fiber extraction button m_Controls->buttonExtractFibers->setEnabled(true); } else { m_Controls->buttonExtractFibers->setEnabled(false); } - if (m_FiberBundleX.IsNotNull()) + if (m_FiberBundle.IsNotNull()) { //show button colorCoding m_Controls->buttonColorFibers->setEnabled(true); m_Controls->ddAvailableColorcodings->setEnabled(true); m_Controls->buttonGenerateFiberIds->setEnabled(true); // m_Controls->buttonSMFibers->setEnabled(true); // m_Controls->buttonVtkDecimatePro->setEnabled(true); // m_Controls->buttonVtkSmoothPD->setEnabled(true); // m_Controls->buttonGenerateTubes->setEnabled(true); } else { m_Controls->buttonColorFibers->setEnabled(false); m_Controls->ddAvailableColorcodings->setEnabled(false); m_Controls->buttonGenerateFiberIds->setEnabled(false); m_Controls->buttonSMFibers->setEnabled(false); m_Controls->buttonVtkDecimatePro->setEnabled(false); m_Controls->buttonVtkSmoothPD->setEnabled(false); m_Controls->buttonGenerateTubes->setEnabled(true); } } } void QmitkFiberBundleDeveloperView::FBXDependendGUIElementsConfigurator() { // ==== FIBER PROCESSING ELEMENTS and ALL ELEMENTS WHICH NEED A FBX DATANODE====== // m_Controls->buttonGenerateFiberIds->setEnabled(isVisible); moved to selectionChangedToolBox SelectionChangedToolBox(-1); //set gui elements with respect to active tab, widget, etc. -1 has no effect } void QmitkFiberBundleDeveloperView::DoMonitorFiberThreads(int checkStatus) { - //check if in datanode exists already a node of type mitkFiberBundleXThreadMonitor + //check if in datanode exists already a node of type mitkFiberBundleThreadMonitor //if not then put node to datastorage //if checkStatus is 1 then start qtimer using fading in starting text in datanode //if checkStatus is 0 then fade out dataNode using qtimer if (checkStatus) { m_fiberMonitorIsOn = true; // Generate Node hosting thread information - mitk::FiberBundleXThreadMonitor::Pointer FBXThreadMonitor = mitk::FiberBundleXThreadMonitor::New(); + mitk::FiberBundleThreadMonitor::Pointer FBXThreadMonitor = mitk::FiberBundleThreadMonitor::New(); FBXThreadMonitor->SetGeometry(this->GenerateStandardGeometryForMITK()); m_MonitorNode = mitk::DataNode::New(); m_MonitorNode->SetName("FBX_threadMonitor"); m_MonitorNode->SetData(FBXThreadMonitor); m_MonitorNode->SetVisibility(true); m_MonitorNode->SetOpacity(1.0); GetDataStorage()->Add(m_MonitorNode); //following code is needed for rendering text in mitk! without geometry nothing is rendered const mitk::PlaneGeometry * tsgeo = m_MultiWidget->GetTimeNavigationController()->GetCurrentPlaneGeometry(); if (tsgeo == NULL) { /* GetDataStorage()->Modified etc. have no effect, therefore proceed as followed below */ // 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 = GetDataStorage()->GetSubset(pred); // calculate bounding geometry of these nodes mitk::TimeGeometry::Pointer bounds = GetDataStorage()->ComputeBoundingGeometry3D(rs); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } else { GetDataStorage()->Modified(); m_MultiWidget->RequestUpdate(); //necessary?? } //__GEOMETRY FOR THREADMONITOR GENERATED /* ====== initialize thread for managing fiberThread information ========= */ m_monitorThread = new QThread; // the package needs datastorage, MonitorDatanode, standardmultiwidget, struct Package4WorkingThread ItemPackageForThreadMonitor; ItemPackageForThreadMonitor.st_DataStorage = GetDataStorage(); ItemPackageForThreadMonitor.st_ThreadMonitorDataNode = m_MonitorNode; ItemPackageForThreadMonitor.st_MultiWidget = m_MultiWidget; ItemPackageForThreadMonitor.st_FBX_Monitor = FBXThreadMonitor; m_fiberThreadMonitorWorker = new QmitkFiberThreadMonitorWorker(m_monitorThread, ItemPackageForThreadMonitor); m_fiberThreadMonitorWorker->moveToThread(m_monitorThread); connect ( m_monitorThread, SIGNAL( started() ), m_fiberThreadMonitorWorker, SLOT( run() ) ); m_monitorThread->start(QThread::LowestPriority); m_fiberThreadMonitorWorker->initializeMonitor();//do some init animation ;-) } else { m_fiberMonitorIsOn = false; m_monitorThread->quit(); //think about outsourcing following lines to quit / terminate slot of thread GetDataStorage()->Remove(m_MonitorNode); GetDataStorage()->Modified(); m_MultiWidget->RequestUpdate(); //necessary?? } } void QmitkFiberBundleDeveloperView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkFiberBundleDeveloperView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } /* OnSelectionChanged is registered to SelectionService, therefore no need to implement SelectionService Listener explicitly */ void QmitkFiberBundleDeveloperView::OnSelectionChanged( std::vector nodes ) { if (nodes.empty()) return; - /* ==== reset everyhing related to FiberBundleX ====== - * - variable m_FiberBundleX + /* ==== reset everyhing related to FiberBundle ====== + * - variable m_FiberBundle * - visualization of analysed fiberbundle */ m_FiberBundleNode = NULL; - m_FiberBundleX = NULL; //reset pointer, so that member does not point to depricated locations + m_FiberBundle = NULL; //reset pointer, so that member does not point to depricated locations m_PlanarFigure = NULL; ResetFiberInfoWidget(); //timer reset only when no thread is in progress if (!m_threadInProgress) { m_Controls->infoTimerGenerateFiberIds->setText("-"); //set GUI representation of timer to - m_Controls->infoTimerGenerateFiberBundle->setText( "-" ); m_Controls->infoTimerColorCoding->setText( "-" ); } //==================================================== for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; /* CHECKPOINT: FIBERBUNDLE*/ - if( node.IsNotNull() && dynamic_cast(node->GetData()) ) + if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_FiberBundleNode = node; - m_FiberBundleX = dynamic_cast(node->GetData()); - if (m_FiberBundleX.IsNull()){ - MITK_INFO << "========ATTENTION=========\n unable to load selected FiberBundleX to FiberBundleDeveloper-plugin \n"; + m_FiberBundle = dynamic_cast(node->GetData()); + if (m_FiberBundle.IsNull()){ + MITK_INFO << "========ATTENTION=========\n unable to load selected FiberBundle to FiberBundleDeveloper-plugin \n"; m_FiberBundleNode = NULL; } // ==== FIBERBUNDLE_INFO ELEMENTS ==== if ( m_Controls->page_FiberInfo->isVisible() ) FeedFiberInfoWidget(); - // enable FiberBundleX related Gui Elements, such as buttons etc. + // enable FiberBundle related Gui Elements, such as buttons etc. this->FBXDependendGUIElementsConfigurator(); this->DoGatherColorCodings(); } /* CHECKPOINT: PLANARFIGURE */ else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_PlanarFigure = dynamic_cast(node->GetData()); MITK_INFO << "PF selected"; if (m_PlanarFigure.IsNull()) MITK_INFO << "========ATTENTION=========\n unable to load selected Planarfigure to FiberBundleDeveloper-plugin \n"; } } //update gui elements depending on given nodes FBXDependendGUIElementsConfigurator(); //every gui element which needs a FBX for processing is disabled } void QmitkFiberBundleDeveloperView::ActionDrawEllipseTriggered() { // bool checked = m_Controls->m_CircleButton->isChecked(); mitk::PlanarCircle::Pointer figure = mitk::PlanarCircle::New(); this->PutFigureToDataStorage(figure, QString("Circle%1").arg(++m_CircleCounter)); MITK_INFO << "PlanarCircle 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->GetDataInteractor().GetPointer()); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); mitk::Module* planarFigureModule = mitk::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( node ); } } } } void QmitkFiberBundleDeveloperView::Activated() { MITK_INFO << "FB DevelopersV ACTIVATED()"; } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.h index bc65c9e735..75d0d9e2f6 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.h @@ -1,382 +1,382 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkFiberBundleDeveloperView_h #define QmitkFiberBundleDeveloperView_h #include #include #include #include "ui_QmitkFiberBundleDeveloperViewControls.h" #include #include #include -#include +#include // Qt #include #include #include // VTK #include #include -#include +#include -#include +#include #include #include class QmitkFiberThreadMonitorWorker; //include needed for struct element class QmitkFiberBundleDeveloperView; //this include is needed for the struct element, especially for functors to QmitkFiberBundleDeveloperView /* ==== THIS STRUCT CONTAINS ALL NECESSARY VARIABLES * TO EXECUTE AND UPDATE GUI ELEMENTS DURING PROCESSING OF A THREAD * why? either you add tons of friendclasses (e.g. FiberWorker objects), or you create a package containing all items needed. Otherwise you have to set all members etc. to public! */ struct Package4WorkingThread { - mitk::FiberBundleX* st_FBX; + mitk::FiberBundle* st_FBX; QTimer* st_FancyGUITimer1; Ui::QmitkFiberBundleDeveloperViewControls* st_Controls; //functors to outdoor methods QmitkFiberBundleDeveloperView* st_host; void (QmitkFiberBundleDeveloperView::*st_pntr_to_Method_PutFibersToDataStorage) (vtkSmartPointer); //==DO NOT TOUCH THIS SECTION=== you might extend this section, but do NOT shorten it! hai capito! //host MITK I/O elements, especially needed for thread monitoring QmitkFiberThreadMonitorWorker *st_fiberThreadMonitorWorker; - mitk::FiberBundleXThreadMonitor::Pointer st_FBX_Monitor; //needed for direct access do animation/fancy methods + mitk::FiberBundleThreadMonitor::Pointer st_FBX_Monitor; //needed for direct access do animation/fancy methods mitk::DataNode::Pointer st_ThreadMonitorDataNode; //needed for renderer to recognize node modifications mitk::DataNode::Pointer st_PassedDataNode; //put an extra node if needed mitk::DataStorage::Pointer st_DataStorage; //well that is discussable if needed ;-) probably not QmitkStdMultiWidget* st_MultiWidget; //needed for rendering update mitk::PlanarFigure::Pointer st_PlanarFigure; //needed for fiberextraction }; // ==================================================================== // ============= WORKER WHICH IS PASSED TO THREAD ===================== // ==================================================================== //## Documentation //## This class does the actual work for generating fiber ids. class QmitkFiberIDWorker : public QObject { Q_OBJECT public: QmitkFiberIDWorker( QThread*, Package4WorkingThread ); public slots: void run(); private: Package4WorkingThread m_itemPackage; QThread* m_hostingThread; }; // ==================================================================== // ============= WORKER WHICH IS PASSED TO THREAD ===================== // ==================================================================== //## Documentation //## This class does the actual work for colorcoding fibers. class QmitkFiberColoringWorker : public QObject { Q_OBJECT public: QmitkFiberColoringWorker( QThread*, Package4WorkingThread ); public slots: void run(); private: Package4WorkingThread m_itemPackage; QThread* m_hostingThread; }; // ==================================================================== // ============= WORKER WHICH IS PASSED TO THREAD ===================== // ==================================================================== class QmitkFiberGenerateRandomWorker : public QObject { Q_OBJECT public: QmitkFiberGenerateRandomWorker( QThread*, Package4WorkingThread ); public slots: void run(); private: Package4WorkingThread m_itemPackage; QThread* m_hostingThread; }; // ==================================================================== // ============= WORKER WHICH IS PASSED TO THREAD ===================== // ==================================================================== class QmitkFiberFeederFAWorker : public QObject { Q_OBJECT public: QmitkFiberFeederFAWorker( QThread*, Package4WorkingThread ); public slots: void run(); private: Package4WorkingThread m_itemPackage; QThread* m_hostingThread; }; // ==================================================================== // ============= WORKER WHICH IS PASSED TO THREAD ===================== // ==================================================================== class QmitkFiberExtractorWorker : public QObject { Q_OBJECT public: QmitkFiberExtractorWorker( QThread*, Package4WorkingThread ); public slots: void run(); private: Package4WorkingThread m_itemPackage; QThread* m_hostingThread; }; // ==================================================================== // ============= WORKER WHICH IS PASSED TO THREAD ===================== // ==================================================================== class QmitkFiberThreadMonitorWorker : public QObject { Q_OBJECT public: QmitkFiberThreadMonitorWorker( QThread*, Package4WorkingThread ); void initializeMonitor(); void threadForFiberProcessingStarted(); void threadForFiberProcessingFinished(); void threadForFiberProcessingTerminated(); void setThreadStatus(QString); public slots: void run(); void fancyMonitorInitialization(); void fancyMonitorInitializationFinalPos(); void fancyMonitorInitializationMask(); void fancyTextFading_threadStarted(); void fancyTextFading_threadFinished(); void fancyTextFading_threadTerminated(); private: Package4WorkingThread m_itemPackage; QThread* m_hostingThread; QTimer* m_thtimer_initMonitor; QTimer* m_thtimer_initMonitorSetFinalPosition; QTimer* m_thtimer_initMonitorSetMasks; QTimer* m_thtimer_threadStarted; QTimer* m_thtimer_threadFinished; QTimer* m_thtimer_threadTerminated; // flags for fancy fading bool m_decreaseOpacity_threadStarted; bool m_decreaseOpacity_threadFinished; bool m_decreaseOpacity_threadTerminated; // members for fancy animation int m_pixelstepper; int m_steppingDistance; }; // strings to display fiber_thread monitor const QString FBX_STATUS_IDLE = "idle"; const QString FBX_STATUS_STARTED = "starting"; const QString FBX_STATUS_RUNNING = "running"; // ========= HERE STARTS THE ACTUAL FIBERBUNDLE DEVELOPER VIEW ======= const QString FIB_RADIOBUTTON_DIRECTION_RANDOM = "radioButton_directionRandom"; const QString FIB_RADIOBUTTON_DIRECTION_X = "radioButton_directionX"; const QString FIB_RADIOBUTTON_DIRECTION_Y = "radioButton_directionY"; const QString FIB_RADIOBUTTON_DIRECTION_Z = "radioButton_directionZ"; /*! \brief QmitkFiberBundleView \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 QmitkFiberBundleDeveloperView : 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; QmitkFiberBundleDeveloperView(); virtual ~QmitkFiberBundleDeveloperView(); virtual void CreateQtPartControl(QWidget *parent); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); virtual void Activated(); protected slots: void DoGenerateFibers(); void DoGenerateFiberIDs(); void DoExtractFibers(); void DoUpdateGenerateFibersWidget(); void SelectionChangedToolBox(int); void DoMonitorFiberThreads(int); void DoSetFAValues(); void DoSetFAMap(); void DoColorFibers(); void DoGatherColorCodings(); void SetCurrentColorCoding(int); void ActionDrawEllipseTriggered(); //SLOTS FOR THREADS void BeforeThread_IdGenerate(); void AfterThread_IdGenerate(); void BeforeThread_GenerateFibersRandom(); void AfterThread_GenerateFibersRandom(); void BeforeThread_FiberSetFA(); void AfterThread_FiberSetFA(); void BeforeThread_FiberColorCoding(); void AfterThread_FiberColorCoding(); void BeforeThread_FiberExtraction(); void AfterThread_FiberExtraction(); //SLOTS FOR TIMERS void UpdateFiberIDTimer(); void UpdateGenerateRandomFibersTimer(); void UpdateColorFibersTimer(); void UpdateExtractFibersTimer(); void UpdateSetFAValuesTimer(); protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); Ui::QmitkFiberBundleDeveloperViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; private: /* METHODS GENERATING FIBERSTRUCTURES */ void GenerateVtkFibersRandom(); vtkSmartPointer GenerateVtkFibersDirectionX(); vtkSmartPointer GenerateVtkFibersDirectionY(); vtkSmartPointer GenerateVtkFibersDirectionZ(); void PutFibersToDataStorage( vtkSmartPointer ); void PutFigureToDataStorage(mitk::PlanarFigure* , const QString& ); /* METHODS FOR FIBER PROCESSING OR PREPROCESSING */ /* HELPERMETHODS */ mitk::Geometry3D::Pointer GenerateStandardGeometryForMITK(); void ResetFiberInfoWidget(); void FeedFiberInfoWidget(); void FBXDependendGUIElementsConfigurator(); void SetGeneratedFBX(); //contains the selected FiberBundle, PlanarFigure mitk::DataNode::Pointer m_FiberBundleNode; - mitk::WeakPointer m_FiberBundleX; + mitk::WeakPointer m_FiberBundle; mitk::PlanarFigure::Pointer m_PlanarFigure; // radiobutton groups QVector< QRadioButton* > m_DirectionRadios; QVector< QRadioButton* > m_FARadios; QVector< QRadioButton* > m_GARadios; // Thread based Workers which do some processing of fibers QmitkFiberIDWorker* m_FiberIDGenerator; QmitkFiberGenerateRandomWorker* m_GeneratorFibersRandom; QmitkFiberFeederFAWorker* m_FiberFeederFASlave; QmitkFiberColoringWorker* m_FiberColoringSlave; QmitkFiberExtractorWorker* m_FiberExtractor; QThread* m_hostThread; QThread* m_monitorThread; bool m_threadInProgress; mitk::DataNode::Pointer m_MonitorNode; QmitkFiberThreadMonitorWorker *m_fiberThreadMonitorWorker; bool m_fiberMonitorIsOn; // counters for ROI nodes int m_CircleCounter; mitk::DataNode::Pointer m_FANode; // flag to bypass signal from qcombobox "index changed(int)" bool m_suppressSignal; }; #endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED 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 e116a924b7..c26ea6b4ae 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.cpp @@ -1,1487 +1,1487 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkFiberProcessingView.h" #include // Qt #include // MITK #include #include #include #include #include #include #include #include #include #include #include #include "usModuleRegistry.h" #include #include "mitkNodePredicateDataType.h" #include #include #include #include // ITK #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #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_CircleCounter(0) , m_PolygonCounter(0) , m_UpsamplingFactor(1) { } // 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 ); 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_GenerateRoiImage, SIGNAL(clicked()), this, SLOT(GenerateRoiImage()) ); connect(m_Controls->m_JoinBundles, SIGNAL(clicked()), this, SLOT(JoinBundles()) ); connect(m_Controls->m_SubstractBundles, SIGNAL(clicked()), this, SLOT(SubstractBundles()) ); connect(m_Controls->m_ExtractFibersButton, SIGNAL(clicked()), this, SLOT(Extract())); connect(m_Controls->m_RemoveButton, SIGNAL(clicked()), this, SLOT(Remove())); connect(m_Controls->m_ModifyButton, SIGNAL(clicked()), this, SLOT(Modify())); connect(m_Controls->m_ExtractionMethodBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui())); connect(m_Controls->m_RemovalMethodBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui())); connect(m_Controls->m_ModificationMethodBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui())); m_Controls->m_ColorMapBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isMitkImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateDataType::Pointer isDwi = mitk::NodePredicateDataType::New("DiffusionImage"); mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); mitk::NodePredicateDataType::Pointer isQbi = mitk::NodePredicateDataType::New("QBallImage"); mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isDwi, isDti); isDiffusionImage = mitk::NodePredicateOr::New(isDiffusionImage, isQbi); mitk::NodePredicateNot::Pointer noDiffusionImage = mitk::NodePredicateNot::New(isDiffusionImage); mitk::NodePredicateAnd::Pointer finalPredicate = mitk::NodePredicateAnd::New(isMitkImage, noDiffusionImage); m_Controls->m_ColorMapBox->SetPredicate(finalPredicate); } UpdateGui(); } void QmitkFiberProcessingView::Modify() { switch (m_Controls->m_ModificationMethodBox->currentIndex()) { case 0: { ResampleSelectedBundles(); break; } case 1: { CompressSelectedBundles(); break; } case 2: { DoImageColorCoding(); break; } case 3: { MirrorFibers(); break; } case 4: { WeightFibers(); break; } } } void QmitkFiberProcessingView::WeightFibers() { float weight = this->m_Controls->m_BundleWeightBox->value(); for (int i=0; i(m_SelectedFB.at(i)->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedFB.at(i)->GetData()); fib->SetFiberWeights(weight); } } void QmitkFiberProcessingView::Remove() { switch (m_Controls->m_RemovalMethodBox->currentIndex()) { case 0: { RemoveDir(); break; } case 1: { PruneBundle(); break; } case 2: { ApplyCurvatureThreshold(); break; } case 3: { RemoveWithMask(false); break; } case 4: { RemoveWithMask(true); break; } } } void QmitkFiberProcessingView::Extract() { switch (m_Controls->m_ExtractionMethodBox->currentIndex()) { case 0: { ExtractWithPlanarFigure(); break; } case 1: { switch (m_Controls->m_ExtractionBoxMask->currentIndex()) { { case 0: ExtractWithMask(true, false); break; } { case 1: ExtractWithMask(true, true); break; } { case 2: ExtractWithMask(false, false); break; } { case 3: ExtractWithMask(false, true); break; } } break; } } } void QmitkFiberProcessingView::PruneBundle() { int minLength = this->m_Controls->m_PruneFibersMinBox->value(); int maxLength = this->m_Controls->m_PruneFibersMaxBox->value(); for (int i=0; i(m_SelectedFB.at(i)->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedFB.at(i)->GetData()); if (!fib->RemoveShortFibers(minLength)) QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); else if (!fib->RemoveLongFibers(maxLength)) QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); } RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberProcessingView::ApplyCurvatureThreshold() { int angle = this->m_Controls->m_CurvSpinBox->value(); int dist = this->m_Controls->m_CurvDistanceSpinBox->value(); std::vector< DataNode::Pointer > nodes = m_SelectedFB; for (int i=0; i(nodes.at(i)->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(nodes.at(i)->GetData()); itk::FiberCurvatureFilter::Pointer filter = itk::FiberCurvatureFilter::New(); filter->SetInputFiberBundle(fib); filter->SetAngularDeviation(angle); filter->SetDistance(dist); filter->SetRemoveFibers(m_Controls->m_RemoveCurvedFibersBox->isChecked()); filter->Update(); - mitk::FiberBundleX::Pointer newFib = filter->GetOutputFiberBundle(); + mitk::FiberBundle::Pointer newFib = filter->GetOutputFiberBundle(); if (newFib->GetNumFibers()>0) { nodes.at(i)->SetVisibility(false); DataNode::Pointer newNode = DataNode::New(); newNode->SetData(newFib); newNode->SetName(nodes.at(i)->GetName()+"_Curvature"); GetDefaultDataStorage()->Add(newNode, nodes.at(i)); } else QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); // if (!fib->ApplyCurvatureThreshold(mm, this->m_Controls->m_RemoveCurvedFibersBox->isChecked())) // QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); } RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberProcessingView::RemoveDir() { for (unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedFB.at(i)->GetData()); vnl_vector_fixed dir; dir[0] = m_Controls->m_ExtractDirX->value(); dir[1] = m_Controls->m_ExtractDirY->value(); dir[2] = m_Controls->m_ExtractDirZ->value(); fib->RemoveDir(dir,cos((float)m_Controls->m_ExtractAngle->value()*M_PI/180)); } RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberProcessingView::RemoveWithMask(bool removeInside) { if (m_MaskImageNode.IsNull()) return; mitk::Image::Pointer mitkMask = dynamic_cast(m_MaskImageNode->GetData()); for (unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedFB.at(i)->GetData()); QString name(m_SelectedFB.at(i)->GetName().c_str()); itkUCharImageType::Pointer mask = itkUCharImageType::New(); mitk::CastToItkImage(mitkMask, mask); - mitk::FiberBundleX::Pointer newFib = fib->RemoveFibersOutside(mask, removeInside); + mitk::FiberBundle::Pointer newFib = fib->RemoveFibersOutside(mask, removeInside); if (newFib->GetNumFibers()<=0) { QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); continue; } DataNode::Pointer newNode = DataNode::New(); newNode->SetData(newFib); if (removeInside) name += "_Inside"; else name += "_Outside"; newNode->SetName(name.toStdString()); GetDefaultDataStorage()->Add(newNode); m_SelectedFB.at(i)->SetVisibility(false); } } void QmitkFiberProcessingView::ExtractWithMask(bool onlyEnds, bool invert) { if (m_MaskImageNode.IsNull()) return; mitk::Image::Pointer mitkMask = dynamic_cast(m_MaskImageNode->GetData()); for (unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedFB.at(i)->GetData()); QString name(m_SelectedFB.at(i)->GetName().c_str()); itkUCharImageType::Pointer mask = itkUCharImageType::New(); mitk::CastToItkImage(mitkMask, mask); - mitk::FiberBundleX::Pointer newFib = fib->ExtractFiberSubset(mask, onlyEnds, invert); + mitk::FiberBundle::Pointer newFib = fib->ExtractFiberSubset(mask, onlyEnds, invert); if (newFib->GetNumFibers()<=0) { QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); continue; } DataNode::Pointer newNode = DataNode::New(); newNode->SetData(newFib); if (invert) { name += "_not"; if (onlyEnds) name += "-ending-in-mask"; else name += "-passing-mask"; } else { if (onlyEnds) name += "_ending-in-mask"; else name += "_passing-mask"; } newNode->SetName(name.toStdString()); GetDefaultDataStorage()->Add(newNode); m_SelectedFB.at(i)->SetVisibility(false); } } void QmitkFiberProcessingView::GenerateRoiImage() { if (m_SelectedPF.empty()) return; mitk::BaseGeometry::Pointer geometry; if (!m_SelectedFB.empty()) { - mitk::FiberBundleX::Pointer fib = dynamic_cast(m_SelectedFB.front()->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedFB.front()->GetData()); geometry = fib->GetGeometry(); } else if (m_SelectedImage) geometry = m_SelectedImage->GetGeometry(); else return; itk::Vector spacing = geometry->GetSpacing(); spacing /= m_UpsamplingFactor; mitk::Point3D newOrigin = geometry->GetOrigin(); mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds(); newOrigin[0] += bounds.GetElement(0); newOrigin[1] += bounds.GetElement(2); newOrigin[2] += bounds.GetElement(4); 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]/spacing[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( spacing ); // Set the image spacing m_PlanarFigureImage->SetOrigin( newOrigin ); // 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()); std::string name = m_SelectedPF.at(0)->GetName(); WritePfToImage(m_SelectedPF.at(0), tmpImage); for (unsigned int i=1; iGetName(); WritePfToImage(m_SelectedPF.at(i), tmpImage); } DataNode::Pointer node = DataNode::New(); tmpImage = Image::New(); tmpImage->InitializeByItk(m_PlanarFigureImage.GetPointer()); tmpImage->SetVolume(m_PlanarFigureImage->GetBufferPointer()); node->SetData(tmpImage); node->SetName(name); this->GetDefaultDataStorage()->Add(node); } void QmitkFiberProcessingView::WritePfToImage(mitk::DataNode::Pointer node, mitk::Image* image) { if (dynamic_cast(node->GetData())) { m_PlanarFigure = dynamic_cast(node->GetData()); AccessFixedDimensionByItk_2( image, InternalReorientImagePlane, 3, m_PlanarFigure->GetGeometry(), -1); AccessFixedDimensionByItk_2( m_InternalImage, InternalCalculateMaskFromPlanarFigure, 3, 2, node->GetName() ); } else if (dynamic_cast(node->GetData())) { mitk::PlanarFigureComposite* pfc = dynamic_cast(node->GetData()); for (int j=0; jgetNumberOfChildren(); j++) { WritePfToImage(pfc->getDataNodeAt(j), image); } } } template < typename TPixel, unsigned int VImageDimension > void QmitkFiberProcessingView::InternalReorientImagePlane( const itk::Image< TPixel, VImageDimension > *image, mitk::BaseGeometry* planegeo3D, int additionalIndex ) { 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->GetExtentInMM(0) / spacing[0]; size[1] = planegeo->GetExtentInMM(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::LinearInterpolateImageFunction InterpolatorType; typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); interpolator->SetInputImage( image ); resampler->SetInterpolator( interpolator ); } resampler->SetInput( image ); resampler->SetDefaultPixelValue(0); resampler->Update(); 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 ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::CastImageFilter< ImageType, itkUCharImageType > CastFilterType; // Generate mask image as new image with same header as input image and // initialize with "1". 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 PlaneGeometry *planarFigurePlaneGeometry = m_PlanarFigure->GetPlaneGeometry(); const PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 ); const BaseGeometry *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; 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; planarFigurePlaneGeometry->WorldToIndex(point2D, point2D); point2D[0] -= 0.5/m_UpsamplingFactor; point2D[1] -= 0.5/m_UpsamplingFactor; planarFigurePlaneGeometry->IndexToWorld(point2D, point2D); planarFigurePlaneGeometry->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.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->SetInputData( 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->SetInputConnection( extrudeFilter->GetOutputPort() ); // Export from ITK to VTK (to use a VTK filter) 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->SetStencilConnection(polyDataToImageStencil->GetOutputPort() ); 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 itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion()); itk::ImageRegionIterator itimage(image, image->GetLargestPossibleRegion()); itmask.GoToBegin(); itimage.GoToBegin(); 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< 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 BaseGeometry *pfImageGeometry3D = tmpImage2->GetGeometry( 0 ); const BaseGeometry *intImageGeometry3D = tmpImage->GetGeometry( 0 ); 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]; if (pfImageGeometry3D->IsIndexInside(index)) 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; } void QmitkFiberProcessingView::UpdateGui() { m_Controls->m_FibLabel->setText("mandatory"); m_Controls->m_PfLabel->setText("needed for extraction"); m_Controls->m_InputData->setTitle("Please Select Input Data"); m_Controls->m_RemoveButton->setEnabled(false); m_Controls->m_PlanarFigureButtonsFrame->setEnabled(false); m_Controls->PFCompoANDButton->setEnabled(false); m_Controls->PFCompoORButton->setEnabled(false); m_Controls->PFCompoNOTButton->setEnabled(false); m_Controls->m_GenerateRoiImage->setEnabled(false); m_Controls->m_ExtractFibersButton->setEnabled(false); m_Controls->m_ModifyButton->setEnabled(false); m_Controls->m_JoinBundles->setEnabled(false); m_Controls->m_SubstractBundles->setEnabled(false); // disable alle frames m_Controls->m_BundleWeightFrame->setVisible(false); m_Controls->m_ExtractionBoxMask->setVisible(false); m_Controls->m_ExtactionFramePF->setVisible(false); m_Controls->m_RemoveDirectionFrame->setVisible(false); m_Controls->m_RemoveLengthFrame->setVisible(false); m_Controls->m_RemoveCurvatureFrame->setVisible(false); m_Controls->m_SmoothFibersFrame->setVisible(false); m_Controls->m_CompressFibersFrame->setVisible(false); m_Controls->m_ColorFibersFrame->setVisible(false); m_Controls->m_MirrorFibersFrame->setVisible(false); bool pfSelected = !m_SelectedPF.empty(); bool fibSelected = !m_SelectedFB.empty(); bool multipleFibsSelected = (m_SelectedFB.size()>1); bool maskSelected = m_MaskImageNode.IsNotNull(); bool imageSelected = m_SelectedImage.IsNotNull(); // toggle visibility of elements according to selected method switch ( m_Controls->m_ExtractionMethodBox->currentIndex() ) { case 0: m_Controls->m_ExtactionFramePF->setVisible(true); break; case 1: m_Controls->m_ExtractionBoxMask->setVisible(true); break; } switch ( m_Controls->m_RemovalMethodBox->currentIndex() ) { case 0: m_Controls->m_RemoveDirectionFrame->setVisible(true); if ( fibSelected ) m_Controls->m_RemoveButton->setEnabled(true); break; case 1: m_Controls->m_RemoveLengthFrame->setVisible(true); if ( fibSelected ) m_Controls->m_RemoveButton->setEnabled(true); break; case 2: m_Controls->m_RemoveCurvatureFrame->setVisible(true); if ( fibSelected ) m_Controls->m_RemoveButton->setEnabled(true); break; case 3: break; case 4: break; } switch ( m_Controls->m_ModificationMethodBox->currentIndex() ) { case 0: m_Controls->m_SmoothFibersFrame->setVisible(true); break; case 1: m_Controls->m_CompressFibersFrame->setVisible(true); break; case 2: m_Controls->m_ColorFibersFrame->setVisible(true); break; case 3: m_Controls->m_MirrorFibersFrame->setVisible(true); break; case 4: m_Controls->m_BundleWeightFrame->setVisible(true); } // are fiber bundles selected? if ( fibSelected ) { m_Controls->m_ModifyButton->setEnabled(true); m_Controls->m_PlanarFigureButtonsFrame->setEnabled(true); m_Controls->m_FibLabel->setText(QString(m_SelectedFB.at(0)->GetName().c_str())); // one bundle and one planar figure needed to extract fibers if (pfSelected) { m_Controls->m_InputData->setTitle("Input Data"); m_Controls->m_PfLabel->setText(QString(m_SelectedPF.at(0)->GetName().c_str())); m_Controls->m_ExtractFibersButton->setEnabled(true); } // more than two bundles needed to join/subtract if (multipleFibsSelected) { m_Controls->m_FibLabel->setText("multiple bundles selected"); m_Controls->m_JoinBundles->setEnabled(true); m_Controls->m_SubstractBundles->setEnabled(true); } if (maskSelected) { m_Controls->m_RemoveButton->setEnabled(true); m_Controls->m_ExtractFibersButton->setEnabled(true); } } // are planar figures selected? if (pfSelected) { if ( fibSelected || m_SelectedImage.IsNotNull()) m_Controls->m_GenerateRoiImage->setEnabled(true); if (m_SelectedPF.size() > 1) { m_Controls->PFCompoANDButton->setEnabled(true); m_Controls->PFCompoORButton->setEnabled(true); } else m_Controls->PFCompoNOTButton->setEnabled(true); } // is image selected if (imageSelected || maskSelected) { m_Controls->m_PlanarFigureButtonsFrame->setEnabled(true); } } void QmitkFiberProcessingView::NodeRemoved(const mitk::DataNode* node) { std::vector nodes; OnSelectionChanged(nodes); } void QmitkFiberProcessingView::NodeAdded(const mitk::DataNode* node) { std::vector nodes; OnSelectionChanged(nodes); } void QmitkFiberProcessingView::OnSelectionChanged( std::vector nodes ) { //reset existing Vectors containing FiberBundles and PlanarFigures from a previous selection m_SelectedFB.clear(); m_SelectedPF.clear(); m_SelectedSurfaces.clear(); m_SelectedImage = NULL; m_MaskImageNode = NULL; for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; - if ( dynamic_cast(node->GetData()) ) + if ( dynamic_cast(node->GetData()) ) m_SelectedFB.push_back(node); else if (dynamic_cast(node->GetData()) || dynamic_cast(node->GetData()) || dynamic_cast(node->GetData())) m_SelectedPF.push_back(node); else if (dynamic_cast(node->GetData())) { m_SelectedImage = dynamic_cast(node->GetData()); bool isBinary = false; node->GetPropertyValue("binary", isBinary); if (isBinary) m_MaskImageNode = node; } else if (dynamic_cast(node->GetData())) m_SelectedSurfaces.push_back(dynamic_cast(node->GetData())); } if (m_SelectedFB.empty()) { int maxLayer = 0; itk::VectorContainer::ConstPointer nodes = this->GetDefaultDataStorage()->GetAll(); for (unsigned int i=0; iSize(); i++) - if (dynamic_cast(nodes->at(i)->GetData())) + if (dynamic_cast(nodes->at(i)->GetData())) { mitk::DataStorage::SetOfObjects::ConstPointer sources = GetDataStorage()->GetSources(nodes->at(i)); if (sources->Size()>0) continue; int layer = 0; nodes->at(i)->GetPropertyValue("layer", layer); if (layer>=maxLayer) { maxLayer = layer; m_SelectedFB.clear(); m_SelectedFB.push_back(nodes->at(i)); } } } if (m_SelectedPF.empty()) { int maxLayer = 0; itk::VectorContainer::ConstPointer nodes = this->GetDefaultDataStorage()->GetAll(); for (unsigned int i=0; iSize(); i++) if (dynamic_cast(nodes->at(i)->GetData()) || dynamic_cast(nodes->at(i)->GetData()) || dynamic_cast(nodes->at(i)->GetData())) { mitk::DataStorage::SetOfObjects::ConstPointer sources = GetDataStorage()->GetSources(nodes->at(i)); if (sources->Size()>0) continue; int layer = 0; nodes->at(i)->GetPropertyValue("layer", layer); if (layer>=maxLayer) { maxLayer = layer; m_SelectedPF.clear(); m_SelectedPF.push_back(nodes->at(i)); } } } UpdateGui(); } void QmitkFiberProcessingView::OnDrawPolygon() { mitk::PlanarPolygon::Pointer figure = mitk::PlanarPolygon::New(); figure->ClosedOn(); this->AddFigureToDataStorage(figure, QString("Polygon%1").arg(++m_PolygonCounter)); } void QmitkFiberProcessingView::OnDrawCircle() { mitk::PlanarCircle::Pointer figure = mitk::PlanarCircle::New(); this->AddFigureToDataStorage(figure, QString("Circle%1").arg(++m_CircleCounter)); } void QmitkFiberProcessingView::Activated() { } void QmitkFiberProcessingView::AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, const char *, mitk::BaseProperty* ) { // initialize figure's geometry with empty geometry mitk::PlaneGeometry::Pointer emptygeometry = mitk::PlaneGeometry::New(); figure->SetPlaneGeometry( 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->SetBoolProperty("planarfigure.3drendering", true); mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(newNode->GetDataInteractor().GetPointer()); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode(newNode); } // figure drawn on the topmost layer / image GetDataStorage()->Add(newNode ); for(unsigned int i = 0; i < m_SelectedPF.size(); i++) m_SelectedPF[i]->SetSelected(false); newNode->SetSelected(true); m_SelectedPF.clear(); m_SelectedPF.push_back(newNode); UpdateGui(); } void QmitkFiberProcessingView::ExtractWithPlanarFigure() { if ( m_SelectedFB.empty() || m_SelectedPF.empty() ){ QMessageBox::information( NULL, "Warning", "No fibe bundle selected!"); return; } std::vector fiberBundles = m_SelectedFB; mitk::DataNode::Pointer planarFigure = m_SelectedPF.at(0); for (unsigned int i=0; i(fiberBundles.at(i)->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(fiberBundles.at(i)->GetData()); mitk::BaseData::Pointer roi = planarFigure->GetData(); - mitk::FiberBundleX::Pointer extFB = fib->ExtractFiberSubset(roi); + mitk::FiberBundle::Pointer extFB = fib->ExtractFiberSubset(roi); if (extFB->GetNumFibers()<=0) { QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); continue; } mitk::DataNode::Pointer node; node = mitk::DataNode::New(); node->SetData(extFB); QString name(fiberBundles.at(i)->GetName().c_str()); name += "_"; name += planarFigure->GetName().c_str(); node->SetName(name.toStdString()); fiberBundles.at(i)->SetVisibility(false); GetDataStorage()->Add(node); } } void QmitkFiberProcessingView::GenerateAndComposite() { mitk::PlanarFigureComposite::Pointer PFCAnd = mitk::PlanarFigureComposite::New(); PFCAnd->setOperationType(mitk::PFCOMPOSITION_AND_OPERATION); for( std::vector::iterator it = m_SelectedPF.begin(); it != m_SelectedPF.end(); ++it ) { mitk::DataNode::Pointer nodePF = *it; PFCAnd->addPlanarFigure( nodePF->GetData() ); PFCAnd->addDataNode( nodePF ); PFCAnd->setDisplayName("AND"); } AddCompositeToDatastorage(PFCAnd); } void QmitkFiberProcessingView::GenerateOrComposite() { mitk::PlanarFigureComposite::Pointer PFCOr = mitk::PlanarFigureComposite::New(); PFCOr->setOperationType(mitk::PFCOMPOSITION_OR_OPERATION); for( std::vector::iterator it = m_SelectedPF.begin(); it != m_SelectedPF.end(); ++it ) { mitk::DataNode::Pointer nodePF = *it; PFCOr->addPlanarFigure( nodePF->GetData() ); PFCOr->addDataNode( nodePF ); PFCOr->setDisplayName("OR"); } AddCompositeToDatastorage(PFCOr); } void QmitkFiberProcessingView::GenerateNotComposite() { mitk::PlanarFigureComposite::Pointer PFCNot = mitk::PlanarFigureComposite::New(); PFCNot->setOperationType(mitk::PFCOMPOSITION_NOT_OPERATION); for( std::vector::iterator it = m_SelectedPF.begin(); it != m_SelectedPF.end(); ++it ) { mitk::DataNode::Pointer nodePF = *it; PFCNot->addPlanarFigure( nodePF->GetData() ); PFCNot->addDataNode( nodePF ); PFCNot->setDisplayName("NOT"); } AddCompositeToDatastorage(PFCNot); } /* CLEANUP NEEDED */ void QmitkFiberProcessingView::AddCompositeToDatastorage(mitk::PlanarFigureComposite::Pointer pfc, mitk::DataNode::Pointer parentNode ) { mitk::DataNode::Pointer newPFCNode; newPFCNode = mitk::DataNode::New(); newPFCNode->SetName( pfc->getDisplayName() ); newPFCNode->SetData(pfc); switch (pfc->getOperationType()) { case 0: { if (parentNode.IsNotNull()) GetDataStorage()->Add(newPFCNode, parentNode); else GetDataStorage()->Add(newPFCNode); //iterate through its childs for(int i=0; igetNumberOfChildren(); ++i) { mitk::BaseData::Pointer tmpPFchild = pfc->getChildAt(i); mitk::DataNode::Pointer savedPFchildNode = pfc->getDataNodeAt(i); mitk::PlanarFigureComposite::Pointer pfcompcast= dynamic_cast(tmpPFchild.GetPointer()); if ( pfcompcast.IsNotNull() ) { // 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 pfc->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); } 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); newPFchildNode->SetBoolProperty("planarfigure.3drendering", true); // replace the dataNode in PFComp DataNodeVector pfc->replaceDataNodeAt(i, newPFchildNode); // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); //add new child to datamanager with its new position as child of newPFCNode parent GetDataStorage()->Add(newPFchildNode, newPFCNode); } } break; } case 1: { if (!parentNode.IsNull()) GetDataStorage()->Add(newPFCNode, parentNode); else GetDataStorage()->Add(newPFCNode); for(int i=0; igetNumberOfChildren(); ++i) { mitk::BaseData::Pointer tmpPFchild = pfc->getChildAt(i); mitk::DataNode::Pointer savedPFchildNode = pfc->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 pfc->replaceDataNodeAt(i, newChildPFCNode); AddCompositeToDatastorage(pfcompcast, newPFCNode); //the current PFCNode becomes the childs parent // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); } 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); newPFchildNode->SetBoolProperty("planarfigure.3drendering", true); // replace the dataNode in PFComp DataNodeVector pfc->replaceDataNodeAt(i, newPFchildNode); // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); //add new child to datamanager with its new position as child of newPFCNode parent GetDataStorage()->Add(newPFchildNode, newPFCNode); } } break; } case 2: { if (!parentNode.IsNull()) GetDataStorage()->Add(newPFCNode, parentNode); else GetDataStorage()->Add(newPFCNode); //iterate through its childs for(int i=0; igetNumberOfChildren(); ++i) { mitk::BaseData::Pointer tmpPFchild = pfc->getChildAt(i); mitk::DataNode::Pointer savedPFchildNode = pfc->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 pfc->replaceDataNodeAt(i, newChildPFCNode); AddCompositeToDatastorage(pfcompcast, newPFCNode); //the current PFCNode becomes the childs parent // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); } 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); newPFchildNode->SetBoolProperty("planarfigure.3drendering", true); // replace the dataNode in PFComp DataNodeVector pfc->replaceDataNodeAt(i, newPFchildNode); // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); //add new child to datamanager with its new position as child of newPFCNode parent GetDataStorage()->Add(newPFchildNode, newPFCNode); } } break; } default: MITK_DEBUG << "we have an UNDEFINED composition... ERROR" ; break; } for(unsigned int i = 0; i < m_SelectedPF.size(); i++) m_SelectedPF[i]->SetSelected(false); newPFCNode->SetSelected(true); m_SelectedPF.clear(); m_SelectedPF.push_back(newPFCNode); UpdateGui(); } 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; } - mitk::FiberBundleX::Pointer newBundle = dynamic_cast(m_SelectedFB.at(0)->GetData()); + mitk::FiberBundle::Pointer newBundle = dynamic_cast(m_SelectedFB.at(0)->GetData()); m_SelectedFB.at(0)->SetVisibility(false); QString name(""); name += QString(m_SelectedFB.at(0)->GetName().c_str()); for (unsigned int i=1; iAddBundle(dynamic_cast(m_SelectedFB.at(i)->GetData())); + newBundle = newBundle->AddBundle(dynamic_cast(m_SelectedFB.at(i)->GetData())); name += "+"+QString(m_SelectedFB.at(i)->GetName().c_str()); m_SelectedFB.at(i)->SetVisibility(false); } 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; } - mitk::FiberBundleX::Pointer newBundle = dynamic_cast(m_SelectedFB.at(0)->GetData()); + mitk::FiberBundle::Pointer newBundle = dynamic_cast(m_SelectedFB.at(0)->GetData()); m_SelectedFB.at(0)->SetVisibility(false); QString name(""); name += QString(m_SelectedFB.at(0)->GetName().c_str()); for (unsigned int i=1; iSubtractBundle(dynamic_cast(m_SelectedFB.at(i)->GetData())); + newBundle = newBundle->SubtractBundle(dynamic_cast(m_SelectedFB.at(i)->GetData())); if (newBundle.IsNull()) break; name += "-"+QString(m_SelectedFB.at(i)->GetName().c_str()); m_SelectedFB.at(i)->SetVisibility(false); } 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::ResampleSelectedBundles() { double factor = this->m_Controls->m_SmoothFibersBox->value(); for (unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedFB.at(i)->GetData()); fib->ResampleSpline(factor); } RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberProcessingView::CompressSelectedBundles() { double factor = this->m_Controls->m_ErrorThresholdBox->value(); for (unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedFB.at(i)->GetData()); fib->Compress(factor); } RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberProcessingView::DoImageColorCoding() { if (m_Controls->m_ColorMapBox->GetSelectedNode().IsNull()) { QMessageBox::information(NULL, "Bundle coloring aborted:", "No image providing the scalar values for coloring the selected bundle available."); return; } for(unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedFB.at(i)->GetData()); fib->ColorFibersByScalarMap(dynamic_cast(m_Controls->m_ColorMapBox->GetSelectedNode()->GetData()), m_Controls->m_FiberOpacityBox->isChecked()); } if(m_MultiWidget) m_MultiWidget->RequestUpdate(); } void QmitkFiberProcessingView::MirrorFibers() { unsigned int axis = this->m_Controls->m_MirrorFibersBox->currentIndex(); for (int i=0; i(m_SelectedFB.at(i)->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedFB.at(i)->GetData()); fib->MirrorFibers(axis); } if (m_SelectedSurfaces.size()>0) { for (int i=0; i poly = surf->GetVtkPolyData(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); for (int i=0; iGetNumberOfPoints(); i++) { double* point = poly->GetPoint(i); point[axis] *= -1; vtkNewPoints->InsertNextPoint(point); } poly->SetPoints(vtkNewPoints); surf->CalculateBoundingBox(); } } RenderingManager::GetInstance()->RequestUpdateAll(); } 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 24d0569311..f94facd239 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.h @@ -1,189 +1,189 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef 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 /*! \brief View to process fiber bundles. Supplies methods to extract fibers from the bundle, join and subtract bundles 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 > itkUCharImageType; 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(); ///< add circle interactors etc. void OnDrawPolygon(); ///< add circle interactors etc. void GenerateAndComposite(); void GenerateOrComposite(); void GenerateNotComposite(); void JoinBundles(); ///< merge selected fiber bundles void SubstractBundles(); ///< subtract bundle A from bundle B. Not commutative! Defined by order of selection. void GenerateRoiImage(); ///< generate binary image of selected planar figures. void Remove(); void Extract(); void Modify(); void UpdateGui(); ///< update button activity etc. dpending on current datamanager selection virtual void AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, const char *propertyKey = NULL, mitk::BaseProperty *property = NULL ); protected: void MirrorFibers(); ///< mirror bundle on the specified plane void ResampleSelectedBundles(); ///< smooth fiber bundle using the specified number of sampling points per cm. void DoImageColorCoding(); ///< color fibers by selected scalar image void CompressSelectedBundles(); ///< remove points below certain error threshold void WeightFibers(); void RemoveWithMask(bool removeInside); void RemoveDir(); void ApplyCurvatureThreshold(); ///< remove/split fibers with a too high curvature threshold void PruneBundle(); ///< remove too short/too long fibers void ExtractWithMask(bool onlyEnds, bool invert); void ExtractWithPlanarFigure(); /// \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::BaseGeometry* planegeo3D, int additionalIndex ); int m_CircleCounter; ///< used for data node naming int m_PolygonCounter; ///< used for data node naming std::vector m_SelectedFB; ///< selected fiber bundle nodes std::vector m_SelectedPF; ///< selected planar figure nodes std::vector m_SelectedSurfaces; mitk::Image::Pointer m_SelectedImage; mitk::Image::Pointer m_InternalImage; mitk::PlanarFigure::Pointer m_PlanarFigure; itkUCharImageType::Pointer m_InternalImageMask3D; itkUCharImageType::Pointer m_PlanarFigureImage; float m_UpsamplingFactor; ///< upsampling factor for all image generations mitk::DataNode::Pointer m_MaskImageNode; void AddCompositeToDatastorage(mitk::PlanarFigureComposite::Pointer pfc, mitk::DataNode::Pointer parentNode=NULL); void debugPFComposition(mitk::PlanarFigureComposite::Pointer , int ); void WritePfToImage(mitk::DataNode::Pointer node, mitk::Image* image); - mitk::DataNode::Pointer GenerateTractDensityImage(mitk::FiberBundleX::Pointer fib, bool binary, bool absolute); - mitk::DataNode::Pointer GenerateColorHeatmap(mitk::FiberBundleX::Pointer fib); - mitk::DataNode::Pointer GenerateFiberEndingsImage(mitk::FiberBundleX::Pointer fib); - mitk::DataNode::Pointer GenerateFiberEndingsPointSet(mitk::FiberBundleX::Pointer fib); + mitk::DataNode::Pointer GenerateTractDensityImage(mitk::FiberBundle::Pointer fib, bool binary, bool absolute); + mitk::DataNode::Pointer GenerateColorHeatmap(mitk::FiberBundle::Pointer fib); + mitk::DataNode::Pointer GenerateFiberEndingsImage(mitk::FiberBundle::Pointer fib); + mitk::DataNode::Pointer GenerateFiberEndingsPointSet(mitk::FiberBundle::Pointer fib); void NodeAdded( const mitk::DataNode* node ); void NodeRemoved(const mitk::DataNode* node); }; #endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberQuantificationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberQuantificationView.cpp index e12f09e205..67114abb21 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberQuantificationView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberQuantificationView.cpp @@ -1,442 +1,442 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkFiberQuantificationView.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 #include #include const std::string QmitkFiberQuantificationView::VIEW_ID = "org.mitk.views.fiberquantification"; const std::string id_DataManager = "org.mitk.views.datamanager"; using namespace mitk; QmitkFiberQuantificationView::QmitkFiberQuantificationView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) , m_UpsamplingFactor(5) { } // Destructor QmitkFiberQuantificationView::~QmitkFiberQuantificationView() { } void QmitkFiberQuantificationView::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::QmitkFiberQuantificationViewControls; m_Controls->setupUi( parent ); connect( m_Controls->m_ProcessFiberBundleButton, SIGNAL(clicked()), this, SLOT(ProcessSelectedBundles()) ); connect( m_Controls->m_ExtractFiberPeaks, SIGNAL(clicked()), this, SLOT(CalculateFiberDirections()) ); } } void QmitkFiberQuantificationView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkFiberQuantificationView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkFiberQuantificationView::CalculateFiberDirections() { typedef itk::Image ItkUcharImgType; typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; typedef itk::VectorContainer< unsigned int, ItkDirectionImage3DType::Pointer > ItkDirectionImageContainerType; // load fiber bundle - mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(m_SelectedFB.back()->GetData()); + mitk::FiberBundle::Pointer inputTractogram = dynamic_cast(m_SelectedFB.back()->GetData()); itk::TractsToVectorImageFilter::Pointer fOdfFilter = itk::TractsToVectorImageFilter::New(); if (m_SelectedImage.IsNotNull()) { ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); mitk::CastToItkImage(m_SelectedImage, itkMaskImage); fOdfFilter->SetMaskImage(itkMaskImage); } // extract directions from fiber bundle fOdfFilter->SetFiberBundle(inputTractogram); fOdfFilter->SetAngularThreshold(cos(m_Controls->m_AngularThreshold->value()*M_PI/180)); fOdfFilter->SetNormalizeVectors(m_Controls->m_NormalizeDirectionsBox->isChecked()); fOdfFilter->SetUseWorkingCopy(true); fOdfFilter->SetCreateDirectionImages(m_Controls->m_DirectionImagesBox->isChecked()); fOdfFilter->SetSizeThreshold(m_Controls->m_PeakThreshold->value()); fOdfFilter->SetMaxNumDirections(m_Controls->m_MaxNumDirections->value()); fOdfFilter->Update(); QString name = m_SelectedFB.back()->GetName().c_str(); if (m_Controls->m_VectorFieldBox->isChecked()) { float minSpacing = 1; if (m_SelectedImage.IsNotNull()) { mitk::Vector3D outImageSpacing = m_SelectedImage->GetGeometry()->GetSpacing(); if(outImageSpacing[0]GetOutputFiberBundle(); + mitk::FiberBundle::Pointer directions = fOdfFilter->GetOutputFiberBundle(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(directions); node->SetName((name+"_vectorfield").toStdString().c_str()); node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(minSpacing)); node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false)); node->SetProperty("color", mitk::ColorProperty::New(1.0f, 1.0f, 1.0f)); GetDefaultDataStorage()->Add(node, m_SelectedFB.back()); } if (m_Controls->m_NumDirectionsBox->isChecked()) { mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( fOdfFilter->GetNumDirectionsImage().GetPointer() ); mitkImage->SetVolume( fOdfFilter->GetNumDirectionsImage()->GetBufferPointer() ); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(mitkImage); node->SetName((name+"_numdirections").toStdString().c_str()); GetDefaultDataStorage()->Add(node, m_SelectedFB.back()); } if (m_Controls->m_DirectionImagesBox->isChecked()) { ItkDirectionImageContainerType::Pointer directionImageContainer = fOdfFilter->GetDirectionImageContainer(); for (unsigned int i=0; iSize(); i++) { itk::TractsToVectorImageFilter::ItkDirectionImageType::Pointer itkImg = directionImageContainer->GetElement(i); if (itkImg.IsNull()) return; mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( itkImg.GetPointer() ); mitkImage->SetVolume( itkImg->GetBufferPointer() ); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(mitkImage); node->SetName( (name+"_direction_"+boost::lexical_cast(i).c_str()).toStdString().c_str()); node->SetVisibility(false); GetDefaultDataStorage()->Add(node, m_SelectedFB.back()); } } } void QmitkFiberQuantificationView::UpdateGui() { m_Controls->m_ProcessFiberBundleButton->setEnabled(!m_SelectedFB.empty()); m_Controls->m_ExtractFiberPeaks->setEnabled(!m_SelectedFB.empty()); } void QmitkFiberQuantificationView::OnSelectionChanged( std::vector nodes ) { //reset existing Vectors containing FiberBundles and PlanarFigures from a previous selection m_SelectedFB.clear(); m_SelectedSurfaces.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()) ) + if ( dynamic_cast(node->GetData()) ) { m_SelectedFB.push_back(node); } else if (dynamic_cast(node->GetData())) m_SelectedImage = dynamic_cast(node->GetData()); else if (dynamic_cast(node->GetData())) { m_SelectedSurfaces.push_back(dynamic_cast(node->GetData())); } } UpdateGui(); GenerateStats(); } void QmitkFiberQuantificationView::Activated() { } void QmitkFiberQuantificationView::GenerateStats() { if ( m_SelectedFB.empty() ) return; QString stats(""); for( int i=0; i(node->GetData())) + if (node.IsNotNull() && dynamic_cast(node->GetData())) { if (i>0) stats += "\n-----------------------------\n"; stats += QString(node->GetName().c_str()) + "\n"; - mitk::FiberBundleX::Pointer fib = dynamic_cast(node->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); stats += "Number of fibers: "+ QString::number(fib->GetNumFibers()) + "\n"; stats += "Number of points: "+ QString::number(fib->GetNumberOfPoints()) + "\n"; stats += "Min. length: "+ QString::number(fib->GetMinFiberLength(),'f',1) + " mm\n"; stats += "Max. length: "+ QString::number(fib->GetMaxFiberLength(),'f',1) + " mm\n"; stats += "Mean length: "+ QString::number(fib->GetMeanFiberLength(),'f',1) + " mm\n"; stats += "Median length: "+ QString::number(fib->GetMedianFiberLength(),'f',1) + " mm\n"; stats += "Standard deviation: "+ QString::number(fib->GetLengthStDev(),'f',1) + " mm\n"; } } this->m_Controls->m_StatsTextEdit->setText(stats); } void QmitkFiberQuantificationView::ProcessSelectedBundles() { if ( m_SelectedFB.empty() ){ QMessageBox::information( NULL, "Warning", "No fibe bundle selected!"); MITK_WARN("QmitkFiberQuantificationView") << "no fibe bundle selected"; return; } int generationMethod = m_Controls->m_GenerationBox->currentIndex(); for( int i=0; i(node->GetData())) + if (node.IsNotNull() && dynamic_cast(node->GetData())) { - mitk::FiberBundleX::Pointer fib = dynamic_cast(node->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); QString name(node->GetName().c_str()); DataNode::Pointer newNode = NULL; switch(generationMethod){ case 0: newNode = GenerateTractDensityImage(fib, false, true); name += "_TDI"; break; case 1: newNode = GenerateTractDensityImage(fib, false, false); name += "_TDI"; break; case 2: newNode = GenerateTractDensityImage(fib, true, false); name += "_envelope"; break; case 3: newNode = GenerateColorHeatmap(fib); break; case 4: newNode = GenerateFiberEndingsImage(fib); name += "_fiber_endings"; break; case 5: 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 QmitkFiberQuantificationView::GenerateFiberEndingsPointSet(mitk::FiberBundleX::Pointer fib) +mitk::DataNode::Pointer QmitkFiberQuantificationView::GenerateFiberEndingsPointSet(mitk::FiberBundle::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 QmitkFiberQuantificationView::GenerateFiberEndingsImage(mitk::FiberBundleX::Pointer fib) +mitk::DataNode::Pointer QmitkFiberQuantificationView::GenerateFiberEndingsImage(mitk::FiberBundle::Pointer fib) { typedef unsigned char OutPixType; typedef itk::Image OutImageType; typedef itk::TractsToFiberEndingsImageFilter< OutImageType > ImageGeneratorType; ImageGeneratorType::Pointer generator = ImageGeneratorType::New(); generator->SetFiberBundle(fib); 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 QmitkFiberQuantificationView::GenerateColorHeatmap(mitk::FiberBundleX::Pointer fib) +mitk::DataNode::Pointer QmitkFiberQuantificationView::GenerateColorHeatmap(mitk::FiberBundle::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 QmitkFiberQuantificationView::GenerateTractDensityImage(mitk::FiberBundleX::Pointer fib, bool binary, bool absolute) +mitk::DataNode::Pointer QmitkFiberQuantificationView::GenerateTractDensityImage(mitk::FiberBundle::Pointer fib, bool binary, bool absolute) { typedef float OutPixType; typedef itk::Image OutImageType; itk::TractDensityImageFilter< OutImageType >::Pointer generator = itk::TractDensityImageFilter< OutImageType >::New(); generator->SetFiberBundle(fib); generator->SetBinaryOutput(binary); generator->SetOutputAbsoluteValues(absolute); 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; } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberQuantificationView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberQuantificationView.h index a8197d688b..b616fe62c9 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberQuantificationView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberQuantificationView.h @@ -1,150 +1,150 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkFiberQuantificationView_h #define QmitkFiberQuantificationView_h #include #include "ui_QmitkFiberQuantificationViewControls.h" #include -#include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*! \brief View to process fiber bundles. Supplies methods to generate images from the selected bundle and much more. \sa QmitkFunctionality \ingroup Functionalities */ class QmitkFiberQuantificationView : 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 > itkUCharImageType; static const std::string VIEW_ID; QmitkFiberQuantificationView(); virtual ~QmitkFiberQuantificationView(); virtual void CreateQtPartControl(QWidget *parent); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); virtual void Activated(); protected slots: void ProcessSelectedBundles(); ///< start selected operation on fiber bundle (e.g. tract density image generation) void CalculateFiberDirections(); ///< Calculate main fiber directions from tractogram protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); Ui::QmitkFiberQuantificationViewControls* 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(); ///< generate statistics of selected fiber bundles void UpdateGui(); ///< update button activity etc. dpending on current datamanager selection std::vector m_SelectedFB; ///< selected fiber bundle nodes mitk::Image::Pointer m_SelectedImage; float m_UpsamplingFactor; ///< upsampling factor for all image generations std::vector m_SelectedSurfaces; - mitk::DataNode::Pointer GenerateTractDensityImage(mitk::FiberBundleX::Pointer fib, bool binary, bool absolute); - mitk::DataNode::Pointer GenerateColorHeatmap(mitk::FiberBundleX::Pointer fib); - mitk::DataNode::Pointer GenerateFiberEndingsImage(mitk::FiberBundleX::Pointer fib); - mitk::DataNode::Pointer GenerateFiberEndingsPointSet(mitk::FiberBundleX::Pointer fib); + mitk::DataNode::Pointer GenerateTractDensityImage(mitk::FiberBundle::Pointer fib, bool binary, bool absolute); + mitk::DataNode::Pointer GenerateColorHeatmap(mitk::FiberBundle::Pointer fib); + mitk::DataNode::Pointer GenerateFiberEndingsImage(mitk::FiberBundle::Pointer fib); + mitk::DataNode::Pointer GenerateFiberEndingsPointSet(mitk::FiberBundle::Pointer fib); }; #endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp index fd750f32f1..78a4210658 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp @@ -1,2694 +1,2694 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //misc #define _USE_MATH_DEFINES #include // Blueberry #include #include // Qmitk #include "QmitkFiberfoxView.h" // MITK #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 #include "usModuleRegistry.h" #include #include #include #include #include #include #include #include #include #include "mitkNodePredicateDataType.h" #include #include #include #include #define _USE_MATH_DEFINES #include QmitkFiberfoxWorker::QmitkFiberfoxWorker(QmitkFiberfoxView* view) : m_View(view) { } void QmitkFiberfoxWorker::run() { try{ switch (m_FilterType) { case 0: m_View->m_TractsToDwiFilter->Update(); break; case 1: m_View->m_ArtifactsToDwiFilter->Update(); break; } } catch( ... ) { } m_View->m_Thread.quit(); } const std::string QmitkFiberfoxView::VIEW_ID = "org.mitk.views.fiberfoxview"; QmitkFiberfoxView::QmitkFiberfoxView() : QmitkAbstractView() , m_Controls( 0 ) , m_SelectedImage( NULL ) , m_Worker(this) , m_ThreadIsRunning(false) { m_Worker.moveToThread(&m_Thread); connect(&m_Thread, SIGNAL(started()), this, SLOT(BeforeThread())); connect(&m_Thread, SIGNAL(started()), &m_Worker, SLOT(run())); connect(&m_Thread, SIGNAL(finished()), this, SLOT(AfterThread())); connect(&m_Thread, SIGNAL(terminated()), this, SLOT(AfterThread())); m_SimulationTimer = new QTimer(this); } void QmitkFiberfoxView::KillThread() { MITK_INFO << "Aborting DWI simulation."; switch (m_Worker.m_FilterType) { case 0: m_TractsToDwiFilter->SetAbortGenerateData(true); break; case 1: m_ArtifactsToDwiFilter->SetAbortGenerateData(true); break; } m_Controls->m_AbortSimulationButton->setEnabled(false); m_Controls->m_AbortSimulationButton->setText("Aborting simulation ..."); } void QmitkFiberfoxView::BeforeThread() { m_SimulationTime = QTime::currentTime(); m_SimulationTimer->start(100); m_Controls->m_AbortSimulationButton->setVisible(true); m_Controls->m_GenerateImageButton->setVisible(false); m_Controls->m_SimulationStatusText->setVisible(true); m_ThreadIsRunning = true; } void QmitkFiberfoxView::AfterThread() { UpdateSimulationStatus(); m_SimulationTimer->stop(); m_Controls->m_AbortSimulationButton->setVisible(false); m_Controls->m_AbortSimulationButton->setEnabled(true); m_Controls->m_AbortSimulationButton->setText("Abort simulation"); m_Controls->m_GenerateImageButton->setVisible(true); m_ThreadIsRunning = false; QString statusText; FiberfoxParameters parameters; mitk::Image::Pointer mitkImage = mitk::Image::New(); switch (m_Worker.m_FilterType) { case 0: { statusText = QString(m_TractsToDwiFilter->GetStatusText().c_str()); if (m_TractsToDwiFilter->GetAbortGenerateData()) { MITK_INFO << "Simulation aborted."; return; } parameters = m_TractsToDwiFilter->GetParameters(); mitkImage = mitk::GrabItkImageMemory( m_TractsToDwiFilter->GetOutput() ); mitkImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( parameters.m_SignalGen.GetGradientDirections() )); mitkImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( parameters.m_SignalGen.m_Bvalue )); mitk::DiffusionPropertyHelper propertyHelper( mitkImage ); propertyHelper.InitializeImage(); parameters.m_Misc.m_ResultNode->SetData( mitkImage ); parameters.m_Misc.m_ResultNode->SetName(parameters.m_Misc.m_ParentNode->GetName() +"_D"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(0)).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(1)).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(2)).toStdString() +"_S"+QString::number(parameters.m_SignalGen.m_ImageSpacing[0]).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageSpacing[1]).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageSpacing[2]).toStdString() +"_b"+QString::number(parameters.m_SignalGen.m_Bvalue).toStdString() +"_"+parameters.m_Misc.m_SignalModelString +parameters.m_Misc.m_ArtifactModelString); GetDataStorage()->Add(parameters.m_Misc.m_ResultNode, parameters.m_Misc.m_ParentNode); parameters.m_Misc.m_ResultNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New(m_TractsToDwiFilter->GetLevelWindow()) ); if (m_Controls->m_VolumeFractionsBox->isChecked()) { std::vector< itk::TractsToDWIImageFilter< short >::ItkDoubleImgType::Pointer > volumeFractions = m_TractsToDwiFilter->GetVolumeFractions(); for (unsigned int k=0; kInitializeByItk(volumeFractions.at(k).GetPointer()); image->SetVolume(volumeFractions.at(k)->GetBufferPointer()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName(parameters.m_Misc.m_ParentNode->GetName()+"_CompartmentVolume-"+QString::number(k).toStdString()); GetDataStorage()->Add(node, parameters.m_Misc.m_ParentNode); } } m_TractsToDwiFilter = NULL; break; } case 1: { statusText = QString(m_ArtifactsToDwiFilter->GetStatusText().c_str()); if (m_ArtifactsToDwiFilter->GetAbortGenerateData()) { MITK_INFO << "Simulation aborted."; return; } parameters = m_ArtifactsToDwiFilter->GetParameters().CopyParameters(); mitk::Image::Pointer diffImg = dynamic_cast(parameters.m_Misc.m_ParentNode->GetData()); mitkImage = mitk::GrabItkImageMemory( m_ArtifactsToDwiFilter->GetOutput() ); mitkImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ) ); mitkImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ) ); mitk::DiffusionPropertyHelper propertyHelper( mitkImage ); propertyHelper.InitializeImage(); parameters.m_Misc.m_ResultNode->SetData( mitkImage ); parameters.m_Misc.m_ResultNode->SetName(parameters.m_Misc.m_ParentNode->GetName()+parameters.m_Misc.m_ArtifactModelString); GetDataStorage()->Add(parameters.m_Misc.m_ResultNode, parameters.m_Misc.m_ParentNode); m_ArtifactsToDwiFilter = NULL; break; } } mitk::BaseData::Pointer basedata = parameters.m_Misc.m_ResultNode->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } if (!parameters.m_Misc.m_OutputPath.empty()) { try{ QString outputFileName(parameters.m_Misc.m_OutputPath.c_str()); outputFileName += parameters.m_Misc.m_ResultNode->GetName().c_str(); outputFileName.replace(QString("."), QString("_")); outputFileName += ".dwi"; QString status("Saving output image to "); status += outputFileName; m_Controls->m_SimulationStatusText->append(status); mitk::IOUtil::SaveBaseData(mitkImage, outputFileName.toStdString()); m_Controls->m_SimulationStatusText->append("File saved successfully."); } catch (itk::ExceptionObject &e) { QString status("Exception during DWI writing: "); status += e.GetDescription(); m_Controls->m_SimulationStatusText->append(status); } catch (...) { m_Controls->m_SimulationStatusText->append("Unknown exception during DWI writing!"); } } parameters.m_SignalGen.m_FrequencyMap = NULL; } void QmitkFiberfoxView::UpdateSimulationStatus() { QString statusText; switch (m_Worker.m_FilterType) { case 0: statusText = QString(m_TractsToDwiFilter->GetStatusText().c_str()); break; case 1: statusText = QString(m_ArtifactsToDwiFilter->GetStatusText().c_str()); break; } if (QString::compare(m_SimulationStatusText,statusText)!=0) { m_Controls->m_SimulationStatusText->clear(); statusText = "
"+statusText+"
"; m_Controls->m_SimulationStatusText->setText(statusText); QScrollBar *vScrollBar = m_Controls->m_SimulationStatusText->verticalScrollBar(); vScrollBar->triggerAction(QScrollBar::SliderToMaximum); } } // Destructor QmitkFiberfoxView::~QmitkFiberfoxView() { delete m_SimulationTimer; } void QmitkFiberfoxView::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::QmitkFiberfoxViewControls; m_Controls->setupUi( parent ); // commented out m_Controls->m_DiffusionDirectionBox->setVisible(false); m_Controls->label_3->setVisible(false); m_Controls->m_SeparationAngleBox->setVisible(false); m_Controls->label_4->setVisible(false); // m_Controls->m_StickWidget1->setVisible(true); m_Controls->m_StickWidget2->setVisible(false); m_Controls->m_ZeppelinWidget1->setVisible(false); m_Controls->m_ZeppelinWidget2->setVisible(false); m_Controls->m_TensorWidget1->setVisible(false); m_Controls->m_TensorWidget2->setVisible(false); m_Controls->m_BallWidget1->setVisible(true); m_Controls->m_BallWidget2->setVisible(false); m_Controls->m_AstrosticksWidget1->setVisible(false); m_Controls->m_AstrosticksWidget2->setVisible(false); m_Controls->m_DotWidget1->setVisible(false); m_Controls->m_DotWidget2->setVisible(false); m_Controls->m_PrototypeWidget1->setVisible(false); m_Controls->m_PrototypeWidget2->setVisible(false); m_Controls->m_PrototypeWidget3->setVisible(false); m_Controls->m_PrototypeWidget4->setVisible(false); m_Controls->m_PrototypeWidget3->SetMinFa(0.0); m_Controls->m_PrototypeWidget3->SetMaxFa(0.15); m_Controls->m_PrototypeWidget4->SetMinFa(0.0); m_Controls->m_PrototypeWidget4->SetMaxFa(0.15); m_Controls->m_PrototypeWidget3->SetMinAdc(0.0); m_Controls->m_PrototypeWidget3->SetMaxAdc(0.001); m_Controls->m_PrototypeWidget4->SetMinAdc(0.003); m_Controls->m_PrototypeWidget4->SetMaxAdc(0.004); m_Controls->m_Comp4FractionFrame->setVisible(false); m_Controls->m_DiffusionPropsMessage->setVisible(false); m_Controls->m_GeometryMessage->setVisible(false); m_Controls->m_AdvancedSignalOptionsFrame->setVisible(false); m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false); m_Controls->m_VarianceBox->setVisible(false); m_Controls->m_NoiseFrame->setVisible(false); m_Controls->m_GhostFrame->setVisible(false); m_Controls->m_DistortionsFrame->setVisible(false); m_Controls->m_EddyFrame->setVisible(false); m_Controls->m_SpikeFrame->setVisible(false); m_Controls->m_AliasingFrame->setVisible(false); m_Controls->m_MotionArtifactFrame->setVisible(false); m_ParameterFile = QDir::currentPath()+"/param.ffp"; m_Controls->m_AbortSimulationButton->setVisible(false); m_Controls->m_SimulationStatusText->setVisible(false); m_Controls->m_FrequencyMapBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_Comp4VolumeFraction->SetDataStorage(this->GetDataStorage()); m_Controls->m_MaskComboBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_TemplateComboBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_FiberBundleComboBox->SetDataStorage(this->GetDataStorage()); - mitk::TNodePredicateDataType::Pointer isFiberBundle = mitk::TNodePredicateDataType::New(); + mitk::TNodePredicateDataType::Pointer isFiberBundle = mitk::TNodePredicateDataType::New(); mitk::TNodePredicateDataType::Pointer isMitkImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateIsDWI::Pointer isDwi = mitk::NodePredicateIsDWI::New( ); mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); mitk::NodePredicateDataType::Pointer isQbi = mitk::NodePredicateDataType::New("QBallImage"); mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isDwi, isDti); isDiffusionImage = mitk::NodePredicateOr::New(isDiffusionImage, isQbi); mitk::NodePredicateNot::Pointer noDiffusionImage = mitk::NodePredicateNot::New(isDiffusionImage); mitk::NodePredicateAnd::Pointer isNonDiffMitkImage = mitk::NodePredicateAnd::New(isMitkImage, noDiffusionImage); mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateAnd::Pointer isBinaryMitkImage = mitk::NodePredicateAnd::New( isNonDiffMitkImage, isBinaryPredicate ); m_Controls->m_FrequencyMapBox->SetPredicate(isNonDiffMitkImage); m_Controls->m_Comp4VolumeFraction->SetPredicate(isNonDiffMitkImage); m_Controls->m_MaskComboBox->SetPredicate(isBinaryMitkImage); m_Controls->m_MaskComboBox->SetZeroEntryText("--"); m_Controls->m_TemplateComboBox->SetPredicate(isMitkImage); m_Controls->m_TemplateComboBox->SetZeroEntryText("--"); m_Controls->m_FiberBundleComboBox->SetPredicate(isFiberBundle); m_Controls->m_FiberBundleComboBox->SetZeroEntryText("--"); // mitk::NodePredicateDimension::Pointer dimensionPredicate = mitk::NodePredicateDimension::New(3); connect( m_SimulationTimer, SIGNAL(timeout()), this, SLOT(UpdateSimulationStatus()) ); connect((QObject*) m_Controls->m_AbortSimulationButton, SIGNAL(clicked()), (QObject*) this, SLOT(KillThread())); connect((QObject*) m_Controls->m_GenerateImageButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateImage())); connect((QObject*) m_Controls->m_GenerateFibersButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateFibers())); connect((QObject*) m_Controls->m_CircleButton, SIGNAL(clicked()), (QObject*) this, SLOT(OnDrawROI())); connect((QObject*) m_Controls->m_FlipButton, SIGNAL(clicked()), (QObject*) this, SLOT(OnFlipButton())); connect((QObject*) m_Controls->m_JoinBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(JoinBundles())); connect((QObject*) m_Controls->m_VarianceBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnVarianceChanged(double))); connect((QObject*) m_Controls->m_DistributionBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnDistributionChanged(int))); connect((QObject*) m_Controls->m_FiberDensityBox, SIGNAL(valueChanged(int)), (QObject*) this, SLOT(OnFiberDensityChanged(int))); connect((QObject*) m_Controls->m_FiberSamplingBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnFiberSamplingChanged(double))); connect((QObject*) m_Controls->m_TensionBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnTensionChanged(double))); connect((QObject*) m_Controls->m_ContinuityBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnContinuityChanged(double))); connect((QObject*) m_Controls->m_BiasBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnBiasChanged(double))); connect((QObject*) m_Controls->m_AddNoise, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddNoise(int))); connect((QObject*) m_Controls->m_AddGhosts, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddGhosts(int))); connect((QObject*) m_Controls->m_AddDistortions, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddDistortions(int))); connect((QObject*) m_Controls->m_AddEddy, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddEddy(int))); connect((QObject*) m_Controls->m_AddSpikes, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddSpikes(int))); connect((QObject*) m_Controls->m_AddAliasing, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddAliasing(int))); connect((QObject*) m_Controls->m_AddMotion, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddMotion(int))); connect((QObject*) m_Controls->m_ConstantRadiusBox, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnConstantRadius(int))); connect((QObject*) m_Controls->m_CopyBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(CopyBundles())); connect((QObject*) m_Controls->m_TransformBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(ApplyTransform())); connect((QObject*) m_Controls->m_AlignOnGrid, SIGNAL(clicked()), (QObject*) this, SLOT(AlignOnGrid())); connect((QObject*) m_Controls->m_Compartment1Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp1ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_Compartment2Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp2ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_Compartment3Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp3ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_Compartment4Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp4ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_AdvancedOptionsBox, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedOptions(int))); connect((QObject*) m_Controls->m_AdvancedOptionsBox_2, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedOptions(int))); connect((QObject*) m_Controls->m_SaveParametersButton, SIGNAL(clicked()), (QObject*) this, SLOT(SaveParameters())); connect((QObject*) m_Controls->m_LoadParametersButton, SIGNAL(clicked()), (QObject*) this, SLOT(LoadParameters())); connect((QObject*) m_Controls->m_OutputPathButton, SIGNAL(clicked()), (QObject*) this, SLOT(SetOutputPath())); connect((QObject*) m_Controls->m_MaskComboBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnMaskSelected(int))); connect((QObject*) m_Controls->m_TemplateComboBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnTemplateSelected(int))); connect((QObject*) m_Controls->m_FiberBundleComboBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnFibSelected(int))); } } void QmitkFiberfoxView::OnMaskSelected(int value) { UpdateGui(); } void QmitkFiberfoxView::OnTemplateSelected(int value) { UpdateGui(); } void QmitkFiberfoxView::OnFibSelected(int value) { UpdateGui(); } template< class ScalarType > FiberfoxParameters< ScalarType > QmitkFiberfoxView::UpdateImageParameters() { FiberfoxParameters< ScalarType > parameters; parameters.m_Misc.m_OutputPath = ""; parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); parameters.m_Misc.m_CheckAdvancedSignalOptionsBox = m_Controls->m_AdvancedOptionsBox_2->isChecked(); parameters.m_Misc.m_CheckOutputVolumeFractionsBox = m_Controls->m_VolumeFractionsBox->isChecked(); string outputPath = m_Controls->m_SavePathEdit->text().toStdString(); if (outputPath.compare("-")!=0) { parameters.m_Misc.m_OutputPath = outputPath; parameters.m_Misc.m_OutputPath += "/"; } if (m_Controls->m_MaskComboBox->GetSelectedNode().IsNotNull()) { mitk::Image::Pointer mitkMaskImage = dynamic_cast(m_Controls->m_MaskComboBox->GetSelectedNode()->GetData()); mitk::CastToItkImage(mitkMaskImage, parameters.m_SignalGen.m_MaskImage); itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); duplicator->SetInputImage(parameters.m_SignalGen.m_MaskImage); duplicator->Update(); parameters.m_SignalGen.m_MaskImage = duplicator->GetOutput(); } if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull() && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()))) // use parameters of selected DWI { mitk::Image::Pointer dwi = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); parameters.m_SignalGen.m_ImageRegion = itkVectorImagePointer->GetLargestPossibleRegion(); parameters.m_SignalGen.m_ImageSpacing = itkVectorImagePointer->GetSpacing(); parameters.m_SignalGen.m_ImageOrigin = itkVectorImagePointer->GetOrigin(); parameters.m_SignalGen.m_ImageDirection = itkVectorImagePointer->GetDirection(); parameters.m_SignalGen.m_Bvalue = static_cast(dwi->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(); parameters.m_SignalGen.SetGradienDirections(static_cast( dwi->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer()); } else if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull()) // use geometry of selected image { mitk::Image::Pointer img = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); itk::Image< float, 3 >::Pointer itkImg = itk::Image< float, 3 >::New(); CastToItkImage< itk::Image< float, 3 > >(img, itkImg); parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion(); parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing(); parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin(); parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection(); parameters.m_SignalGen.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value()); parameters.m_SignalGen.m_Bvalue = m_Controls->m_BvalueBox->value(); } else // use GUI parameters { parameters.m_SignalGen.m_ImageRegion.SetSize(0, m_Controls->m_SizeX->value()); parameters.m_SignalGen.m_ImageRegion.SetSize(1, m_Controls->m_SizeY->value()); parameters.m_SignalGen.m_ImageRegion.SetSize(2, m_Controls->m_SizeZ->value()); parameters.m_SignalGen.m_ImageSpacing[0] = m_Controls->m_SpacingX->value(); parameters.m_SignalGen.m_ImageSpacing[1] = m_Controls->m_SpacingY->value(); parameters.m_SignalGen.m_ImageSpacing[2] = m_Controls->m_SpacingZ->value(); parameters.m_SignalGen.m_ImageOrigin[0] = parameters.m_SignalGen.m_ImageSpacing[0]/2; parameters.m_SignalGen.m_ImageOrigin[1] = parameters.m_SignalGen.m_ImageSpacing[1]/2; parameters.m_SignalGen.m_ImageOrigin[2] = parameters.m_SignalGen.m_ImageSpacing[2]/2; parameters.m_SignalGen.m_ImageDirection.SetIdentity(); parameters.m_SignalGen.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value()); parameters.m_SignalGen.m_Bvalue = m_Controls->m_BvalueBox->value(); parameters.m_SignalGen.GenerateGradientHalfShell(); } // signal relaxation parameters.m_SignalGen.m_DoSimulateRelaxation = m_Controls->m_RelaxationBox->isChecked(); parameters.m_SignalGen.m_SimulateKspaceAcquisition = parameters.m_SignalGen.m_DoSimulateRelaxation; if (parameters.m_SignalGen.m_DoSimulateRelaxation && m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNotNull() ) parameters.m_Misc.m_ArtifactModelString += "_RELAX"; // N/2 ghosts parameters.m_Misc.m_CheckAddGhostsBox = m_Controls->m_AddGhosts->isChecked(); if (m_Controls->m_AddGhosts->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_Misc.m_ArtifactModelString += "_GHOST"; parameters.m_SignalGen.m_KspaceLineOffset = m_Controls->m_kOffsetBox->value(); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Ghost", DoubleProperty::New(parameters.m_SignalGen.m_KspaceLineOffset)); } else parameters.m_SignalGen.m_KspaceLineOffset = 0; // Aliasing parameters.m_Misc.m_CheckAddAliasingBox = m_Controls->m_AddAliasing->isChecked(); if (m_Controls->m_AddAliasing->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_Misc.m_ArtifactModelString += "_ALIASING"; parameters.m_SignalGen.m_CroppingFactor = (100-m_Controls->m_WrapBox->value())/100; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Aliasing", DoubleProperty::New(m_Controls->m_WrapBox->value())); } // Spikes parameters.m_Misc.m_CheckAddSpikesBox = m_Controls->m_AddSpikes->isChecked(); if (m_Controls->m_AddSpikes->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_SignalGen.m_Spikes = m_Controls->m_SpikeNumBox->value(); parameters.m_SignalGen.m_SpikeAmplitude = m_Controls->m_SpikeScaleBox->value(); parameters.m_Misc.m_ArtifactModelString += "_SPIKES"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Spikes.Number", IntProperty::New(parameters.m_SignalGen.m_Spikes)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Spikes.Amplitude", DoubleProperty::New(parameters.m_SignalGen.m_SpikeAmplitude)); } // gibbs ringing parameters.m_SignalGen.m_DoAddGibbsRinging = m_Controls->m_AddGibbsRinging->isChecked(); if (m_Controls->m_AddGibbsRinging->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Ringing", BoolProperty::New(true)); parameters.m_Misc.m_ArtifactModelString += "_RINGING"; } // add distortions parameters.m_Misc.m_CheckAddDistortionsBox = m_Controls->m_AddDistortions->isChecked(); if (m_Controls->m_AddDistortions->isChecked() && m_Controls->m_FrequencyMapBox->GetSelectedNode().IsNotNull()) { mitk::DataNode::Pointer fMapNode = m_Controls->m_FrequencyMapBox->GetSelectedNode(); mitk::Image* img = dynamic_cast(fMapNode->GetData()); ItkDoubleImgType::Pointer itkImg = ItkDoubleImgType::New(); CastToItkImage< ItkDoubleImgType >(img, itkImg); if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNull()) // use geometry of frequency map { parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion(); parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing(); parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin(); parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection(); } if (parameters.m_SignalGen.m_ImageRegion.GetSize(0)==itkImg->GetLargestPossibleRegion().GetSize(0) && parameters.m_SignalGen.m_ImageRegion.GetSize(1)==itkImg->GetLargestPossibleRegion().GetSize(1) && parameters.m_SignalGen.m_ImageRegion.GetSize(2)==itkImg->GetLargestPossibleRegion().GetSize(2)) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); duplicator->SetInputImage(itkImg); duplicator->Update(); parameters.m_SignalGen.m_FrequencyMap = duplicator->GetOutput(); parameters.m_Misc.m_ArtifactModelString += "_DISTORTED"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Distortions", BoolProperty::New(true)); } } parameters.m_SignalGen.m_EddyStrength = 0; parameters.m_Misc.m_CheckAddEddyCurrentsBox = m_Controls->m_AddEddy->isChecked(); if (m_Controls->m_AddEddy->isChecked()) { parameters.m_SignalGen.m_EddyStrength = m_Controls->m_EddyGradientStrength->value(); parameters.m_Misc.m_ArtifactModelString += "_EDDY"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Eddy-strength", DoubleProperty::New(parameters.m_SignalGen.m_EddyStrength)); } // Motion parameters.m_SignalGen.m_DoAddMotion = m_Controls->m_AddMotion->isChecked(); parameters.m_SignalGen.m_DoRandomizeMotion = m_Controls->m_RandomMotion->isChecked(); parameters.m_SignalGen.m_Translation[0] = m_Controls->m_MaxTranslationBoxX->value(); parameters.m_SignalGen.m_Translation[1] = m_Controls->m_MaxTranslationBoxY->value(); parameters.m_SignalGen.m_Translation[2] = m_Controls->m_MaxTranslationBoxZ->value(); parameters.m_SignalGen.m_Rotation[0] = m_Controls->m_MaxRotationBoxX->value(); parameters.m_SignalGen.m_Rotation[1] = m_Controls->m_MaxRotationBoxY->value(); parameters.m_SignalGen.m_Rotation[2] = m_Controls->m_MaxRotationBoxZ->value(); if ( m_Controls->m_AddMotion->isChecked() && m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNotNull() ) { parameters.m_Misc.m_ArtifactModelString += "_MOTION"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Random", BoolProperty::New(parameters.m_SignalGen.m_DoRandomizeMotion)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-x", DoubleProperty::New(parameters.m_SignalGen.m_Translation[0])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-y", DoubleProperty::New(parameters.m_SignalGen.m_Translation[1])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-z", DoubleProperty::New(parameters.m_SignalGen.m_Translation[2])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-x", DoubleProperty::New(parameters.m_SignalGen.m_Rotation[0])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-y", DoubleProperty::New(parameters.m_SignalGen.m_Rotation[1])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-z", DoubleProperty::New(parameters.m_SignalGen.m_Rotation[2])); } // other imaging parameters parameters.m_SignalGen.m_tLine = m_Controls->m_LineReadoutTimeBox->value(); parameters.m_SignalGen.m_tInhom = m_Controls->m_T2starBox->value(); parameters.m_SignalGen.m_tEcho = m_Controls->m_TEbox->value(); parameters.m_SignalGen.m_DoDisablePartialVolume = m_Controls->m_EnforcePureFiberVoxelsBox->isChecked(); parameters.m_SignalGen.m_AxonRadius = m_Controls->m_FiberRadius->value(); parameters.m_SignalGen.m_SignalScale = m_Controls->m_SignalScaleBox->value(); // adjust echo time if needed if ( parameters.m_SignalGen.m_tEcho < parameters.m_SignalGen.m_ImageRegion.GetSize(1)*parameters.m_SignalGen.m_tLine ) { this->m_Controls->m_TEbox->setValue( parameters.m_SignalGen.m_ImageRegion.GetSize(1)*parameters.m_SignalGen.m_tLine ); parameters.m_SignalGen.m_tEcho = m_Controls->m_TEbox->value(); QMessageBox::information( NULL, "Warning", "Echo time is too short! Time not sufficient to read slice. Automaticall adjusted to "+QString::number(parameters.m_SignalGen.m_tEcho)+" ms"); } // Noise parameters.m_Misc.m_CheckAddNoiseBox = m_Controls->m_AddNoise->isChecked(); if (m_Controls->m_AddNoise->isChecked()) { double noiseVariance = m_Controls->m_NoiseLevel->value(); { switch (m_Controls->m_NoiseDistributionBox->currentIndex()) { case 0: { parameters.m_NoiseModel = new mitk::RicianNoiseModel(); parameters.m_Misc.m_ArtifactModelString += "_RICIAN-"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Rician")); break; } case 1: { parameters.m_NoiseModel = new mitk::ChiSquareNoiseModel(); parameters.m_Misc.m_ArtifactModelString += "_CHISQUARED-"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Chi-squared")); break; } default: { parameters.m_NoiseModel = new mitk::RicianNoiseModel(); parameters.m_Misc.m_ArtifactModelString += "_RICIAN-"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Rician")); } } } parameters.m_NoiseModel->SetNoiseVariance(noiseVariance); parameters.m_Misc.m_ArtifactModelString += QString::number(noiseVariance).toStdString(); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Variance", DoubleProperty::New(noiseVariance)); } // adjusting line readout time to the adapted image size needed for the DFT unsigned int y = parameters.m_SignalGen.m_ImageRegion.GetSize(1); y += y%2; if ( y>parameters.m_SignalGen.m_ImageRegion.GetSize(1) ) parameters.m_SignalGen.m_tLine *= (double)parameters.m_SignalGen.m_ImageRegion.GetSize(1)/y; // signal models { // compartment 1 switch (m_Controls->m_Compartment1Box->currentIndex()) { case 0: { mitk::StickModel* model = new mitk::StickModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_StickWidget1->GetD()); model->SetT2(m_Controls->m_StickWidget1->GetT2()); model->m_CompartmentId = 1; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Stick"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Stick") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D", DoubleProperty::New(m_Controls->m_StickWidget1->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); break; } case 1: { mitk::TensorModel* model = new mitk::TensorModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity1(m_Controls->m_ZeppelinWidget1->GetD1()); model->SetDiffusivity2(m_Controls->m_ZeppelinWidget1->GetD2()); model->SetDiffusivity3(m_Controls->m_ZeppelinWidget1->GetD2()); model->SetT2(m_Controls->m_ZeppelinWidget1->GetT2()); model->m_CompartmentId = 1; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Zeppelin"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Zeppelin") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD1()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); break; } case 2: { mitk::TensorModel* model = new mitk::TensorModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity1(m_Controls->m_TensorWidget1->GetD1()); model->SetDiffusivity2(m_Controls->m_TensorWidget1->GetD2()); model->SetDiffusivity3(m_Controls->m_TensorWidget1->GetD3()); model->SetT2(m_Controls->m_TensorWidget1->GetT2()); model->m_CompartmentId = 1; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Tensor"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Tensor") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD1()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D3", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD3()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); break; } case 3: { mitk::RawShModel* model = new mitk::RawShModel(); parameters.m_SignalGen.m_DoSimulateRelaxation = false; model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetMaxNumKernels(m_Controls->m_PrototypeWidget1->GetNumberOfSamples()); model->SetFaRange(m_Controls->m_PrototypeWidget1->GetMinFa(), m_Controls->m_PrototypeWidget1->GetMaxFa()); model->SetAdcRange(m_Controls->m_PrototypeWidget1->GetMinAdc(), m_Controls->m_PrototypeWidget1->GetMaxAdc()); model->m_CompartmentId = 1; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Prototype"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Prototype") ); break; } } // compartment 2 switch (m_Controls->m_Compartment2Box->currentIndex()) { case 0: break; case 1: { mitk::StickModel* model = new mitk::StickModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_StickWidget2->GetD()); model->SetT2(m_Controls->m_StickWidget2->GetT2()); model->m_CompartmentId = 2; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Stick"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Stick") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D", DoubleProperty::New(m_Controls->m_StickWidget2->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); break; } case 2: { mitk::TensorModel* model = new mitk::TensorModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity1(m_Controls->m_ZeppelinWidget2->GetD1()); model->SetDiffusivity2(m_Controls->m_ZeppelinWidget2->GetD2()); model->SetDiffusivity3(m_Controls->m_ZeppelinWidget2->GetD2()); model->SetT2(m_Controls->m_ZeppelinWidget2->GetT2()); model->m_CompartmentId = 2; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Zeppelin"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Zeppelin") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD1()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); break; } case 3: { mitk::TensorModel* model = new mitk::TensorModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity1(m_Controls->m_TensorWidget2->GetD1()); model->SetDiffusivity2(m_Controls->m_TensorWidget2->GetD2()); model->SetDiffusivity3(m_Controls->m_TensorWidget2->GetD3()); model->SetT2(m_Controls->m_TensorWidget2->GetT2()); model->m_CompartmentId = 2; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Tensor"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Tensor") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD1()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D3", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD3()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); break; } } // compartment 3 switch (m_Controls->m_Compartment3Box->currentIndex()) { case 0: { mitk::BallModel* model = new mitk::BallModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_BallWidget1->GetD()); model->SetT2(m_Controls->m_BallWidget1->GetT2()); model->m_CompartmentId = 3; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Ball"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Ball") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_BallWidget1->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); break; } case 1: { mitk::AstroStickModel* model = new mitk::AstroStickModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_AstrosticksWidget1->GetD()); model->SetT2(m_Controls->m_AstrosticksWidget1->GetT2()); model->SetRandomizeSticks(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()); model->m_CompartmentId = 3; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Astrosticks"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Astrosticks") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget1->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()) ); break; } case 2: { mitk::DotModel* model = new mitk::DotModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetT2(m_Controls->m_DotWidget1->GetT2()); model->m_CompartmentId = 3; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Dot"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Dot") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); break; } case 3: { mitk::RawShModel* model = new mitk::RawShModel(); parameters.m_SignalGen.m_DoSimulateRelaxation = false; model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetMaxNumKernels(m_Controls->m_PrototypeWidget3->GetNumberOfSamples()); model->SetFaRange(m_Controls->m_PrototypeWidget3->GetMinFa(), m_Controls->m_PrototypeWidget3->GetMaxFa()); model->SetAdcRange(m_Controls->m_PrototypeWidget3->GetMinAdc(), m_Controls->m_PrototypeWidget3->GetMaxAdc()); model->m_CompartmentId = 3; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Prototype"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Prototype") ); break; } } // compartment 4 ItkDoubleImgType::Pointer comp4VolumeImage = NULL; ItkDoubleImgType::Pointer comp3VolumeImage = NULL; if (m_Controls->m_Compartment4Box->currentIndex()>0) { mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp4VolumeFraction->GetSelectedNode(); if (volumeNode.IsNull()) { QMessageBox::information( NULL, "Information", "No volume fraction image selected! Second extra-axonal compartment has been disabled for this simultation."); MITK_WARN << "No volume fraction image selected! Second extra-axonal compartment has been disabled."; } else { MITK_INFO << "Rescaling volume fraction image..."; comp4VolumeImage = ItkDoubleImgType::New(); mitk::Image* img = dynamic_cast(volumeNode->GetData()); CastToItkImage< ItkDoubleImgType >(img, comp4VolumeImage); double max = itk::NumericTraits::min(); double min = itk::NumericTraits::max(); itk::ImageRegionIterator< ItkDoubleImgType > it(comp4VolumeImage, comp4VolumeImage->GetLargestPossibleRegion()); while(!it.IsAtEnd()) { if (parameters.m_SignalGen.m_MaskImage.IsNotNull() && parameters.m_SignalGen.m_MaskImage->GetPixel(it.GetIndex())<=0) { it.Set(0.0); ++it; continue; } if (it.Get()>900) it.Set(900); if (it.Get()>max) max = it.Get(); if (it.Get()::Pointer scaler = itk::ShiftScaleImageFilter< ItkDoubleImgType, ItkDoubleImgType >::New(); scaler->SetInput(comp4VolumeImage); scaler->SetShift(-min); scaler->SetScale(1.0/(max-min)); scaler->Update(); comp4VolumeImage = scaler->GetOutput(); // itk::ImageFileWriter< ItkDoubleImgType >::Pointer wr = itk::ImageFileWriter< ItkDoubleImgType >::New(); // wr->SetInput(comp4VolumeImage); // wr->SetFileName("/local/comp4.nrrd"); // wr->Update(); // if (max>1 || min<0) // are volume fractions between 0 and 1? // { // itk::RescaleIntensityImageFilter::Pointer rescaler = itk::RescaleIntensityImageFilter::New(); // rescaler->SetInput(0, comp4VolumeImage); // rescaler->SetOutputMaximum(1); // rescaler->SetOutputMinimum(0); // rescaler->Update(); // comp4VolumeImage = rescaler->GetOutput(); // } itk::InvertIntensityImageFilter< ItkDoubleImgType, ItkDoubleImgType >::Pointer inverter = itk::InvertIntensityImageFilter< ItkDoubleImgType, ItkDoubleImgType >::New(); inverter->SetMaximum(1.0); inverter->SetInput(comp4VolumeImage); inverter->Update(); comp3VolumeImage = inverter->GetOutput(); } } if (comp4VolumeImage.IsNotNull()) { switch (m_Controls->m_Compartment4Box->currentIndex()) { case 0: break; case 1: { mitk::BallModel* model = new mitk::BallModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_BallWidget2->GetD()); model->SetT2(m_Controls->m_BallWidget2->GetT2()); model->SetVolumeFractionImage(comp4VolumeImage); model->m_CompartmentId = 4; parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp3VolumeImage); parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Ball"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Ball") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_BallWidget2->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); break; } case 2: { mitk::AstroStickModel* model = new mitk::AstroStickModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_AstrosticksWidget2->GetD()); model->SetT2(m_Controls->m_AstrosticksWidget2->GetT2()); model->SetRandomizeSticks(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()); parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp3VolumeImage); model->SetVolumeFractionImage(comp4VolumeImage); model->m_CompartmentId = 4; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Astrosticks"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Astrosticks") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget2->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()) ); break; } case 3: { mitk::DotModel* model = new mitk::DotModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetT2(m_Controls->m_DotWidget2->GetT2()); model->SetVolumeFractionImage(comp4VolumeImage); model->m_CompartmentId = 4; parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp3VolumeImage); parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Dot"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Dot") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); break; } case 4: { mitk::RawShModel* model = new mitk::RawShModel(); parameters.m_SignalGen.m_DoSimulateRelaxation = false; model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetMaxNumKernels(m_Controls->m_PrototypeWidget4->GetNumberOfSamples()); model->SetFaRange(m_Controls->m_PrototypeWidget4->GetMinFa(), m_Controls->m_PrototypeWidget4->GetMaxFa()); model->SetAdcRange(m_Controls->m_PrototypeWidget4->GetMinAdc(), m_Controls->m_PrototypeWidget4->GetMaxAdc()); model->SetVolumeFractionImage(comp4VolumeImage); model->m_CompartmentId = 4; parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp3VolumeImage); parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Prototype"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Prototype") ); break; } } } } parameters.m_SignalGen.m_FiberSeparationThreshold = m_Controls->m_SeparationAngleBox->value(); switch (m_Controls->m_DiffusionDirectionBox->currentIndex()) { case 0: parameters.m_SignalGen.m_DiffusionDirectionMode = SignalGenerationParameters::FIBER_TANGENT_DIRECTIONS; break; case 1: parameters.m_SignalGen.m_DiffusionDirectionMode = SignalGenerationParameters::MAIN_FIBER_DIRECTIONS; break; case 2: parameters.m_SignalGen.m_DiffusionDirectionMode = SignalGenerationParameters::RANDOM_DIRECTIONS; parameters.m_SignalGen.m_DoAddMotion = false; parameters.m_SignalGen.m_DoAddGibbsRinging = false; parameters.m_SignalGen.m_KspaceLineOffset = 0.0; parameters.m_SignalGen.m_FrequencyMap = NULL; parameters.m_SignalGen.m_CroppingFactor = 1.0; parameters.m_SignalGen.m_EddyStrength = 0; break; default: parameters.m_SignalGen.m_DiffusionDirectionMode = SignalGenerationParameters::FIBER_TANGENT_DIRECTIONS; } parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.SignalScale", IntProperty::New(parameters.m_SignalGen.m_SignalScale)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.FiberRadius", IntProperty::New(parameters.m_SignalGen.m_AxonRadius)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Tinhom", DoubleProperty::New(parameters.m_SignalGen.m_tInhom)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Tline", DoubleProperty::New(parameters.m_SignalGen.m_tLine)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.TE", DoubleProperty::New(parameters.m_SignalGen.m_tEcho)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.b-value", DoubleProperty::New(parameters.m_SignalGen.m_Bvalue)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.NoPartialVolume", BoolProperty::New(parameters.m_SignalGen.m_DoDisablePartialVolume)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Relaxation", BoolProperty::New(parameters.m_SignalGen.m_DoSimulateRelaxation)); parameters.m_Misc.m_ResultNode->AddProperty("binary", BoolProperty::New(false)); parameters.m_Misc.m_CheckRealTimeFibersBox = m_Controls->m_RealTimeFibers->isChecked(); parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); parameters.m_Misc.m_CheckIncludeFiducialsBox = m_Controls->m_IncludeFiducials->isChecked(); parameters.m_Misc.m_CheckConstantRadiusBox = m_Controls->m_ConstantRadiusBox->isChecked(); switch(m_Controls->m_DistributionBox->currentIndex()) { case 0: parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; break; case 1: parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN; break; default: parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; } parameters.m_FiberGen.m_Variance = m_Controls->m_VarianceBox->value(); parameters.m_FiberGen.m_Density = m_Controls->m_FiberDensityBox->value(); parameters.m_FiberGen.m_Sampling = m_Controls->m_FiberSamplingBox->value(); parameters.m_FiberGen.m_Tension = m_Controls->m_TensionBox->value(); parameters.m_FiberGen.m_Continuity = m_Controls->m_ContinuityBox->value(); parameters.m_FiberGen.m_Bias = m_Controls->m_BiasBox->value(); parameters.m_FiberGen.m_Rotation[0] = m_Controls->m_XrotBox->value(); parameters.m_FiberGen.m_Rotation[1] = m_Controls->m_YrotBox->value(); parameters.m_FiberGen.m_Rotation[2] = m_Controls->m_ZrotBox->value(); parameters.m_FiberGen.m_Translation[0] = m_Controls->m_XtransBox->value(); parameters.m_FiberGen.m_Translation[1] = m_Controls->m_YtransBox->value(); parameters.m_FiberGen.m_Translation[2] = m_Controls->m_ZtransBox->value(); parameters.m_FiberGen.m_Scale[0] = m_Controls->m_XscaleBox->value(); parameters.m_FiberGen.m_Scale[1] = m_Controls->m_YscaleBox->value(); parameters.m_FiberGen.m_Scale[2] = m_Controls->m_ZscaleBox->value(); return parameters; } void QmitkFiberfoxView::SaveParameters() { FiberfoxParameters<> ffParamaters = UpdateImageParameters(); QString filename = QFileDialog::getSaveFileName( 0, tr("Save Parameters"), m_ParameterFile, tr("Fiberfox Parameters (*.ffp)") ); bool ok = true; bool first = true; bool dosampling = false; mitk::Image::Pointer diffImg = NULL; itk::Image< itk::DiffusionTensor3D< double >, 3 >::Pointer tensorImage = NULL; const int shOrder = 2; typedef itk::AnalyticalDiffusionQballReconstructionImageFilter QballFilterType; QballFilterType::CoefficientImageType::Pointer itkFeatureImage = NULL; ItkDoubleImgType::Pointer adcImage = NULL; for (unsigned int i=0; i* model = NULL; if (i* >(ffParamaters.m_FiberModelList.at(i)); else model = dynamic_cast< mitk::RawShModel<>* >(ffParamaters.m_NonFiberModelList.at(i-ffParamaters.m_FiberModelList.size())); if (model!=0 && model->GetNumberOfKernels()<=0) { if (first==true) { if (QMessageBox::question(NULL, "Prototype signal sampling", "Do you want to sample prototype signals from the selected diffusion-weighted imag and save them?",QMessageBox::Yes,QMessageBox::No)==QMessageBox::Yes) dosampling = true; first = false; if (dosampling && (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNull() || !mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData())))) { QMessageBox::information(NULL, "Parameter file not saved", "No diffusion-weighted image selected to sample signal from."); return; } else if (dosampling) { diffImg = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(diffImg, itkVectorImagePointer); filter->SetGradientImage( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), itkVectorImagePointer ); filter->SetBValue( static_cast(diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); filter->Update(); tensorImage = filter->GetOutput(); const int NumCoeffs = (shOrder*shOrder + shOrder + 2)/2 + shOrder; QballFilterType::Pointer qballfilter = QballFilterType::New(); qballfilter->SetGradientImage( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), itkVectorImagePointer ); qballfilter->SetBValue( static_cast(diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); qballfilter->SetLambda(0.006); qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL); qballfilter->Update(); itkFeatureImage = qballfilter->GetCoefficientImage(); itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New(); adcFilter->SetInput( itkVectorImagePointer ); adcFilter->SetGradientDirections( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); adcFilter->SetB_value( static_cast(diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); adcFilter->Update(); adcImage = adcFilter->GetOutput(); } } if (dosampling && diffImg.IsNotNull()) { ok = model->SampleKernels(diffImg, ffParamaters.m_SignalGen.m_MaskImage, tensorImage, itkFeatureImage, adcImage); if (!ok) { QMessageBox::information( NULL, "Parameter file not saved", "No valid prototype signals could be sampled."); return; } } } } ffParamaters.SaveParameters(filename.toStdString()); m_ParameterFile = filename; } void QmitkFiberfoxView::LoadParameters() { QString filename = QFileDialog::getOpenFileName(0, tr("Load Parameters"), QString(itksys::SystemTools::GetFilenamePath(m_ParameterFile.toStdString()).c_str()), tr("Fiberfox Parameters (*.ffp)") ); if(filename.isEmpty() || filename.isNull()) return; m_ParameterFile = filename; FiberfoxParameters<> parameters; parameters.LoadParameters(filename.toStdString()); m_Controls->m_RealTimeFibers->setChecked(parameters.m_Misc.m_CheckRealTimeFibersBox); m_Controls->m_AdvancedOptionsBox->setChecked(parameters.m_Misc.m_CheckAdvancedFiberOptionsBox); m_Controls->m_IncludeFiducials->setChecked(parameters.m_Misc.m_CheckIncludeFiducialsBox); m_Controls->m_ConstantRadiusBox->setChecked(parameters.m_Misc.m_CheckConstantRadiusBox); m_Controls->m_DistributionBox->setCurrentIndex(parameters.m_FiberGen.m_Distribution); m_Controls->m_VarianceBox->setValue(parameters.m_FiberGen.m_Variance); m_Controls->m_FiberDensityBox->setValue(parameters.m_FiberGen.m_Density); m_Controls->m_FiberSamplingBox->setValue(parameters.m_FiberGen.m_Sampling); m_Controls->m_TensionBox->setValue(parameters.m_FiberGen.m_Tension); m_Controls->m_ContinuityBox->setValue(parameters.m_FiberGen.m_Continuity); m_Controls->m_BiasBox->setValue(parameters.m_FiberGen.m_Bias); m_Controls->m_XrotBox->setValue(parameters.m_FiberGen.m_Rotation[0]); m_Controls->m_YrotBox->setValue(parameters.m_FiberGen.m_Rotation[1]); m_Controls->m_ZrotBox->setValue(parameters.m_FiberGen.m_Rotation[2]); m_Controls->m_XtransBox->setValue(parameters.m_FiberGen.m_Translation[0]); m_Controls->m_YtransBox->setValue(parameters.m_FiberGen.m_Translation[1]); m_Controls->m_ZtransBox->setValue(parameters.m_FiberGen.m_Translation[2]); m_Controls->m_XscaleBox->setValue(parameters.m_FiberGen.m_Scale[0]); m_Controls->m_YscaleBox->setValue(parameters.m_FiberGen.m_Scale[1]); m_Controls->m_ZscaleBox->setValue(parameters.m_FiberGen.m_Scale[2]); // image generation parameters m_Controls->m_SizeX->setValue(parameters.m_SignalGen.m_ImageRegion.GetSize(0)); m_Controls->m_SizeY->setValue(parameters.m_SignalGen.m_ImageRegion.GetSize(1)); m_Controls->m_SizeZ->setValue(parameters.m_SignalGen.m_ImageRegion.GetSize(2)); m_Controls->m_SpacingX->setValue(parameters.m_SignalGen.m_ImageSpacing[0]); m_Controls->m_SpacingY->setValue(parameters.m_SignalGen.m_ImageSpacing[1]); m_Controls->m_SpacingZ->setValue(parameters.m_SignalGen.m_ImageSpacing[2]); m_Controls->m_NumGradientsBox->setValue(parameters.m_SignalGen.GetNumWeightedVolumes()); m_Controls->m_BvalueBox->setValue(parameters.m_SignalGen.m_Bvalue); m_Controls->m_SignalScaleBox->setValue(parameters.m_SignalGen.m_SignalScale); m_Controls->m_TEbox->setValue(parameters.m_SignalGen.m_tEcho); m_Controls->m_LineReadoutTimeBox->setValue(parameters.m_SignalGen.m_tLine); m_Controls->m_T2starBox->setValue(parameters.m_SignalGen.m_tInhom); m_Controls->m_FiberRadius->setValue(parameters.m_SignalGen.m_AxonRadius); m_Controls->m_RelaxationBox->setChecked(parameters.m_SignalGen.m_DoSimulateRelaxation); m_Controls->m_EnforcePureFiberVoxelsBox->setChecked(parameters.m_SignalGen.m_DoDisablePartialVolume); if (parameters.m_NoiseModel!=NULL) { m_Controls->m_AddNoise->setChecked(parameters.m_Misc.m_CheckAddNoiseBox); if (dynamic_cast*>(parameters.m_NoiseModel)) m_Controls->m_NoiseDistributionBox->setCurrentIndex(0); else if (dynamic_cast*>(parameters.m_NoiseModel)) m_Controls->m_NoiseDistributionBox->setCurrentIndex(1); m_Controls->m_NoiseLevel->setValue(parameters.m_NoiseModel->GetNoiseVariance()); } else m_Controls->m_AddNoise->setChecked(false); m_Controls->m_VolumeFractionsBox->setChecked(parameters.m_Misc.m_CheckOutputVolumeFractionsBox); m_Controls->m_AdvancedOptionsBox_2->setChecked(parameters.m_Misc.m_CheckAdvancedSignalOptionsBox); m_Controls->m_AddGhosts->setChecked(parameters.m_Misc.m_CheckAddGhostsBox); m_Controls->m_AddAliasing->setChecked(parameters.m_Misc.m_CheckAddAliasingBox); m_Controls->m_AddDistortions->setChecked(parameters.m_Misc.m_CheckAddDistortionsBox); m_Controls->m_AddSpikes->setChecked(parameters.m_Misc.m_CheckAddSpikesBox); m_Controls->m_AddEddy->setChecked(parameters.m_Misc.m_CheckAddEddyCurrentsBox); m_Controls->m_kOffsetBox->setValue(parameters.m_SignalGen.m_KspaceLineOffset); m_Controls->m_WrapBox->setValue(100*(1-parameters.m_SignalGen.m_CroppingFactor)); m_Controls->m_SpikeNumBox->setValue(parameters.m_SignalGen.m_Spikes); m_Controls->m_SpikeScaleBox->setValue(parameters.m_SignalGen.m_SpikeAmplitude); m_Controls->m_EddyGradientStrength->setValue(parameters.m_SignalGen.m_EddyStrength); m_Controls->m_AddGibbsRinging->setChecked(parameters.m_SignalGen.m_DoAddGibbsRinging); m_Controls->m_AddMotion->setChecked(parameters.m_SignalGen.m_DoAddMotion); m_Controls->m_RandomMotion->setChecked(parameters.m_SignalGen.m_DoRandomizeMotion); m_Controls->m_MaxTranslationBoxX->setValue(parameters.m_SignalGen.m_Translation[0]); m_Controls->m_MaxTranslationBoxY->setValue(parameters.m_SignalGen.m_Translation[1]); m_Controls->m_MaxTranslationBoxZ->setValue(parameters.m_SignalGen.m_Translation[2]); m_Controls->m_MaxRotationBoxX->setValue(parameters.m_SignalGen.m_Rotation[0]); m_Controls->m_MaxRotationBoxY->setValue(parameters.m_SignalGen.m_Rotation[1]); m_Controls->m_MaxRotationBoxZ->setValue(parameters.m_SignalGen.m_Rotation[2]); m_Controls->m_DiffusionDirectionBox->setCurrentIndex(parameters.m_SignalGen.m_DiffusionDirectionMode); m_Controls->m_SeparationAngleBox->setValue(parameters.m_SignalGen.m_FiberSeparationThreshold); m_Controls->m_Compartment1Box->setCurrentIndex(0); m_Controls->m_Compartment2Box->setCurrentIndex(0); m_Controls->m_Compartment3Box->setCurrentIndex(0); m_Controls->m_Compartment4Box->setCurrentIndex(0); for (unsigned int i=0; i* signalModel = NULL; if (im_CompartmentId) { case 1: { if (dynamic_cast*>(signalModel)) { mitk::StickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_StickWidget1->SetT2(model->GetT2()); m_Controls->m_StickWidget1->SetD(model->GetDiffusivity()); m_Controls->m_Compartment1Box->setCurrentIndex(0); break; } else if (dynamic_cast*>(signalModel)) { mitk::TensorModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_TensorWidget1->SetT2(model->GetT2()); m_Controls->m_TensorWidget1->SetD1(model->GetDiffusivity1()); m_Controls->m_TensorWidget1->SetD2(model->GetDiffusivity2()); m_Controls->m_TensorWidget1->SetD3(model->GetDiffusivity3()); m_Controls->m_Compartment1Box->setCurrentIndex(2); break; } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_PrototypeWidget1->SetNumberOfSamples(model->GetMaxNumKernels()); m_Controls->m_PrototypeWidget1->SetMinFa(model->GetFaRange().first); m_Controls->m_PrototypeWidget1->SetMaxFa(model->GetFaRange().second); m_Controls->m_PrototypeWidget1->SetMinAdc(model->GetAdcRange().first); m_Controls->m_PrototypeWidget1->SetMaxAdc(model->GetAdcRange().second); m_Controls->m_Compartment1Box->setCurrentIndex(3); break; } break; } case 2: { if (dynamic_cast*>(signalModel)) { mitk::StickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_StickWidget2->SetT2(model->GetT2()); m_Controls->m_StickWidget2->SetD(model->GetDiffusivity()); m_Controls->m_Compartment2Box->setCurrentIndex(1); break; } else if (dynamic_cast*>(signalModel)) { mitk::TensorModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_TensorWidget2->SetT2(model->GetT2()); m_Controls->m_TensorWidget2->SetD1(model->GetDiffusivity1()); m_Controls->m_TensorWidget2->SetD2(model->GetDiffusivity2()); m_Controls->m_TensorWidget2->SetD3(model->GetDiffusivity3()); m_Controls->m_Compartment2Box->setCurrentIndex(3); break; } break; } case 3: { if (dynamic_cast*>(signalModel)) { mitk::BallModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_BallWidget1->SetT2(model->GetT2()); m_Controls->m_BallWidget1->SetD(model->GetDiffusivity()); m_Controls->m_Compartment3Box->setCurrentIndex(0); break; } else if (dynamic_cast*>(signalModel)) { mitk::AstroStickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_AstrosticksWidget1->SetT2(model->GetT2()); m_Controls->m_AstrosticksWidget1->SetD(model->GetDiffusivity()); m_Controls->m_AstrosticksWidget1->SetRandomizeSticks(model->GetRandomizeSticks()); m_Controls->m_Compartment3Box->setCurrentIndex(1); break; } else if (dynamic_cast*>(signalModel)) { mitk::DotModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_DotWidget1->SetT2(model->GetT2()); m_Controls->m_Compartment3Box->setCurrentIndex(2); break; } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_PrototypeWidget3->SetNumberOfSamples(model->GetMaxNumKernels()); m_Controls->m_PrototypeWidget3->SetMinFa(model->GetFaRange().first); m_Controls->m_PrototypeWidget3->SetMaxFa(model->GetFaRange().second); m_Controls->m_PrototypeWidget3->SetMinAdc(model->GetAdcRange().first); m_Controls->m_PrototypeWidget3->SetMaxAdc(model->GetAdcRange().second); m_Controls->m_Compartment3Box->setCurrentIndex(3); break; } break; } case 4: { if (dynamic_cast*>(signalModel)) { mitk::BallModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_BallWidget2->SetT2(model->GetT2()); m_Controls->m_BallWidget2->SetD(model->GetDiffusivity()); m_Controls->m_Compartment4Box->setCurrentIndex(1); break; } else if (dynamic_cast*>(signalModel)) { mitk::AstroStickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_AstrosticksWidget2->SetT2(model->GetT2()); m_Controls->m_AstrosticksWidget2->SetD(model->GetDiffusivity()); m_Controls->m_AstrosticksWidget2->SetRandomizeSticks(model->GetRandomizeSticks()); m_Controls->m_Compartment4Box->setCurrentIndex(2); break; } else if (dynamic_cast*>(signalModel)) { mitk::DotModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_DotWidget2->SetT2(model->GetT2()); m_Controls->m_Compartment4Box->setCurrentIndex(3); break; } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_PrototypeWidget4->SetNumberOfSamples(model->GetMaxNumKernels()); m_Controls->m_PrototypeWidget4->SetMinFa(model->GetFaRange().first); m_Controls->m_PrototypeWidget4->SetMaxFa(model->GetFaRange().second); m_Controls->m_PrototypeWidget4->SetMinAdc(model->GetAdcRange().first); m_Controls->m_PrototypeWidget4->SetMaxAdc(model->GetAdcRange().second); m_Controls->m_Compartment4Box->setCurrentIndex(4); break; } break; } } } } void QmitkFiberfoxView::ShowAdvancedOptions(int state) { if (state) { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(true); m_Controls->m_AdvancedSignalOptionsFrame->setVisible(true); m_Controls->m_AdvancedOptionsBox->setChecked(true); m_Controls->m_AdvancedOptionsBox_2->setChecked(true); } else { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false); m_Controls->m_AdvancedSignalOptionsFrame->setVisible(false); m_Controls->m_AdvancedOptionsBox->setChecked(false); m_Controls->m_AdvancedOptionsBox_2->setChecked(false); } } void QmitkFiberfoxView::Comp1ModelFrameVisibility(int index) { m_Controls->m_StickWidget1->setVisible(false); m_Controls->m_ZeppelinWidget1->setVisible(false); m_Controls->m_TensorWidget1->setVisible(false); m_Controls->m_PrototypeWidget1->setVisible(false); switch (index) { case 0: m_Controls->m_StickWidget1->setVisible(true); break; case 1: m_Controls->m_ZeppelinWidget1->setVisible(true); break; case 2: m_Controls->m_TensorWidget1->setVisible(true); break; case 3: m_Controls->m_PrototypeWidget1->setVisible(true); break; } } void QmitkFiberfoxView::Comp2ModelFrameVisibility(int index) { m_Controls->m_StickWidget2->setVisible(false); m_Controls->m_ZeppelinWidget2->setVisible(false); m_Controls->m_TensorWidget2->setVisible(false); switch (index) { case 0: break; case 1: m_Controls->m_StickWidget2->setVisible(true); break; case 2: m_Controls->m_ZeppelinWidget2->setVisible(true); break; case 3: m_Controls->m_TensorWidget2->setVisible(true); break; } } void QmitkFiberfoxView::Comp3ModelFrameVisibility(int index) { m_Controls->m_BallWidget1->setVisible(false); m_Controls->m_AstrosticksWidget1->setVisible(false); m_Controls->m_DotWidget1->setVisible(false); m_Controls->m_PrototypeWidget3->setVisible(false); switch (index) { case 0: m_Controls->m_BallWidget1->setVisible(true); break; case 1: m_Controls->m_AstrosticksWidget1->setVisible(true); break; case 2: m_Controls->m_DotWidget1->setVisible(true); break; case 3: m_Controls->m_PrototypeWidget3->setVisible(true); break; } } void QmitkFiberfoxView::Comp4ModelFrameVisibility(int index) { m_Controls->m_BallWidget2->setVisible(false); m_Controls->m_AstrosticksWidget2->setVisible(false); m_Controls->m_DotWidget2->setVisible(false); m_Controls->m_PrototypeWidget4->setVisible(false); m_Controls->m_Comp4FractionFrame->setVisible(false); switch (index) { case 0: break; case 1: m_Controls->m_BallWidget2->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; case 2: m_Controls->m_AstrosticksWidget2->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; case 3: m_Controls->m_DotWidget2->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; case 4: m_Controls->m_PrototypeWidget4->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; } } void QmitkFiberfoxView::OnConstantRadius(int value) { if (value>0 && m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnAddMotion(int value) { if (value>0) m_Controls->m_MotionArtifactFrame->setVisible(true); else m_Controls->m_MotionArtifactFrame->setVisible(false); } void QmitkFiberfoxView::OnAddAliasing(int value) { if (value>0) m_Controls->m_AliasingFrame->setVisible(true); else m_Controls->m_AliasingFrame->setVisible(false); } void QmitkFiberfoxView::OnAddSpikes(int value) { if (value>0) m_Controls->m_SpikeFrame->setVisible(true); else m_Controls->m_SpikeFrame->setVisible(false); } void QmitkFiberfoxView::OnAddEddy(int value) { if (value>0) m_Controls->m_EddyFrame->setVisible(true); else m_Controls->m_EddyFrame->setVisible(false); } void QmitkFiberfoxView::OnAddDistortions(int value) { if (value>0) m_Controls->m_DistortionsFrame->setVisible(true); else m_Controls->m_DistortionsFrame->setVisible(false); } void QmitkFiberfoxView::OnAddGhosts(int value) { if (value>0) m_Controls->m_GhostFrame->setVisible(true); else m_Controls->m_GhostFrame->setVisible(false); } void QmitkFiberfoxView::OnAddNoise(int value) { if (value>0) m_Controls->m_NoiseFrame->setVisible(true); else m_Controls->m_NoiseFrame->setVisible(false); } void QmitkFiberfoxView::OnDistributionChanged(int value) { if (value==1) m_Controls->m_VarianceBox->setVisible(true); else m_Controls->m_VarianceBox->setVisible(false); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnVarianceChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFiberDensityChanged(int) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFiberSamplingChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnTensionChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnContinuityChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnBiasChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::AlignOnGrid() { for (unsigned int i=0; i(m_SelectedFiducials.at(i)->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::DataStorage::SetOfObjects::ConstPointer parentFibs = GetDataStorage()->GetSources(m_SelectedFiducials.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = parentFibs->begin(); it != parentFibs->end(); ++it ) { mitk::DataNode::Pointer pFibNode = *it; - if ( pFibNode.IsNotNull() && dynamic_cast(pFibNode->GetData()) ) + if ( pFibNode.IsNotNull() && dynamic_cast(pFibNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(pFibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 ) { mitk::DataNode::Pointer pImgNode = *it2; if ( pImgNode.IsNotNull() && dynamic_cast(pImgNode->GetData()) ) { mitk::Image::Pointer img = dynamic_cast(pImgNode->GetData()); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); break; } } break; } } } for(unsigned int i=0; iGetSources(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it = sources->begin(); it != sources->end(); ++it ) { mitk::DataNode::Pointer imgNode = *it; if ( imgNode.IsNotNull() && dynamic_cast(imgNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::Image::Pointer img = dynamic_cast(imgNode->GetData()); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); } } break; } } } for(unsigned int i=0; i(m_SelectedImages.at(i)->GetData()); mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(m_SelectedImages.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it ) { mitk::DataNode::Pointer fibNode = *it; - if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) + if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer derivations2 = GetDataStorage()->GetDerivations(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations2->begin(); it2 != derivations2->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); } } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFlipButton() { if (m_SelectedFiducial.IsNull()) return; std::map::iterator it = m_DataNodeToPlanarFigureData.find(m_SelectedFiducial.GetPointer()); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; data.m_Flipped += 1; data.m_Flipped %= 2; } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } QmitkFiberfoxView::GradientListType QmitkFiberfoxView::GenerateHalfShell(int NPoints) { NPoints *= 2; GradientListType pointshell; int numB0 = NPoints/20; if (numB0==0) numB0=1; GradientType g; g.Fill(0.0); for (int i=0; i theta; theta.set_size(NPoints); vnl_vector phi; phi.set_size(NPoints); double C = sqrt(4*M_PI); phi(0) = 0.0; phi(NPoints-1) = 0.0; for(int i=0; i0 && i std::vector > QmitkFiberfoxView::MakeGradientList() { std::vector > retval; vnl_matrix_fixed* U = itk::PointShell >::DistributePointShell(); // Add 0 vector for B0 int numB0 = ndirs/10; if (numB0==0) numB0=1; itk::Vector v; v.Fill(0.0); 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); } return retval; } void QmitkFiberfoxView::OnAddBundle() { if (m_SelectedImage.IsNull()) return; mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedImage); - mitk::FiberBundleX::Pointer bundle = mitk::FiberBundleX::New(); + mitk::FiberBundle::Pointer bundle = mitk::FiberBundle::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( bundle ); QString name = QString("Bundle_%1").arg(children->size()); node->SetName(name.toStdString()); m_SelectedBundles.push_back(node); UpdateGui(); GetDataStorage()->Add(node, m_SelectedImage); } void QmitkFiberfoxView::OnDrawROI() { if (m_SelectedBundles.empty()) OnAddBundle(); if (m_SelectedBundles.empty()) return; mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedBundles.at(0)); mitk::PlanarEllipse::Pointer figure = mitk::PlanarEllipse::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( figure ); node->SetBoolProperty("planarfigure.3drendering", true); QList nodes = this->GetDataManagerSelection(); for( int i=0; iSetSelected(false); m_SelectedFiducial = node; QString name = QString("Fiducial_%1").arg(children->size()); node->SetName(name.toStdString()); node->SetSelected(true); this->DisableCrosshairNavigation(); mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetDataInteractor().GetPointer()); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( node ); } UpdateGui(); GetDataStorage()->Add(node, m_SelectedBundles.at(0)); } bool CompareLayer(mitk::DataNode::Pointer i,mitk::DataNode::Pointer j) { int li = -1; i->GetPropertyValue("layer", li); int lj = -1; j->GetPropertyValue("layer", lj); return liGetSources(m_SelectedFiducial); for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it ) - if(dynamic_cast((*it)->GetData())) + if(dynamic_cast((*it)->GetData())) m_SelectedBundles.push_back(*it); if (m_SelectedBundles.empty()) return; } FiberfoxParameters parameters = UpdateImageParameters(); for (unsigned int i=0; iGetDerivations(m_SelectedBundles.at(i)); std::vector< mitk::DataNode::Pointer > childVector; for( mitk::DataStorage::SetOfObjects::const_iterator it = children->begin(); it != children->end(); ++it ) childVector.push_back(*it); sort(childVector.begin(), childVector.end(), CompareLayer); vector< mitk::PlanarEllipse::Pointer > fib; vector< unsigned int > flip; float radius = 1; int count = 0; for( std::vector< mitk::DataNode::Pointer >::const_iterator it = childVector.begin(); it != childVector.end(); ++it ) { mitk::DataNode::Pointer node = *it; if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { mitk::PlanarEllipse* ellipse = dynamic_cast(node->GetData()); if (m_Controls->m_ConstantRadiusBox->isChecked()) { ellipse->SetTreatAsCircle(true); mitk::Point2D c = ellipse->GetControlPoint(0); mitk::Point2D p = ellipse->GetControlPoint(1); mitk::Vector2D v = p-c; if (count==0) { radius = v.GetVnlVector().magnitude(); ellipse->SetControlPoint(1, p); ellipse->Modified(); } else { v.Normalize(); v *= radius; ellipse->SetControlPoint(1, c+v); ellipse->Modified(); } } fib.push_back(ellipse); std::map::iterator it = m_DataNodeToPlanarFigureData.find(node.GetPointer()); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; flip.push_back(data.m_Flipped); } else flip.push_back(0); } count++; } if (fib.size()>1) { parameters.m_FiberGen.m_Fiducials.push_back(fib); parameters.m_FiberGen.m_FlipList.push_back(flip); } else if (fib.size()>0) - m_SelectedBundles.at(i)->SetData( mitk::FiberBundleX::New() ); + m_SelectedBundles.at(i)->SetData( mitk::FiberBundle::New() ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New(); filter->SetParameters(parameters.m_FiberGen); filter->Update(); - vector< mitk::FiberBundleX::Pointer > fiberBundles = filter->GetFiberBundles(); + vector< mitk::FiberBundle::Pointer > fiberBundles = filter->GetFiberBundles(); for (unsigned int i=0; iSetData( fiberBundles.at(i) ); if (fiberBundles.at(i)->GetNumFibers()>50000) m_SelectedBundles.at(i)->SetVisibility(false); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::GenerateImage() { if (m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNull() && m_Controls->m_TemplateComboBox->GetSelectedNode().IsNull()) { mitk::Image::Pointer image = mitk::ImageGenerator::GenerateGradientImage( m_Controls->m_SizeX->value(), m_Controls->m_SizeY->value(), m_Controls->m_SizeZ->value(), m_Controls->m_SpacingX->value(), m_Controls->m_SpacingY->value(), m_Controls->m_SpacingZ->value()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("Dummy"); unsigned int window = m_Controls->m_SizeX->value()*m_Controls->m_SizeY->value()*m_Controls->m_SizeZ->value(); unsigned int level = window/2; mitk::LevelWindow lw; lw.SetLevelWindow(level, window); node->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) ); GetDataStorage()->Add(node); m_SelectedImage = node; mitk::BaseData::Pointer basedata = node->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } UpdateGui(); } else if (m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNotNull()) SimulateImageFromFibers(m_Controls->m_FiberBundleComboBox->GetSelectedNode()); else if ( m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull() ) SimulateForExistingDwi(m_Controls->m_TemplateComboBox->GetSelectedNode()); } void QmitkFiberfoxView::SimulateForExistingDwi(mitk::DataNode* imageNode) { bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(imageNode->GetData())) ); if ( !isDiffusionImage ) { return; } FiberfoxParameters parameters = UpdateImageParameters(); if (parameters.m_NoiseModel==NULL && parameters.m_SignalGen.m_Spikes==0 && parameters.m_SignalGen.m_FrequencyMap.IsNull() && parameters.m_SignalGen.m_KspaceLineOffset<=0.000001 && !parameters.m_SignalGen.m_DoAddGibbsRinging && !(parameters.m_SignalGen.m_EddyStrength>0) && parameters.m_SignalGen.m_CroppingFactor>0.999) { QMessageBox::information( NULL, "Simulation cancelled", "No valid artifact enabled! Motion artifacts and relaxation effects can NOT be added to an existing diffusion weighted image."); return; } mitk::Image::Pointer diffImg = dynamic_cast(imageNode->GetData()); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(diffImg, itkVectorImagePointer); m_ArtifactsToDwiFilter = itk::AddArtifactsToDwiImageFilter< short >::New(); m_ArtifactsToDwiFilter->SetInput(itkVectorImagePointer); parameters.m_Misc.m_ParentNode = imageNode; m_ArtifactsToDwiFilter->SetParameters(parameters); m_Worker.m_FilterType = 1; m_Thread.start(QThread::LowestPriority); } void QmitkFiberfoxView::SimulateImageFromFibers(mitk::DataNode* fiberNode) { - mitk::FiberBundleX::Pointer fiberBundle = dynamic_cast(fiberNode->GetData()); + mitk::FiberBundle::Pointer fiberBundle = dynamic_cast(fiberNode->GetData()); if (fiberBundle->GetNumFibers()<=0) return; FiberfoxParameters parameters = UpdateImageParameters(); m_TractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); parameters.m_Misc.m_ParentNode = fiberNode; if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull() && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()))) { bool first = true; bool ok = true; mitk::Image::Pointer diffImg = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); itk::Image< itk::DiffusionTensor3D< double >, 3 >::Pointer tensorImage = NULL; const int shOrder = 2; typedef itk::AnalyticalDiffusionQballReconstructionImageFilter QballFilterType; QballFilterType::CoefficientImageType::Pointer itkFeatureImage = NULL; ItkDoubleImgType::Pointer adcImage = NULL; for (unsigned int i=0; i* model = NULL; if (i* >(parameters.m_FiberModelList.at(i)); else model = dynamic_cast< mitk::RawShModel<>* >(parameters.m_NonFiberModelList.at(i-parameters.m_FiberModelList.size())); if (model!=0 && model->GetNumberOfKernels()<=0) { if (first==true) { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(diffImg, itkVectorImagePointer); typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); filter->SetGradientImage( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), itkVectorImagePointer ); filter->SetBValue( static_cast(diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); filter->Update(); tensorImage = filter->GetOutput(); const int NumCoeffs = (shOrder*shOrder + shOrder + 2)/2 + shOrder; QballFilterType::Pointer qballfilter = QballFilterType::New(); qballfilter->SetGradientImage( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), itkVectorImagePointer ); qballfilter->SetBValue( static_cast(diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); qballfilter->SetLambda(0.006); qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL); qballfilter->Update(); itkFeatureImage = qballfilter->GetCoefficientImage(); itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New(); adcFilter->SetInput( itkVectorImagePointer ); adcFilter->SetGradientDirections( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); adcFilter->SetB_value( static_cast(diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); adcFilter->Update(); adcImage = adcFilter->GetOutput(); } ok = model->SampleKernels(diffImg, parameters.m_SignalGen.m_MaskImage, tensorImage, itkFeatureImage, adcImage); if (!ok) break; } } if (!ok) { QMessageBox::information( NULL, "Simulation cancelled", "No valid prototype signals could be sampled."); return; } } else if ( m_Controls->m_Compartment1Box->currentIndex()==3 || m_Controls->m_Compartment3Box->currentIndex()==3 || m_Controls->m_Compartment4Box->currentIndex()==4 ) { QMessageBox::information( NULL, "Simulation cancelled", "Prototype signal but no diffusion-weighted image selected to sample signal from."); return; } m_TractsToDwiFilter->SetParameters(parameters); m_TractsToDwiFilter->SetFiberBundle(fiberBundle); m_Worker.m_FilterType = 0; m_Thread.start(QThread::LowestPriority); } void QmitkFiberfoxView::ApplyTransform() { vector< mitk::DataNode::Pointer > selectedBundles; for(unsigned int i=0; iGetDerivations(m_SelectedImages.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it ) { mitk::DataNode::Pointer fibNode = *it; - if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) + if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) selectedBundles.push_back(fibNode); } } if (selectedBundles.empty()) selectedBundles = m_SelectedBundles2; if (!selectedBundles.empty()) { for (std::vector::const_iterator it = selectedBundles.begin(); it!=selectedBundles.end(); ++it) { - mitk::FiberBundleX::Pointer fib = dynamic_cast((*it)->GetData()); + mitk::FiberBundle::Pointer fib = dynamic_cast((*it)->GetData()); fib->RotateAroundAxis(m_Controls->m_XrotBox->value(), m_Controls->m_YrotBox->value(), m_Controls->m_ZrotBox->value()); fib->TranslateFibers(m_Controls->m_XtransBox->value(), m_Controls->m_YtransBox->value(), m_Controls->m_ZtransBox->value()); fib->ScaleFibers(m_Controls->m_XscaleBox->value(), m_Controls->m_YscaleBox->value(), m_Controls->m_ZscaleBox->value()); // handle child fiducials if (m_Controls->m_IncludeFiducials->isChecked()) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse* pe = dynamic_cast(fiducialNode->GetData()); mitk::BaseGeometry* geom = pe->GetGeometry(); // translate mitk::Vector3D world; world[0] = m_Controls->m_XtransBox->value(); world[1] = m_Controls->m_YtransBox->value(); world[2] = m_Controls->m_ZtransBox->value(); geom->Translate(world); // calculate rotation matrix double x = m_Controls->m_XrotBox->value()*M_PI/180; double y = m_Controls->m_YrotBox->value()*M_PI/180; double z = m_Controls->m_ZrotBox->value()*M_PI/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; // transform control point coordinate into geometry translation geom->SetOrigin(pe->GetWorldControlPoint(0)); mitk::Point2D cp; cp.Fill(0.0); pe->SetControlPoint(0, cp); // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); // implicit translation mitk::Vector3D trans; trans[0] = geom->GetOrigin()[0]-fib->GetGeometry()->GetCenter()[0]; trans[1] = geom->GetOrigin()[1]-fib->GetGeometry()->GetCenter()[1]; trans[2] = geom->GetOrigin()[2]-fib->GetGeometry()->GetCenter()[2]; mitk::Vector3D newWc = rot*trans; newWc = newWc-trans; geom->Translate(newWc); pe->Modified(); } } } } } else { for (unsigned int i=0; i(m_SelectedFiducials.at(i)->GetData()); mitk::BaseGeometry* geom = pe->GetGeometry(); // translate mitk::Vector3D world; world[0] = m_Controls->m_XtransBox->value(); world[1] = m_Controls->m_YtransBox->value(); world[2] = m_Controls->m_ZtransBox->value(); geom->Translate(world); // calculate rotation matrix double x = m_Controls->m_XrotBox->value()*M_PI/180; double y = m_Controls->m_YrotBox->value()*M_PI/180; double z = m_Controls->m_ZrotBox->value()*M_PI/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; // transform control point coordinate into geometry translation geom->SetOrigin(pe->GetWorldControlPoint(0)); mitk::Point2D cp; cp.Fill(0.0); pe->SetControlPoint(0, cp); // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); pe->Modified(); } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::CopyBundles() { if ( m_SelectedBundles.size()<1 ){ QMessageBox::information( NULL, "Warning", "Select at least one fiber bundle!"); MITK_WARN("QmitkFiberFoxView") << "Select at least one fiber bundle!"; return; } for (std::vector::const_iterator it = m_SelectedBundles.begin(); it!=m_SelectedBundles.end(); ++it) { // find parent image mitk::DataNode::Pointer parentNode; mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 ) { mitk::DataNode::Pointer pImgNode = *it2; if ( pImgNode.IsNotNull() && dynamic_cast(pImgNode->GetData()) ) { parentNode = pImgNode; break; } } - mitk::FiberBundleX::Pointer fib = dynamic_cast((*it)->GetData()); - mitk::FiberBundleX::Pointer newBundle = fib->GetDeepCopy(); + mitk::FiberBundle::Pointer fib = dynamic_cast((*it)->GetData()); + mitk::FiberBundle::Pointer newBundle = fib->GetDeepCopy(); QString name((*it)->GetName().c_str()); name += "_copy"; mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); if (parentNode.IsNotNull()) GetDataStorage()->Add(fbNode, parentNode); else GetDataStorage()->Add(fbNode); // copy child fiducials if (m_Controls->m_IncludeFiducials->isChecked()) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData())->Clone(); mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetData(pe); newNode->SetName(fiducialNode->GetName()); newNode->SetBoolProperty("planarfigure.3drendering", true); GetDataStorage()->Add(newNode, fbNode); } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::JoinBundles() { if ( m_SelectedBundles.size()<2 ){ QMessageBox::information( NULL, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberFoxView") << "Select at least two fiber bundles!"; return; } std::vector::const_iterator it = m_SelectedBundles.begin(); - mitk::FiberBundleX::Pointer newBundle = dynamic_cast((*it)->GetData()); + mitk::FiberBundle::Pointer newBundle = dynamic_cast((*it)->GetData()); QString name(""); name += QString((*it)->GetName().c_str()); ++it; for (; it!=m_SelectedBundles.end(); ++it) { - newBundle = newBundle->AddBundle(dynamic_cast((*it)->GetData())); + 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); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::UpdateGui() { m_Controls->m_GeometryFrame->setEnabled(true); m_Controls->m_GeometryMessage->setVisible(false); m_Controls->m_DiffusionPropsMessage->setVisible(false); m_Controls->m_FiberGenMessage->setVisible(true); m_Controls->m_TransformBundlesButton->setEnabled(false); m_Controls->m_CopyBundlesButton->setEnabled(false); m_Controls->m_GenerateFibersButton->setEnabled(false); m_Controls->m_FlipButton->setEnabled(false); m_Controls->m_CircleButton->setEnabled(false); m_Controls->m_BvalueBox->setEnabled(true); m_Controls->m_NumGradientsBox->setEnabled(true); m_Controls->m_JoinBundlesButton->setEnabled(false); m_Controls->m_AlignOnGrid->setEnabled(false); // Fiber generation gui if (m_SelectedFiducial.IsNotNull()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_FlipButton->setEnabled(true); m_Controls->m_AlignOnGrid->setEnabled(true); } if (m_SelectedImage.IsNotNull() || !m_SelectedBundles.empty()) { m_Controls->m_CircleButton->setEnabled(true); m_Controls->m_FiberGenMessage->setVisible(false); } if (m_SelectedImage.IsNotNull() && !m_SelectedBundles.empty()) m_Controls->m_AlignOnGrid->setEnabled(true); if (!m_SelectedBundles.empty()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_CopyBundlesButton->setEnabled(true); m_Controls->m_GenerateFibersButton->setEnabled(true); if (m_SelectedBundles.size()>1) m_Controls->m_JoinBundlesButton->setEnabled(true); } // Signal generation gui if (m_Controls->m_MaskComboBox->GetSelectedNode().IsNotNull() || m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull()) { m_Controls->m_GeometryMessage->setVisible(true); m_Controls->m_GeometryFrame->setEnabled(false); } if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull() && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()))) { m_Controls->m_DiffusionPropsMessage->setVisible(true); m_Controls->m_BvalueBox->setEnabled(false); m_Controls->m_NumGradientsBox->setEnabled(false); m_Controls->m_GeometryMessage->setVisible(true); m_Controls->m_GeometryFrame->setEnabled(false); } } void QmitkFiberfoxView::OnSelectionChanged( berry::IWorkbenchPart::Pointer, const QList& nodes ) { m_SelectedBundles2.clear(); m_SelectedImages.clear(); m_SelectedFiducials.clear(); m_SelectedFiducial = NULL; m_SelectedBundles.clear(); m_SelectedImage = NULL; // iterate all selected objects, adjust warning visibility for( int i=0; i(node->GetData())); // } // if ( node.IsNotNull() && isDiffusionImage ) // { // m_SelectedDWI = node; // m_SelectedImage = node; // m_SelectedImages.push_back(node); // } if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedImages.push_back(node); m_SelectedImage = node; } - else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) + else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedBundles2.push_back(node); if (m_Controls->m_RealTimeFibers->isChecked()) { m_SelectedBundles.push_back(node); - mitk::FiberBundleX::Pointer newFib = dynamic_cast(node->GetData()); + mitk::FiberBundle::Pointer newFib = dynamic_cast(node->GetData()); if (newFib->GetNumFibers()!=m_Controls->m_FiberDensityBox->value()) GenerateFibers(); } else m_SelectedBundles.push_back(node); } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedFiducials.push_back(node); m_SelectedFiducial = node; m_SelectedBundles.clear(); mitk::DataStorage::SetOfObjects::ConstPointer parents = GetDataStorage()->GetSources(node); for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it ) { mitk::DataNode::Pointer pNode = *it; - if ( pNode.IsNotNull() && dynamic_cast(pNode->GetData()) ) + if ( pNode.IsNotNull() && dynamic_cast(pNode->GetData()) ) m_SelectedBundles.push_back(pNode); } } } UpdateGui(); } void QmitkFiberfoxView::EnableCrosshairNavigation() { MITK_DEBUG << "EnableCrosshairNavigation"; // enable the crosshair navigation if (mitk::ILinkedRenderWindowPart* linkedRenderWindow = dynamic_cast(this->GetRenderWindowPart())) { MITK_DEBUG << "enabling linked navigation"; linkedRenderWindow->EnableLinkedNavigation(true); // linkedRenderWindow->EnableSlicingPlanes(true); } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::DisableCrosshairNavigation() { MITK_DEBUG << "DisableCrosshairNavigation"; // disable the crosshair navigation during the drawing if (mitk::ILinkedRenderWindowPart* linkedRenderWindow = dynamic_cast(this->GetRenderWindowPart())) { MITK_DEBUG << "disabling linked navigation"; linkedRenderWindow->EnableLinkedNavigation(false); // linkedRenderWindow->EnableSlicingPlanes(false); } } void QmitkFiberfoxView::NodeRemoved(const mitk::DataNode* node) { mitk::DataNode* nonConstNode = const_cast(node); std::map::iterator it = m_DataNodeToPlanarFigureData.find(nonConstNode); - if (dynamic_cast(node->GetData())) + if (dynamic_cast(node->GetData())) { m_SelectedBundles.clear(); m_SelectedBundles2.clear(); } else if (dynamic_cast(node->GetData())) m_SelectedImages.clear(); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; // remove observers data.m_Figure->RemoveObserver( data.m_EndPlacementObserverTag ); data.m_Figure->RemoveObserver( data.m_SelectObserverTag ); data.m_Figure->RemoveObserver( data.m_StartInteractionObserverTag ); data.m_Figure->RemoveObserver( data.m_EndInteractionObserverTag ); m_DataNodeToPlanarFigureData.erase( it ); } } void QmitkFiberfoxView::NodeAdded( const mitk::DataNode* node ) { // add observer for selection in renderwindow mitk::PlanarFigure* figure = dynamic_cast(node->GetData()); bool isPositionMarker (false); node->GetBoolProperty("isContourMarker", isPositionMarker); if( figure && !isPositionMarker ) { MITK_DEBUG << "figure added. will add interactor if needed."; mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetDataInteractor().GetPointer()); mitk::DataNode* nonConstNode = const_cast( node ); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( nonConstNode ); } MITK_DEBUG << "will now add observers for planarfigure"; QmitkPlanarFigureData data; data.m_Figure = figure; // // add observer for event when figure has been placed typedef itk::SimpleMemberCommand< QmitkFiberfoxView > SimpleCommandType; // SimpleCommandType::Pointer initializationCommand = SimpleCommandType::New(); // initializationCommand->SetCallbackFunction( this, &QmitkFiberfoxView::PlanarFigureInitialized ); // data.m_EndPlacementObserverTag = figure->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand ); // add observer for event when figure is picked (selected) typedef itk::MemberCommand< QmitkFiberfoxView > MemberCommandType; MemberCommandType::Pointer selectCommand = MemberCommandType::New(); selectCommand->SetCallbackFunction( this, &QmitkFiberfoxView::PlanarFigureSelected ); data.m_SelectObserverTag = figure->AddObserver( mitk::SelectPlanarFigureEvent(), selectCommand ); // add observer for event when interaction with figure starts SimpleCommandType::Pointer startInteractionCommand = SimpleCommandType::New(); startInteractionCommand->SetCallbackFunction( this, &QmitkFiberfoxView::DisableCrosshairNavigation); data.m_StartInteractionObserverTag = figure->AddObserver( mitk::StartInteractionPlanarFigureEvent(), startInteractionCommand ); // add observer for event when interaction with figure starts SimpleCommandType::Pointer endInteractionCommand = SimpleCommandType::New(); endInteractionCommand->SetCallbackFunction( this, &QmitkFiberfoxView::EnableCrosshairNavigation); data.m_EndInteractionObserverTag = figure->AddObserver( mitk::EndInteractionPlanarFigureEvent(), endInteractionCommand ); m_DataNodeToPlanarFigureData[nonConstNode] = data; } } void QmitkFiberfoxView::PlanarFigureSelected( itk::Object* object, const itk::EventObject& ) { mitk::TNodePredicateDataType::Pointer isPf = mitk::TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer allPfs = this->GetDataStorage()->GetSubset( isPf ); for ( mitk::DataStorage::SetOfObjects::const_iterator it = allPfs->begin(); it!=allPfs->end(); ++it) { mitk::DataNode* node = *it; if( node->GetData() == object ) { node->SetSelected(true); m_SelectedFiducial = node; } else node->SetSelected(false); } UpdateGui(); this->RequestRenderWindowUpdate(); } void QmitkFiberfoxView::SetFocus() { m_Controls->m_CircleButton->setFocus(); } void QmitkFiberfoxView::SetOutputPath() { // SELECT FOLDER DIALOG string outputPath = QFileDialog::getExistingDirectory(NULL, "Save images to...", QString(outputPath.c_str())).toStdString(); if (outputPath.empty()) m_Controls->m_SavePathEdit->setText("-"); else { outputPath += "/"; m_Controls->m_SavePathEdit->setText(QString(outputPath.c_str())); } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h index 0f13f5c17b..3d261cdab2 100755 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h @@ -1,218 +1,218 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include "ui_QmitkFiberfoxViewControls.h" #include #include #include #ifndef Q_MOC_RUN -#include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif #include #include #include #include /*! \brief View for fiber based diffusion software phantoms (Fiberfox). See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details. \sa QmitkFunctionality \ingroup Functionalities */ // Forward Qt class declarations using namespace std; class QmitkFiberfoxView; class QmitkFiberfoxWorker : public QObject { Q_OBJECT public: QmitkFiberfoxWorker(QmitkFiberfoxView* view); int m_FilterType; public slots: void run(); private: QmitkFiberfoxView* m_View; }; class QmitkFiberfoxView : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const string VIEW_ID; QmitkFiberfoxView(); virtual ~QmitkFiberfoxView(); virtual void CreateQtPartControl(QWidget *parent); void SetFocus(); typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType; typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType; typedef itk::Vector GradientType; typedef vector GradientListType; typedef itk::VectorImage< short, 3 > ItkDwiType; typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkUcharImgType; template vector > MakeGradientList(); protected slots: void SetOutputPath(); ///< path where image is automatically saved to after the simulation is finished void LoadParameters(); ///< load fiberfox parameters void SaveParameters(); ///< save fiberfox parameters void BeforeThread(); void AfterThread(); void KillThread(); ///< abort simulation void UpdateSimulationStatus(); ///< print simulation progress and satus messages void OnDrawROI(); ///< adds new ROI, handles interactors etc. void OnAddBundle(); ///< adds new fiber bundle to datastorage void OnFlipButton(); ///< negate one coordinate of the fiber waypoints in the selcted planar figure. needed in case of unresolvable twists void GenerateFibers(); ///< generate fibers from the selected ROIs void GenerateImage(); ///< start image simulation void JoinBundles(); ///< merges selcted fiber bundles into one void CopyBundles(); ///< add copy of the selected bundle to the datamanager void ApplyTransform(); ///< rotate and shift selected bundles void AlignOnGrid(); ///< shift selected fiducials to nearest voxel center void Comp1ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 1 void Comp2ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 2 void Comp3ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 3 void Comp4ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 4 void ShowAdvancedOptions(int state); /** update fibers if any parameter changes */ void OnFiberDensityChanged(int value); void OnFiberSamplingChanged(double value); void OnTensionChanged(double value); void OnContinuityChanged(double value); void OnBiasChanged(double value); void OnVarianceChanged(double value); void OnDistributionChanged(int value); void OnConstantRadius(int value); /** update GUI elements */ void OnAddNoise(int value); void OnAddGhosts(int value); void OnAddDistortions(int value); void OnAddEddy(int value); void OnAddSpikes(int value); void OnAddAliasing(int value); void OnAddMotion(int value); void OnMaskSelected(int value); void OnFibSelected(int value); void OnTemplateSelected(int value); protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList&); GradientListType GenerateHalfShell(int NPoints); ///< generate vectors distributed over the halfsphere Ui::QmitkFiberfoxViewControls* m_Controls; void SimulateForExistingDwi(mitk::DataNode* imageNode); ///< add artifacts to existing diffusion weighted image void SimulateImageFromFibers(mitk::DataNode* fiberNode); ///< simulate new diffusion weighted image template< class ScalarType > FiberfoxParameters< ScalarType > UpdateImageParameters(); ///< update fiberfox paramater object (template parameter defines noise model type) void UpdateGui(); ///< enable/disbale buttons etc. according to current datamanager selection void PlanarFigureSelected( itk::Object* object, const itk::EventObject& ); void EnableCrosshairNavigation(); ///< enable crosshair navigation if planar figure interaction ends void DisableCrosshairNavigation(); ///< disable crosshair navigation if planar figure interaction starts void NodeAdded( const mitk::DataNode* node ); ///< add observers void NodeRemoved(const mitk::DataNode* node); ///< remove observers /** structure to keep track of planar figures and observers */ struct QmitkPlanarFigureData { QmitkPlanarFigureData() : m_Figure(0) , m_EndPlacementObserverTag(0) , m_SelectObserverTag(0) , m_StartInteractionObserverTag(0) , m_EndInteractionObserverTag(0) , m_Flipped(0) { } mitk::PlanarFigure* m_Figure; unsigned int m_EndPlacementObserverTag; unsigned int m_SelectObserverTag; unsigned int m_StartInteractionObserverTag; unsigned int m_EndInteractionObserverTag; unsigned int m_Flipped; }; std::map m_DataNodeToPlanarFigureData; ///< map each planar figure uniquely to a QmitkPlanarFigureData mitk::DataNode::Pointer m_SelectedFiducial; ///< selected planar ellipse mitk::DataNode::Pointer m_SelectedImage; vector< mitk::DataNode::Pointer > m_SelectedBundles; vector< mitk::DataNode::Pointer > m_SelectedBundles2; vector< mitk::DataNode::Pointer > m_SelectedFiducials; vector< mitk::DataNode::Pointer > m_SelectedImages; QString m_ParameterFile; ///< parameter file name // GUI thread QmitkFiberfoxWorker m_Worker; ///< runs filter QThread m_Thread; ///< worker thread bool m_ThreadIsRunning; QTimer* m_SimulationTimer; QTime m_SimulationTime; QString m_SimulationStatusText; /** Image filters that do all the simulations. */ itk::TractsToDWIImageFilter< short >::Pointer m_TractsToDwiFilter; itk::AddArtifactsToDwiImageFilter< short >::Pointer m_ArtifactsToDwiFilter; friend class QmitkFiberfoxWorker; }; 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 5de6996c71..b131d32f75 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.cpp @@ -1,768 +1,768 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkGibbsTrackingView.h" #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(); m_View->m_GlobalTracker->SetQBallImage(m_View->m_ItkQBallImage); m_View->m_GlobalTracker->SetTensorImage(m_View->m_ItkTensorImage); m_View->m_GlobalTracker->SetMaskImage(m_View->m_MaskImage); m_View->m_GlobalTracker->SetStartTemperature((float)m_View->m_Controls->m_StartTempSlider->value()/100); m_View->m_GlobalTracker->SetEndTemperature((float)m_View->m_Controls->m_EndTempSlider->value()/10000); m_View->m_GlobalTracker->SetIterations(m_View->m_Iterations); m_View->m_GlobalTracker->SetParticleWeight((float)m_View->m_Controls->m_ParticleWeightSlider->value()/10000); m_View->m_GlobalTracker->SetParticleWidth((float)(m_View->m_Controls->m_ParticleWidthSlider->value())/10); m_View->m_GlobalTracker->SetParticleLength((float)(m_View->m_Controls->m_ParticleLengthSlider->value())/10); m_View->m_GlobalTracker->SetInexBalance((float)m_View->m_Controls->m_InExBalanceSlider->value()/10); m_View->m_GlobalTracker->SetMinFiberLength(m_View->m_Controls->m_FiberLengthSlider->value()); m_View->m_GlobalTracker->SetCurvatureThreshold(cos((float)m_View->m_Controls->m_CurvatureThresholdSlider->value()*M_PI/180)); m_View->m_GlobalTracker->SetRandomSeed(m_View->m_Controls->m_RandomSeedSlider->value()); try{ m_View->m_GlobalTracker->Update(); } catch( mitk::Exception e ) { MITK_ERROR << "Internal error occured: " << e.what() << "\nAborting"; } m_View->m_TrackingThread.quit(); } const std::string QmitkGibbsTrackingView::VIEW_ID = "org.mitk.views.gibbstracking"; QmitkGibbsTrackingView::QmitkGibbsTrackingView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget(NULL) , m_FiberBundle(NULL) , m_MaskImage(NULL) , m_TensorImage(NULL) , m_QBallImage(NULL) , m_ItkQBallImage(NULL) , m_ItkTensorImage(NULL) , m_ImageNode(NULL) , m_MaskImageNode(NULL) , m_FiberBundleNode(NULL) , m_ThreadIsRunning(false) , m_ElapsedTime(0) , m_Iterations(10000000) , m_LastStep(0) , m_GlobalTracker(NULL) , m_TrackingWorker(this) , m_TrackingNode(NULL) { m_TrackingWorker.moveToThread(&m_TrackingThread); connect(&m_TrackingThread, SIGNAL(started()), this, SLOT(BeforeThread())); connect(&m_TrackingThread, SIGNAL(started()), &m_TrackingWorker, SLOT(run())); connect(&m_TrackingThread, SIGNAL(finished()), this, SLOT(AfterThread())); connect(&m_TrackingThread, SIGNAL(terminated()), this, SLOT(AfterThread())); m_TrackingTimer = new QTimer(this); } QmitkGibbsTrackingView::~QmitkGibbsTrackingView() { if (m_GlobalTracker.IsNull()) return; m_GlobalTracker->SetAbortTracking(true); m_TrackingThread.wait(); } // update tracking status and generate fiber bundle void QmitkGibbsTrackingView::TimerUpdate() { int currentStep = m_GlobalTracker->GetCurrentStep(); mitk::ProgressBar::GetInstance()->Progress(currentStep-m_LastStep); UpdateTrackingStatus(); GenerateFiberBundle(); 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 ..."); m_TrackingNode = NULL; } // 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(); if( !m_GlobalTracker->GetIsInValidState() ) { QMessageBox::critical( NULL, "Gibbs Tracking", "An internal error occured. Tracking aborted.\n Please check the log for details." ); m_FiberBundleNode = NULL; return; } UpdateTrackingStatus(); if(m_Controls->m_ParticleWeightSlider->value()==0) { m_Controls->m_ParticleWeightLabel->setText(QString::number(m_GlobalTracker->GetParticleWeight())); m_Controls->m_ParticleWeightSlider->setValue(m_GlobalTracker->GetParticleWeight()*10000); } if(m_Controls->m_ParticleWidthSlider->value()==0) { m_Controls->m_ParticleWidthLabel->setText(QString::number(m_GlobalTracker->GetParticleWidth())); m_Controls->m_ParticleWidthSlider->setValue(m_GlobalTracker->GetParticleWidth()*10); } if(m_Controls->m_ParticleLengthSlider->value()==0) { m_Controls->m_ParticleLengthLabel->setText(QString::number(m_GlobalTracker->GetParticleLength())); m_Controls->m_ParticleLengthSlider->setValue(m_GlobalTracker->GetParticleLength()*10); } GenerateFiberBundle(); m_FiberBundleNode = 0; m_GlobalTracker = 0; // images not needed anymore ( relevant only for computation ) // we need to release them to remove the memory access block created through CastToItk<> calls this->m_ItkQBallImage = 0; this->m_ItkTensorImage = 0; } // start tracking timer and update gui elements before tracking is started void QmitkGibbsTrackingView::BeforeThread() { m_ThreadIsRunning = true; m_TrackingTime = QTime::currentTime(); m_ElapsedTime = 0; m_TrackingTimer->start(1000); 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_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_RandomSeedSlider, SIGNAL(valueChanged(int)), this, SLOT(SetRandomSeed(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::SetRandomSeed(int value) { if (value>=0) m_Controls->m_RandomSeedLabel->setText(QString::number(value)); else m_Controls->m_RandomSeedLabel->setText("auto"); } void QmitkGibbsTrackingView::SetParticleWeight(int value) { if (value>0) m_Controls->m_ParticleWeightLabel->setText(QString::number((float)value/10000)); else m_Controls->m_ParticleWeightLabel->setText("auto"); } void QmitkGibbsTrackingView::SetStartTemp(int value) { m_Controls->m_StartTempLabel->setText(QString::number((float)value/100)); } void QmitkGibbsTrackingView::SetEndTemp(int value) { m_Controls->m_EndTempLabel->setText(QString::number((float)value/10000)); } void QmitkGibbsTrackingView::SetParticleWidth(int value) { if (value>0) m_Controls->m_ParticleWidthLabel->setText(QString::number((float)value/10)+" mm"); else m_Controls->m_ParticleWidthLabel->setText("auto"); } void QmitkGibbsTrackingView::SetParticleLength(int value) { if (value>0) m_Controls->m_ParticleLengthLabel->setText(QString::number((float)value/10)+" mm"); else m_Controls->m_ParticleLengthLabel->setText("auto"); } void QmitkGibbsTrackingView::SetCurvatureThreshold(int value) { m_Controls->m_CurvatureThresholdLabel->setText(QString::number(value)+"°"); } 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; } } 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 ) { if (m_ThreadIsRunning) return; m_ImageNode = 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_ImageNode = node; else if( node.IsNotNull() && dynamic_cast(node->GetData()) ) m_ImageNode = node; else if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { mitk::Image::Pointer img = dynamic_cast(node->GetData()); if (img->GetPixelType().GetPixelType()==itk::ImageIOBase::SCALAR) m_MaskImageNode = node; } } UpdateGUI(); } void QmitkGibbsTrackingView::NodeRemoved(const mitk::DataNode * node) { if (m_ThreadIsRunning) { if (node==m_TrackingNode.GetPointer()) { StopGibbsTracking(); } } } // update gui elements displaying trackings status void QmitkGibbsTrackingView::UpdateTrackingStatus() { if (m_GlobalTracker.IsNull()) return; m_ElapsedTime += m_TrackingTime.elapsed()/1000; m_TrackingTime.restart(); unsigned long hours = m_ElapsedTime/3600; unsigned long minutes = (m_ElapsedTime%3600)/60; unsigned long seconds = m_ElapsedTime%60; m_Controls->m_ProposalAcceptance->setText(QString::number(m_GlobalTracker->GetProposalAcceptance()*100)+"%"); m_Controls->m_TrackingTimeLabel->setText( QString::number(hours)+QString("h ")+QString::number(minutes)+QString("m ")+QString::number(seconds)+QString("s") ); m_Controls->m_NumConnectionsLabel->setText( QString::number(m_GlobalTracker->GetNumConnections()) ); m_Controls->m_NumParticlesLabel->setText( QString::number(m_GlobalTracker->GetNumParticles()) ); m_Controls->m_CurrentStepLabel->setText( QString::number(100*(float)(m_GlobalTracker->GetCurrentStep()-1)/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_ImageNode.IsNotNull()) { m_Controls->m_QballImageLabel->setText(m_ImageNode->GetName().c_str()); m_Controls->m_DataFrame->setTitle("Input Data"); } else { m_Controls->m_QballImageLabel->setText("mandatory"); m_Controls->m_DataFrame->setTitle("Please Select Input Data"); } if (m_MaskImageNode.IsNotNull()) m_Controls->m_MaskImageLabel->setText(m_MaskImageNode->GetName().c_str()); else m_Controls->m_MaskImageLabel->setText("optional"); if (!m_ThreadIsRunning && m_ImageNode.IsNotNull()) { m_Controls->m_TrackingStop->setEnabled(false); m_Controls->m_TrackingStart->setEnabled(true); m_Controls->m_LoadTrackingParameters->setEnabled(true); m_Controls->m_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_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_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_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_MaskImageLabel->setText(node->GetName().c_str()); return; } } } // check for mask and qbi and start tracking thread void QmitkGibbsTrackingView::StartGibbsTracking() { if(m_ThreadIsRunning) { MITK_WARN("QmitkGibbsTrackingView")<<"Thread already running!"; return; } m_GlobalTracker = NULL; if (m_ImageNode.IsNull()) { QMessageBox::information( NULL, "Warning", "Please load and select a qball image before starting image processing."); return; } if (dynamic_cast(m_ImageNode->GetData())) m_QBallImage = dynamic_cast(m_ImageNode->GetData()); else if (dynamic_cast(m_ImageNode->GetData())) m_TensorImage = dynamic_cast(m_ImageNode->GetData()); if (m_QBallImage.IsNull() && m_TensorImage.IsNull()) return; // cast qbi to itk m_TrackingNode = m_ImageNode; m_ItkTensorImage = NULL; m_ItkQBallImage = NULL; m_MaskImage = NULL; if (m_QBallImage.IsNotNull()) { m_ItkQBallImage = ItkQBallImgType::New(); mitk::CastToItkImage(m_QBallImage, m_ItkQBallImage); } else { m_ItkTensorImage = ItkTensorImage::New(); mitk::CastToItkImage(m_TensorImage, m_ItkTensorImage); } // mask image found? // catch exceptions thrown by the itkAccess macros try{ if(m_MaskImageNode.IsNotNull()) { if (dynamic_cast(m_MaskImageNode->GetData())) mitk::CastToItkImage(dynamic_cast(m_MaskImageNode->GetData()), m_MaskImage); } } catch(...){}; unsigned int steps = m_Iterations/10000; if (steps<10) steps = 10; m_LastStep = 1; mitk::ProgressBar::GetInstance()->AddStepsToDo(steps); // start worker thread m_TrackingThread.start(QThread::LowestPriority); } // generate mitkFiberBundle from tracking filter output void QmitkGibbsTrackingView::GenerateFiberBundle() { if (m_GlobalTracker.IsNull() || (!(m_Controls->m_VisualizationCheckbox->isChecked() || m_Controls->m_VisualizeOnceButton->isChecked()) && m_ThreadIsRunning)) return; if (m_Controls->m_VisualizeOnceButton->isChecked()) m_Controls->m_VisualizeOnceButton->setChecked(false); vtkSmartPointer fiberBundle = m_GlobalTracker->GetFiberBundle(); if ( m_GlobalTracker->GetNumAcceptedFibers()==0 ) return; - m_FiberBundle = mitk::FiberBundleX::New(fiberBundle); + m_FiberBundle = mitk::FiberBundle::New(fiberBundle); m_FiberBundle->SetReferenceGeometry(dynamic_cast(m_ImageNode->GetData())->GetGeometry()); if (m_FiberBundleNode.IsNotNull()){ GetDefaultDataStorage()->Remove(m_FiberBundleNode); m_FiberBundleNode = 0; } m_FiberBundleNode = mitk::DataNode::New(); m_FiberBundleNode->SetData(m_FiberBundle); QString name("FiberBundle_"); name += m_ImageNode->GetName().c_str(); name += "_Gibbs"; m_FiberBundleNode->SetName(name.toStdString()); m_FiberBundleNode->SetVisibility(true); if (!m_OutputFileName.isEmpty() && !m_ThreadIsRunning) { try { mitk::IOUtil::Save(m_FiberBundle.GetPointer(),m_OutputFileName.toStdString()); QMessageBox::information(NULL, "Fiber bundle saved to", m_OutputFileName); } catch (itk::ExceptionObject &ex) { 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_ImageNode.IsNull()) GetDataStorage()->Add(m_FiberBundleNode); else GetDataStorage()->Add(m_FiberBundleNode, m_ImageNode); } void QmitkGibbsTrackingView::SetOutputFile() { // SELECT FOLDER DIALOG m_OutputFileName = QFileDialog::getSaveFileName(0, tr("Set file name"), QDir::currentPath()+"/FiberBundle.fib", tr("Fiber Bundle (*.fib)") ); if (m_OutputFileName.isEmpty()) m_Controls->m_OutputFileLabel->setText("N/A"); else m_Controls->m_OutputFileLabel->setText(m_OutputFileName); } // save current tracking paramters as xml file (.gtp) void QmitkGibbsTrackingView::SaveTrackingParameters() { TiXmlDocument documentXML; TiXmlDeclaration* declXML = new TiXmlDeclaration( "1.0", "", "" ); documentXML.LinkEndChild( declXML ); TiXmlElement* mainXML = new TiXmlElement("global_tracking_parameter_file"); mainXML->SetAttribute("file_version", "0.1"); documentXML.LinkEndChild(mainXML); TiXmlElement* paramXML = new TiXmlElement("parameter_set"); paramXML->SetAttribute("iterations", 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 5cebd39bb4..a9294e9ca7 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.h @@ -1,167 +1,167 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkGibbsTrackingView_h #define QmitkGibbsTrackingView_h #include #include #include "ui_QmitkGibbsTrackingViewControls.h" #include #include -#include +#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 View for global fiber tracking (Gibbs tracking) \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 ItkFloatImageType; typedef itk::Vector OdfVectorType; typedef itk::Image ItkQBallImgType; typedef itk::Image< itk::DiffusionTensor3D, 3 > ItkTensorImage; typedef itk::GibbsTrackingFilter< ItkQBallImgType > 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(); ///< update gui etc. after tracking has finished void BeforeThread(); ///< start timer etc. void TimerUpdate(); void SetMask(); void AdvancedSettings(); ///< show/hide advanced tracking options void SaveTrackingParameters(); ///< save tracking parameters to xml file void LoadTrackingParameters(); ///< load tracking parameters from xml file /** update labels if parameters have changed */ 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 SetRandomSeed(int value); void SetOutputFile(); private: // Visualization & GUI void GenerateFiberBundle(); ///< generate fiber bundle from tracking output and add to datanode void UpdateGUI(); ///< update button activity etc. dpending on current datamanager selection void UpdateTrackingStatus(); ///< update textual status display of the tracking process /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); /// \brief called when DataNode is removed to stop gibbs tracking after node is removed virtual void NodeRemoved(const mitk::DataNode * node); void UpdateIteraionsGUI(unsigned long iterations); ///< update iterations label text Ui::QmitkGibbsTrackingViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; /** data objects */ mitk::DataNode::Pointer m_TrackingNode; ///< actual node that is tracked - mitk::FiberBundleX::Pointer m_FiberBundle; ///< tracking output + mitk::FiberBundle::Pointer m_FiberBundle; ///< tracking output ItkFloatImageType::Pointer m_MaskImage; ///< used to reduce the algorithms search space. tracking only inside of the mask. mitk::TensorImage::Pointer m_TensorImage; ///< actual image that is tracked mitk::QBallImage::Pointer m_QBallImage; ///< actual image that is tracked ItkQBallImgType::Pointer m_ItkQBallImage; ///< actual image that is tracked ItkTensorImage::Pointer m_ItkTensorImage; ///< actual image that is tracked /** data nodes */ mitk::DataNode::Pointer m_ImageNode; 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; unsigned long m_Iterations; int m_LastStep; QString m_OutputFileName; /** 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/QmitkOdfMaximaExtractionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkOdfMaximaExtractionView.cpp index c928cfe266..15fd3e614c 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkOdfMaximaExtractionView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkOdfMaximaExtractionView.cpp @@ -1,778 +1,778 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //misc #define _USE_MATH_DEFINES #include #include // Blueberry #include #include // Qmitk #include "QmitkOdfMaximaExtractionView.h" // MITK #include -#include +#include #include #include #include // ITK #include #include #include #include #include #include #include // Qt #include const std::string QmitkOdfMaximaExtractionView::VIEW_ID = "org.mitk.views.odfmaximaextractionview"; using namespace mitk; QmitkOdfMaximaExtractionView::QmitkOdfMaximaExtractionView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) { } // Destructor QmitkOdfMaximaExtractionView::~QmitkOdfMaximaExtractionView() { } void QmitkOdfMaximaExtractionView::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::QmitkOdfMaximaExtractionViewControls; m_Controls->setupUi( parent ); connect((QObject*) m_Controls->m_StartTensor, SIGNAL(clicked()), (QObject*) this, SLOT(StartTensor())); connect((QObject*) m_Controls->m_StartFiniteDiff, SIGNAL(clicked()), (QObject*) this, SLOT(StartFiniteDiff())); connect((QObject*) m_Controls->m_GenerateImageButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateImage())); connect((QObject*) m_Controls->m_ImportPeaks, SIGNAL(clicked()), (QObject*) this, SLOT(ConvertPeaks())); connect((QObject*) m_Controls->m_ImportShCoeffs, SIGNAL(clicked()), (QObject*) this, SLOT(ConvertShCoeffs())); } } void QmitkOdfMaximaExtractionView::UpdateGui() { m_Controls->m_GenerateImageButton->setEnabled(false); m_Controls->m_StartFiniteDiff->setEnabled(false); m_Controls->m_StartTensor->setEnabled(false); m_Controls->m_CoeffImageFrame->setEnabled(false); if (!m_ImageNodes.empty() || !m_TensorImageNodes.empty()) { m_Controls->m_InputData->setTitle("Input Data"); if (!m_TensorImageNodes.empty()) { m_Controls->m_DwiFibLabel->setText(m_TensorImageNodes.front()->GetName().c_str()); m_Controls->m_StartTensor->setEnabled(true); } else { m_Controls->m_DwiFibLabel->setText(m_ImageNodes.front()->GetName().c_str()); m_Controls->m_StartFiniteDiff->setEnabled(true); m_Controls->m_GenerateImageButton->setEnabled(true); m_Controls->m_CoeffImageFrame->setEnabled(true); m_Controls->m_ShOrderBox->setEnabled(true); m_Controls->m_MaxNumPeaksBox->setEnabled(true); m_Controls->m_PeakThresholdBox->setEnabled(true); m_Controls->m_AbsoluteThresholdBox->setEnabled(true); } } else m_Controls->m_DwiFibLabel->setText("mandatory"); if (m_ImageNodes.empty()) { m_Controls->m_ImportPeaks->setEnabled(false); m_Controls->m_ImportShCoeffs->setEnabled(false); } else { m_Controls->m_ImportPeaks->setEnabled(true); m_Controls->m_ImportShCoeffs->setEnabled(true); } if (!m_BinaryImageNodes.empty()) { m_Controls->m_MaskLabel->setText(m_BinaryImageNodes.front()->GetName().c_str()); } else { m_Controls->m_MaskLabel->setText("optional"); } } template void QmitkOdfMaximaExtractionView::TemplatedConvertShCoeffs(mitk::Image* mitkImg) { typedef itk::ShCoefficientImageImporter< float, shOrder > FilterType; typedef mitk::ImageToItk< itk::Image< float, 4 > > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(mitkImg); caster->Update(); typename FilterType::Pointer filter = FilterType::New(); switch (m_Controls->m_ToolkitBox->currentIndex()) { case 0: filter->SetToolkit(FilterType::FSL); break; case 1: filter->SetToolkit(FilterType::MRTRIX); break; default: filter->SetToolkit(FilterType::FSL); } filter->SetInputImage(caster->GetOutput()); filter->GenerateData(); typename FilterType::QballImageType::Pointer itkQbi = filter->GetQballImage(); typename FilterType::CoefficientImageType::Pointer itkCi = filter->GetCoefficientImage(); { mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk( itkCi.GetPointer() ); img->SetVolume( itkCi->GetBufferPointer() ); DataNode::Pointer node = DataNode::New(); node->SetData(img); node->SetName("_ShCoefficientImage"); node->SetVisibility(false); GetDataStorage()->Add(node); } { mitk::QBallImage::Pointer img = mitk::QBallImage::New(); img->InitializeByItk( itkQbi.GetPointer() ); img->SetVolume( itkQbi->GetBufferPointer() ); DataNode::Pointer node = DataNode::New(); node->SetData(img); node->SetName("_QballImage"); GetDataStorage()->Add(node); } } void QmitkOdfMaximaExtractionView::ConvertShCoeffs() { if (m_ImageNodes.empty()) return; mitk::Image::Pointer mitkImg = dynamic_cast(m_ImageNodes.at(0)->GetData()); if (mitkImg->GetDimension()!=4) { MITK_INFO << "wrong image type (need 4 dimensions)"; return; } int nrCoeffs = mitkImg->GetLargestPossibleRegion().GetSize()[3]; // solve bx² + cx + d = 0 = shOrder² + 2*shOrder + 2-2*neededCoeffs; int c=3, d=2-2*nrCoeffs; double D = c*c-4*d; int shOrder; if (D>0) { shOrder = (-c+sqrt(D))/2.0; if (shOrder<0) shOrder = (-c-sqrt(D))/2.0; } else if (D==0) shOrder = -c/2.0; MITK_INFO << "using SH-order " << shOrder; switch (shOrder) { case 2: TemplatedConvertShCoeffs<2>(mitkImg); break; case 4: TemplatedConvertShCoeffs<4>(mitkImg); break; case 6: TemplatedConvertShCoeffs<6>(mitkImg); break; case 8: TemplatedConvertShCoeffs<8>(mitkImg); break; case 10: TemplatedConvertShCoeffs<10>(mitkImg); break; case 12: TemplatedConvertShCoeffs<12>(mitkImg); break; default: MITK_INFO << "SH-order " << shOrder << " not supported"; } } void QmitkOdfMaximaExtractionView::ConvertPeaks() { if (m_ImageNodes.empty()) return; switch (m_Controls->m_ToolkitBox->currentIndex()) { case 0: { typedef itk::Image< float, 4 > ItkImageType; typedef itk::FslPeakImageConverter< float > FilterType; FilterType::Pointer filter = FilterType::New(); FilterType::InputType::Pointer inputVec = FilterType::InputType::New(); mitk::BaseGeometry::Pointer geom; for (int i=0; i(m_ImageNodes.at(i)->GetData()); geom = mitkImg->GetGeometry(); typedef mitk::ImageToItk< FilterType::InputImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(mitkImg); caster->Update(); FilterType::InputImageType::Pointer itkImg = caster->GetOutput(); inputVec->InsertElement(inputVec->Size(), itkImg); } filter->SetInputImages(inputVec); filter->GenerateData(); mitk::Vector3D outImageSpacing = geom->GetSpacing(); float maxSpacing = 1; if(outImageSpacing[0]>outImageSpacing[1] && outImageSpacing[0]>outImageSpacing[2]) maxSpacing = outImageSpacing[0]; else if (outImageSpacing[1] > outImageSpacing[2]) maxSpacing = outImageSpacing[1]; else maxSpacing = outImageSpacing[2]; - mitk::FiberBundleX::Pointer directions = filter->GetOutputFiberBundle(); + mitk::FiberBundle::Pointer directions = filter->GetOutputFiberBundle(); // directions->SetGeometry(geom); DataNode::Pointer node = DataNode::New(); node->SetData(directions); node->SetName("_VectorField"); node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(maxSpacing)); node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false)); GetDataStorage()->Add(node); typedef FilterType::DirectionImageContainerType DirectionImageContainerType; DirectionImageContainerType::Pointer container = filter->GetDirectionImageContainer(); for (int i=0; iSize(); i++) { ItkDirectionImage3DType::Pointer itkImg = container->GetElement(i); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk( itkImg.GetPointer() ); img->SetVolume( itkImg->GetBufferPointer() ); DataNode::Pointer node = DataNode::New(); node->SetData(img); QString name(m_ImageNodes.at(i)->GetName().c_str()); name += "_Direction"; name += QString::number(i+1); node->SetName(name.toStdString().c_str()); node->SetVisibility(false); GetDataStorage()->Add(node); } break; } case 1: { typedef itk::Image< float, 4 > ItkImageType; typedef itk::MrtrixPeakImageConverter< float > FilterType; FilterType::Pointer filter = FilterType::New(); // cast to itk mitk::Image::Pointer mitkImg = dynamic_cast(m_ImageNodes.at(0)->GetData()); mitk::BaseGeometry::Pointer geom = mitkImg->GetGeometry(); typedef mitk::ImageToItk< FilterType::InputImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(mitkImg); caster->Update(); FilterType::InputImageType::Pointer itkImg = caster->GetOutput(); filter->SetInputImage(itkImg); filter->GenerateData(); mitk::Vector3D outImageSpacing = geom->GetSpacing(); float maxSpacing = 1; if(outImageSpacing[0]>outImageSpacing[1] && outImageSpacing[0]>outImageSpacing[2]) maxSpacing = outImageSpacing[0]; else if (outImageSpacing[1] > outImageSpacing[2]) maxSpacing = outImageSpacing[1]; else maxSpacing = outImageSpacing[2]; - mitk::FiberBundleX::Pointer directions = filter->GetOutputFiberBundle(); + mitk::FiberBundle::Pointer directions = filter->GetOutputFiberBundle(); //directions->SetGeometry(geom); DataNode::Pointer node = DataNode::New(); node->SetData(directions); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_VectorField"; node->SetName(name.toStdString().c_str()); node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(maxSpacing)); node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false)); GetDataStorage()->Add(node); { ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage(); mitk::Image::Pointer image2 = mitk::Image::New(); image2->InitializeByItk( numDirImage.GetPointer() ); image2->SetVolume( numDirImage->GetBufferPointer() ); DataNode::Pointer node2 = DataNode::New(); node2->SetData(image2); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_NumDirections"; node2->SetName(name.toStdString().c_str()); GetDataStorage()->Add(node2); } typedef FilterType::DirectionImageContainerType DirectionImageContainerType; DirectionImageContainerType::Pointer container = filter->GetDirectionImageContainer(); for (int i=0; iSize(); i++) { ItkDirectionImage3DType::Pointer itkImg = container->GetElement(i); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk( itkImg.GetPointer() ); img->SetVolume( itkImg->GetBufferPointer() ); DataNode::Pointer node = DataNode::New(); node->SetData(img); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_Direction"; name += QString::number(i+1); node->SetName(name.toStdString().c_str()); node->SetVisibility(false); GetDataStorage()->Add(node); } break; } } } void QmitkOdfMaximaExtractionView::GenerateImage() { if (!m_ImageNodes.empty()) GenerateDataFromDwi(); } void QmitkOdfMaximaExtractionView::StartTensor() { if (m_TensorImageNodes.empty()) return; typedef itk::DiffusionTensorPrincipalDirectionImageFilter< float, float > MaximaExtractionFilterType; MaximaExtractionFilterType::Pointer filter = MaximaExtractionFilterType::New(); mitk::BaseGeometry::Pointer geometry; try{ TensorImage::Pointer img = dynamic_cast(m_TensorImageNodes.at(0)->GetData()); ItkTensorImage::Pointer itkImage = ItkTensorImage::New(); CastToItkImage(img, itkImage); filter->SetInput(itkImage); geometry = img->GetGeometry(); } catch(itk::ExceptionObject &e) { MITK_INFO << "wrong image type: " << e.what(); QMessageBox::warning( NULL, "Wrong pixel type", "Could not perform Tensor Principal Direction Extraction due to Image has wrong pixel type.", QMessageBox::Ok ); return; //throw e; } if (!m_BinaryImageNodes.empty()) { ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); Image::Pointer mitkMaskImg = dynamic_cast(m_BinaryImageNodes.at(0)->GetData()); CastToItkImage(mitkMaskImg, itkMaskImage); filter->SetMaskImage(itkMaskImage); } if (m_Controls->m_NormalizationBox->currentIndex()==0) filter->SetNormalizeVectors(false); filter->Update(); if (m_Controls->m_OutputDirectionImagesBox->isChecked()) { MaximaExtractionFilterType::OutputImageType::Pointer itkImg = filter->GetOutput(); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk( itkImg.GetPointer() ); img->SetVolume( itkImg->GetBufferPointer() ); DataNode::Pointer node = DataNode::New(); node->SetData(img); QString name(m_TensorImageNodes.at(0)->GetName().c_str()); name += "_PrincipalDirection"; node->SetName(name.toStdString().c_str()); node->SetVisibility(false); GetDataStorage()->Add(node); } if (m_Controls->m_OutputNumDirectionsBox->isChecked()) { ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage(); mitk::Image::Pointer image2 = mitk::Image::New(); image2->InitializeByItk( numDirImage.GetPointer() ); image2->SetVolume( numDirImage->GetBufferPointer() ); DataNode::Pointer node2 = DataNode::New(); node2->SetData(image2); QString name(m_TensorImageNodes.at(0)->GetName().c_str()); name += "_NumDirections"; node2->SetName(name.toStdString().c_str()); GetDataStorage()->Add(node2); } if (m_Controls->m_OutputVectorFieldBox->isChecked()) { mitk::Vector3D outImageSpacing = geometry->GetSpacing(); float minSpacing = 1; if(outImageSpacing[0]GetOutputFiberBundle(); + mitk::FiberBundle::Pointer directions = filter->GetOutputFiberBundle(); // directions->SetGeometry(geometry); DataNode::Pointer node = DataNode::New(); node->SetData(directions); QString name(m_TensorImageNodes.at(0)->GetName().c_str()); name += "_VectorField"; node->SetName(name.toStdString().c_str()); node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(minSpacing)); node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false)); GetDataStorage()->Add(node); } } template void QmitkOdfMaximaExtractionView::StartMaximaExtraction() { typedef itk::FiniteDiffOdfMaximaExtractionFilter< float, shOrder, 20242 > MaximaExtractionFilterType; typename MaximaExtractionFilterType::Pointer filter = MaximaExtractionFilterType::New(); switch (m_Controls->m_ToolkitBox->currentIndex()) { case 0: filter->SetToolkit(MaximaExtractionFilterType::FSL); break; case 1: filter->SetToolkit(MaximaExtractionFilterType::MRTRIX); break; default: filter->SetToolkit(MaximaExtractionFilterType::FSL); } mitk::BaseGeometry::Pointer geometry; try{ Image::Pointer img = dynamic_cast(m_ImageNodes.at(0)->GetData()); typedef ImageToItk< typename MaximaExtractionFilterType::CoefficientImageType > CasterType; typename CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); filter->SetInput(caster->GetOutput()); geometry = img->GetGeometry(); } catch(itk::ExceptionObject &e) { MITK_INFO << "wrong image type: " << e.what(); QMessageBox::warning( NULL, "Wrong pixel type", "Could not perform Finite Differences Extraction due to Image has wrong pixel type.", QMessageBox::Ok ); return; //throw; } filter->SetAngularThreshold(cos((float)m_Controls->m_AngularThreshold->value()*M_PI/180)); filter->SetClusteringThreshold(cos((float)m_Controls->m_ClusteringAngleBox->value()*M_PI/180)); filter->SetMaxNumPeaks(m_Controls->m_MaxNumPeaksBox->value()); filter->SetPeakThreshold(m_Controls->m_PeakThresholdBox->value()); filter->SetAbsolutePeakThreshold(m_Controls->m_AbsoluteThresholdBox->value()); if (!m_BinaryImageNodes.empty()) { ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); Image::Pointer mitkMaskImg = dynamic_cast(m_BinaryImageNodes.at(0)->GetData()); CastToItkImage(mitkMaskImg, itkMaskImage); filter->SetMaskImage(itkMaskImage); } switch (m_Controls->m_NormalizationBox->currentIndex()) { case 0: filter->SetNormalizationMethod(MaximaExtractionFilterType::NO_NORM); break; case 1: filter->SetNormalizationMethod(MaximaExtractionFilterType::MAX_VEC_NORM); break; case 2: filter->SetNormalizationMethod(MaximaExtractionFilterType::SINGLE_VEC_NORM); break; } filter->Update(); if (m_Controls->m_OutputDirectionImagesBox->isChecked()) { typedef typename MaximaExtractionFilterType::ItkDirectionImageContainer ItkDirectionImageContainer; typename ItkDirectionImageContainer::Pointer container = filter->GetDirectionImageContainer(); for (int i=0; iSize(); i++) { typename MaximaExtractionFilterType::ItkDirectionImage::Pointer itkImg = container->GetElement(i); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk( itkImg.GetPointer() ); img->SetVolume( itkImg->GetBufferPointer() ); DataNode::Pointer node = DataNode::New(); node->SetData(img); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_Direction"; name += QString::number(i+1); node->SetName(name.toStdString().c_str()); node->SetVisibility(false); GetDataStorage()->Add(node); } } if (m_Controls->m_OutputNumDirectionsBox->isChecked()) { ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage(); mitk::Image::Pointer image2 = mitk::Image::New(); image2->InitializeByItk( numDirImage.GetPointer() ); image2->SetVolume( numDirImage->GetBufferPointer() ); DataNode::Pointer node2 = DataNode::New(); node2->SetData(image2); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_NumDirections"; node2->SetName(name.toStdString().c_str()); GetDataStorage()->Add(node2); } if (m_Controls->m_OutputVectorFieldBox->isChecked()) { mitk::Vector3D outImageSpacing = geometry->GetSpacing(); float minSpacing = 1; if(outImageSpacing[0]GetOutputFiberBundle(); + mitk::FiberBundle::Pointer directions = filter->GetOutputFiberBundle(); // directions->SetGeometry(geometry); DataNode::Pointer node = DataNode::New(); node->SetData(directions); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_VectorField"; node->SetName(name.toStdString().c_str()); node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(minSpacing)); node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false)); GetDataStorage()->Add(node); } } void QmitkOdfMaximaExtractionView::StartFiniteDiff() { if (m_ImageNodes.empty()) return; switch (m_Controls->m_ShOrderBox->currentIndex()) { case 0: StartMaximaExtraction<2>(); break; case 1: StartMaximaExtraction<4>(); break; case 2: StartMaximaExtraction<6>(); break; case 3: StartMaximaExtraction<8>(); break; case 4: StartMaximaExtraction<10>(); break; case 5: StartMaximaExtraction<12>(); break; } } void QmitkOdfMaximaExtractionView::GenerateDataFromDwi() { typedef itk::OdfMaximaExtractionFilter< float > MaximaExtractionFilterType; MaximaExtractionFilterType::Pointer filter = MaximaExtractionFilterType::New(); mitk::BaseGeometry::Pointer geometry; if (!m_ImageNodes.empty()) { try{ Image::Pointer img = dynamic_cast(m_ImageNodes.at(0)->GetData()); typedef ImageToItk< MaximaExtractionFilterType::CoefficientImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); filter->SetShCoeffImage(caster->GetOutput()); geometry = img->GetGeometry(); } catch(itk::ExceptionObject &e) { MITK_INFO << "wrong image type: " << e.what(); return; } } else return; filter->SetMaxNumPeaks(m_Controls->m_MaxNumPeaksBox->value()); filter->SetPeakThreshold(m_Controls->m_PeakThresholdBox->value()); if (!m_BinaryImageNodes.empty()) { ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); Image::Pointer mitkMaskImg = dynamic_cast(m_BinaryImageNodes.at(0)->GetData()); CastToItkImage(mitkMaskImg, itkMaskImage); filter->SetMaskImage(itkMaskImage); } switch (m_Controls->m_NormalizationBox->currentIndex()) { case 0: filter->SetNormalizationMethod(MaximaExtractionFilterType::NO_NORM); break; case 1: filter->SetNormalizationMethod(MaximaExtractionFilterType::MAX_VEC_NORM); break; case 2: filter->SetNormalizationMethod(MaximaExtractionFilterType::SINGLE_VEC_NORM); break; } filter->GenerateData(); ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage(); if (m_Controls->m_OutputDirectionImagesBox->isChecked()) { typedef MaximaExtractionFilterType::ItkDirectionImageContainer ItkDirectionImageContainer; ItkDirectionImageContainer::Pointer container = filter->GetDirectionImageContainer(); for (int i=0; iSize(); i++) { MaximaExtractionFilterType::ItkDirectionImage::Pointer itkImg = container->GetElement(i); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk( itkImg.GetPointer() ); img->SetVolume( itkImg->GetBufferPointer() ); DataNode::Pointer node = DataNode::New(); node->SetData(img); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_Direction"; name += QString::number(i+1); node->SetName(name.toStdString().c_str()); GetDataStorage()->Add(node); } } if (m_Controls->m_OutputNumDirectionsBox->isChecked()) { mitk::Image::Pointer image2 = mitk::Image::New(); image2->InitializeByItk( numDirImage.GetPointer() ); image2->SetVolume( numDirImage->GetBufferPointer() ); DataNode::Pointer node = DataNode::New(); node->SetData(image2); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_NumDirections"; node->SetName(name.toStdString().c_str()); GetDataStorage()->Add(node); } if (m_Controls->m_OutputVectorFieldBox->isChecked()) { mitk::Vector3D outImageSpacing = geometry->GetSpacing(); float minSpacing = 1; if(outImageSpacing[0]GetOutputFiberBundle(); + mitk::FiberBundle::Pointer directions = filter->GetOutputFiberBundle(); // directions->SetGeometry(geometry); DataNode::Pointer node = DataNode::New(); node->SetData(directions); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_VectorField"; node->SetName(name.toStdString().c_str()); node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(minSpacing)); node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false)); GetDataStorage()->Add(node); } } void QmitkOdfMaximaExtractionView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkOdfMaximaExtractionView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkOdfMaximaExtractionView::OnSelectionChanged( std::vector nodes ) { m_Controls->m_InputData->setTitle("Please Select Input Data"); m_Controls->m_DwiFibLabel->setText("mandatory"); m_Controls->m_MaskLabel->setText("optional"); m_BinaryImageNodes.clear(); m_ImageNodes.clear(); m_TensorImageNodes.clear(); // 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_TensorImageNodes.push_back(node); } else if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { bool isBinary = false; node->GetPropertyValue("binary", isBinary); if (isBinary) m_BinaryImageNodes.push_back(node); else m_ImageNodes.push_back(node); } } UpdateGui(); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingView.cpp index a5ccce623d..738e29bf18 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingView.cpp @@ -1,295 +1,295 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include #include // Qmitk #include "QmitkStochasticFiberTrackingView.h" #include "QmitkStdMultiWidget.h" // Qt #include // MITK #include -#include +#include #include // VTK #include #include #include #include #include #include const std::string QmitkStochasticFiberTrackingView::VIEW_ID = "org.mitk.views.stochasticfibertracking"; const std::string id_DataManager = "org.mitk.views.datamanager"; using namespace berry; QmitkStochasticFiberTrackingView::QmitkStochasticFiberTrackingView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) , m_SeedRoi( NULL ) , m_DiffusionImage( NULL ) { } // Destructor QmitkStochasticFiberTrackingView::~QmitkStochasticFiberTrackingView() { } void QmitkStochasticFiberTrackingView::CreateQtPartControl( QWidget *parent ) { if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkStochasticFiberTrackingViewControls; m_Controls->setupUi( parent ); connect( m_Controls->commandLinkButton, SIGNAL(clicked()), this, SLOT(DoFiberTracking()) ); connect( m_Controls->m_SeedsPerVoxelSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSeedsPerVoxelChanged(int)) ); connect( m_Controls->m_MaxCacheSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(OnMaxCacheSizeChanged(int)) ); connect( m_Controls->m_MaxTractLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(OnMaxTractLengthChanged(int)) ); } } void QmitkStochasticFiberTrackingView::OnSeedsPerVoxelChanged(int value) { m_Controls->m_SeedsPerVoxelLabel->setText(QString("Seeds per Voxel: ")+QString::number(value)); } void QmitkStochasticFiberTrackingView::OnMaxTractLengthChanged(int value) { m_Controls->m_MaxTractLengthLabel->setText(QString("Max. Tract Length: ")+QString::number(value)); } void QmitkStochasticFiberTrackingView::OnMaxCacheSizeChanged(int value) { m_Controls->m_MaxCacheSizeLabel->setText(QString("Max. Cache Size: ")+QString::number(value)+"GB"); } void QmitkStochasticFiberTrackingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkStochasticFiberTrackingView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkStochasticFiberTrackingView::OnSelectionChanged( std::vector nodes ) { m_DiffusionImageNode = NULL; m_DiffusionImage = NULL; m_SeedRoi = NULL; m_Controls->m_DiffusionImageLabel->setText("mandatory"); m_Controls->m_RoiImageLabel->setText("mandatory"); for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(node->GetData())) ); if ( isDiffusionImage ) { m_DiffusionImageNode = node; m_DiffusionImage = dynamic_cast(node->GetData()); m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str()); } else { bool isBinary = false; node->GetPropertyValue("binary", isBinary); if (isBinary) { m_SeedRoi = dynamic_cast(node->GetData()); m_Controls->m_RoiImageLabel->setText(node->GetName().c_str()); } } } } if(m_DiffusionImage.IsNotNull() && m_SeedRoi.IsNotNull()) { m_Controls->m_InputData->setTitle("Input Data"); m_Controls->commandLinkButton->setEnabled(true); } else { m_Controls->m_InputData->setTitle("Please Select Input Data"); m_Controls->commandLinkButton->setEnabled(false); } } void QmitkStochasticFiberTrackingView::DoFiberTracking() { typedef itk::VectorImage< short int, 3 > DWIVectorImageType; typedef itk::Image< float, 3 > FloatImageType; typedef itk::Image< unsigned int, 3 > CImageType; typedef itk::StochasticTractographyFilter< DWIVectorImageType, FloatImageType, CImageType > TrackingFilterType; typedef itk::DTITubeSpatialObject<3> DTITubeType; typedef itk::DTITubeSpatialObjectPoint<3> DTITubePointType; typedef itk::SceneSpatialObject<3> SceneSpatialObjectType; /* get Gradients/Direction of dwi */ GradientDirectionContainerType::Pointer Pdir = static_cast( m_DiffusionImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); /* bValueContainer, Container includes b-values according to corresponding gradient-direction*/ TrackingFilterType::bValueContainerType::Pointer vecCont = TrackingFilterType::bValueContainerType::New(); /* for each gradient set b-Value; for 0-gradient set b-value eq. 0 */ for ( int i=0; i<(int)Pdir->size(); ++i) { vnl_vector_fixed valsGrad = Pdir->at(i); if (valsGrad.get(0) == 0 && valsGrad.get(1) == 0 && valsGrad.get(2) == 0) { //set 0-Gradient to bValue 0 vecCont->InsertElement(i,0); }else{ vecCont->InsertElement(i, static_cast(m_DiffusionImage->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue()); } } /* define measurement frame (identity-matrix 3x3) */ TrackingFilterType::MeasurementFrameType measurement_frame = static_cast(m_DiffusionImage->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame(); /* generate white matterImage (dummy?)*/ ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(m_DiffusionImage, itkVectorImagePointer); FloatImageType::Pointer wmImage = FloatImageType::New(); wmImage->SetSpacing( itkVectorImagePointer->GetSpacing() ); wmImage->SetOrigin( itkVectorImagePointer->GetOrigin() ); wmImage->SetDirection( itkVectorImagePointer->GetDirection() ); wmImage->SetLargestPossibleRegion( itkVectorImagePointer->GetLargestPossibleRegion() ); wmImage->SetBufferedRegion( wmImage->GetLargestPossibleRegion() ); wmImage->SetRequestedRegion( wmImage->GetLargestPossibleRegion() ); wmImage->Allocate(); itk::ImageRegionIterator ot(wmImage, wmImage->GetLargestPossibleRegion() ); while (!ot.IsAtEnd()) { ot.Set(1); ++ot; } /* init TractographyFilter */ TrackingFilterType::Pointer trackingFilter = TrackingFilterType::New(); trackingFilter->SetPrimaryInput(itkVectorImagePointer.GetPointer()); trackingFilter->SetbValues(vecCont); trackingFilter->SetGradients(Pdir); trackingFilter->SetMeasurementFrame(measurement_frame); trackingFilter->SetWhiteMatterProbabilityImage(wmImage); trackingFilter->SetTotalTracts(m_Controls->m_SeedsPerVoxelSlider->value()); trackingFilter->SetMaxLikelihoodCacheSize(m_Controls->m_MaxCacheSizeSlider->value()*1000); trackingFilter->SetMaxTractLength(m_Controls->m_MaxTractLengthSlider->value()); //itk::Image< char, 3 > mitk::ImageToItk< itk::Image< unsigned char, 3 > >::Pointer binaryImageToItk1 = mitk::ImageToItk< itk::Image< unsigned char, 3 > >::New(); binaryImageToItk1->SetInput( m_SeedRoi ); binaryImageToItk1->Update(); vtkSmartPointer vPoints = vtkSmartPointer::New(); vtkSmartPointer vCellArray = vtkSmartPointer::New(); itk::ImageRegionConstIterator< BinaryImageType > it(binaryImageToItk1->GetOutput(), binaryImageToItk1->GetOutput()->GetRequestedRegion()); it.GoToBegin(); mitk::BaseGeometry* geom = m_DiffusionImage->GetGeometry(); while(!it.IsAtEnd()) { itk::ImageConstIterator::PixelType tmpPxValue = it.Get(); if(tmpPxValue != 0){ mitk::Point3D point; itk::ImageRegionConstIterator< BinaryImageType >::IndexType seedIdx = it.GetIndex(); trackingFilter->SetSeedIndex(seedIdx); trackingFilter->Update(); /* get results from Filter */ /* write each single tract into member container */ TrackingFilterType::TractContainerType::Pointer container_tmp = trackingFilter->GetOutputTractContainer(); TrackingFilterType::TractContainerType::Iterator elIt = container_tmp->Begin(); TrackingFilterType::TractContainerType::Iterator end = container_tmp->End(); bool addTract = true; while( elIt != end ){ TrackingFilterType::TractContainerType::Element tract = elIt.Value(); TrackingFilterType::TractContainerType::Element::ObjectType::VertexListType::ConstPointer vertexlist = tract->GetVertexList(); vtkSmartPointer vPolyLine = vtkSmartPointer::New(); for( int j=0; j<(int)vertexlist->Size(); j++) { TrackingFilterType::TractContainerType::Element::ObjectType::VertexListType::Element vertex = vertexlist->GetElement(j); mitk::Point3D index; index[0] = (float)vertex[0]; index[1] = (float)vertex[1]; index[2] = (float)vertex[2]; if (geom->IsIndexInside(index)) { geom->IndexToWorld(index, point); vtkIdType id = vPoints->InsertNextPoint(point.GetDataPointer()); vPolyLine->GetPointIds()->InsertNextId(id); } else { addTract = false; break; } } if (addTract) vCellArray->InsertNextCell(vPolyLine); ++elIt; } } ++it; } vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); fiberPolyData->SetPoints(vPoints); fiberPolyData->SetLines(vCellArray); - mitk::FiberBundleX::Pointer fib = mitk::FiberBundleX::New(fiberPolyData); + mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(fiberPolyData); fib->SetReferenceGeometry(dynamic_cast(m_DiffusionImageNode->GetData())->GetGeometry()); mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(fib); QString name("FiberBundle_"); name += m_DiffusionImageNode->GetName().c_str(); name += "_Probabilistic"; fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode, m_DiffusionImageNode); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingView.cpp index 6c60f8db19..da8fb53113 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingView.cpp @@ -1,286 +1,286 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include #include // Qmitk #include "QmitkStreamlineTrackingView.h" #include "QmitkStdMultiWidget.h" // Qt #include // MITK #include -#include +#include #include #include #include #include #include #include // VTK #include #include #include #include #include #include const std::string QmitkStreamlineTrackingView::VIEW_ID = "org.mitk.views.streamlinetracking"; const std::string id_DataManager = "org.mitk.views.datamanager"; using namespace berry; QmitkStreamlineTrackingView::QmitkStreamlineTrackingView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) , m_MaskImage( NULL ) , m_SeedRoi( NULL ) { } // Destructor QmitkStreamlineTrackingView::~QmitkStreamlineTrackingView() { } void QmitkStreamlineTrackingView::CreateQtPartControl( QWidget *parent ) { if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkStreamlineTrackingViewControls; m_Controls->setupUi( parent ); m_Controls->m_FaImageBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isImagePredicate = mitk::TNodePredicateDataType::New(); mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateNot::Pointer isNotBinaryPredicate = mitk::NodePredicateNot::New( isBinaryPredicate ); mitk::NodePredicateAnd::Pointer isNotABinaryImagePredicate = mitk::NodePredicateAnd::New( isImagePredicate, isNotBinaryPredicate ); mitk::NodePredicateDimension::Pointer dimensionPredicate = mitk::NodePredicateDimension::New(3); m_Controls->m_FaImageBox->SetPredicate( mitk::NodePredicateAnd::New(isNotABinaryImagePredicate, dimensionPredicate) ); connect( m_Controls->commandLinkButton, SIGNAL(clicked()), this, SLOT(DoFiberTracking()) ); connect( m_Controls->m_SeedsPerVoxelSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSeedsPerVoxelChanged(int)) ); connect( m_Controls->m_MinTractLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(OnMinTractLengthChanged(int)) ); connect( m_Controls->m_FaThresholdSlider, SIGNAL(valueChanged(int)), this, SLOT(OnFaThresholdChanged(int)) ); connect( m_Controls->m_AngularThresholdSlider, SIGNAL(valueChanged(int)), this, SLOT(OnAngularThresholdChanged(int)) ); connect( m_Controls->m_StepsizeSlider, SIGNAL(valueChanged(int)), this, SLOT(OnStepsizeChanged(int)) ); connect( m_Controls->m_fSlider, SIGNAL(valueChanged(int)), this, SLOT(OnfChanged(int)) ); connect( m_Controls->m_gSlider, SIGNAL(valueChanged(int)), this, SLOT(OngChanged(int)) ); } } void QmitkStreamlineTrackingView::OnfChanged(int value) { m_Controls->m_fLabel->setText(QString("f: ")+QString::number((float)value/100)); } void QmitkStreamlineTrackingView::OngChanged(int value) { m_Controls->m_gLabel->setText(QString("g: ")+QString::number((float)value/100)); } void QmitkStreamlineTrackingView::OnAngularThresholdChanged(int value) { if (value<0) m_Controls->m_AngularThresholdLabel->setText(QString("Min. Curvature Radius: auto")); else m_Controls->m_AngularThresholdLabel->setText(QString("Min. Curvature Radius: ")+QString::number((float)value/10)+QString("mm")); } void QmitkStreamlineTrackingView::OnSeedsPerVoxelChanged(int value) { m_Controls->m_SeedsPerVoxelLabel->setText(QString("Seeds per Voxel: ")+QString::number(value)); } void QmitkStreamlineTrackingView::OnMinTractLengthChanged(int value) { m_Controls->m_MinTractLengthLabel->setText(QString("Min. Tract Length: ")+QString::number(value)+QString("mm")); } void QmitkStreamlineTrackingView::OnFaThresholdChanged(int value) { m_Controls->m_FaThresholdLabel->setText(QString("FA Threshold: ")+QString::number((float)value/100)); } void QmitkStreamlineTrackingView::OnStepsizeChanged(int value) { if (value==0) m_Controls->m_StepsizeLabel->setText(QString("Stepsize: auto")); else m_Controls->m_StepsizeLabel->setText(QString("Stepsize: ")+QString::number((float)value/10)+QString("mm")); } void QmitkStreamlineTrackingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkStreamlineTrackingView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkStreamlineTrackingView::OnSelectionChanged( std::vector nodes ) { m_TensorImageNodes.clear(); m_TensorImages.clear(); m_SeedRoi = NULL; m_MaskImage = NULL; m_Controls->m_TensorImageLabel->setText("mandatory"); m_Controls->m_RoiImageLabel->setText("optional"); m_Controls->m_MaskImageLabel->setText("optional"); for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { if( dynamic_cast(node->GetData()) ) { m_TensorImageNodes.push_back(node); m_TensorImages.push_back(dynamic_cast(node->GetData())); } else { bool isBinary = false; node->GetPropertyValue("binary", isBinary); if (isBinary && m_SeedRoi.IsNull()) { m_SeedRoi = dynamic_cast(node->GetData()); m_Controls->m_RoiImageLabel->setText(node->GetName().c_str()); } else if (isBinary) { m_MaskImage = dynamic_cast(node->GetData()); m_Controls->m_MaskImageLabel->setText(node->GetName().c_str()); } } } } if(!m_TensorImageNodes.empty()) { if (m_TensorImageNodes.size()>1) m_Controls->m_TensorImageLabel->setText(m_TensorImageNodes.size()+" tensor images selected"); else m_Controls->m_TensorImageLabel->setText(m_TensorImageNodes.at(0)->GetName().c_str()); m_Controls->m_InputData->setTitle("Input Data"); m_Controls->commandLinkButton->setEnabled(true); } else { m_Controls->m_InputData->setTitle("Please Select Input Data"); m_Controls->commandLinkButton->setEnabled(false); } } void QmitkStreamlineTrackingView::DoFiberTracking() { if (m_TensorImages.empty()) return; typedef itk::Image< itk::DiffusionTensor3D, 3> TensorImageType; typedef mitk::ImageToItk CastType; typedef mitk::ImageToItk CastType2; typedef itk::StreamlineTrackingFilter< float > FilterType; FilterType::Pointer filter = FilterType::New(); for (int i=0; i<(int)m_TensorImages.size(); i++) { CastType::Pointer caster = CastType::New(); caster->SetInput(m_TensorImages.at(i)); caster->Update(); filter->SetInput(i, caster->GetOutput()); } if (m_Controls->m_UseFaImage->isChecked()) { mitk::ImageToItk::Pointer floatCast = mitk::ImageToItk::New(); floatCast->SetInput(dynamic_cast(m_Controls->m_FaImageBox->GetSelectedNode()->GetData())); floatCast->Update(); filter->SetFaImage(floatCast->GetOutput()); } //filter->SetNumberOfThreads(1); filter->SetSeedsPerVoxel(m_Controls->m_SeedsPerVoxelSlider->value()); filter->SetFaThreshold((float)m_Controls->m_FaThresholdSlider->value()/100); filter->SetMinCurvatureRadius((float)m_Controls->m_AngularThresholdSlider->value()/10); filter->SetStepSize((float)m_Controls->m_StepsizeSlider->value()/10); filter->SetF((float)m_Controls->m_fSlider->value()/100); filter->SetG((float)m_Controls->m_gSlider->value()/100); filter->SetInterpolate(m_Controls->m_InterpolationBox->isChecked()); filter->SetMinTractLength(m_Controls->m_MinTractLengthSlider->value()); if (m_SeedRoi.IsNotNull()) { ItkUCharImageType::Pointer mask = ItkUCharImageType::New(); mitk::CastToItkImage(m_SeedRoi, mask); filter->SetSeedImage(mask); } if (m_MaskImage.IsNotNull()) { ItkUCharImageType::Pointer mask = ItkUCharImageType::New(); mitk::CastToItkImage(m_MaskImage, mask); filter->SetMaskImage(mask); } filter->Update(); vtkSmartPointer fiberBundle = filter->GetFiberPolyData(); if ( fiberBundle->GetNumberOfLines()==0 ) { QMessageBox warnBox; warnBox.setWindowTitle("Warning"); warnBox.setText("No fiberbundle was generated!"); warnBox.setDetailedText("No fibers were generated using the parameters: \n\n" + m_Controls->m_FaThresholdLabel->text() + "\n" + m_Controls->m_AngularThresholdLabel->text() + "\n" + m_Controls->m_fLabel->text() + "\n" + m_Controls->m_gLabel->text() + "\n" + m_Controls->m_StepsizeLabel->text() + "\n" + m_Controls->m_MinTractLengthLabel->text() + "\n" + m_Controls->m_SeedsPerVoxelLabel->text() + "\n\nPlease check your parametersettings."); warnBox.setIcon(QMessageBox::Warning); warnBox.exec(); return; } - mitk::FiberBundleX::Pointer fib = mitk::FiberBundleX::New(fiberBundle); + mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(fiberBundle); fib->SetReferenceGeometry(dynamic_cast(m_TensorImageNodes.at(0)->GetData())->GetGeometry()); if (m_Controls->m_ResampleFibersBox->isChecked()) fib->Compress(m_Controls->m_FiberErrorBox->value()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(fib); QString name("FiberBundle_"); name += m_TensorImageNodes.at(0)->GetName().c_str(); name += "_Streamline"; node->SetName(name.toStdString()); node->SetVisibility(true); GetDataStorage()->Add(node, m_TensorImageNodes.at(0)); } 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 7de3c7fdef..efc75ed8e0 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.cpp @@ -1,1137 +1,1137 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Qmitk #include "QmitkTractbasedSpatialStatisticsView.h" #include "QmitkStdMultiWidget.h" #include "mitkDataNodeObject.h" #include // Qt #include #include #include #include #include #include #include #include #include "vtkPoints.h" #include #include const std::string QmitkTractbasedSpatialStatisticsView::VIEW_ID = "org.mitk.views.tractbasedspatialstatistics"; using namespace berry; QmitkTractbasedSpatialStatisticsView::QmitkTractbasedSpatialStatisticsView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) { } QmitkTractbasedSpatialStatisticsView::~QmitkTractbasedSpatialStatisticsView() { } void QmitkTractbasedSpatialStatisticsView::PerformChange() { m_Controls->m_RoiPlotWidget->ModifyPlot(m_Controls->m_Segments->value(), m_Controls->m_Average->isChecked()); } void QmitkTractbasedSpatialStatisticsView::OnSelectionChanged(std::vector nodes) { //datamanager selection changed if (!this->IsActivated()) return; // Check which datatypes are selected in the datamanager and enable/disable widgets accordingly bool foundTbssRoi = false; bool foundTbss = false; bool found3dImage = false; bool found4dImage = false; bool foundFiberBundle = false; bool foundStartRoi = false; bool foundEndRoi = false; mitk::TbssRoiImage* roiImage; mitk::TbssImage* image; mitk::Image* img; - mitk::FiberBundleX* fib; + mitk::FiberBundle* fib; mitk::PlanarFigure* start; mitk::PlanarFigure* end; m_CurrentStartRoi = NULL; m_CurrentEndRoi = NULL; for ( int i=0; iGetData(); if( nodeData ) { if(QString("TbssRoiImage").compare(nodeData->GetNameOfClass())==0) { foundTbssRoi = true; roiImage = static_cast(nodeData); } else if (QString("TbssImage").compare(nodeData->GetNameOfClass())==0) { 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(nodeData->GetNameOfClass())==0) + else if (QString("FiberBundle").compare(nodeData->GetNameOfClass())==0) { foundFiberBundle = true; - fib = static_cast(nodeData); + fib = static_cast(nodeData); this->m_CurrentFiberNode = nodes[i]; } if(QString("PlanarCircle").compare(nodeData->GetNameOfClass())==0) { if(!foundStartRoi) { start = dynamic_cast(nodeData); this->m_CurrentStartRoi = nodes[i]; foundStartRoi = true; } else { end = dynamic_cast(nodeData); this->m_CurrentEndRoi = nodes[i]; foundEndRoi = true; } } } } this->m_Controls->m_CreateRoi->setEnabled(found3dImage); this->m_Controls->m_ImportFsl->setEnabled(found4dImage); if(foundTbss && foundTbssRoi) { this->Plot(image, roiImage); } else if(found3dImage && foundFiberBundle && foundStartRoi && foundEndRoi) { this->PlotFiberBundle(fib, img, start, end); } else if(found3dImage && foundFiberBundle) { this->PlotFiberBundle(fib, img); } else if(foundTbss && foundStartRoi && foundEndRoi && foundFiberBundle) { this->PlotFiber4D(image, fib, start, end); } if(found3dImage) { this->InitPointsets(); } this->m_Controls->m_Cut->setEnabled(foundFiberBundle && foundStartRoi && foundEndRoi); this->m_Controls->m_SegmentLabel->setEnabled(foundFiberBundle && foundStartRoi && foundEndRoi && (found3dImage || foundTbss)); this->m_Controls->m_Segments->setEnabled(foundFiberBundle && foundStartRoi && foundEndRoi && (found3dImage || foundTbss)); this->m_Controls->m_Average->setEnabled(foundFiberBundle && foundStartRoi && foundEndRoi && found3dImage); } 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(true) ); // 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(); } // Table for the FSL TBSS import m_GroupModel = new QmitkTbssTableModel(); m_Controls->m_GroupInfo->setModel(m_GroupModel); } void QmitkTractbasedSpatialStatisticsView::Activated() { QmitkFunctionality::Activated(); } 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 QPointF&)), SLOT(Clicked(const QPointF&) ) ); connect( m_Controls->m_RoiPlotWidget->m_PlotPicker, SIGNAL(moved(const QPointF&)), SLOT(Clicked(const QPointF&) ) ); connect( (QObject*)(m_Controls->m_Cut), SIGNAL(clicked()), this, SLOT(Cut()) ); connect( (QObject*)(m_Controls->m_Average), SIGNAL(stateChanged(int)), this, SLOT(PerformChange()) ); connect( (QObject*)(m_Controls->m_Segments), SIGNAL(valueChanged(int)), this, SLOT(PerformChange()) ); } } void QmitkTractbasedSpatialStatisticsView::CopyToClipboard() { if(m_Controls->m_RoiPlotWidget->IsPlottingFiber()) { // Working with fiber bundles std::vector > profiles = m_Controls->m_RoiPlotWidget->GetIndividualProfiles(); QString clipboardText; for (std::vector >::iterator it = profiles.begin(); it != profiles.end(); ++it) { for (std::vector::iterator it2 = (*it).begin(); it2 != (*it).end(); ++it2) { clipboardText.append(QString("%1 \t").arg(*it2)); } clipboardText.append(QString("\n")); } if(m_Controls->m_Average->isChecked()) { std::vector averages = m_Controls->m_RoiPlotWidget->GetAverageProfile(); clipboardText.append(QString("\nAverage\n")); for (std::vector::iterator it2 = averages.begin(); it2 != averages.end(); ++it2) { clipboardText.append(QString("%1 \t").arg(*it2)); } } QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard); } else{ // Working with TBSS Data if(m_Controls->m_Average->isChecked()) { 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); } else { std::vector > vals = m_Controls->m_RoiPlotWidget->GetIndividualProfiles(); 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); QItemSelectionModel *selectionModel = temp->selectionModel(); QModelIndexList indices = selectionModel->selectedRows(); QModelIndex index; foreach(index, indices) { int row = index.row(); m_GroupModel->removeRows(row, 1, QModelIndex()); } } 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); } } 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 = ""; std::vector nodes = this->GetDataManagerSelection(); for ( int i=0; iGetData()->GetNameOfClass())==0) { mitk::Image* img = static_cast(nodes[i]->GetData()); if(img->GetDimension() == 4) { importer->SetImportVolume(img); name = nodes[i]->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 QPointF& pos) { int index = (int)pos.x(); if(m_Roi.size() > 0 && m_CurrentGeometry != NULL && !m_Controls->m_RoiPlotWidget->IsPlottingFiber() ) { index = std::min( (int)m_Roi.size()-1, std::max(0, index) ); 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); } else if(m_Controls->m_RoiPlotWidget->IsPlottingFiber() ) { mitk::Point3D point = m_Controls->m_RoiPlotWidget->GetPositionInWorld(index); m_MultiWidget->MoveCrossToPosition(point); } } void QmitkTractbasedSpatialStatisticsView::Cut() { mitk::BaseData* fibData = m_CurrentFiberNode->GetData(); - mitk::FiberBundleX* fib = static_cast(fibData); + mitk::FiberBundle* fib = static_cast(fibData); mitk::BaseData* startData = m_CurrentStartRoi->GetData(); mitk::PlanarFigure* startRoi = static_cast(startData); mitk::PlaneGeometry* startGeometry2D = const_cast(startRoi->GetPlaneGeometry()); mitk::BaseData* endData = m_CurrentEndRoi->GetData(); mitk::PlanarFigure* endRoi = static_cast(endData); mitk::PlaneGeometry* endGeometry2D = const_cast(endRoi->GetPlaneGeometry()); mitk::Point3D startCenter = startRoi->GetWorldControlPoint(0); //center Point of start roi mitk::Point3D endCenter = endRoi->GetWorldControlPoint(0); //center Point of end roi - mitk::FiberBundleX::Pointer inStart = fib->ExtractFiberSubset(startRoi); - mitk::FiberBundleX::Pointer inBoth = inStart->ExtractFiberSubset(endRoi); + mitk::FiberBundle::Pointer inStart = fib->ExtractFiberSubset(startRoi); + mitk::FiberBundle::Pointer inBoth = inStart->ExtractFiberSubset(endRoi); int num = inBoth->GetNumFibers(); vtkSmartPointer fiberPolyData = inBoth->GetFiberPolyData(); vtkCellArray* lines = fiberPolyData->GetLines(); lines->InitTraversal(); // initialize new vtk polydata vtkSmartPointer points = vtkSmartPointer::New(); vtkSmartPointer polyData = vtkSmartPointer::New(); vtkSmartPointer cells = vtkSmartPointer::New(); int pointIndex=0; // find start and endpoint for( int fiberID( 0 ); fiberID < num; fiberID++ ) { vtkIdType numPointsInCell(0); vtkIdType* pointsInCell(NULL); lines->GetNextCell ( numPointsInCell, pointsInCell ); int startId = 0; int endId = 0; float minDistStart = std::numeric_limits::max(); float minDistEnd = std::numeric_limits::max(); vtkSmartPointer polyLine = vtkSmartPointer::New(); int lineIndex=0; for( int pointInCellID( 0 ); pointInCellID < numPointsInCell ; pointInCellID++) { double *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] ); mitk::Point3D point; point[0] = p[0]; point[1] = p[1]; point[2] = p[2]; float distanceToStart = point.EuclideanDistanceTo(startCenter); float distanceToEnd = point.EuclideanDistanceTo(endCenter); if(distanceToStart < minDistStart) { minDistStart = distanceToStart; startId = pointInCellID; } if(distanceToEnd < minDistEnd) { minDistEnd = distanceToEnd; endId = pointInCellID; } } /* We found the start and end points of of the part that should be plottet for the current fiber. now we need to plot them. If the endId is smaller than the startId the plot order must be reversed*/ if(startId < endId) { double *p = fiberPolyData->GetPoint( pointsInCell[ startId ] ); mitk::Vector3D p0; p0[0] = p[0]; p0[1] = p[1]; p0[2] = p[2]; p = fiberPolyData->GetPoint( pointsInCell[ startId+1 ] ); mitk::Vector3D p1; p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2]; // Check if p and p2 are both on the same side of the plane mitk::Vector3D normal = startGeometry2D->GetNormal(); mitk::Point3D pStart; pStart[0] = p0[0]; pStart[1] = p0[1]; pStart[2] = p0[2]; bool startOnPositive = startGeometry2D->IsAbove(pStart); mitk::Point3D pSecond; pSecond[0] = p1[0]; pSecond[1] = p1[1]; pSecond[2] = p1[2]; bool secondOnPositive = startGeometry2D->IsAbove(pSecond); // Calculate intersection with the plane mitk::Vector3D onPlane; onPlane[0] = startCenter[0]; onPlane[1] = startCenter[1]; onPlane[2] = startCenter[2]; if(! (secondOnPositive ^ startOnPositive) ) { /* startId and startId+1 lie on the same side of the plane, so we need need startId-1 to calculate the intersection with the planar figure*/ p = fiberPolyData->GetPoint( pointsInCell[ startId-1 ] ); p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2]; } double d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal ); mitk::Vector3D newPoint = (p0-p1); newPoint[0] = d*newPoint[0] + p0[0]; newPoint[1] = d*newPoint[1] + p0[1]; newPoint[2] = d*newPoint[2] + p0[2]; double insertPoint[3]; insertPoint[0] = newPoint[0]; insertPoint[1] = newPoint[1]; insertPoint[2] = newPoint[2]; // First insert the intersection with the start roi points->InsertNextPoint(insertPoint); polyLine->GetPointIds()->InsertId(lineIndex,pointIndex); lineIndex++; pointIndex++; if(! (secondOnPositive ^ startOnPositive) ) { /* StartId and startId+1 lie on the same side of the plane so startId is also part of the ROI*/ double *start = fiberPolyData->GetPoint( pointsInCell[startId] ); points->InsertNextPoint(start); polyLine->GetPointIds()->InsertId(lineIndex,pointIndex); lineIndex++; pointIndex++; } // Insert the rest up and to including endId-1 for( int pointInCellID( startId+1 ); pointInCellID < endId ; pointInCellID++) { // create new polyline for new polydata double *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] ); points->InsertNextPoint(p); // add point to line polyLine->GetPointIds()->InsertId(lineIndex,pointIndex); lineIndex++; pointIndex++; } /* endId must be included if endId and endId-1 lie on the same side of the plane defined by endRoi*/ p = fiberPolyData->GetPoint( pointsInCell[ endId ] ); p0[0] = p[0]; p0[1] = p[1]; p0[2] = p[2]; p = fiberPolyData->GetPoint( pointsInCell[ endId-1 ] ); p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2]; mitk::Point3D pLast; pLast[0] = p0[0]; pLast[1] = p0[1]; pLast[2] = p0[2]; mitk::Point3D pBeforeLast; pBeforeLast[0] = p1[0]; pBeforeLast[1] = p1[1]; pBeforeLast[2] = p1[2]; bool lastOnPositive = endGeometry2D->IsAbove(pLast); bool secondLastOnPositive = endGeometry2D->IsAbove(pBeforeLast); normal = endGeometry2D->GetNormal(); onPlane[0] = endCenter[0]; onPlane[1] = endCenter[1]; onPlane[2] = endCenter[2]; if(! (lastOnPositive ^ secondLastOnPositive) ) { /* endId and endId-1 lie on the same side of the plane, so we need need endId+1 to calculate the intersection with the planar figure. this should exist since we know that the fiber crosses the planar figure endId is part of the roi so can also be included here*/ p = fiberPolyData->GetPoint( pointsInCell[ endId+1 ] ); p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2]; double *end = fiberPolyData->GetPoint( pointsInCell[endId] ); points->InsertNextPoint(end); polyLine->GetPointIds()->InsertId(lineIndex,pointIndex); lineIndex++; pointIndex++; } d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal ); newPoint = (p0-p1); newPoint[0] = d*newPoint[0] + p0[0]; newPoint[1] = d*newPoint[1] + p0[1]; newPoint[2] = d*newPoint[2] + p0[2]; insertPoint[0] = newPoint[0]; insertPoint[1] = newPoint[1]; insertPoint[2] = newPoint[2]; //Insert the Last Point (intersection with the end roi) points->InsertNextPoint(insertPoint); polyLine->GetPointIds()->InsertId(lineIndex,pointIndex); lineIndex++; pointIndex++; } // Need to reverse walking order else{ double *p = fiberPolyData->GetPoint( pointsInCell[ startId ] ); mitk::Vector3D p0; p0[0] = p[0]; p0[1] = p[1]; p0[2] = p[2]; p = fiberPolyData->GetPoint( pointsInCell[ startId-1 ] ); mitk::Vector3D p1; p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2]; // Check if p and p2 are both on the same side of the plane mitk::Vector3D normal = startGeometry2D->GetNormal(); mitk::Point3D pStart; pStart[0] = p0[0]; pStart[1] = p0[1]; pStart[2] = p0[2]; bool startOnPositive = startGeometry2D->IsAbove(pStart); mitk::Point3D pSecond; pSecond[0] = p1[0]; pSecond[1] = p1[1]; pSecond[2] = p1[2]; bool secondOnPositive = startGeometry2D->IsAbove(pSecond); // Calculate intersection with the plane mitk::Vector3D onPlane; onPlane[0] = startCenter[0]; onPlane[1] = startCenter[1]; onPlane[2] = startCenter[2]; if(! (secondOnPositive ^ startOnPositive) ) { /* startId and startId-1 lie on the same side of the plane, so we need need startId+1 to calculate the intersection with the planar figure*/ p = fiberPolyData->GetPoint( pointsInCell[ startId+1 ] ); p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2]; } double d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal ); mitk::Vector3D newPoint = (p0-p1); newPoint[0] = d*newPoint[0] + p0[0]; newPoint[1] = d*newPoint[1] + p0[1]; newPoint[2] = d*newPoint[2] + p0[2]; double insertPoint[3]; insertPoint[0] = newPoint[0]; insertPoint[1] = newPoint[1]; insertPoint[2] = newPoint[2]; // First insert the intersection with the start roi points->InsertNextPoint(insertPoint); polyLine->GetPointIds()->InsertId(lineIndex,pointIndex); lineIndex++; pointIndex++; if(! (secondOnPositive ^ startOnPositive) ) { /* startId and startId-1 lie on the same side of the plane so endId is also part of the ROI*/ double *start = fiberPolyData->GetPoint( pointsInCell[startId] ); points->InsertNextPoint(start); polyLine->GetPointIds()->InsertId(lineIndex,pointIndex); lineIndex++; pointIndex++; } // Insert the rest up and to including endId-1 for( int pointInCellID( startId-1 ); pointInCellID > endId ; pointInCellID--) { // create new polyline for new polydata double *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] ); points->InsertNextPoint(p); // add point to line polyLine->GetPointIds()->InsertId(lineIndex,pointIndex); lineIndex++; pointIndex++; } /* startId must be included if startId and startId+ lie on the same side of the plane defined by endRoi*/ p = fiberPolyData->GetPoint( pointsInCell[ endId ] ); p0[0] = p[0]; p0[1] = p[1]; p0[2] = p[2]; p = fiberPolyData->GetPoint( pointsInCell[ endId+1 ] ); p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2]; mitk::Point3D pLast; pLast[0] = p0[0]; pLast[1] = p0[1]; pLast[2] = p0[2]; bool lastOnPositive = endGeometry2D->IsAbove(pLast); mitk::Point3D pBeforeLast; pBeforeLast[0] = p1[0]; pBeforeLast[1] = p1[1]; pBeforeLast[2] = p1[2]; bool secondLastOnPositive = endGeometry2D->IsAbove(pBeforeLast); onPlane[0] = endCenter[0]; onPlane[1] = endCenter[1]; onPlane[2] = endCenter[2]; if(! (lastOnPositive ^ secondLastOnPositive) ) { /* endId and endId+1 lie on the same side of the plane, so we need need endId-1 to calculate the intersection with the planar figure. this should exist since we know that the fiber crosses the planar figure*/ p = fiberPolyData->GetPoint( pointsInCell[ endId-1 ] ); p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2]; /* endId and endId+1 lie on the same side of the plane so startId is also part of the ROI*/ double *end = fiberPolyData->GetPoint( pointsInCell[endId] ); points->InsertNextPoint(end); polyLine->GetPointIds()->InsertId(lineIndex,pointIndex); lineIndex++; pointIndex++; } d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal ); newPoint = (p0-p1); newPoint[0] = d*newPoint[0] + p0[0]; newPoint[1] = d*newPoint[1] + p0[1]; newPoint[2] = d*newPoint[2] + p0[2]; insertPoint[0] = newPoint[0]; insertPoint[1] = newPoint[1]; insertPoint[2] = newPoint[2]; //Insert the Last Point (intersection with the end roi) points->InsertNextPoint(insertPoint); polyLine->GetPointIds()->InsertId(lineIndex,pointIndex); lineIndex++; pointIndex++; } // add polyline to vtk cell array cells->InsertNextCell(polyLine); } // Add the points to the dataset polyData->SetPoints(points); // Add the lines to the dataset polyData->SetLines(cells); - mitk::FiberBundleX::Pointer cutBundle = mitk::FiberBundleX::New(polyData); + mitk::FiberBundle::Pointer cutBundle = mitk::FiberBundle::New(polyData); mitk::DataNode::Pointer cutNode = mitk::DataNode::New(); cutNode->SetData(cutBundle); std::string name = "fiberCut"; cutNode->SetName(name); GetDataStorage()->Add(cutNode); } void QmitkTractbasedSpatialStatisticsView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkTractbasedSpatialStatisticsView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkTractbasedSpatialStatisticsView::CreateRoi() { bool ok; double threshold = QInputDialog::getDouble(m_Controls->m_CreateRoi, tr("Set an FA threshold"), tr("Threshold:"), 0.2, 0.0, 1.0, 2, &ok); if(!ok) return; mitk::Image::Pointer image; std::vector nodes = this->GetDataManagerSelection(); for ( int i=0; iGetData()->GetNameOfClass())==0) { mitk::Image* img = static_cast(nodes[i]->GetData()); if(img->GetDimension() == 3) { image = img; } } } if(image.IsNull()) { return; } mitk::TractAnalyzer analyzer; analyzer.SetInputImage(image); analyzer.SetThreshold(threshold); m_PointSetNode = this->m_Controls->m_PointWidget->GetPointSet(); // Set Pointset to analyzer analyzer.SetPointSet(m_PointSetNode); // Run Analyzer try { analyzer.MakeRoi(); } catch (const mitk::Exception& e) { QMessageBox msgBox; msgBox.setText(QString::fromStdString(e.what())); msgBox.exec(); } // Obtain tbss roi image from analyzer mitk::TbssRoiImage::Pointer tbssRoi = analyzer.GetRoiImage(); tbssRoi->SetStructure(m_Controls->m_Structure->text().toStdString()); // get path description and set to interface std::string pathDescription = analyzer.GetPathDescription(); m_Controls->m_PathTextEdit->setPlainText(QString(pathDescription.c_str())); // Add roi image to datastorage AddTbssToDataStorage(tbssRoi, m_Controls->m_RoiName->text().toStdString()); } void QmitkTractbasedSpatialStatisticsView::PlotFiber4D(mitk::TbssImage* image, - mitk::FiberBundleX* fib, + mitk::FiberBundle* fib, mitk::PlanarFigure* startRoi, mitk::PlanarFigure* endRoi) { if(m_Controls->m_TabWidget->currentWidget() == m_Controls->m_MeasureTAB) { m_CurrentGeometry = image->GetGeometry(); m_Controls->m_RoiPlotWidget->SetGroups(image->GetGroupInfo()); m_Controls->m_RoiPlotWidget->SetProjections(image->GetImage()); m_Controls->m_RoiPlotWidget->SetMeasure( image->GetMeasurementInfo() ); m_Controls->m_RoiPlotWidget->PlotFiber4D(image, fib, startRoi, endRoi, m_Controls->m_Segments->value()); } } -void QmitkTractbasedSpatialStatisticsView:: PlotFiberBundle(mitk::FiberBundleX *fib, mitk::Image* img, +void QmitkTractbasedSpatialStatisticsView:: PlotFiberBundle(mitk::FiberBundle *fib, mitk::Image* img, mitk::PlanarFigure* startRoi, mitk::PlanarFigure* endRoi) { bool avg = m_Controls->m_Average->isChecked(); int segments = m_Controls->m_Segments->value(); m_Controls->m_RoiPlotWidget->PlotFiberBetweenRois(fib, img, startRoi ,endRoi, avg, segments); m_Controls->m_RoiPlotWidget->SetPlottingFiber(true); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); } 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 structure = roiImage->GetStructure(); m_Controls->m_RoiPlotWidget->SetGroups(image->GetGroupInfo()); 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(); } m_Controls->m_RoiPlotWidget->SetPlottingFiber(false); } 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 e2ff1abc48..bd78730a44 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTractbasedSpatialStatisticsView.h @@ -1,178 +1,177 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkTractbasedSpatialStatisticsView_h #define QmitkTractbasedSpatialStatisticsView_h #include #include "ui_QmitkTractbasedSpatialStatisticsViewControls.h" #include #include #include -#include #include #include #include #include "QmitkTbssTableModel.h" #include "QmitkTbssMetaTableModel.h" -#include +#include // Image types typedef short DiffusionPixelType; typedef itk::Image CharImageType; typedef itk::Image UCharImageType; typedef itk::Image Float4DImageType; typedef itk::Image FloatImageType; typedef itk::VectorImage VectorImageType; // Readers/Writers 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; /*! * \brief This plugin provides an extension for Tract-based spatial statistics (see Smith et al., 2009. http://dx.doi.org/10.1016/j.neuroimage.2006.02.024) * TBSS enables analyzing the brain by a pipeline of registration, skeletonization, and projection that results in a white matter skeleton * for all subjects that are analyzed statistically in a whole-brain manner. * This plugin provides functionality to select single tracts and analyze them separately. * * Prerequisites: the mean_FA_skeleton and all_FA_skeletonised datasets produced by the FSL TBSS pipeline: http://fsl.fmrib.ox.ac.uk/fsl/fsl4.0/tbss/index */ class QmitkTractbasedSpatialStatisticsView : public QmitkFunctionality { 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: // Creates Roi void CreateRoi(); void Clicked(const QPointF& pos); // Import of FSL TBSS data void TbssImport(); // Add a group as metadata. This metadata is required by the plotting functionality void AddGroup(); // Remove a group void RemoveGroup(); // Copies the values displayed in the plot widget to clipboard, i.e. exports the data void CopyToClipboard(); // Method to cut away parts of fiber bundles that should not be plotted. void Cut(); // Adjust plot widget void PerformChange(); protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); // Creates a plot using a 4D image containing the projections of all subjects and a region of interest void Plot(mitk::TbssImage*, mitk::TbssRoiImage*); - void PlotFiberBundle(mitk::FiberBundleX* fib, mitk::Image* img, mitk::PlanarFigure* startRoi=NULL, mitk::PlanarFigure* endRoi=NULL); + void PlotFiberBundle(mitk::FiberBundle* fib, mitk::Image* img, mitk::PlanarFigure* startRoi=NULL, mitk::PlanarFigure* endRoi=NULL); - void PlotFiber4D(mitk::TbssImage*, mitk::FiberBundleX* fib, mitk::PlanarFigure* startRoi=NULL, mitk::PlanarFigure* endRoi=NULL); + void PlotFiber4D(mitk::TbssImage*, mitk::FiberBundle* fib, mitk::PlanarFigure* startRoi=NULL, mitk::PlanarFigure* endRoi=NULL); // Create a point set. This point set defines the points through which a region of interest should go void InitPointsets(); // Pointset and DataNode to contain the PointSet used in ROI creation mitk::PointSet::Pointer m_PointSetNode; mitk::DataNode::Pointer m_P1; // GUI widgets Ui::QmitkTractbasedSpatialStatisticsViewControls* m_Controls; /* A pointer to the QmitkStdMultiWidget. Used for interaction with the plot widget (clicking in the plot widget makes the image cross jump to the corresponding location on the skeleton).*/ QmitkStdMultiWidget* m_MultiWidget; // Used to save the region of interest in a vector of itk::index. std::vector< itk::Index<3> > m_Roi; - mitk::FiberBundleX* m_Fib; + mitk::FiberBundle* m_Fib; mitk::BaseGeometry* m_CurrentGeometry; // A table model for saving group information in a name,number pair. QmitkTbssTableModel* m_GroupModel; // Convenience function for adding a new image to the datastorage and giving it a name. void AddTbssToDataStorage(mitk::Image* image, std::string name); mitk::DataNode::Pointer m_CurrentFiberNode; // needed for the index property when interacting with the plot widget // needed when a plot should only show values between a start end end roi mitk::DataNode::Pointer m_CurrentStartRoi; mitk::DataNode::Pointer m_CurrentEndRoi; }; #endif // _QMITKTRACTBASEDSPATIALSTATISTICSVIEW_H_INCLUDED 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 e4afa76043..f527d82203 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppIntroPart.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppIntroPart.cpp @@ -1,215 +1,212 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkDiffusionImagingAppIntroPart.h" #include "mitkNodePredicateDataType.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) # include #endif #include #include #include #include #include #include #include "QmitkDiffusionApplicationPlugin.h" #include "mitkDataStorageEditorInput.h" #include -#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 = 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 = QmitkDiffusionApplicationPlugin::GetDefault()->GetPreferencesService()->GetSystemPreferences(); workbenchPrefs->PutBool(berry::WorkbenchPreferenceConstants::SHOW_INTRO, false); workbenchPrefs->Flush(); } else { 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.perspectives.diffusiondefault"); 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); // 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(); } } 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(); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) QByteArray urlHostname = showMeNext.encodedHost(); QByteArray urlPath = showMeNext.encodedPath(); QByteArray dataset = showMeNext.encodedQueryItemValue("dataset"); QByteArray clear = showMeNext.encodedQueryItemValue("clear"); #else QByteArray urlHostname = QUrl::toAce(showMeNext.host()); QByteArray urlPath = showMeNext.path().toLatin1(); QUrlQuery query(showMeNext); QByteArray dataset = query.queryItemValue("dataset").toLatin1(); QByteArray clear = query.queryItemValue("clear").toLatin1();//showMeNext.encodedQueryItemValue("clear"); #endif 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() ); // search the Workbench for opened StdMultiWidgets to ensure the focus does not stay on the welcome screen and is switched to // an StdMultiWidget if one available mitk::IDataStorageService::Pointer service = berry::Platform::GetServiceRegistry().GetServiceById(mitk::IDataStorageService::ID); berry::IEditorInput::Pointer editorInput; editorInput = new mitk::DataStorageEditorInput( service->GetActiveDataStorage() ); // the solution is not clean, but the dependency to the StdMultiWidget was removed in order to fix a crash problem // as described in Bug #11715 // This is the correct way : use the static string ID variable // berry::IEditorPart::Pointer editor = GetIntroSite()->GetPage()->FindEditors( editorInput, QmitkStdMultiWidgetEditor::EDITOR_ID ); // QuickFix: we use the same string for an local variable const std::string stdEditorID = "org.mitk.editors.stdmultiwidget"; // search for opened StdMultiWidgetEditors std::vector editorList = GetIntroSite()->GetPage()->FindEditors( editorInput, stdEditorID, 1 ); // if an StdMultiWidgetEditor open was found, give focus to it if(editorList.size()) { GetIntroSite()->GetPage()->Activate( editorList[0]->GetPart(true) ); } } } // 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); } } void QmitkDiffusionImagingAppIntroPart::StandbyStateChanged(bool) { } void QmitkDiffusionImagingAppIntroPart::SetFocus() { } diff --git a/Plugins/org.mitk.gui.qt.dtiatlasapp/src/internal/QmitkDTIAtlasAppIntroPart.cpp b/Plugins/org.mitk.gui.qt.dtiatlasapp/src/internal/QmitkDTIAtlasAppIntroPart.cpp index c4406ff44d..4bf921972b 100644 --- a/Plugins/org.mitk.gui.qt.dtiatlasapp/src/internal/QmitkDTIAtlasAppIntroPart.cpp +++ b/Plugins/org.mitk.gui.qt.dtiatlasapp/src/internal/QmitkDTIAtlasAppIntroPart.cpp @@ -1,304 +1,285 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkDTIAtlasAppIntroPart.h" #include "mitkNodePredicateDataType.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef QT_WEBKIT # include # include # if QT_VERSION >= QT_VERSION_CHECK(5,0,0) # include # endif #endif #include #include #include #include #include #include #include "QmitkStdMultiWidget.h" #include "QmitkStdMultiWidgetEditor.h" #include "QmitkDTIAtlasAppApplicationPlugin.h" #include "mitkDataStorageEditorInput.h" -#include "mitkBaseDataIOFactory.h" +#include #include "mitkSceneIO.h" #include "mitkProgressBar.h" -#include "mitkDataNodeFactory.h" #include "mitkNodePredicateNot.h" #include "mitkNodePredicateProperty.h" QmitkDTIAtlasAppIntroPart::QmitkDTIAtlasAppIntroPart() : m_Controls(NULL) { berry::IPreferences::Pointer workbenchPrefs = QmitkDTIAtlasAppApplicationPlugin::GetDefault()->GetPreferencesService()->GetSystemPreferences(); workbenchPrefs->PutBool(berry::WorkbenchPreferenceConstants::SHOW_INTRO, true); workbenchPrefs->Flush(); } QmitkDTIAtlasAppIntroPart::~QmitkDTIAtlasAppIntroPart() { // 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 = QmitkDTIAtlasAppApplicationPlugin::GetDefault()->GetPreferencesService()->GetSystemPreferences(); workbenchPrefs->PutBool(berry::WorkbenchPreferenceConstants::SHOW_INTRO, false); workbenchPrefs->Flush(); } else { berry::IPreferences::Pointer workbenchPrefs = QmitkDTIAtlasAppApplicationPlugin::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.dtiatlasapp.perspectives.welcome" && !this->GetIntroSite()->GetPage()->GetWorkbenchWindow()->GetWorkbench()->IsClosing()) { berry::IPerspectiveDescriptor::Pointer perspective = this->GetIntroSite()->GetWorkbenchWindow()->GetWorkbench()->GetPerspectiveRegistry()->FindPerspectiveWithId("org.mitk.dtiatlasapp.perspectives.dtiatlasapp"); if (perspective) { this->GetIntroSite()->GetPage()->SetPerspective(perspective); } } } void QmitkDTIAtlasAppIntroPart::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/mitkdtiatlasappwelcomeview.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 } } +#define QT_WEBKIT #ifdef QT_WEBKIT void QmitkDTIAtlasAppIntroPart::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_view->page()), SIGNAL(linkClicked(const QUrl& )), this, SLOT(DelegateMeTo(const QUrl& )) ); } } void QmitkDTIAtlasAppIntroPart::DelegateMeTo(const QUrl& showMeNext) { QString scheme = showMeNext.scheme(); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) QByteArray urlHostname = showMeNext.encodedHost(); QByteArray urlPath = showMeNext.encodedPath(); QByteArray dataset = showMeNext.encodedQueryItemValue("dataset"); QByteArray clear = showMeNext.encodedQueryItemValue("clear"); #else QByteArray urlHostname = QUrl::toAce(showMeNext.host()); QByteArray urlPath = showMeNext.path().toLatin1(); QUrlQuery query(showMeNext); QByteArray dataset = query.queryItemValue("dataset").toLatin1(); QByteArray clear = query.queryItemValue("clear").toLatin1();//showMeNext.encodedQueryItemValue("clear"); #endif 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; QString *fileName = new QString(dataset.data()); if ( fileName->right(5) == ".mitk" ) { mitk::SceneIO::Pointer sceneIO = mitk::SceneIO::New(); bool clearDataStorageFirst(false); QString *sClear = new QString(clear.data()); if ( sClear->right(4) == "true" ) { clearDataStorageFirst = true; } mitk::ProgressBar::GetInstance()->AddStepsToDo(2); dataStorage = sceneIO->LoadScene( fileName->toLocal8Bit().constData(), dataStorage, clearDataStorageFirst ); dsmodified = true; mitk::ProgressBar::GetInstance()->Progress(2); } else { - mitk::DataNodeFactory::Pointer nodeReader = mitk::DataNodeFactory::New(); - try - { - nodeReader->SetFileName(fileName->toLocal8Bit().data()); - nodeReader->Update(); - for ( unsigned int i = 0 ; i < nodeReader->GetNumberOfOutputs( ); ++i ) - { - mitk::DataNode::Pointer node; - node = nodeReader->GetOutput(i); - if ( node->GetData() != NULL ) - { - dataStorage->Add(node); - dsmodified = true; - } - } - } - catch(...) - { - MITK_INFO << "Could not open file!"; - } + mitk::IOUtil::Load(fileName->toStdString(),*(dataStorage.GetPointer())); } 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::TimeGeometry::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 QmitkDTIAtlasAppIntroPart::StandbyStateChanged(bool standby) { } void QmitkDTIAtlasAppIntroPart::SetFocus() { } diff --git a/Plugins/org.mitk.gui.qt.ext/src/QmitkOpenDicomEditorAction.cpp b/Plugins/org.mitk.gui.qt.ext/src/QmitkOpenDicomEditorAction.cpp index 45fe845eb2..930eeeaf90 100644 --- a/Plugins/org.mitk.gui.qt.ext/src/QmitkOpenDicomEditorAction.cpp +++ b/Plugins/org.mitk.gui.qt.ext/src/QmitkOpenDicomEditorAction.cpp @@ -1,114 +1,113 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkOpenDicomEditorAction.h" #include #include -#include #include "mitkCoreObjectFactory.h" #include "mitkSceneIO.h" #include "mitkProgressBar.h" #include #include #include #include #include #include #include #include "mitkProperties.h" #include "mitkNodePredicateData.h" #include "mitkNodePredicateNot.h" #include "mitkNodePredicateProperty.h" //#include QmitkOpenDicomEditorAction::QmitkOpenDicomEditorAction(berry::IWorkbenchWindow::Pointer window) : QAction(0) { this->init(window); } QmitkOpenDicomEditorAction::QmitkOpenDicomEditorAction(const QIcon & icon, berry::IWorkbenchWindow::Pointer window) : QAction(0) { this->setIcon(icon); this->init(window); } void QmitkOpenDicomEditorAction::init(berry::IWorkbenchWindow::Pointer window) { m_Window = window; this->setParent(static_cast(m_Window->GetShell()->GetControl())); this->setText("&DICOM"); this->setToolTip("Open dicom tool"); berry::IPreferencesService::Pointer prefService = berry::Platform::GetServiceRegistry() .GetServiceById(berry::IPreferencesService::ID); m_GeneralPreferencesNode = prefService->GetSystemPreferences()->Node("/General"); this->connect(this, SIGNAL(triggered(bool)), this, SLOT(Run())); } void QmitkOpenDicomEditorAction::Run() { // check if there is an open perspective, if not open the default perspective if (m_Window->GetActivePage().IsNull()) { std::string defaultPerspId = m_Window->GetWorkbench()->GetPerspectiveRegistry()->GetDefaultPerspective(); m_Window->GetWorkbench()->ShowPerspective(defaultPerspId, m_Window); } mitk::DataStorageEditorInput::Pointer editorInput; //mitk::DataStorage::Pointer dataStorage; //QmitkStdMultiWidgetEditor::Pointer multiWidgetEditor; //berry::IEditorPart::Pointer editor = m_Window->GetActivePage()->GetActiveEditor(); //if (editor.Cast().IsNull()) //{ // editorInput = new mitk::DataStorageEditorInput(); // dataStorage = editorInput->GetDataStorageReference()->GetDataStorage(); //} //else //{ // multiWidgetEditor = editor.Cast(); // dataStorage = multiWidgetEditor->GetEditorInput().Cast()->GetDataStorageReference()->GetDataStorage(); //} //if (multiWidgetEditor.IsNull()) //{ // //berry::IEditorPart::Pointer editor = m_Window->GetActivePage()->OpenEditor(editorInput, QmitkStdMultiWidgetEditor::EDITOR_ID); // multiWidgetEditor = editor.Cast(); //} //else //{ // multiWidgetEditor->GetStdMultiWidget()->RequestUpdate(); //} berry::IEditorInput::Pointer editorInput2(new berry::FileEditorInput(Poco::Path())); m_Window->GetActivePage()->OpenEditor(editorInput2, "org.mitk.editors.dicomeditor"); } diff --git a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkCommonExtPlugin.cpp b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkCommonExtPlugin.cpp index b28e27f6f2..16b21d90ae 100644 --- a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkCommonExtPlugin.cpp +++ b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkCommonExtPlugin.cpp @@ -1,259 +1,250 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkCommonExtPlugin.h" #include #include "QmitkAppInstancesPreferencePage.h" #include "QmitkExternalProgramsPreferencePage.h" #include "QmitkInputDevicesPrefPage.h" #include "QmitkModuleView.h" -#include #include #include #include #include #include #include +#include #include #include #include #include #include #include "berryPlatform.h" #include ctkPluginContext* QmitkCommonExtPlugin::_context = 0; void QmitkCommonExtPlugin::start(ctkPluginContext* context) { this->_context = context; QtWidgetsExtRegisterClasses(); BERRY_REGISTER_EXTENSION_CLASS(QmitkAppInstancesPreferencePage, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkExternalProgramsPreferencePage, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkInputDevicesPrefPage, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkModuleView, context) if (qApp->metaObject()->indexOfSignal("messageReceived(QByteArray)") > -1) { connect(qApp, SIGNAL(messageReceived(QByteArray)), this, SLOT(handleIPCMessage(QByteArray))); } std::vector args = berry::Platform::GetApplicationArgs(); QStringList qargs; for (std::vector::const_iterator it = args.begin(); it != args.end(); ++it) { qargs << QString::fromStdString(*it); } // This is a potentially long running operation. loadDataFromDisk(qargs, true); } void QmitkCommonExtPlugin::stop(ctkPluginContext* context) { Q_UNUSED(context) this->_context = 0; } ctkPluginContext* QmitkCommonExtPlugin::getContext() { return _context; } void QmitkCommonExtPlugin::loadDataFromDisk(const QStringList &arguments, bool globalReinit) { if (!arguments.empty()) { ctkServiceReference serviceRef = _context->getServiceReference(); if (serviceRef) { mitk::IDataStorageService* dataStorageService = _context->getService(serviceRef); mitk::DataStorage::Pointer dataStorage = dataStorageService->GetDefaultDataStorage()->GetDataStorage(); int argumentsAdded = 0; for (int i = 0; i < arguments.size(); ++i) { if (arguments[i].right(5) == ".mitk") { mitk::SceneIO::Pointer sceneIO = mitk::SceneIO::New(); bool clearDataStorageFirst(false); mitk::ProgressBar::GetInstance()->AddStepsToDo(2); dataStorage = sceneIO->LoadScene( arguments[i].toLocal8Bit().constData(), dataStorage, clearDataStorageFirst ); mitk::ProgressBar::GetInstance()->Progress(2); argumentsAdded++; } else { - mitk::DataNodeFactory::Pointer nodeReader = mitk::DataNodeFactory::New(); try { - nodeReader->SetFileName(arguments[i].toStdString()); - nodeReader->Update(); - for (unsigned int j = 0 ; j < nodeReader->GetNumberOfOutputs( ); ++j) - { - mitk::DataNode::Pointer node = nodeReader->GetOutput(j); - if (node->GetData() != 0) - { - dataStorage->Add(node); - argumentsAdded++; - } - } + const std::string path(arguments[i].toStdString()); + mitk::IOUtil::Load(path, *dataStorage); + argumentsAdded++; } catch(...) { MITK_WARN << "Failed to load command line argument: " << arguments[i].toStdString(); } } } // end for each command line argument if (argumentsAdded > 0 && globalReinit) { // calculate bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(dataStorage->ComputeBoundingGeometry3D()); } } else { MITK_ERROR << "A service reference for mitk::IDataStorageService does not exist"; } } } void QmitkCommonExtPlugin::startNewInstance(const QStringList &args, const QStringList& files) { QStringList newArgs(args); #ifdef Q_OS_UNIX newArgs << QString("--") + QString::fromStdString(berry::Platform::ARG_NEWINSTANCE); #else newArgs << QString("/") + QString::fromStdString(berry::Platform::ARG_NEWINSTANCE); #endif newArgs << files; QProcess::startDetached(qApp->applicationFilePath(), newArgs); } void QmitkCommonExtPlugin::handleIPCMessage(const QByteArray& msg) { QDataStream ds(msg); QString msgType; ds >> msgType; // we only handle messages containing command line arguments if (msgType != "$cmdLineArgs") return; // activate the current workbench window berry::IWorkbenchWindow::Pointer window = berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow(); QMainWindow* mainWindow = static_cast (window->GetShell()->GetControl()); mainWindow->setWindowState(mainWindow->windowState() & ~Qt::WindowMinimized); mainWindow->raise(); mainWindow->activateWindow(); // Get the preferences for the instantiation behavior berry::IPreferencesService::Pointer prefService = berry::Platform::GetServiceRegistry() .GetServiceById(berry::IPreferencesService::ID); berry::IPreferences::Pointer prefs = prefService->GetSystemPreferences()->Node("/General"); bool newInstanceAlways = prefs->GetBool("newInstance.always", false); bool newInstanceScene = prefs->GetBool("newInstance.scene", true); QStringList args; ds >> args; QStringList fileArgs; QStringList sceneArgs; Poco::Util::OptionSet os; berry::Platform::GetOptionSet(os); Poco::Util::OptionProcessor processor(os); #if !defined(POCO_OS_FAMILY_UNIX) processor.setUnixStyle(false); #endif args.pop_front(); QStringList::Iterator it = args.begin(); while (it != args.end()) { std::string name; std::string value; if (processor.process(it->toStdString(), name, value)) { ++it; } else { if (it->endsWith(".mitk")) { sceneArgs << *it; } else { fileArgs << *it; } it = args.erase(it); } } if (newInstanceAlways) { if (newInstanceScene) { startNewInstance(args, fileArgs); foreach(QString sceneFile, sceneArgs) { startNewInstance(args, QStringList(sceneFile)); } } else { fileArgs.append(sceneArgs); startNewInstance(args, fileArgs); } } else { loadDataFromDisk(fileArgs, false); if (newInstanceScene) { foreach(QString sceneFile, sceneArgs) { startNewInstance(args, QStringList(sceneFile)); } } else { loadDataFromDisk(sceneArgs, false); } } } #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) Q_EXPORT_PLUGIN2(org_mitk_gui_qt_ext, QmitkCommonExtPlugin) #endif diff --git a/Plugins/org.mitk.gui.qt.extapplication/CMakeLists.txt b/Plugins/org.mitk.gui.qt.extapplication/CMakeLists.txt index 4f0146d128..bec267ead4 100644 --- a/Plugins/org.mitk.gui.qt.extapplication/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.extapplication/CMakeLists.txt @@ -1,17 +1,7 @@ project(org_mitk_gui_qt_extapplication) MACRO_CREATE_MITK_CTK_PLUGIN( EXPORT_DIRECTIVE MITK_QT_EXTAPP EXPORTED_INCLUDE_SUFFIXES src PACKAGE_DEPENDS Qt4|QtWebKit Qt5|WebKit ) - -if (DESIRED_QT_VERSION MATCHES "5") - if (Qt5WebKit_DIR) - add_definitions(-DQT_WEBKIT) - endif() -else() - if(QT_QTWEBKIT_FOUND) - add_definitions(-DQT_WEBKIT) - endif(QT_QTWEBKIT_FOUND) -endif() diff --git a/Plugins/org.mitk.gui.qt.extapplication/resources/welcome/function.js b/Plugins/org.mitk.gui.qt.extapplication/resources/welcome/function.js index 697544a26b..68928e2714 100644 --- a/Plugins/org.mitk.gui.qt.extapplication/resources/welcome/function.js +++ b/Plugins/org.mitk.gui.qt.extapplication/resources/welcome/function.js @@ -1,265 +1,265 @@ // If you want to create a new button you have to add some data (strings) to the following five arrays. // Make sure that you add your data at the same position in each array. // The buttons will be generated in order to the array's index. e.g. data at array's index '0' will generate the first button. // enter the name of your module here var moduleNames = new Array("MITK Website"); // add the MITK-link to your module var moduleLinks = new Array("http://www.mitk.org/"); // add the filename of your icon for the module. Place the picture in subdirectory "pics". // The picture's width should be 136 pixel; the height 123 pixel. var picFilenames = new Array("button_mitk.png"); // if you want to create an animated icon, add the name of your animated gif (placed in subdirectory "pics"). Otherwise enter an empty string "". // The animation's width should be 136 pixel; the height 123 pixel. var aniFilenames = new Array("button_mitka.png"); // if your module is not stable, you can mark it as experimental. // just set true for experimental or false for stable. var experimental = new Array(false); // add the description for your module. The description is displayed in a PopUp-window. var moduleDescriptions = new Array(""); var bttns = new Array(); var d = document, da = d.all; // holds id of current mouseover-HTML-element var currentTarget; // get the id of current mouseover-HTML-element d.onmouseover = function(o){ var e = da ? event.srcElement : o.target; currentTarget = e.id; } // build-function called by onload-event in HTML-document function createButtons(){ for (i=0; i < moduleNames.length; i++){ bttns[i] = new Button(moduleNames[i],moduleLinks[i], picFilenames[i], aniFilenames[i],moduleDescriptions[i]); bttns[i].createButton(); } for (i=0; i < moduleNames.length; i++){ if(experimental[i]){ setExperimental(i); } } createClearFloat(); } // Class Button function Button(moduleName, moduleLink, picFilename, aniFilename, moduleDescr){ // Properties this.bttnID = "bttn" + moduleName; this.modName = moduleName; this.modLink = moduleLink; this.picPath = "pics/" + picFilename; this.aniPath = "pics/" + aniFilename; this.modDescr = moduleDescr; // Methods this.createButton = function(){ // get DIV-wrapper for Button and append it to HTML-document bttnWrapper = this.createWrapper(); document.getElementById("bttnField").appendChild(bttnWrapper); // get link-element for picture and append it to DIV-wrapper bttnPicLink = this.createPicLink(); bttnWrapper.appendChild(bttnPicLink); // set HTML attributes for button-element bttn = document.createElement("img"); bttn.src = this.picPath; bttn.id = this.bttnID; bttn.className = "modBttn"; bttn.height = 123; bttn.width = 136; bttn.onmouseover = function(){startAni(this.id);}; bttn.onmouseout = function(){stopAni(this.id);}; bttn.onclick = function(){openPage();}; // append button to link-element bttnPicLink.appendChild(bttn); // create text-link and add it to DIV-wrapper bttnTxtLink = document.createElement("a"); bttnTxtLink.onclick = function(){openPage();}; bttnTxtLink.href = this.modLink; bttnTxtLink.className = "txtLink"; bttnTxtLink.appendChild(document.createTextNode(this.modName)); bttnWrapper.appendChild(bttnTxtLink); // create pop-up link for module description if (this.modDescr.length != 0) { bttnPopUpLink = document.createElement("a"); modName = this.modName; modDescr = this.modDescr; bttnPopUpLink.onclick = function(){showPopUpWindow();}; bttnPopUpLink.className = "popUpLink"; bttnPopUpLink.id = "popup" + this.modName; bttnPopUpLink.appendChild(document.createTextNode("more info >>")); bttnWrapper.appendChild(document.createElement("br")); bttnWrapper.appendChild(bttnPopUpLink); } return bttn; } this.createWrapper = function(){ bttnWrapper = document.createElement("div"); bttnWrapper.id = "wrapper" + this.modName; bttnWrapper.className = "bttnWrap"; return bttnWrapper; } this.createPicLink = function(){ picLink = document.createElement("a"); picLink.href = this.modLink; picLink.id = "link" + this.modName; return picLink; } } function showPopUpWindow(){ // modules position in array? modulePos = getPos(currentTarget,"popup"); // get reference to anchor-element in HTML-document popUpAnchor = document.getElementById("popupAnchor"); // check if a popUp is open if(popUpAnchor.hasChildNodes()){ // if a popUp is open, remove it! popUpAnchor.removeChild(document.getElementById("popup")); } // create new container for popUp container = document.createElement("div"); container.id = "popup"; container.align = "right"; // append popUp-container to HTML-document popUpAnchor.appendChild(container); // create close-button and append it to popUp-container bttnClose = document.createElement("img"); bttnClose.src = "pics/popup_bttn_close.png"; bttnClose.id = "bttnClose"; bttnClose.onclick = function(){closeInfoWindow();}; container.appendChild(bttnClose); // create container for content-elements contHeadline = document.createElement("div"); contHeadline.id = "contHeadline"; contDescription = document.createElement("div"); contDescription.id = "contDescription"; contModLink = document.createElement("div"); contModLink.id = "contModLink"; // append content-container to popUp-container container.appendChild(contHeadline); container.appendChild(contDescription); container.appendChild(contModLink); // create text-elements with content headline = document.createTextNode(moduleNames[modulePos] + " "); description = document.createTextNode(moduleDescriptions[modulePos]); moduleLink = document.createElement("a"); moduleLink.href = moduleLinks[modulePos] ; moduleLink.className = 'moduleLink'; moduleLinkTxt = document.createTextNode("Click here to open '" + moduleNames[modulePos].toLowerCase() + "'"); moduleLink.appendChild(moduleLinkTxt); // append text-elements to their container contHeadline.appendChild(headline); contDescription.appendChild(description); contModLink.appendChild(moduleLink); } function getPos(id,prefix){ if(prefix == "popup"){ targetID = id.slice(5); }else{ if(prefix == "bttn"){ targetID = id.slice(4); } } for(i=0; i < moduleNames.length; i++ ){ if(moduleNames[i] == targetID){ return i; } } } function setExperimental(modPos){ linkID = "link" + moduleNames[modPos]; expPic = document.createElement("img"); expPic.src = "pics/experimental.png"; expPic.className = "expPic"; //alert(bttns[modPos].bttnID); expPic.onmouseover = function(){startAni(bttns[modPos].bttnID);changeToHover(bttns[modPos].bttnID);}; expPic.onmouseout = function(){stopAni(bttns[modPos].bttnID);changeToNormal(bttns[modPos].bttnID);}; document.getElementById(linkID).appendChild(expPic); } function changeToHover(targetId){ bttn = document.getElementById(targetId); bttn.className = "modBttnHover"; } function openPage(){ - window.open("http://www.mitk.org","_self"); + window.open("http://www.mitk.org","_blank"); } function changeToNormal(targetId){ bttn = document.getElementById(targetId); bttn.className = "modBttn"; } // function to close PopUp-window function closeInfoWindow(){ popUpAnchor = document.getElementById("popupAnchor"); popUpAnchor.removeChild(document.getElementById("popup")); } function createClearFloat(){ cf = document.createElement("div"); cf.className = "clearfloat"; document.getElementById("bttnField").appendChild(cf); } startAni = function(targetId){ modulePos = getPos(targetId,"bttn"); if(aniFilenames[modulePos] != ''){ bttn = document.getElementById(targetId); bttn.src = "pics/" + aniFilenames[modulePos]; } } stopAni = function(targetId){ modulePos = getPos(targetId,"bttn"); bttn = document.getElementById(targetId); bttn.src = "pics/" + picFilenames[modulePos]; } diff --git a/Plugins/org.mitk.gui.qt.extapplication/src/internal/QmitkMitkWorkbenchIntroPart.cpp b/Plugins/org.mitk.gui.qt.extapplication/src/internal/QmitkMitkWorkbenchIntroPart.cpp index 7cc83fba92..ab6e40341b 100644 --- a/Plugins/org.mitk.gui.qt.extapplication/src/internal/QmitkMitkWorkbenchIntroPart.cpp +++ b/Plugins/org.mitk.gui.qt.extapplication/src/internal/QmitkMitkWorkbenchIntroPart.cpp @@ -1,214 +1,207 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkMitkWorkbenchIntroPart.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#ifdef QT_WEBKIT + # include # include # if QT_VERSION >= QT_VERSION_CHECK(5,0,0) # include # endif -#endif + #include #include #include #include #include #include #include "QmitkExtApplicationPlugin.h" #include "mitkDataStorageEditorInput.h" #include QmitkMitkWorkbenchIntroPart::QmitkMitkWorkbenchIntroPart() : m_Controls(NULL) { berry::IPreferences::Pointer workbenchPrefs = QmitkExtApplicationPlugin::GetDefault()->GetPreferencesService()->GetSystemPreferences(); workbenchPrefs->PutBool(berry::WorkbenchPreferenceConstants::SHOW_INTRO, true); workbenchPrefs->Flush(); } QmitkMitkWorkbenchIntroPart::~QmitkMitkWorkbenchIntroPart() { // 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 = QmitkExtApplicationPlugin::GetDefault()->GetPreferencesService()->GetSystemPreferences(); workbenchPrefs->PutBool(berry::WorkbenchPreferenceConstants::SHOW_INTRO, false); workbenchPrefs->Flush(); } else { berry::IPreferences::Pointer workbenchPrefs = QmitkExtApplicationPlugin::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.mitkworkbench.perspectives.editor" && !this->GetIntroSite()->GetPage()->GetWorkbenchWindow()->GetWorkbench()->IsClosing()) { berry::IPerspectiveDescriptor::Pointer perspective = this->GetIntroSite()->GetWorkbenchWindow()->GetWorkbench()->GetPerspectiveRegistry()->FindPerspectiveWithId("org.mitk.mitkworkbench.perspectives.editor"); if (perspective) { this->GetIntroSite()->GetPage()->SetPerspective(perspective); } } } void QmitkMitkWorkbenchIntroPart::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/mitkworkbenchwelcomeview.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 QmitkMitkWorkbenchIntroPart::CreateConnections() { if ( m_Controls ) { - connect( (QObject*)(m_view->page()), SIGNAL(linkClicked(const QUrl& )), this, SLOT(DelegateMeTo(const QUrl& )) ); + connect( m_view, SIGNAL(linkClicked(const QUrl& )), this, SLOT(DelegateMeTo(const QUrl& )) ); } } void QmitkMitkWorkbenchIntroPart::DelegateMeTo(const QUrl& showMeNext) { QString scheme = showMeNext.scheme(); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) QByteArray urlHostname = showMeNext.encodedHost(); QByteArray urlPath = showMeNext.encodedPath(); QByteArray dataset = showMeNext.encodedQueryItemValue("dataset"); QByteArray clear = showMeNext.encodedQueryItemValue("clear"); #else QByteArray urlHostname = QUrl::toAce(showMeNext.host()); QByteArray urlPath = showMeNext.path().toLatin1(); QUrlQuery query(showMeNext); QByteArray dataset = query.queryItemValue("dataset").toLatin1(); QByteArray clear = query.queryItemValue("clear").toLatin1();//showMeNext.encodedQueryItemValue("clear"); #endif 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() ); // search the Workbench for opened StdMultiWidgets to ensure the focus does not stay on the welcome screen and is switched to // an StdMultiWidget if one available mitk::IDataStorageService::Pointer service = berry::Platform::GetServiceRegistry().GetServiceById(mitk::IDataStorageService::ID); berry::IEditorInput::Pointer editorInput; editorInput = new mitk::DataStorageEditorInput( service->GetActiveDataStorage() ); // the solution is not clean, but the dependency to the StdMultiWidget was removed in order to fix a crash problem // as described in Bug #11715 // This is the correct way : use the static string ID variable // berry::IEditorPart::Pointer editor = GetIntroSite()->GetPage()->FindEditors( editorInput, QmitkStdMultiWidgetEditor::EDITOR_ID ); // QuickFix: we use the same string for an local variable const std::string stdEditorID = "org.mitk.editors.stdmultiwidget"; // search for opened StdMultiWidgetEditors std::vector editorList = GetIntroSite()->GetPage()->FindEditors( editorInput, stdEditorID, 1 ); // if an StdMultiWidgetEditor open was found, give focus to it if(editorList.size()) { GetIntroSite()->GetPage()->Activate( editorList[0]->GetPart(true) ); } } } // 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 QmitkMitkWorkbenchIntroPart::StandbyStateChanged(bool /*standby*/) { } void QmitkMitkWorkbenchIntroPart::SetFocus() { } diff --git a/Plugins/org.mitk.gui.qt.extapplication/src/internal/QmitkMitkWorkbenchIntroPart.h b/Plugins/org.mitk.gui.qt.extapplication/src/internal/QmitkMitkWorkbenchIntroPart.h index 1167daf04f..34c38732cb 100644 --- a/Plugins/org.mitk.gui.qt.extapplication/src/internal/QmitkMitkWorkbenchIntroPart.h +++ b/Plugins/org.mitk.gui.qt.extapplication/src/internal/QmitkMitkWorkbenchIntroPart.h @@ -1,88 +1,87 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKWORKBENCHINTROPART_H_ #define QMITKWORKBENCHINTROPART_H_ #include #include #include /** * \ingroup org_mitk_gui_qt_welcomescreen_internal * \brief QmitkMitkWorkbenchIntroPart * The WelcomeView Module is an helpful feature to people new to MITK. The main idea is to provide first * information about the MITK Workbench. * The WelcomeView is realized by making use of the QTWebKit Module. The Qt WebKit module * provides an HTML browser engine that makes it easy to embed web content into native applications, and to enhance * web content with native controls. * For the welcome view of the application the QWebView, QWebPage classes have been used. The shown WelcomeView * html start page is styled by an external css stylesheet. The required resources as well as the html pages are integrated * into the QtResource system. The QT resource system allows the storage of files like html pages, css pages, jpgs etc. * as binaries within the executable. * This minimizes the risk of loosing resource files as well as the risk of getting files deleted. In order to use the Qt * resource system the resource files have to be added to the associated qrt resource file list. * * The foundation is set to design more complex html pages. The Q::WebPage gives options to set a * LinkDelegationPolicy. The used policy defines how links to external or internal resources are handled. To fit our needs * the delegate all links policy is used. This requires all external as well as internal links of the html pages to be handle * explicitly. In order to change mitk working modes (perspectives) a mitk url scheme has been designed. The url scheme * is set to mitk. The url host provides information about what's next to do. In our case, the case of switching to a * particular working mode the host is set to perspectives. The followed path provides information about the perspective id. * (e.g. mitk//::mitk.perspectives/org.mitk.qt.defaultperspective) The the generic design of the mitk url scheme allows to * execute other task depending on the mitk url host. * \sa QmitkWelcomePage Editor */ class QWebView ; class QmitkMitkWorkbenchIntroPart : public berry::QtIntroPart { // this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: QmitkMitkWorkbenchIntroPart(); ~QmitkMitkWorkbenchIntroPart(); virtual void CreateQtPartControl(QWidget *parent); void StandbyStateChanged(bool); void SetFocus(); -#ifdef QT_WEBKIT virtual void CreateConnections(); protected slots: void DelegateMeTo(const QUrl& ShowMeNext); -#endif + protected: Ui::QmitkWelcomeScreenViewControls* m_Controls; QWebView* m_view; }; #endif /* QMITKWORKBENCHINTROPART_H_ */ diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/CMakeLists.txt b/Plugins/org.mitk.gui.qt.igtlplugin/CMakeLists.txt new file mode 100644 index 0000000000..8748012389 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/CMakeLists.txt @@ -0,0 +1,8 @@ +project(org_mitk_gui_qt_igtlplugin) + +MACRO_CREATE_MITK_CTK_PLUGIN( + DEPENDS + EXPORT_DIRECTIVE IGTLPLUGIN_EXPORT + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkQtWidgetsExt MitkOpenIGTLink MitkOpenIGTLinkUI MitkIGT +) diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.igtlplugin/documentation/UserManual/Manual.dox new file mode 100644 index 0000000000..c94e724867 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/documentation/UserManual/Manual.dox @@ -0,0 +1,17 @@ +/** +\page org_mitk_gui_qt_igtlplugin The Igtlplugin + +\imageMacro{icon.png,"Icon of Igtlplugin",2.00} + +\tableofcontents + +\section org_mitk_gui_qt_igtlpluginOverview Overview +Describe the features of your awesome plugin here +
    +
  • Increases productivity +
  • Creates beautiful images +
  • Generates PhD thesis +
  • Brings world peace +
+ +*/ diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/documentation/UserManual/icon.xpm b/Plugins/org.mitk.gui.qt.igtlplugin/documentation/UserManual/icon.xpm new file mode 100644 index 0000000000..9057c20bc6 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/documentation/UserManual/icon.xpm @@ -0,0 +1,21 @@ +/* XPM */ +static const char * icon_xpm[] = { +"16 16 2 1", +" c #FF0000", +". c #000000", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.igtlplugin/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..7da567195c --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_mitk_gui_qt_igtlplugin org.mitk.gui.qt.igtlplugin + \ingroup MITKPlugins + + \brief Describe your plugin here. + +*/ + +/** + \defgroup org_mitk_gui_qt_igtlplugin_internal Internal + \ingroup org_mitk_gui_qt_igtlplugin + + \brief This subcategory includes the internal classes of the org.mitk.gui.qt.igtlplugin plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/files.cmake b/Plugins/org.mitk.gui.qt.igtlplugin/files.cmake new file mode 100644 index 0000000000..623ed923af --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/files.cmake @@ -0,0 +1,50 @@ +set(SRC_CPP_FILES + +) + +set(INTERNAL_CPP_FILES + org_mitk_gui_qt_igtlplugin_Activator.cpp + OpenIGTLinkManager.cpp + OpenIGTLinkExample.cpp + OpenIGTLinkProviderExample.cpp +) + +set(UI_FILES + src/internal/OpenIGTLinkProviderExampleControls.ui + src/internal/OpenIGTLinkExampleControls.ui + src/internal/OpenIGTLinkManagerControls.ui +) + +set(MOC_H_FILES + src/internal/org_mitk_gui_qt_igtlplugin_Activator.h + src/internal/OpenIGTLinkProviderExample.h + src/internal/OpenIGTLinkExample.h + src/internal/OpenIGTLinkManager.h +) + +# 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 +set(CACHED_RESOURCE_FILES + resources/manager.png + resources/example.png + resources/provider.png + plugin.xml +) + +# list of Qt .qrc files which contain additional resources +# specific to this plugin +set(QRC_FILES + +) + +set(CPP_FILES ) + +foreach(file ${SRC_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/${file}) +endforeach(file ${SRC_CPP_FILES}) + +foreach(file ${INTERNAL_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/internal/${file}) +endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.igtlplugin/manifest_headers.cmake new file mode 100644 index 0000000000..72e7125730 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "Igtlplugin") +set(Plugin-Version "0.1") +set(Plugin-Vendor "DKFZ") +set(Plugin-ContactAddress "") +set(Require-Plugin org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/plugin.xml b/Plugins/org.mitk.gui.qt.igtlplugin/plugin.xml new file mode 100644 index 0000000000..f34b3b1988 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/plugin.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/resources/example.png b/Plugins/org.mitk.gui.qt.igtlplugin/resources/example.png new file mode 100644 index 0000000000..7b13daf633 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.igtlplugin/resources/example.png differ diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/resources/manager.png b/Plugins/org.mitk.gui.qt.igtlplugin/resources/manager.png new file mode 100644 index 0000000000..52d18e59a2 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.igtlplugin/resources/manager.png differ diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/resources/provider.png b/Plugins/org.mitk.gui.qt.igtlplugin/resources/provider.png new file mode 100644 index 0000000000..85eef0c203 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.igtlplugin/resources/provider.png differ diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.cpp b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.cpp new file mode 100644 index 0000000000..e3767d44ff --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.cpp @@ -0,0 +1,174 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +// Blueberry +#include +#include + +// Qmitk +#include "QmitkRenderWindow.h" + +// Qt +#include + +// mitk +#include +#include +#include +#include +#include + +// vtk +#include + +// +#include "OpenIGTLinkExample.h" + +//igtl +#include "igtlStringMessage.h" +#include "igtlTrackingDataMessage.h" + + +const std::string OpenIGTLinkExample::VIEW_ID = "org.mitk.views.OpenIGTLinkExample"; + +void OpenIGTLinkExample::SetFocus() +{ +} + +OpenIGTLinkExample::~OpenIGTLinkExample() +{ + this->GetDataStorage()->Remove(m_DemoNodeT1); + this->GetDataStorage()->Remove(m_DemoNodeT2); + this->GetDataStorage()->Remove(m_DemoNodeT3); +} + +void OpenIGTLinkExample::CreateQtPartControl( QWidget *parent ) +{ + // create GUI widgets from the Qt Designer's .ui file + m_Controls.setupUi( parent ); + + // connect the widget items with the methods + connect( m_Controls.butStart, SIGNAL(clicked()), + this, SLOT(Start()) ); + connect( &m_Timer, SIGNAL(timeout()), this, SLOT(UpdatePipeline())); + + //Setup the pipeline + this->CreatePipeline(); +} + +void OpenIGTLinkExample::CreatePipeline() +{ + //create a new OpenIGTLinkExample Client + m_IGTLClient = mitk::IGTLClient::New(); + m_IGTLClient->SetName("OIGTL Example Client Device"); + + //create a new OpenIGTLinkExample Device source + m_IGTLDeviceSource = mitk::IGTLDeviceSource::New(); + + //set the client as the source for the device source + m_IGTLDeviceSource->SetIGTLDevice(m_IGTLClient); + + m_IGTLDeviceSource->RegisterAsMicroservice(); + + //create a filter that converts OpenIGTLinkExample messages into navigation data + m_IGTLMsgToNavDataFilter = mitk::IGTLMessageToNavigationDataFilter::New(); + + //create a visualization filter + m_VisFilter = mitk::NavigationDataObjectVisualizationFilter::New(); + + //we expect a tracking data message with three tools. Since we cannot change + //the outputs at runtime we have to set it manually. + m_IGTLMsgToNavDataFilter->SetNumberOfExpectedOutputs(3); + + //connect the filters with each other + //the OpenIGTLinkExample messages will be passed to the first filter that converts + //it to navigation data, then it is passed to the visualization filter that + //will visualize the transformation + m_IGTLMsgToNavDataFilter->ConnectTo(m_IGTLDeviceSource); + m_VisFilter->ConnectTo(m_IGTLMsgToNavDataFilter); + + //create an object that will be moved respectively to the navigation data + m_DemoNodeT1 = mitk::DataNode::New(); + m_DemoNodeT1->SetName("DemoNode IGTLExmpl T1"); + m_DemoNodeT2 = mitk::DataNode::New(); + m_DemoNodeT2->SetName("DemoNode IGTLExmpl T2"); + m_DemoNodeT3 = mitk::DataNode::New(); + m_DemoNodeT3->SetName("DemoNode IGTLExmpl T3"); + + //create small sphere and use it as surface + mitk::Surface::Pointer mySphere = mitk::Surface::New(); + vtkSphereSource *vtkData = vtkSphereSource::New(); + vtkData->SetRadius(2.0f); + vtkData->SetCenter(0.0, 0.0, 0.0); + vtkData->Update(); + mySphere->SetVtkPolyData(vtkData->GetOutput()); + vtkData->Delete(); + m_DemoNodeT1->SetData(mySphere); + + mitk::Surface::Pointer mySphere2 = mySphere->Clone(); + m_DemoNodeT2->SetData(mySphere2); + mitk::Surface::Pointer mySphere3 = mySphere->Clone(); + m_DemoNodeT3->SetData(mySphere3); + + // add node to DataStorage + this->GetDataStorage()->Add(m_DemoNodeT1); + this->GetDataStorage()->Add(m_DemoNodeT2); + this->GetDataStorage()->Add(m_DemoNodeT3); + + //use this sphere as representation object + m_VisFilter->SetRepresentationObject(0, mySphere); + m_VisFilter->SetRepresentationObject(1, mySphere2); + m_VisFilter->SetRepresentationObject(2, mySphere3); +} + +void OpenIGTLinkExample::DestroyPipeline() +{ + m_VisFilter = NULL; + this->GetDataStorage()->Remove(m_DemoNodeT1); + this->GetDataStorage()->Remove(m_DemoNodeT2); + this->GetDataStorage()->Remove(m_DemoNodeT3); +} + +void OpenIGTLinkExample::Start() +{ + if ( this->m_Controls.butStart->text().contains("Start Pipeline") ) + { + m_Timer.setInterval(90); + m_Timer.start(); + this->m_Controls.butStart->setText("Stop Pipeline"); + } + else + { + m_Timer.stop(); + igtl::StopTrackingDataMessage::Pointer stopStreaming = + igtl::StopTrackingDataMessage::New(); + this->m_IGTLClient->SendMessage(stopStreaming.GetPointer()); + this->m_Controls.butStart->setText("Start Pipeline"); + } +} + +void OpenIGTLinkExample::UpdatePipeline() +{ + //update the pipeline + m_VisFilter->Update(); + + //update the boundings + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); + + //Update rendering + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.h b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.h new file mode 100644 index 0000000000..1ddedc5621 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.h @@ -0,0 +1,84 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef OpenIGTLinkExample_h +#define OpenIGTLinkExample_h + +#include + +#include + +#include "ui_OpenIGTLinkExampleControls.h" +#include "mitkIGTLClient.h" +#include "mitkIGTLServer.h" +#include "mitkIGTLDeviceSource.h" +#include "mitkNavigationDataObjectVisualizationFilter.h" +#include "mitkIGTLMessageToNavigationDataFilter.h" + +#include "qtimer.h" + +/** + \brief OpenIGTLinkExample + + \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. + + \sa QmitkAbstractView + \ingroup ${plugin_target}_internal +*/ +class OpenIGTLinkExample : public QmitkAbstractView +{ + // this is needed for all Qt objects that should have a Qt meta-object + // (everything that derives from QObject and wants to have signal/slots) + Q_OBJECT + + public: + ~OpenIGTLinkExample(); + + static const std::string VIEW_ID; + + protected slots: + + void Start(); + void UpdatePipeline(); + + + protected: + + virtual void CreateQtPartControl(QWidget *parent); + + virtual void SetFocus(); + + void CreatePipeline(); + void DestroyPipeline(); + + Ui::OpenIGTLinkExampleControls m_Controls; + mitk::IGTLClient::Pointer m_IGTLClient; + mitk::IGTLDeviceSource::Pointer m_IGTLDeviceSource; + mitk::IGTLMessageToNavigationDataFilter::Pointer m_IGTLMsgToNavDataFilter; + mitk::NavigationDataObjectVisualizationFilter::Pointer m_VisFilter; + mitk::DataNode::Pointer m_DemoNodeT1; + mitk::DataNode::Pointer m_DemoNodeT2; + mitk::DataNode::Pointer m_DemoNodeT3; + + //REMOVE LATER +// mitk::IGTLServer::Pointer m_IGTLServer; +// mitk::IGTLDeviceSource::Pointer m_IGTLDeviceSource2; + + QTimer m_Timer; +}; + +#endif // OpenIGTLinkExample_h diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExampleControls.ui b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExampleControls.ui new file mode 100644 index 0000000000..7151dd71b8 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExampleControls.ui @@ -0,0 +1,52 @@ + + + OpenIGTLinkExampleControls + + + + 0 + 0 + 668 + 392 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + + + Start Pipeline + + + + + + + Qt::Vertical + + + + 20 + 220 + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManager.cpp b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManager.cpp new file mode 100644 index 0000000000..72397c9036 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManager.cpp @@ -0,0 +1,84 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +// Blueberry +#include +#include + +// +#include "OpenIGTLinkManager.h" + + +const std::string OpenIGTLinkManager::VIEW_ID = + "org.mitk.views.openigtlinkmanager"; + +OpenIGTLinkManager::OpenIGTLinkManager() +: QmitkAbstractView() +{ +} + +OpenIGTLinkManager::~OpenIGTLinkManager() +{ + for(unsigned int i=0; i < m_AllSourcesHandledByThisWidget.size(); i++) + m_AllSourcesHandledByThisWidget.at(i)->UnRegisterMicroservice(); +} + +void OpenIGTLinkManager::SetFocus() +{ +} + +void OpenIGTLinkManager::CreateQtPartControl( QWidget *parent ) +{ + // create GUI widgets from the Qt Designer's .ui file + m_Controls.setupUi( parent ); + + // create GUI widgets from the Qt Designer's .ui file +// connect( (QObject*)(m_Controls.m_SourceManagerWidget), +// SIGNAL(NewSourceAdded(mitk::IGTLDeviceSource::Pointer, std::string)), +// this, +// SLOT(NewSourceByWidget(mitk::IGTLDeviceSource::Pointer,std::string)) ); + connect( (QObject*)(m_Controls.m_SourceListWidget), + SIGNAL(IGTLDeviceSourceSelected(mitk::IGTLDeviceSource::Pointer)), + this, + SLOT(SourceSelected(mitk::IGTLDeviceSource::Pointer)) ); +} + + +void OpenIGTLinkManager::NewSourceByWidget( + mitk::IGTLDeviceSource::Pointer source,std::string /*sourceName*/) +{ + source->RegisterAsMicroservice(/*sourceName*/); + m_AllSourcesHandledByThisWidget.push_back(source); +} + +void OpenIGTLinkManager::SourceSelected( + mitk::IGTLDeviceSource::Pointer source) +{ + if (source.IsNull()) //no source selected + { + //reset everything + return; + } + + this->m_Controls.m_SourceManagerWidget->LoadSource(source); + + //check if the current selected source is also a message provider + mitk::IGTLMessageProvider::Pointer msgProvider = + mitk::IGTLMessageProvider::New(); + msgProvider = dynamic_cast(source.GetPointer()); + this->m_Controls.m_StreamManagerWidget->LoadSource(msgProvider); +} diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManager.h b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManager.h new file mode 100644 index 0000000000..b82c756ccf --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManager.h @@ -0,0 +1,71 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef OpenIGTLinkManager_h +#define OpenIGTLinkManager_h + +#include + +#include + +#include "ui_OpenIGTLinkManagerControls.h" +#include "mitkIGTLClient.h" +#include "mitkIGTLDeviceSource.h" + +/** + \brief OpenIGTLinkManager + + \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. + + \sa QmitkAbstractView + \ingroup ${plugin_target}_internal +*/ +class OpenIGTLinkManager : public QmitkAbstractView +{ + // this is needed for all Qt objects that should have a Qt meta-object + // (everything that derives from QObject and wants to have signal/slots) + Q_OBJECT + + public: + + static const std::string VIEW_ID; + + OpenIGTLinkManager(); + virtual ~OpenIGTLinkManager(); + + public slots: + void NewSourceByWidget(mitk::IGTLDeviceSource::Pointer source, std::string); + void SourceSelected(mitk::IGTLDeviceSource::Pointer source); + + protected: + + virtual void CreateQtPartControl(QWidget *parent); + + virtual void SetFocus(); + + void CreatePipeline(); + void DestroyPipeline(); + + Ui::OpenIGTLinkManagerControls m_Controls; + + /** Someone needs to hold the smart pointers of new sources, otherwise the + * objects will be lost although they are listed as microservice. + */ + std::vector m_AllSourcesHandledByThisWidget; +}; + +#endif // OpenIGTLinkManager_h diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManagerControls.ui b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManagerControls.ui new file mode 100644 index 0000000000..fc8aeba7ed --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManagerControls.ui @@ -0,0 +1,98 @@ + + + OpenIGTLinkManagerControls + + + + 0 + 0 + 668 + 392 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + + 12 + 75 + true + + + + Select OpenIGTLink Device Source: + + + + + + + + + + + 12 + 75 + true + + + + Manage Device: + + + + + + + + + + + 12 + 75 + true + + + + Manage Streams: + + + + + + + + + + + + QmitkIGTLDeviceSourceSelectionWidget + QTextEdit +
QmitkIGTLDeviceSourceSelectionWidget.h
+
+ + QmitkIGTLDeviceSourceManagementWidget + QWidget +
QmitkIGTLDeviceSourceManagementWidget.h
+ 1 +
+ + QmitkIGTLStreamingManagementWidget + QWidget +
QmitkIGTLStreamingManagementWidget.h
+ 1 +
+
+ + +
diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.cpp b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.cpp new file mode 100644 index 0000000000..eb9a447021 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.cpp @@ -0,0 +1,239 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +// Blueberry +#include +#include + +// Qmitk +#include "QmitkRenderWindow.h" + +// Qt +#include +#include + +// mitk +#include +#include +#include +#include +#include +#include + +// vtk +#include + +// +#include "OpenIGTLinkProviderExample.h" + +//igtl +#include "igtlStringMessage.h" + + +const std::string OpenIGTLinkProviderExample::VIEW_ID = + "org.mitk.views.OpenIGTLinkProviderExample"; + +OpenIGTLinkProviderExample::~OpenIGTLinkProviderExample() +{ + this->GetDataStorage()->Remove(m_DemoNodeT1); + this->GetDataStorage()->Remove(m_DemoNodeT2); + this->GetDataStorage()->Remove(m_DemoNodeT3); +} + +void OpenIGTLinkProviderExample::SetFocus() +{ +} + +void OpenIGTLinkProviderExample::CreateQtPartControl( QWidget *parent ) +{ + // create GUI widgets from the Qt Designer's .ui file + m_Controls.setupUi( parent ); + + // connect the widget items with the methods + connect( m_Controls.butStart, SIGNAL(clicked()), + this, SLOT(Start()) ); + connect( m_Controls.butOpenNavData, SIGNAL(clicked()), + this, SLOT(OnOpenFile()) ); + connect( &m_VisualizerTimer, SIGNAL(timeout()), + this, SLOT(UpdateVisualization())); +} + +void OpenIGTLinkProviderExample::CreatePipeline() +{ + //create a new OpenIGTLink Client + m_IGTLServer = mitk::IGTLServer::New(); + m_IGTLServer->SetName("OIGTL Provider Example Device"); + + //create a new OpenIGTLink Device source + m_IGTLMessageProvider = mitk::IGTLMessageProvider::New(); + + //set the OpenIGTLink server as the source for the device source + m_IGTLMessageProvider->SetIGTLDevice(m_IGTLServer); + + //register the provider so that it can be configured with the IGTL manager + //plugin. This could be hardcoded but now I already have the fancy plugin. + m_IGTLMessageProvider->RegisterAsMicroservice(); + + //create a filter that converts navigation data into IGTL messages + m_NavDataToIGTLMsgFilter = mitk::NavigationDataToIGTLMessageFilter::New(); + + //define the operation mode for this filter, we want to send tracking data + //messages + m_NavDataToIGTLMsgFilter->SetOperationMode( + mitk::NavigationDataToIGTLMessageFilter::ModeSendTDataMsg); +// mitk::NavigationDataToIGTLMessageFilter::ModeSendTransMsg); + + //set the name of this filter to identify it easier + m_NavDataToIGTLMsgFilter->SetName("Tracking Data Source From Example"); + + //register this filter as micro service. The message provider looks for + //provided IGTLMessageSources, once it found this microservice and someone + //requested this data type then the provider will connect with this filter + //automatically (this is not implemented so far, check m_StreamingConnector + //for more information) + m_NavDataToIGTLMsgFilter->RegisterAsMicroservice(); + + //create a navigation data player object that will play nav data from a + //recorded file + m_NavDataPlayer = mitk::NavigationDataPlayer::New(); + + //set the currently read navigation data set + m_NavDataPlayer->SetNavigationDataSet(m_NavDataSet); + + //connect the filters with each other + //the navigation data player reads a file with recorded navigation data, + //passes this data to a filter that converts it into a IGTLMessage. + //The provider is not connected because it will search for fitting services. + //Once it found the filter it will automatically connect to it (this is not + // implemented so far, check m_StreamingConnector for more information). + m_NavDataToIGTLMsgFilter->ConnectTo(m_NavDataPlayer); + + //create an object that will be moved respectively to the navigation data + m_DemoNodeT1 = mitk::DataNode::New(); + m_DemoNodeT1->SetName("DemoNode IGTLProviderExmpl T1"); + m_DemoNodeT2 = mitk::DataNode::New(); + m_DemoNodeT2->SetName("DemoNode IGTLProviderExmpl T2"); + m_DemoNodeT3 = mitk::DataNode::New(); + m_DemoNodeT3->SetName("DemoNode IGTLProviderExmpl T3"); + + //create small sphere and use it as surface + mitk::Surface::Pointer mySphere = mitk::Surface::New(); + vtkSphereSource *vtkData = vtkSphereSource::New(); + vtkData->SetRadius(2.0f); + vtkData->SetCenter(0.0, 0.0, 0.0); + vtkData->Update(); + mySphere->SetVtkPolyData(vtkData->GetOutput()); + vtkData->Delete(); + m_DemoNodeT1->SetData(mySphere); + + mitk::Surface::Pointer mySphere2 = mySphere->Clone(); + m_DemoNodeT2->SetData(mySphere2); + mitk::Surface::Pointer mySphere3 = mySphere->Clone(); + m_DemoNodeT3->SetData(mySphere3); + + // add node to DataStorage + this->GetDataStorage()->Add(m_DemoNodeT1); + this->GetDataStorage()->Add(m_DemoNodeT2); + this->GetDataStorage()->Add(m_DemoNodeT3); + + //initialize the streaming connector + //the streaming connector is checking if the data from the filter has to be + //streamed. The message provider is used for sending the messages. +// m_StreamingConnector.Initialize(m_NavDataToIGTLMsgFilter.GetPointer(), +// m_IGTLMessageProvider); + + //also create a visualize filter to visualize the data + m_NavDataVisualizer = mitk::NavigationDataObjectVisualizationFilter::New(); + m_NavDataVisualizer->SetRepresentationObject(0, mySphere); + m_NavDataVisualizer->SetRepresentationObject(1, mySphere2); + m_NavDataVisualizer->SetRepresentationObject(2, mySphere3); + m_NavDataVisualizer->ConnectTo(m_NavDataPlayer); + + //start the player + this->Start(); + + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); +} + +void OpenIGTLinkProviderExample::DestroyPipeline() +{ + m_NavDataPlayer->StopPlaying(); + this->GetDataStorage()->Remove(m_DemoNodeT1); +} + +void OpenIGTLinkProviderExample::Start() +{ + if ( this->m_Controls.butStart->text().contains("Start") ) + { + m_NavDataPlayer->SetRepeat(true); + m_NavDataPlayer->StartPlaying(); + this->m_Controls.butStart->setText("Stop Playing Recorded Navigation Data "); + + //start the visualization + this->m_VisualizerTimer.start(100); + } + else + { + m_NavDataPlayer->StopPlaying(); + this->m_Controls.butStart->setText("Start Playing Recorded Navigation Data "); + + //stop the visualization + this->m_VisualizerTimer.stop(); + } +} + +void OpenIGTLinkProviderExample::OnOpenFile(){ + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + + // FIXME Filter for correct files and use correct Reader + QString fileName = + QFileDialog::getOpenFileName(NULL, "Open Navigation Data Set", "", "XML files (*.xml)"); + if ( fileName.isNull() ) { return; } // user pressed cancel + + try + { + m_NavDataSet = reader->Read(fileName.toStdString()); + } + catch ( const mitk::Exception &e ) + { + MITK_WARN("NavigationDataPlayerView") << "could not open file " << fileName.toStdString(); + QMessageBox::critical(0, "Error Reading File", "The file '" + fileName + +"' could not be read.\n" + e.GetDescription() ); + return; + } + + this->m_Controls.butStart->setEnabled(true); + + //Setup the pipeline + this->CreatePipeline(); + + // Update Labels +// m_Controls->m_LblFilePath->setText(fileName); +// m_Controls->m_LblTools->setText(QString::number(m_NavDataSet->GetNumberOfTools())); +} + +void OpenIGTLinkProviderExample::UpdateVisualization() +{ + //update the filter + this->m_NavDataVisualizer->Update(); + + //update the bounds + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); + + //update rendering + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.h b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.h new file mode 100644 index 0000000000..edec2ae0b5 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.h @@ -0,0 +1,85 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef OpenIGTLinkProviderExample_h +#define OpenIGTLinkProviderExample_h + +#include + +#include +#include + +#include "ui_OpenIGTLinkProviderExampleControls.h" +#include "mitkIGTLServer.h" +#include "mitkIGTLMessageProvider.h" +#include "mitkNavigationDataToIGTLMessageFilter.h" +#include "mitkNavigationDataPlayer.h" +#include "mitkNavigationDataObjectVisualizationFilter.h" + +#include "qtimer.h" + +/** + \brief OpenIGTLinkProviderExample + + \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. + + \sa QmitkAbstractView + \ingroup ${plugin_target}_internal +*/ +class OpenIGTLinkProviderExample : public QmitkAbstractView +{ + // this is needed for all Qt objects that should have a Qt meta-object + // (everything that derives from QObject and wants to have signal/slots) + Q_OBJECT + + public: + ~OpenIGTLinkProviderExample(); + + static const std::string VIEW_ID; + + protected slots: + + void Start(); + void OnOpenFile(); + void UpdateVisualization(); + + + protected: + + virtual void CreateQtPartControl(QWidget *parent); + + virtual void SetFocus(); + + void CreatePipeline(); + void DestroyPipeline(); + + Ui::OpenIGTLinkProviderExampleControls m_Controls; + mitk::IGTLServer::Pointer m_IGTLServer; + mitk::IGTLMessageProvider::Pointer m_IGTLMessageProvider; + mitk::NavigationDataToIGTLMessageFilter::Pointer m_NavDataToIGTLMsgFilter; + mitk::NavigationDataPlayer::Pointer m_NavDataPlayer; + mitk::NavigationDataObjectVisualizationFilter::Pointer m_NavDataVisualizer; + mitk::DataNode::Pointer m_DemoNodeT1; + mitk::DataNode::Pointer m_DemoNodeT2; + mitk::DataNode::Pointer m_DemoNodeT3; + mitk::NavigationDataSet::Pointer m_NavDataSet; + QmitkIGTLStreamingConnector m_StreamingConnector; + + QTimer m_VisualizerTimer; +}; + +#endif // OpenIGTLinkProviderExample_h diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExampleControls.ui b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExampleControls.ui new file mode 100644 index 0000000000..c1cedf25bd --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExampleControls.ui @@ -0,0 +1,62 @@ + + + OpenIGTLinkProviderExampleControls + + + + 0 + 0 + 668 + 392 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + + + Open Recorded Navigation Data + + + + + + + false + + + Start Playing Recorded Navigation Data + + + + + + + Qt::Vertical + + + + 20 + 220 + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/org_mitk_gui_qt_igtlplugin_Activator.cpp b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/org_mitk_gui_qt_igtlplugin_Activator.cpp new file mode 100644 index 0000000000..cf9b299d68 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/org_mitk_gui_qt_igtlplugin_Activator.cpp @@ -0,0 +1,44 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#include "org_mitk_gui_qt_igtlplugin_Activator.h" + +#include + +#include "OpenIGTLinkProviderExample.h" +#include "OpenIGTLinkExample.h" +#include "OpenIGTLinkManager.h" + +namespace mitk { + +void org_mitk_gui_qt_igtlplugin_Activator::start(ctkPluginContext* context) +{ + BERRY_REGISTER_EXTENSION_CLASS(OpenIGTLinkProviderExample, context) + BERRY_REGISTER_EXTENSION_CLASS(OpenIGTLinkExample, context) + BERRY_REGISTER_EXTENSION_CLASS(OpenIGTLinkManager, context) +} + +void org_mitk_gui_qt_igtlplugin_Activator::stop(ctkPluginContext* context) +{ + Q_UNUSED(context) +} + +} + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + Q_EXPORT_PLUGIN2(org_mitk_gui_qt_igtlplugin, mitk::org_mitk_gui_qt_igtlplugin_Activator) +#endif diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/org_mitk_gui_qt_igtlplugin_Activator.h b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/org_mitk_gui_qt_igtlplugin_Activator.h new file mode 100644 index 0000000000..3d26668f32 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/org_mitk_gui_qt_igtlplugin_Activator.h @@ -0,0 +1,43 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef org_mitk_gui_qt_igtlplugin_Activator_h +#define org_mitk_gui_qt_igtlplugin_Activator_h + +#include + +namespace mitk { + +class org_mitk_gui_qt_igtlplugin_Activator : + public QObject, public ctkPluginActivator +{ + Q_OBJECT +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_igtlplugin") +#endif + Q_INTERFACES(ctkPluginActivator) + +public: + + void start(ctkPluginContext* context); + void stop(ctkPluginContext* context); + +}; // org_mitk_gui_qt_igtlplugin_Activator + +} + +#endif // org_mitk_gui_qt_igtlplugin_Activator_h diff --git a/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkImageCropperControls.ui b/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkImageCropperControls.ui index eec64dacb6..547a5f4816 100644 --- a/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkImageCropperControls.ui +++ b/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkImageCropperControls.ui @@ -1,426 +1,444 @@ QmitkImageCropperControls 0 0 422 651 0 0 BoundingObjectImageCropper true 170 0 0 170 0 0 170 0 0 The image cropper cannot handle 2D images false 0 0 crop the selected image Crop false 0 0 crop the selected image New bounding box! -2000 2000 -1000 0 0 Set border voxel value false -2000 2000 -1000 Qt::Horizontal 0 0 Show usage information 24 0 0 0 <!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:'Sans'; font-size:10pt; 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;">The yellow box around the selected image can be changed in size and orientation. You can use it to mark an interesing region of the image and then use the &quot;Crop&quot; button to cut off parts of the image that are outside the box.<br />The original image will not be modified, it will only be hidden.</p></body></html> Qt::AlignVCenter true - - - - - - - 0 - 0 - - - - :/imagecropper/btn_ctrl.xpm - - - false - - - false - - - - - - - - 0 - 0 - - - - :/imagecropper/mouse_left.xpm - - - false - - - false - - - - - - - Move the box - - - false - - - - - - - - - - - - 0 - 0 - - - - - - - :/imagecropper/btn_ctrl.xpm - - - false - - - false - - - - - - - - 0 - 0 - - - - :/imagecropper/mouse_middle.xpm - - - false - - - false - - - - - - - Rotate the box - - - false - - - - - - - - - - - - 0 - 0 - - - - - - - :/imagecropper/btn_ctrl.xpm - - - false - - - false - - - - - - - - 0 - 0 - - - - :/imagecropper/mouse_right.xpm - - - false - - - false - - - - - - - Resize the box - - - false - - - - - + + + + Qt::Vertical + + + QSizePolicy::Minimum + + + + 20 + 20 + + + + + + + + + + + 0 + 0 + + + + :/imagecropper/btn_ctrl.xpm + + + false + + + false + + + + + + + + 0 + 0 + + + + :/imagecropper/mouse_left.xpm + + + false + + + false + + + + + + + Move the box + + + false + + + + + + + + + + + + 0 + 0 + + + + + + + :/imagecropper/btn_ctrl.xpm + + + false + + + false + + + + + + + + 0 + 0 + + + + :/imagecropper/mouse_right.xpm + + + false + + + false + + + + + + + Resize the box + + + false + + + + + + + + + + + + 0 + 0 + + + + + + + :/imagecropper/btn_ctrl.xpm + + + false + + + false + + + + + + + + 0 + 0 + + + + :/imagecropper/mouse_middle.xpm + + + false + + + false + + + + + + + Rotate the box + + + false + + + + + Qt::Vertical QSizePolicy::Expanding 20 200 QmitkDataStorageComboBox.h + + m_SurroundingSpin valueChanged(int) m_SurroundingSlider setValue(int) 20 20 20 20 m_SurroundingSlider valueChanged(int) m_SurroundingSpin setValue(int) 20 20 20 20 diff --git a/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkMovieMaker_ScreenshotMakerInterface.png b/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkMovieMaker_ScreenshotMakerInterface.png new file mode 100644 index 0000000000..085dcbdea6 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkMovieMaker_ScreenshotMakerInterface.png differ diff --git a/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkScreenshotMaker.dox b/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkScreenshotMaker.dox new file mode 100644 index 0000000000..05b657bdeb --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker/documentation/UserManual/QmitkScreenshotMaker.dox @@ -0,0 +1,19 @@ +/** +\page org_mitk_views_screenshotmaker The Screenshot Maker + +This view provides the functionality to create and save screenshots of the data. + +Available sections: + - \ref QmitkScreenshotMakerUserManualUse + +\imageMacro{QmitkMovieMaker_ScreenshotMakerInterface.png,"The Screenshot Maker User Interface",7.09} + +\section QmitkScreenshotMakerUserManualUse Usage + +The first section offers the option of creating a screenshot of the last activated render window (thus the one, which was last clicked into). Upon clicking the button, the Screenshot Maker asks for a filename in which the screenshot is to be stored. The multiplanar Screenshot button asks for a folder, where screenshots of the three 2D views will be stored with default names. + +The high resolution screenshot section works the same as the simple screenshot section, aside from the fact, that the user can choose a magnification factor. + +In the option section one can rotate the camera in the 3D view by using the buttons. Furthermore one can choose the background colour for the screenshots, default is black. + +*/ diff --git a/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkPointBasedRegistrationView.cpp b/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkPointBasedRegistrationView.cpp index e32eefc0a4..1e5b35cfac 100644 --- a/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkPointBasedRegistrationView.cpp +++ b/Plugins/org.mitk.gui.qt.registration/src/internal/QmitkPointBasedRegistrationView.cpp @@ -1,1331 +1,1329 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkPointBasedRegistrationView.h" #include "ui_QmitkPointBasedRegistrationViewControls.h" #include "QmitkPointListWidget.h" #include #include #include #include "vtkPolyData.h" #include #include #include "qradiobutton.h" #include "qapplication.h" #include #include #include #include #include "qmessagebox.h" #include "mitkLandmarkWarping.h" #include #include #include "mitkOperationEvent.h" #include "mitkUndoController.h" -#include -#include #include "mitkNodePredicateDataType.h" #include "mitkNodePredicateProperty.h" #include "mitkNodePredicateAnd.h" #include "mitkNodePredicateNot.h" #include #include #include #include "mitkDataNodeObject.h" #include "berryIWorkbenchWindow.h" #include "berryISelectionService.h" const std::string QmitkPointBasedRegistrationView::VIEW_ID = "org.mitk.views.pointbasedregistration"; using namespace berry; struct SelListenerPointBasedRegistration : ISelectionListener { berryObjectMacro(SelListenerPointBasedRegistration); SelListenerPointBasedRegistration(QmitkPointBasedRegistrationView* 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) { if (m_View->m_CurrentSelection->Size() != 2) { if (m_View->m_FixedNode.IsNull() || m_View->m_MovingNode.IsNull()) { m_View->m_Controls.m_StatusLabel->show(); m_View->m_Controls.TextLabelFixed->hide(); m_View->m_Controls.m_FixedLabel->hide(); m_View->m_Controls.line2->hide(); m_View->m_Controls.m_FixedPointListWidget->hide(); m_View->m_Controls.TextLabelMoving->hide(); m_View->m_Controls.m_MovingLabel->hide(); m_View->m_Controls.line1->hide(); m_View->m_Controls.m_MovingPointListWidget->hide(); m_View->m_Controls.m_OpacityLabel->hide(); m_View->m_Controls.m_OpacitySlider->hide(); m_View->m_Controls.label->hide(); m_View->m_Controls.label_2->hide(); m_View->m_Controls.m_SwitchImages->hide(); m_View->m_Controls.m_ShowRedGreenValues->setEnabled(false); } } else { m_View->m_Controls.m_StatusLabel->hide(); bool foundFixedImage = false; mitk::DataNode::Pointer fixedNode; // 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::TNodePredicateDataType::Pointer isBaseData(mitk::TNodePredicateDataType::New()); mitk::TNodePredicateDataType::Pointer isPointSet(mitk::TNodePredicateDataType::New()); mitk::NodePredicateNot::Pointer notPointSet = mitk::NodePredicateNot::New(isPointSet); mitk::TNodePredicateDataType::Pointer isPlaneGeometryData(mitk::TNodePredicateDataType::New()); mitk::NodePredicateNot::Pointer notPlaneGeometryData = mitk::NodePredicateNot::New(isPlaneGeometryData); mitk::NodePredicateAnd::Pointer notPointSetAndNotPlaneGeometryData = mitk::NodePredicateAnd::New( notPointSet, notPlaneGeometryData ); mitk::NodePredicateAnd::Pointer predicate = mitk::NodePredicateAnd::New( isBaseData, notPointSetAndNotPlaneGeometryData ); mitk::DataStorage::SetOfObjects::ConstPointer setOfObjects = m_View->GetDataStorage()->GetSubset(predicate); mitk::DataNode::Pointer node = nodeObj->GetDataNode(); // only look at interesting types for (mitk::DataStorage::SetOfObjects::ConstIterator nodeIt = setOfObjects->Begin() ; nodeIt != setOfObjects->End(); ++nodeIt) // for each node { if(nodeIt->Value().GetPointer() == node.GetPointer()) { // was - compare() // use contain to allow other Image types to be selected, i.e. a diffusion image if (QString( node->GetData()->GetNameOfClass() ).contains("Image") ) { // verify that the node selected by name is really an image or derived class mitk::Image* _image = dynamic_cast(node->GetData()); if (_image != NULL) { if( _image->GetDimension() == 4) { m_View->m_Controls.m_StatusLabel->show(); QMessageBox::information( NULL, "PointBasedRegistration", "Only 2D or 3D images can be processed.", QMessageBox::Ok ); return; } if (foundFixedImage == false) { fixedNode = node; foundFixedImage = true; } else { // method deleted for more information see bug-18492 // m_View->SetImagesVisible(selection); m_View->FixedSelected(fixedNode); m_View->MovingSelected(node); m_View->m_Controls.m_StatusLabel->hide(); m_View->m_Controls.TextLabelFixed->show(); m_View->m_Controls.m_FixedLabel->show(); m_View->m_Controls.line2->show(); m_View->m_Controls.m_FixedPointListWidget->show(); m_View->m_Controls.TextLabelMoving->show(); m_View->m_Controls.m_MovingLabel->show(); m_View->m_Controls.line1->show(); m_View->m_Controls.m_MovingPointListWidget->show(); m_View->m_Controls.m_OpacityLabel->show(); m_View->m_Controls.m_OpacitySlider->show(); m_View->m_Controls.label->show(); m_View->m_Controls.label_2->show(); m_View->m_Controls.m_SwitchImages->show(); m_View->m_Controls.m_ShowRedGreenValues->setEnabled(true); } } } else { m_View->m_Controls.m_StatusLabel->show(); return; } } } } } if (m_View->m_FixedNode.IsNull() || m_View->m_MovingNode.IsNull()) { m_View->m_Controls.m_StatusLabel->show(); } } } else if (m_View->m_FixedNode.IsNull() || m_View->m_MovingNode.IsNull()) { m_View->m_Controls.m_StatusLabel->show(); } } 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("Data Manager")==0) { // apply selection DoSelectionChanged(selection); } } } QmitkPointBasedRegistrationView* m_View; }; QmitkPointBasedRegistrationView::QmitkPointBasedRegistrationView(QObject * /*parent*/, const char * /*name*/) : QmitkFunctionality(), m_SelListener(0), m_MultiWidget(NULL), m_FixedLandmarks(NULL), m_MovingLandmarks(NULL), m_MovingNode(NULL), m_FixedNode(NULL), m_ShowRedGreen(false), m_Opacity(0.5), m_OriginalOpacity(1.0), m_Transformation(0), m_HideFixedImage(false), m_HideMovingImage(false), m_OldFixedLabel(""), m_OldMovingLabel(""), m_Deactivated (false), m_CurrentFixedLandmarksObserverID(0), m_CurrentMovingLandmarksObserverID(0) { m_FixedLandmarksChangedCommand = itk::SimpleMemberCommand::New(); m_FixedLandmarksChangedCommand->SetCallbackFunction(this, &QmitkPointBasedRegistrationView::updateFixedLandmarksList); m_MovingLandmarksChangedCommand = itk::SimpleMemberCommand::New(); m_MovingLandmarksChangedCommand->SetCallbackFunction(this, &QmitkPointBasedRegistrationView::updateMovingLandmarksList); this->GetDataStorage()->RemoveNodeEvent.AddListener(mitk::MessageDelegate1 ( this, &QmitkPointBasedRegistrationView::DataNodeHasBeenRemoved )); } QmitkPointBasedRegistrationView::~QmitkPointBasedRegistrationView() { if(m_SelListener.IsNotNull()) { berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService(); if(s) s->RemovePostSelectionListener(m_SelListener); m_SelListener = NULL; } if (m_FixedPointSetNode.IsNotNull()) { m_Controls.m_FixedPointListWidget->DeactivateInteractor(true); m_FixedPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldFixedLabel)); } if (m_MovingPointSetNode.IsNotNull()) { m_Controls.m_MovingPointListWidget->DeactivateInteractor(true); m_MovingPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldMovingLabel)); } m_Controls.m_FixedPointListWidget->SetPointSetNode(NULL); m_Controls.m_MovingPointListWidget->SetPointSetNode(NULL); } void QmitkPointBasedRegistrationView::CreateQtPartControl(QWidget* parent) { m_Controls.setupUi(parent); m_Parent->setEnabled(false); m_Controls.m_MeanErrorLCD->hide(); m_Controls.m_MeanError->hide(); m_Controls.TextLabelFixed->hide(); m_Controls.line2->hide(); m_Controls.m_FixedPointListWidget->hide(); m_Controls.m_FixedLabel->hide(); m_Controls.TextLabelMoving->hide(); m_Controls.m_MovingLabel->hide(); m_Controls.line1->hide(); m_Controls.m_MovingPointListWidget->hide(); m_Controls.m_OpacityLabel->hide(); m_Controls.m_OpacitySlider->hide(); m_Controls.label->hide(); m_Controls.label_2->hide(); m_Controls.m_SwitchImages->hide(); m_Controls.m_ShowRedGreenValues->setEnabled(false); this->CreateConnections(); // let the point set widget know about the multi widget (cross hair updates) m_Controls.m_FixedPointListWidget->SetMultiWidget( m_MultiWidget ); m_Controls.m_MovingPointListWidget->SetMultiWidget( m_MultiWidget ); } void QmitkPointBasedRegistrationView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_Parent->setEnabled(true); m_MultiWidget = &stdMultiWidget; m_MultiWidget->SetWidgetPlanesVisibility(true); m_Controls.m_FixedPointListWidget->SetMultiWidget( m_MultiWidget ); m_Controls.m_MovingPointListWidget->SetMultiWidget( m_MultiWidget ); } void QmitkPointBasedRegistrationView::StdMultiWidgetNotAvailable() { m_Parent->setEnabled(false); m_MultiWidget = NULL; m_Controls.m_FixedPointListWidget->SetMultiWidget( NULL ); m_Controls.m_MovingPointListWidget->SetMultiWidget( NULL ); } void QmitkPointBasedRegistrationView::CreateConnections() { connect( (QObject*)(m_Controls.m_FixedPointListWidget), SIGNAL(EditPointSets(bool)), (QObject*)(m_Controls.m_MovingPointListWidget), SLOT(DeactivateInteractor(bool))); connect( (QObject*)(m_Controls.m_MovingPointListWidget), SIGNAL(EditPointSets(bool)), (QObject*)(m_Controls.m_FixedPointListWidget), SLOT(DeactivateInteractor(bool))); connect( (QObject*)(m_Controls.m_FixedPointListWidget), SIGNAL(EditPointSets(bool)), this, SLOT(HideMovingImage(bool))); connect( (QObject*)(m_Controls.m_MovingPointListWidget), SIGNAL(EditPointSets(bool)), this, SLOT(HideFixedImage(bool))); connect( (QObject*)(m_Controls.m_FixedPointListWidget), SIGNAL(PointListChanged()), this, SLOT(updateFixedLandmarksList())); connect( (QObject*)(m_Controls.m_MovingPointListWidget), SIGNAL(PointListChanged()), this, SLOT(updateMovingLandmarksList())); connect((QObject*)(m_Controls.m_Calculate),SIGNAL(clicked()),this,SLOT(calculate())); connect((QObject*)(m_Controls.m_SwitchImages),SIGNAL(clicked()),this,SLOT(SwitchImages())); connect((QObject*)(m_Controls.m_UndoTransformation),SIGNAL(clicked()),this,SLOT(UndoTransformation())); connect((QObject*)(m_Controls.m_RedoTransformation),SIGNAL(clicked()),this,SLOT(RedoTransformation())); connect((QObject*)(m_Controls.m_ShowRedGreenValues),SIGNAL(toggled(bool)),this,SLOT(showRedGreen(bool))); connect((QObject*)(m_Controls.m_OpacitySlider),SIGNAL(valueChanged(int)),this,SLOT(OpacityUpdate(int))); connect((QObject*)(m_Controls.m_SelectedTransformationClass),SIGNAL(activated(int)), this,SLOT(transformationChanged(int))); connect((QObject*)(m_Controls.m_UseICP),SIGNAL(toggled(bool)), this,SLOT(checkCalculateEnabled())); connect((QObject*)(m_Controls.m_UseICP),SIGNAL(toggled(bool)), this,SLOT(checkLandmarkError())); } void QmitkPointBasedRegistrationView::Activated() { m_Deactivated = false; mitk::RenderingManager::GetInstance()->RequestUpdateAll(); QmitkFunctionality::Activated(); this->clearTransformationLists(); if (m_SelListener.IsNull()) { m_SelListener = berry::ISelectionListener::Pointer(new SelListenerPointBasedRegistration(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); } this->OpacityUpdate(m_Controls.m_OpacitySlider->value()); this->showRedGreen(m_Controls.m_ShowRedGreenValues->isChecked()); } void QmitkPointBasedRegistrationView::Visible() { } void QmitkPointBasedRegistrationView::Deactivated() { m_Deactivated = true; if (m_FixedPointSetNode.IsNotNull()) m_FixedPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldFixedLabel)); m_Controls.m_FixedPointListWidget->SetPointSetNode(NULL); m_Controls.m_FixedPointListWidget->DeactivateInteractor(true); if (m_MovingPointSetNode.IsNotNull()) m_MovingPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldMovingLabel)); m_Controls.m_MovingPointListWidget->SetPointSetNode(NULL); m_Controls.m_MovingPointListWidget->DeactivateInteractor(true); this->setImageColor(false); if (m_FixedNode.IsNotNull()) m_FixedNode->SetOpacity(1.0); if (m_MovingNode.IsNotNull()) { m_MovingNode->SetOpacity(m_OriginalOpacity); } this->clearTransformationLists(); if (m_FixedPointSetNode.IsNotNull() && m_FixedLandmarks.IsNotNull() && m_FixedLandmarks->GetSize() == 0) { this->GetDataStorage()->Remove(m_FixedPointSetNode); } if (m_MovingPointSetNode.IsNotNull() && m_MovingLandmarks.IsNotNull() && m_MovingLandmarks->GetSize() == 0) { this->GetDataStorage()->Remove(m_MovingPointSetNode); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); m_FixedNode = NULL; m_MovingNode = NULL; if(m_FixedLandmarks.IsNotNull()) m_FixedLandmarks->RemoveObserver(m_CurrentFixedLandmarksObserverID); m_FixedLandmarks = NULL; if(m_MovingLandmarks.IsNotNull()) m_MovingLandmarks->RemoveObserver(m_CurrentMovingLandmarksObserverID); m_MovingLandmarks = NULL; m_FixedPointSetNode = NULL; m_MovingPointSetNode = NULL; m_Controls.m_FixedLabel->hide(); m_Controls.TextLabelFixed->hide(); m_Controls.line2->hide(); m_Controls.m_FixedPointListWidget->hide(); m_Controls.m_MovingLabel->hide(); m_Controls.TextLabelMoving->hide(); m_Controls.line1->hide(); m_Controls.m_MovingPointListWidget->hide(); m_Controls.m_OpacityLabel->hide(); m_Controls.m_OpacitySlider->hide(); m_Controls.label->hide(); m_Controls.label_2->hide(); m_Controls.m_SwitchImages->hide(); berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService(); if(s) s->RemovePostSelectionListener(m_SelListener); m_SelListener = NULL; } void QmitkPointBasedRegistrationView::Hidden() { /* m_Deactivated = true; if (m_FixedPointSetNode.IsNotNull()) m_FixedPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldFixedLabel)); m_Controls.m_FixedPointListWidget->SetPointSetNode(NULL); m_Controls.m_FixedPointListWidget->DeactivateInteractor(true); if (m_MovingPointSetNode.IsNotNull()) m_MovingPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldMovingLabel)); m_Controls.m_MovingPointListWidget->SetPointSetNode(NULL); m_Controls.m_MovingPointListWidget->DeactivateInteractor(true); this->setImageColor(false); if (m_MovingNode.IsNotNull()) { m_MovingNode->SetOpacity(m_OriginalOpacity); } this->clearTransformationLists(); if (m_FixedPointSetNode.IsNotNull() && m_FixedLandmarks.IsNotNull() && m_FixedLandmarks->GetSize() == 0) { this->GetDataStorage()->Remove(m_FixedPointSetNode); } if (m_MovingPointSetNode.IsNotNull() && m_MovingLandmarks.IsNotNull() && m_MovingLandmarks->GetSize() == 0) { this->GetDataStorage()->Remove(m_MovingPointSetNode); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); m_FixedNode = NULL; m_MovingNode = NULL; if(m_FixedLandmarks.IsNotNull()) m_FixedLandmarks->RemoveObserver(m_CurrentFixedLandmarksObserverID); m_FixedLandmarks = NULL; if(m_MovingLandmarks.IsNotNull()) m_MovingLandmarks->RemoveObserver(m_CurrentMovingLandmarksObserverID); m_MovingLandmarks = NULL; m_FixedPointSetNode = NULL; m_MovingPointSetNode = NULL; m_Controls.m_FixedLabel->hide(); m_Controls.TextLabelFixed->hide(); m_Controls.line2->hide(); m_Controls.m_FixedPointListWidget->hide(); m_Controls.m_MovingLabel->hide(); m_Controls.TextLabelMoving->hide(); m_Controls.line1->hide(); m_Controls.m_MovingPointListWidget->hide(); m_Controls.m_OpacityLabel->hide(); m_Controls.m_OpacitySlider->hide(); m_Controls.label->hide(); m_Controls.label_2->hide(); m_Controls.m_SwitchImages->hide(); berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService(); if(s) s->RemovePostSelectionListener(m_SelListener); m_SelListener = NULL; //mitk::RenderingManager::GetInstance()->RequestUpdateAll(); //QmitkFunctionality::Deactivated();*/ } void QmitkPointBasedRegistrationView::DataNodeHasBeenRemoved(const mitk::DataNode* node) { if(node == m_FixedNode || node == m_MovingNode) { m_Controls.m_StatusLabel->show(); m_Controls.TextLabelFixed->hide(); m_Controls.m_FixedLabel->hide(); m_Controls.line2->hide(); m_Controls.m_FixedPointListWidget->hide(); m_Controls.TextLabelMoving->hide(); m_Controls.m_MovingLabel->hide(); m_Controls.line1->hide(); m_Controls.m_MovingPointListWidget->hide(); m_Controls.m_OpacityLabel->hide(); m_Controls.m_OpacitySlider->hide(); m_Controls.label->hide(); m_Controls.label_2->hide(); m_Controls.m_SwitchImages->hide(); m_Controls.m_ShowRedGreenValues->setEnabled(false); } } void QmitkPointBasedRegistrationView::FixedSelected(mitk::DataNode::Pointer fixedImage) { if(m_FixedLandmarks.IsNotNull()) m_FixedLandmarks->RemoveObserver(m_CurrentFixedLandmarksObserverID); if (fixedImage.IsNotNull()) { if (m_FixedNode != fixedImage) { // remove changes on previous selected node if (m_FixedNode.IsNotNull()) { this->setImageColor(false); m_FixedNode->SetOpacity(1.0); if (m_FixedPointSetNode.IsNotNull()) { m_FixedPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldFixedLabel)); } } // get selected node m_FixedNode = fixedImage; m_FixedNode->SetOpacity(0.5); m_FixedNode->SetVisibility(true); m_Controls.m_FixedLabel->setText(QString::fromStdString(m_FixedNode->GetName())); m_Controls.m_FixedLabel->show(); m_Controls.m_SwitchImages->show(); m_Controls.TextLabelFixed->show(); m_Controls.line2->show(); m_Controls.m_FixedPointListWidget->show(); mitk::ColorProperty::Pointer colorProperty; colorProperty = dynamic_cast(m_FixedNode->GetProperty("color")); if ( colorProperty.IsNotNull() ) { m_FixedColor = colorProperty->GetColor(); } this->setImageColor(m_ShowRedGreen); bool hasPointSetNode = false; mitk::DataStorage::SetOfObjects::ConstPointer children = this->GetDataStorage()->GetDerivations(m_FixedNode); unsigned long size; size = children->Size(); for (unsigned long i = 0; i < size; ++i) { mitk::StringProperty::Pointer nameProp = dynamic_cast(children->GetElement(i)->GetProperty("name")); if(nameProp.IsNotNull() && nameProp->GetValueAsString()=="PointBasedRegistrationNode") { m_FixedPointSetNode=children->GetElement(i); m_FixedLandmarks = dynamic_cast (m_FixedPointSetNode->GetData()); this->GetDataStorage()->Remove(m_FixedPointSetNode); hasPointSetNode = true; break; } } if (!hasPointSetNode) { m_FixedLandmarks = mitk::PointSet::New(); m_FixedPointSetNode = mitk::DataNode::New(); m_FixedPointSetNode->SetData(m_FixedLandmarks); m_FixedPointSetNode->SetProperty("name", mitk::StringProperty::New("PointBasedRegistrationNode")); } m_FixedPointSetNode->GetStringProperty("label", m_OldFixedLabel); m_FixedPointSetNode->SetProperty("label", mitk::StringProperty::New("F ")); m_FixedPointSetNode->SetProperty("color", mitk::ColorProperty::New(0.0f, 1.0f, 1.0f)); m_FixedPointSetNode->SetVisibility(true); m_Controls.m_FixedPointListWidget->SetPointSetNode(m_FixedPointSetNode); this->GetDataStorage()->Add(m_FixedPointSetNode, m_FixedNode); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } if (m_FixedPointSetNode.IsNull()) { m_FixedLandmarks = mitk::PointSet::New(); m_FixedPointSetNode = mitk::DataNode::New(); m_FixedPointSetNode->SetData(m_FixedLandmarks); m_FixedPointSetNode->SetProperty("name", mitk::StringProperty::New("PointBasedRegistrationNode")); m_FixedPointSetNode->GetStringProperty("label", m_OldFixedLabel); m_FixedPointSetNode->SetProperty("label", mitk::StringProperty::New("F ")); m_FixedPointSetNode->SetProperty("color", mitk::ColorProperty::New(0.0f, 1.0f, 1.0f)); m_FixedPointSetNode->SetVisibility(true); m_Controls.m_FixedPointListWidget->SetPointSetNode(m_FixedPointSetNode); this->GetDataStorage()->Add(m_FixedPointSetNode, m_FixedNode); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } else { m_FixedNode = NULL; if (m_FixedPointSetNode.IsNotNull()) m_FixedPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldFixedLabel)); m_FixedPointSetNode = NULL; m_FixedLandmarks = NULL; m_Controls.m_FixedPointListWidget->SetPointSetNode(m_FixedPointSetNode); m_Controls.m_FixedLabel->hide(); m_Controls.TextLabelFixed->hide(); m_Controls.line2->hide(); m_Controls.m_FixedPointListWidget->hide(); m_Controls.m_SwitchImages->hide(); } if(m_FixedLandmarks.IsNotNull()) m_CurrentFixedLandmarksObserverID = m_FixedLandmarks->AddObserver(itk::ModifiedEvent(), m_FixedLandmarksChangedCommand); } void QmitkPointBasedRegistrationView::MovingSelected(mitk::DataNode::Pointer movingImage) { if(m_MovingLandmarks.IsNotNull()) m_MovingLandmarks->RemoveObserver(m_CurrentMovingLandmarksObserverID); if (movingImage.IsNotNull()) { if (m_MovingNode != movingImage) { if (m_MovingNode.IsNotNull()) { m_MovingNode->SetOpacity(m_OriginalOpacity); if (m_FixedNode == m_MovingNode) m_FixedNode->SetOpacity(0.5); this->setImageColor(false); if (m_MovingNode != m_FixedNode) { m_MovingPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldMovingLabel)); } else { m_OldFixedLabel = m_OldMovingLabel; } } if (m_MovingPointSetNode.IsNotNull()) m_MovingPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldMovingLabel)); m_MovingNode = movingImage; m_MovingNode->SetVisibility(true); m_Controls.m_MovingLabel->setText(QString::fromStdString(m_MovingNode->GetName())); m_Controls.m_MovingLabel->show(); m_Controls.TextLabelMoving->show(); m_Controls.line1->show(); m_Controls.m_MovingPointListWidget->show(); m_Controls.m_OpacityLabel->show(); m_Controls.m_OpacitySlider->show(); m_Controls.label->show(); m_Controls.label_2->show(); mitk::ColorProperty::Pointer colorProperty; colorProperty = dynamic_cast(m_MovingNode->GetProperty("color")); if ( colorProperty.IsNotNull() ) { m_MovingColor = colorProperty->GetColor(); } this->setImageColor(m_ShowRedGreen); m_MovingNode->GetFloatProperty("opacity", m_OriginalOpacity); this->OpacityUpdate(m_Opacity); bool hasPointSetNode = false; mitk::DataStorage::SetOfObjects::ConstPointer children = this->GetDataStorage()->GetDerivations(m_MovingNode); unsigned long size; size = children->Size(); for (unsigned long i = 0; i < size; ++i) { mitk::StringProperty::Pointer nameProp = dynamic_cast(children->GetElement(i)->GetProperty("name")); if(nameProp.IsNotNull() && nameProp->GetValueAsString()=="PointBasedRegistrationNode") { m_MovingPointSetNode=children->GetElement(i); m_MovingLandmarks = dynamic_cast (m_MovingPointSetNode->GetData()); this->GetDataStorage()->Remove(m_MovingPointSetNode); hasPointSetNode = true; break; } } if (!hasPointSetNode) { m_MovingLandmarks = mitk::PointSet::New(); m_MovingPointSetNode = mitk::DataNode::New(); m_MovingPointSetNode->SetData(m_MovingLandmarks); m_MovingPointSetNode->SetProperty("name", mitk::StringProperty::New("PointBasedRegistrationNode")); } this->GetDataStorage()->Add(m_MovingPointSetNode, m_MovingNode); m_MovingPointSetNode->GetStringProperty("label", m_OldMovingLabel); m_MovingPointSetNode->SetProperty("label", mitk::StringProperty::New("M ")); m_MovingPointSetNode->SetProperty("color", mitk::ColorProperty::New(1.0f, 1.0f, 0.0f)); m_MovingPointSetNode->SetVisibility(true); m_Controls.m_MovingPointListWidget->SetPointSetNode(m_MovingPointSetNode); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); this->clearTransformationLists(); this->OpacityUpdate(m_Opacity); } if (m_MovingPointSetNode.IsNull()) { m_MovingLandmarks = mitk::PointSet::New(); m_MovingPointSetNode = mitk::DataNode::New(); m_MovingPointSetNode->SetData(m_MovingLandmarks); m_MovingPointSetNode->SetProperty("name", mitk::StringProperty::New("PointBasedRegistrationNode")); m_MovingPointSetNode->GetStringProperty("label", m_OldMovingLabel); m_MovingPointSetNode->SetProperty("label", mitk::StringProperty::New("M ")); m_MovingPointSetNode->SetProperty("color", mitk::ColorProperty::New(1.0f, 1.0f, 0.0f)); m_MovingPointSetNode->SetVisibility(true); m_Controls.m_MovingPointListWidget->SetPointSetNode(m_MovingPointSetNode); this->GetDataStorage()->Add(m_MovingPointSetNode, m_MovingNode); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } else { m_MovingNode = NULL; if (m_MovingPointSetNode.IsNotNull()) m_MovingPointSetNode->SetProperty("label", mitk::StringProperty::New(m_OldMovingLabel)); m_MovingPointSetNode = NULL; m_MovingLandmarks = NULL; m_Controls.m_MovingPointListWidget->SetPointSetNode(m_MovingPointSetNode); m_Controls.m_MovingLabel->hide(); m_Controls.TextLabelMoving->hide(); m_Controls.line1->hide(); m_Controls.m_MovingPointListWidget->hide(); m_Controls.m_OpacityLabel->hide(); m_Controls.m_OpacitySlider->hide(); m_Controls.label->hide(); m_Controls.label_2->hide(); } if(m_MovingLandmarks.IsNotNull()) m_CurrentMovingLandmarksObserverID = m_MovingLandmarks->AddObserver(itk::ModifiedEvent(), m_MovingLandmarksChangedCommand); } void QmitkPointBasedRegistrationView::updateMovingLandmarksList() { // mitk::PointSet* ps = mitk::PointSet::New(); // ps = dynamic_cast(m_MovingPointSetNode->GetData()); // mitk::DataNode::Pointer tmpPtr = m_MovingPointSetNode; // m_MovingLandmarks = 0; // m_MovingLandmarks = (ps); m_MovingLandmarks = dynamic_cast(m_MovingPointSetNode->GetData()); // m_Controls.m_MovingPointListWidget->SetPointSetNode(m_MovingPointSetNode); //Workaround: m_MovingPointListWidget->m_PointListView->m_PointListModel loses the pointer on the pointsetnode this->checkLandmarkError(); this->CheckCalculate(); } void QmitkPointBasedRegistrationView::updateFixedLandmarksList() { m_FixedLandmarks = dynamic_cast(m_FixedPointSetNode->GetData()); this->checkLandmarkError(); this->CheckCalculate(); } void QmitkPointBasedRegistrationView::HideFixedImage(bool hide) { m_HideFixedImage = hide; if(m_FixedNode.IsNotNull()) { m_FixedNode->SetVisibility(!hide); } if (hide) { //this->reinitMovingClicked(); } if (!m_HideMovingImage && !m_HideFixedImage) { //this->globalReinitClicked(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPointBasedRegistrationView::HideMovingImage(bool hide) { m_HideMovingImage = hide; if(m_MovingNode.IsNotNull()) { m_MovingNode->SetVisibility(!hide); } if (hide) { //this->reinitFixedClicked(); } if (!m_HideMovingImage && !m_HideFixedImage) { //this->globalReinitClicked(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } bool QmitkPointBasedRegistrationView::CheckCalculate() { if((m_MovingPointSetNode.IsNull())||(m_FixedPointSetNode.IsNull()||m_FixedLandmarks.IsNull()||m_MovingLandmarks.IsNull())) return false; if(m_MovingNode==m_FixedNode) return false; return this->checkCalculateEnabled(); } void QmitkPointBasedRegistrationView::UndoTransformation() { if(!m_UndoPointsGeometryList.empty()) { mitk::BaseGeometry::Pointer movingLandmarksGeometry = m_MovingLandmarks->GetGeometry(0)->Clone(); m_RedoPointsGeometryList.push_back(movingLandmarksGeometry.GetPointer()); m_MovingLandmarks->SetGeometry(m_UndoPointsGeometryList.back()); m_UndoPointsGeometryList.pop_back(); //\FIXME when geometry is substituted the matrix referenced by the actor created by the mapper //is still pointing to the old one. Workaround: delete mapper m_MovingPointSetNode->SetMapper(1, NULL); mitk::BaseData::Pointer movingData = m_MovingNode->GetData(); mitk::BaseGeometry::Pointer movingGeometry = movingData->GetGeometry(0)->Clone(); m_RedoGeometryList.push_back(movingGeometry.GetPointer()); movingData->SetGeometry(m_UndoGeometryList.back()); m_UndoGeometryList.pop_back(); //\FIXME when geometry is substituted the matrix referenced by the actor created by the mapper //is still pointing to the old one. Workaround: delete mapper m_MovingNode->SetMapper(1, NULL); mitk::RenderingManager::GetInstance()->RequestUpdate(m_MultiWidget->mitkWidget4->GetRenderWindow()); movingData->GetTimeGeometry()->Update(); m_MovingLandmarks->GetTimeGeometry()->Update(); m_Controls.m_RedoTransformation->setEnabled(true); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); this->checkLandmarkError(); } if(!m_UndoPointsGeometryList.empty()) { m_Controls.m_UndoTransformation->setEnabled(true); } else { m_Controls.m_UndoTransformation->setEnabled(false); } } void QmitkPointBasedRegistrationView::RedoTransformation() { if(!m_RedoPointsGeometryList.empty()) { mitk::BaseGeometry::Pointer movingLandmarksGeometry = m_MovingLandmarks->GetGeometry(0)->Clone(); m_UndoPointsGeometryList.push_back(movingLandmarksGeometry.GetPointer()); m_MovingLandmarks->SetGeometry(m_RedoPointsGeometryList.back()); m_RedoPointsGeometryList.pop_back(); //\FIXME when geometry is substituted the matrix referenced by the actor created by the mapper //is still pointing to the old one. Workaround: delete mapper m_MovingPointSetNode->SetMapper(1, NULL); mitk::BaseData::Pointer movingData = m_MovingNode->GetData(); mitk::BaseGeometry::Pointer movingGeometry = movingData->GetGeometry(0)->Clone(); m_UndoGeometryList.push_back(movingGeometry.GetPointer()); movingData->SetGeometry(m_RedoGeometryList.back()); m_RedoGeometryList.pop_back(); //\FIXME when geometry is substituted the matrix referenced by the actor created by the mapper //is still pointing to the old one. Workaround: delete mapper m_MovingNode->SetMapper(1, NULL); mitk::RenderingManager::GetInstance()->RequestUpdate(m_MultiWidget->mitkWidget4->GetRenderWindow()); movingData->GetTimeGeometry()->Update(); m_MovingLandmarks->GetTimeGeometry()->Update(); m_Controls.m_UndoTransformation->setEnabled(true); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); this->checkLandmarkError(); } if(!m_RedoPointsGeometryList.empty()) { m_Controls.m_RedoTransformation->setEnabled(true); } else { m_Controls.m_RedoTransformation->setEnabled(false); } } void QmitkPointBasedRegistrationView::showRedGreen(bool redGreen) { m_ShowRedGreen = redGreen; this->setImageColor(m_ShowRedGreen); } void QmitkPointBasedRegistrationView::setImageColor(bool redGreen) { if (!redGreen && m_FixedNode.IsNotNull()) { m_FixedNode->SetColor(m_FixedColor); } if (!redGreen && m_MovingNode.IsNotNull()) { m_MovingNode->SetColor(m_MovingColor); } if (redGreen && m_FixedNode.IsNotNull()) { m_FixedNode->SetColor(1.0f, 0.0f, 0.0f); } if (redGreen && m_MovingNode.IsNotNull()) { m_MovingNode->SetColor(0.0f, 1.0f, 0.0f); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPointBasedRegistrationView::OpacityUpdate(float opacity) { if (opacity > 1) { opacity = opacity/100.0f; } m_Opacity = opacity; if (m_MovingNode.IsNotNull()) { m_MovingNode->SetOpacity(m_Opacity); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPointBasedRegistrationView::OpacityUpdate(int opacity) { float fValue = ((float)opacity)/100.0f; this->OpacityUpdate(fValue); } void QmitkPointBasedRegistrationView::clearTransformationLists() { m_Controls.m_UndoTransformation->setEnabled(false); m_Controls.m_RedoTransformation->setEnabled(false); m_Controls.m_MeanErrorLCD->hide(); m_Controls.m_MeanError->hide(); m_UndoGeometryList.clear(); m_UndoPointsGeometryList.clear(); m_RedoGeometryList.clear(); m_RedoPointsGeometryList.clear(); } void QmitkPointBasedRegistrationView::checkLandmarkError() { double totalDist = 0, dist = 0, dist2 = 0; mitk::Point3D point1, point2, point3; double p1[3], p2[3]; if(m_Transformation < 3) { if (m_Controls.m_UseICP->isChecked()) { if (m_MovingLandmarks.IsNotNull() && m_FixedLandmarks.IsNotNull()&& m_MovingLandmarks->GetSize() != 0 && m_FixedLandmarks->GetSize() != 0) { for(int pointId = 0; pointId < m_MovingLandmarks->GetSize(); ++pointId) { point1 = m_MovingLandmarks->GetPoint(pointId); point2 = m_FixedLandmarks->GetPoint(0); p1[0] = point1[0]; p1[1] = point1[1]; p1[2] = point1[2]; p2[0] = point2[0]; p2[1] = point2[1]; p2[2] = point2[2]; dist = vtkMath::Distance2BetweenPoints(p1, p2); for(int pointId2 = 1; pointId2 < m_FixedLandmarks->GetSize(); ++pointId2) { point2 = m_FixedLandmarks->GetPoint(pointId2); p1[0] = point1[0]; p1[1] = point1[1]; p1[2] = p1[2]; p2[0] = point2[0]; p2[1] = point2[1]; p2[2] = p2[2]; dist2 = vtkMath::Distance2BetweenPoints(p1, p2); if (dist2 < dist) { dist = dist2; } } totalDist += dist; } m_Controls.m_MeanErrorLCD->display(sqrt(totalDist/m_FixedLandmarks->GetSize())); m_Controls.m_MeanErrorLCD->show(); m_Controls.m_MeanError->show(); } else { m_Controls.m_MeanErrorLCD->hide(); m_Controls.m_MeanError->hide(); } } else { if (m_MovingLandmarks.IsNotNull() && m_FixedLandmarks.IsNotNull() && m_MovingLandmarks->GetSize() != 0 && m_FixedLandmarks->GetSize() != 0 && m_MovingLandmarks->GetSize() == m_FixedLandmarks->GetSize()) { for(int pointId = 0; pointId < m_MovingLandmarks->GetSize(); ++pointId) { point1 = m_MovingLandmarks->GetPoint(pointId); point2 = m_FixedLandmarks->GetPoint(pointId); p1[0] = point1[0]; p1[1] = point1[1]; p1[2] = point1[2]; p2[0] = point2[0]; p2[1] = point2[1]; p2[2] = point2[2]; totalDist += vtkMath::Distance2BetweenPoints(p1, p2); } m_Controls.m_MeanErrorLCD->display(sqrt(totalDist/m_FixedLandmarks->GetSize())); m_Controls.m_MeanErrorLCD->show(); m_Controls.m_MeanError->show(); } else { m_Controls.m_MeanErrorLCD->hide(); m_Controls.m_MeanError->hide(); } } } else { if (m_MovingLandmarks.IsNotNull() && m_FixedLandmarks.IsNotNull() && m_MovingLandmarks->GetSize() != 0 && m_FixedLandmarks->GetSize() != 0 && m_MovingLandmarks->GetSize() == m_FixedLandmarks->GetSize()) { for(int pointId = 0; pointId < m_MovingLandmarks->GetSize(); ++pointId) { point1 = m_MovingLandmarks->GetPoint(pointId); point2 = m_FixedLandmarks->GetPoint(pointId); p1[0] = point1[0]; p1[1] = point1[1]; p1[2] = point1[2]; p2[0] = point2[0]; p2[1] = point2[1]; p2[2] = point2[2]; totalDist += vtkMath::Distance2BetweenPoints(p1, p2); } m_Controls.m_MeanErrorLCD->display(sqrt(totalDist/m_FixedLandmarks->GetSize())); m_Controls.m_MeanErrorLCD->show(); m_Controls.m_MeanError->show(); } else { m_Controls.m_MeanErrorLCD->hide(); m_Controls.m_MeanError->hide(); } } } void QmitkPointBasedRegistrationView::transformationChanged(int transform) { m_Transformation = transform; this->checkCalculateEnabled(); this->checkLandmarkError(); } // ICP with vtkLandmarkTransformation void QmitkPointBasedRegistrationView::calculateLandmarkbasedWithICP() { if(CheckCalculate()) { mitk::BaseGeometry::Pointer pointsGeometry = m_MovingLandmarks->GetGeometry(0); mitk::BaseGeometry::Pointer movingLandmarksGeometry = m_MovingLandmarks->GetGeometry(0)->Clone(); m_UndoPointsGeometryList.push_back(movingLandmarksGeometry.GetPointer()); mitk::BaseData::Pointer originalData = m_MovingNode->GetData(); mitk::BaseGeometry::Pointer originalDataGeometry = originalData->GetGeometry(0)->Clone(); m_UndoGeometryList.push_back(originalDataGeometry.GetPointer()); vtkIdType pointId; vtkPoints* vPointsSource=vtkPoints::New(); vtkCellArray* vCellsSource=vtkCellArray::New(); for(pointId=0; pointIdGetSize();++pointId) { mitk::Point3D pointSource=m_MovingLandmarks->GetPoint(pointId); vPointsSource->InsertNextPoint(pointSource[0],pointSource[1],pointSource[2]); vCellsSource->InsertNextCell(1, &pointId); } vtkPoints* vPointsTarget=vtkPoints::New(); vtkCellArray* vCellsTarget = vtkCellArray::New(); for(pointId=0; pointIdGetSize();++pointId) { mitk::Point3D pointTarget=m_FixedLandmarks->GetPoint(pointId); vPointsTarget->InsertNextPoint(pointTarget[0],pointTarget[1],pointTarget[2]); vCellsTarget->InsertNextCell(1, &pointId); } vtkPolyData* vPointSetSource=vtkPolyData::New(); vtkPolyData* vPointSetTarget=vtkPolyData::New(); vPointSetTarget->SetPoints(vPointsTarget); vPointSetTarget->SetVerts(vCellsTarget); vPointSetSource->SetPoints(vPointsSource); vPointSetSource->SetVerts(vCellsSource); vtkIterativeClosestPointTransform * icp=vtkIterativeClosestPointTransform::New(); icp->SetCheckMeanDistance(1); icp->SetSource(vPointSetSource); icp->SetTarget(vPointSetTarget); icp->SetMaximumNumberOfIterations(50); icp->StartByMatchingCentroidsOn(); vtkLandmarkTransform * transform=icp->GetLandmarkTransform(); if(m_Transformation==0) { transform->SetModeToRigidBody(); } if(m_Transformation==1) { transform->SetModeToSimilarity(); } if(m_Transformation==2) { transform->SetModeToAffine(); } vtkMatrix4x4 * matrix=icp->GetMatrix(); double determinant = fabs(matrix->Determinant()); if((determinant < mitk::eps) || (determinant > 100) || (determinant < 0.01) || (determinant==itk::NumericTraits::infinity()) || (determinant==itk::NumericTraits::quiet_NaN()) || (determinant==itk::NumericTraits::signaling_NaN()) || (determinant==-itk::NumericTraits::infinity()) || (determinant==-itk::NumericTraits::quiet_NaN()) || (determinant==-itk::NumericTraits::signaling_NaN()) || (!(determinant <= 0) && !(determinant > 0))) { QMessageBox msgBox; msgBox.setText("Suspicious determinant of matrix calculated by ICP.\n" "Please select more points or other points!" ); msgBox.exec(); return; } pointsGeometry->Compose(matrix); m_MovingLandmarks->GetTimeGeometry()->Update(); mitk::BaseData::Pointer movingData = m_MovingNode->GetData(); mitk::BaseGeometry::Pointer movingGeometry = movingData->GetGeometry(0); movingGeometry->Compose(matrix); movingData->GetTimeGeometry()->Update(); m_Controls.m_UndoTransformation->setEnabled(true); m_Controls.m_RedoTransformation->setEnabled(false); m_RedoGeometryList.clear(); m_RedoPointsGeometryList.clear(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); this->checkLandmarkError(); } } // only vtkLandmarkTransformation void QmitkPointBasedRegistrationView::calculateLandmarkbased() { if(CheckCalculate()) { mitk::BaseGeometry::Pointer pointsGeometry = m_MovingLandmarks->GetGeometry(0); mitk::BaseGeometry::Pointer movingLandmarksGeometry = m_MovingLandmarks->GetGeometry(0)->Clone(); m_UndoPointsGeometryList.push_back(movingLandmarksGeometry.GetPointer()); mitk::BaseData::Pointer originalData = m_MovingNode->GetData(); mitk::BaseGeometry::Pointer originalDataGeometry = originalData->GetGeometry(0)->Clone(); m_UndoGeometryList.push_back(originalDataGeometry.GetPointer()); vtkIdType pointId; vtkPoints* vPointsSource=vtkPoints::New(); for(pointId = 0; pointId < m_MovingLandmarks->GetSize(); ++pointId) { mitk::Point3D sourcePoint = m_MovingLandmarks->GetPoint(pointId); vPointsSource->InsertNextPoint(sourcePoint[0],sourcePoint[1],sourcePoint[2]); } vtkPoints* vPointsTarget=vtkPoints::New(); for(pointId=0; pointIdGetSize();++pointId) { mitk::Point3D targetPoint=m_FixedLandmarks->GetPoint(pointId); vPointsTarget->InsertNextPoint(targetPoint[0],targetPoint[1],targetPoint[2]); } vtkLandmarkTransform * transform= vtkLandmarkTransform::New(); transform->SetSourceLandmarks(vPointsSource); transform->SetTargetLandmarks(vPointsTarget); if(m_Transformation==0) { transform->SetModeToRigidBody(); } if(m_Transformation==1) { transform->SetModeToSimilarity(); } if(m_Transformation==2) { transform->SetModeToAffine(); } vtkMatrix4x4 * matrix=transform->GetMatrix(); double determinant = fabs(matrix->Determinant()); if((determinant < mitk::eps) || (determinant > 100) || (determinant < 0.01) || (determinant==itk::NumericTraits::infinity()) || (determinant==itk::NumericTraits::quiet_NaN()) || (determinant==itk::NumericTraits::signaling_NaN()) || (determinant==-itk::NumericTraits::infinity()) || (determinant==-itk::NumericTraits::quiet_NaN()) || (determinant==-itk::NumericTraits::signaling_NaN()) || (!(determinant <= 0) && !(determinant > 0))) { QMessageBox msgBox; msgBox.setText("Suspicious determinant of matrix calculated.\n" "Please select more points or other points!" ); msgBox.exec(); return; } pointsGeometry->Compose(matrix); m_MovingLandmarks->GetTimeGeometry()->Update(); mitk::BaseData::Pointer movingData = m_MovingNode->GetData(); mitk::BaseGeometry::Pointer movingGeometry = movingData->GetGeometry(0); movingGeometry->Compose(matrix); movingData->GetTimeGeometry()->Update(); m_Controls.m_UndoTransformation->setEnabled(true); m_Controls.m_RedoTransformation->setEnabled(false); m_RedoGeometryList.clear(); m_RedoPointsGeometryList.clear(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); this->checkLandmarkError(); } } void QmitkPointBasedRegistrationView::calculateLandmarkWarping() { mitk::LandmarkWarping* registration = new mitk::LandmarkWarping(); mitk::LandmarkWarping::FixedImageType::Pointer fixedImage = mitk::LandmarkWarping::FixedImageType::New(); mitk::Image::Pointer fimage = dynamic_cast(m_FixedNode->GetData()); mitk::LandmarkWarping::MovingImageType::Pointer movingImage = mitk::LandmarkWarping::MovingImageType::New(); mitk::Image::Pointer mimage = dynamic_cast(m_MovingNode->GetData()); if (fimage.IsNotNull() && /*fimage->GetDimension() == 2 || */ fimage->GetDimension() == 3 && mimage.IsNotNull() && mimage->GetDimension() == 3) { mitk::CastToItkImage(fimage, fixedImage); mitk::CastToItkImage(mimage, movingImage); registration->SetFixedImage(fixedImage); registration->SetMovingImage(movingImage); unsigned int pointId; mitk::Point3D sourcePoint, targetPoint; mitk::LandmarkWarping::LandmarkContainerType::Pointer fixedLandmarks = mitk::LandmarkWarping::LandmarkContainerType::New(); mitk::LandmarkWarping::LandmarkPointType point; for(pointId = 0; pointId < (unsigned int)m_FixedLandmarks->GetSize(); ++pointId) { fimage->GetGeometry(0)->WorldToItkPhysicalPoint(m_FixedLandmarks->GetPoint(pointId), point); fixedLandmarks->InsertElement( pointId, point); } mitk::LandmarkWarping::LandmarkContainerType::Pointer movingLandmarks = mitk::LandmarkWarping::LandmarkContainerType::New(); for(pointId = 0; pointId < (unsigned int)m_MovingLandmarks->GetSize(); ++pointId) { mitk::BaseData::Pointer fixedData = m_FixedNode->GetData(); mitk::BaseGeometry::Pointer fixedGeometry = fixedData->GetGeometry(0); fixedGeometry->WorldToItkPhysicalPoint(m_MovingLandmarks->GetPoint(pointId), point); movingLandmarks->InsertElement( pointId, point); } registration->SetLandmarks(fixedLandmarks.GetPointer(), movingLandmarks.GetPointer()); mitk::LandmarkWarping::MovingImageType::Pointer output = registration->Register(); if (output.IsNotNull()) { mitk::Image::Pointer image = mitk::Image::New(); mitk::CastToMitkImage(output, image); m_MovingNode->SetData(image); mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); mitk::LevelWindow levelWindow; levelWindow.SetAuto( image ); levWinProp->SetLevelWindow(levelWindow); m_MovingNode->GetPropertyList()->SetProperty("levelwindow",levWinProp); movingLandmarks = registration->GetTransformedTargetLandmarks(); mitk::PointSet::PointDataIterator it; it = m_MovingLandmarks->GetPointSet()->GetPointData()->Begin(); //increase the eventId to encapsulate the coming operations mitk::OperationEvent::IncCurrObjectEventId(); mitk::OperationEvent::ExecuteIncrement(); for(pointId=0; pointIdSize();++pointId, ++it) { int position = it->Index(); mitk::PointSet::PointType pt = m_MovingLandmarks->GetPoint(position); mitk::Point3D undoPoint = ( pt ); point = movingLandmarks->GetElement(pointId); fimage->GetGeometry(0)->ItkPhysicalPointToWorld(point, pt); mitk::PointOperation* doOp = new mitk::PointOperation(mitk::OpMOVE, pt, position); //undo operation mitk::PointOperation* undoOp = new mitk::PointOperation(mitk::OpMOVE, undoPoint, position); mitk::OperationEvent* operationEvent = new mitk::OperationEvent(m_MovingLandmarks, doOp, undoOp, "Move point"); mitk::UndoController::GetCurrentUndoModel()->SetOperationEvent(operationEvent); //execute the Operation m_MovingLandmarks->ExecuteOperation(doOp); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); this->clearTransformationLists(); this->checkLandmarkError(); } } } bool QmitkPointBasedRegistrationView::checkCalculateEnabled() { if (m_FixedLandmarks.IsNotNull() && m_MovingLandmarks.IsNotNull()) { int fixedPoints = m_FixedLandmarks->GetSize(); int movingPoints = m_MovingLandmarks->GetSize(); if (m_Transformation == 0 || m_Transformation == 1 || m_Transformation == 2) { if (m_Controls.m_UseICP->isChecked()) { if((movingPoints > 0 && fixedPoints > 0)) { m_Controls.m_Calculate->setEnabled(true); return true; } else { m_Controls.m_Calculate->setEnabled(false); return false; } } else { if ((movingPoints == fixedPoints) && movingPoints > 0) { m_Controls.m_Calculate->setEnabled(true); return true; } else { m_Controls.m_Calculate->setEnabled(false); return false; } } } else { m_Controls.m_Calculate->setEnabled(true); return true; } } else { return false; } } void QmitkPointBasedRegistrationView::calculate() { if (m_Transformation == 0 || m_Transformation == 1 || m_Transformation == 2) { if (m_Controls.m_UseICP->isChecked()) { if (m_MovingLandmarks->GetSize() == 1 && m_FixedLandmarks->GetSize() == 1) { this->calculateLandmarkbased(); } else { this->calculateLandmarkbasedWithICP(); } } else { this->calculateLandmarkbased(); } } else { this->calculateLandmarkWarping(); } } void QmitkPointBasedRegistrationView::SwitchImages() { mitk::DataNode::Pointer newMoving = m_FixedNode; mitk::DataNode::Pointer newFixed = m_MovingNode; this->FixedSelected(newFixed); this->MovingSelected(newMoving); } diff --git a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkClippingPlane.dox b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkClippingPlane.dox index 2c98b29a58..01adc438d8 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkClippingPlane.dox +++ b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkClippingPlane.dox @@ -1,71 +1,73 @@ /** \page org_mitk_views_deformableclippingplane The Clipping Plane \imageMacro{QmitkClippingPlane_Icon.png,"Icon of the Clipping Plane Plugin",5.00} + + \imageMacro{QmitkClippingPlane_Overview2.png,"Clipping Plane view",16.00} \tableofcontents \section org_mitk_views_clippingPlaneManualOverview Overview The Clipping Plane view allows you to create clipping planes and calculate the volumina of the devided parts. \section org_mitk_views_clippingPlaneTechnicalIssue Technical Issue To use the Update Volumina function your image should be binary. \section org_mitk_views_clippingPlaneManualImageSelection Image Selection The Clipping Plane view makes use of the Data Manager view to give you an overview of all images, segmentations and clipping planes. \imageMacro{QmitkClippingPlane_DataManager.png,"Data Manager is used for selecting the current clipping plane. The reference plane is selected in the drop down box of the control area.",8.00} To select the reference plane use the drop down box in the control area of the Clipping Plane view or the Data Manager. The clipping plane selected in the Data Manager is displayed below the drop down box. If no clipping plane exists or none is selected create a new clipping plane by using the "Create new clipping plane" button. Some items of the graphical user interface might be disabled when no plane is selected. In any case, the application will give you hints if a selection is needed. \section org_mitk_views_clippingPlaneCreating Creating New Clipping Plane If you want to create a new clipping plane select an image from the Data Manager and press the button "Create new clipping plane". Optionally you can enable the "...with surface model" option. \section org_mitk_views_clippingPlaneInteraction Interaction with the planes \imageMacro{QmitkClippingPlane_Interaction.png,"The interaction buttons",5.00} You have different options to interact with the clipping planes: \subsection org_mitk_views_clippingPlaneTranslation Translation In Translation mode you can change the position of the clipping plane. - Click the Translation Button - Move mouse over the selected clipping plane (the plane changes its color from blue to green) - Hold mouse-left button and move the mouse orthogonally to the plane \subsection org_mitk_views_clippingPlaneRotation Rotation In Rotation mode you can change the angle of the clipping plane. - Click the Rotation Button - Move mouse over the selected clipping plane (the plane changes its color from blue to green) - Hold mouse-left button and move the mouse in the direction it should be rotated \subsection org_mitk_views_clippingPlaneDeformation Deformation In Deformation mode you can change the surface of the clipping plane. - Click the Deformation Button - Move mouse over the selected clipping plane (the plane changes its color from blue to green). The deformation area is highlighted in red and yellow. - On mouse-scrolling you can change the size of the deformation area (Scroll-Down = smaller / Scroll-Up = bigger). - Hold mouse-left button and move the mouse orthogonally to the plane to deformate the plane \section org_mitk_views_clippingPlaneUpdateVolumina Update Volumina \imageMacro{QmitkClippingPlane_UpdateVolumina.png,"The 'Update Volumina' button",5.00} Calculating the volumina of the segmentation parts, which are devided by the clipping plane(s). - Create a segmentation (see Segmentation-Manual) - Create one or more clipping plane(s) - Use the interaction buttons (Translation, Rotation, Deformation) to adjust the clipping plane for intersecting the segmentation - (You can decide which planes shouldnt be included for the calculation by changing their visibility to invisible) - Click button "Update Volumina" button - The intersected parts are displayed in different colors and their volumina are shown beneath the "Update Volumina" button **/ diff --git a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkClippingPlane_Icon.png b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkClippingPlane_Icon.png index efc4775416..74834e777a 100644 Binary files a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkClippingPlane_Icon.png and b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkClippingPlane_Icon.png differ diff --git a/Plugins/org.mitk.gui.qt.segmentation/resources/deformablePlane.png b/Plugins/org.mitk.gui.qt.segmentation/resources/deformablePlane.png index 28c5fb54e8..74834e777a 100644 Binary files a/Plugins/org.mitk.gui.qt.segmentation/resources/deformablePlane.png and b/Plugins/org.mitk.gui.qt.segmentation/resources/deformablePlane.png differ diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/QmitkSegmentationUtilitiesViewControls.ui b/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/QmitkSegmentationUtilitiesViewControls.ui index f062908021..0cd7cac125 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/QmitkSegmentationUtilitiesViewControls.ui +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/QmitkSegmentationUtilitiesViewControls.ui @@ -1,61 +1,49 @@ QmitkSegmentationUtilitiesViewControls 0 0 289 418 0 0 QmitkTemplate icon-size: 32px 32px 0 - - ::tab -{ - background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 palette(light), stop:1 palette(midlight)); -} - -::tab:selected -{ - background: palette(highlight); - color: palette(highlighted-text); -} - -1 0 diff --git a/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.cpp b/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.cpp index bf35daf36b..0e6fd04853 100644 --- a/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.cpp +++ b/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.cpp @@ -1,343 +1,345 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "org_mitk_gui_qt_simulation_Activator.h" #include "QmitkBaseItemDelegate.h" #include "QmitkNoEditItemDelegate.h" #include "QmitkSimulationView.h" #include #include #include #include #include #include #include template static T* GetService() { ctkPluginContext* context = mitk::org_mitk_gui_qt_simulation_Activator::GetContext(); if (context == NULL) return NULL; ctkServiceReference serviceReference = context->getServiceReference(); return serviceReference ? context->getService(serviceReference) : NULL; } static mitk::SimulationInteractor::Pointer CreateSimulationInteractor() { const us::Module* simulationModule = us::ModuleRegistry::GetModule("MitkSimulation"); mitk::SimulationInteractor::Pointer interactor = mitk::SimulationInteractor::New(); interactor->LoadStateMachine("Simulation.xml", simulationModule); interactor->SetEventConfig("SimulationConfig.xml", simulationModule); return interactor; } class Equals { public: explicit Equals(mitk::DataNode::Pointer dataNode) : m_DataNode(dataNode) { } bool operator()(const mitk::DataStorage::SetOfObjects::value_type& object) { return object == m_DataNode; } private: mitk::DataNode::Pointer m_DataNode; }; QmitkSimulationView::QmitkSimulationView() : m_SimulationService(GetService()), m_Interactor(CreateSimulationInteractor()), m_VtkModelContextMenu(NULL), m_Timer(this) { this->GetDataStorage()->RemoveNodeEvent.AddListener( mitk::MessageDelegate1(this, &QmitkSimulationView::OnNodeRemovedFromDataStorage)); connect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout())); } QmitkSimulationView::~QmitkSimulationView() { this->GetDataStorage()->RemoveNodeEvent.RemoveListener( mitk::MessageDelegate1(this, &QmitkSimulationView::OnNodeRemovedFromDataStorage)); } void QmitkSimulationView::CreateQtPartControl(QWidget* parent) { m_Ui.setupUi(parent); m_Ui.simulationComboBox->SetDataStorage(this->GetDataStorage()); m_Ui.simulationComboBox->SetPredicate(mitk::NodePredicateDataType::New("Simulation")); QAction* vtkModelModeAction = new QAction(/*QIcon(":/Qmitk/Surface_48.png"),*/ "Render to Surface", m_VtkModelContextMenu); vtkModelModeAction->setCheckable(true); m_VtkModelContextMenu = new QMenu(m_Ui.sceneTreeWidget); m_VtkModelContextMenu->addAction(vtkModelModeAction); connect(m_Ui.simulationComboBox, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnSelectedSimulationChanged(const mitk::DataNode*))); connect(m_Ui.animateButton, SIGNAL(toggled(bool)), this, SLOT(OnAnimateButtonToggled(bool))); connect(m_Ui.stepButton, SIGNAL(clicked()), this, SLOT(OnStepButtonClicked())); connect(m_Ui.resetButton, SIGNAL(clicked()), this, SLOT(OnResetButtonClicked())); connect(m_Ui.dtSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnDtChanged(double))); connect(m_Ui.sceneTreeWidget, SIGNAL(itemSelectionChanged()), this, SLOT(OnSelectedBaseChanged())); connect(m_Ui.sceneTreeWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(OnBaseContextMenuRequested(const QPoint&))); if (m_Ui.simulationComboBox->GetSelectedNode().IsNotNull()) { this->OnSelectedSimulationChanged(m_Ui.simulationComboBox->GetSelectedNode()); } else { this->SetSimulationControlsEnabled(false); } } void QmitkSimulationView::OnAnimateButtonToggled(bool toggled) { mitk::Scheduler* scheduler = m_SimulationService->GetScheduler(); if (toggled) { mitk::Simulation::Pointer simulation = static_cast(m_Selection->GetData()); simulation->SetAnimationFlag(true); scheduler->AddProcess(simulation); m_Ui.stepButton->setEnabled(false); } else if (m_Selection.IsNotNull()) { mitk::Simulation::Pointer simulation = static_cast(m_Selection->GetData()); scheduler->RemoveProcess(simulation); simulation->SetAnimationFlag(false); m_Ui.stepButton->setEnabled(true); } if (!scheduler->IsEmpty()) { if (!m_Timer.isActive()) m_Timer.start(0); } else { m_Timer.stop(); } } void QmitkSimulationView::OnBaseContextMenuRequested(const QPoint& point) { typedef mitk::DataStorage::SetOfObjects SetOfObjects; QTreeWidgetItem* item = m_Ui.sceneTreeWidget->itemAt(point); if (item == NULL) return; QmitkSceneTreeWidget::Base* base = m_Ui.sceneTreeWidget->GetBaseFromItem(item); if (base == NULL) return; mitk::VtkModel* vtkModel = dynamic_cast(base); if (vtkModel == NULL) return; + m_VtkModelContextMenu->actions().first()->setChecked(vtkModel->GetMode() == mitk::VtkModel::Surface); + QAction* action = m_VtkModelContextMenu->exec(m_Ui.sceneTreeWidget->mapToGlobal(point)); if (action == NULL) return; if (action->text() == "Render to Surface") { mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(); SetOfObjects::ConstPointer objects = dataStorage->GetSubset(NULL); if (action->isChecked()) { vtkModel->SetMode(mitk::VtkModel::Surface); mitk::DataNode::Pointer dataNode = vtkModel->GetDataNode(); if (std::find_if(objects->begin(), objects->end(), Equals(dataNode)) == objects->end()) dataStorage->Add(dataNode, m_Selection); } else { mitk::DataNode::Pointer dataNode = vtkModel->GetDataNode(); if (std::find_if(objects->begin(), objects->end(), Equals(dataNode)) != objects->end()) dataStorage->Remove(dataNode); vtkModel->SetMode(mitk::VtkModel::OpenGL); } } } void QmitkSimulationView::OnDtChanged(double dt) { if (m_Selection.IsNull()) return; mitk::Simulation::Pointer simulation = static_cast(m_Selection->GetData()); simulation->SetDt(std::max(0.0, dt)); } void QmitkSimulationView::OnNodeRemovedFromDataStorage(const mitk::DataNode* node) { mitk::Simulation::Pointer simulation = dynamic_cast(node->GetData()); if (simulation.IsNotNull()) { mitk::Scheduler* scheduler = m_SimulationService->GetScheduler(); scheduler->RemoveProcess(simulation); if (scheduler->IsEmpty() && m_Timer.isActive()) m_Timer.stop(); if (m_SimulationService->GetActiveSimulation() == simulation) m_SimulationService->SetActiveSimulation(NULL); } } void QmitkSimulationView::OnResetButtonClicked() { mitk::Simulation::Pointer simulation = static_cast(m_Selection->GetData()); m_SimulationService->SetActiveSimulation(simulation); m_Ui.dtSpinBox->setValue(simulation->GetRootNode()->getDt()); simulation->Reset(); this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_ALL); } void QmitkSimulationView::OnSelectedSimulationChanged(const mitk::DataNode* node) { if (node != NULL) { m_Selection = m_Ui.simulationComboBox->GetSelectedNode(); mitk::Simulation* simulation = static_cast(m_Selection->GetData()); m_Ui.animateButton->setChecked(simulation->GetAnimationFlag()); m_Ui.dtSpinBox->setValue(simulation->GetRootNode()->getDt()); this->SetSimulationControlsEnabled(true); } else { m_Selection = NULL; this->SetSimulationControlsEnabled(false); m_Ui.animateButton->setChecked(false); m_Ui.dtSpinBox->setValue(0.0); } m_Interactor->SetDataNode(m_Selection); this->ResetSceneTreeWidget(); } void QmitkSimulationView::OnSelectedBaseChanged() { QList selectedBaseItems = m_Ui.sceneTreeWidget->selectedItems(); m_Ui.baseTreeWidget->OnSelectedBaseChanged(!selectedBaseItems.isEmpty() ? m_Ui.sceneTreeWidget->GetBaseFromItem(selectedBaseItems[0]) : NULL); } void QmitkSimulationView::OnStep(bool renderWindowUpdate) { mitk::Scheduler* scheduler = m_SimulationService->GetScheduler(); mitk::Simulation::Pointer simulation = dynamic_cast(scheduler->GetNextProcess()); m_SimulationService->SetActiveSimulation(simulation); if (simulation.IsNotNull()) simulation->Animate(); if (renderWindowUpdate) this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_ALL); } void QmitkSimulationView::OnStepButtonClicked() { if (m_Selection.IsNull()) return; mitk::Simulation::Pointer simulation = static_cast(m_Selection->GetData()); m_SimulationService->SetActiveSimulation(simulation); simulation->Animate(); this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_ALL); } void QmitkSimulationView::OnTimeout() { QTime currentTime = QTime::currentTime(); if (currentTime.msecsTo(m_NextRenderWindowUpdate) > 0) { this->OnStep(false); } else { m_NextRenderWindowUpdate = currentTime.addMSecs(MSecsPerFrame); this->OnStep(true); } } void QmitkSimulationView::ResetSceneTreeWidget() { m_Ui.sceneTreeWidget->clear(); if (m_Selection.IsNull()) return; mitk::Simulation::Pointer simulation = static_cast(m_Selection->GetData()); m_Ui.sceneTreeWidget->addChild(NULL, simulation->GetRootNode().get()); m_Ui.sceneTreeWidget->expandItem(m_Ui.sceneTreeWidget->topLevelItem(0)); } void QmitkSimulationView::SetSimulationControlsEnabled(bool enabled) { m_Ui.animateButton->setEnabled(enabled); m_Ui.stepButton->setEnabled(enabled); m_Ui.resetButton->setEnabled(enabled); m_Ui.dtLabel->setEnabled(enabled); m_Ui.dtSpinBox->setEnabled(enabled); } void QmitkSimulationView::SetFocus() { m_Ui.animateButton->setFocus(); } diff --git a/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFScreenshotMaker.cpp b/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFScreenshotMaker.cpp index 7b035a88eb..f2c6a6c6da 100644 --- a/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFScreenshotMaker.cpp +++ b/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFScreenshotMaker.cpp @@ -1,147 +1,148 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Qmitk #include "QmitkToFScreenshotMaker.h" #include // Mitk #include #include -#include // Qt #include #include #include const std::string QmitkToFScreenshotMaker::VIEW_ID = "org.mitk.views.tofscreenshotmaker"; QmitkToFScreenshotMaker::QmitkToFScreenshotMaker() : QmitkAbstractView(), m_SavingCounter(0) { } QmitkToFScreenshotMaker::~QmitkToFScreenshotMaker() { } void QmitkToFScreenshotMaker::SetFocus() { } void QmitkToFScreenshotMaker::CreateQtPartControl( QWidget *parent ) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi( parent ); connect( (QObject*)(m_Controls.m_MakeScreenshot), SIGNAL(clicked()), this, SLOT(OnMakeScreenshotClicked()) ); connect( m_Controls.m_ConnectedDeviceServiceListWidget, SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(OnSelectCamera())); std::string filter = ""; m_Controls.m_ConnectedDeviceServiceListWidget->Initialize("ToFImageSourceName", filter); std::string defaultPath = "/tmp/"; #ifdef _WIN32 defaultPath = "C:/tmp/"; #endif m_Controls.m_PathToSaveFiles->setText(defaultPath.c_str()); } void QmitkToFScreenshotMaker::OnSelectCamera() { //Update gui according to device properties mitk::ToFImageGrabber* source = static_cast(m_Controls.m_ConnectedDeviceServiceListWidget->GetSelectedService()); mitk::ToFCameraDevice* device = source->GetCameraDevice(); m_Controls.m_MakeScreenshot->setEnabled(device->IsCameraActive()); //todo: where do i get correct file extensions? - mitk::ImageWriter::Pointer imageWriter = mitk::ImageWriter::New(); - std::vector fileExtensions = imageWriter->GetPossibleFileExtensions(); + std::vector fileExtensions; + fileExtensions.push_back(".png"); + fileExtensions.push_back(".nrrd"); + fileExtensions.push_back(".jpg"); QStringList extensions; for( unsigned int i = 0; i < fileExtensions.size(); ++i) { extensions.append(QString(fileExtensions.at(i).c_str())); } this->UpdateGUIElements(device, "no depth property available", m_Controls.m_SaveDepth, m_Controls.m_DepthFormat, extensions, ".nrrd"); //usually you want to save depth data, but there is no "HasDepthImage" property, because every depth //camera should provide a depth iamge m_Controls.m_SaveDepth->setChecked(true); m_Controls.m_SaveDepth->setEnabled(true); m_Controls.m_DepthFormat->setEnabled(true); this->UpdateGUIElements(device, "HasAmplitudeImage", m_Controls.m_SaveAmplitude , m_Controls.m_AmplitudeFormat, extensions, ".nrrd"); this->UpdateGUIElements(device, "HasIntensityImage", m_Controls.m_SaveIntensity, m_Controls.m_IntensityFormat, extensions, ".nrrd"); this->UpdateGUIElements(device, "HasRGBImage", m_Controls.m_SaveColor, m_Controls.m_ColorFormat, extensions, ".png"); //png is nice default for calibration this->UpdateGUIElements(device, "HasRawImage", m_Controls.m_SaveRaw, m_Controls.m_RawFormat, extensions, ".nrrd"); } void QmitkToFScreenshotMaker::UpdateGUIElements(mitk::ToFCameraDevice* device, const char* ToFImageType, QCheckBox* saveCheckBox, QComboBox* saveTypeComboBox, QStringList fileExentions, const char* preferredFormat) { bool isTypeProvidedByDevice = false; device->GetBoolProperty(ToFImageType, isTypeProvidedByDevice); saveCheckBox->setChecked(isTypeProvidedByDevice); saveCheckBox->setEnabled(isTypeProvidedByDevice); saveTypeComboBox->clear(); saveTypeComboBox->setEnabled(isTypeProvidedByDevice); saveTypeComboBox->addItems(fileExentions); int index = saveTypeComboBox->findText(preferredFormat); if ( index != -1 ) { // -1 for not found saveTypeComboBox->setCurrentIndex(index); } } void QmitkToFScreenshotMaker::OnMakeScreenshotClicked() { mitk::ToFImageGrabber* source = static_cast(m_Controls.m_ConnectedDeviceServiceListWidget->GetSelectedService()); source->Update(); //### Save Images this->SaveImage(source->GetOutput(0), m_Controls.m_SaveDepth->isChecked(), m_Controls.m_PathToSaveFiles->text().toStdString(), std::string("Depth_"), m_Controls.m_DepthFormat->currentText().toStdString()); this->SaveImage(source->GetOutput(1), m_Controls.m_SaveAmplitude->isChecked(), m_Controls.m_PathToSaveFiles->text().toStdString(), std::string("Amplitude_"), m_Controls.m_AmplitudeFormat->currentText().toStdString()); this->SaveImage(source->GetOutput(2), m_Controls.m_SaveIntensity->isChecked(), m_Controls.m_PathToSaveFiles->text().toStdString(), std::string("Intensity_"), m_Controls.m_IntensityFormat->currentText().toStdString()); this->SaveImage(source->GetOutput(3), m_Controls.m_SaveColor->isChecked(), m_Controls.m_PathToSaveFiles->text().toStdString(), std::string("Color_"), m_Controls.m_ColorFormat->currentText().toStdString()); //todo, where is the raw data? //todo what about the surface or pre-processed data? m_SavingCounter++; } void QmitkToFScreenshotMaker::SaveImage(mitk::Image::Pointer image, bool saveImage, std::string path, std::string name, std::string extension) { if(saveImage) { std::stringstream outdepthimage; outdepthimage << path << name<< m_SavingCounter << extension; mitk::IOUtil::SaveImage( image, outdepthimage.str() ); } } diff --git a/Plugins/org.mitk.gui.qt.viewnavigator/src/QmitkNewPerspectiveDialog.cpp b/Plugins/org.mitk.gui.qt.viewnavigator/src/QmitkNewPerspectiveDialog.cpp index e4c33a892c..f177ba6361 100644 --- a/Plugins/org.mitk.gui.qt.viewnavigator/src/QmitkNewPerspectiveDialog.cpp +++ b/Plugins/org.mitk.gui.qt.viewnavigator/src/QmitkNewPerspectiveDialog.cpp @@ -1,88 +1,86 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkNewPerspectiveDialog.h" #include "mitkOrganTypeProperty.h" #include #include #include #include #include #include #include #include -#include - QmitkNewPerspectiveDialog::QmitkNewPerspectiveDialog(QWidget* parent) :QDialog(parent) { QGridLayout* formGridLayout = new QGridLayout( this ); QLabel* label = new QLabel( "Perspective name:", this ); m_PerspectiveNameLineEdit = new QLineEdit( "", this ); m_PerspectiveNameLineEdit->setFocus(); m_AcceptNameButton = new QPushButton( tr("Ok"), this ); m_AcceptNameButton->setDefault(true); m_AcceptNameButton->setEnabled(false); QPushButton* rejectNameButton = new QPushButton( tr("Cancel"), this ); formGridLayout->addWidget(label, 0, 0); formGridLayout->addWidget(m_PerspectiveNameLineEdit, 0, 1); formGridLayout->addWidget(m_AcceptNameButton, 1, 0); formGridLayout->addWidget(rejectNameButton, 1, 1); setLayout(formGridLayout); // create connections connect( rejectNameButton, SIGNAL(clicked()), this, SLOT(reject()) ); connect( m_AcceptNameButton, SIGNAL(clicked()), this, SLOT(OnAcceptClicked()) ); connect( m_PerspectiveNameLineEdit, SIGNAL(textEdited(const QString&)), this, SLOT(OnPerspectiveNameChanged(const QString&)) ); } QmitkNewPerspectiveDialog::~QmitkNewPerspectiveDialog() { } void QmitkNewPerspectiveDialog::SetPerspectiveName(QString name) { m_PerspectiveNameLineEdit->setText(name); OnPerspectiveNameChanged(name); } void QmitkNewPerspectiveDialog::OnAcceptClicked() { m_PerspectiveName = m_PerspectiveNameLineEdit->text(); this->accept(); } const QString QmitkNewPerspectiveDialog::GetPerspectiveName() { return m_PerspectiveName; } void QmitkNewPerspectiveDialog::OnPerspectiveNameChanged(const QString& newText) { if (!newText.isEmpty()) m_AcceptNameButton->setEnabled(true); else m_AcceptNameButton->setEnabled(false); } diff --git a/SuperBuild.cmake b/SuperBuild.cmake index dcf548130b..cc83b6f696 100644 --- a/SuperBuild.cmake +++ b/SuperBuild.cmake @@ -1,442 +1,444 @@ include(mitkFunctionInstallExternalCMakeProject) include(mitkFunctionCheckCompilerFlags) #----------------------------------------------------------------------------- # Convenient macro allowing to download a file #----------------------------------------------------------------------------- if(NOT MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL) set(MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL http://mitk.org/download/thirdparty) endif() macro(downloadFile url dest) file(DOWNLOAD ${url} ${dest} STATUS status) list(GET status 0 error_code) list(GET status 1 error_msg) if(error_code) message(FATAL_ERROR "error: Failed to download ${url} - ${error_msg}") endif() endmacro() #----------------------------------------------------------------------------- # MITK Prerequisites #----------------------------------------------------------------------------- if(UNIX AND NOT APPLE) include(mitkFunctionCheckPackageHeader) # Check for libxt-dev mitkFunctionCheckPackageHeader(StringDefs.h libxt-dev /usr/include/X11/) # Check for libtiff4-dev mitkFunctionCheckPackageHeader(tiff.h libtiff4-dev) # Check for libwrap0-dev mitkFunctionCheckPackageHeader(tcpd.h libwrap0-dev) endif() # We need a proper patch program. On Linux and MacOS, we assume # that "patch" is available. On Windows, we download patch.exe # if not patch program is found. find_program(PATCH_COMMAND patch) if((NOT PATCH_COMMAND OR NOT EXISTS ${PATCH_COMMAND}) AND WIN32) downloadFile(${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/patch.exe ${CMAKE_CURRENT_BINARY_DIR}/patch.exe) find_program(PATCH_COMMAND patch ${CMAKE_CURRENT_BINARY_DIR}) endif() if(NOT PATCH_COMMAND) message(FATAL_ERROR "No patch program found.") endif() #----------------------------------------------------------------------------- # Qt options for external projects and MITK #----------------------------------------------------------------------------- if(MITK_USE_QT) set(qt_project_args -DDESIRED_QT_VERSION:STRING=${DESIRED_QT_VERSION}) else() set(qt_project_args ) endif() if(MITK_USE_Qt4) list(APPEND qt_project_args -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} ) endif() #----------------------------------------------------------------------------- # ExternalProjects #----------------------------------------------------------------------------- get_property(external_projects GLOBAL PROPERTY MITK_EXTERNAL_PROJECTS) # A list of "nice" external projects, playing well together with CMake set(nice_external_projects ${external_projects}) list(REMOVE_ITEM nice_external_projects Boost Python) foreach(proj ${nice_external_projects}) if(MITK_USE_${proj}) set(EXTERNAL_${proj}_DIR "${${proj}_DIR}" CACHE PATH "Path to ${proj} build directory") mark_as_advanced(EXTERNAL_${proj}_DIR) if(EXTERNAL_${proj}_DIR) set(${proj}_DIR ${EXTERNAL_${proj}_DIR}) endif() endif() endforeach() if(MITK_USE_Boost) set(EXTERNAL_BOOST_ROOT "${BOOST_ROOT}" CACHE PATH "Path to Boost directory") mark_as_advanced(EXTERNAL_BOOST_ROOT) if(EXTERNAL_BOOST_ROOT) set(BOOST_ROOT ${EXTERNAL_BOOST_ROOT}) endif() endif() # Setup file for setting custom ctest vars configure_file( CMake/SuperbuildCTestCustom.cmake.in ${MITK_BINARY_DIR}/CTestCustom.cmake @ONLY ) if(BUILD_TESTING) set(EXTERNAL_MITK_DATA_DIR "${MITK_DATA_DIR}" CACHE PATH "Path to the MITK data directory") mark_as_advanced(EXTERNAL_MITK_DATA_DIR) if(EXTERNAL_MITK_DATA_DIR) set(MITK_DATA_DIR ${EXTERNAL_MITK_DATA_DIR}) endif() endif() # Look for git early on, if needed if((BUILD_TESTING AND NOT EXTERNAL_MITK_DATA_DIR) OR (MITK_USE_CTK AND NOT EXTERNAL_CTK_DIR)) find_package(Git REQUIRED) endif() #----------------------------------------------------------------------------- # External project settings #----------------------------------------------------------------------------- include(ExternalProject) set(ep_prefix "${CMAKE_BINARY_DIR}/ep") set_property(DIRECTORY PROPERTY EP_PREFIX ${ep_prefix}) # Compute -G arg for configuring external projects with the same CMake generator: if(CMAKE_EXTRA_GENERATOR) set(gen "${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}") else() set(gen "${CMAKE_GENERATOR}") endif() # Use this value where semi-colons are needed in ep_add args: set(sep "^^") ## if(MSVC_VERSION) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /bigobj /MP") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj /MP") endif() # This is necessary to avoid problems with compile feature checks. # CMAKE_CXX_STANDARD seems to only set the -std=c++11 flag for targets. # The CMAKE_CXX_FLAGS variable is also used for non-CMake based # external projects like Boost and PCRE. mitkFunctionCheckCompilerFlags("-std=c++11" CMAKE_CXX_FLAGS) # This is a workaround for passing linker flags # actually down to the linker invocation set(_cmake_required_flags_orig ${CMAKE_REQUIRED_FLAGS}) set(CMAKE_REQUIRED_FLAGS "-Wl,-rpath") mitkFunctionCheckCompilerFlags(${CMAKE_REQUIRED_FLAGS} _has_rpath_flag) set(CMAKE_REQUIRED_FLAGS ${_cmake_required_flags_orig}) set(_install_rpath_linkflag ) if(_has_rpath_flag) if(APPLE) set(_install_rpath_linkflag "-Wl,-rpath,@loader_path/../lib") else() set(_install_rpath_linkflag "-Wl,-rpath='$ORIGIN/../lib'") endif() endif() set(_install_rpath) if(APPLE) set(_install_rpath "@loader_path/../lib") elseif(UNIX) # this work for libraries as well as executables set(_install_rpath "\$ORIGIN/../lib") endif() set(ep_common_args -DCMAKE_CXX_EXTENSIONS:STRING=0 -DCMAKE_CXX_STANDARD:STRING=11 -DCMAKE_DEBUG_POSTFIX:STRING=d -DCMAKE_MACOSX_RPATH:BOOL=TRUE "-DCMAKE_INSTALL_RPATH:STRING=${_install_rpath}" -DBUILD_TESTING:BOOL=OFF -DCMAKE_INSTALL_PREFIX:PATH= "-DCMAKE_PREFIX_PATH:PATH=^^${CMAKE_PREFIX_PATH}" + -DCMAKE_INCLUDE_PATH:PATH=${CMAKE_INCLUDE_PATH} + -DCMAKE_LIBRARY_PATH:PATH=${CMAKE_LIBRARY_PATH} -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} -DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS} "-DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS}" #debug flags -DCMAKE_CXX_FLAGS_DEBUG:STRING=${CMAKE_CXX_FLAGS_DEBUG} -DCMAKE_C_FLAGS_DEBUG:STRING=${CMAKE_C_FLAGS_DEBUG} #release flags -DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE} -DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE} #relwithdebinfo -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DCMAKE_C_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_C_FLAGS_RELWITHDEBINFO} #link flags -DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_SHARED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_MODULE_LINKER_FLAGS} ) # Pass the CMAKE_OSX variables to external projects if(APPLE) set(MAC_OSX_ARCHITECTURE_ARGS -DCMAKE_OSX_ARCHITECTURES:PATH=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET:PATH=${CMAKE_OSX_DEPLOYMENT_TARGET} -DCMAKE_OSX_SYSROOT:PATH=${CMAKE_OSX_SYSROOT} ) set(ep_common_args ${MAC_OSX_ARCHITECTURE_ARGS} ${ep_common_args} ) endif() set(mitk_superbuild_ep_args) set(mitk_depends ) # Include external projects include(CMakeExternals/MITKData.cmake) foreach(p ${external_projects}) include(CMakeExternals/${p}.cmake) list(APPEND mitk_superbuild_ep_args -DMITK_USE_${p}:BOOL=${MITK_USE_${p}} ) get_property(_package GLOBAL PROPERTY MITK_${p}_PACKAGE) if(_package) list(APPEND mitk_superbuild_ep_args -D${p}_DIR:PATH=${${p}_DIR}) endif() list(APPEND mitk_depends ${${p}_DEPENDS}) endforeach() #----------------------------------------------------------------------------- # Set superbuild boolean args #----------------------------------------------------------------------------- set(mitk_cmake_boolean_args BUILD_SHARED_LIBS WITH_COVERAGE BUILD_TESTING MITK_BUILD_ALL_PLUGINS MITK_BUILD_ALL_APPS MITK_BUILD_TUTORIAL # Deprecated. Use MITK_BUILD_EXAMPLES instead MITK_BUILD_EXAMPLES MITK_USE_QT MITK_USE_SYSTEM_Boost MITK_USE_BLUEBERRY MITK_USE_OpenCL MITK_ENABLE_PIC_READER ) #----------------------------------------------------------------------------- # Create the final variable containing superbuild boolean args #----------------------------------------------------------------------------- set(mitk_superbuild_boolean_args) foreach(mitk_cmake_arg ${mitk_cmake_boolean_args}) list(APPEND mitk_superbuild_boolean_args -D${mitk_cmake_arg}:BOOL=${${mitk_cmake_arg}}) endforeach() if(MITK_BUILD_ALL_PLUGINS) list(APPEND mitk_superbuild_boolean_args -DBLUEBERRY_BUILD_ALL_PLUGINS:BOOL=ON) endif() #----------------------------------------------------------------------------- # MITK Utilities #----------------------------------------------------------------------------- set(proj MITK-Utilities) ExternalProject_Add(${proj} DOWNLOAD_COMMAND "" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" DEPENDS ${mitk_depends} ) #----------------------------------------------------------------------------- # Additional MITK CXX/C Flags #----------------------------------------------------------------------------- set(MITK_ADDITIONAL_C_FLAGS "" CACHE STRING "Additional C Flags for MITK") set(MITK_ADDITIONAL_C_FLAGS_RELEASE "" CACHE STRING "Additional Release C Flags for MITK") set(MITK_ADDITIONAL_C_FLAGS_DEBUG "" CACHE STRING "Additional Debug C Flags for MITK") mark_as_advanced(MITK_ADDITIONAL_C_FLAGS MITK_ADDITIONAL_C_FLAGS_DEBUG MITK_ADDITIONAL_C_FLAGS_RELEASE) set(MITK_ADDITIONAL_CXX_FLAGS "" CACHE STRING "Additional CXX Flags for MITK") set(MITK_ADDITIONAL_CXX_FLAGS_RELEASE "" CACHE STRING "Additional Release CXX Flags for MITK") set(MITK_ADDITIONAL_CXX_FLAGS_DEBUG "" CACHE STRING "Additional Debug CXX Flags for MITK") mark_as_advanced(MITK_ADDITIONAL_CXX_FLAGS MITK_ADDITIONAL_CXX_FLAGS_DEBUG MITK_ADDITIONAL_CXX_FLAGS_RELEASE) set(MITK_ADDITIONAL_EXE_LINKER_FLAGS "" CACHE STRING "Additional exe linker flags for MITK") set(MITK_ADDITIONAL_SHARED_LINKER_FLAGS "" CACHE STRING "Additional shared linker flags for MITK") set(MITK_ADDITIONAL_MODULE_LINKER_FLAGS "" CACHE STRING "Additional module linker flags for MITK") mark_as_advanced(MITK_ADDITIONAL_EXE_LINKER_FLAGS MITK_ADDITIONAL_SHARED_LINKER_FLAGS MITK_ADDITIONAL_MODULE_LINKER_FLAGS) #----------------------------------------------------------------------------- # MITK Configure #----------------------------------------------------------------------------- if(MITK_INITIAL_CACHE_FILE) set(mitk_initial_cache_arg -C "${MITK_INITIAL_CACHE_FILE}") endif() set(mitk_optional_cache_args ) foreach(type RUNTIME ARCHIVE LIBRARY) if(DEFINED CTK_PLUGIN_${type}_OUTPUT_DIRECTORY) list(APPEND mitk_optional_cache_args -DCTK_PLUGIN_${type}_OUTPUT_DIRECTORY:PATH=${CTK_PLUGIN_${type}_OUTPUT_DIRECTORY}) endif() endforeach() # Optional python variables if(MITK_USE_Python) list(APPEND mitk_optional_cache_args -DMITK_USE_Python:BOOL=${MITK_USE_Python} -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} -DMITK_USE_SYSTEM_PYTHON:BOOL=${MITK_USE_SYSTEM_PYTHON} ) endif() if(MITK_USE_QT) if(DESIRED_QT_VERSION MATCHES "5") list(APPEND mitk_optional_cache_args -DQT5_INSTALL_PREFIX:PATH=${QT5_INSTALL_PREFIX} ) endif() endif() set(proj MITK-Configure) ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} DOWNLOAD_COMMAND "" CMAKE_GENERATOR ${gen} CMAKE_CACHE_ARGS # --------------- Build options ---------------- -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} # --------------- Compile options ---------------- -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS} ${MITK_ADDITIONAL_C_FLAGS}" "-DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS} ${MITK_ADDITIONAL_CXX_FLAGS}" # debug flags "-DCMAKE_CXX_FLAGS_DEBUG:STRING=${CMAKE_CXX_FLAGS_DEBUG} ${MITK_ADDITIONAL_CXX_FLAGS_DEBUG}" "-DCMAKE_C_FLAGS_DEBUG:STRING=${CMAKE_C_FLAGS_DEBUG} ${MITK_ADDITIONAL_C_FLAGS_DEBUG}" # release flags "-DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE} ${MITK_ADDITIONAL_CXX_FLAGS_RELEASE}" "-DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE} ${MITK_ADDITIONAL_C_FLAGS_RELEASE}" # relwithdebinfo -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DCMAKE_C_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_C_FLAGS_RELWITHDEBINFO} # link flags "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS} ${MITK_ADDITIONAL_EXE_LINKER_FLAGS}" "-DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_SHARED_LINKER_FLAGS} ${MITK_ADDITIONAL_SHARED_LINKER_FLAGS}" "-DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_MODULE_LINKER_FLAGS} ${MITK_ADDITIONAL_MODULE_LINKER_FLAGS}" # Output directories -DMITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY:PATH=${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY} -DMITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY:PATH=${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY} -DMITK_CMAKE_ARCHIVE_OUTPUT_DIRECTORY:PATH=${MITK_CMAKE_ARCHIVE_OUTPUT_DIRECTORY} # ------------- Boolean build options -------------- ${mitk_superbuild_boolean_args} ${mitk_optional_cache_args} -DMITK_USE_SUPERBUILD:BOOL=OFF -DMITK_BUILD_CONFIGURATION:STRING=${MITK_BUILD_CONFIGURATION} -DCTEST_USE_LAUNCHERS:BOOL=${CTEST_USE_LAUNCHERS} # ----------------- Miscellaneous --------------- -DMITK_CTEST_SCRIPT_MODE:STRING=${MITK_CTEST_SCRIPT_MODE} -DMITK_SUPERBUILD_BINARY_DIR:PATH=${MITK_BINARY_DIR} -DMITK_MODULES_TO_BUILD:INTERNAL=${MITK_MODULES_TO_BUILD} -DMITK_WHITELIST:STRING=${MITK_WHITELIST} -DMITK_WHITELISTS_EXTERNAL_PATH:STRING=${MITK_WHITELISTS_EXTERNAL_PATH} -DMITK_WHITELISTS_INTERNAL_PATH:STRING=${MITK_WHITELISTS_INTERNAL_PATH} ${qt_project_args} -DMITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES} -DMITK_ACCESSBYITK_FLOATING_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES} -DMITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES} -DMITK_ACCESSBYITK_VECTOR_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES} -DMITK_ACCESSBYITK_DIMENSIONS:STRING=${MITK_ACCESSBYITK_DIMENSIONS} # --------------- External project options --------------- -DMITK_DATA_DIR:PATH=${MITK_DATA_DIR} -DMITK_EXTERNAL_PROJECT_PREFIX:PATH=${ep_prefix} -DCppMicroServices_DIR:PATH=${CppMicroServices_DIR} -DMITK_KWSTYLE_EXECUTABLE:FILEPATH=${MITK_KWSTYLE_EXECUTABLE} -DDCMTK_CMAKE_DEBUG_POSTFIX:STRING=d -DBOOST_ROOT:PATH=${BOOST_ROOT} -DBOOST_LIBRARYDIR:PATH=${BOOST_LIBRARYDIR} -DMITK_USE_Boost_LIBRARIES:STRING=${MITK_USE_Boost_LIBRARIES} CMAKE_ARGS ${mitk_initial_cache_arg} ${MAC_OSX_ARCHITECTURE_ARGS} ${mitk_superbuild_ep_args} "-DCMAKE_PREFIX_PATH:PATH=${ep_prefix}${sep}${CMAKE_PREFIX_PATH}" SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} BINARY_DIR ${CMAKE_BINARY_DIR}/MITK-build BUILD_COMMAND "" INSTALL_COMMAND "" DEPENDS MITK-Utilities ) mitkFunctionInstallExternalCMakeProject(${proj}) #----------------------------------------------------------------------------- # MITK #----------------------------------------------------------------------------- if(CMAKE_GENERATOR MATCHES ".*Makefiles.*") set(mitk_build_cmd "$(MAKE)") else() set(mitk_build_cmd ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/MITK-build --config ${CMAKE_CFG_INTDIR}) endif() if(NOT DEFINED SUPERBUILD_EXCLUDE_MITKBUILD_TARGET OR NOT SUPERBUILD_EXCLUDE_MITKBUILD_TARGET) set(MITKBUILD_TARGET_ALL_OPTION "ALL") else() set(MITKBUILD_TARGET_ALL_OPTION "") endif() add_custom_target(MITK-build ${MITKBUILD_TARGET_ALL_OPTION} COMMAND ${mitk_build_cmd} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/MITK-build DEPENDS MITK-Configure ) #----------------------------------------------------------------------------- # Custom target allowing to drive the build of the MITK project itself #----------------------------------------------------------------------------- add_custom_target(MITK COMMAND ${mitk_build_cmd} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/MITK-build )