diff --git a/CMake/MITKDashboardSetup.cmake b/CMake/MITKDashboardSetup.cmake index 38fc7565e4..db3c968991 100644 --- a/CMake/MITKDashboardSetup.cmake +++ b/CMake/MITKDashboardSetup.cmake @@ -1,155 +1,155 @@ # 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) if(CMAKE_CL_64) set(CMAKE_LIBRARY_ARCHITECTURE x64) else() set(CMAKE_LIBRARY_ARCHITECTURE x86) endif() - find_path(OPENCV_BIN_DIR opencv_core248.dll + find_path(OPENCV_BIN_DIR opencv_core2411.dll PATHS "${CTEST_BINARY_DIRECTORY}/ep/${CMAKE_LIBRARY_ARCHITECTURE}" PATH_SUFFIXES vc10/bin vc11/bin vc12/bin vc13/bin vc14/bin NO_DEFAULT_PATH ) message("OpenCV runtime path: ${OPENCV_BIN_DIR}") set(SOFA_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/ep/src/SOFA-build/bin/${CTEST_BUILD_CONFIGURATION}") set(BLUEBERRY_RUNTIME_DIR "${CTEST_BINARY_DIRECTORY}/MITK-build/bin/plugins/${CTEST_BUILD_CONFIGURATION}") set(CTEST_PATH "${CTEST_PATH};${CTEST_BINARY_DIRECTORY}/ep/bin;${QT_BINARY_DIR};${SOFA_BINARY_DIR};${BLUEBERRY_RUNTIME_DIR};${OPENCV_BIN_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(CTEST_CMAKE_GENERATOR MATCHES ".*Makefiles.*") set(CTEST_USE_LAUNCHERS 1) else() set(CTEST_USE_LAUNCHERS 0) endif() set(ENV{CTEST_USE_LAUNCHERS_DEFAULT} ${CTEST_USE_LAUNCHERS}) # 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_HDF5_Config.cmake b/CMake/PackageDepends/MITK_HDF5_Config.cmake new file mode 100644 index 0000000000..30fe719f4f --- /dev/null +++ b/CMake/PackageDepends/MITK_HDF5_Config.cmake @@ -0,0 +1,2 @@ +list(APPEND ALL_INCLUDE_DIRECTORIES ${HDF5_INCLUDE_DIR}) +list(APPEND ALL_LIBRARIES ${HDF5_LIBRARIES}) diff --git a/CMake/PackageDepends/MITK_Vigra_Config.cmake b/CMake/PackageDepends/MITK_Vigra_Config.cmake new file mode 100644 index 0000000000..87f8c25534 --- /dev/null +++ b/CMake/PackageDepends/MITK_Vigra_Config.cmake @@ -0,0 +1,3 @@ +list(APPEND ALL_INCLUDE_DIRECTORIES ${Vigra_INCLUDE_DIRS}) +list(APPEND ALL_LIBRARIES vigraimpex) + diff --git a/CMake/mitkFunctionGetLibrarySearchPaths.cmake b/CMake/mitkFunctionGetLibrarySearchPaths.cmake index 8a3b718be3..ba00cc5fde 100644 --- a/CMake/mitkFunctionGetLibrarySearchPaths.cmake +++ b/CMake/mitkFunctionGetLibrarySearchPaths.cmake @@ -1,137 +1,168 @@ +macro(_find_package package_name) + find_package(${package_name} REQUIRED PATHS ${${package_name}_DIR} PATH_SUFFIXES ${package_name} NO_DEFAULT_PATH NO_MODULE QUIET) + if(NOT ${package_name}_FOUND) + find_package(${package_name} REQUIRED) + endif() +endmacro() + 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(MITK_USE_HDF5) + _find_package(HDF5) + get_target_property(_location hdf5 LOCATION) + get_filename_component(_location ${_location} PATH) + list(APPEND _additional_paths ${_location}) + + # This is a work-around. The hdf5-config.cmake file is not robust enough + # to be included several times via find_pakcage calls. + set(HDF5_LIBRARIES ${HDF5_LIBRARIES} PARENT_SCOPE) + endif() + if(MITK_USE_Vigra) + # we cannot use _find_package(Vigra) here because the vigra-config.cmake file + # always includes the target-exports files without using an include guard. This + # would lead to errors when another find_package(Vigra) call is processed. The + # (bad) assumption here is that for the time being, only the Classification module + # is using Vigra. + if(UNIX) + list(APPEND _additional_paths ${Vigra_DIR}/lib) + else() + list(APPEND _additional_paths ${Vigra_DIR}/bin) + endif() + endif() + 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() else() if(SOFA_DIR) list(APPEND _dir_candidates "${SOFA_DIR}/lib") endif() endif() if(OpenCV_DIR) set(_opencv_link_directories "${OpenCV_LIB_DIR_DBG}" "${OpenCV_LIB_DIR_OPT}" "${OpenCV_3RDPARTY_LIB_DIR_DBG}" "${OpenCV_3RDPARTY_LIB_DIR_OPT}") list(REMOVE_DUPLICATES _opencv_link_directories) if(WIN32) foreach(_opencv_link_directory ${_opencv_link_directories}) list(APPEND _dir_candidates "${_opencv_link_directory}/../bin") endforeach() else() list(APPEND _dir_candidates ${_opencv_link_directories}) 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/CMake/mitkInstallRules.cmake b/CMake/mitkInstallRules.cmake index f615b28c69..1475d84a7f 100644 --- a/CMake/mitkInstallRules.cmake +++ b/CMake/mitkInstallRules.cmake @@ -1,100 +1,118 @@ MITK_INSTALL(FILES "${MITK_SOURCE_DIR}/mitk.ico") MITK_INSTALL(FILES "${MITK_SOURCE_DIR}/mitk.bmp") # Install CTK Qt (designer) plugins if(MITK_USE_CTK) if(EXISTS ${CTK_QTDESIGNERPLUGINS_DIR}) set(_qtplugin_install_destinations) if(MACOSX_BUNDLE_NAMES) foreach(bundle_name ${MACOSX_BUNDLE_NAMES}) list(APPEND _qtplugin_install_destinations ${bundle_name}.app/Contents/MacOS/${_install_DESTINATION}/plugins/designer) endforeach() else() list(APPEND _qtplugin_install_destinations bin/plugins/designer) endif() set(_ctk_qt_plugin_folder_release) set(_ctk_qt_plugin_folder_debug) if(NOT CMAKE_CFG_INTDIR STREQUAL ".") set(_ctk_qt_plugin_folder_release "Release/") set(_ctk_qt_plugin_folder_debug "Debug/") endif() foreach(_qtplugin_install_dir ${_qtplugin_install_destinations}) install(DIRECTORY "${CTK_QTDESIGNERPLUGINS_DIR}/designer/${_ctk_qt_plugin_folder_release}" DESTINATION ${_qtplugin_install_dir} CONFIGURATIONS Release ) install(DIRECTORY "${CTK_QTDESIGNERPLUGINS_DIR}/designer/${_ctk_qt_plugin_folder_debug}" DESTINATION ${_qtplugin_install_dir} CONFIGURATIONS Debug ) endforeach() endif() endif() if(WIN32) + if(MITK_USE_Qt5) + get_property(_qmake_location TARGET ${Qt5Core_QMAKE_EXECUTABLE} + PROPERTY IMPORT_LOCATION) + get_filename_component(_qmake_path "${_qmake_location}" DIRECTORY) + install(FILES "${_qmake_path}/../plugins/platforms/qwindows.dll" + DESTINATION "bin/plugins/platforms" + CONFIGURATIONS Release) + install(FILES "${_qmake_path}/../plugins/sqldrivers/qsqlite.dll" + DESTINATION "bin/plugins/sqldrivers" + CONFIGURATIONS Release) + install(FILES "${_qmake_path}/../plugins/platforms/qwindowsd.dll" + DESTINATION "bin/plugins/platforms" + CONFIGURATIONS Debug) + install(FILES "${_qmake_path}/../plugins/sqldrivers/qsqlited.dll" + DESTINATION "bin/plugins/sqldrivers" + CONFIGURATIONS Debug) + endif() + #DCMTK Dlls install target (shared libs on gcc only) if(MINGW AND DCMTK_ofstd_LIBRARY) set(_dcmtk_libs ${DCMTK_dcmdata_LIBRARY} ${DCMTK_dcmimgle_LIBRARY} ${DCMTK_dcmnet_LIBRARY} ${DCMTK_ofstd_LIBRARY} ) foreach(_dcmtk_lib ${_dcmtk_libs}) MITK_INSTALL(FILES ${_dcmtk_lib} ) endforeach() endif() #BlueBerry # Since this file is also included from external projects, you # can only use variables which are made available through MITKConfig.cmake if(MITK_USE_BLUEBERRY) if(MINGW) MITK_INSTALL(FILES "${MITK_BINARY_DIR}/bin/plugins/liborg_blueberry_core_runtime.dll") else() if(NOT APPLE) MITK_INSTALL(FILES "${MITK_BINARY_DIR}/bin/plugins/debug/liborg_blueberry_core_runtime.dll" CONFIGURATIONS Debug) MITK_INSTALL(FILES "${MITK_BINARY_DIR}/bin/plugins/release/liborg_blueberry_core_runtime.dll" CONFIGURATIONS Release) endif(NOT APPLE) endif() endif() #MinGW dll if(MINGW) find_library(MINGW_RUNTIME_DLL "mingwm10.dll" HINTS ${CMAKE_FIND_ROOT_PATH}/sys-root/mingw/bin) if(MINGW_RUNTIME_DLL) MITK_INSTALL(FILES ${MINGW_RUNTIME_DLL} ) else() message(SEND_ERROR "Could not find mingwm10.dll which is needed for a proper install") endif() find_library(MINGW_GCC_RUNTIME_DLL "libgcc_s_dw2-1.dll" HINTS ${CMAKE_FIND_ROOT_PATH}/sys-root/mingw/bin) if(MINGW_GCC_RUNTIME_DLL) MITK_INSTALL(FILES ${MINGW_GCC_RUNTIME_DLL} ) else() message(SEND_ERROR "Could not find libgcc_s_dw2-1.dll which is needed for a proper install") endif() endif() else() #DCMTK Dlls install target (shared libs on gcc only) if(DCMTK_ofstd_LIBRARY) set(_dcmtk_libs ${DCMTK_dcmdata_LIBRARY} ${DCMTK_dcmimgle_LIBRARY} ${DCMTK_dcmnet_LIBRARY} ${DCMTK_ofstd_LIBRARY} ) foreach(_dcmtk_lib ${_dcmtk_libs}) #MITK_INSTALL(FILES ${_dcmtk_lib} DESTINATION lib) endforeach() endif() endif() diff --git a/CMakeExternals/ChangeHDF5LibsInstallNameForMac.cmake.in b/CMakeExternals/ChangeHDF5LibsInstallNameForMac.cmake.in new file mode 100644 index 0000000000..ebe1f89651 --- /dev/null +++ b/CMakeExternals/ChangeHDF5LibsInstallNameForMac.cmake.in @@ -0,0 +1,17 @@ +# Get all the shared libraries which are located in the HDF5-install/lib directory +file(GLOB dylibFiles @HDF5_DIR@/lib/*.dylib) + +# For each shared library call the install_name_tool in order to change the install name of the according library +foreach(_dylib ${dylibFiles}) + message("Fixing HDF5 install name for lib: ${_dylib}") + execute_process(COMMAND install_name_tool -id ${_dylib} ${_dylib}) + foreach(_dep_dylib ${dylibFiles}) + get_filename_component(_dep_dylib_name ${_dep_dylib} NAME) + execute_process(COMMAND install_name_tool -change ${_dep_dylib_name} \@loader_path/${_dep_dylib_name} ${_dylib}) + endforeach() +endforeach() + + + + + diff --git a/CMakeExternals/HDF5.cmake b/CMakeExternals/HDF5.cmake new file mode 100644 index 0000000000..13091b6970 --- /dev/null +++ b/CMakeExternals/HDF5.cmake @@ -0,0 +1,46 @@ +#----------------------------------------------------------------------------- +# HDF5 +#----------------------------------------------------------------------------- + +if(MITK_USE_HDF5) + + # Sanity checks + if(DEFINED HDF5_DIR AND NOT EXISTS ${HDF5_DIR}) + message(FATAL_ERROR "HDF5_DIR variable is defined but corresponds to non-existing directory") + endif() + + set(proj HDF5) + set(proj_DEPENDENCIES ) + set(HDF5_DEPENDS ${proj}) + + if(NOT DEFINED HDF5_DIR) + + # We might build static libs with -DBUILD_SHARED_LIBS=0 but this conflicts with + # the in ITK integrated version! So we need to go the way with dynamic libs. Too + # bad :( This would be fixed by using an external HDF-Installation with ITK/VTK + + ExternalProject_Add(${proj} + URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/hdf5-1.8.12.tar.gz + URL_MD5 d804802feb99b87fc668a90e6fa34411 + CMAKE_GENERATOR ${gen} + CMAKE_ARGS + ${ep_common_args} + -DHDF5_BUILD_HL_LIB:BOOL=ON + -DHDF5_BUILD_CPP_LIB:BOOL=ON + -DCMAKE_INSTALL_PREFIX:PATH= + DEPENDS ${proj_DEPENDENCIES} + ) + + ExternalProject_Get_Property(${proj} install_dir) + if(WIN32) + set(HDF5_DIR ${install_dir}/cmake/hdf5) + else() + set(HDF5_DIR ${install_dir}/share/cmake/hdf5) + endif() + + else() + + mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") + + endif() +endif(MITK_USE_HDF5) diff --git a/CMakeExternals/ITK.cmake b/CMakeExternals/ITK.cmake index f66c7444c9..9389663998 100644 --- a/CMakeExternals/ITK.cmake +++ b/CMakeExternals/ITK.cmake @@ -1,78 +1,82 @@ #----------------------------------------------------------------------------- # ITK #----------------------------------------------------------------------------- # Sanity checks if(DEFINED ITK_DIR AND NOT EXISTS ${ITK_DIR}) message(FATAL_ERROR "ITK_DIR variable is defined but corresponds to non-existing directory") endif() set(proj ITK) set(proj_DEPENDENCIES GDCM) if(MITK_USE_OpenCV) list(APPEND proj_DEPENDENCIES OpenCV) endif() +if(MITK_USE_HDF5) + list(APPEND proj_DEPENDENCIES HDF5) +endif() + set(ITK_DEPENDS ${proj}) if(NOT DEFINED ITK_DIR) set(additional_cmake_args ) if(MINGW) set(additional_cmake_args -DCMAKE_USE_WIN32_THREADS:BOOL=ON -DCMAKE_USE_PTHREADS:BOOL=OFF) endif() list(APPEND additional_cmake_args -DUSE_WRAP_ITK:BOOL=OFF ) if(MITK_USE_OpenCV) list(APPEND additional_cmake_args -DModule_ITKVideoBridgeOpenCV:BOOL=ON -DOpenCV_DIR:PATH=${OpenCV_DIR} ) endif() # Keep the behaviour of ITK 4.3 which by default turned on ITK Review # see MITK bug #17338 list(APPEND additional_cmake_args -DModule_ITKReview:BOOL=ON # for 4.7, the OpenJPEG is needed by review but the variable must be set -DModule_ITKOpenJPEG:BOOL=ON ) set(vcl_constexpr_patch) if(GCC_VERSION VERSION_LESS 4.7 AND GCC_VERSION VERSION_GREATER 4) set(vcl_constexpr_patch COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/ITK-4.5.1-gcc-4.6.patch ) endif() ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/InsightToolkit-4.7.1-20c0592.tar.gz URL_MD5 f778a5f0e297c06dc629c33ec45733dc # work with external GDCM PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/ITK-4.5.1.patch ${vcl_constexpr_patch} CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} ${additional_cmake_args} -DBUILD_EXAMPLES:BOOL=OFF -DITK_USE_SYSTEM_GDCM:BOOL=ON -DGDCM_DIR:PATH=${GDCM_DIR} DEPENDS ${proj_DEPENDENCIES} ) set(ITK_DIR ${ep_prefix}) mitkFunctionInstallExternalCMakeProject(${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() diff --git a/CMakeExternals/OpenCV-2.4.8.2.patch b/CMakeExternals/OpenCV-2.4.11.patch similarity index 62% rename from CMakeExternals/OpenCV-2.4.8.2.patch rename to CMakeExternals/OpenCV-2.4.11.patch index fc5233bd46..4c2a99252e 100644 --- a/CMakeExternals/OpenCV-2.4.8.2.patch +++ b/CMakeExternals/OpenCV-2.4.11.patch @@ -1,48 +1,60 @@ -diff -burN OpenCV-2.4.8.2/cmake/OpenCVModule.cmake OpenCV/cmake/OpenCVModule.cmake ---- OpenCV-2.4.8.2/cmake/OpenCVModule.cmake 2014-02-14 14:12:31.000000000 +0100 -+++ OpenCV/cmake/OpenCVModule.cmake 2015-01-29 17:02:40.735387894 +0100 -@@ -503,7 +503,7 @@ +--- OpenCV-2.4.11/cmake/OpenCVModule.cmake 2015-02-25 13:10:31.000000000 +0100 ++++ opencv/cmake/OpenCVModule.cmake 2015-03-06 13:05:45.000000000 +0100 +@@ -519,7 +519,7 @@ ocv_include_directories(${OPENCL_INCLUDE_DIRS}) add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.cpp" "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.hpp" - COMMAND ${CMAKE_COMMAND} -DCL_DIR="${CMAKE_CURRENT_SOURCE_DIR}/src/opencl" -DOUTPUT="${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.cpp" -P "${OpenCV_SOURCE_DIR}/cmake/cl2cpp.cmake" + COMMAND ${CMAKE_COMMAND} -DCL_DIR=${CMAKE_CURRENT_SOURCE_DIR}/src/opencl -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.cpp -P ${OpenCV_SOURCE_DIR}/cmake/cl2cpp.cmake DEPENDS ${cl_kernels} "${OpenCV_SOURCE_DIR}/cmake/cl2cpp.cmake") source_group("OpenCL" FILES ${cl_kernels} "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.cpp" "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.hpp") list(APPEND lib_srcs ${cl_kernels} "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.cpp" "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.hpp") -@@ -551,7 +551,7 @@ +@@ -589,7 +589,7 @@ ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH} LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH} RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} - INSTALL_NAME_DIR lib + # INSTALL_NAME_DIR lib ) # For dynamic link numbering convenions -@@ -894,3 +894,4 @@ - __ocv_track_module_link_dependencies("${m}" DBG) - endforeach() - endmacro() -+ -diff -burN OpenCV-2.4.8.2/cmake/templates/OpenCVConfig.cmake.in OpenCV/cmake/templates/OpenCVConfig.cmake.in ---- OpenCV-2.4.8.2/cmake/templates/OpenCVConfig.cmake.in 2014-02-14 14:12:31.000000000 +0100 -+++ OpenCV/cmake/templates/OpenCVConfig.cmake.in 2015-01-29 14:20:42.003947242 +0100 -@@ -90,7 +90,7 @@ +--- OpenCV-2.4.11/cmake/templates/OpenCVConfig.cmake.in 2015-02-25 13:10:31.000000000 +0100 ++++ opencv/cmake/templates/OpenCVConfig.cmake.in 2015-03-06 13:08:56.000000000 +0100 +@@ -120,7 +120,7 @@ # Provide the include directories to the caller set(OpenCV_INCLUDE_DIRS @OpenCV_INCLUDE_DIRS_CONFIGCMAKE@) -include_directories(${OpenCV_INCLUDE_DIRS}) +# include_directories(${OpenCV_INCLUDE_DIRS}) # ====================================================== # Link directories to add to the user project: -@@ -123,7 +123,7 @@ +@@ -153,7 +153,7 @@ # ============================================================== SET(OpenCV2_INCLUDE_DIRS @OpenCV2_INCLUDE_DIRS_CONFIGCMAKE@) if(OpenCV2_INCLUDE_DIRS) - include_directories(${OpenCV2_INCLUDE_DIRS}) + # include_directories(${OpenCV2_INCLUDE_DIRS}) list(APPEND OpenCV_INCLUDE_DIRS ${OpenCV2_INCLUDE_DIRS}) set(OpenCV_ADD_DEBUG_RELEASE @OpenCV_ADD_DEBUG_RELEASE_CONFIGCMAKE@) +--- OpenCV-2.4.11/modules/highgui/src/cap_gstreamer.cpp 2015-02-25 13:10:31.000000000 +0100 ++++ opencv/modules/highgui/src/cap_gstreamer.cpp 2015-03-09 10:51:34.000000000 +0100 +@@ -574,7 +574,7 @@ + return false; + } + g_object_unref(G_OBJECT(testfac)); +- filename = "v4lsrc ! "COLOR_ELEM" ! appsink"; ++ filename = "v4lsrc ! " COLOR_ELEM " ! appsink"; + } + if (type == CV_CAP_GSTREAMER_V4L2){ + testfac = gst_element_factory_find("v4l2src"); +@@ -582,7 +582,7 @@ + return false; + } + g_object_unref(G_OBJECT(testfac)); +- filename = "v4l2src ! "COLOR_ELEM" ! appsink"; ++ filename = "v4l2src ! " COLOR_ELEM " ! appsink"; + } + diff --git a/CMakeExternals/OpenCV.cmake b/CMakeExternals/OpenCV.cmake index 4667415b4d..0534497145 100644 --- a/CMakeExternals/OpenCV.cmake +++ b/CMakeExternals/OpenCV.cmake @@ -1,93 +1,93 @@ #----------------------------------------------------------------------------- # OpenCV #----------------------------------------------------------------------------- if(MITK_USE_OpenCV) # Sanity checks if(DEFINED OpenCV_DIR AND NOT EXISTS ${OpenCV_DIR}) message(FATAL_ERROR "OpenCV_DIR variable is defined but corresponds to non-existing directory") endif() set(proj OpenCV) set(proj_DEPENDENCIES) set(OpenCV_DEPENDS ${proj}) if(NOT DEFINED OpenCV_DIR) set(additional_cmake_args -DBUILD_opencv_java:BOOL=OFF -DBUILD_opencv_ts:BOOL=OFF -DBUILD_PERF_TESTS:BOOL=OFF ) if(MITK_USE_Python) #message(STATUS "PYTHON_EXECUTABLE: ${PYTHON_EXECUTABLE}") #message(STATUS "PYTHON_DEBUG_LIBRARY: ${PYTHON_DEBUG_LIBRARY}") #message(STATUS "PYTHON_INCLUDE_DIR: ${PYTHON_INCLUDE_DIR}") #message(STATUS "PYTHON_LIBRARY: ${PYTHON_LIBRARY}") list(APPEND additional_cmake_args -DBUILD_opencv_python:BOOL=ON -DBUILD_NEW_PYTHON_SUPPORT:BOOL=ON -DPYTHON_DEBUG_LIBRARY:FILEPATH=${PYTHON_DEBUG_LIBRARY} -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} #-DPYTHON_LIBRARIES=${PYTHON_LIBRARY} #-DPYTHON_DEBUG_LIBRARIES=${PYTHON_DEBUG_LIBRARIES} ) if(NOT MITK_USE_SYSTEM_PYTHON) list(APPEND proj_DEPENDENCIES Python Numpy) # export python home set(ENV{PYTHONHOME} "${Python_DIR}") endif() else() list(APPEND additional_cmake_args -DBUILD_opencv_python:BOOL=OFF -DBUILD_NEW_PYTHON_SUPPORT:BOOL=OFF ) endif() # 12-05-02, muellerm, added QT usage by OpenCV if QT is used in MITK # 12-09-11, muellerm, removed automatic usage again, since this will struggle with the MITK Qt application object if(MITK_USE_QT) list(APPEND additional_cmake_args -DWITH_QT:BOOL=OFF -DWITH_QT_OPENGL:BOOL=OFF -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} ) endif() - set(opencv_url ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/OpenCV-2.4.8.2.tar.gz) - set(opencv_url_md5 07fa7c1d225ea7fe8eeb1270a6b00e69) + set(opencv_url ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/OpenCV-2.4.11.tar.gz) + set(opencv_url_md5 54fe3dba49ea276ec0228f8819e653bc) ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} URL ${opencv_url} URL_MD5 ${opencv_url_md5} # Related bug: http://bugs.mitk.org/show_bug.cgi?id=5912 - PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/OpenCV-2.4.8.2.patch + PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/OpenCV-2.4.11.patch CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} -DBUILD_TESTS:BOOL=OFF -DBUILD_DOCS:BOOL=OFF -DBUILD_EXAMPLES:BOOL=OFF -DBUILD_DOXYGEN_DOCS:BOOL=OFF -DWITH_CUDA:BOOL=OFF ${additional_cmake_args} DEPENDS ${proj_DEPENDENCIES} ) set(OpenCV_DIR ${ep_prefix}) mitkFunctionInstallExternalCMakeProject(${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() endif() diff --git a/CMakeExternals/VTK.cmake b/CMakeExternals/VTK.cmake index 0c2259f748..07f3cd1c29 100644 --- a/CMakeExternals/VTK.cmake +++ b/CMakeExternals/VTK.cmake @@ -1,109 +1,112 @@ #----------------------------------------------------------------------------- # VTK #----------------------------------------------------------------------------- if(WIN32) option(VTK_USE_SYSTEM_FREETYPE OFF) else(WIN32) option(VTK_USE_SYSTEM_FREETYPE ON) endif(WIN32) # Sanity checks if(DEFINED VTK_DIR AND NOT EXISTS ${VTK_DIR}) message(FATAL_ERROR "VTK_DIR variable is defined but corresponds to non-existing directory") endif() set(proj VTK) set(proj_DEPENDENCIES ) set(VTK_DEPENDS ${proj}) +if(MITK_USE_HDF5) + list(APPEND proj_DEPENDENCIES HDF5) +endif() + if(NOT DEFINED VTK_DIR) set(additional_cmake_args ) if(MINGW) set(additional_cmake_args -DCMAKE_USE_WIN32_THREADS:BOOL=ON -DCMAKE_USE_PTHREADS:BOOL=OFF -DVTK_USE_VIDEO4WINDOWS:BOOL=OFF # no header files provided by MinGW ) endif() if(WIN32) # see http://bugs.mitk.org/show_bug.cgi?id=17858 list(APPEND additional_cmake_args -DVTK_DO_NOT_DEFINE_OSTREAM_SLL:BOOL=ON -DVTK_DO_NOT_DEFINE_OSTREAM_ULL:BOOL=ON ) endif() # Optionally enable memory leak checks for any objects derived from vtkObject. This # will force unit tests to fail if they have any of these memory leaks. option(MITK_VTK_DEBUG_LEAKS OFF) mark_as_advanced(MITK_VTK_DEBUG_LEAKS) list(APPEND additional_cmake_args -DVTK_DEBUG_LEAKS:BOOL=${MITK_VTK_DEBUG_LEAKS} ) if(MITK_USE_Python) if(NOT MITK_USE_SYSTEM_PYTHON) list(APPEND proj_DEPENDENCIES Python) endif() list(APPEND additional_cmake_args -DVTK_WRAP_PYTHON:BOOL=ON -DVTK_USE_TK:BOOL=OFF -DVTK_WINDOWS_PYTHON_DEBUGGABLE:BOOL=OFF -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} ) else() list(APPEND additional_cmake_args -DVTK_WRAP_PYTHON:BOOL=OFF -DVTK_WINDOWS_PYTHON_DEBUGGABLE:BOOL=OFF ) endif() if(MITK_USE_QT) list(APPEND additional_cmake_args -DVTK_QT_VERSION:STRING=${DESIRED_QT_VERSION} -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} -DModule_vtkGUISupportQt:BOOL=ON -DModule_vtkGUISupportQtWebkit:BOOL=ON -DModule_vtkGUISupportQtSQL:BOOL=ON -DModule_vtkRenderingQt:BOOL=ON -DVTK_Group_Qt:BOOL=ON ) endif() set(VTK_URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/VTK-6.1.0+74f4888.tar.gz) set(VTK_URL_MD5 1f19dae22c42c032109bd3cf91c4e8c9) - ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} URL ${VTK_URL} URL_MD5 ${VTK_URL_MD5} PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/VTK-6.1.0+74f4888.patch CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} -DVTK_WRAP_TCL:BOOL=OFF -DVTK_WRAP_PYTHON:BOOL=OFF -DVTK_WRAP_JAVA:BOOL=OFF -DVTK_USE_SYSTEM_FREETYPE:BOOL=${VTK_USE_SYSTEM_FREETYPE} -DVTK_LEGACY_REMOVE:BOOL=ON -DModule_vtkTestingRendering:BOOL=ON -DVTK_MAKE_INSTANTIATORS:BOOL=ON ${additional_cmake_args} DEPENDS ${proj_DEPENDENCIES} ) set(VTK_DIR ${ep_prefix}) mitkFunctionInstallExternalCMakeProject(${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() diff --git a/CMakeExternals/Vigra.cmake b/CMakeExternals/Vigra.cmake new file mode 100644 index 0000000000..c0f9517438 --- /dev/null +++ b/CMakeExternals/Vigra.cmake @@ -0,0 +1,43 @@ +#----------------------------------------------------------------------------- +# VIGRA +#----------------------------------------------------------------------------- + +if(MITK_USE_Vigra) + + # Sanity checks + if(DEFINED Vigra_DIR AND NOT EXISTS ${Vigra_DIR}) + message(FATAL_ERROR "Vigra_DIR variable is defined but corresponds to non-existing directory") + endif() + + if(NOT ${MITK_USE_HDF5}) + message(FATAL_ERROR "HDF5 is required for Vigra. Please enable it.") + endif() + + set(proj Vigra) + set(proj_DEPENDENCIES HDF5) + set(Vigra_DEPENDS ${proj}) + + if(NOT DEFINED Vigra_DIR) + ExternalProject_Add(${proj} + URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/vigra-1.10.0-src.tar.gz + URL_MD5 4f963f0be4fcb8b06271c2aa40baa9be + PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/Vigra.patch + CMAKE_GENERATOR ${gen} + CMAKE_ARGS + ${ep_common_args} + -DAUTOEXEC_TESTS:BOOL=OFF + -DWITH_VIGRANUMPY:BOOL=OFF + -DHDF5_DIR:PATH=${HDF5_DIR} + -DCMAKE_INSTALL_RPATH_USE_LINK_PATH:BOOL=TRUE + -DCMAKE_INSTALL_PREFIX:PATH= + DEPENDS ${proj_DEPENDENCIES} + ) + + set(Vigra_DIR ${ep_prefix}) + + else() + + mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") + + endif() +endif(MITK_USE_Vigra) diff --git a/CMakeExternals/Vigra.patch b/CMakeExternals/Vigra.patch new file mode 100644 index 0000000000..b462dacc91 --- /dev/null +++ b/CMakeExternals/Vigra.patch @@ -0,0 +1,291 @@ +diff -urNb vigra-Version-1-10-0/CMakeLists.txt Vigra/CMakeLists.txt +--- vigra-Version-1-10-0/CMakeLists.txt 2013-11-18 17:48:16.000000000 +0100 ++++ Vigra/CMakeLists.txt 2015-03-03 10:13:57.693725000 +0100 +@@ -70,8 +70,11 @@ + ENDIF() + + IF(WITH_HDF5) ++ FIND_PACKAGE(HDF5 PATHS ${HDF5_DIR} PATH_SUFFIXES hdf5 NO_DEFAULT_PATH NO_MODULE) ++IF(NOT HDF5_FOUND) + VIGRA_FIND_PACKAGE(HDF5) + ENDIF() ++ENDIF() + + IF(WITH_BOOST_GRAPH) + IF(WITH_VIGRANUMPY) +@@ -395,3 +398,4 @@ + ENDIF() + + MESSAGE( STATUS "---------------------------------------------------------" ) ++ +diff -urNb vigra-Version-1-10-0/config/VigraConfig.cmake.in Vigra/config/VigraConfig.cmake.in +--- vigra-Version-1-10-0/config/VigraConfig.cmake.in 2013-11-18 17:48:16.000000000 +0100 ++++ Vigra/config/VigraConfig.cmake.in 2015-03-03 10:13:57.693725000 +0100 +@@ -1,7 +1,9 @@ + get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) + get_filename_component(Vigra_TOP_DIR "${SELF_DIR}/../../" ABSOLUTE) + +-include(${SELF_DIR}/vigra-targets.cmake) ++if(NOT TARGET vigraimpex) ++ include(${SELF_DIR}/vigra-targets.cmake) ++endif() + get_target_property(VIGRA_TYPE vigraimpex TYPE) + if(${VIGRA_TYPE} STREQUAL "STATIC_LIBRARY") + SET(VIGRA_STATIC_LIB True) +@@ -12,3 +14,4 @@ + IF(EXISTS ${SELF_DIR}/../vigranumpy/VigranumpyConfig.cmake) + INCLUDE(${SELF_DIR}/../vigranumpy/VigranumpyConfig.cmake) + ENDIF() ++ +diff -urNb vigra-Version-1-10-0/include/vigra/random_forest/rf_common.hxx Vigra/include/vigra/random_forest/rf_common.hxx +--- vigra-Version-1-10-0/include/vigra/random_forest/rf_common.hxx 2013-11-18 17:48:16.000000000 +0100 ++++ Vigra/include/vigra/random_forest/rf_common.hxx 2015-03-03 10:45:19.423056174 +0100 +@@ -558,6 +558,7 @@ + int is_weighted_; // class_weights_ are used + double precision_; // termination criterion for regression loss + int response_size_; ++ int max_tree_depth; + + template + void to_classlabel(int index, T & out) const +@@ -583,7 +584,8 @@ + EQUALS(class_weights_), + EQUALS(is_weighted_), + EQUALS(precision_), +- EQUALS(response_size_) ++ EQUALS(response_size_), ++ EQUALS(max_tree_depth) + { + std::back_insert_iterator > + iter(classes); +@@ -604,7 +606,8 @@ + EQUALS(class_weights_), + EQUALS(is_weighted_), + EQUALS(precision_), +- EQUALS(response_size_) ++ EQUALS(response_size_), ++ EQUALS(max_tree_depth) + { + std::back_insert_iterator > + iter(classes); +@@ -624,7 +627,8 @@ + EQUALS(used_); + EQUALS(is_weighted_); + EQUALS(precision_); +- EQUALS(response_size_) ++ EQUALS(response_size_); ++ EQUALS(max_tree_depth) + class_weights_.clear(); + std::back_insert_iterator > + iter2(class_weights_); +@@ -648,7 +652,8 @@ + EQUALS(used_); + EQUALS(is_weighted_); + EQUALS(precision_); +- EQUALS(response_size_) ++ EQUALS(response_size_); ++ EQUALS(max_tree_depth) + class_weights_.clear(); + std::back_insert_iterator > + iter2(class_weights_); +@@ -677,7 +682,8 @@ + COMPARE(used_); + COMPARE(class_weights_); + COMPARE(classes); +- COMPARE(response_size_) ++ COMPARE(response_size_); ++ COMPARE(max_tree_depth) + #undef COMPARE + return result; + } +@@ -715,6 +721,7 @@ + PULL(used_, int); + PULL(precision_, double); + PULL(response_size_, int); ++ PULL(max_tree_depth, int); + if(is_weighted_) + { + vigra_precondition(end - begin == 10 + 2*class_count_, +@@ -747,6 +754,7 @@ + PUSH(used_); + PUSH(precision_); + PUSH(response_size_); ++ PUSH(max_tree_depth); + if(is_weighted_) + { + std::copy(class_weights_.begin(), +@@ -773,6 +781,7 @@ + PULL(used_, int); + PULL(precision_, double); + PULL(response_size_, int); ++ PULL(max_tree_depth, int); + class_weights_ = in["class_weights_"]; + #undef PUSH + } +@@ -789,6 +798,7 @@ + PUSH(used_); + PUSH(precision_); + PUSH(response_size_); ++ PUSH(max_tree_depth); + in["class_weights_"] = class_weights_; + #undef PUSH + } +@@ -805,7 +815,8 @@ + used_(false), + is_weighted_(false), + precision_(0.0), +- response_size_(1) ++ response_size_(1), ++ max_tree_depth(50) + {} + + +@@ -857,7 +868,7 @@ + is_weighted_ = false; + precision_ = 0.0; + response_size_ = 0; +- ++ max_tree_depth = 50; + } + + bool used() const +diff -urNb vigra-Version-1-10-0/include/vigra/random_forest/rf_decisionTree.hxx Vigra/include/vigra/random_forest/rf_decisionTree.hxx +--- vigra-Version-1-10-0/include/vigra/random_forest/rf_decisionTree.hxx 2013-11-18 17:48:16.000000000 +0100 ++++ Vigra/include/vigra/random_forest/rf_decisionTree.hxx 2015-03-03 10:49:22.264260358 +0100 +@@ -90,6 +90,8 @@ + ProblemSpec<> ext_param_; + unsigned int classCount_; + ++ std::map m_Parents; ++ + + public: + /* \brief Create tree with parameters */ +@@ -350,6 +352,22 @@ + continueLearn(features,labels,stack_entry,split,stop,visitor,randint); + } + ++template < class TRandomForest> ++int GetTreeDepthForNode(int nodeIndex, TRandomForest* rf) ++{ ++ int depth = 0; ++ while (true) ++ { ++ if (nodeIndex < 1) ++ { ++ break; ++ } ++ ++depth; ++ nodeIndex = rf->m_Parents[nodeIndex]; ++ } ++ return depth; ++} ++ + template < class U, class C, + class U2, class C2, + class StackEntry_t, +@@ -374,6 +392,11 @@ + size_t last_node_pos = 0; + StackEntry_t top=stack.back(); + ++ Split_t* splitPointer = &split; ++ bool isDepthSplitter = true; ++ ++ int maximumTreeDepth = splitPointer->GetMaximumTreeDepth(); ++ + while(!stack.empty()) + { + +@@ -392,7 +415,20 @@ + //kind of node to make + TreeInt NodeID; + +- if(stop(top)) ++ bool depthStop = false; ++ if (isDepthSplitter) ++ { ++ int currentDepthLevel; ++ if (top.leftParent != StackEntry_t::DecisionTreeNoParent) ++ currentDepthLevel = GetTreeDepthForNode(top.leftParent, this); ++ else ++ currentDepthLevel = GetTreeDepthForNode(top.rightParent, this); ++ ++ depthStop = (currentDepthLevel >= maximumTreeDepth); ++ } ++ if(stop(top) || (depthStop)) ++ ++ //if (stop(top) || currentDepthLevel >= MaximumSplitDepth(split)) + NodeID = split.makeTerminalNode(features, + labels, + top, +@@ -421,17 +457,20 @@ + // Using InteriorNodeBase because exact parameter form not needed. + // look at the Node base before getting scared. + last_node_pos = topology_.size(); ++ m_Parents[last_node_pos] = StackEntry_t::DecisionTreeNoParent; + if(top.leftParent != StackEntry_t::DecisionTreeNoParent) + { + NodeBase(topology_, + parameters_, + top.leftParent).child(0) = last_node_pos; ++ m_Parents[last_node_pos] = top.leftParent; + } + else if(top.rightParent != StackEntry_t::DecisionTreeNoParent) + { + NodeBase(topology_, + parameters_, + top.rightParent).child(1) = last_node_pos; ++ m_Parents[last_node_pos] = top.rightParent; + } + + +diff -urNb vigra-Version-1-10-0/include/vigra/random_forest/rf_nodeproxy.hxx Vigra/include/vigra/random_forest/rf_nodeproxy.hxx +--- vigra-Version-1-10-0/include/vigra/random_forest/rf_nodeproxy.hxx 2013-11-18 17:48:16.000000000 +0100 ++++ Vigra/include/vigra/random_forest/rf_nodeproxy.hxx 2015-03-03 10:13:57.693725000 +0100 +@@ -50,7 +50,11 @@ + namespace vigra + { + +- ++class DepthSplitterBase ++{ ++public: ++ virtual int GetMaximumTreeDepth() const = 0; ++}; + + enum NodeTags + { +diff -urNb vigra-Version-1-10-0/include/vigra/random_forest/rf_split.hxx Vigra/include/vigra/random_forest/rf_split.hxx +--- vigra-Version-1-10-0/include/vigra/random_forest/rf_split.hxx 2013-11-18 17:48:16.000000000 +0100 ++++ Vigra/include/vigra/random_forest/rf_split.hxx 2015-03-03 10:49:01.164155728 +0100 +@@ -108,6 +108,11 @@ + \ref SplitBase::findBestSplit() or \ref SplitBase::makeTerminalNode(). + **/ + ++ virtual int GetMaximumTreeDepth() ++ { ++ return ext_param_.max_tree_depth; ++ } ++ + template + void set_external_parameters(ProblemSpec const & in) + { +diff -urNb vigra-Version-1-10-0/include/vigra/random_forest.hxx Vigra/include/vigra/random_forest.hxx +--- vigra-Version-1-10-0/include/vigra/random_forest.hxx 2013-11-18 17:48:16.000000000 +0100 ++++ Vigra/include/vigra/random_forest.hxx 2015-03-03 10:13:57.693725000 +0100 +@@ -584,6 +584,7 @@ + { + vigra_precondition(features.shape(0) == labels.shape(0), + "RandomForest::predictLabels(): Label array has wrong size."); ++#pragma omp parallel for + for(int k=0; k currentRow(rowVector(features, row)); diff --git a/CMakeLists.txt b/CMakeLists.txt index a8122cde04..324416ee26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,1337 +1,1366 @@ set(MITK_CMAKE_MINIMUM_REQUIRED_VERSION 3.1) cmake_minimum_required(VERSION ${MITK_CMAKE_MINIMUM_REQUIRED_VERSION}) #----------------------------------------------------------------------------- # 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() #----------------------------------------------------------------------------- # 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() #----------------------------------------------------------------------------- # 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(mitkFunctionGetGccVersion) include(mitkFunctionCheckCompilerFlags) include(mitkFunctionSuppressWarnings) # includes several functions include(mitkMacroEmptyExternalProject) include(mitkFunctionGenerateProjectXml) include(mitkFunctionEnableBuildConfiguration) include(mitkFunctionWhitelists) include(mitkFunctionAddExternalProject) SUPPRESS_VC_DEPRECATED_WARNINGS() #----------------------------------------------------------------------------- # 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() +#----------------------------------------------------------------------------- +# Check miminum Mac OS X version +#----------------------------------------------------------------------------- +# The minimum supported Mac OS X version is 10.9. If you use a version less than 10.9, there is no guarantee that the build still works. +if(APPLE) + exec_program(sw_vers ARGS -productVersion OUTPUT_VARIABLE osx_version) + if (osx_version VERSION_LESS "10.9") + message(WARNING "Detected OS X version \"${osx_version}\" is not supported anymore. Minimum required OS X version is 10.9 or greater.") + endif() + if (CMAKE_OSX_DEPLOYMENT_TARGET AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS 10.9) + message(WARNING "Detected OS X deployment target \"${CMAKE_OSX_DEPLOYMENT_TARGET}\" is not supported anymore. Minimum required OS X version is 10.9 or greater.") + endif() +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() if(CMAKE_COMPILER_IS_GNUCXX) mitkFunctionGetGccVersion(${CMAKE_CXX_COMPILER} GCC_VERSION) else() set(GCC_VERSION 0) endif() 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" AND GCC_VERSION VERSION_GREATER 4.6) set(CMAKE_CXX_EXTENSIONS 0) set(CMAKE_CXX_STANDARD ${MITK_CXX_STANDARD}) set(CMAKE_CXX_STANDARD_REQUIRED 1) 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. # However, compile flag checks also need to be done with -std=c++11. # The MITK_CXX11_FLAG variable is also used for external projects # build during the MITK super-build. mitkFunctionCheckCompilerFlags("-std=c++11" MITK_CXX11_FLAG) if(NOT MITK_CXX11_FLAG) # Older gcc compilers use -std=c++0x mitkFunctionCheckCompilerFlags("-std=c++0x" MITK_CXX11_FLAG) 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() #----------------------------------------------------------------------------- # 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 if(APPLE) set(DESIRED_QT_VERSION 4 CACHE STRING "Pick a version of Qt to use: 4 or 5") else() set(DESIRED_QT_VERSION 5 CACHE STRING "Pick a version of Qt to use: 4 or 5") endif() env_option(MITK_USE_QT "Use the Qt Company'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(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}" CACHE PATH "") 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 Zip) 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) +mitkFunctionAddExternalProject(NAME HDF5 OFF ADVANCED) + # ----------------------------------------- # The following external projects must be # ordered according to their # inter-dependencies 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) +mitkFunctionAddExternalProject(NAME Vigra OFF DEPENDS HDF5) # 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 QT 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") if(MITK_USE_QT) mitkFunctionAddExternalProject(NAME Qwt ON ADVANCED DEPENDS QT) 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) #----------------------------------------------------------------------------- # 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) # ----------------------------------------- # 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() #----------------------------------------------------------------------------- # 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(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 #----------------------------------------------------------------------------- # 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} ${MITK_CXX11_FLAG}") set(MITK_CXX_FLAGS_DEBUG ) set(MITK_CXX_FLAGS_RELEASE ) set(MITK_EXE_LINKER_FLAGS ) set(MITK_SHARED_LINKER_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) # 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}) if(NOT MITK_USE_SYSTEM_Boost) set(Boost_NO_SYSTEM_PATHS 1) endif() set(Boost_USE_MULTITHREADED 1) set(Boost_USE_STATIC_LIBS 0) set(Boost_USE_STATIC_RUNTIME 0) # We need this later for a DCMTK workaround set(_dcmtk_dir_orig ${DCMTK_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 fail. # (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() # Ensure that the MITK CMake module path comes first set(CMAKE_MODULE_PATH ${MITK_CMAKE_DIR} ${CMAKE_MODULE_PATH} ) if(MITK_USE_DCMTK) # Due to the preferred CONFIG mode in find_package calls above, # the DCMTKConfig.cmake file is read, which does not provide useful # package information. We explictly need MODULE mode to find DCMTK. if(${_dcmtk_dir_orig} MATCHES "${MITK_EXTERNAL_PROJECT_PREFIX}.*") # Help our FindDCMTK.cmake script find our super-build DCMTK set(DCMTK_DIR ${MITK_EXTERNAL_PROJECT_PREFIX}) else() # Use the original value set(DCMTK_DIR ${_dcmtk_dir_orig}) endif() find_package(DCMTK REQUIRED MODULE) endif() 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() if(MITK_USE_Boost) # Same as SOFA above link_directories(${Boost_LIBRARY_DIRS}) endif() if(MITK_USE_OpenIGTLink) # Same as SOFA above link_directories(${OpenIGTLink_LIBRARY_DIRS}) endif() if(MITK_USE_SimpleITK) link_directories(${SimpleITK_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 get_target_property(_qmake_exec Qt5::qmake LOCATION) execute_process(COMMAND ${_qmake_exec} -query QT_INSTALL_BINS RESULT_VARIABLE _result OUTPUT_VARIABLE QT_BINARY_DIR ERROR_VARIABLE _error ) string(STRIP "${QT_BINARY_DIR}" QT_BINARY_DIR) if(_result OR NOT EXISTS "${QT_BINARY_DIR}") message(FATAL_ERROR "Could not determine Qt binary directory: ${_result} ${QT_BINARY_DIR} ${_error}") endif() endif() endif() #----------------------------------------------------------------------------- # 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) 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_CXX_FLAGS "${MITK_CXX_FLAGS}") set(BLUEBERRY_CXX_FLAGS_RELEASE "${MITK_CXX_FLAGS_RELEASE}") set(BLUEBERRY_C_FLAGS "${MITK_C_FLAGS}") 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") + if(MITK_USE_HDF5) + list(APPEND MITK_LIBRARY_DIRS ${HDF5_DIR}/install/bin) + message(STATUS "MITK-Runtime " ${MITK_RUNTIME_PATH}) + endif(MITK_USE_HDF5) 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/Modules/DiffusionImaging/FiberTracking/Algorithms/MLTracking/itkMLBSTrackingFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/MLTracking/itkMLBSTrackingFilter.cpp new file mode 100644 index 0000000000..d8eb05879a --- /dev/null +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/MLTracking/itkMLBSTrackingFilter.cpp @@ -0,0 +1,791 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY 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 __itkMLBSTrackingFilter_txx +#define __itkMLBSTrackingFilter_txx + +#include +#include +#include + +#include "itkMLBSTrackingFilter.h" +#include +#include +#include +#include +//#include + +#define _USE_MATH_DEFINES +#include + +namespace itk { + +template< int NumImageFeatures > +MLBSTrackingFilter< NumImageFeatures > +::MLBSTrackingFilter() + : m_FiberPolyData(NULL) + , m_Points(NULL) + , m_Cells(NULL) + , m_AngularThreshold(0.7) + , m_StepSize(0) + , m_MaxLength(10000) + , m_MinTractLength(20.0) + , m_MaxTractLength(400.0) + , m_SeedsPerVoxel(1) + , m_UseDirection(true) + , m_NumberOfSamples(50) + , m_SamplingDistance(-1) + , m_SeedImage(NULL) + , m_MaskImage(NULL) + , m_DecisionForest(NULL) + , m_StoppingRegions(NULL) + , m_DemoMode(false) + , m_PauseTracking(false) + , m_AbortTracking(false) + , m_RemoveWmEndFibers(false) + , m_AposterioriCurvCheck(false) + , m_AvoidStop(true) +{ + this->SetNumberOfRequiredInputs(1); +} + +template< int NumImageFeatures > +double MLBSTrackingFilter< NumImageFeatures > +::RoundToNearest(double num) { + return (num > 0.0) ? floor(num + 0.5) : ceil(num - 0.5); +} + +template< int NumImageFeatures > +void MLBSTrackingFilter< NumImageFeatures >::BeforeThreadedGenerateData() +{ + m_InputImage = const_cast(this->GetInput(0)); + PreprocessRawData(); + + m_FiberPolyData = PolyDataType::New(); + m_Points = vtkSmartPointer< vtkPoints >::New(); + m_Cells = vtkSmartPointer< vtkCellArray >::New(); + + m_ImageSize.resize(3); + m_ImageSize[0] = m_FeatureImage->GetLargestPossibleRegion().GetSize()[0]; + m_ImageSize[1] = m_FeatureImage->GetLargestPossibleRegion().GetSize()[1]; + m_ImageSize[2] = m_FeatureImage->GetLargestPossibleRegion().GetSize()[2]; + + m_ImageSpacing.resize(3); + m_ImageSpacing[0] = m_FeatureImage->GetSpacing()[0]; + m_ImageSpacing[1] = m_FeatureImage->GetSpacing()[1]; + m_ImageSpacing[2] = m_FeatureImage->GetSpacing()[2]; + + double minSpacing; + if(m_ImageSpacing[0]GetNumberOfThreads(); i++) + { + PolyDataType poly = PolyDataType::New(); + m_PolyDataContainer.push_back(poly); + } + + m_NotWmImage = ItkDoubleImgType::New(); + m_NotWmImage->SetSpacing( m_FeatureImage->GetSpacing() ); + m_NotWmImage->SetOrigin( m_FeatureImage->GetOrigin() ); + m_NotWmImage->SetDirection( m_FeatureImage->GetDirection() ); + m_NotWmImage->SetRegions( m_FeatureImage->GetLargestPossibleRegion() ); + m_NotWmImage->Allocate(); + m_NotWmImage->FillBuffer(0); + + m_WmImage = ItkDoubleImgType::New(); + m_WmImage->SetSpacing( m_FeatureImage->GetSpacing() ); + m_WmImage->SetOrigin( m_FeatureImage->GetOrigin() ); + m_WmImage->SetDirection( m_FeatureImage->GetDirection() ); + m_WmImage->SetRegions( m_FeatureImage->GetLargestPossibleRegion() ); + m_WmImage->Allocate(); + m_WmImage->FillBuffer(0); + + m_AvoidStopImage = ItkDoubleImgType::New(); + m_AvoidStopImage->SetSpacing( m_FeatureImage->GetSpacing() ); + m_AvoidStopImage->SetOrigin( m_FeatureImage->GetOrigin() ); + m_AvoidStopImage->SetDirection( m_FeatureImage->GetDirection() ); + m_AvoidStopImage->SetRegions( m_FeatureImage->GetLargestPossibleRegion() ); + m_AvoidStopImage->Allocate(); + m_AvoidStopImage->FillBuffer(0); + + if (m_StoppingRegions.IsNull()) + { + m_StoppingRegions = ItkUcharImgType::New(); + m_StoppingRegions->SetSpacing( m_FeatureImage->GetSpacing() ); + m_StoppingRegions->SetOrigin( m_FeatureImage->GetOrigin() ); + m_StoppingRegions->SetDirection( m_FeatureImage->GetDirection() ); + m_StoppingRegions->SetRegions( m_FeatureImage->GetLargestPossibleRegion() ); + m_StoppingRegions->Allocate(); + m_StoppingRegions->FillBuffer(0); + } + + if (m_SeedImage.IsNull()) + { + m_SeedImage = ItkUcharImgType::New(); + m_SeedImage->SetSpacing( m_FeatureImage->GetSpacing() ); + m_SeedImage->SetOrigin( m_FeatureImage->GetOrigin() ); + m_SeedImage->SetDirection( m_FeatureImage->GetDirection() ); + m_SeedImage->SetRegions( m_FeatureImage->GetLargestPossibleRegion() ); + m_SeedImage->Allocate(); + m_SeedImage->FillBuffer(1); + } + + if (m_MaskImage.IsNull()) + { + // initialize mask image + m_MaskImage = ItkUcharImgType::New(); + m_MaskImage->SetSpacing( m_FeatureImage->GetSpacing() ); + m_MaskImage->SetOrigin( m_FeatureImage->GetOrigin() ); + m_MaskImage->SetDirection( m_FeatureImage->GetDirection() ); + m_MaskImage->SetRegions( m_FeatureImage->GetLargestPossibleRegion() ); + m_MaskImage->Allocate(); + m_MaskImage->FillBuffer(1); + } + else + std::cout << "MLBSTrackingFilter: using mask image" << std::endl; + + if (m_AngularThreshold<0.0) + m_AngularThreshold = 0.5*minSpacing; + + m_BuildFibersReady = 0; + m_BuildFibersFinished = false; + m_Threads = 0; + m_Tractogram.clear(); + + std::cout << "MLBSTrackingFilter: Angular threshold: " << m_AngularThreshold << std::endl; + std::cout << "MLBSTrackingFilter: Stepsize: " << m_StepSize << " mm" << std::endl; + std::cout << "MLBSTrackingFilter: Seeds per voxel: " << m_SeedsPerVoxel << std::endl; + std::cout << "MLBSTrackingFilter: Max. sampling distance: " << m_SamplingDistance << " mm" << std::endl; + std::cout << "MLBSTrackingFilter: Number of samples: " << m_NumberOfSamples << std::endl; + std::cout << "MLBSTrackingFilter: Max. tract length: " << m_MaxTractLength << " mm" << std::endl; + std::cout << "MLBSTrackingFilter: Min. tract length: " << m_MinTractLength << " mm" << std::endl; + std::cout << "MLBSTrackingFilter: Starting streamline tracking using " << this->GetNumberOfThreads() << " threads." << std::endl; +} + +template< int NumImageFeatures > +void MLBSTrackingFilter< NumImageFeatures >::PreprocessRawData() +{ + typedef itk::AnalyticalDiffusionQballReconstructionImageFilter InterpolationFilterType; + + std::cout << "MLBSTrackingFilter: Spherical signal interpolation and sampling ..." << std::endl; + typename InterpolationFilterType::Pointer filter = InterpolationFilterType::New(); + filter->SetGradientImage( m_GradientDirections, m_InputImage ); + filter->SetBValue( m_B_Value ); + filter->SetLambda(0.006); + filter->SetNormalizationMethod(InterpolationFilterType::QBAR_RAW_SIGNAL); + filter->Update(); + // FeatureImageType::Pointer itkFeatureImage = qballfilter->GetCoefficientImage(); + // featureImageVector.push_back(itkFeatureImage); + + std::cout << "MLBSTrackingFilter: Creating feature image ..." << std::endl; + vnl_vector_fixed ref; ref.fill(0); ref[0]=1; + itk::OrientationDistributionFunction< double, NumImageFeatures*2 > odf; + m_DirectionIndices.clear(); + for (unsigned int f=0; f0) // only used directions on one hemisphere + m_DirectionIndices.push_back(f); + } + + m_FeatureImage = FeatureImageType::New(); + m_FeatureImage->SetSpacing(filter->GetOutput()->GetSpacing()); + m_FeatureImage->SetOrigin(filter->GetOutput()->GetOrigin()); + m_FeatureImage->SetDirection(filter->GetOutput()->GetDirection()); + m_FeatureImage->SetLargestPossibleRegion(filter->GetOutput()->GetLargestPossibleRegion()); + m_FeatureImage->SetBufferedRegion(filter->GetOutput()->GetLargestPossibleRegion()); + m_FeatureImage->SetRequestedRegion(filter->GetOutput()->GetLargestPossibleRegion()); + m_FeatureImage->Allocate(); + + itk::ImageRegionIterator< typename InterpolationFilterType::OutputImageType > it(filter->GetOutput(), filter->GetOutput()->GetLargestPossibleRegion()); + while(!it.IsAtEnd()) + { + typename FeatureImageType::PixelType pix; + for (unsigned int f=0; fSetPixel(it.GetIndex(), pix); + ++it; + } +} + +template< int NumImageFeatures > +void MLBSTrackingFilter< NumImageFeatures >::CalculateNewPosition(itk::Point& pos, vnl_vector_fixed& dir) +{ + // vnl_matrix_fixed< double, 3, 3 > rot = m_FeatureImage->GetDirection().GetTranspose(); + // dir = rot*dir; + + dir *= m_StepSize; + pos[0] += dir[0]; + pos[1] += dir[1]; + pos[2] += dir[2]; +} + +template< int NumImageFeatures > +bool MLBSTrackingFilter< NumImageFeatures > +::IsValidPosition(itk::Point &pos) +{ + typename FeatureImageType::IndexType idx; + m_FeatureImage->TransformPhysicalPointToIndex(pos, idx); + if (!m_FeatureImage->GetLargestPossibleRegion().IsInside(idx) || m_MaskImage->GetPixel(idx)==0) + return false; + + return true; +} + +template< int NumImageFeatures > +typename MLBSTrackingFilter< NumImageFeatures >::FeatureImageType::PixelType MLBSTrackingFilter< NumImageFeatures >::GetImageValues(itk::Point itkP) +{ + itk::Index<3> idx; + itk::ContinuousIndex< double, 3> cIdx; + m_FeatureImage->TransformPhysicalPointToIndex(itkP, idx); + m_FeatureImage->TransformPhysicalPointToContinuousIndex(itkP, cIdx); + + typename FeatureImageType::PixelType pix; pix.Fill(0.0); + if ( m_FeatureImage->GetLargestPossibleRegion().IsInside(idx) ) + pix = m_FeatureImage->GetPixel(idx); + else + return pix; + + double frac_x = cIdx[0] - idx[0]; + double frac_y = cIdx[1] - idx[1]; + double frac_z = cIdx[2] - idx[2]; + if (frac_x<0) + { + idx[0] -= 1; + frac_x += 1; + } + if (frac_y<0) + { + idx[1] -= 1; + frac_y += 1; + } + if (frac_z<0) + { + idx[2] -= 1; + frac_z += 1; + } + frac_x = 1-frac_x; + frac_y = 1-frac_y; + frac_z = 1-frac_z; + + // int coordinates inside image? + if (idx[0] >= 0 && idx[0] < m_FeatureImage->GetLargestPossibleRegion().GetSize(0)-1 && + idx[1] >= 0 && idx[1] < m_FeatureImage->GetLargestPossibleRegion().GetSize(1)-1 && + idx[2] >= 0 && idx[2] < m_FeatureImage->GetLargestPossibleRegion().GetSize(2)-1) + { + vnl_vector_fixed interpWeights; + interpWeights[0] = ( frac_x)*( frac_y)*( frac_z); + interpWeights[1] = (1-frac_x)*( frac_y)*( frac_z); + interpWeights[2] = ( frac_x)*(1-frac_y)*( frac_z); + interpWeights[3] = ( frac_x)*( frac_y)*(1-frac_z); + interpWeights[4] = (1-frac_x)*(1-frac_y)*( frac_z); + interpWeights[5] = ( frac_x)*(1-frac_y)*(1-frac_z); + interpWeights[6] = (1-frac_x)*( frac_y)*(1-frac_z); + interpWeights[7] = (1-frac_x)*(1-frac_y)*(1-frac_z); + + pix = m_FeatureImage->GetPixel(idx) * interpWeights[0]; + typename FeatureImageType::IndexType tmpIdx = idx; tmpIdx[0]++; + pix += m_FeatureImage->GetPixel(tmpIdx) * interpWeights[1]; + tmpIdx = idx; tmpIdx[1]++; + pix += m_FeatureImage->GetPixel(tmpIdx) * interpWeights[2]; + tmpIdx = idx; tmpIdx[2]++; + pix += m_FeatureImage->GetPixel(tmpIdx) * interpWeights[3]; + tmpIdx = idx; tmpIdx[0]++; tmpIdx[1]++; + pix += m_FeatureImage->GetPixel(tmpIdx) * interpWeights[4]; + tmpIdx = idx; tmpIdx[1]++; tmpIdx[2]++; + pix += m_FeatureImage->GetPixel(tmpIdx) * interpWeights[5]; + tmpIdx = idx; tmpIdx[2]++; tmpIdx[0]++; + pix += m_FeatureImage->GetPixel(tmpIdx) * interpWeights[6]; + tmpIdx = idx; tmpIdx[0]++; tmpIdx[1]++; tmpIdx[2]++; + pix += m_FeatureImage->GetPixel(tmpIdx) * interpWeights[7]; + } +} + +template< int NumImageFeatures > +vnl_vector_fixed MLBSTrackingFilter< NumImageFeatures >::Classify(itk::Point& pos, int& candidates, vnl_vector_fixed& olddir, double angularThreshold, double& prob, bool avoidStop) +{ + vnl_vector_fixed direction; direction.fill(0); + + vigra::MultiArray<2, double> featureData; + if(m_UseDirection) + featureData = vigra::MultiArray<2, double>( vigra::Shape2(1,NumImageFeatures+3) ); + else + featureData = vigra::MultiArray<2, double>( vigra::Shape2(1,NumImageFeatures) ); + + typename FeatureImageType::PixelType featurePixel = GetImageValues(pos); + + // pixel values + for (unsigned int f=0; f ref; ref.fill(0); ref[0]=1; + for (unsigned int f=NumImageFeatures; f probs(vigra::Shape2(1, m_DecisionForest->class_count())); + m_DecisionForest->predictProbabilities(featureData, probs); + + double outProb = 0; + prob = 0; + candidates = 0; // directions with probability > 0 + for (int i=0; iclass_count(); i++) + { + if (probs(0,i)>0) + { + int classLabel = 0; + m_DecisionForest->ext_param_.to_classlabel(i, classLabel); + + if (classLabel d = m_ODF.GetDirection(m_DirectionIndices.at(classLabel)); + double dot = dot_product(d, olddir); + + if (olddir.magnitude()>0) + { + if (fabs(dot)>angularThreshold) + { + if (dot<0) + d *= -1; + dot = fabs(dot); + direction += probs(0,i)*dot*d; + prob += probs(0,i)*dot; + } + } + else + { + direction += probs(0,i)*d; + prob += probs(0,i); + } + } + else + outProb += probs(0,i); + } + } + + ItkDoubleImgType::IndexType idx; + m_NotWmImage->TransformPhysicalPointToIndex(pos, idx); + if (m_NotWmImage->GetLargestPossibleRegion().IsInside(idx)) + { + m_NotWmImage->SetPixel(idx, m_NotWmImage->GetPixel(idx)+outProb); + m_WmImage->SetPixel(idx, m_WmImage->GetPixel(idx)+prob); + } + if (outProb>prob && prob>0) + { + candidates = 0; + prob = 0; + direction.fill(0.0); + } + if (avoidStop && m_AvoidStopImage->GetLargestPossibleRegion().IsInside(idx) && candidates>0 && direction.magnitude()>0.001) + m_AvoidStopImage->SetPixel(idx, m_AvoidStopImage->GetPixel(idx)+0.1); + + return direction; +} + + +template< int NumImageFeatures > +double MLBSTrackingFilter< NumImageFeatures >::GetRandDouble(double min, double max) +{ + return (double)(rand()%((int)(10000*(max-min))) + 10000*min)/10000; +} + +template< int NumImageFeatures > +vnl_vector_fixed MLBSTrackingFilter< NumImageFeatures >::GetNewDirection(itk::Point &pos, vnl_vector_fixed& olddir) +{ + vnl_vector_fixed direction; direction.fill(0); + + ItkUcharImgType::IndexType idx; + m_StoppingRegions->TransformPhysicalPointToIndex(pos, idx); + if (m_StoppingRegions->GetPixel(idx)>0) + return direction; + + if (olddir.magnitude()>0) + olddir.normalize(); + + int candidates = 0; // number of directions with probability > 0 + double prob = 0; + direction = Classify(pos, candidates, olddir, m_AngularThreshold, prob); // sample neighborhood + direction *= prob; + + + itk::OrientationDistributionFunction< double, 50 > probeVecs; + + for (int i=0; i d; +// probe[0] = GetRandDouble()*m_SamplingDistance; +// probe[1] = GetRandDouble()*m_SamplingDistance; +// probe[2] = GetRandDouble()*m_SamplingDistance; + + d = probeVecs.GetDirection(i)*m_SamplingDistance; + + itk::Point sample_pos; + sample_pos[0] = pos[0] + d[0]; + sample_pos[1] = pos[1] + d[1]; + sample_pos[2] = pos[2] + d[2]; + + candidates = 0; + vnl_vector_fixed tempDir = Classify(sample_pos, candidates, olddir, m_AngularThreshold, prob); // sample neighborhood + if (candidates>0 && tempDir.magnitude()>0.001) + { + direction += tempDir*prob; + } + else if (m_AvoidStop && candidates==0 && olddir.magnitude()>0) // out of white matter + { + double dot = dot_product(d, olddir); + if (dot >= 0.0) // in front of plane defined by pos and olddir + d = -d + 2*dot*olddir; // reflect + else + d = -d; // invert + + // look a bit further into the other direction + sample_pos[0] = pos[0] + d[0]*2; + sample_pos[1] = pos[1] + d[1]*2; + sample_pos[2] = pos[2] + d[2]*2; + candidates = 0; + vnl_vector_fixed tempDir = Classify(sample_pos, candidates, olddir, m_AngularThreshold, prob, true); // sample neighborhood + + if (candidates>0 && tempDir.magnitude()>0.001) // are we back in the white matter? + { + direction += d; // go into the direction of the white matter + direction += tempDir*prob; // go into the direction of the white matter direction at this location + } + } + } + + if (direction.magnitude()>0.001) + { + direction.normalize(); + olddir[0] = direction[0]; + olddir[1] = direction[1]; + olddir[2] = direction[2]; + } + else + direction.fill(0); + + return direction; +} + +template< int NumImageFeatures > +double MLBSTrackingFilter< NumImageFeatures >::FollowStreamline(ThreadIdType threadId, itk::Point pos, vnl_vector_fixed dir, FiberType* fib, double tractLength, bool front) +{ + vnl_vector_fixed dirOld = dir; + dirOld = dir; + + for (int step=0; step< m_MaxLength/2; step++) + { + while (m_PauseTracking){} + if (m_DemoMode) + { + m_Mutex.Lock(); + m_BuildFibersReady++; + m_Tractogram.push_back(*fib); + BuildFibers(true); + m_Stop = true; + m_Mutex.Unlock(); + while (m_Stop){} + } + + // get new position + CalculateNewPosition(pos, dir); + + // is new position inside of image and mask + if (!IsValidPosition(pos) || m_AbortTracking) // if not end streamline + { + return tractLength; + } + else // if yes, add new point to streamline + { + tractLength += m_StepSize; + if (front) + fib->push_front(pos); + else + fib->push_back(pos); + + if (m_AposterioriCurvCheck) + { + int curv = CheckCurvature(fib, front); // TODO: Move into classification ??? + if (curv>0) + { + tractLength -= m_StepSize*curv; + while (curv>0) + { + if (front) + fib->pop_front(); + else + fib->pop_back(); + curv--; + } + return tractLength; + } + } + + if (tractLength>m_MaxTractLength) + return tractLength; + } + + dir = GetNewDirection(pos, dirOld); + + if (dir.magnitude()<0.0001) + return tractLength; + } + return tractLength; +} + +template< int NumImageFeatures > +int MLBSTrackingFilter::CheckCurvature(FiberType* fib, bool front) +{ + double m_Distance = 5; + if (fib->size()<3) + return 0; + + double dist = 0; + std::vector< vnl_vector_fixed< float, 3 > > vectors; + vnl_vector_fixed< float, 3 > meanV; meanV.fill(0); + double dev = 0; + + if (front) + { + int c=0; + while(distsize()-1) + { + itk::Point p1 = fib->at(c); + itk::Point p2 = fib->at(c+1); + + 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); + if (c==0) + meanV += v; + c++; + } + } + else + { + int c=fib->size()-1; + while(dist0) + { + itk::Point p1 = fib->at(c); + itk::Point p2 = fib->at(c-1); + + 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); + if (c==fib->size()-1) + meanV += v; + c--; + } + } + meanV.normalize(); + + for (int c=0; c1.0) + angle = 1.0; + if (angle<-1.0) + angle = -1.0; + dev += acos(angle)*180/M_PI; + } + if (vectors.size()>0) + dev /= vectors.size(); + + if (dev<30) + return 0; + else + return vectors.size(); +} + +template< int NumImageFeatures > +void MLBSTrackingFilter< NumImageFeatures >::ThreadedGenerateData(const InputImageRegionType ®ionForThread, ThreadIdType threadId) +{ + m_Mutex.Lock(); + m_Threads++; + m_Mutex.Unlock(); + typedef ImageRegionConstIterator< ItkUcharImgType > MaskIteratorType; + MaskIteratorType sit(m_SeedImage, regionForThread ); + MaskIteratorType mit(m_MaskImage, regionForThread ); + + sit.GoToBegin(); + mit.GoToBegin(); + itk::Point worldPos; + while( !sit.IsAtEnd() ) + { + if (sit.Value()==0 || mit.Value()==0) + { + ++sit; + ++mit; + continue; + } + + for (int s=0; s start; + unsigned int counter = 0; + + if (m_SeedsPerVoxel>1) + { + start[0] = index[0]+GetRandDouble(-0.5, 0.5); + start[1] = index[1]+GetRandDouble(-0.5, 0.5); + start[2] = index[2]+GetRandDouble(-0.5, 0.5); + } + else + { + start[0] = index[0]; + start[1] = index[1]; + start[2] = index[2]; + } + + // get staring position + m_SeedImage->TransformContinuousIndexToPhysicalPoint( start, worldPos ); + + // get starting direction + int candidates = 0; + double prob = 0; + vnl_vector_fixed dirOld; dirOld.fill(0.0); + vnl_vector_fixed dir = Classify(worldPos, candidates, dirOld, 0, prob); + if (dir.magnitude()<0.0001) + continue; + + // forward tracking + tractLength = FollowStreamline(threadId, worldPos, dir, &fib, 0, false); + fib.push_front(worldPos); + + if (m_RemoveWmEndFibers) + { + itk::Point check = fib.back(); + dirOld.fill(0.0); + vnl_vector_fixed check2 = GetNewDirection(check, dirOld); + if (check2.magnitude()>0.001) + { + MITK_INFO << "Detected WM ending. Discarding fiber."; + continue; + } + } + + // backward tracking + tractLength = FollowStreamline(threadId, worldPos, -dir, &fib, tractLength, true); + counter = fib.size(); + + if (m_RemoveWmEndFibers) + { + itk::Point check = fib.front(); + dirOld.fill(0.0); + vnl_vector_fixed check2 = GetNewDirection(check, dirOld); + if (check2.magnitude()>0.001) + { + MITK_INFO << "Detected WM ending. Discarding fiber."; + continue; + } + } + + if (tractLength +void MLBSTrackingFilter< NumImageFeatures >::BuildFibers(bool check) +{ + if (m_BuildFibersReady::New(); + vtkSmartPointer vNewLines = vtkSmartPointer::New(); + vtkSmartPointer vNewPoints = vtkSmartPointer::New(); + + for (int i=0; i container = vtkSmartPointer::New(); + FiberType fib = m_Tractogram.at(i); + for (FiberType::iterator it = fib.begin(); it!=fib.end(); it++) + { + vtkIdType id = vNewPoints->InsertNextPoint((*it).GetDataPointer()); + container->GetPointIds()->InsertNextId(id); + } + vNewLines->InsertNextCell(container); + } + if (check) + for (int i=0; iSetPoints(vNewPoints); + m_FiberPolyData->SetLines(vNewLines); + m_BuildFibersFinished = true; +} + +template< int NumImageFeatures > +void MLBSTrackingFilter< NumImageFeatures >::AfterThreadedGenerateData() +{ + MITK_INFO << "Generating polydata "; + BuildFibers(false); + MITK_INFO << "done"; +} + +} + +#endif // __itkDiffusionQballPrincipleDirectionsImageFilter_txx diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/MLTracking/itkMLBSTrackingFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/MLTracking/itkMLBSTrackingFilter.h new file mode 100644 index 0000000000..5e1a62d0e2 --- /dev/null +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/MLTracking/itkMLBSTrackingFilter.h @@ -0,0 +1,191 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY 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 __itkMLBSTrackingFilter_h_ +#define __itkMLBSTrackingFilter_h_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// classification includes +#include +#include +#include + +namespace itk{ + +/** +* \brief Performes deterministic streamline tracking on the input tensor image. */ + +template< int NumImageFeatures=100 > +class MLBSTrackingFilter : public ImageToImageFilter< VectorImage< short, 3 >, Image< double, 3 > > +{ + +public: + + typedef MLBSTrackingFilter Self; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + typedef ImageToImageFilter< VectorImage< short, 3 >, Image< double, 3 > > Superclass; + + typedef vigra::RandomForest DecisionForestType; + typedef typename Superclass::InputImageType InputImageType; + typedef typename Superclass::InputImageRegionType InputImageRegionType; + typedef Image< Vector< float, NumImageFeatures > , 3 > FeatureImageType; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + /** Runtime information support. */ + itkTypeMacro(MLBSTrackingFilter, ImageToImageFilter) + + typedef itk::Image ItkUcharImgType; + typedef itk::Image ItkDoubleImgType; + typedef itk::Image ItkFloatImgType; + typedef vtkSmartPointer< vtkPolyData > PolyDataType; + + typedef std::deque< itk::Point > FiberType; + typedef std::vector< FiberType > BundleType; + + bool m_PauseTracking; + bool m_AbortTracking; + bool m_BuildFibersFinished; + int m_BuildFibersReady; + bool m_Stop; +// void RequestFibers(){ m_Stop=true; m_BuildFibersReady=0; m_BuildFibersFinished=false; } + + itkGetMacro( FiberPolyData, PolyDataType ) ///< Output fibers + itkSetMacro( SeedImage, ItkUcharImgType::Pointer) ///< Seeds are only placed inside of this mask. + itkSetMacro( MaskImage, ItkUcharImgType::Pointer) ///< Tracking is only performed inside of this mask image. + itkSetMacro( SeedsPerVoxel, int) ///< One seed placed in the center of each voxel or multiple seeds randomly placed inside each voxel. + itkSetMacro( StepSize, double) ///< Integration step size in mm + itkSetMacro( MinTractLength, double ) ///< Shorter tracts are discarded. + itkSetMacro( MaxTractLength, double ) + itkSetMacro( AngularThreshold, double ) + itkSetMacro( UseDirection, bool ) + itkSetMacro( SamplingDistance, double ) + itkSetMacro( NumberOfSamples, int ) + itkSetMacro( StoppingRegions, ItkUcharImgType::Pointer) + itkSetMacro( B_Value, float ) + itkSetMacro( GradientDirections, mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer ) + itkSetMacro( DemoMode, bool ) + itkSetMacro( RemoveWmEndFibers, bool ) + itkSetMacro( AposterioriCurvCheck, bool ) + itkSetMacro( AvoidStop, bool ) + + void SetDecisionForest( DecisionForestType* forest ) + { + m_DecisionForest = forest; + } + + itkGetMacro( WmImage, ItkDoubleImgType::Pointer ) + itkGetMacro( NotWmImage, ItkDoubleImgType::Pointer ) + itkGetMacro( AvoidStopImage, ItkDoubleImgType::Pointer ) + + protected: + MLBSTrackingFilter(); + ~MLBSTrackingFilter() {} + + void CalculateNewPosition(itk::Point& pos, vnl_vector_fixed& dir); ///< Calculate next integration step. + double FollowStreamline(ThreadIdType threadId, itk::Point pos, vnl_vector_fixed dir, FiberType* fib, double tractLength, bool front); ///< Start streamline in one direction. + bool IsValidPosition(itk::Point& pos); ///< Are we outside of the mask image? + vnl_vector_fixed GetNewDirection(itk::Point& pos, vnl_vector_fixed& olddir); + vnl_vector_fixed Classify(itk::Point& pos, int& candidates, vnl_vector_fixed& olddir, double angularThreshold, double& prob, bool avoidStop=false); + + typename FeatureImageType::PixelType GetImageValues(itk::Point itkP); + double GetRandDouble(double min=-1, double max=1); + double RoundToNearest(double num); + + void BeforeThreadedGenerateData(); + void PreprocessRawData(); + void ThreadedGenerateData( const InputImageRegionType &outputRegionForThread, ThreadIdType threadId); + void AfterThreadedGenerateData(); + + PolyDataType m_FiberPolyData; + vtkSmartPointer m_Points; + vtkSmartPointer m_Cells; + BundleType m_Tractogram; + + double m_AngularThreshold; + double m_StepSize; + int m_MaxLength; + double m_MinTractLength; + double m_MaxTractLength; + int m_SeedsPerVoxel; + bool m_UseDirection; + double m_SamplingDistance; + int m_NumberOfSamples; + std::vector< int > m_ImageSize; + std::vector< double > m_ImageSpacing; + + SimpleFastMutexLock m_Mutex; + ItkUcharImgType::Pointer m_StoppingRegions; + ItkDoubleImgType::Pointer m_WmImage; + ItkDoubleImgType::Pointer m_NotWmImage; + ItkDoubleImgType::Pointer m_AvoidStopImage; + ItkUcharImgType::Pointer m_SeedImage; + ItkUcharImgType::Pointer m_MaskImage; + typename FeatureImageType::Pointer m_FeatureImage; + typename InputImageType::Pointer m_InputImage; + mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer m_GradientDirections; + float m_B_Value; + + bool m_AposterioriCurvCheck; + bool m_RemoveWmEndFibers; + bool m_AvoidStop; + + int m_Threads; + bool m_DemoMode; + void BuildFibers(bool check); + int CheckCurvature(FiberType* fib, bool front); + + // decision forest + DecisionForestType* m_DecisionForest; + itk::OrientationDistributionFunction< double, NumImageFeatures*2 > m_ODF; + std::vector< int > m_DirectionIndices; + + std::vector< PolyDataType > m_PolyDataContainer; + +private: + +}; + +} + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkMLBSTrackingFilter.cpp" +#endif + +#endif //__itkMLBSTrackingFilter_h_ + diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/MLTracking/mitkTrackingForestHandler.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/MLTracking/mitkTrackingForestHandler.cpp new file mode 100644 index 0000000000..aa50256bdb --- /dev/null +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/MLTracking/mitkTrackingForestHandler.cpp @@ -0,0 +1,540 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef _TrackingForestHandler_cpp +#define _TrackingForestHandler_cpp + +#include "mitkTrackingForestHandler.h" +#include +#include + +namespace mitk +{ + +template< int NumberOfSignalFeatures > +TrackingForestHandler< NumberOfSignalFeatures >::TrackingForestHandler() + : m_GrayMatterSamplesPerVoxel(50) + , m_StepSize(-1) + , m_UsePreviousDirection(true) + , m_NumTrees(30) + , m_MaxTreeDepth(50) + , m_SampleFraction(1.0) +{ + +} + +template< int NumberOfSignalFeatures > +TrackingForestHandler< NumberOfSignalFeatures >::~TrackingForestHandler() +{ + +} + +template< int NumberOfSignalFeatures > +typename TrackingForestHandler< NumberOfSignalFeatures >::InterpolatedRawImageType::PixelType TrackingForestHandler< NumberOfSignalFeatures >::GetImageValues(itk::Point itkP, typename InterpolatedRawImageType::Pointer image) +{ + itk::Index<3> idx; + itk::ContinuousIndex< double, 3> cIdx; + image->TransformPhysicalPointToIndex(itkP, idx); + image->TransformPhysicalPointToContinuousIndex(itkP, cIdx); + + typename InterpolatedRawImageType::PixelType pix; pix.Fill(0.0); + if ( image->GetLargestPossibleRegion().IsInside(idx) ) + pix = image->GetPixel(idx); + else + return pix; + + double frac_x = cIdx[0] - idx[0]; + double frac_y = cIdx[1] - idx[1]; + double frac_z = cIdx[2] - idx[2]; + if (frac_x<0) + { + idx[0] -= 1; + frac_x += 1; + } + if (frac_y<0) + { + idx[1] -= 1; + frac_y += 1; + } + if (frac_z<0) + { + idx[2] -= 1; + frac_z += 1; + } + frac_x = 1-frac_x; + frac_y = 1-frac_y; + frac_z = 1-frac_z; + + // int coordinates inside image? + if (idx[0] >= 0 && idx[0] < image->GetLargestPossibleRegion().GetSize(0)-1 && + idx[1] >= 0 && idx[1] < image->GetLargestPossibleRegion().GetSize(1)-1 && + idx[2] >= 0 && idx[2] < image->GetLargestPossibleRegion().GetSize(2)-1) + { + vnl_vector_fixed interpWeights; + interpWeights[0] = ( frac_x)*( frac_y)*( frac_z); + interpWeights[1] = (1-frac_x)*( frac_y)*( frac_z); + interpWeights[2] = ( frac_x)*(1-frac_y)*( frac_z); + interpWeights[3] = ( frac_x)*( frac_y)*(1-frac_z); + interpWeights[4] = (1-frac_x)*(1-frac_y)*( frac_z); + interpWeights[5] = ( frac_x)*(1-frac_y)*(1-frac_z); + interpWeights[6] = (1-frac_x)*( frac_y)*(1-frac_z); + interpWeights[7] = (1-frac_x)*(1-frac_y)*(1-frac_z); + + + pix = image->GetPixel(idx) * interpWeights[0]; + typename InterpolatedRawImageType::IndexType tmpIdx = idx; tmpIdx[0]++; + pix += image->GetPixel(tmpIdx) * interpWeights[1]; + tmpIdx = idx; tmpIdx[1]++; + pix += image->GetPixel(tmpIdx) * interpWeights[2]; + tmpIdx = idx; tmpIdx[2]++; + pix += image->GetPixel(tmpIdx) * interpWeights[3]; + tmpIdx = idx; tmpIdx[0]++; tmpIdx[1]++; + pix += image->GetPixel(tmpIdx) * interpWeights[4]; + tmpIdx = idx; tmpIdx[1]++; tmpIdx[2]++; + pix += image->GetPixel(tmpIdx) * interpWeights[5]; + tmpIdx = idx; tmpIdx[2]++; tmpIdx[0]++; + pix += image->GetPixel(tmpIdx) * interpWeights[6]; + tmpIdx = idx; tmpIdx[0]++; tmpIdx[1]++; tmpIdx[2]++; + pix += image->GetPixel(tmpIdx) * interpWeights[7]; + } + + return pix; +} + +template< int NumberOfSignalFeatures > +void TrackingForestHandler< NumberOfSignalFeatures >::InputDataValidForTracking() +{ + if (m_RawData.empty()) + mitkThrow() << "No diffusion-weighted images set!"; +} + +template< int NumberOfSignalFeatures > +void TrackingForestHandler< NumberOfSignalFeatures >::StartTraining() +{ + InputDataValidForTraining(); + PreprocessInputData(); + CalculateFeatures(); + TrainForest(); +} + +template< int NumberOfSignalFeatures > +void TrackingForestHandler< NumberOfSignalFeatures >::InputDataValidForTraining() +{ + if (m_RawData.empty()) + mitkThrow() << "No diffusion-weighted images set!"; + if (m_Tractograms.empty()) + mitkThrow() << "No tractograms set!"; + if (m_RawData.size()!=m_Tractograms.size()) + mitkThrow() << "Unequal number of diffusion-weighted images and tractograms detected!"; +} + +template< int NumberOfSignalFeatures > +void TrackingForestHandler< NumberOfSignalFeatures >::PreprocessInputData() +{ + typedef itk::AnalyticalDiffusionQballReconstructionImageFilter InterpolationFilterType; + + MITK_INFO << "Spherical signal interpolation and sampling ..."; + for (unsigned int i=0; iSetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(m_RawData.at(i)), mitk::DiffusionPropertyHelper::GetItkVectorImage(m_RawData.at(i)) ); + qballfilter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(m_RawData.at(i))); + qballfilter->SetLambda(0.006); + qballfilter->SetNormalizationMethod(InterpolationFilterType::QBAR_RAW_SIGNAL); + qballfilter->Update(); + // FeatureImageType::Pointer itkFeatureImage = qballfilter->GetCoefficientImage(); + // featureImageVector.push_back(itkFeatureImage); + m_InterpolatedRawImages.push_back(qballfilter->GetOutput()); + + if (i>=m_MaskImages.size()) + { + ItkUcharImgType::Pointer newMask = ItkUcharImgType::New(); + newMask->SetSpacing( m_InterpolatedRawImages.at(i)->GetSpacing() ); + newMask->SetOrigin( m_InterpolatedRawImages.at(i)->GetOrigin() ); + newMask->SetDirection( m_InterpolatedRawImages.at(i)->GetDirection() ); + newMask->SetLargestPossibleRegion( m_InterpolatedRawImages.at(i)->GetLargestPossibleRegion() ); + newMask->SetBufferedRegion( m_InterpolatedRawImages.at(i)->GetLargestPossibleRegion() ); + newMask->SetRequestedRegion( m_InterpolatedRawImages.at(i)->GetLargestPossibleRegion() ); + newMask->Allocate(); + newMask->FillBuffer(1); + m_MaskImages.push_back(newMask); + } + } + + MITK_INFO << "Resampling fibers and calculating number of samples ..."; + m_NumberOfSamples = 0; + for (unsigned int t=0; t::Pointer env = itk::TractDensityImageFilter< ItkUcharImgType >::New(); + env->SetFiberBundle(m_Tractograms.at(t)); + env->SetInputImage(mask); + env->SetBinaryOutput(true); + env->SetUseImageGeometry(true); + env->Update(); + wmmask = env->GetOutput(); + m_WhiteMatterImages.push_back(wmmask); + } + + itk::ImageRegionConstIterator it(wmmask, wmmask->GetLargestPossibleRegion()); + int OUTOFWM = 0; + while(!it.IsAtEnd()) + { + if (it.Get()==0 && mask->GetPixel(it.GetIndex())>0) + OUTOFWM++; + ++it; + } + m_NumberOfSamples += m_GrayMatterSamplesPerVoxel*OUTOFWM; + MITK_INFO << "Samples outside of WM: " << m_NumberOfSamples; + + if (m_StepSize<0) + { + typename InterpolatedRawImageType::Pointer image = m_InterpolatedRawImages.at(t); + float minSpacing = 1; + if(image->GetSpacing()[0]GetSpacing()[1] && image->GetSpacing()[0]GetSpacing()[2]) + minSpacing = image->GetSpacing()[0]; + else if (image->GetSpacing()[1] < image->GetSpacing()[2]) + minSpacing = image->GetSpacing()[1]; + else + minSpacing = image->GetSpacing()[2]; + m_StepSize = minSpacing*0.5; + } + + m_Tractograms.at(t)->ResampleSpline(m_StepSize); + m_NumberOfSamples += m_Tractograms.at(t)->GetNumberOfPoints(); + m_NumberOfSamples -= 2*m_Tractograms.at(t)->GetNumFibers(); + } + MITK_INFO << "Number of samples: " << m_NumberOfSamples; +} + +template< int NumberOfSignalFeatures > +void TrackingForestHandler< NumberOfSignalFeatures >::CalculateFeatures() +{ + vnl_vector_fixed ref; ref.fill(0); ref[0]=1; + itk::OrientationDistributionFunction< double, 2*NumberOfSignalFeatures > directions; + std::vector< int > directionIndices; + for (unsigned int f=0; f<2*NumberOfSignalFeatures; f++) + { + if (dot_product(ref, directions.GetDirection(f))>0) + directionIndices.push_back(f); + } + + int numDirectionFeatures = 0; + if (m_UsePreviousDirection) + numDirectionFeatures = 3; + + m_FeatureData.reshape( vigra::Shape2(m_NumberOfSamples, NumberOfSignalFeatures+numDirectionFeatures) ); + m_LabelData.reshape( vigra::Shape2(m_NumberOfSamples,1) ); + MITK_INFO << "Number of features: " << m_FeatureData.shape(1); + + itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandGen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New(); + m_RandGen->SetSeed(); + MITK_INFO << "Creating training data ..."; + int sampleCounter = 0; + for (unsigned int t=0; t it(wmMask, wmMask->GetLargestPossibleRegion()); + while(!it.IsAtEnd()) + { + if (it.Get()==0 && (mask.IsNull() || (mask.IsNotNull() && mask->GetPixel(it.GetIndex())>0))) + { + typename InterpolatedRawImageType::PixelType pix = image->GetPixel(it.GetIndex()); + if (m_UsePreviousDirection) + { + // null direction + for (unsigned int f=0; f probe; + probe[0] = m_RandGen->GetVariate()*2-1; + probe[1] = m_RandGen->GetVariate()*2-1; + probe[2] = m_RandGen->GetVariate()*2-1; + probe.normalize(); + if (dot_product(ref, probe)<0) + probe *= -1; + for (unsigned int f=NumberOfSignalFeatures; f idx; + idx[0] = it.GetIndex()[0]; + idx[1] = it.GetIndex()[1]; + idx[2] = it.GetIndex()[2]; + itk::Point itkP1; + image->TransformContinuousIndexToPhysicalPoint(idx, itkP1); + typename InterpolatedRawImageType::PixelType pix = GetImageValues(itkP1, image);; + for (unsigned int f=0; f idx; + idx[0] = it.GetIndex()[0] + m_RandGen->GetVariate()-0.5; + idx[1] = it.GetIndex()[1] + m_RandGen->GetVariate()-0.5; + idx[2] = it.GetIndex()[2] + m_RandGen->GetVariate()-0.5; + itk::Point itkP1; + image->TransformContinuousIndexToPhysicalPoint(idx, itkP1); + typename InterpolatedRawImageType::PixelType pix = GetImageValues(itkP1, image);; + for (unsigned int f=0; f polyData = fib->GetFiberPolyData(); + for (int i=0; iGetNumFibers(); i++) + { + vtkCell* cell = polyData->GetCell(i); + int numPoints = cell->GetNumberOfPoints(); + vtkPoints* points = cell->GetPoints(); + + vnl_vector_fixed dirOld; dirOld.fill(0.0); + + for (int j=0; jGetPoint(j); + itk::Point itkP1; + itkP1[0] = p1[0]; itkP1[1] = p1[1]; itkP1[2] = p1[2]; + + vnl_vector_fixed dir; dir.fill(0.0); + + itk::Point itkP2; + double* p2 = points->GetPoint(j+1); + itkP2[0] = p2[0]; itkP2[1] = p2[1]; itkP2[2] = p2[2]; + dir[0]=itkP2[0]-itkP1[0]; + dir[1]=itkP2[1]-itkP1[1]; + dir[2]=itkP2[2]-itkP1[2]; + + if (dir.magnitude()<0.0001) + { + MITK_INFO << "streamline error!"; + continue; + } + dir.normalize(); + if (dir[0]!=dir[0] || dir[1]!=dir[1] || dir[2]!=dir[2]) + { + MITK_INFO << "ERROR: NaN direction!"; + continue; + } + + if (j==0) + { + dirOld = dir; + continue; + } + + // get voxel values + typename InterpolatedRawImageType::PixelType pix = GetImageValues(itkP1, image); + for (unsigned int f=0; f0.0001) + { + int label = 0; + for (unsigned int f=0; fangle) + { + m_LabelData(sampleCounter,0) = f; + angle = a; + label = f; + } + } + } + + dirOld = dir; + sampleCounter++; + } + } + } +} + +template< int NumberOfSignalFeatures > +void TrackingForestHandler< NumberOfSignalFeatures >::TrainForest() +{ + MITK_INFO << "Maximum tree depths: " << m_MaxTreeDepth; + MITK_INFO << "Sample fraction per tree: " << m_SampleFraction; + MITK_INFO << "Number of trees: " << m_NumTrees; + bool random_split = false; + vigra::rf::visitors::OOB_Error oob_v; + MITK_INFO << "Create Split Function"; + // typedef ThresholdSplit, vigra::ClassificationTag> DefaultSplitType; + + m_Forest.set_options().use_stratification(vigra::RF_NONE); // How the data should be made equal + m_Forest.set_options().sample_with_replacement(true); // if sampled with replacement or not + m_Forest.set_options().samples_per_tree(m_SampleFraction); // Fraction of samples that are used to train a tree + m_Forest.set_options().tree_count(1); // Number of trees that are calculated; + m_Forest.set_options().min_split_node_size(5); // Minimum number of datapoints that must be in a node + // rf.set_options().features_per_node(10); + + m_Forest.learn(m_FeatureData, m_LabelData, vigra::rf::visitors::create_visitor(oob_v)); + + // Prepare parallel VariableImportance Calculation + int numMod = m_FeatureData.shape(1); + const int numClass = 2 + 2; + + float** varImp = new float*[numMod]; + + for(int i = 0; i < numMod; i++) + varImp[i] = new float[numClass]; + + for (int i = 0; i < numMod; ++i) + for (int j = 0; j < numClass; ++j) + varImp[i][j] = 0.0; + +#pragma omp parallel for + for (int i = 0; i < m_NumTrees - 1; ++i) + { + vigra::RandomForest lrf; + vigra::rf::visitors::OOB_Error loob_v; + + lrf.set_options().use_stratification(vigra::RF_NONE); // How the data should be made equal + lrf.set_options().sample_with_replacement(true); // if sampled with replacement or not + lrf.set_options().samples_per_tree(m_SampleFraction); // Fraction of samples that are used to train a tree + lrf.set_options().tree_count(1); // Number of trees that are calculated; + lrf.set_options().min_split_node_size(5); // Minimum number of datapoints that must be in a node + // lrf.set_options().features_per_node(10); + + vigra::rf::visitors::VariableImportanceVisitor lvariableImportance; + lrf.learn(m_FeatureData, m_LabelData, vigra::rf::visitors::create_visitor(loob_v)); + +#pragma omp critical + { + m_Forest.trees_.push_back(lrf.trees_[0]); + } + } + + m_Forest.options_.tree_count_ = m_NumTrees; + MITK_INFO << "Training finsihed"; + MITK_INFO << "The out-of-bag error is: " << oob_v.oob_breiman << std::endl; +} + +template< int NumberOfSignalFeatures > +void TrackingForestHandler< NumberOfSignalFeatures >::SaveForest(std::string forestFile) +{ + MITK_INFO << "Saving forest to " << forestFile; + vigra::rf_export_HDF5( m_Forest, forestFile, "" ); +} + +template< int NumberOfSignalFeatures > +void TrackingForestHandler< NumberOfSignalFeatures >::LoadForest(std::string forestFile) +{ + MITK_INFO << "Loading forest from " << forestFile; + vigra::rf_import_HDF5(m_Forest, forestFile); +} + +//// superclass implementations +//template< int NumberOfSignalFeatures > +//void TrackingForestHandler< NumberOfSignalFeatures >::UpdateOutputInformation() +//{ + +//} +//template< int NumberOfSignalFeatures > +//void TrackingForestHandler< NumberOfSignalFeatures >::SetRequestedRegionToLargestPossibleRegion() +//{ + +//} +//template< int NumberOfSignalFeatures > +//bool TrackingForestHandler< NumberOfSignalFeatures >::RequestedRegionIsOutsideOfTheBufferedRegion() +//{ +// return false; +//} +//template< int NumberOfSignalFeatures > +//bool TrackingForestHandler< NumberOfSignalFeatures >::VerifyRequestedRegion() +//{ +// return true; +//} +//template< int NumberOfSignalFeatures > +//void TrackingForestHandler< NumberOfSignalFeatures >::SetRequestedRegion(const itk::DataObject* ) +//{ + +//} + +} + +#endif diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/MLTracking/mitkTrackingForestHandler.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/MLTracking/mitkTrackingForestHandler.h new file mode 100644 index 0000000000..4aecb1ac41 --- /dev/null +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/MLTracking/mitkTrackingForestHandler.h @@ -0,0 +1,115 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef _TrackingForestHandler +#define _TrackingForestHandler + +#include "mitkBaseData.h" + +#include +#include +#include +#include + +// classification includes +//#include "RegressionForestClasses.hxx" +#undef DIFFERENCE +#define VIGRA_STATIC_LIB +#include +#include +#include + +#define _USE_MATH_DEFINES +#include + +namespace mitk +{ + +/** +* \brief */ + +template< int NumberOfSignalFeatures=100 > +class TrackingForestHandler +{ + +public: + + TrackingForestHandler(); + ~TrackingForestHandler(); + + typedef itk::Image ItkUcharImgType; + typedef itk::Image< itk::Vector< float, NumberOfSignalFeatures*2 > , 3 > InterpolatedRawImageType; + + void SetRawData( std::vector< Image::Pointer > images ){ m_RawData = images; } + void SetTractograms( std::vector< FiberBundle::Pointer > tractograms ) + { + m_Tractograms.clear(); + for (int i=0; iGetDeepCopy()); + } + } + void SetMaskImages( std::vector< ItkUcharImgType::Pointer > images ){ m_MaskImages = images; } + void SetWhiteMatterImages( std::vector< ItkUcharImgType::Pointer > images ){ m_WhiteMatterImages = images; } + + void StartTraining(); + void SaveForest(std::string forestFile); + void LoadForest(std::string forestFile); + + void SetNumTrees(int num){ m_NumTrees = num; } + void SetMaxTreeDepth(int depth){ m_MaxTreeDepth = depth; } + void SetUsePreviousDirection(bool use){ m_UsePreviousDirection = use; } + void SetStepSize(double step){ m_StepSize = step; } + void SetGrayMatterSamplesPerVoxel(int samples){ m_GrayMatterSamplesPerVoxel = samples; } + void SetSampleFraction(double fraction){ m_SampleFraction = fraction; } + vigra::RandomForest GetForest(){ return m_Forest; } + +protected: + + void InputDataValidForTracking(); + void InputDataValidForTraining(); + void PreprocessInputData(); + void CalculateFeatures(); + void TrainForest(); + + int m_GrayMatterSamplesPerVoxel; + double m_StepSize; + bool m_UsePreviousDirection; + int m_NumTrees; + int m_MaxTreeDepth; + double m_SampleFraction; + + std::vector< Image::Pointer > m_RawData; + std::vector< FiberBundle::Pointer > m_Tractograms; + std::vector< ItkUcharImgType::Pointer > m_MaskImages; + std::vector< ItkUcharImgType::Pointer > m_WhiteMatterImages; + std::vector< ItkUcharImgType::Pointer > m_SeedImages; + std::vector< ItkUcharImgType::Pointer > m_StopImages; + + int m_NumberOfSamples; + vigra::RandomForest m_Forest; + vigra::MultiArray<2, double> m_FeatureData; + vigra::MultiArray<2, double> m_LabelData; + std::vector< typename InterpolatedRawImageType::Pointer > m_InterpolatedRawImages; + + typename InterpolatedRawImageType::PixelType GetImageValues(itk::Point itkP, typename InterpolatedRawImageType::Pointer image); +}; + +} + +#include "mitkTrackingForestHandler.cpp" + +#endif diff --git a/Modules/DiffusionImaging/FiberTracking/CMakeLists.txt b/Modules/DiffusionImaging/FiberTracking/CMakeLists.txt index 78a0983713..53a22b6883 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/FiberBundle IODataStructures/PlanarFigureComposite Interactions SignalModels Rendering ${CMAKE_CURRENT_BINARY_DIR} + INCLUDE_DIRS Algorithms Algorithms/MLTracking 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 + PACKAGE_DEPENDS PUBLIC ITK|ITKFFT ITK|ITKDiffusionTensorImage Vigra HDF5 #WARNINGS_AS_ERRORS ) if(MODULE_IS_ENABLED) add_subdirectory(Testing) endif() diff --git a/Modules/DiffusionImaging/FiberTracking/files.cmake b/Modules/DiffusionImaging/FiberTracking/files.cmake index adc2368cf2..7a0b4dd4c8 100644 --- a/Modules/DiffusionImaging/FiberTracking/files.cmake +++ b/Modules/DiffusionImaging/FiberTracking/files.cmake @@ -1,78 +1,80 @@ set(CPP_FILES mitkFiberTrackingModuleActivator.cpp ## IO datastructures 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 -> 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 + # 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 + Algorithms/MLTracking/mitkTrackingForestHandler.h + Algorithms/MLTracking/itkMLBSTrackingFilter.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/CMakeLists.txt b/Modules/DiffusionImaging/MiniApps/CMakeLists.txt index 3325706db6..84dd09cf5b 100755 --- a/Modules/DiffusionImaging/MiniApps/CMakeLists.txt +++ b/Modules/DiffusionImaging/MiniApps/CMakeLists.txt @@ -1,115 +1,128 @@ option(BUILD_DiffusionMiniApps "Build commandline tools for diffusion" OFF) if(BUILD_DiffusionMiniApps OR MITK_BUILD_ALL_APPS) + + 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() + # needed include directories include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) # list of diffusion miniapps # if an app requires additional dependencies # they are added after a "^^" and separated by "_" set( diffusionminiapps DwiDenoising^^ ImageResampler^^ NetworkCreation^^MitkFiberTracking_MitkConnectomics NetworkStatistics^^MitkConnectomics ExportShImage^^ Fiberfox^^MitkFiberTracking MultishellMethods^^MitkFiberTracking PeaksAngularError^^MitkFiberTracking PeakExtraction^^MitkFiberTracking FiberExtraction^^MitkFiberTracking FiberProcessing^^MitkFiberTracking FiberDirectionExtraction^^MitkFiberTracking LocalDirectionalFiberPlausibility^^MitkFiberTracking StreamlineTracking^^MitkFiberTracking GibbsTracking^^MitkFiberTracking CopyGeometry^^ DiffusionIndices^^ TractometerMetrics^^MitkFiberTracking QballReconstruction^^ Registration^^ FileFormatConverter^^MitkFiberTracking TensorReconstruction^^ TensorDerivedMapsExtraction^^ DICOMLoader^^ + DFTraining^^MitkFiberTracking + DFTracking^^MitkFiberTracking ) foreach(diffusionminiapp ${diffusionminiapps}) # extract mini app name and dependencies string(REPLACE "^^" "\\;" miniapp_info ${diffusionminiapp}) set(miniapp_info_list ${miniapp_info}) list(GET miniapp_info_list 0 appname) list(GET miniapp_info_list 1 raw_dependencies) string(REPLACE "_" "\\;" dependencies "${raw_dependencies}") set(dependencies_list ${dependencies}) mitk_create_executable(${appname} DEPENDS MitkCore MitkDiffusionCore ${dependencies_list} PACKAGE_DEPENDS ITK CPP_FILES ${appname}.cpp mitkCommandLineParser.cpp ) if(EXECUTABLE_IS_ENABLED) # On Linux, create a shell script to start a relocatable application if(UNIX AND NOT APPLE) install(PROGRAMS "${MITK_SOURCE_DIR}/CMake/RunInstalledApp.sh" DESTINATION "." RENAME ${EXECUTABLE_TARGET}.sh) endif() get_target_property(_is_bundle ${EXECUTABLE_TARGET} MACOSX_BUNDLE) if(APPLE) if(_is_bundle) set(_target_locations ${EXECUTABLE_TARGET}.app) set(${_target_locations}_qt_plugins_install_dir ${EXECUTABLE_TARGET}.app/Contents/MacOS) set(_bundle_dest_dir ${EXECUTABLE_TARGET}.app/Contents/MacOS) set(_qt_plugins_for_current_bundle ${EXECUTABLE_TARGET}.app/Contents/MacOS) set(_qt_conf_install_dirs ${EXECUTABLE_TARGET}.app/Contents/Resources) install(TARGETS ${EXECUTABLE_TARGET} BUNDLE DESTINATION . ) else() if(NOT MACOSX_BUNDLE_NAMES) set(_qt_conf_install_dirs bin) set(_target_locations bin/${EXECUTABLE_TARGET}) set(${_target_locations}_qt_plugins_install_dir bin) install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION bin) else() foreach(bundle_name ${MACOSX_BUNDLE_NAMES}) list(APPEND _qt_conf_install_dirs ${bundle_name}.app/Contents/Resources) set(_current_target_location ${bundle_name}.app/Contents/MacOS/${EXECUTABLE_TARGET}) list(APPEND _target_locations ${_current_target_location}) set(${_current_target_location}_qt_plugins_install_dir ${bundle_name}.app/Contents/MacOS) message( " set(${_current_target_location}_qt_plugins_install_dir ${bundle_name}.app/Contents/MacOS) ") install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION ${bundle_name}.app/Contents/MacOS/) endforeach() endif() endif() else() set(_target_locations bin/${EXECUTABLE_TARGET}${CMAKE_EXECUTABLE_SUFFIX}) set(${_target_locations}_qt_plugins_install_dir bin) set(_qt_conf_install_dirs bin) install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION bin) endif() endif() endforeach() # This mini app does not depend on mitkDiffusionImaging at all mitk_create_executable(Dicom2Nrrd DEPENDS MitkCore CPP_FILES Dicom2Nrrd.cpp mitkCommandLineParser.cpp ) # On Linux, create a shell script to start a relocatable application if(UNIX AND NOT APPLE) install(PROGRAMS "${MITK_SOURCE_DIR}/CMake/RunInstalledApp.sh" DESTINATION "." RENAME ${EXECUTABLE_TARGET}.sh) endif() if(EXECUTABLE_IS_ENABLED) MITK_INSTALL_TARGETS(EXECUTABLES ${EXECUTABLE_TARGET}) endif() endif() diff --git a/Modules/DiffusionImaging/MiniApps/DFTracking.cpp b/Modules/DiffusionImaging/MiniApps/DFTracking.cpp new file mode 100755 index 0000000000..93ab11c30f --- /dev/null +++ b/Modules/DiffusionImaging/MiniApps/DFTracking.cpp @@ -0,0 +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 "mitkCommandLineParser.h" +#include +#include +#include +//#include +#include +#include +#include +#include + +#include +#include +//#include +#include +#include +#include +#include + +#define _USE_MATH_DEFINES +#include + +const int numOdfSamples = 200; +typedef itk::Image< itk::Vector< float, numOdfSamples > , 3 > SampledShImageType; + +int main(int argc, char* argv[]) +{ + mitkCommandLineParser parser; + + parser.setTitle("Machine Learning Based Streamline Tractography"); + parser.setCategory("Fiber Tracking and Processing Methods"); + parser.setDescription(""); + parser.setContributor("MBI"); + + parser.setArgumentPrefix("--", "-"); + parser.addArgument("image", "i", mitkCommandLineParser::String, "DWIs:", "input diffusion-weighted image", us::Any(), false); + parser.addArgument("forest", "f", mitkCommandLineParser::String, "Forest:", "input forest", us::Any(), false); + parser.addArgument("out", "o", mitkCommandLineParser::OutputDirectory, "Output:", "output fiberbundle", us::Any(), false); + + parser.addArgument("stop", "st", mitkCommandLineParser::String, "Stop image:", "stop image", us::Any()); + parser.addArgument("mask", "m", mitkCommandLineParser::String, "Mask image:", "mask image", us::Any()); + parser.addArgument("seed", "s", mitkCommandLineParser::String, "Seed image:", "seed image", us::Any()); + + parser.addArgument("athres", "a", mitkCommandLineParser::Float, "Angular threshold:", "angular threshold (in radians)", us::Any()); + parser.addArgument("stepsize", "se", mitkCommandLineParser::Float, "Stepsize:", "stepsize", us::Any()); + parser.addArgument("samples", "ns", mitkCommandLineParser::Int, "Samples:", "samples", us::Any()); + parser.addArgument("samplingdist", "sd", mitkCommandLineParser::Float, "Sampling distance:", "sampling distance (in voxels)", us::Any()); + parser.addArgument("seeds", "nse", mitkCommandLineParser::Int, "Seeds per voxel:", "seeds per voxel", us::Any()); + + parser.addArgument("usedirection", "ud", mitkCommandLineParser::Bool, "Use previous direction:", "use previous direction as feature", us::Any()); + parser.addArgument("verbose", "v", mitkCommandLineParser::Bool, "Verbose:", "output additional images", us::Any()); + + map parsedArgs = parser.parseArguments(argc, argv); + if (parsedArgs.size()==0) + return EXIT_FAILURE; + + string imageFile = us::any_cast(parsedArgs["image"]); + string forestFile = us::any_cast(parsedArgs["forest"]); + string outFile = us::any_cast(parsedArgs["out"]); + + string maskFile = ""; + if (parsedArgs.count("mask")) + maskFile = us::any_cast(parsedArgs["mask"]); + + string seedFile = ""; + if (parsedArgs.count("seed")) + seedFile = us::any_cast(parsedArgs["seed"]); + + string stopFile = ""; + if (parsedArgs.count("stop")) + stopFile = us::any_cast(parsedArgs["stop"]); + + float stepsize = -1; + if (parsedArgs.count("stepsize")) + stepsize = us::any_cast(parsedArgs["stepsize"]); + + float athres = 0.7; + if (parsedArgs.count("athres")) + athres = us::any_cast(parsedArgs["athres"]); + + float samplingdist = 0.25; + if (parsedArgs.count("samplingdist")) + samplingdist = us::any_cast(parsedArgs["samplingdist"]); + + bool useDirection = false; + if (parsedArgs.count("usedirection")) + useDirection = true; + + bool verbose = false; + if (parsedArgs.count("verbose")) + verbose = true; + + int samples = 10; + if (parsedArgs.count("samples")) + samples = us::any_cast(parsedArgs["samples"]); + + int seeds = 1; + if (parsedArgs.count("seeds")) + seeds = us::any_cast(parsedArgs["seeds"]); + + typedef itk::Image ItkUcharImgType; + + MITK_INFO << "loading diffusion-weighted image"; + mitk::Image::Pointer dwi = dynamic_cast(mitk::IOUtil::LoadImage(imageFile).GetPointer()); + + ItkUcharImgType::Pointer mask; + if (!maskFile.empty()) + { + MITK_INFO << "loading mask image"; + mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::LoadImage(maskFile).GetPointer()); + mask = ItkUcharImgType::New(); + mitk::CastToItkImage(img, mask); + } + + ItkUcharImgType::Pointer seed; + if (!seedFile.empty()) + { + MITK_INFO << "loading seed image"; + mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::LoadImage(seedFile).GetPointer()); + seed = ItkUcharImgType::New(); + mitk::CastToItkImage(img, seed); + } + + ItkUcharImgType::Pointer stop; + if (!stopFile.empty()) + { + MITK_INFO << "loading stop image"; + mitk::Image::Pointer img = dynamic_cast(mitk::IOUtil::LoadImage(stopFile).GetPointer()); + stop = ItkUcharImgType::New(); + mitk::CastToItkImage(img, stop); + } + + MITK_INFO << "loading forest"; + vigra::RandomForest rf; + vigra::rf_import_HDF5(rf, forestFile); + + typedef itk::MLBSTrackingFilter<100> TrackerType; + TrackerType::Pointer tracker = TrackerType::New(); + tracker->SetInput(0, mitk::DiffusionPropertyHelper::GetItkVectorImage(dwi)); + tracker->SetGradientDirections( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi) ); + tracker->SetB_Value( mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi) ); + tracker->SetMaskImage(mask); + tracker->SetSeedImage(seed); + tracker->SetStoppingRegions(stop); + tracker->SetSeedsPerVoxel(seeds); + tracker->SetUseDirection(useDirection); + tracker->SetStepSize(stepsize); + tracker->SetAngularThreshold(athres); + tracker->SetDecisionForest(&rf); + tracker->SetSamplingDistance(samplingdist); + tracker->SetNumberOfSamples(samples); + //tracker->SetAvoidStop(false); + tracker->SetAposterioriCurvCheck(false); + tracker->SetRemoveWmEndFibers(false); + tracker->Update(); + vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData(); + mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly); + + mitk::IOUtil::SaveBaseData(outFib, outFile); + + if (verbose) + { + MITK_INFO << "Writing images..."; + string outName = itksys::SystemTools::GetFilenamePath(outFile)+"/"+itksys::SystemTools::GetFilenameWithoutLastExtension(outFile); + itk::ImageFileWriter< TrackerType::ItkDoubleImgType >::Pointer writer = itk::ImageFileWriter< TrackerType::ItkDoubleImgType >::New(); + writer->SetFileName(outName+"_WhiteMatter.nrrd"); + writer->SetInput(tracker->GetWmImage()); + writer->Update(); + + writer->SetFileName(outName+"_NotWhiteMatter.nrrd"); + writer->SetInput(tracker->GetNotWmImage()); + writer->Update(); + + writer->SetFileName(outName+"_AvoidStop.nrrd"); + writer->SetInput(tracker->GetAvoidStopImage()); + writer->Update(); + } + + return EXIT_SUCCESS; +} diff --git a/Modules/DiffusionImaging/MiniApps/DFTraining.cpp b/Modules/DiffusionImaging/MiniApps/DFTraining.cpp new file mode 100755 index 0000000000..d4c2bc3d40 --- /dev/null +++ b/Modules/DiffusionImaging/MiniApps/DFTraining.cpp @@ -0,0 +1,529 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY 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" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define _USE_MATH_DEFINES +#include + +const int numOdfSamples = 200; // ODF is sampled in 200 directions but actuyll only 100 are used (symmetric) +typedef itk::Image< itk::Vector< float, numOdfSamples > , 3 > SampledShImageType; + +void TrainForest( vigra::RandomForest &rf, vigra::MultiArray<2, double> &labelData, vigra::MultiArray<2, double> &featureData, int numTrees, int max_tree_depth, double sample_fraction ) +{ + MITK_INFO << "Maximum tree depths: " << max_tree_depth; + MITK_INFO << "Sample fraction per tree: " << sample_fraction; + MITK_INFO << "Number of trees: " << numTrees; + vigra::rf::visitors::OOB_Error oob_v; + +// rf.set_options().use_stratification(vigra::RF_NONE); // How the data should be made equal +// rf.set_options().sample_with_replacement(true); // if sampled with replacement or not +// rf.set_options().samples_per_tree(sample_fraction); // Fraction of samples that are used to train a tree +// rf.set_options().tree_count(1); // Number of trees that are calculated; +// rf.set_options().min_split_node_size(5); // Minimum number of datapoints that must be in a node +// rf.ext_param_.max_tree_depth = max_tree_depth; +// // rf.set_options().features_per_node(10); +// rf.learn(featureData, labelData, vigra::rf::visitors::create_visitor(oob_v)); + + std::vector< vigra::RandomForest > trees; + int count = 0; +#pragma omp parallel for + for (int i = 0; i < numTrees; ++i) + { + vigra::RandomForest lrf; + vigra::rf::visitors::OOB_Error loob_v; + + lrf.set_options().use_stratification(vigra::RF_NONE); // How the data should be made equal + lrf.set_options().sample_with_replacement(true); // if sampled with replacement or not + lrf.set_options().samples_per_tree(sample_fraction); // Fraction of samples that are used to train a tree + lrf.set_options().tree_count(1); // Number of trees that are calculated; + lrf.set_options().min_split_node_size(5); // Minimum number of datapoints that must be in a node + lrf.ext_param_.max_tree_depth = max_tree_depth; + // lrf.set_options().features_per_node(10); + + lrf.learn(featureData, labelData);//, vigra::rf::visitors::create_visitor(loob_v)); +#pragma omp critical + { + count++; + MITK_INFO << "Tree " << count << " finished training."; + trees.push_back(lrf); + //rf.trees_.push_back(lrf.trees_[0]); + } + } + + for (int i = 1; i < numTrees; ++i) + trees.at(0).trees_.push_back(trees.at(i).trees_[0]); + + rf = trees.at(0); + rf.options_.tree_count_ = numTrees; + MITK_INFO << "Training finsihed"; + //MITK_INFO << "The out-of-bag error is: " << oob_v.oob_breiman << std::endl; +} + +SampledShImageType::PixelType GetImageValues(itk::Point itkP, SampledShImageType::Pointer image) +{ + itk::Index<3> idx; + itk::ContinuousIndex< double, 3> cIdx; + image->TransformPhysicalPointToIndex(itkP, idx); + image->TransformPhysicalPointToContinuousIndex(itkP, cIdx); + + SampledShImageType::PixelType pix; pix.Fill(0.0); + if ( image->GetLargestPossibleRegion().IsInside(idx) ) + pix = image->GetPixel(idx); + else + return pix; + + double frac_x = cIdx[0] - idx[0]; + double frac_y = cIdx[1] - idx[1]; + double frac_z = cIdx[2] - idx[2]; + if (frac_x<0) + { + idx[0] -= 1; + frac_x += 1; + } + if (frac_y<0) + { + idx[1] -= 1; + frac_y += 1; + } + if (frac_z<0) + { + idx[2] -= 1; + frac_z += 1; + } + frac_x = 1-frac_x; + frac_y = 1-frac_y; + frac_z = 1-frac_z; + + // int coordinates inside image? + if (idx[0] >= 0 && idx[0] < image->GetLargestPossibleRegion().GetSize(0)-1 && + idx[1] >= 0 && idx[1] < image->GetLargestPossibleRegion().GetSize(1)-1 && + idx[2] >= 0 && idx[2] < image->GetLargestPossibleRegion().GetSize(2)-1) + { + vnl_vector_fixed interpWeights; + interpWeights[0] = ( frac_x)*( frac_y)*( frac_z); + interpWeights[1] = (1-frac_x)*( frac_y)*( frac_z); + interpWeights[2] = ( frac_x)*(1-frac_y)*( frac_z); + interpWeights[3] = ( frac_x)*( frac_y)*(1-frac_z); + interpWeights[4] = (1-frac_x)*(1-frac_y)*( frac_z); + interpWeights[5] = ( frac_x)*(1-frac_y)*(1-frac_z); + interpWeights[6] = (1-frac_x)*( frac_y)*(1-frac_z); + interpWeights[7] = (1-frac_x)*(1-frac_y)*(1-frac_z); + + + pix = image->GetPixel(idx) * interpWeights[0]; + SampledShImageType::IndexType tmpIdx = idx; tmpIdx[0]++; + pix += image->GetPixel(tmpIdx) * interpWeights[1]; + tmpIdx = idx; tmpIdx[1]++; + pix += image->GetPixel(tmpIdx) * interpWeights[2]; + tmpIdx = idx; tmpIdx[2]++; + pix += image->GetPixel(tmpIdx) * interpWeights[3]; + tmpIdx = idx; tmpIdx[0]++; tmpIdx[1]++; + pix += image->GetPixel(tmpIdx) * interpWeights[4]; + tmpIdx = idx; tmpIdx[1]++; tmpIdx[2]++; + pix += image->GetPixel(tmpIdx) * interpWeights[5]; + tmpIdx = idx; tmpIdx[2]++; tmpIdx[0]++; + pix += image->GetPixel(tmpIdx) * interpWeights[6]; + tmpIdx = idx; tmpIdx[0]++; tmpIdx[1]++; tmpIdx[2]++; + pix += image->GetPixel(tmpIdx) * interpWeights[7]; + } + + return pix; +} + +int main(int argc, char* argv[]) +{ + MITK_INFO << "DFTraining"; + mitkCommandLineParser parser; + + parser.setTitle("Machine Learning Based Streamline Tractography"); + parser.setCategory("Fiber Tracking and Processing Methods"); + parser.setDescription(""); + parser.setContributor("MBI"); + + parser.setArgumentPrefix("--", "-"); + parser.addArgument("images", "i", mitkCommandLineParser::StringList, "DWIs:", "input diffusion-weighted images", us::Any(), false); + parser.addArgument("wmmasks", "w", mitkCommandLineParser::StringList, "WM-Masks:", "white matter mask images", us::Any(), false); + parser.addArgument("tractograms", "t", mitkCommandLineParser::StringList, "Tractograms:", "input tractograms (.fib, vtk ascii file format)", us::Any(), false); + parser.addArgument("masks", "m", mitkCommandLineParser::StringList, "Masks:", "mask images", us::Any()); + parser.addArgument("forest", "f", mitkCommandLineParser::OutputFile, "Forest:", "output forest", us::Any(), false); + + parser.addArgument("stepsize", "s", mitkCommandLineParser::Float, "Stepsize:", "stepsize", us::Any()); + parser.addArgument("gmsamples", "g", mitkCommandLineParser::Int, "Number of gray matter samples per voxel:", "Number of gray matter samples per voxel", us::Any()); + parser.addArgument("numtrees", "n", mitkCommandLineParser::Int, "Number of trees:", "number of trees", us::Any()); + parser.addArgument("max_tree_depth", "d", mitkCommandLineParser::Int, "Max. tree depth:", "maximum tree depth", us::Any()); + parser.addArgument("sample_fraction", "sf", mitkCommandLineParser::Float, "Sample fraction:", "fraction of samples used per tree", us::Any()); + parser.addArgument("usedirection", "ud", mitkCommandLineParser::Bool, "bla:", "bla", us::Any()); + + map parsedArgs = parser.parseArguments(argc, argv); + if (parsedArgs.size()==0) + return EXIT_FAILURE; + + mitkCommandLineParser::StringContainerType imageFiles = us::any_cast(parsedArgs["images"]); + mitkCommandLineParser::StringContainerType wmMaskFiles = us::any_cast(parsedArgs["wmmasks"]); + + mitkCommandLineParser::StringContainerType maskFiles; + if (parsedArgs.count("masks")) + maskFiles = us::any_cast(parsedArgs["masks"]); + + string forestFile = us::any_cast(parsedArgs["forest"]); + + mitkCommandLineParser::StringContainerType tractogramFiles; + if (parsedArgs.count("tractograms")) + tractogramFiles = us::any_cast(parsedArgs["tractograms"]); + + int numTrees = 30; + if (parsedArgs.count("numtrees")) + numTrees = us::any_cast(parsedArgs["numtrees"]); + + int gmsamples = 50; + if (parsedArgs.count("gmsamples")) + gmsamples = us::any_cast(parsedArgs["gmsamples"]); + + float stepsize = -1; + if (parsedArgs.count("stepsize")) + stepsize = us::any_cast(parsedArgs["stepsize"]); + + int max_tree_depth = 50; + if (parsedArgs.count("max_tree_depth")) + max_tree_depth = us::any_cast(parsedArgs["max_tree_depth"]); + + double sample_fraction = 1.0; + if (parsedArgs.count("sample_fraction")) + sample_fraction = us::any_cast(parsedArgs["sample_fraction"]); + + // load DWI images + if (imageFiles.size() QballFilterType; + + MITK_INFO << "loading diffusion-weighted images and reconstructing feature images"; + std::vector< SampledShImageType::Pointer > sampledShImages; + for (unsigned int i=0; i(mitk::IOUtil::LoadImage(imageFiles.at(i)).GetPointer()); + + QballFilterType::Pointer qballfilter = QballFilterType::New(); + qballfilter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), mitk::DiffusionPropertyHelper::GetItkVectorImage(dwi) ); + qballfilter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); + qballfilter->SetLambda(0.006); + qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL); + qballfilter->Update(); + // FeatureImageType::Pointer itkFeatureImage = qballfilter->GetCoefficientImage(); + // featureImageVector.push_back(itkFeatureImage); + sampledShImages.push_back(qballfilter->GetOutput()); + } + + + typedef itk::Image ItkUcharImgType; + std::vector< ItkUcharImgType::Pointer > maskImageVector; + std::vector< ItkUcharImgType::Pointer > wmMaskImageVector; + + MITK_INFO << "loading tractograms"; + int numSamples = 0; + std::vector< mitk::FiberBundle::Pointer > tractograms; + for (unsigned int t=0; t(mitk::IOUtil::LoadImage(maskFiles.at(t)).GetPointer()); + mask = ItkUcharImgType::New(); + mitk::CastToItkImage(img, mask); + maskImageVector.push_back(mask); + } + mitk::Image::Pointer img2 = dynamic_cast(mitk::IOUtil::LoadImage(wmMaskFiles.at(t)).GetPointer()); + ItkUcharImgType::Pointer wmmask = ItkUcharImgType::New(); + mitk::CastToItkImage(img2, wmmask); + wmMaskImageVector.push_back(wmmask); + + itk::ImageRegionConstIterator it(wmmask, wmmask->GetLargestPossibleRegion()); + int OUTOFWM = 0; // count voxels outside of the white matter mask + while(!it.IsAtEnd()) + { + if (it.Get()==0) + if (mask.IsNull() || (mask.IsNotNull() && mask->GetPixel(it.GetIndex())>0)) + OUTOFWM++; + ++it; + } + numSamples += gmsamples*OUTOFWM; // for each of the non-white matter voxels we add a certain number of sampling points. these sampling points are used to tell the classifier where to recognize non-WM tissue + + MITK_INFO << "Samples outside of WM: " << numSamples << " (" << gmsamples << " per non-WM voxel)"; + + // load and resample training tractograms + mitk::FiberBundle::Pointer fib = dynamic_cast(mitk::IOUtil::Load(tractogramFiles.at(t)).at(0).GetPointer()); + if (stepsize<0) + { + SampledShImageType::Pointer image = sampledShImages.at(t); + float minSpacing = 1; + if(image->GetSpacing()[0]GetSpacing()[1] && image->GetSpacing()[0]GetSpacing()[2]) + minSpacing = image->GetSpacing()[0]; + else if (image->GetSpacing()[1] < image->GetSpacing()[2]) + minSpacing = image->GetSpacing()[1]; + else + minSpacing = image->GetSpacing()[2]; + stepsize = minSpacing*0.5; + } + fib->ResampleSpline(stepsize); + tractograms.push_back(fib); + numSamples += fib->GetNumberOfPoints(); // each point of the fiber gives us a training direction + numSamples -= 2*fib->GetNumFibers(); // we don't use the first and last point because there we do not have a previous direction, which is needed as feature + } + MITK_INFO << "Number of samples: " << numSamples; + + // get ODF directions and number of features + vnl_vector_fixed ref; ref.fill(0); ref[0]=1; + itk::OrientationDistributionFunction< double, numOdfSamples > odf; + std::vector< int > directionIndices; + for (unsigned int f=0; f0) // we only use directions on one hemisphere (symmetric) + directionIndices.push_back(f); // remember indices that are on the desired hemisphere + } + const int numSignalFeatures = numOdfSamples/2; + int numDirectionFeatures = 0; + if (useDirection) + numDirectionFeatures = 3; + + vigra::MultiArray<2, double> featureData( vigra::Shape2(numSamples,numSignalFeatures+numDirectionFeatures) ); + MITK_INFO << "Number of features: " << featureData.shape(1); + vigra::MultiArray<2, double> labelData( vigra::Shape2(numSamples,1) ); + + itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandGen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New(); + m_RandGen->SetSeed(); + MITK_INFO << "Creating training data from tractograms and feature images"; + int sampleCounter = 0; + for (unsigned int t=0; t it(wmMask, wmMask->GetLargestPossibleRegion()); + while(!it.IsAtEnd()) + { + if (it.Get()==0 && (mask.IsNull() || (mask.IsNotNull() && mask->GetPixel(it.GetIndex())>0))) + { + SampledShImageType::PixelType pix = image->GetPixel(it.GetIndex()); + if (useDirection) + { + // null direction + for (unsigned int f=0; f probe; + probe[0] = m_RandGen->GetVariate()*2-1; + probe[1] = m_RandGen->GetVariate()*2-1; + probe[2] = m_RandGen->GetVariate()*2-1; + probe.normalize(); + if (dot_product(ref, probe)<0) + probe *= -1; + for (unsigned int f=numSignalFeatures; f idx; + idx[0] = it.GetIndex()[0]; + idx[1] = it.GetIndex()[1]; + idx[2] = it.GetIndex()[2]; + itk::Point itkP1; + image->TransformContinuousIndexToPhysicalPoint(idx, itkP1); + SampledShImageType::PixelType pix = GetImageValues(itkP1, image);; + for (unsigned int f=0; f idx; + idx[0] = it.GetIndex()[0] + m_RandGen->GetVariate()-0.5; + idx[1] = it.GetIndex()[1] + m_RandGen->GetVariate()-0.5; + idx[2] = it.GetIndex()[2] + m_RandGen->GetVariate()-0.5; + itk::Point itkP1; + image->TransformContinuousIndexToPhysicalPoint(idx, itkP1); + SampledShImageType::PixelType pix = GetImageValues(itkP1, image);; + for (unsigned int f=0; f polyData = fib->GetFiberPolyData(); + for (int i=0; iGetNumFibers(); i++) + { + vtkCell* cell = polyData->GetCell(i); + int numPoints = cell->GetNumberOfPoints(); + vtkPoints* points = cell->GetPoints(); + + vnl_vector_fixed dirOld; dirOld.fill(0.0); + + for (int j=0; jGetPoint(j); + itk::Point itkP1; + itkP1[0] = p1[0]; itkP1[1] = p1[1]; itkP1[2] = p1[2]; + + vnl_vector_fixed dir; dir.fill(0.0); + + itk::Point itkP2; + double* p2 = points->GetPoint(j+1); + itkP2[0] = p2[0]; itkP2[1] = p2[1]; itkP2[2] = p2[2]; + dir[0]=itkP2[0]-itkP1[0]; + dir[1]=itkP2[1]-itkP1[1]; + dir[2]=itkP2[2]-itkP1[2]; + + if (dir.magnitude()<0.0001) + { + MITK_INFO << "streamline error!"; + continue; + } + dir.normalize(); + if (dir[0]!=dir[0] || dir[1]!=dir[1] || dir[2]!=dir[2]) + { + MITK_INFO << "ERROR: NaN direction!"; + continue; + } + + if (j==0) + { + dirOld = dir; + continue; + } + + // get voxel values + SampledShImageType::PixelType pix = GetImageValues(itkP1, image); + for (unsigned int f=0; f0.0001) + { + int label = 0; + for (unsigned int f=0; fangle) + { + labelData(sampleCounter,0) = f; + angle = a; + label = f; + } + } + } + + dirOld = dir; + sampleCounter++; + } + } + } + + MITK_INFO << "Training forest"; + vigra::RandomForest rf; + TrainForest( rf, labelData, featureData, numTrees, max_tree_depth, sample_fraction ); + MITK_INFO << "Writing forest"; + vigra::rf_export_HDF5( rf, forestFile, "" ); + MITK_INFO << "Finished training"; + + return EXIT_SUCCESS; +} diff --git a/Modules/DiffusionImaging/MiniApps/ExportShImage.cpp b/Modules/DiffusionImaging/MiniApps/ExportShImage.cpp index 242ad2fcb8..17af3b197c 100755 --- a/Modules/DiffusionImaging/MiniApps/ExportShImage.cpp +++ b/Modules/DiffusionImaging/MiniApps/ExportShImage.cpp @@ -1,135 +1,140 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY 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" #include #include #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(); + mitk::Image::Pointer image = mitk::GrabItkImageMemory(outImage.GetPointer()); + mitk::IOUtil::Save(image, outFile ); + +// 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/TractometerMetrics.cpp b/Modules/DiffusionImaging/MiniApps/TractometerMetrics.cpp index d37e7c3980..38795b6bf5 100755 --- a/Modules/DiffusionImaging/MiniApps/TractometerMetrics.cpp +++ b/Modules/DiffusionImaging/MiniApps/TractometerMetrics.cpp @@ -1,414 +1,413 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY 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 #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::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::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::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::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/IGT/IO/mitkNavigationToolReader.cpp b/Modules/IGT/IO/mitkNavigationToolReader.cpp index cf30e6a5de..d7592d730b 100644 --- a/Modules/IGT/IO/mitkNavigationToolReader.cpp +++ b/Modules/IGT/IO/mitkNavigationToolReader.cpp @@ -1,220 +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. ===================================================================*/ //Poco headers #include #include //mitk headers #include "mitkNavigationToolReader.h" #include "mitkTrackingTypes.h" #include #include mitk::NavigationToolReader::NavigationToolReader() { - //TODO: maybe replace program path by a valid temp directory if there is one. See bug 17310 for the current problems. - m_ToolfilePath = mitk::IOUtil::GetProgramPath() + Poco::Path::separator() + "IGT_Toolfiles" + Poco::Path::separator(); + m_ToolfilePath = mitk::IOUtil::GetTempPath() + Poco::Path::separator() + "IGT_Toolfiles" + Poco::Path::separator(); } mitk::NavigationToolReader::~NavigationToolReader() { } mitk::NavigationTool::Pointer mitk::NavigationToolReader::DoRead(std::string filename) { //decompress all files into a temporary directory std::ifstream file( filename.c_str(), std::ios::binary ); if (!file.good()) { m_ErrorMessage = "Cannot open '" + filename + "' for reading"; return NULL; } std::string tempDirectory = m_ToolfilePath + GetFileWithoutPath(filename); Poco::Zip::Decompress unzipper( file, Poco::Path( tempDirectory ) ); unzipper.decompressAllFiles(); //use SceneSerialization to load the DataStorage mitk::SceneIO::Pointer mySceneIO = mitk::SceneIO::New(); mitk::DataStorage::Pointer loadedStorage = mySceneIO->LoadScene(tempDirectory + Poco::Path::separator() + GetFileWithoutPath(filename) + ".storage"); if (loadedStorage->GetAll()->size()==0 || loadedStorage.IsNull()) { m_ErrorMessage = "Invalid file: cannot parse tool data."; return NULL; } //convert the DataStorage back to a NavigationTool-Object mitk::DataNode::Pointer myNode = loadedStorage->GetAll()->ElementAt(0); mitk::NavigationTool::Pointer returnValue = ConvertDataNodeToNavigationTool(myNode, tempDirectory); //delete the data-storage file which is not needed any more. The toolfile must be left in the temporary directory becauses it is linked in the datatreenode of the tool std::remove((std::string(tempDirectory + Poco::Path::separator() + GetFileWithoutPath(filename) + ".storage")).c_str()); return returnValue; } mitk::NavigationTool::Pointer mitk::NavigationToolReader::ConvertDataNodeToNavigationTool(mitk::DataNode::Pointer node, std::string toolPath) { mitk::NavigationTool::Pointer returnValue = mitk::NavigationTool::New(); //DateTreeNode with Name and Surface mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetName(node->GetName()); newNode->SetData(node->GetData()); returnValue->SetDataNode(newNode); //Identifier std::string identifier; node->GetStringProperty("identifier",identifier); returnValue->SetIdentifier(identifier); //Serial Number std::string serial; node->GetStringProperty("serial number",serial); returnValue->SetSerialNumber(serial); //Tracking Device int device_type; node->GetIntProperty("tracking device type",device_type); returnValue->SetTrackingDeviceType(static_cast(device_type)); //Tool Type int type; node->GetIntProperty("tracking tool type",type); returnValue->SetType(static_cast(type)); //Calibration File Name std::string calibration_filename; node->GetStringProperty("toolfileName",calibration_filename); if (calibration_filename=="none") { returnValue->SetCalibrationFile("none"); } else { std::string calibration_filename_with_path = toolPath + Poco::Path::separator() + calibration_filename; returnValue->SetCalibrationFile(calibration_filename_with_path); } //Tool Landmarks mitk::PointSet::Pointer ToolRegLandmarks = mitk::PointSet::New(); mitk::PointSet::Pointer ToolCalLandmarks = mitk::PointSet::New(); std::string RegLandmarksString; std::string CalLandmarksString; node->GetStringProperty("ToolRegistrationLandmarks",RegLandmarksString); node->GetStringProperty("ToolCalibrationLandmarks",CalLandmarksString); ToolRegLandmarks = ConvertStringToPointSet(RegLandmarksString); ToolCalLandmarks = ConvertStringToPointSet(CalLandmarksString); returnValue->SetToolRegistrationLandmarks(ToolRegLandmarks); returnValue->SetToolCalibrationLandmarks(ToolCalLandmarks); //Tool Tip std::string toolTipPositionString; std::string toolTipOrientationString; bool positionSet = node->GetStringProperty("ToolTipPosition",toolTipPositionString); bool orientationSet = node->GetStringProperty("ToolTipOrientation",toolTipOrientationString); if(positionSet && orientationSet) //only define tooltip if it is set { returnValue->SetToolTipPosition(ConvertStringToPoint(toolTipPositionString)); returnValue->SetToolTipOrientation(ConvertStringToQuaternion(toolTipOrientationString)); } else if(positionSet != orientationSet) { MITK_WARN << "Tooltip definition incomplete: position and orientation have to be set! Skipping tooltip definition."; } return returnValue; } std::string mitk::NavigationToolReader::GetFileWithoutPath(std::string FileWithPath) { Poco::Path myFile(FileWithPath.c_str()); return myFile.getFileName(); } mitk::PointSet::Pointer mitk::NavigationToolReader::ConvertStringToPointSet(std::string string) { mitk::PointSet::Pointer returnValue = mitk::PointSet::New(); std::string pointSeperator = "|"; std::string valueSeperator = ";"; std::vector points; split(string,pointSeperator,points); for(unsigned int i=0; i values; split(points.at(i),valueSeperator,values); if (values.size() == 4) { double index = atof(values.at(0).c_str()); mitk::Point3D point; point[0] = atof(values.at(1).c_str()); point[1] = atof(values.at(2).c_str()); point[2] = atof(values.at(3).c_str()); returnValue->SetPoint(index,point); } } return returnValue; } mitk::Point3D mitk::NavigationToolReader::ConvertStringToPoint(std::string string) { std::string valueSeperator = ";"; std::vector values; split(string,valueSeperator,values); mitk::Point3D point; if (values.size() == 3) { point[0] = atof(values.at(0).c_str()); point[1] = atof(values.at(1).c_str()); point[2] = atof(values.at(2).c_str()); } return point; } mitk::Quaternion mitk::NavigationToolReader::ConvertStringToQuaternion(std::string string) { std::string valueSeperator = ";"; std::vector values; split(string,valueSeperator,values); mitk::Quaternion quat = mitk::Quaternion(0,0,0,1); if (values.size() == 4) { quat = mitk::Quaternion(atof(values.at(0).c_str()), atof(values.at(1).c_str()), atof(values.at(2).c_str()), atof(values.at(3).c_str())); } return quat; } void mitk::NavigationToolReader::split(std::string& text, std::string& separators, std::vector& words) { int n = text.length(); int start, stop; start = text.find_first_not_of(separators); while ((start >= 0) && (start < n)) { stop = text.find_first_of(separators, start); if ((stop < 0) || (stop > n)) stop = n; words.push_back(text.substr(start, stop - start)); start = text.find_first_not_of(separators, stop+1); } } diff --git a/Modules/IGT/Testing/files.cmake b/Modules/IGT/Testing/files.cmake index cc77978970..ed3cd8c6ec 100644 --- a/Modules/IGT/Testing/files.cmake +++ b/Modules/IGT/Testing/files.cmake @@ -1,65 +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 + #mitkNavigationToolReaderAndWriterTest.cpp #deactivated because of bug 18835 # ----------------------------------------------------------------------- ) set(MODULE_CUSTOM_TESTS mitkNDIAuroraHardwareTest.cpp mitkNDIPolarisHardwareTest.cpp mitkClaronTrackingDeviceHardwareTest.cpp ) diff --git a/Modules/IGT/Testing/mitkNavigationToolReaderAndWriterTest.cpp b/Modules/IGT/Testing/mitkNavigationToolReaderAndWriterTest.cpp index 70ad72db64..486773f04a 100644 --- a/Modules/IGT/Testing/mitkNavigationToolReaderAndWriterTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationToolReaderAndWriterTest.cpp @@ -1,224 +1,228 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //Poco headers #include "Poco/Path.h" //mitk headers #include "mitkNavigationToolWriter.h" #include "mitkCommon.h" #include "mitkTestingMacros.h" #include "mitkNavigationTool.h" #include "mitkBaseData.h" #include "mitkDataNode.h" #include "mitkSurface.h" #include "mitkStandaloneDataStorage.h" #include "mitkDataStorage.h" #include "mitkNavigationToolReader.h" #include "mitkIGTConfig.h" #include #include #include mitk::Surface::Pointer m_testSurface; static void TestInstantiation() { // let's create an object of our class mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); MITK_TEST_CONDITION_REQUIRED(myWriter.IsNotNull(),"Testing instantiation") } static void TestWrite() { //testcase with first test tool: a claron tool //create a NavigationTool which we can write on the harddisc std::string toolFileName(MITK_IGT_DATA_DIR); toolFileName.append("/ClaronTool"); mitk::NavigationTool::Pointer myNavigationTool = mitk::NavigationTool::New(); myNavigationTool->SetCalibrationFile(toolFileName); mitk::DataNode::Pointer myNode = mitk::DataNode::New(); myNode->SetName("ClaronTool"); std::string surfaceFileName(MITK_IGT_DATA_DIR); surfaceFileName.append("/ClaronTool.stl"); m_testSurface = mitk::IOUtil::LoadSurface( surfaceFileName ); myNode->SetData(m_testSurface); myNavigationTool->SetDataNode(myNode); myNavigationTool->SetIdentifier("ClaronTool#1"); myNavigationTool->SetSerialNumber("0815"); myNavigationTool->SetTrackingDeviceType(mitk::ClaronMicron); myNavigationTool->SetType(mitk::NavigationTool::Fiducial); //now create a writer and write it to the harddisc mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); - std::string filename = "TestTool.tool"; + std::string filename = mitk::IOUtil::GetTempPath() + "TestTool.tool"; MITK_TEST_OUTPUT(<<"---- Testing navigation tool writer with first test tool (claron tool) ----"); bool test = myWriter->DoWrite(filename,myNavigationTool); MITK_TEST_CONDITION_REQUIRED(test,"OK"); } static void TestRead() { mitk::NavigationToolReader::Pointer myReader = mitk::NavigationToolReader::New(); - mitk::NavigationTool::Pointer readTool = myReader->DoRead("TestTool.tool"); + std::string filename = mitk::IOUtil::GetTempPath() + "TestTool.tool"; + mitk::NavigationTool::Pointer readTool = myReader->DoRead(filename); MITK_TEST_OUTPUT(<<"---- Testing navigation tool reader with first test tool (claron tool) ----"); //Test if the surfaces do have the same number of vertexes (it would be better to test for real equality of the surfaces!) MITK_TEST_CONDITION_REQUIRED(dynamic_cast(readTool->GetDataNode()->GetData())->GetSizeOfPolyDataSeries()==m_testSurface->GetSizeOfPolyDataSeries(),"Test if surface was restored correctly ..."); MITK_TEST_CONDITION_REQUIRED(readTool->GetType()==mitk::NavigationTool::Fiducial,"Testing Tool Type"); MITK_TEST_CONDITION_REQUIRED(readTool->GetTrackingDeviceType()==mitk::ClaronMicron,"Testing Tracking Device Type"); MITK_TEST_CONDITION_REQUIRED(readTool->GetSerialNumber()=="0815","Testing Serial Number"); std::ifstream TestFile(readTool->GetCalibrationFile().c_str()); MITK_TEST_CONDITION_REQUIRED(TestFile,"Testing If Calibration File Exists"); } static void TestWrite2() { //testcase with second test tool: an aurora tool //create a NavigationTool which we can write on the harddisc mitk::NavigationTool::Pointer myNavigationTool = mitk::NavigationTool::New(); mitk::DataNode::Pointer myNode = mitk::DataNode::New(); myNode->SetName("AuroraTool"); std::string surfaceFileName(MITK_IGT_DATA_DIR); surfaceFileName.append("/EMTool.stl"); m_testSurface = mitk::IOUtil::LoadSurface( surfaceFileName ); myNode->SetData(m_testSurface); myNavigationTool->SetDataNode(myNode); myNavigationTool->SetIdentifier("AuroraTool#1"); myNavigationTool->SetSerialNumber("0816"); myNavigationTool->SetTrackingDeviceType(mitk::NDIAurora); myNavigationTool->SetType(mitk::NavigationTool::Instrument); //now create a writer and write it to the harddisc mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); - std::string filename = "TestTool2.tool"; + std::string filename = mitk::IOUtil::GetTempPath() + "TestTool2.tool"; MITK_TEST_OUTPUT(<<"---- Testing navigation tool writer with second tool (aurora tool) ----"); bool test = myWriter->DoWrite(filename,myNavigationTool); MITK_TEST_CONDITION_REQUIRED(test,"OK"); } static void TestRead2() { mitk::NavigationToolReader::Pointer myReader = mitk::NavigationToolReader::New(); - mitk::NavigationTool::Pointer readTool = myReader->DoRead("TestTool2.tool"); + std::string filename = mitk::IOUtil::GetTempPath() + "TestTool2.tool"; + mitk::NavigationTool::Pointer readTool = myReader->DoRead(filename); MITK_TEST_OUTPUT(<<"---- Testing navigation tool reader with second tool (aurora tool) ----"); //Test if the surfaces do have the same number of vertexes (it would be better to test for real equality of the surfaces!) MITK_TEST_CONDITION_REQUIRED(dynamic_cast(readTool->GetDataNode()->GetData())->GetSizeOfPolyDataSeries()==m_testSurface->GetSizeOfPolyDataSeries(),"Test if surface was restored correctly ..."); //Test if the tool type is the same MITK_TEST_CONDITION_REQUIRED(readTool->GetType()==mitk::NavigationTool::Instrument,"Testing Tool Type"); MITK_TEST_CONDITION_REQUIRED(readTool->GetTrackingDeviceType()==mitk::NDIAurora,"Testing Tracking Device Type"); MITK_TEST_CONDITION_REQUIRED(readTool->GetSerialNumber()=="0816","Testing Serial Number"); MITK_TEST_CONDITION_REQUIRED(readTool->GetCalibrationFile()=="none","Testing Calibration File"); } static void CleanUp() { - std::remove("TestTool.tool"); - std::remove("TestTool2.tool"); + std::string tempFile1 = mitk::IOUtil::GetTempPath() + "TestTool.tool"; + std::remove(tempFile1.c_str()); + std::string tempFile2 = mitk::IOUtil::GetTempPath() + "TestTool2.tool"; + std::remove(tempFile2.c_str()); } static void TestReadInvalidData() { mitk::NavigationToolReader::Pointer myReader = mitk::NavigationToolReader::New(); mitk::NavigationTool::Pointer readTool = myReader->DoRead("invalidTool"); MITK_TEST_CONDITION_REQUIRED(readTool.IsNull(), "Testing return value if filename is invalid"); MITK_TEST_CONDITION_REQUIRED(myReader->GetErrorMessage() == "Cannot open 'invalidTool' for reading", "Testing error message in this case"); } static void TestWriteInvalidFilename() { //create a test navigation tool mitk::NavigationTool::Pointer myNavigationTool = mitk::NavigationTool::New(); mitk::DataNode::Pointer myNode = mitk::DataNode::New(); myNode->SetName("AuroraTool"); std::string surfaceFileName(MITK_IGT_DATA_DIR); surfaceFileName.append("/EMTool.stl"); m_testSurface = mitk::IOUtil::LoadSurface( surfaceFileName ); myNode->SetData(m_testSurface); myNavigationTool->SetDataNode(myNode); myNavigationTool->SetIdentifier("AuroraTool#1"); myNavigationTool->SetSerialNumber("0816"); myNavigationTool->SetTrackingDeviceType(mitk::NDIAurora); myNavigationTool->SetType(mitk::NavigationTool::Instrument); //now create a writer and write it to the harddisc mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); std::string filename = "NH:/sfdsfsdsf.&%%%"; MITK_TEST_OUTPUT(<<"---- Testing write invalid file ----"); bool test = myWriter->DoWrite(filename,myNavigationTool); MITK_TEST_CONDITION_REQUIRED(!test,"testing write"); MITK_TEST_CONDITION_REQUIRED(myWriter->GetErrorMessage() == "Could not open a zip file for writing: 'NH:/sfdsfsdsf.&%%%'","testing error message"); } static void TestWriteInvalidData() { mitk::NavigationTool::Pointer myNavigationTool; //tool is invalid because no data note is created //now create a writer and write it to the harddisc mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); std::string filename = "NH:/sfdsfsdsf.&%%%"; MITK_TEST_OUTPUT(<<"---- Testing write invalid tool ----"); bool test = myWriter->DoWrite(filename,myNavigationTool); MITK_TEST_CONDITION_REQUIRED(!test,"testing write"); MITK_TEST_CONDITION_REQUIRED(myWriter->GetErrorMessage() == "Cannot write a navigation tool containing invalid tool data, aborting!","testing error message"); } /** This function is testing the TrackingVolume class. */ int mitkNavigationToolReaderAndWriterTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("NavigationToolWriter") TestInstantiation(); TestWrite(); TestRead(); TestWrite2(); TestRead2(); TestReadInvalidData(); TestWriteInvalidData(); TestWriteInvalidFilename(); CleanUp(); MITK_TEST_END() } diff --git a/Modules/Segmentation/Interactions/mitkPaintbrushTool.cpp b/Modules/Segmentation/Interactions/mitkPaintbrushTool.cpp index e8c21346b5..ce7289025b 100644 --- a/Modules/Segmentation/Interactions/mitkPaintbrushTool.cpp +++ b/Modules/Segmentation/Interactions/mitkPaintbrushTool.cpp @@ -1,519 +1,500 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY 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 "mitkPaintbrushTool.h" #include "mitkToolManager.h" #include "mitkOverwriteSliceImageFilter.h" #include "mitkBaseRenderer.h" #include "mitkImageDataItem.h" #include "ipSegmentation.h" #include "mitkAbstractTransformGeometry.h" #include "mitkLevelWindowProperty.h" #define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a))) int mitk::PaintbrushTool::m_Size = 1; mitk::PaintbrushTool::PaintbrushTool(int paintingPixelValue) :FeedbackContourTool("PressMoveReleaseWithCTRLInversionAllMouseMoves"), m_PaintingPixelValue(paintingPixelValue), m_LastContourSize(0) // other than initial mitk::PaintbrushTool::m_Size (around l. 28) { m_MasterContour = ContourModel::New(); m_MasterContour->Initialize(); - m_CurrentPlane = NULL; + m_CurrentPlane = nullptr; m_WorkingNode = DataNode::New(); m_WorkingNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( mitk::LevelWindow(0, 1) ) ); m_WorkingNode->SetProperty( "binary", mitk::BoolProperty::New(true) ); } mitk::PaintbrushTool::~PaintbrushTool() { } void mitk::PaintbrushTool::ConnectActionsAndFunctions() { CONNECT_FUNCTION( "PrimaryButtonPressed", OnMousePressed); CONNECT_FUNCTION( "Move", OnPrimaryButtonPressedMoved); CONNECT_FUNCTION( "MouseMove", OnMouseMoved); CONNECT_FUNCTION( "Release", OnMouseReleased); CONNECT_FUNCTION( "InvertLogic", OnInvertLogic); } void mitk::PaintbrushTool::Activated() { Superclass::Activated(); FeedbackContourTool::SetFeedbackContourVisible(true); SizeChanged.Send(m_Size); m_ToolManager->WorkingDataChanged += mitk::MessageDelegate( this, &mitk::PaintbrushTool::OnToolManagerWorkingDataModified ); } void mitk::PaintbrushTool::Deactivated() { FeedbackContourTool::SetFeedbackContourVisible(false); if (m_ToolManager->GetDataStorage()->Exists(m_WorkingNode)) m_ToolManager->GetDataStorage()->Remove(m_WorkingNode); Superclass::Deactivated(); - m_WorkingSlice = NULL; - m_CurrentPlane = NULL; + m_WorkingSlice = nullptr; + m_CurrentPlane = nullptr; m_ToolManager->WorkingDataChanged -= mitk::MessageDelegate( this, &mitk::PaintbrushTool::OnToolManagerWorkingDataModified ); } void mitk::PaintbrushTool::SetSize(int value) { m_Size = value; } mitk::Point2D mitk::PaintbrushTool::upperLeft(mitk::Point2D p) { p[0] -= 0.5; p[1] += 0.5; return p; } void mitk::PaintbrushTool::UpdateContour(const InteractionPositionEvent* positionEvent) { //MITK_INFO<<"Update..."; // examine stateEvent and create a contour that matches the pixel mask that we are going to draw //mitk::InteractionPositionEvent* positionEvent = dynamic_cast( interactionEvent ); //const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return; // Get Spacing of current Slice //mitk::Vector3D vSpacing = m_WorkingSlice->GetSlicedGeometry()->GetPlaneGeometry(0)->GetSpacing(); // // Draw a contour in Square according to selected brush size // int radius = (m_Size)/2; float fradius = static_cast(m_Size) / 2.0f; ContourModel::Pointer contourInImageIndexCoordinates = ContourModel::New(); // estimate center point of the brush ( relative to the pixel the mouse points on ) // -- left upper corner for even sizes, // -- midpoint for uneven sizes mitk::Point2D centerCorrection; centerCorrection.Fill(0); // even --> correction of [+0.5, +0.5] bool evenSize = ((m_Size % 2) == 0); if( evenSize ) { centerCorrection[0] += 0.5; centerCorrection[1] += 0.5; } // we will compute the control points for the upper left quarter part of a circle contour std::vector< mitk::Point2D > quarterCycleUpperRight; std::vector< mitk::Point2D > quarterCycleLowerRight; std::vector< mitk::Point2D > quarterCycleLowerLeft; std::vector< mitk::Point2D > quarterCycleUpperLeft; mitk::Point2D curPoint; bool curPointIsInside = true; curPoint[0] = 0; curPoint[1] = radius; quarterCycleUpperRight.push_back( upperLeft(curPoint) ); // to estimate if a pixel is inside the circle, we need to compare against the 'outer radius' // i.e. the distance from the midpoint [0,0] to the border of the pixel [0,radius] //const float outer_radius = static_cast(radius) + 0.5; while (curPoint[1] > 0) { // Move right until pixel is outside circle float curPointX_squared = 0.0f; float curPointY_squared = (curPoint[1] - centerCorrection[1] ) * (curPoint[1] - centerCorrection[1] ); while( curPointIsInside ) { // increment posX and chec curPoint[0]++; curPointX_squared = (curPoint[0] - centerCorrection[0] ) * (curPoint[0] - centerCorrection[0] ); const float len = sqrt( curPointX_squared + curPointY_squared); if ( len > fradius ) { // found first Pixel in this horizontal line, that is outside the circle curPointIsInside = false; } } quarterCycleUpperRight.push_back( upperLeft(curPoint) ); // Move down until pixel is inside circle while( !curPointIsInside ) { // increment posX and chec curPoint[1]--; curPointY_squared = (curPoint[1] - centerCorrection[1] ) * (curPoint[1] - centerCorrection[1] ); const float len = sqrt( curPointX_squared + curPointY_squared); if ( len <= fradius ) { // found first Pixel in this horizontal line, that is outside the circle curPointIsInside = true; quarterCycleUpperRight.push_back( upperLeft(curPoint) ); } // Quarter cycle is full, when curPoint y position is 0 if (curPoint[1] <= 0) break; } } // QuarterCycle is full! Now copy quarter cycle to other quarters. if( !evenSize ) { std::vector< mitk::Point2D >::const_iterator it = quarterCycleUpperRight.begin(); while( it != quarterCycleUpperRight.end() ) { mitk::Point2D p; p = *it; // the contour points in the lower right corner have same position but with negative y values p[1] *= -1; quarterCycleLowerRight.push_back(p); // the contour points in the lower left corner have same position // but with both x,y negative p[0] *= -1; quarterCycleLowerLeft.push_back(p); // the contour points in the upper left corner have same position // but with x negative p[1] *= -1; quarterCycleUpperLeft.push_back(p); it++; } } else { std::vector< mitk::Point2D >::const_iterator it = quarterCycleUpperRight.begin(); while( it != quarterCycleUpperRight.end() ) { mitk::Point2D p,q; p = *it; q = p; // the contour points in the lower right corner have same position but with negative y values q[1] *= -1; // correct for moved offset if size even = the midpoint is not the midpoint of the current pixel // but its upper rigt corner q[1] += 1; quarterCycleLowerRight.push_back(q); q = p; // the contour points in the lower left corner have same position // but with both x,y negative q[1] = -1.0f * q[1] + 1; q[0] = -1.0f * q[0] + 1; quarterCycleLowerLeft.push_back(q); // the contour points in the upper left corner have same position // but with x negative q = p; q[0] *= -1; q[0] += 1; quarterCycleUpperLeft.push_back(q); it++; } } // fill contour with poins in right ordering, starting with the upperRight block mitk::Point3D tempPoint; for (unsigned int i=0; iAddVertex( tempPoint ); } // the lower right has to be parsed in reverse order for (int i=quarterCycleLowerRight.size()-1; i>=0; i--) { tempPoint[0] = quarterCycleLowerRight[i][0]; tempPoint[1] = quarterCycleLowerRight[i][1]; tempPoint[2] = 0; contourInImageIndexCoordinates->AddVertex( tempPoint ); } for (unsigned int i=0; iAddVertex( tempPoint ); } // the upper left also has to be parsed in reverse order for (int i=quarterCycleUpperLeft.size()-1; i>=0; i--) { tempPoint[0] = quarterCycleUpperLeft[i][0]; tempPoint[1] = quarterCycleUpperLeft[i][1]; tempPoint[2] = 0; contourInImageIndexCoordinates->AddVertex( tempPoint ); } m_MasterContour = contourInImageIndexCoordinates; } /** Just show the contour, get one point as the central point and add surrounding points to the contour. */ bool mitk::PaintbrushTool::OnMousePressed ( StateMachineAction*, InteractionEvent* interactionEvent ) { mitk::InteractionPositionEvent* positionEvent = dynamic_cast( interactionEvent ); - //const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); + if (!positionEvent) return false; m_LastEventSender = positionEvent->GetSender(); m_LastEventSlice = m_LastEventSender->GetSlice(); m_MasterContour->SetClosed(true); return this->MouseMoved(interactionEvent, true); } bool mitk::PaintbrushTool::OnMouseMoved( StateMachineAction*, InteractionEvent* interactionEvent ) { return MouseMoved(interactionEvent, false); } bool mitk::PaintbrushTool::OnPrimaryButtonPressedMoved( StateMachineAction*, InteractionEvent* interactionEvent ) { return MouseMoved(interactionEvent, true); } /** Insert the point to the feedback contour,finish to build the contour and at the same time the painting function */ bool mitk::PaintbrushTool::MouseMoved(mitk::InteractionEvent* interactionEvent, bool leftMouseButtonPressed) { mitk::InteractionPositionEvent* positionEvent = dynamic_cast( interactionEvent ); - //const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); CheckIfCurrentSliceHasChanged( positionEvent ); if ( m_LastContourSize != m_Size ) { UpdateContour( positionEvent ); m_LastContourSize = m_Size; } -// stateEvent->GetId() == 530 -// || stateEvent->GetId() == 534 -// || stateEvent->GetId() == 1 -// || stateEvent->GetId() == 5 -// ); - Point3D worldCoordinates = positionEvent->GetPositionInWorld(); Point3D indexCoordinates; m_WorkingSlice->GetGeometry()->WorldToIndex( worldCoordinates, indexCoordinates ); MITK_DEBUG << "Mouse at W " << worldCoordinates << std::endl; MITK_DEBUG << "Mouse at I " << indexCoordinates << std::endl; // round to nearest voxel center (abort if this hasn't changed) if ( m_Size % 2 == 0 ) // even { indexCoordinates[0] = ROUND( indexCoordinates[0]);// /*+ 0.5*/) + 0.5; indexCoordinates[1] = ROUND( indexCoordinates[1]);// /*+ 0.5*/ ) + 0.5; } else // odd { indexCoordinates[0] = ROUND( indexCoordinates[0] ) ; indexCoordinates[1] = ROUND( indexCoordinates[1] ) ; } static Point3D lastPos; // uninitialized: if somebody finds out how this can be initialized in a one-liner, tell me if ( fabs(indexCoordinates[0] - lastPos[0]) > mitk::eps || fabs(indexCoordinates[1] - lastPos[1]) > mitk::eps || fabs(indexCoordinates[2] - lastPos[2]) > mitk::eps || leftMouseButtonPressed ) { lastPos = indexCoordinates; } else { MITK_DEBUG << "." << std::flush; return false; } MITK_DEBUG << "Mouse at C " << indexCoordinates; int timestep = positionEvent->GetSender()->GetTimeStep(); ContourModel::Pointer contour = ContourModel::New(); contour->Expand(timestep + 1); contour->SetClosed(true, timestep); ContourModel::VertexIterator it = m_MasterContour->Begin(); ContourModel::VertexIterator end = m_MasterContour->End(); while(it != end) { Point3D point = (*it)->Coordinates; point[0] += indexCoordinates[ 0 ]; point[1] += indexCoordinates[ 1 ]; contour->AddVertex( point, timestep ); it++; } if (leftMouseButtonPressed) { FeedbackContourTool::FillContourInSlice( contour, timestep, m_WorkingSlice, m_PaintingPixelValue ); m_WorkingNode->SetData(m_WorkingSlice); m_WorkingNode->Modified(); } // visualize contour ContourModel::Pointer displayContour = ContourModel::New(); displayContour->Initialize(); - - //for (unsigned int index = 0; index < contour->GetNumberOfPoints(); ++index) - //{ - // Point3D point = contour->GetPoints()->ElementAt(index); - // if ( m_Size % 2 == 0 ) // even - // { - // point[0] += 0.5; - // point[1] += 0.5; - // } - // displayContour->AddVertex( point ); - //} - displayContour = FeedbackContourTool::BackProjectContourFrom2DSlice( m_WorkingSlice->GetGeometry(), /*displayContour*/contour ); SetFeedbackContour( *displayContour ); assert( positionEvent->GetSender()->GetRenderWindow() ); RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } bool mitk::PaintbrushTool::OnMouseReleased( StateMachineAction*, InteractionEvent* interactionEvent ) { //When mouse is released write segmentationresult back into image mitk::InteractionPositionEvent* positionEvent = dynamic_cast( interactionEvent ); - //const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; + CheckIfCurrentSliceHasChanged(positionEvent); this->WriteBackSegmentationResult(positionEvent, m_WorkingSlice->Clone()); return true; } /** Called when the CTRL key is pressed. Will change the painting pixel value from 0 to 1 or from 1 to 0. */ bool mitk::PaintbrushTool::OnInvertLogic( StateMachineAction*, InteractionEvent* interactionEvent ) { // Inversion only for 0 and 1 as painting values if (m_PaintingPixelValue == 1) { m_PaintingPixelValue = 0; FeedbackContourTool::SetFeedbackContourColor( 1.0, 0.0, 0.0 ); } else if (m_PaintingPixelValue == 0) { m_PaintingPixelValue = 1; FeedbackContourTool::SetFeedbackContourColorDefault(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } void mitk::PaintbrushTool::CheckIfCurrentSliceHasChanged(const InteractionPositionEvent *event) { const PlaneGeometry* planeGeometry( dynamic_cast (event->GetSender()->GetCurrentWorldPlaneGeometry() ) ); const AbstractTransformGeometry* abstractTransformGeometry( dynamic_cast (event->GetSender()->GetCurrentWorldPlaneGeometry() ) ); DataNode* workingNode( m_ToolManager->GetWorkingData(0) ); if (!workingNode) return; Image::Pointer image = dynamic_cast(workingNode->GetData()); if ( !image || !planeGeometry || abstractTransformGeometry ) return; if(m_CurrentPlane.IsNull() || m_WorkingSlice.IsNull()) { m_CurrentPlane = const_cast(planeGeometry); m_WorkingSlice = SegTool2D::GetAffectedImageSliceAs2DImage(event, image)->Clone(); m_WorkingNode->ReplaceProperty( "color", workingNode->GetProperty("color") ); m_WorkingNode->SetData(m_WorkingSlice); } else { bool isSameSlice (false); isSameSlice = mitk::MatrixEqualElementWise(planeGeometry->GetIndexToWorldTransform()->GetMatrix(),m_CurrentPlane->GetIndexToWorldTransform()->GetMatrix()); isSameSlice = mitk::Equal(planeGeometry->GetIndexToWorldTransform()->GetOffset(),m_CurrentPlane->GetIndexToWorldTransform()->GetOffset()); if (!isSameSlice) { m_ToolManager->GetDataStorage()->Remove(m_WorkingNode); - m_CurrentPlane = NULL; - m_WorkingSlice = NULL; - m_WorkingNode = NULL; + m_CurrentPlane = nullptr; + m_WorkingSlice = nullptr; + m_WorkingNode = nullptr; m_CurrentPlane = const_cast(planeGeometry); m_WorkingSlice = SegTool2D::GetAffectedImageSliceAs2DImage(event, image)->Clone(); m_WorkingNode = mitk::DataNode::New(); m_WorkingNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( mitk::LevelWindow(0, 1) ) ); m_WorkingNode->SetProperty( "binary", mitk::BoolProperty::New(true) ); m_WorkingNode->SetData(m_WorkingSlice); //So that the paintbrush contour vanished in the previous render window RenderingManager::GetInstance()->RequestUpdateAll(); } } if(!m_ToolManager->GetDataStorage()->Exists(m_WorkingNode)) { m_WorkingNode->SetProperty( "outline binary", mitk::BoolProperty::New(true) ); m_WorkingNode->SetProperty( "color", workingNode->GetProperty("color") ); m_WorkingNode->SetProperty( "name", mitk::StringProperty::New("Paintbrush_Node") ); m_WorkingNode->SetProperty( "helper object", mitk::BoolProperty::New(true) ); m_WorkingNode->SetProperty( "opacity", mitk::FloatProperty::New(0.8) ); m_WorkingNode->SetProperty( "includeInBoundingBox", mitk::BoolProperty::New(false)); m_WorkingNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); m_ToolManager->GetDataStorage()->Add(m_WorkingNode); } } void mitk::PaintbrushTool::OnToolManagerWorkingDataModified() { //Here we simply set the current working slice to null. The next time the mouse is moved //within a renderwindow a new slice will be extracted from the new working data - m_WorkingSlice = 0; + m_WorkingSlice = nullptr; } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/CMakeLists.txt b/Plugins/org.mitk.gui.qt.diffusionimaging/CMakeLists.txt index c18e24b43a..445d7daaa3 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/CMakeLists.txt @@ -1,8 +1,8 @@ project(org_mitk_gui_qt_diffusionimaging) MACRO_CREATE_MITK_CTK_PLUGIN( EXPORT_DIRECTIVE DIFFUSIONIMAGING_EXPORT EXPORTED_INCLUDE_SUFFIXES src MODULE_DEPENDS MitkQtWidgetsExt MitkConnectomics MitkFiberTracking MitkDiffusionCore MitkQuantification - PACKAGE_DEPENDS ITK|ITKDiffusionTensorImage + PACKAGE_DEPENDS PUBLIC ITK|ITKDiffusionTensorImage Vigra HDF5 ) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/files.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging/files.cmake index a6f512c7f6..fa0b37ba15 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/files.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/files.cmake @@ -1,208 +1,211 @@ set(SRC_CPP_FILES QmitkODFDetailsWidget.cpp QmitkODFRenderWidget.cpp QmitkPartialVolumeAnalysisWidget.cpp QmitkIVIMWidget.cpp QmitkTbssRoiAnalysisWidget.cpp QmitkResidualAnalysisWidget.cpp QmitkResidualViewWidget.cpp QmitkTensorModelParametersWidget.cpp QmitkZeppelinModelParametersWidget.cpp QmitkStickModelParametersWidget.cpp QmitkDotModelParametersWidget.cpp QmitkBallModelParametersWidget.cpp QmitkAstrosticksModelParametersWidget.cpp QmitkPrototypeSignalParametersWidget.cpp ) set(INTERNAL_CPP_FILES mitkPluginActivator.cpp QmitkQBallReconstructionView.cpp QmitkPreprocessingView.cpp QmitkDiffusionDicomImportView.cpp QmitkDiffusionQuantificationView.cpp QmitkTensorReconstructionView.cpp QmitkControlVisualizationPropertiesView.cpp QmitkODFDetailsView.cpp QmitkGibbsTrackingView.cpp QmitkStochasticFiberTrackingView.cpp QmitkStreamlineTrackingView.cpp QmitkFiberQuantificationView.cpp -# QmitkFiberBundleDeveloperView.cpp QmitkPartialVolumeAnalysisView.cpp QmitkIVIMView.cpp QmitkTractbasedSpatialStatisticsView.cpp QmitkTbssTableModel.cpp QmitkTbssMetaTableModel.cpp QmitkTbssSkeletonizationView.cpp Connectomics/QmitkConnectomicsDataView.cpp Connectomics/QmitkConnectomicsNetworkOperationsView.cpp Connectomics/QmitkConnectomicsStatisticsView.cpp Connectomics/QmitkNetworkHistogramCanvas.cpp Connectomics/QmitkRandomParcellationView.cpp QmitkDwiSoftwarePhantomView.cpp QmitkOdfMaximaExtractionView.cpp QmitkFiberfoxView.cpp QmitkFiberProcessingView.cpp QmitkFieldmapGeneratorView.cpp QmitkDiffusionRegistrationView.cpp QmitkDenoisingView.cpp + QmitkMLBTView.cpp Perspectives/QmitkFiberProcessingPerspective.cpp Perspectives/QmitkDiffusionImagingAppPerspective.cpp Perspectives/QmitkGibbsTractographyPerspective.cpp Perspectives/QmitkStreamlineTractographyPerspective.cpp Perspectives/QmitkProbabilisticTractographyPerspective.cpp Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.cpp Perspectives/QmitkDIAppIVIMPerspective.cpp Perspectives/QmitkDiffusionDefaultPerspective.cpp ) set(UI_FILES src/internal/QmitkQBallReconstructionViewControls.ui src/internal/QmitkPreprocessingViewControls.ui src/internal/QmitkDiffusionDicomImportViewControls.ui src/internal/QmitkDiffusionQuantificationViewControls.ui src/internal/QmitkTensorReconstructionViewControls.ui src/internal/QmitkControlVisualizationPropertiesViewControls.ui src/internal/QmitkODFDetailsViewControls.ui src/internal/QmitkGibbsTrackingViewControls.ui src/internal/QmitkStochasticFiberTrackingViewControls.ui src/internal/QmitkStreamlineTrackingViewControls.ui src/internal/QmitkFiberQuantificationViewControls.ui # src/internal/QmitkFiberBundleDeveloperViewControls.ui src/internal/QmitkPartialVolumeAnalysisViewControls.ui src/internal/QmitkIVIMViewControls.ui src/internal/QmitkTractbasedSpatialStatisticsViewControls.ui src/internal/QmitkTbssSkeletonizationViewControls.ui src/internal/Connectomics/QmitkConnectomicsDataViewControls.ui src/internal/Connectomics/QmitkConnectomicsNetworkOperationsViewControls.ui src/internal/Connectomics/QmitkConnectomicsStatisticsViewControls.ui src/internal/Connectomics/QmitkRandomParcellationViewControls.ui src/internal/QmitkDwiSoftwarePhantomViewControls.ui src/internal/QmitkOdfMaximaExtractionViewControls.ui src/internal/QmitkFiberfoxViewControls.ui src/internal/QmitkFiberProcessingViewControls.ui src/QmitkTensorModelParametersWidgetControls.ui src/QmitkZeppelinModelParametersWidgetControls.ui src/QmitkStickModelParametersWidgetControls.ui src/QmitkDotModelParametersWidgetControls.ui src/QmitkBallModelParametersWidgetControls.ui src/QmitkAstrosticksModelParametersWidgetControls.ui src/QmitkPrototypeSignalParametersWidgetControls.ui src/internal/QmitkFieldmapGeneratorViewControls.ui src/internal/QmitkDiffusionRegistrationViewControls.ui src/internal/QmitkDenoisingViewControls.ui + src/internal/QmitkMLBTViewControls.ui ) set(MOC_H_FILES src/internal/mitkPluginActivator.h src/internal/QmitkQBallReconstructionView.h src/internal/QmitkPreprocessingView.h src/internal/QmitkDiffusionDicomImportView.h src/internal/QmitkDiffusionQuantificationView.h src/internal/QmitkTensorReconstructionView.h src/internal/QmitkControlVisualizationPropertiesView.h src/internal/QmitkODFDetailsView.h src/QmitkODFRenderWidget.h src/QmitkODFDetailsWidget.h src/internal/QmitkGibbsTrackingView.h src/internal/QmitkStochasticFiberTrackingView.h src/internal/QmitkStreamlineTrackingView.h src/internal/QmitkFiberQuantificationView.h # src/internal/QmitkFiberBundleDeveloperView.h src/internal/QmitkPartialVolumeAnalysisView.h src/QmitkPartialVolumeAnalysisWidget.h src/internal/QmitkIVIMView.h src/internal/QmitkTractbasedSpatialStatisticsView.h src/internal/QmitkTbssSkeletonizationView.h src/QmitkTbssRoiAnalysisWidget.h src/QmitkResidualAnalysisWidget.h src/QmitkResidualViewWidget.h src/internal/Connectomics/QmitkConnectomicsDataView.h src/internal/Connectomics/QmitkConnectomicsNetworkOperationsView.h src/internal/Connectomics/QmitkConnectomicsStatisticsView.h src/internal/Connectomics/QmitkNetworkHistogramCanvas.h src/internal/Connectomics/QmitkRandomParcellationView.h src/internal/QmitkDwiSoftwarePhantomView.h src/internal/QmitkOdfMaximaExtractionView.h src/internal/QmitkFiberfoxView.h src/internal/QmitkFiberProcessingView.h src/QmitkTensorModelParametersWidget.h src/QmitkZeppelinModelParametersWidget.h src/QmitkStickModelParametersWidget.h src/QmitkDotModelParametersWidget.h src/QmitkBallModelParametersWidget.h src/QmitkAstrosticksModelParametersWidget.h src/QmitkPrototypeSignalParametersWidget.h src/internal/QmitkFieldmapGeneratorView.h src/internal/QmitkDiffusionRegistrationView.h src/internal/QmitkDenoisingView.h + src/internal/QmitkMLBTView.h src/internal/Perspectives/QmitkFiberProcessingPerspective.h src/internal/Perspectives/QmitkDiffusionImagingAppPerspective.h src/internal/Perspectives/QmitkGibbsTractographyPerspective.h src/internal/Perspectives/QmitkStreamlineTractographyPerspective.h src/internal/Perspectives/QmitkProbabilisticTractographyPerspective.h src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.h src/internal/Perspectives/QmitkDIAppIVIMPerspective.h src/internal/Perspectives/QmitkDiffusionDefaultPerspective.h ) set(CACHED_RESOURCE_FILES # list of resource files which can be used by the plug-in # system without loading the plug-ins shared library, # for example the icon used in the menu and tabs for the # plug-in views in the workbench plugin.xml resources/preprocessing.png resources/dwiimport.png resources/quantification.png resources/reconodf.png resources/recontensor.png resources/vizControls.png resources/OdfDetails.png resources/GibbsTracking.png resources/FiberBundleOperations.png resources/PartialVolumeAnalysis_24.png resources/IVIM_48.png resources/stochFB.png resources/tbss.png resources/connectomics/QmitkConnectomicsDataViewIcon_48.png resources/connectomics/QmitkConnectomicsNetworkOperationsViewIcon_48.png resources/connectomics/QmitkConnectomicsStatisticsViewIcon_48.png resources/connectomics/QmitkRandomParcellationIcon.png resources/arrow.png resources/qball_peaks.png resources/phantom.png resources/tensor.png resources/qball.png resources/StreamlineTracking.png resources/dwi2.png resources/dwi.png resources/odf.png resources/refresh.xpm resources/diffusionregistration.png resources/denoisingicon.png resources/syntheticdata.png resources/ivim.png resources/tractography.png + resources/fiberTracking1.png ) set(QRC_FILES # uncomment the following line if you want to use Qt resources resources/QmitkDiffusionImaging.qrc #resources/QmitkTractbasedSpatialStatisticsView.qrc ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/plugin.xml b/Plugins/org.mitk.gui.qt.diffusionimaging/plugin.xml index 99206fa33f..a3ed07f6e8 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/plugin.xml +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/plugin.xml @@ -1,428 +1,435 @@ Q-Ball reconstruction view Diffusion DICOM data import Calculation of tensor and Q-ball derived measures. Diffusion weighted MRI data simulation tool. - + + + + This perspective contains all views necessary to post process fibers. diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/resources/fiberTracking1.png b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/fiberTracking1.png new file mode 100644 index 0000000000..be82a2eeb2 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.diffusionimaging/resources/fiberTracking1.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkMLBTView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkMLBTView.cpp new file mode 100644 index 0000000000..992e0c577e --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkMLBTView.cpp @@ -0,0 +1,329 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +// Blueberry +#include +#include + +// Qmitk +#include "QmitkMLBTView.h" +#include "QmitkStdMultiWidget.h" + +// Qt +#include +#include +#include + +#include "mitkNodePredicateDataType.h" +#include +#include +#include +#include +#include + +#define _USE_MATH_DEFINES +#include + +const std::string QmitkMLBTView::VIEW_ID = "org.mitk.views.mlbtview"; +using namespace berry; + +QmitkMLBTView::QmitkMLBTView() + : QmitkFunctionality() + , m_Controls( 0 ) + , m_MultiWidget( NULL ) +{ + m_TrackingTimer = new QTimer(this); +} + +// Destructor +QmitkMLBTView::~QmitkMLBTView() +{ + +} + +void QmitkMLBTView::CreateQtPartControl( QWidget *parent ) +{ + // build up qt view, unless already done + if ( !m_Controls ) + { + // create GUI widgets from the Qt Designer's .ui file + m_Controls = new Ui::QmitkMLBTViewControls; + m_Controls->setupUi( parent ); + + connect( m_Controls->m_StartTrainingButton, SIGNAL ( clicked() ), this, SLOT( StartTrainingThread() ) ); + connect( &m_TrainingWatcher, SIGNAL ( finished() ), this, SLOT( OnTrainingThreadStop() ) ); + connect( m_Controls->m_StartTrackingButton, SIGNAL ( clicked() ), this, SLOT( StartTrackingThread() ) ); + connect( &m_TrackingWatcher, SIGNAL ( finished() ), this, SLOT( OnTrackingThreadStop() ) ); + connect( m_Controls->m_SaveForestButton, SIGNAL ( clicked() ), this, SLOT( SaveForest() ) ); + connect( m_Controls->m_LoadForestButton, SIGNAL ( clicked() ), this, SLOT( LoadForest() ) ); + connect( m_TrackingTimer, SIGNAL(timeout()), this, SLOT(BuildFibers()) ); + connect( m_Controls->m_TimerIntervalBox, SIGNAL(valueChanged(int)), this, SLOT( ChangeTimerInterval(int) )); + connect( m_Controls->m_DemoModeBox, SIGNAL(stateChanged(int)), this, SLOT( ToggleDemoMode(int) )); + connect( m_Controls->m_PauseTrackingButton, SIGNAL ( clicked() ), this, SLOT( PauseTracking() ) ); + connect( m_Controls->m_AbortTrackingButton, SIGNAL ( clicked() ), this, SLOT( AbortTracking() ) ); + + int numThread = itk::MultiThreader::GetGlobalDefaultNumberOfThreads(); + m_Controls->m_NumberOfThreadsBox->setMaximum(numThread); + m_Controls->m_NumberOfThreadsBox->setValue(numThread); + + m_Controls->m_TrackingMaskImageBox->SetDataStorage(this->GetDataStorage()); + m_Controls->m_TrackingSeedImageBox->SetDataStorage(this->GetDataStorage()); + m_Controls->m_TrackingStopImageBox->SetDataStorage(this->GetDataStorage()); + m_Controls->m_TrackingRawImageBox->SetDataStorage(this->GetDataStorage()); + + 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); + mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); + finalPredicate = mitk::NodePredicateAnd::New(finalPredicate, isBinaryPredicate); + m_Controls->m_TrackingMaskImageBox->SetPredicate(finalPredicate); + m_Controls->m_TrackingSeedImageBox->SetPredicate(finalPredicate); + m_Controls->m_TrackingStopImageBox->SetPredicate(finalPredicate); + m_Controls->m_TrackingRawImageBox->SetPredicate(isDwi); + } +} + +void QmitkMLBTView::AbortTracking() +{ + if (tracker.IsNotNull()) + { + tracker->m_AbortTracking = true; + } +} + +void QmitkMLBTView::PauseTracking() +{ + if (tracker.IsNotNull()) + { + tracker->m_PauseTracking = !tracker->m_PauseTracking; + } +} + +void QmitkMLBTView::ChangeTimerInterval(int value) +{ + m_TrackingTimer->setInterval(value); +} + +void QmitkMLBTView::ToggleDemoMode(int state) +{ + if (tracker.IsNotNull()) + { + tracker->SetDemoMode(m_Controls->m_DemoModeBox->isChecked()); + tracker->m_Stop = false; + } +} + +void QmitkMLBTView::BuildFibers() +{ + if (m_Controls->m_DemoModeBox->isChecked() && tracker.IsNotNull() && tracker->m_BuildFibersFinished) + { + vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData(); + mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly); + outFib->SetFiberColors(255,0,0); + m_TractogramNode->SetData(outFib); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + tracker->m_BuildFibersFinished = false; + tracker->m_Stop = false; + tracker->m_BuildFibersReady = 0; + } +} + +void QmitkMLBTView::LoadForest() +{ + + QString filename = QFileDialog::getOpenFileName(0, tr("Load Forest"), QDir::currentPath(), tr("HDF5 random forest file (*.rf)") ); + if(filename.isEmpty() || filename.isNull()) + return; + + m_ForestHandler.LoadForest( filename.toStdString() ); +} + +void QmitkMLBTView::StartTrackingThread() +{ + m_TractogramNode = mitk::DataNode::New(); + m_TractogramNode->SetName("MLBT Result"); + m_TractogramNode->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(20)); + m_TractogramNode->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false)); + m_TractogramNode->SetProperty("LineWidth", mitk::IntProperty::New(2)); + m_TractogramNode->SetProperty("color",mitk::ColorProperty::New(0, 1, 1)); + this->GetDataStorage()->Add(m_TractogramNode); + + QFuture future = QtConcurrent::run( this, &QmitkMLBTView::StartTracking ); + m_TrackingWatcher.setFuture(future); + m_TrackingThreadIsRunning = true; + m_Controls->m_StartTrackingButton->setEnabled(false); + m_TrackingTimer->start(10); +} + +void QmitkMLBTView::OnTrackingThreadStop() +{ + m_TrackingThreadIsRunning = false; + m_Controls->m_StartTrackingButton->setEnabled(true); + + + vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData(); + mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly); + outFib->SetFiberColors(255,0,0); +// mitk::DataNode::Pointer node = mitk::DataNode::New(); + m_TractogramNode->SetData(outFib); + + tracker = NULL; + m_TrackingTimer->stop(); +} + +void QmitkMLBTView::StartTracking() +{ + if ( m_Controls->m_TrackingRawImageBox->GetSelectedNode().IsNull() ) + return; + + mitk::Image::Pointer dwi = dynamic_cast(m_Controls->m_TrackingRawImageBox->GetSelectedNode()->GetData()); + tracker = TrackerType::New(); + tracker->SetNumberOfThreads(m_Controls->m_NumberOfThreadsBox->value()); + tracker->SetInput(0, mitk::DiffusionPropertyHelper::GetItkVectorImage(dwi) ); + tracker->SetGradientDirections( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi) ); + tracker->SetB_Value( mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi) ); + tracker->SetDemoMode(m_Controls->m_DemoModeBox->isChecked()); + if (m_Controls->m_TrackingUseMaskImageBox->isChecked() && m_Controls->m_TrackingMaskImageBox->GetSelectedNode().IsNotNull()) + { + mitk::Image::Pointer mask = dynamic_cast(m_Controls->m_TrackingMaskImageBox->GetSelectedNode()->GetData()); + ItkUcharImgType::Pointer itkMask = ItkUcharImgType::New(); + mitk::CastToItkImage(mask, itkMask); + tracker->SetMaskImage(itkMask); + } + if (m_Controls->m_TrackingUseSeedImageBox->isChecked() && m_Controls->m_TrackingSeedImageBox->GetSelectedNode().IsNotNull()) + { + mitk::Image::Pointer img = dynamic_cast(m_Controls->m_TrackingSeedImageBox->GetSelectedNode()->GetData()); + ItkUcharImgType::Pointer itkImg = ItkUcharImgType::New(); + mitk::CastToItkImage(img, itkImg); + tracker->SetSeedImage(itkImg); + } + if (m_Controls->m_TrackingUseStopImageBox->isChecked() && m_Controls->m_TrackingStopImageBox->GetSelectedNode().IsNotNull()) + { + mitk::Image::Pointer img = dynamic_cast(m_Controls->m_TrackingStopImageBox->GetSelectedNode()->GetData()); + ItkUcharImgType::Pointer itkImg = ItkUcharImgType::New(); + mitk::CastToItkImage(img, itkImg); + tracker->SetStoppingRegions(itkImg); + } + tracker->SetSeedsPerVoxel(m_Controls->m_NumberOfSeedsBox->value()); + tracker->SetUseDirection(true); + tracker->SetStepSize(m_Controls->m_TrackingStepSizeBox->value()); + tracker->SetAngularThreshold(cos((float)m_Controls->m_AngularThresholdBox->value()*M_PI/180)); + tracker->SetMinTractLength(m_Controls->m_MinLengthBox->value()); + tracker->SetMaxTractLength(m_Controls->m_MaxLengthBox->value()); + + vigra::RandomForest forest = m_ForestHandler.GetForest(); + tracker->SetDecisionForest(&forest); + tracker->SetSamplingDistance(m_Controls->m_SamplingDistanceBox->value()); + tracker->SetNumberOfSamples(m_Controls->m_NumSamplesBox->value()); + tracker->Update(); +// vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData(); +// mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly); +// outFib->SetColorCoding(mitk::FiberBundle::COLORCODING_CUSTOM); +// mitk::DataNode::Pointer node = mitk::DataNode::New(); +// m_TractogramNode->SetData(outFib); +// node->SetData(outFib); +// node->SetName("MLBT Result"); +// this->GetDataStorage()->Add(node); +// mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +void QmitkMLBTView::SaveForest() +{ + QString filename = QFileDialog::getSaveFileName(0, tr("Save Forest"), QDir::currentPath()+"/forest.rf", tr("HDF5 random forest file (*.rf)") ); + + if(filename.isEmpty() || filename.isNull()) + return; + if(!filename.endsWith(".rf")) + filename += ".rf"; + + m_ForestHandler.SaveForest( filename.toStdString() ); +} + +void QmitkMLBTView::StartTrainingThread() +{ + QFuture future = QtConcurrent::run( this, &QmitkMLBTView::StartTraining ); + m_TrainingWatcher.setFuture(future); + m_Controls->m_StartTrainingButton->setEnabled(false); + m_Controls->m_SaveForestButton->setEnabled(false); + m_Controls->m_LoadForestButton->setEnabled(false); +} + +void QmitkMLBTView::OnTrainingThreadStop() +{ + m_Controls->m_StartTrainingButton->setEnabled(true); + m_Controls->m_SaveForestButton->setEnabled(true); + m_Controls->m_LoadForestButton->setEnabled(true); +} + +void QmitkMLBTView::StartTraining() +{ + m_ForestHandler.SetRawData(m_SelectedDiffImages); + m_ForestHandler.SetTractograms(m_SelectedFB); + m_ForestHandler.SetNumTrees(m_Controls->m_NumTreesBox->value()); + m_ForestHandler.SetMaxTreeDepth(m_Controls->m_MaxDepthBox->value()); + m_ForestHandler.SetGrayMatterSamplesPerVoxel(m_Controls->m_GmSamplingBox->value()); + m_ForestHandler.SetSampleFraction(m_Controls->m_SampleFractionBox->value()); + m_ForestHandler.SetStepSize(m_Controls->m_TrainingStepSizeBox->value()); + m_ForestHandler.SetUsePreviousDirection(m_Controls->m_TrackingUsePreviousDirectionBox->isChecked()); + m_ForestHandler.StartTraining(); +} + +void QmitkMLBTView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) +{ + m_MultiWidget = &stdMultiWidget; +} + + +void QmitkMLBTView::StdMultiWidgetNotAvailable() +{ + m_MultiWidget = NULL; +} + +void QmitkMLBTView::OnSelectionChanged( std::vector nodes ) +{ + if ( !this->IsVisible() ) + { + // do nothing if nobody wants to see me :-( + return; + } + + m_SelectedFB.clear(); + m_SelectedDiffImages.clear(); + m_MaskImages.clear(); + m_WhiteMatterImages.clear(); + + for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) + { + mitk::DataNode::Pointer node = *it; + if ( dynamic_cast(node->GetData()) ) + m_SelectedFB.push_back( dynamic_cast(node->GetData()) ); + else if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(node)) + m_SelectedDiffImages.push_back( dynamic_cast(node->GetData()) ); + } +} + +void QmitkMLBTView::Activated() +{ + +} + + diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkMLBTView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkMLBTView.h new file mode 100644 index 0000000000..9b260c22db --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkMLBTView.h @@ -0,0 +1,105 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY 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 "ui_QmitkMLBTViewControls.h" + +#ifndef Q_MOC_RUN +#include "mitkDataStorage.h" +#include "mitkDataStorageSelection.h" +#include +#include +#endif + +#include +#include +#include + +/*! +\brief +*/ + +// Forward Qt class declarations + + +class QmitkMLBTView : 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; + + typedef itk::Image ItkUcharImgType; + typedef itk::MLBSTrackingFilter<100> TrackerType; + + QmitkMLBTView(); + virtual ~QmitkMLBTView(); + + virtual void CreateQtPartControl(QWidget *parent); + + virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); + virtual void StdMultiWidgetNotAvailable(); + virtual void Activated(); + + protected slots: + + void StartTrackingThread(); + void OnTrackingThreadStop(); + void StartTrainingThread(); + void OnTrainingThreadStop(); + void SaveForest(); + void LoadForest(); + void BuildFibers(); + void ChangeTimerInterval(int value); + void ToggleDemoMode(int state); + void PauseTracking(); + void AbortTracking(); + +protected: + + void StartTracking(); + void StartTraining(); + + /// \brief called by QmitkFunctionality when DataManager's selection has changed + virtual void OnSelectionChanged( std::vector nodes ); + + Ui::QmitkMLBTViewControls* m_Controls; + QmitkStdMultiWidget* m_MultiWidget; + + mitk::TrackingForestHandler<> m_ForestHandler; + std::vector< mitk::Image::Pointer > m_SelectedDiffImages; + std::vector< mitk::FiberBundle::Pointer > m_SelectedFB; + std::vector< ItkUcharImgType::Pointer > m_MaskImages; + std::vector< ItkUcharImgType::Pointer > m_WhiteMatterImages; + + QFutureWatcher m_TrainingWatcher; + QFutureWatcher m_TrackingWatcher; + bool m_TrackingThreadIsRunning; + TrackerType::Pointer tracker; + QTimer* m_TrackingTimer; + mitk::DataNode::Pointer m_TractogramNode; + +private: + + }; + + + diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkMLBTViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkMLBTViewControls.ui new file mode 100644 index 0000000000..cf19c52391 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkMLBTViewControls.ui @@ -0,0 +1,620 @@ + + + QmitkMLBTViewControls + + + + 0 + 0 + 359 + 1127 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 1 + + + + + 0 + 0 + 359 + 1065 + + + + Training + + + + + + Load Forest + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Step size: + + + + + + + Num. Trees: + + + + + + + Max. Depth: + + + + + + + 3 + + + -1.000000000000000 + + + 999.000000000000000 + + + 0.100000000000000 + + + -1.000000000000000 + + + + + + + 1 + + + 999999999 + + + + + + + Sample Fraction: + + + + + + + 1 + + + 999999999 + + + 10 + + + + + + + 1 + + + 999999999 + + + 10 + + + + + + + 3 + + + 1.000000000000000 + + + 0.100000000000000 + + + 1.000000000000000 + + + + + + + GM Sampling Points: + + + + + + + Use Previous Direction: + + + + + + + + + + true + + + + + + + + + + Start Training + + + + + + + Save Forest + + + + + + + + + 0 + 0 + 359 + 1065 + + + + Tractography + + + + + + Use Previous Direction + + + true + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + ... + + + + :/org.mbi.gui.qt.diffusionimaginginternal/resources/Media-playback-pause.svg:/org.mbi.gui.qt.diffusionimaginginternal/resources/Media-playback-pause.svg + + + + + + + ... + + + + :/org.mbi.gui.qt.diffusionimaginginternal/resources/Media-playback-start.svg:/org.mbi.gui.qt.diffusionimaginginternal/resources/Media-playback-start.svg + + + + + + + ... + + + + :/org.mbi.gui.qt.diffusionimaginginternal/resources/Media-playback-stop.svg:/org.mbi.gui.qt.diffusionimaginginternal/resources/Media-playback-stop.svg + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Demo Mode + + + + + + + 1 + + + 1000 + + + 10 + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0.500000000000000 + + + + + + + Max. Length + + + + + + + 999999999 + + + 50 + + + + + + + Num. Samples: + + + + + + + Input DWI: + + + + + + + Step Size: + + + + + + + Sampling Distance: + + + + + + + 1 + + + 999 + + + + + + + Min. Length + + + + + + + 0.100000000000000 + + + 0.500000000000000 + + + + + + + 999999999.000000000000000 + + + 1.000000000000000 + + + 20.000000000000000 + + + + + + + Angular Threshold: + + + + + + + Num. Seeds: + + + + + + + 999999999.000000000000000 + + + 1.000000000000000 + + + 400.000000000000000 + + + + + + + 1 + + + 90.000000000000000 + + + 45.000000000000000 + + + + + + + + + + Num. Threads: + + + + + + + 1 + + + 30 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Use Stop Image: + + + + + + + Use Seed Image: + + + false + + + + + + + Use Mask Image: + + + true + + + + + + + + + + + + + + + + + + + + + + + + QmitkDataStorageComboBox + QComboBox +
QmitkDataStorageComboBox.h
+
+
+ + + + +
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp index 502929a7bf..f8c0de6e51 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp @@ -1,106 +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 "mitkPluginActivator.h" #include #include "src/internal/Perspectives/QmitkDiffusionImagingAppPerspective.h" #include "src/internal/Perspectives/QmitkDIAppIVIMPerspective.h" #include "src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.h" #include "src/internal/Perspectives/QmitkGibbsTractographyPerspective.h" #include "src/internal/Perspectives/QmitkStreamlineTractographyPerspective.h" #include "src/internal/Perspectives/QmitkProbabilisticTractographyPerspective.h" #include "src/internal/Perspectives/QmitkFiberProcessingPerspective.h" #include "src/internal/Perspectives/QmitkDiffusionDefaultPerspective.h" #include "src/internal/QmitkQBallReconstructionView.h" #include "src/internal/QmitkPreprocessingView.h" #include "src/internal/QmitkDiffusionDicomImportView.h" #include "src/internal/QmitkDiffusionQuantificationView.h" #include "src/internal/QmitkTensorReconstructionView.h" #include "src/internal/QmitkControlVisualizationPropertiesView.h" #include "src/internal/QmitkODFDetailsView.h" #include "src/internal/QmitkGibbsTrackingView.h" #include "src/internal/QmitkStochasticFiberTrackingView.h" #include "src/internal/QmitkFiberQuantificationView.h" #include "src/internal/QmitkPartialVolumeAnalysisView.h" #include "src/internal/QmitkIVIMView.h" #include "src/internal/QmitkTractbasedSpatialStatisticsView.h" #include "src/internal/QmitkTbssSkeletonizationView.h" #include "src/internal/QmitkStreamlineTrackingView.h" #include "src/internal/Connectomics/QmitkConnectomicsDataView.h" #include "src/internal/Connectomics/QmitkConnectomicsNetworkOperationsView.h" #include "src/internal/Connectomics/QmitkConnectomicsStatisticsView.h" #include "src/internal/Connectomics/QmitkRandomParcellationView.h" #include "src/internal/QmitkOdfMaximaExtractionView.h" #include "src/internal/QmitkFiberfoxView.h" #include "src/internal/QmitkFiberProcessingView.h" #include "src/internal/QmitkFieldmapGeneratorView.h" #include "src/internal/QmitkDiffusionRegistrationView.h" #include "src/internal/QmitkDenoisingView.h" +#include "src/internal/QmitkMLBTView.h" namespace mitk { void PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionImagingAppPerspective, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkGibbsTractographyPerspective, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkStreamlineTractographyPerspective, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkProbabilisticTractographyPerspective, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppSyntheticDataGenerationPerspective, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppIVIMPerspective, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberProcessingPerspective, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionDefaultPerspective, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkQBallReconstructionView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkPreprocessingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionDicomImport, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionQuantificationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkTensorReconstructionView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkControlVisualizationPropertiesView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkODFDetailsView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkGibbsTrackingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkStochasticFiberTrackingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberQuantificationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkPartialVolumeAnalysisView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkIVIMView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkTractbasedSpatialStatisticsView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkTbssSkeletonizationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkConnectomicsDataView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkConnectomicsNetworkOperationsView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkConnectomicsStatisticsView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkStreamlineTrackingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkOdfMaximaExtractionView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberfoxView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberProcessingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkFieldmapGeneratorView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionRegistrationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDenoisingView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkRandomParcellationView, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkMLBTView, context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) Q_EXPORT_PLUGIN2(org_mitk_gui_qt_diffusionimaging, mitk::PluginActivator) #endif