diff --git a/Applications/PluginGenerator/CMakeLists.txt b/Applications/PluginGenerator/CMakeLists.txt index 81765479ad..aebbe5def5 100644 --- a/Applications/PluginGenerator/CMakeLists.txt +++ b/Applications/PluginGenerator/CMakeLists.txt @@ -1,78 +1,73 @@ if (${CMAKE_SOURCE_DIR} EQUAL ${PROJECT_SOURCE_DIR}) cmake_minimum_required(VERSION 3.14.5 FATAL_ERROR) endif() project(MitkPluginGenerator) set(VERSION_MAJOR 1) set(VERSION_MINOR 5) set(VERSION_PATCH 0) set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) set(standalone_build 1) else() set(standalone_build 0) endif() #----------------------------------------------------------------------------- # Prerequisites #----------------------------------------------------------------------------- find_package(Qt5Core REQUIRED) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/PluginGeneratorConfig.h.in" "${CMAKE_CURRENT_BINARY_DIR}/PluginGeneratorConfig.h" @ONLY) include_directories("${CMAKE_CURRENT_BINARY_DIR}") #----------------------------------------------------------------------------- # Executable #----------------------------------------------------------------------------- set(src_files PluginGenerator.cpp ctkCommandLineParser.cpp ) qt5_wrap_cpp(src_files ctkCommandLineParser.h OPTIONS -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) qt5_add_resources(src_files plugin_template.qrc project_template.qrc) set(exec_target ${PROJECT_NAME}) add_executable(${exec_target} ${src_files}) -set_property(TARGET ${exec_target} PROPERTY FOLDER "${MITK_ROOT_FOLDER}/Plugins/PluginGenerator") +set_property(TARGET ${exec_target} PROPERTY FOLDER "${MITK_ROOT_FOLDER}/Applications/PluginGenerator") target_link_libraries(${exec_target} Qt5::Core) -if(NOT standalone_build) - # subproject support - add_dependencies(MITK-CoreUI ${exec_target}) -endif() - #----------------------------------------------------------------------------- # Win32 Convenience #----------------------------------------------------------------------------- if(WIN32 AND NOT standalone_build) file(TO_NATIVE_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}" native_runtime_dir) add_custom_target(NewPlugin start "MITK PluginGenerator" /D "${native_runtime_dir}" cmd /K ${exec_target}.exe -h DEPENDS ${exec_target}) - set_property(TARGET NewPlugin PROPERTY FOLDER "${MITK_ROOT_FOLDER}/Plugins/PluginGenerator") + set_property(TARGET NewPlugin PROPERTY FOLDER "${MITK_ROOT_FOLDER}/Applications/PluginGenerator") endif() #----------------------------------------------------------------------------- # Testing #----------------------------------------------------------------------------- if(NOT standalone_build) # Test the plugin generator include(mitkTestPluginGenerator) endif() #----------------------------------------------------------------------------- # Packaging support #----------------------------------------------------------------------------- if(standalone_build) include(SetupPackaging.cmake) endif() diff --git a/Applications/PluginGenerator/ProjectTemplate/CMake/CTestCustom.cmake.in b/Applications/PluginGenerator/ProjectTemplate/CMake/CTestCustom.cmake.in deleted file mode 100644 index fb9b4d60f6..0000000000 --- a/Applications/PluginGenerator/ProjectTemplate/CMake/CTestCustom.cmake.in +++ /dev/null @@ -1,80 +0,0 @@ -set(CTEST_CUSTOM_COVERAGE_EXCLUDE - ${CTEST_CUSTOM_COVERAGE_EXCLUDE} - - # Exclude try_compile sources from coverage results: - "/CMakeFiles/CMakeTmp/" - - # Exclude files generated by the moc pre-compiler - ".*/moc_.*" - - # Exclude files generated by the uic pre-compiler - ".*/ui_.*" - - # Exclude files from the Testing directories - ".*/Testing/.*" - - ".*/CMakeExternals/.*" - - ) - -# The following tests should not be run under valgrind -set(CTEST_CUSTOM_MEMCHECK_IGNORE - - ) - -set(CTEST_CUSTOM_ERROR_MATCH - ${CTEST_CUSTOM_ERROR_MATCH} - "CMake Error[ :]" - ) - -set(CTEST_CUSTOM_WARNING_MATCH - ${CTEST_CUSTOM_WARNING_MATCH} - "CMake Warning[ :]" - ) - -set(CTEST_CUSTOM_WARNING_EXCEPTION - ${CTEST_CUSTOM_WARNING_EXCEPTION} - - # kwstyle suppressions - "[Kk][Ww][Ss]tyle.*kws.*cxx" - "[Kk][Ww][Ss]tyle.*kws.*h" - "[Kk][Ww][Ss]tyle.*metaCommand.*cxx" - - # vtk suppressions - "vtkfreetype" - "Utilities.vtktiff" - "VTK.*IO.vtkMySQLQuery.cxx" - "VTK.*Utilities.vtkexodus2" - "VTK.*Utilities.vtklibproj" - "VTK.*Utilities.vtksqlite" - "VTK.*Utilities.vtkmetaio" - "VTK.*warn_unused_result" - "VTK.*Filtering.*cxx" - "VTK.*IO.*cxx" - "VTK.*Infovis.*cxx" - - # qt suppressions from vtk... - # Some VTK dashboards include building bits of Qt which produce lots of - # the following warnings when built with the MS compilers. Qt guys should - # fix their code. Until they do, keep the Qt chatter off the VTK dashboard - # results: - "include.[Qq]t([Cc]ore|[Gg]ui).*warning C4127: conditional expression is constant" - "[Qq]t.*h.*warning.*declaration of .* shadows a member of .this" - "[Qq]t.*h.*warning.*(copy constructor|assignment operator) could not be generated" - - # Suppress warning caused when QT 'foreach' loops are combined - ".*warning: declaration of '_container_' shadows a previous local" - - # PythonQt suppressions - "PythonQt.*src.*PythonQt.*(cpp|h)" - "include.PythonQt.PythonQt.*h" - - # Suppressing warnings about duplicate libraries in Darwin - # At some point this may be addressed by CMake feature request: - # http://public.kitware.com/Bug/view.php?id=10179 - "ld: warning: duplicate dylib.*" - - # Visual studio spurious warnings... - "The following environment variables were not found" - - ) diff --git a/Applications/PluginGenerator/ProjectTemplate/CMakeLists.txt b/Applications/PluginGenerator/ProjectTemplate/CMakeLists.txt index 887f5c0d30..1618e04c80 100644 --- a/Applications/PluginGenerator/ProjectTemplate/CMakeLists.txt +++ b/Applications/PluginGenerator/ProjectTemplate/CMakeLists.txt @@ -1,339 +1,329 @@ cmake_minimum_required(VERSION 3.14.5 FATAL_ERROR) # Change project and application name to your own set(MY_PROJECT_NAME $(project-name)) set(MY_APP_NAME $(project-app-name)) #----------------------------------------------------------------------------- # Set the language standard (MITK requires C++14) #----------------------------------------------------------------------------- set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED 1) set(CMAKE_CXX_EXTENSIONS 0) #----------------------------------------------------------------------------- # Set a default build type if none was specified #----------------------------------------------------------------------------- if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'Debug' as none was specified.") set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() #----------------------------------------------------------------------------- # Superbuild Option - Enabled by default #----------------------------------------------------------------------------- option(${MY_PROJECT_NAME}_USE_SUPERBUILD "Build ${MY_PROJECT_NAME} and the projects it depends on via SuperBuild.cmake." ON) if(${MY_PROJECT_NAME}_USE_SUPERBUILD) project(${MY_PROJECT_NAME}-superbuild) set(${MY_PROJECT_NAME}_SOURCE_DIR ${PROJECT_SOURCE_DIR}) set(${MY_PROJECT_NAME}_BINARY_DIR ${PROJECT_BINARY_DIR}) else() project(${MY_PROJECT_NAME}) endif() #----------------------------------------------------------------------------- # See http://cmake.org/cmake/help/cmake-2-8-docs.html#section_Policies for details #----------------------------------------------------------------------------- set(project_policies CMP0001 # NEW: CMAKE_BACKWARDS_COMPATIBILITY should no longer be used. CMP0002 # NEW: Logical target names must be globally unique. CMP0003 # NEW: Libraries linked via full path no longer produce linker search paths. CMP0004 # NEW: Libraries linked may NOT have leading or trailing whitespace. CMP0005 # NEW: Preprocessor definition values are now escaped automatically. CMP0006 # NEW: Installing MACOSX_BUNDLE targets requires a BUNDLE DESTINATION. CMP0007 # NEW: List command no longer ignores empty elements. CMP0008 # NEW: Libraries linked by full-path must have a valid library file name. CMP0009 # NEW: FILE GLOB_RECURSE calls should not follow symlinks by default. CMP0010 # NEW: Bad variable reference syntax is an error. CMP0011 # NEW: Included scripts do automatic cmake_policy PUSH and POP. CMP0012 # NEW: if() recognizes numbers and boolean constants. CMP0013 # NEW: Duplicate binary directories are not allowed. CMP0014 # NEW: Input directories must have CMakeLists.txt CMP0020 # NEW: Automatically link Qt executables to qtmain target on Windows. CMP0028 # NEW: Double colon in target name means ALIAS or IMPORTED target. ) foreach(policy ${project_policies}) if(POLICY ${policy}) cmake_policy(SET ${policy} NEW) endif() endforeach() #----------------------------------------------------------------------------- # Update CMake module path #------------------------------------------------------------------------------ set(CMAKE_MODULE_PATH ${${MY_PROJECT_NAME}_SOURCE_DIR}/CMake ${CMAKE_MODULE_PATH} ) #----------------------------------------------------------------------------- # CMake Function(s) and Macro(s) #----------------------------------------------------------------------------- +include(CTest) include(MacroEmptyExternalProject) #----------------------------------------------------------------------------- # Output directories. #----------------------------------------------------------------------------- foreach(type LIBRARY RUNTIME ARCHIVE) set(output_dir ${${MY_PROJECT_NAME}_BINARY_DIR}/bin) set(CMAKE_${type}_OUTPUT_DIRECTORY ${output_dir} CACHE INTERNAL "Single output directory for building all libraries.") mark_as_advanced(CMAKE_${type}_OUTPUT_DIRECTORY) endforeach() #----------------------------------------------------------------------------- # Additional Options (also shown during superbuild) #----------------------------------------------------------------------------- option(BUILD_SHARED_LIBS "Build ${MY_PROJECT_NAME} with shared libraries" ON) option(WITH_COVERAGE "Enable/Disable coverage" OFF) option(BUILD_TESTING "Test the project" ON) option(${MY_PROJECT_NAME}_BUILD_ALL_PLUGINS "Build all ${MY_PROJECT_NAME} plugins" OFF) mark_as_advanced(${MY_PROJECT_NAME}_INSTALL_RPATH_RELATIVE ${MY_PROJECT_NAME}_BUILD_ALL_PLUGINS ) #----------------------------------------------------------------------------- # Superbuild script #----------------------------------------------------------------------------- if(${MY_PROJECT_NAME}_USE_SUPERBUILD) include("${CMAKE_CURRENT_SOURCE_DIR}/SuperBuild.cmake") return() endif() #***************************************************************************** #**************************** END OF SUPERBUILD **************************** #***************************************************************************** #----------------------------------------------------------------------------- # Prerequesites #----------------------------------------------------------------------------- set(${PROJECT_NAME}_MODULES_PACKAGE_DEPENDS_DIR "${PROJECT_SOURCE_DIR}/CMake/PackageDepends") set(MODULES_PACKAGE_DEPENDS_DIRS ${${PROJECT_NAME}_MODULES_PACKAGE_DEPENDS_DIR}) find_package(MITK 2018.04.99 REQUIRED) if(COMMAND mitkFunctionCheckMitkCompatibility) mitkFunctionCheckMitkCompatibility(VERSIONS MITK_VERSION_PLUGIN_SYSTEM 1 REQUIRED) else() message(SEND_ERROR "Your MITK version is too old. Please use Git hash b86bf28 or newer") endif() link_directories(${MITK_LINK_DIRECTORIES}) #----------------------------------------------------------------------------- # CMake Function(s) and Macro(s) #----------------------------------------------------------------------------- set(CMAKE_MODULE_PATH ${MITK_SOURCE_DIR}/CMake ${CMAKE_MODULE_PATH} ) include(mitkFunctionCheckCompilerFlags) include(mitkFunctionGetGccVersion) include(mitkFunctionGetVersion) #----------------------------------------------------------------------------- # Set project specific options and variables (NOT available during superbuild) #----------------------------------------------------------------------------- set(${PROJECT_NAME}_VERSION_MAJOR "0") set(${PROJECT_NAME}_VERSION_MINOR "1") set(${PROJECT_NAME}_VERSION_PATCH "1") set(${PROJECT_NAME}_VERSION_STRING "${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH}") # Ask the user if a console window should be shown with the applications option(${PROJECT_NAME}_SHOW_CONSOLE_WINDOW "Use this to enable or disable the console window when starting GUI Applications" ON) mark_as_advanced(${PROJECT_NAME}_SHOW_CONSOLE_WINDOW) if(NOT UNIX) set(MITK_WIN32_FORCE_STATIC "STATIC") endif() #----------------------------------------------------------------------------- # Get project version info #----------------------------------------------------------------------------- mitkFunctionGetVersion(${PROJECT_SOURCE_DIR} ${PROJECT_NAME}) #----------------------------------------------------------------------------- # Installation preparation # # These should be set before any MITK install macros are used #----------------------------------------------------------------------------- # on macOS all CTK plugins get copied into every # application bundle (.app directory) specified here set(MACOSX_BUNDLE_NAMES) if(APPLE) list(APPEND MACOSX_BUNDLE_NAMES ${MY_APP_NAME}) endif(APPLE) #----------------------------------------------------------------------------- # Set symbol visibility Flags #----------------------------------------------------------------------------- if(CMAKE_COMPILER_IS_GNUCXX) # The MITK module build system does not yet support default hidden visibility set(VISIBILITY_CXX_FLAGS ) # "-fvisibility=hidden -fvisibility-inlines-hidden") endif() #----------------------------------------------------------------------------- # Set coverage Flags #----------------------------------------------------------------------------- if(WITH_COVERAGE) if(CMAKE_COMPILER_IS_GNUCXX) set(coverage_flags "-g -fprofile-arcs -ftest-coverage -O0 -DNDEBUG") set(COVERAGE_CXX_FLAGS ${coverage_flags}) set(COVERAGE_C_FLAGS ${coverage_flags}) endif() endif() #----------------------------------------------------------------------------- # Project C/CXX Flags #----------------------------------------------------------------------------- set(${PROJECT_NAME}_C_FLAGS "${MITK_C_FLAGS} ${COVERAGE_C_FLAGS}") set(${PROJECT_NAME}_C_FLAGS_DEBUG ${MITK_C_FLAGS_DEBUG}) set(${PROJECT_NAME}_C_FLAGS_RELEASE ${MITK_C_FLAGS_RELEASE}) set(${PROJECT_NAME}_CXX_FLAGS "${MITK_CXX_FLAGS} ${VISIBILITY_CXX_FLAGS} ${COVERAGE_CXX_FLAGS}") set(${PROJECT_NAME}_CXX_FLAGS_DEBUG ${MITK_CXX_FLAGS_DEBUG}) set(${PROJECT_NAME}_CXX_FLAGS_RELEASE ${MITK_CXX_FLAGS_RELEASE}) set(${PROJECT_NAME}_EXE_LINKER_FLAGS ${MITK_EXE_LINKER_FLAGS}) set(${PROJECT_NAME}_SHARED_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS}) set(${PROJECT_NAME}_MODULE_LINKER_FLAGS ${MITK_MODULE_LINKER_FLAGS}) #----------------------------------------------------------------------------- # Set C/CXX Flags #----------------------------------------------------------------------------- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${${PROJECT_NAME}_C_FLAGS}") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${${PROJECT_NAME}_C_FLAGS_DEBUG}") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${${PROJECT_NAME}_C_FLAGS_RELEASE}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${${PROJECT_NAME}_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${${PROJECT_NAME}_CXX_FLAGS_DEBUG}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${${PROJECT_NAME}_CXX_FLAGS_RELEASE}") set(CMAKE_EXE_LINKER_FLAGS ${${PROJECT_NAME}_EXE_LINKER_FLAGS}) set(CMAKE_SHARED_LINKER_FLAGS ${${PROJECT_NAME}_SHARED_LINKER_FLAGS}) set(CMAKE_MODULE_LINKER_FLAGS ${${PROJECT_NAME}_MODULE_LINKER_FLAGS}) #----------------------------------------------------------------------------- # Testing #----------------------------------------------------------------------------- if(BUILD_TESTING) - enable_testing() - include(CTest) - mark_as_advanced(TCL_TCLSH DART_ROOT) - - # Setup file for setting custom ctest vars - configure_file( - CMake/CTestCustom.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake - @ONLY - ) - # Configuration for the CMake-generated test driver set(CMAKE_TESTDRIVER_EXTRA_INCLUDES "#include ") set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN " try {") - set(CMAKE_TESTDRIVER_AFTER_TESTMAIN " } - catch ( const std::exception & excp ) - { - fprintf(stderr,\"%s\\n\",excp.what()); + set(CMAKE_TESTDRIVER_AFTER_TESTMAIN " + } + catch (const std::exception& e) + { + fprintf(stderr, \"%s\\n\", e.what()); return EXIT_FAILURE; - } - catch( ... ) - { + } + catch (...) + { printf(\"Exception caught in the test driver\\n\"); return EXIT_FAILURE; - } - ") + }") endif() #----------------------------------------------------------------------------- # ${MY_PROJECT_NAME}_SUPERBUILD_BINARY_DIR #----------------------------------------------------------------------------- # If ${MY_PROJECT_NAME}_SUPERBUILD_BINARY_DIR isn't defined, it means this project is # *NOT* build using Superbuild. In that specific case, ${MY_PROJECT_NAME}_SUPERBUILD_BINARY_DIR # should default to PROJECT_BINARY_DIR if(NOT DEFINED ${PROJECT_NAME}_SUPERBUILD_BINARY_DIR) set(${PROJECT_NAME}_SUPERBUILD_BINARY_DIR ${PROJECT_BINARY_DIR}) endif() #----------------------------------------------------------------------------- # MITK modules #----------------------------------------------------------------------------- #add_subdirectory(Modules) #----------------------------------------------------------------------------- # CTK plugins #----------------------------------------------------------------------------- # The CMake code in this section *must* be in the top-level CMakeLists.txt file macro(GetMyTargetLibraries all_target_libraries varname) set(re_ctkplugin "^$(project-plugin-base)_[a-zA-Z0-9_]+$") set(_tmp_list) list(APPEND _tmp_list ${all_target_libraries}) ctkMacroListFilter(_tmp_list re_ctkplugin OUTPUT_VARIABLE ${varname}) endmacro() include(${CMAKE_CURRENT_SOURCE_DIR}/Plugins/Plugins.cmake) ctkMacroSetupPlugins(${PROJECT_PLUGINS} BUILD_OPTION_PREFIX ${MY_PROJECT_NAME}_ BUILD_ALL ${${MY_PROJECT_NAME}_BUILD_ALL_PLUGINS}) #----------------------------------------------------------------------------- # Add subdirectories #----------------------------------------------------------------------------- add_subdirectory(Apps/$(project-app-name)) #----------------------------------------------------------------------------- # Installation #----------------------------------------------------------------------------- # set MITK cpack variables include(mitkSetupCPack) # Customize CPack variables for this project include(CPackSetup) list(APPEND CPACK_CREATE_DESKTOP_LINKS "${MY_APP_NAME}") configure_file(${MITK_SOURCE_DIR}/MITKCPackOptions.cmake.in ${PROJECT_BINARY_DIR}/${PROJECT_NAME}CPackOptions.cmake @ONLY) set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}CPackOptions.cmake") # include CPack model once all variables are set include(CPack) # Additional installation rules include(mitkInstallRules) #----------------------------------------------------------------------------- # Last configuration steps #----------------------------------------------------------------------------- diff --git a/Applications/PluginGenerator/project_template.qrc b/Applications/PluginGenerator/project_template.qrc index 85b8e2c88a..0a59ca2311 100644 --- a/Applications/PluginGenerator/project_template.qrc +++ b/Applications/PluginGenerator/project_template.qrc @@ -1,17 +1,16 @@ ProjectTemplate/CMakeLists.txt ProjectTemplate/LICENSE ProjectTemplate/SuperBuild.cmake ProjectTemplate/Apps/TemplateApp/CMakeLists.txt ProjectTemplate/Apps/TemplateApp/startTemplateApp.bat.in ProjectTemplate/Apps/TemplateApp/TemplateApp.cpp ProjectTemplate/Apps/TemplateApp/TemplateApp.ini ProjectTemplate/CMake/CPackSetup.cmake - ProjectTemplate/CMake/CTestCustom.cmake.in ProjectTemplate/CMake/MacroEmptyExternalProject.cmake ProjectTemplate/CMakeExternals/MITK.cmake ProjectTemplate/Plugins/Plugins.cmake LICENSE diff --git a/CMake/CTestCustom.cmake.in b/CMake/CTestCustom.cmake.in deleted file mode 100644 index 09fb1b8137..0000000000 --- a/CMake/CTestCustom.cmake.in +++ /dev/null @@ -1,83 +0,0 @@ -set(CTEST_CUSTOM_COVERAGE_EXCLUDE - ${CTEST_CUSTOM_COVERAGE_EXCLUDE} - - # Exclude try_compile sources from coverage results: - "/CMakeFiles/CMakeTmp/" - - # Exclude files generated by the moc pre-compiler - ".*/moc_.*" - - # Exclude files generated by the uic pre-compiler - ".*/ui_.*" - - # Exclude files from the Testing directories - ".*/Testing/.*" - - ".*/CMakeExternals/.*" - - ) - -# The following tests should not be run under valgrind -set(CTEST_CUSTOM_MEMCHECK_IGNORE - - ) - -set(CTEST_CUSTOM_ERROR_MATCH - ${CTEST_CUSTOM_ERROR_MATCH} - "CMake Error[ :]" - ) - -set(CTEST_CUSTOM_WARNING_MATCH - ${CTEST_CUSTOM_WARNING_MATCH} - "CMake Warning[ :]" - ) - -set(CTEST_CUSTOM_WARNING_EXCEPTION - ${CTEST_CUSTOM_WARNING_EXCEPTION} - - # MITK Utilities - "Utilities/Poco/" - - # kwstyle suppressions - "[Kk][Ww][Ss]tyle.*kws.*cxx" - "[Kk][Ww][Ss]tyle.*kws.*h" - "[Kk][Ww][Ss]tyle.*metaCommand.*cxx" - - # vtk suppressions - "vtkfreetype" - "Utilities.vtktiff" - "VTK.*IO.vtkMySQLQuery.cxx" - "VTK.*Utilities.vtkexodus2" - "VTK.*Utilities.vtklibproj" - "VTK.*Utilities.vtksqlite" - "VTK.*Utilities.vtkmetaio" - "VTK.*warn_unused_result" - "VTK.*Filtering.*cxx" - "VTK.*IO.*cxx" - "VTK.*Infovis.*cxx" - - # qt suppressions from vtk... - # Some VTK dashboards include building bits of Qt which produce lots of - # the following warnings when built with the MS compilers. Qt guys should - # fix their code. Until they do, keep the Qt chatter off the VTK dashboard - # results: - "include.[Qq]t([Cc]ore|[Gg]ui).*warning C4127: conditional expression is constant" - "[Qq]t.*h.*warning.*declaration of .* shadows a member of .this" - "[Qq]t.*h.*warning.*(copy constructor|assignment operator) could not be generated" - - # Suppress warning caused when QT 'foreach' loops are combined - ".*warning: declaration of '_container_' shadows a previous local" - - # PythonQt suppressions - "PythonQt.*src.*PythonQt.*(cpp|h)" - "include.PythonQt.PythonQt.*h" - - # Suppressing warnings about duplicate libraries in Darwin - # At some point this may be addressed by CMake feature request: - # http://public.kitware.com/Bug/view.php?id=10179 - "ld: warning: duplicate dylib.*" - - # Visual studio spurious warnings... - "The following environment variables were not found" - - ) diff --git a/CMake/MITKDashboardDriverScript.cmake b/CMake/MITKDashboardDriverScript.cmake deleted file mode 100644 index 08f10cd767..0000000000 --- a/CMake/MITKDashboardDriverScript.cmake +++ /dev/null @@ -1,529 +0,0 @@ - -# -# Included from a dashboard script, this cmake file will drive the configure and build -# steps of MITK -# - -#----------------------------------------------------------------------------- -# The following variable are expected to be define in the top-level script: -set(expected_variables - CTEST_NOTES_FILES - CTEST_SITE - CTEST_DASHBOARD_ROOT - CTEST_CMAKE_COMMAND - CTEST_CMAKE_GENERATOR - WITH_MEMCHECK - WITH_COVERAGE - WITH_DOCUMENTATION - CTEST_BUILD_CONFIGURATION - CTEST_TEST_TIMEOUT - CTEST_BUILD_FLAGS - TEST_TO_EXCLUDE_REGEX - CTEST_SOURCE_DIRECTORY - CTEST_BINARY_DIRECTORY - CTEST_BUILD_NAME - SCRIPT_MODE - CTEST_COVERAGE_COMMAND - CTEST_MEMORYCHECK_COMMAND - CTEST_GIT_COMMAND - PROJECT_BUILD_DIR - ) - -foreach(var ${expected_variables}) - if(NOT DEFINED ${var}) - message(FATAL_ERROR "Variable ${var} should be defined in top-level script !") - endif() -endforeach() - -string(REPLACE " " "%20" _build_name_escaped "${CTEST_BUILD_NAME}") - -# Check if "mbits" is reachable -file(DOWNLOAD "http://mbits" "${CTEST_SCRIPT_DIRECTORY}/mbits.html" TIMEOUT 2 STATUS _status) -list(GET _status 0 _status_code) -if(_status_code EQUAL 0) # successful completion - set(MBITS_AVAILABLE 1) -else() - set(MBITS_AVAILABLE 0) -endif() - -# -# Site specific options -# -if(NOT CDASH_ADMIN_URL_PREFIX AND MBITS_AVAILABLE) - set(CDASH_ADMIN_URL_PREFIX "http://mbits") -endif() - -if(NOT DEFINED GIT_BRANCH OR GIT_BRANCH STREQUAL "") - set(GIT_BRANCH "") -else() - set(GIT_BRANCH "-b ${GIT_BRANCH}") -endif() - -# Should binary directory be cleaned? -set(empty_binary_directory FALSE) - -# Attempt to build and test also if 'ctest_update' returned an error -set(initial_force_build FALSE) - -# Set model options -set(model "") -if(SCRIPT_MODE STREQUAL "experimental") - set(empty_binary_directory FALSE) - set(initial_force_build TRUE) - set(model Experimental) -elseif(SCRIPT_MODE STREQUAL "continuous") - set(empty_binary_directory FALSE) - set(initial_force_build FALSE) - set(model Continuous) -elseif(SCRIPT_MODE STREQUAL "nightly") - set(empty_binary_directory TRUE) - set(initial_force_build TRUE) - set(model Nightly) -else() - message(FATAL_ERROR "Unknown script mode: '${SCRIPT_MODE}'. Script mode should be either 'experimental', 'continuous' or 'nightly'") -endif() - -#message("script_mode:${SCRIPT_MODE}") -#message("model:${model}") -#message("empty_binary_directory:${empty_binary_directory}") -#message("force_build:${initial_force_build}") - -set(CTEST_CONFIGURATION_TYPE ${CTEST_BUILD_CONFIGURATION}) - -if(empty_binary_directory) - message("Clean \"${CTEST_BINARY_DIRECTORY}\"") - ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY}) -endif() - -if(NOT DEFINED CTEST_CHECKOUT_DIR) - set(CTEST_CHECKOUT_DIR ${CTEST_SOURCE_DIRECTORY}) -endif() - -if(NOT EXISTS "${CTEST_CHECKOUT_DIR}") - set(CTEST_CHECKOUT_COMMAND "\"${CTEST_GIT_COMMAND}\" clone ${GIT_BRANCH} ${GIT_REPOSITORY} \"${CTEST_CHECKOUT_DIR}\"") -endif() - -set(CTEST_UPDATE_TYPE "git") -set(CTEST_UPDATE_COMMAND "${CTEST_GIT_COMMAND}") - -#---------------------------------------------------------------------- -# Utility macros -#---------------------------------------------------------------------- - -function(func_build_target target build_dir) - set(CTEST_BUILD_TARGET ${target}) - ctest_build(BUILD "${build_dir}" APPEND - RETURN_VALUE res - NUMBER_ERRORS num_errors - NUMBER_WARNINGS num_warnings) - ctest_submit(PARTS Build RETRY_DELAY 3 RETRY_COUNT 3) - - if(num_errors) - math(EXPR build_errors "${build_errors} + ${num_errors}") - set(build_errors ${build_errors} PARENT_SCOPE) - endif() - if(num_warnings) - math(EXPR build_warnings "${build_warnings} + ${num_warnings}") - set(build_warnings ${build_warnings} PARENT_SCOPE) - endif() -endfunction() - -function(func_test label build_dir) - if(NOT TESTING_PARALLEL_LEVEL) - set(TESTING_PARALLEL_LEVEL 8) - endif() - - if(label MATCHES "Unlabeled") - set(_include_label EXCLUDE_LABEL .*) - else() - set(_include_label INCLUDE_LABEL ${label}) - endif() - - ctest_test(BUILD "${build_dir}" - ${_include_label} - PARALLEL_LEVEL ${TESTING_PARALLEL_LEVEL} - EXCLUDE ${TEST_TO_EXCLUDE_REGEX} - RETURN_VALUE res - ) - ctest_submit(PARTS Test RETRY_DELAY 3 RETRY_COUNT 3) - - if(res) - math(EXPR test_errors "${test_errors} + 1") - set(test_errors ${test_errors} PARENT_SCOPE) - endif() - - if(ARG3) - set(WITH_COVERAGE ${ARG3}) - endif() - if(ARG4) - set(WITH_MEMCHECK ${ARG4}) - endif() - - if(WITH_COVERAGE AND CTEST_COVERAGE_COMMAND) - message("----------- [ Coverage ${label} ] -----------") - ctest_coverage(BUILD "${build_dir}" LABELS ${label}) - ctest_submit(PARTS Coverage RETRY_DELAY 3 RETRY_COUNT 3) - endif() - - if(WITH_MEMCHECK AND CTEST_MEMORYCHECK_COMMAND) - if(NOT CTEST_MEMORYCHECK_SUPPRESSIONS_FILE) - if(EXISTS "${CTEST_SOURCE_DIRECTORY}/CMake/valgrind.supp") - set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE "${CTEST_SOURCE_DIRECTORY}/CMake/valgrind.supp") - endif() - endif() - if(NOT CTEST_MEMORYCHECK_COMMAND_OPTIONS) - set(CTEST_MEMORYCHECK_COMMAND_OPTIONS "-q --tool=memcheck --leak-check=yes --show-reachable=no --show-possibly-lost=no --workaround-gcc296-bugs=yes --num-callers=50") - endif() - ctest_memcheck(BUILD "${build_dir}" INCLUDE_LABEL ${label}) - ctest_submit(PARTS MemCheck RETRY_DELAY 3 RETRY_COUNT 3) - endif() - -endfunction() - -macro(finalize_submission) - - # Note should be at the end - ctest_submit(PARTS Notes Done RETRY_DELAY 3 RETRY_COUNT 3) - - # Send status to the "CDash Web Admin" - if(CDASH_ADMIN_URL_PREFIX) - set(cdash_admin_url "${CDASH_ADMIN_URL_PREFIX}/cdashadmin-web/index.php?pw=4da12ca9c06d46d3171d7f73974c900f") - string(REGEX REPLACE ".*\\?project=(.*)&?" "\\1" _ctest_project "${CTEST_DROP_LOCATION}") - file(DOWNLOAD - "${cdash_admin_url}&action=submit&name=${_build_name_escaped}&hasTestErrors=${test_errors}&hasBuildErrors=${build_errors}&hasBuildWarnings=${build_warnings}&ctestDropSite=${CTEST_DROP_SITE}&ctestProject=${_ctest_project}" - "${CTEST_BINARY_DIRECTORY}/cdashadmin.txt" - STATUS status - ) - list(GET status 0 error_code) - list(GET status 1 error_msg) - if(error_code) - message(FATAL_ERROR "error: Failed to communicate with cdashadmin-web - ${error_msg}") - endif() - endif() - -endmacro() - -macro(check_for_errors) - - set(_curr_target ${ARGV0}) - if(build_errors AND _curr_target) - # try to remove the stamp file for external projects - set(_stamp_file "${CTEST_BINARY_DIRECTORY}/ep/src/${_curr_target}-stamp/${_curr_target}-configure") - if(EXISTS "${_stamp_file}") - file(REMOVE "${_stamp_file}") - endif() - endif() - - if(build_errors OR test_errors) - finalize_submission() - # this should return from run_ctest() - return() - endif() - -endmacro() - -#--------------------------------------------------------------------- -# run_ctest macro -#--------------------------------------------------------------------- -function(run_ctest) - - set(build_warnings 0) - set(build_errors 0) - set(test_errors 0) - - set(force_build ${initial_force_build}) - - ctest_start(${model}) - - if(MITK_EXTENSIONS) - foreach(extension ${MITK_EXTENSIONS}) - if(extension MATCHES "([^|]+)\\|([^|]+)\\|(.+)") - set(extension_repo ${CMAKE_MATCH_1}) - set(extension_tag ${CMAKE_MATCH_2}) - set(extension_source_dir ${CMAKE_MATCH_3}) - if(NOT EXISTS "${CTEST_DASHBOARD_ROOT}/${extension_source_dir}") - message("Clone ${extension_repo} (${extension_tag})") - execute_process( - COMMAND ${CTEST_GIT_COMMAND} clone -b ${extension_tag} ${extension_repo} ${extension_source_dir} - WORKING_DIRECTORY ${CTEST_DASHBOARD_ROOT}) - else() - set(working_dir "${CTEST_DASHBOARD_ROOT}/${extension_source_dir}") - message("Update ${extension_repo} (${extension_tag})") - execute_process( - COMMAND ${CTEST_GIT_COMMAND} fetch origin ${extension_tag} - WORKING_DIRECTORY "${working_dir}" - RESULT_VARIABLE exit_code) - - if(exit_code EQUAL 0) - execute_process( - COMMAND ${CTEST_GIT_COMMAND} diff --quiet HEAD FETCH_HEAD - WORKING_DIRECTORY "${working_dir}" - RESULT_VARIABLE exit_code) - - if(NOT exit_code EQUAL 0) - execute_process( - COMMAND ${CTEST_GIT_COMMAND} reset --hard FETCH_HEAD - WORKING_DIRECTORY "${working_dir}") - set(force_build TRUE) - endif() - else() - message(FATAL_ERROR "Could not update ${extension_repo} (${extension_tag})") - endif() - endif() - endif() - endforeach() - endif() - - message("Update MITK") - ctest_update(SOURCE "${CTEST_CHECKOUT_DIR}" RETURN_VALUE res) - - if(res LESS 0) - # update error - math(EXPR build_errors "${build_errors} + 1") - endif() - - # force a build if this is the first run and the build dir is empty - if(NOT EXISTS "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt") - message("First time build - Initialize CMakeCache.txt") - set(res 1) - - # Write initial cache. - if(NOT DEFINED BUILD_TESTING) - set(BUILD_TESTING ON) - endif() - - # Write initial cache. - file(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" " -CTEST_USE_LAUNCHERS:BOOL=${CTEST_USE_LAUNCHERS} -CTEST_PROJECT_ADDITIONAL_TARGETS:INTERNAL=${CTEST_PROJECT_ADDITIONAL_TARGETS} -BUILD_TESTING:BOOL=${BUILD_TESTING} -MITK_CTEST_SCRIPT_MODE:STRING=${SCRIPT_MODE} -CMAKE_BUILD_TYPE:STRING=${CTEST_BUILD_CONFIGURATION} -WITH_COVERAGE:BOOL=${WITH_COVERAGE} -MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL:STRING=${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL} -${INITIAL_CMAKECACHE_OPTIONS} -") - endif() - - if(res GREATER 0 OR force_build) - - # Clear the forced rerun request - if(CDASH_ADMIN_URL_PREFIX AND cdash_remove_rerun_url) - file(DOWNLOAD "${cdash_remove_rerun_url}" "${CTEST_BINARY_DIRECTORY}/tmp.txt") - file(REMOVE "${CTEST_BINARY_DIRECTORY}/tmp.txt") - endif() - - if(CTEST_PROJECT_NAME_SUPERBUILD) - set(ctest_project_name_orig ${CTEST_PROJECT_NAME}) - set(CTEST_PROJECT_NAME ${CTEST_PROJECT_NAME_SUPERBUILD}) - endif() - - message("----------- [ Configure SuperBuild ] -----------") - - set_property(GLOBAL PROPERTY SubProject SuperBuild) - set_property(GLOBAL PROPERTY Label SuperBuild) - - if(MITK_EXTENSIONS) - set(SUPERBUILD_CONFIG_OPTIONS -D MITK_EXTENSION_DIRS:STRING=${MITK_EXTENSION_DIRS}) - endif() - - ctest_configure(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res OPTIONS "${SUPERBUILD_CONFIG_OPTIONS}") - - if(res) - math(EXPR build_errors "${build_errors} + 1") - endif() - - # Project.xml is generated during the superbuild configure step - ctest_submit(FILES "${CTEST_BINARY_DIRECTORY}/Project.xml" RETRY_DELAY 3 RETRY_COUNT 3) - - ctest_read_custom_files("${CTEST_BINARY_DIRECTORY}") - - ctest_submit(PARTS Configure RETRY_DELAY 3 RETRY_COUNT 3) - - # submit the update results *after* the submitting the Configure info, - # otherwise CDash is somehow confused and cannot add the update info - # to the superbuild project - ctest_submit(PARTS Update RETRY_DELAY 3 RETRY_COUNT 3) - - check_for_errors() - - # To get CTEST_PROJECT_SUBPROJECTS and CTEST_PROJECT_EXTERNALS definition - include("${CTEST_BINARY_DIRECTORY}/CTestConfigSubProject.cmake") - - # Read in a list of super-build targets (SUPERBUILD_TARGETS). If an error - # occurs in one of the listed projects, the ctest superbuild make step stops - # and the error is reported in the dashboard. If this variable would be empty - # the errors are still reported but make would keep building external - # projects which leads to potentially more errors because of dependencies. - set(MITK_SUPERBUILD_TARGETS_FILE "${CTEST_BINARY_DIRECTORY}/SuperBuildTargets.cmake") - if(EXISTS "${MITK_SUPERBUILD_TARGETS_FILE}") - include("${MITK_SUPERBUILD_TARGETS_FILE}") - endif() - - # Build top level (either all or the supplied targets at - # superbuild level - if(SUPERBUILD_TARGETS) - foreach(superbuild_target ${SUPERBUILD_TARGETS}) - - message("----------- [ Build ${superbuild_target} - SuperBuild ] -----------") - func_build_target(${superbuild_target} "${CTEST_BINARY_DIRECTORY}") - check_for_errors(${superbuild_target}) - - # runs only tests that have a LABELS property matching "SuperBuild" - func_test("SuperBuild" "${CTEST_BINARY_DIRECTORY}") - check_for_errors() - endforeach() - - # HACK Unfortunately ctest_coverage ignores the build argument, back-up the original dirs - file(READ "${CTEST_BINARY_DIRECTORY}/CMakeFiles/TargetDirectories.txt" old_coverage_dirs) - - # explicitly build requested external projects as subprojects - foreach(external_project_with_build_dir ${CTEST_PROJECT_EXTERNALS}) - - string(REPLACE "^^" ";" external_project_with_build_dir_list "${external_project_with_build_dir}") - list(GET external_project_with_build_dir_list 0 external_project_name) - list(GET external_project_with_build_dir_list 1 external_project_builddir) - - set_property(GLOBAL PROPERTY SubProject ${external_project_name}) - set_property(GLOBAL PROPERTY Label ${external_project_name}) - - message("----------- [ Build ${external_project_name} ] -----------") - - func_build_target("${external_project_name}" "${CTEST_BINARY_DIRECTORY}") - check_for_errors() - - # HACK Unfortunately ctest_coverage ignores the build argument, try to force it... - file(READ "${CTEST_BINARY_DIRECTORY}/${external_project_builddir}/CMakeFiles/TargetDirectories.txt" mitk_build_coverage_dirs) - file(APPEND "${CTEST_BINARY_DIRECTORY}/CMakeFiles/TargetDirectories.txt" "${mitk_build_coverage_dirs}") - - message("----------- [ Test ${external_project_name} ] -----------") - - # runs only tests that have a LABELS property matching "${external_project_name}" - func_test(${external_project_name} "${CTEST_BINARY_DIRECTORY}/${external_project_builddir}") - - # restore old coverage dirs - file(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeFiles/TargetDirectories.txt" "${old_coverage_dirs}") - - endforeach() - - # switch back to SuperBuild label - set_property(GLOBAL PROPERTY SubProject SuperBuild) - set_property(GLOBAL PROPERTY Label SuperBuild) - - message("----------- [ Finish SuperBuild ] -----------") - else() - message("----------- [ Build SuperBuild ] -----------") - endif() - - # build everything at superbuild level which has not yet been built - func_build_target("" "${CTEST_BINARY_DIRECTORY}") - check_for_errors() - - # runs only tests that have a LABELS property matching "SuperBuild" - #func_test("SuperBuild" "${CTEST_BINARY_DIRECTORY}") - - set(build_dir "${CTEST_BINARY_DIRECTORY}/${PROJECT_BUILD_DIR}") - if(CTEST_PROJECT_NAME_SUPERBUILD) - set(CTEST_PROJECT_NAME ${ctest_project_name_orig}) - endif() - - message("----------- [ Configure ${build_dir} ] -----------") - # Configure target - ctest_configure(BUILD "${build_dir}" - OPTIONS "-DCTEST_USE_LAUNCHERS=${CTEST_USE_LAUNCHERS}" - RETURN_VALUE res - ) - ctest_read_custom_files("${CTEST_BINARY_DIRECTORY}") - ctest_submit(PARTS Configure RETRY_DELAY 3 RETRY_COUNT 3) - - if(res) - math(EXPR build_errors "${build_errors} + 1") - endif() - check_for_errors() - - foreach(subproject ${CTEST_PROJECT_SUBPROJECTS}) - set_property(GLOBAL PROPERTY SubProject ${subproject}) - set_property(GLOBAL PROPERTY Label ${subproject}) - - if(subproject MATCHES "Unlabeled") - message("----------- [ Build All (Unlabeled) ] -----------") - # Build target - func_build_target("" "${build_dir}") - else() - message("----------- [ Build ${subproject} ] -----------") - # Build target - func_build_target(${subproject} "${build_dir}") - endif() - check_for_errors() - endforeach() - - # HACK Unfortunately ctest_coverage ignores the build argument, try to force it... - file(READ ${build_dir}/CMakeFiles/TargetDirectories.txt mitk_build_coverage_dirs) - file(APPEND "${CTEST_BINARY_DIRECTORY}/CMakeFiles/TargetDirectories.txt" "${mitk_build_coverage_dirs}") - - foreach(subproject ${CTEST_PROJECT_SUBPROJECTS}) - set_property(GLOBAL PROPERTY SubProject ${subproject}) - set_property(GLOBAL PROPERTY Label ${subproject}) - message("----------- [ Test ${subproject} ] -----------") - - # runs only tests that have a LABELS property matching "${subproject}" - func_test(${subproject} "${build_dir}") - endforeach() - - # Build any additional target which is not build by "all" - # i.e. the "package" target - if(CTEST_PROJECT_ADDITIONAL_TARGETS) - foreach(additional_target ${CTEST_PROJECT_ADDITIONAL_TARGETS}) - set_property(GLOBAL PROPERTY SubProject ${additional_target}) - set_property(GLOBAL PROPERTY Label ${additional_target}) - - message("----------- [ Build ${additional_target} ] -----------") - func_build_target(${additional_target} "${build_dir}") - check_for_errors() - - message("----------- [ Test ${additional_target} ] -----------") - # runs only tests that have a LABELS property matching "${subproject}" - func_test(${additional_target} "${build_dir}") - endforeach() - endif() - - if(WITH_DOCUMENTATION) - message("----------- [ Build Documentation ] -----------") - set(ctest_use_launchers_orig ${CTEST_USE_LAUNCHERS}) - set(CTEST_USE_LAUNCHERS 0) - # Build Documentation target - set_property(GLOBAL PROPERTY SubProject Documentation) - set_property(GLOBAL PROPERTY Label Documentation) - func_build_target("doc" "${build_dir}") - set(CTEST_USE_LAUNCHERS ${ctest_use_launchers_orig}) - endif() - - set_property(GLOBAL PROPERTY SubProject SuperBuild) - set_property(GLOBAL PROPERTY Label SuperBuild) - - # Global coverage ... - if(WITH_COVERAGE AND CTEST_COVERAGE_COMMAND) - message("----------- [ Global coverage ] -----------") - ctest_coverage(BUILD "${build_dir}" APPEND) - ctest_submit(PARTS Coverage RETRY_DELAY 3 RETRY_COUNT 3) - endif() - - # Global dynamic analysis ... - if(WITH_MEMCHECK AND CTEST_MEMORYCHECK_COMMAND) - message("----------- [ Global memcheck ] -----------") - ctest_memcheck(BUILD "${build_dir}") - ctest_submit(PARTS MemCheck RETRY_DELAY 3 RETRY_COUNT 3) - endif() - - check_for_errors() - finalize_submission() - - endif() - - # Clear the CTEST_CHECKOUT_COMMAND variable to prevent continuous clients - # to try to checkout again - set(CTEST_CHECKOUT_COMMAND "") - -endfunction() - -run_ctest() diff --git a/CMake/MITKDashboardScript.TEMPLATE.cmake b/CMake/MITKDashboardScript.TEMPLATE.cmake deleted file mode 100644 index 0d459014e1..0000000000 --- a/CMake/MITKDashboardScript.TEMPLATE.cmake +++ /dev/null @@ -1,143 +0,0 @@ -# -# OS: Ubuntu 9.04 2.6.28-18-generic -# Hardware: x86_64 GNU/Linux -# GPU: NA -# - -# Note: The specific version and processor type of this machine should be reported in the -# header above. Indeed, this file will be send to the dashboard as a NOTE file. - -cmake_minimum_required(VERSION 3.14.5 FATAL_ERROR) - -# -# Dashboard properties -# - -set(MY_COMPILER "gcc-4.9.x") -# For Windows, e.g. -#set(MY_COMPILER "VC12.0") - -set(CTEST_CMAKE_COMMAND "/usr/bin/cmake") -set(CTEST_CMAKE_GENERATOR "Unix Makefiles") -set(CTEST_DASHBOARD_ROOT "/opt/dartclients") -# For Windows, e.g. -#set(CTEST_CMAKE_COMMAND "cmake") -#set(CTEST_CMAKE_GENERATOR "Visual Studio 16 2019") -#set(CTEST_CMAKE_GENERATOR_PLATFORM "x64") -#set(CTEST_DASHBOARD_ROOT "D:/dc") - -set(MITK_EXTENSIONS # "||" -# "https://phabricator.mitk.org/source/mitk-projecttemplate.git|master|MITK-ProjectTemplate" -# "https://phabricator.mitk.org/source/mitk-diffusion.git|master|MITK-Diffusion" -) - -# -# Dashboard options -# -set(WITH_KWSTYLE FALSE) -set(WITH_MEMCHECK FALSE) -set(WITH_COVERAGE FALSE) -set(WITH_DOCUMENTATION FALSE) -#set(DOCUMENTATION_ARCHIVES_OUTPUT_DIRECTORY ) # for example: $ENV{HOME}/Projects/Doxygen -set(CTEST_BUILD_CONFIGURATION "Release") -set(CTEST_TEST_TIMEOUT 500) -if(UNIX) - set(CTEST_BUILD_FLAGS "-j4") # Use multiple CPU cores to build -else() - set(CTEST_BUILD_FLAGS "") -endif() - -# experimental: -# - run_ctest() macro will be called *ONE* time -# - binary directory will *NOT* be cleaned -# continuous: -# - run_ctest() macro will be called EVERY 5 minutes ... -# - binary directory will *NOT* be cleaned -# - configure/build will be executed *ONLY* if the repository has been updated -# nightly: -# - run_ctest() macro will be called *ONE* time -# - binary directory *WILL BE* cleaned -set(SCRIPT_MODE "experimental") # "experimental", "continuous", "nightly" - -# -# Project specific properties -# -# In order to shorten the global path length, the build directory for each DartClient -# uses the following abrevation sceme: -# For build configuration: -# Debug -> d -# Release -> r -# For scripte mode: -# continuous -> c -# nightly -> n -# experimental -> e -# Example directory: /MITK-sb-d-n/ for a nightly MITK superbuild in debug mode. -set(short_of_ctest_build_configuration "") -set(short_of_script_mode "") -string(SUBSTRING ${CTEST_BUILD_CONFIGURATION} 0 1 short_of_ctest_build_configuration) -string(SUBSTRING ${SCRIPT_MODE} 0 1 short_of_script_mode) -set(CTEST_SOURCE_DIRECTORY "${CTEST_DASHBOARD_ROOT}/MITK") -set(CTEST_BINARY_DIRECTORY "${CTEST_DASHBOARD_ROOT}/MITK-sb-${short_of_ctest_build_configuration}-${short_of_script_mode}") - -# Create an initial cache file for MITK. This file is used to configure the MITK-Build. Use ADDITIONAL_CMAKECACHE_OPTION -# to configure the MITK-Superbuild. The -set(MITK_INITIAL_CACHE " -# Example how to set a boolean variable in the MITK-Build via this script: -#set(MITK_ENABLE_TOF_HARDWARE \"TRUE\" CACHE INTERNAL \"Enable ToF Hardware\") -# Example how to set a path variable in the MITK-Build via this script: -#set(MITK_PMD_LIB \"/home/kilgus/thomas/PMDSDK2/Linux_x86_64/bin/libpmdaccess2.so\" CACHE INTERNAL \"PMD lib\") -") - -set(ADDITIONAL_CMAKECACHE_OPTION " -# Superbuild variables are not passed through to the MITK-Build (or any other build like ITK, VTK, ...) -# Use the MITK_INITIAL_CACHE the pass variables to the MITK-Build. -# add entries like this -#MITK_USE_OpenCV:BOOL=OFF -CMAKE_PREFIX_PATH:PATH=${CMAKE_PREFIX_PATH} -") - -# List of test that should be explicitly disabled on this machine -set(TEST_TO_EXCLUDE_REGEX "") - -# set any extra environment variables here -set(ENV{PATH} "$ENV{PATH}") - -find_program(CTEST_COVERAGE_COMMAND NAMES gcov) -find_program(CTEST_MEMORYCHECK_COMMAND NAMES valgrind) -find_program(CTEST_GIT_COMMAND NAMES git) - -# -# Git repository - Overwrite the default value provided by the driver script -# -# The git repository containing MITK code -#set(GIT_REPOSITORY "/home/username/MITK") -# The branch of the MITK git repository to check out -#set(GIT_BRANCH "develop") - -########################################## -# WARNING: DO NOT EDIT BEYOND THIS POINT # -########################################## - -# -# Convenient macro allowing to download a file -# -macro(downloadFile url dest) - file(DOWNLOAD "${url}" "${dest}" STATUS status) - list(GET status 0 error_code) - list(GET status 1 error_msg) - if(error_code) - message(FATAL_ERROR "error: Failed to download ${url} - ${error_msg}") - endif() -endmacro() - -if(NOT GIT_BRANCH) - set(GIT_BRANCH "master") -endif() - -# -# Download and include setup script -# -set(url "https://raw.githubusercontent.com/MITK/MITK/${GIT_BRANCH}/CMake/MITKDashboardSetup.cmake") -set(dest ${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}.setup) -downloadFile("${url}" "${dest}") -include(${dest}) diff --git a/CMake/MITKDashboardScript.cmake b/CMake/MITKDashboardScript.cmake new file mode 100644 index 0000000000..5fe6085372 --- /dev/null +++ b/CMake/MITKDashboardScript.cmake @@ -0,0 +1,174 @@ +#[============================================================================[ + + Configuration + + ]============================================================================] + +set(CTEST_CMAKE_GENERATOR +# "Unix Makefiles" + "Visual Studio 16 2019" +) + +set(CTEST_CMAKE_GENERATOR_PLATFORM +# "Win32" + "x64" +) + +set(CTEST_BUILD_CONFIGURATION +# "Debug" + "Release" +# "MinSizeRel" +# "RelWithDebInfo" +) + +set(CTEST_DASHBOARD_MODEL +# "Continuous" + "Experimental" +# "Nightly" +) + +# If empty: Default site name is the name of this computer +set(CTEST_SITE + "" +) + +# If empty: Default build name is based on OS, compiler, +# CTEST_BUILD_CONFIGURATION, and MITK_BUILD_CONFIGURATION +set(CTEST_BUILD_NAME + "" +) + +set(CTEST_BUILD_FLAGS +# "-j8" +) + +# If empty: Default URL is CTEST_SUBMIT_URL (CTestConfig.cmake) +set(MITK_SUBMIT_URL + "https://cdash.mitk.org/submit.php?project=MITK" +) + +set(MITK_BUILD_CONFIGURATION +# "All" + "WorkbenchRelease" +# "Minimal" +) + +set(MITK_SUPERBUILD_OPTIONS +# "MITK_WHITELIST:STRING=Minimal" + "Qt5_DIR:PATH=C:/Qt/5.12.9/msvc2017_64/lib/cmake/Qt5" + "MITK_AUTOCLEAN_EXTERNAL_PROJECTS:BOOL=ON" + "MITK_FAST_TESTING:BOOL=ON" + "MITK_XVFB_TESTING:BOOL=OFF" +) + +set(MITK_BUILD_OPTIONS + "" +) + +set(MITK_REPOSITORY + "https://phabricator.mitk.org/source/mitk.git" +) + +# Branch name, tag, or commit hash +set(MITK_BRANCH + "develop" +# "master" +) + +# Three list items per MITK extension: +set(MITK_EXTENSIONS +# "MITK-ProjectTemplate" +# "https://phabricator.mitk.org/source/mitk-projecttemplate.git" +# "master" +# "MITK Diffusion" +# "https://phabricator.mitk.org/source/mitk-diffusion.git" +# "master" +) + +#[============================================================================[ + + Helper functions + + ]============================================================================] + +function(get_temp_directory) + set(temp_directory "${CMAKE_CURRENT_SOURCE_DIR}/temp") + + if(NOT EXISTS "${temp_directory}") + file(MAKE_DIRECTORY "${temp_directory}") + elseif(NOT IS_DIRECTORY "${temp_directory}") + message(FATAL_ERROR "Temporary directory location blocked by file \"${temp_directory}\"") + endif() + + set(${ARGV0} "${temp_directory}" PARENT_SCOPE) +endfunction() + +function(download_file) + cmake_parse_arguments(PARSE_ARGV 0 ARG "QUIET" "URL;OUTPUT_FILE;ERROR_CODE" "") + + get_filename_component(output_dir "${ARG_OUTPUT_FILE}" DIRECTORY) + get_filename_component(output_filename "${ARG_OUTPUT_FILE}" NAME) + + if(NOT output_dir) + set(output_dir "${CMAKE_CURRENT_SOURCE_DIR}") + endif() + + set(output_file "${output_dir}/${output_filename}") + + if(NOT ARG_QUIET) + message("Download file\n from: ${ARG_URL}\n to: ${output_file}") + endif() + + get_temp_directory(temp_dir) + string(RANDOM random_filename) + + while(EXISTS "${temp_dir}/${random_filename}") + string(RANDOM random_filename) + endwhile() + + set(temp_output_file "${temp_dir}/${random_filename}") + + file(DOWNLOAD "${ARG_URL}" "${temp_output_file}" STATUS status) + + list(GET status 0 error_code) + list(GET status 1 error_message) + set(error_message "${error_message} (${error_code})") + + if(NOT 0 EQUAL error_code) + if(EXISTS "${temp_output_file}") + file(REMOVE "${temp_output_file}") + endif() + + if(NOT ARG_ERROR_CODE) + message(FATAL_ERROR "${error_message}") + elseif(NOT ARG_QUIET) + message(" error: ${error_message}") + endif() + else() + file(RENAME "${temp_output_file}" "${output_file}") + endif() + + if(ARG_ERROR_CODE) + set(${ARG_ERROR_CODE} ${error_code} PARENT_SCOPE) + endif() +endfunction() + +#[============================================================================[ + + Download and include actual script + + ]============================================================================] + +include("MITKDashboardScript.local.cmake" OPTIONAL RESULT_VARIABLE found) + +if(NOT found) + get_temp_directory(temp_dir) + set(script "${temp_dir}/MITKDashboardScript.cmake") + + download_file( + URL "https://raw.githubusercontent.com/MITK/MITK/${MITK_BRANCH}/CMake/MITKDashboardScript.download.cmake" + OUTPUT_FILE "${script}" + ) + + include("${script}") +endif() diff --git a/CMake/MITKDashboardScript.download.cmake b/CMake/MITKDashboardScript.download.cmake new file mode 100644 index 0000000000..aa173f276b --- /dev/null +++ b/CMake/MITKDashboardScript.download.cmake @@ -0,0 +1,615 @@ +#[============================================================================[ + + Helper functions + + ]============================================================================] + +function(get_macos_codename) + set(macos_codename "") + + set(software_license_file "\ +/System/Library/CoreServices/Setup Assistant.app\ +/Contents/Resources/en.lproj/OSXSoftwareLicense.rtf") + + if(EXISTS "${software_license_file}") + file(READ "${software_license_file}" software_license) + + if(software_license MATCHES "SOFTWARE LICENSE AGREEMENT FOR macOS ([^\n]+)") + set(macos_codename "${CMAKE_MATCH_1}") + endif() + endif() + + set(${ARGV0} ${macos_codename} PARENT_SCOPE) +endfunction() + +function(get_macos_name) + set(macos_name "macOS") + + get_macos_codename(macos_codename) + + if(macos_codename) + set(macos_name "${macos_name} ${macos_codename}") + endif() + + execute_process( + RESULT_VARIABLE error_code + OUTPUT_VARIABLE version + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND "sw_vers" "-productVersion") + + if(0 EQUAL error_code AND version) + set(macos_name "${macos_name} ${version}") + endif() + + set(${ARGV0} ${macos_name} PARENT_SCOPE) +endfunction() + +function(get_linux_name) + set(linux_name "Linux") + set(os_release_file "/etc/os-release") + + if(EXISTS "${os_release_file}") + file(STRINGS "${os_release_file}" os_release) + + set(name "") + set(version_id "") + + foreach(line ${os_release}) + if(NOT name AND line MATCHES "^NAME=[\"]?([^\"]+)") + set(name "${CMAKE_MATCH_1}") + continue() + endif() + + if(NOT version_id AND line MATCHES "^VERSION_ID=\"?([^\"]+)") + set(version_id "${CMAKE_MATCH_1}") + continue() + endif() + + if(name AND version_id) + break() + endif() + endforeach() + + if(name) + set(linux_name "${name}") + endif() + + if(version_id) + set(linux_name "${linux_name} ${version_id}") + endif() + endif() + + set(${ARGV0} ${linux_name} PARENT_SCOPE) +endfunction() + +function(get_windows_name) + set(windows_name "Windows") + + execute_process( + RESULT_VARIABLE error_code + OUTPUT_VARIABLE version + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND "wmic" "os" "get" "Version" "-value") + + if(0 EQUAL error_code AND version) + if(version MATCHES "Version=([0-9]+)\\.([0-9]+)") + set(windows_name "${windows_name} ${CMAKE_MATCH_1}") + if(NOT 0 EQUAL CMAKE_MATCH_2) + set(windows_name "${windows_name}.${CMAKE_MATCH_2}") + endif() + endif() + endif() + + set(${ARGV0} ${windows_name} PARENT_SCOPE) +endfunction() + +function(get_os_name) + set(os_name "") + + if(APPLE) + get_macos_name(os_name) + elseif(UNIX) + get_linux_name(os_name) + elseif(WIN32) + get_windows_name(os_name) + endif() + + set(${ARGV0} ${os_name} PARENT_SCOPE) +endfunction() + +function(download_string) + cmake_parse_arguments(PARSE_ARGV 0 ARG "" "URL;OUTPUT_VARIABLE" "") + + get_temp_directory(temp_dir) + string(RANDOM random_filename) + + while(EXISTS "${temp_dir}/${random_filename}") + string(RANDOM random_filename) + endwhile() + + set(temp_output_file "${temp_dir}/${random_filename}") + + download_file( + URL ${ARG_URL} + OUTPUT_FILE ${temp_output_file} + ERROR_CODE error_code) + + set(output "") + + if(EXISTS "${temp_output_file}") + file(READ "${temp_output_file}" output) + file(REMOVE "${temp_output_file}") + endif() + + set(${ARG_OUTPUT_VARIABLE} ${output} PARENT_SCOPE) +endfunction() + +function(find_vswhere) + get_temp_directory(temp_dir) + set(latest_vswhere "${temp_dir}/vswhere.exe") + set(vswhere "vswhere.exe-NOTFOUND") + + if(EXISTS "${latest_vswhere}") + set(vswhere "${latest_vswhere}") + else() + set(program_files_x86 "PROGRAMFILES(X86)") + set(program_files_x86 "$ENV{${program_files_x86}}") + set(system_vswhere "${program_files_x86}/Microsoft Visual Studio/Installer/vswhere.exe") + + if(EXISTS "${system_vswhere}") + set(vswhere "${system_vswhere}") + else() + download_string( + URL "https://api.github.com/repos/microsoft/vswhere/releases/latest" + OUTPUT_VARIABLE latest_vswhere_json) + + if(latest_vswhere_json MATCHES "\"browser_download_url\": *\"([^\"]*)\"") + download_file( + URL "${CMAKE_MATCH_1}" + OUTPUT_FILE "${latest_vswhere}" + ERROR_CODE error_code) + + if (0 EQUAL error_code) + set(vswhere "${latest_vswhere}") + endif() + endif() + endif() + endif() + + set(${ARGV0} "${vswhere}" PARENT_SCOPE) +endfunction() + +function(vswhere) + cmake_parse_arguments(PARSE_ARGV 0 ARG "" "PROPERTY;OUTPUT_VARIABLE" "") + + set(property_value "") + + if(CTEST_CMAKE_GENERATOR MATCHES "^Visual Studio ([0-9]+)") + set(major_version "${CMAKE_MATCH_1}") + math(EXPR next_major_version "${major_version} + 1") + + find_vswhere(vswhere) + + if (vswhere) + execute_process( + OUTPUT_VARIABLE property_value + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND ${vswhere} + "-requires" "Microsoft.VisualStudio.Workload.NativeDesktop" + "-version" "[${major_version},${next_major_version})" + "-property" "${ARG_PROPERTY}" + "-format" "value") + endif() + endif() + + set(${ARG_OUTPUT_VARIABLE} ${property_value} PARENT_SCOPE) +endfunction() + +function(get_visual_studio_name) + set(visual_studio_name "Visual Studio") + + if(CTEST_CMAKE_GENERATOR MATCHES "^Visual Studio [0-9]+ ([0-9]+)") + set(product_line_version "${CMAKE_MATCH_1}") + set(visual_studio_name "${visual_studio_name} ${product_line_version}") + + vswhere(PROPERTY "catalog_productDisplayVersion" OUTPUT_VARIABLE product_display_version) + + if(product_display_version) + set(visual_studio_name "${visual_studio_name} ${product_display_version}") + endif() + endif() + + set(${ARGV0} ${visual_studio_name} PARENT_SCOPE) +endfunction() + +function(get_compiler_name) + set(compiler_name "") + + if(CTEST_CMAKE_GENERATOR MATCHES "^Visual Studio") + get_visual_studio_name(compiler_name) + else() + get_temp_directory(temp_dir) + + file(WRITE "${temp_dir}/src/CMakeLists.txt" "\ +project(probe C) +message(STATUS \"CMAKE_C_COMPILER_ID=\\\"\${CMAKE_C_COMPILER_ID}\\\"\") +message(STATUS \"CMAKE_C_COMPILER_VERSION=\\\"\${CMAKE_C_COMPILER_VERSION}\\\"\")") + + file(REMOVE_RECURSE "${temp_dir}/build") + + unset(options) + + foreach(option ${MITK_SUPERBUILD_OPTIONS}) + list(APPEND options "-D" "${option}") + endforeach() + + execute_process( + RESULT_VARIABLE error_code + OUTPUT_VARIABLE compiler + ERROR_QUIET + COMMAND ${CMAKE_COMMAND} + "-S" "${temp_dir}/src" + "-B" "${temp_dir}/build" + "-G" "${CTEST_CMAKE_GENERATOR}" + ${options}) + + if(0 EQUAL error_code) + if(compiler MATCHES "CMAKE_C_COMPILER_ID=\"([^\"]*)\"") + set(compiler_name "${CMAKE_MATCH_1}") + + if(compiler MATCHES "CMAKE_C_COMPILER_VERSION=\"([^\"]*)\"") + set(version "${CMAKE_MATCH_1}") + + if(version MATCHES "^([0-9]+\\.[0-9]+\\.[0-9]+)") + set(version "${CMAKE_MATCH_1}") + endif() + + string(REGEX REPLACE "\\.0$" "" version "${version}") + + set(compiler_name "${compiler_name} ${version}") + endif() + endif() + endif() + endif() + + set(${ARGV0} ${compiler_name} PARENT_SCOPE) +endfunction() + +function(get_default_build_name) + get_os_name(default_build_name) + get_compiler_name(compiler_name) + + if(compiler_name) + set(default_build_name "${default_build_name} ${compiler_name}") + endif() + + set(default_build_name "${default_build_name} ${CTEST_BUILD_CONFIGURATION}") + + if(MITK_BUILD_CONFIGURATION) + set(default_build_name "${default_build_name} ${MITK_BUILD_CONFIGURATION}") + endif() + + set(${ARGV0} ${default_build_name} PARENT_SCOPE) +endfunction() + +function(git) + cmake_parse_arguments(PARSE_ARGV 0 ARG "" "WORKING_DIRECTORY;OUTPUT_VARIABLE;RESULT_VARIABLE" "") + + if(NOT ARG_WORKING_DIRECTORY) + set(ARG_WORKING_DIRECTORY "${CTEST_SOURCE_DIRECTORY}") + endif() + + execute_process( + WORKING_DIRECTORY "${ARG_WORKING_DIRECTORY}" + RESULT_VARIABLE error_code + OUTPUT_VARIABLE output + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND "${CTEST_GIT_COMMAND}" ${ARG_UNPARSED_ARGUMENTS}) + + if(ARG_OUTPUT_VARIABLE) + set(${ARG_OUTPUT_VARIABLE} ${output} PARENT_SCOPE) + endif() + + if(ARG_RESULT_VARIABLE) + set(${ARG_RESULT_VARIABLE} ${error_code} PARENT_SCOPE) + endif() +endfunction() + +function(git_log) + cmake_parse_arguments(PARSE_ARGV 0 ARG "" "WORKING_DIRECTORY;COMMIT_HASH;COMMITTER;SUBJECT" "") + + if(NOT ARG_WORKING_DIRECTORY) + set(ARG_WORKING_DIRECTORY "${CTEST_SOURCE_DIRECTORY}") + endif() + + set(args WORKING_DIRECTORY "${ARG_WORKING_DIRECTORY}" "log" "-1") + + if(ARG_COMMIT_HASH) + unset(commit_hash) + git(OUTPUT_VARIABLE commit_hash ${args} "--pretty=%h" ) + if(commit_hash) + set(${ARG_COMMIT_HASH} ${commit_hash} PARENT_SCOPE) + endif() + endif() + + if(ARG_COMMITTER) + unset(committer) + git(OUTPUT_VARIABLE committer ${args} "--pretty=%cn" ) + if(committer) + set(${ARG_COMMITTER} ${committer} PARENT_SCOPE) + endif() + endif() + + if(ARG_SUBJECT) + unset(subject) + git(OUTPUT_VARIABLE subject ${args} "--pretty=%s" ) + if(subject) + set(${ARG_SUBJECT} ${subject} PARENT_SCOPE) + endif() + endif() +endfunction() + +function(submit) + cmake_parse_arguments(PARSE_ARGV 0 ARG "" "" "PARTS") + + if(MITK_SUBMIT_URL) + set(submit_url "SUBMIT_URL" "${MITK_SUBMIT_URL}") + else() + unset(submit_url) + endif() + + ctest_submit(${submit_url} RETRY_COUNT 3 RETRY_DELAY 5 PARTS ${ARG_PARTS}) +endfunction() + +#[============================================================================[ + + Actual script + + ]============================================================================] + +cmake_minimum_required(VERSION 3.15 FATAL_ERROR) + +find_program(CTEST_GIT_COMMAND git) + +if(NOT CTEST_GIT_COMMAND) + message(FATAL_ERROR "Git not found") +endif() + +if(NOT CTEST_CMAKE_GENERATOR MATCHES "^Visual Studio") + unset(CTEST_CMAKE_GENERATOR_PLATFORM) +endif() + +if(NOT CTEST_SITE) + unset(CTEST_SITE) + site_name(CTEST_SITE) +endif() + +if(NOT CTEST_BUILD_NAME) + get_default_build_name(CTEST_BUILD_NAME) +endif() + +set(CTEST_SOURCE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/MITK") +set(CTEST_BINARY_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build") + +set(indent " ") + +message("CTest settings") + +if(MITK_SUBMIT_URL) + message("${indent}Submit URL: ${MITK_SUBMIT_URL}") +endif() + +message("\ +${indent}Dashboard model: ${CTEST_DASHBOARD_MODEL} +${indent}Build name: ${CTEST_BUILD_NAME} +${indent}Site: ${CTEST_SITE}") + +message("MITK repository") + +if(NOT EXISTS "${CTEST_SOURCE_DIRECTORY}") + message("\ +${indent}Clone repository: ${MITK_REPOSITORY} +${indent}Branch: ${MITK_BRANCH}") + + set(CTEST_CHECKOUT_COMMAND "\"${CTEST_GIT_COMMAND}\" clone --branch=${MITK_BRANCH} -- ${MITK_REPOSITORY} MITK") + + ctest_start(${CTEST_DASHBOARD_MODEL}) +else() + git_log(COMMIT_HASH old_revision COMMITTER committer SUBJECT subject) + + message("\ +${indent}Update repository: ${CTEST_SOURCE_DIRECTORY} +${indent}Branch: ${MITK_BRANCH} +${indent}Old revision: ${old_revision} (committed by ${committer}) +${indent}${indent}${subject}") + + ctest_start(${CTEST_DASHBOARD_MODEL}) + + set(CTEST_UPDATE_OPTIONS "origin ${MITK_BRANCH}") + + ctest_update(RETURN_VALUE return_value) + + if(-1 EQUAL return_value) + return() + endif() + + git_log(COMMIT_HASH new_revision) + + if(new_revision STREQUAL old_revision) + message("${indent}New revision: up-to-date") + else() + git_log(COMMITTER committer SUBJECT subject) + + message("\ +${indent}New revision: ${new_revision} (committed by ${committer}) +${indent}${indent}${subject}") + endif() +endif() + +unset(extension_dirs) + +if(MITK_EXTENSIONS) + list(LENGTH MITK_EXTENSIONS mitk_extensions_size) + math(EXPR max_index "${mitk_extensions_size} - 1") + + foreach(name_index RANGE 0 ${max_index} 3) + list(GET MITK_EXTENSIONS ${name_index} name) + + math(EXPR url_index "${name_index} + 1") + list(GET MITK_EXTENSIONS ${url_index} url) + + math(EXPR branch_index "${name_index} + 2") + list(GET MITK_EXTENSIONS ${branch_index} branch) + + message("${name} repository") + + set(extension_dir "${CMAKE_CURRENT_SOURCE_DIR}/src/${name}") + list(APPEND extension_dirs "${extension_dir}") + + if(NOT EXISTS "${extension_dir}") + message("\ +${indent}Clone repository: ${url} +${indent}Branch: ${branch}") + + git("clone" "--quiet" "--branch=${branch}" "${url}" "${name}" + WORKING_DIRECTORY "${extension_dir}/..") + else() + git_log(COMMIT_HASH old_revision COMMITTER committer SUBJECT subject + WORKING_DIRECTORY "${extension_dir}") + + message("\ +${indent}Update repository: ${extension_dir} +${indent}Branch: ${branch} +${indent}Old revision: ${old_revision} (committed by ${committer}) +${indent}${indent}${subject}") + + git("fetch" "--quiet" "origin" "${branch}" + WORKING_DIRECTORY "${extension_dir}") + + git("diff" "--quiet" "HEAD" "FETCH_HEAD" + WORKING_DIRECTORY "${extension_dir}" + RESULT_VARIABLE error_code) + + if(NOT error_code EQUAL 0) + git("reset" "--quiet" "--hard" "FETCH_HEAD" + WORKING_DIRECTORY "${extension_dir}") + endif() + + git_log(COMMIT_HASH new_revision + WORKING_DIRECTORY "${extension_dir}") + + if(new_revision STREQUAL old_revision) + message("${indent}New revision: up-to-date") + else() + git_log(COMMITTER committer SUBJECT subject + WORKING_DIRECTORY "${extension_dir}") + + message("\ +${indent}New revision: ${new_revision} (committed by ${committer}) +${indent}${indent}${subject}") + endif() + endif() + endforeach() +endif() + +submit(PARTS Update) + +set(options + "-D" "MITK_CTEST_SCRIPT_MODE:STRING=${CTEST_DASHBOARD_MODEL}" +# "-D" "SUPERBUILD_EXCLUDE_MITKBUILD_TARGET:BOOL=TRUE" +) + +if(extension_dirs) + string (REPLACE ";" "\\\;" extension_dirs "${extension_dirs}") + list(APPEND options "-D" "MITK_EXTENSION_DIRS:STRING=${extension_dirs}") +endif() + +if(MITK_BUILD_CONFIGURATION) + list(APPEND options "-D" "MITK_BUILD_CONFIGURATION:STRING=${MITK_BUILD_CONFIGURATION}") +endif() + +foreach(option ${MITK_SUPERBUILD_OPTIONS}) + list(APPEND options "-D" "${option}") +endforeach() + +ctest_configure(OPTIONS "${options}" RETURN_VALUE return_value) +submit(PARTS Configure) + +if(NOT 0 EQUAL return_value) + submit(PARTS Done) + return() +endif() + +include("${CTEST_BINARY_DIRECTORY}/SuperBuildTargets.cmake") + +if(NOT SUPERBUILD_TARGETS) + submit(PARTS Done) + message(FATAL_ERROR "SUPERBUILD_TARGETS variable not set in SuperBuildTargets.cmake") +else() + set(mitk_targets + MITK-Data + MITK-Utilities + MITK-Configure + MITK-build + ) + + list(LENGTH SUPERBUILD_TARGETS n) + list(LENGTH mitk_targets num_mitk_targets) + math(EXPR n "${n} + ${num_mitk_targets}") + set(i 1) + + unset(append) + + foreach(target ${SUPERBUILD_TARGETS} ${mitk_targets}) + message("MITK superbuild - [${i}/${n}] Build ${target}") + + if(NOT target IN_LIST mitk_targets) + list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION ".*") + set(pop_warning_exception TRUE) + else() + set(pop_warning_exception FALSE) + endif() + + ctest_build(TARGET ${target} + NUMBER_ERRORS num_build_errors + NUMBER_WARNINGS num_build_warnings + RETURN_VALUE return_value + ${append}) + + if(pop_warning_exception) + list(POP_BACK CTEST_CUSTOM_WARNING_EXCEPTION) + endif() + + submit(PARTS Build) + + if(0 LESS num_build_warnings) + message("${indent}${num_build_warnings} warning(s)") + endif() + + if(NOT (0 EQUAL return_value AND 0 EQUAL num_build_errors)) + submit(PARTS Done) + message("${indent}${num_build_errors} error(s)") + return() + else() + message("${indent}${target} was built successfully") + endif() + + if(NOT append) + set(append APPEND) + endif() + + math(EXPR i "${i} + 1") + endforeach() +endif() + +message("Run unit tests...") + +set(CTEST_CONFIGURATION_TYPE "${CTEST_BUILD_CONFIGURATION}") + +ctest_test( + BUILD "${CTEST_BINARY_DIRECTORY}/MITK-build" + PARALLEL_LEVEL 4) + +submit(PARTS Test Done) + +message("Done") diff --git a/CMake/MITKDashboardSetup.cmake b/CMake/MITKDashboardSetup.cmake deleted file mode 100644 index a1befe0885..0000000000 --- a/CMake/MITKDashboardSetup.cmake +++ /dev/null @@ -1,134 +0,0 @@ -# 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) - set(url "https://raw.githubusercontent.com/MITK/MITK/${GIT_BRANCH}/CMake/mitkDetectOS.sh") - 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_Qt5) - set(MITK_USE_Qt5 1) -endif() - -# -# Project specific properties -# -if(NOT CTEST_BUILD_NAME) - if(MITK_USE_Qt5) - set(CTEST_BUILD_NAME "${MY_OPERATING_SYSTEM} ${MY_COMPILER} ${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("${CTEST_CMAKE_GENERATOR_PLATFORM}" STREQUAL "x64") - set(CMAKE_LIBRARY_ARCHITECTURE x64) - else() - set(CMAKE_LIBRARY_ARCHITECTURE x86) - endif() - string(SUBSTRING "${MY_COMPILER}" 2 2 vc_version) - - set(OPENCV_BIN_DIR "${CTEST_BINARY_DIRECTORY}/ep/${CMAKE_LIBRARY_ARCHITECTURE}/vc${vc_version}/bin") - - set(BLUEBERRY_RUNTIME_DIR "${CTEST_BINARY_DIRECTORY}/MITK-build/bin/plugins/${CTEST_BUILD_CONFIGURATION}") - - set(PYTHON_BINARY_DIRS "${CTEST_BINARY_DIRECTORY}/ep/src/CTK-build/CMakeExternals/Install/bin") - get_filename_component(_python_dir "${Python3_EXECUTABLE}" DIRECTORY) - list(APPEND PYTHON_BINARY_DIRS "${_python_dir}") - - set(CTEST_PATH "${CTEST_PATH};${CTEST_BINARY_DIRECTORY}/ep/bin;${BLUEBERRY_RUNTIME_DIR};${OPENCV_BIN_DIR};${PYTHON_BINARY_DIRS}") -endif() -set(ENV{PATH} "${CTEST_PATH}") - -# 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 "https://phabricator.mitk.org/source/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}) - -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} -") - -# 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() - -if(MITK_EXTENSIONS) - set(MITK_EXTENSION_DIRS "") - foreach(extension ${MITK_EXTENSIONS}) - if(extension MATCHES "[^|]+\\|[^|]+\\|(.+)") - if(MITK_EXTENSION_DIRS) - set(MITK_EXTENSION_DIRS "${MITK_EXTENSION_DIRS};") - endif() - set(MITK_EXTENSION_DIRS "${MITK_EXTENSION_DIRS}${CTEST_DASHBOARD_ROOT}/${CMAKE_MATCH_1}") - endif() - endforeach() -endif() - -# -# Download and include dashboard driver script -# -set(url "https://raw.githubusercontent.com/MITK/MITK/${GIT_BRANCH}/CMake/MITKDashboardDriverScript.cmake") -set(dest ${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}.driver) -downloadFile("${url}" "${dest}") -include(${dest}) diff --git a/CMake/SuperbuildCTestCustom.cmake.in b/CMake/SuperbuildCTestCustom.cmake.in deleted file mode 100644 index 55266955f0..0000000000 --- a/CMake/SuperbuildCTestCustom.cmake.in +++ /dev/null @@ -1,5 +0,0 @@ -set(CTEST_CUSTOM_ERROR_EXCEPTION - ${CTEST_CUSTOM_ERROR_EXCEPTION} - "link.jam: No such file or directory" - ) - diff --git a/CMake/mitkDetectOS.sh b/CMake/mitkDetectOS.sh deleted file mode 100755 index be296a336c..0000000000 --- a/CMake/mitkDetectOS.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh -# Detects which OS and if it is Linux then it will detect which Linux Distribution. - -OS=`uname -s` -MACH=`uname -m` - -if [ "${OS}" = "SunOS" ] ; then - OS=Solaris - ARCH=`uname -p` - OSSTR="${OS} ${REV} (${ARCH} `uname -v`)" -elif [ "${OS}" = "AIX" ] ; then - OSSTR="${OS} `oslevel` (`oslevel -r`)" -elif [ "${OS}" = "Linux" ] ; then - if [ -f /etc/os-release ] ; then - DIST=`cat /etc/os-release | tr "\n" ' ' | sed s/.*PRETTY_NAME=\"// | sed s/\".*//` - elif [ -f /etc/redhat-release ] ; then - DIST=`cat /etc/redhat-release | sed s/\ release.*//` - VERSION=`cat /etc/redhat-release | sed s/.*release\ //` - elif [ -f /etc/SUSE-release ] ; then - DIST=`cat /etc/SUSE-release | tr "\n" ' '| sed s/VERSION.*//` - VERSION=`cat /etc/SUSE-release | tr "\n" ' ' | sed s/.*=\ //` - elif [ -f /etc/mandrake-release ] ; then - DIST='Mandrake' - VERSION=`cat /etc/mandrake-release | sed s/.*release\ //` - elif [ -f /etc/debian_version ] ; then - DIST="Debian" - VERSION=`cat /etc/debian_version` - fi - - OSSTR="${DIST} ${VERSION} ${MACH}" -fi - -echo ${OSSTR} diff --git a/CMake/mitkFunctionAddCustomModuleTest.cmake b/CMake/mitkFunctionAddCustomModuleTest.cmake index 3c57b8cfd3..4893b55495 100644 --- a/CMake/mitkFunctionAddCustomModuleTest.cmake +++ b/CMake/mitkFunctionAddCustomModuleTest.cmake @@ -1,28 +1,27 @@ #! #! \brief Add a custom test for MITK module #! #! \param test_name Unique identifier for the test #! \param test_function Name of the test function (the one with the argc,argv signature) #! #! Additional parameters will be passed as command line parameters to the test. #! function(mitkAddCustomModuleTest test_name test_function) if (BUILD_TESTING AND MODULE_IS_ENABLED) if(MITK_XVFB_TESTING) set(xvfb_run ${MITK_XVFB_TESTING_COMMAND}) else() set(xvfb_run ) endif() add_test(NAME ${test_name} COMMAND ${xvfb_run} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} ${test_function} ${ARGN}) - set_property(TEST ${test_name} PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) mitkFunctionGetLibrarySearchPaths(MITK_RUNTIME_PATH_RELEASE release RELEASE) mitkFunctionGetLibrarySearchPaths(MITK_RUNTIME_PATH_DEBUG debug DEBUG) set(test_env_path ${MITK_RUNTIME_PATH_RELEASE} ${MITK_RUNTIME_PATH_DEBUG} $ENV{PATH}) list(REMOVE_DUPLICATES test_env_path) string (REGEX REPLACE "\;" "\\\;" test_env_path "${test_env_path}") set_property(TEST ${test_name} PROPERTY ENVIRONMENT "PATH=${test_env_path}" APPEND) set_property(TEST ${test_name} PROPERTY SKIP_RETURN_CODE 77) endif() endfunction() diff --git a/CMake/mitkFunctionAddTestLabel.cmake b/CMake/mitkFunctionAddTestLabel.cmake deleted file mode 100644 index 57d44da7bc..0000000000 --- a/CMake/mitkFunctionAddTestLabel.cmake +++ /dev/null @@ -1,15 +0,0 @@ -# -# Use to attach a CTest/CDash label to a test (already added via ADD_TEST) -# -# Call with or without an explicit second parameter. If no second parameter is given, -# ${MITK_DEFAULT_SUBPROJECTS} will be used as standard label -# -function(mitkFunctionAddTestLabel test_name) - set(label ${MITK_DEFAULT_SUBPROJECTS}) - if(ARGN) - set(label ${ARGN}) - endif() - set_property(TEST ${test_name} APPEND PROPERTY LABELS ${label}) -endfunction(mitkFunctionAddTestLabel) - - diff --git a/CMake/mitkFunctionCompileSnippets.cmake b/CMake/mitkFunctionCompileSnippets.cmake index ea5ca47ef5..e6632fe0fb 100644 --- a/CMake/mitkFunctionCompileSnippets.cmake +++ b/CMake/mitkFunctionCompileSnippets.cmake @@ -1,50 +1,49 @@ function(mitkFunctionCompileSnippets snippet_path) # get all files called "main.cpp" file(GLOB_RECURSE main_cpp_list "${snippet_path}/main.cpp") foreach(main_cpp_file ${main_cpp_list}) # get the directory containing the main.cpp file get_filename_component(main_cpp_dir "${main_cpp_file}" PATH) set(snippet_src_files ) # If there exists a "files.cmake" file in the snippet directory, # include it and assume it sets the variable "snippet_src_files" # to a list of source files for the snippet. if(EXISTS "${main_cpp_dir}/files.cmake") include("${main_cpp_dir}/files.cmake") set(_tmp_src_files ${snippet_src_files}) set(snippet_src_files ) foreach(_src_file ${_tmp_src_files}) if(IS_ABSOLUTE ${_src_file}) list(APPEND snippet_src_files ${_src_file}) else() list(APPEND snippet_src_files ${main_cpp_dir}/${_src_file}) endif() endforeach() else() # glob all files in the directory and add them to the snippet src list file(GLOB_RECURSE snippet_src_files "${main_cpp_dir}/*") endif() # Uset the top-level directory name as the executable name string(REPLACE "/" ";" main_cpp_dir_tokens "${main_cpp_dir}") list(GET main_cpp_dir_tokens -1 snippet_exec_name) set(snippet_target_name "Snippet-${snippet_exec_name}") add_executable(${snippet_target_name} ${snippet_src_files}) if(ARGN) target_link_libraries(${snippet_target_name} ${ARGN}) endif() set_target_properties(${snippet_target_name} PROPERTIES - LABELS Documentation RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/snippets" ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/snippets" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/snippets" OUTPUT_NAME ${snippet_exec_name} FOLDER "${MITK_ROOT_FOLDER}/Documentation/Snippets" ) endforeach() endfunction() diff --git a/CMake/mitkFunctionCreateModule.cmake b/CMake/mitkFunctionCreateModule.cmake index 6e17f8a5ed..e89c11457f 100644 --- a/CMake/mitkFunctionCreateModule.cmake +++ b/CMake/mitkFunctionCreateModule.cmake @@ -1,677 +1,646 @@ ################################################################## # # mitk_create_module # #! Creates a module for the automatic module dependency system within MITK. #! #! Example: #! #! \code #! mitk_create_module( #! DEPENDS PUBLIC MitkCore #! PACKAGE_DEPENDS #! PRIVATE Qt5|Xml+Networking #! PUBLIC ITK|Watershed #! \endcode #! #! The parameter specifies the name of the module which is used #! to create a logical target name. The parameter is optional in case the #! MITK_MODULE_NAME_DEFAULTS_TO_DIRECTORY_NAME variable evaluates to TRUE. The #! module name will then be derived from the directory name in which this #! function is called. #! #! If set, the following variables will be used to validate the module name: #! #! MITK_MODULE_NAME_REGEX_MATCH The module name must match this regular expression. #! MITK_MODULE_NAME_REGEX_NOT_MATCH The module name must not match this regular expression. #! #! If the MITK_MODULE_NAME_PREFIX variable is set, the module name will be prefixed #! with its contents. #! #! A modules source files are specified in a separate CMake file usually #! called files.cmake, located in the module root directory. The #! mitk_create_module() macro evaluates the following CMake variables #! from the files.cmake file: #! #! - CPP_FILES A list of .cpp files #! - H_FILES A list of .h files without a corresponding .cpp file #! - TXX_FILES A list of .txx files #! - RESOURCE_FILES A list of files (resources) which are embedded into the module #! - MOC_H_FILES A list of Qt header files which should be processed by the MOC #! - UI_FILES A list of .ui Qt UI files #! - QRC_FILES A list of .qrc Qt resource files #! - DOX_FILES A list of .dox Doxygen files #! #! List of variables available after the function is called: #! - MODULE_NAME #! - MODULE_TARGET #! - MODULE_IS_ENABLED -#! - MODULE_SUBPROJECTS #! #! \sa mitk_create_executable #! #! Parameters (all optional): #! #! \param The module name (also used as target name) #! \param FILES_CMAKE File name of a CMake file setting source list variables #! (defaults to files.cmake) #! \param VERSION Module version number, e.g. "1.2.0" #! \param AUTOLOAD_WITH A module target name identifying the module which will #! trigger the automatic loading of this module #! \param DEPRECATED_SINCE Marks this modules as deprecated since #! \param DESCRIPTION A description for this module #! #! Multi-value Parameters (all optional): #! -#! \param SUBPROJECTS List of CDash labels #! \param INCLUDE_DIRS Include directories for this module: #! \verbatim #! [[PUBLIC|PRIVATE|INTERFACE] ...]... #! \endverbatim #! The default scope for include directories is PUBLIC. #! \param DEPENDS List of module dependencies: #! \verbatim #! [[PUBLIC|PRIVATE|INTERFACE] ...]... #! \endverbatim #! The default scope for module dependencies is PUBLIC. #! \param PACKAGE_DEPENDS List of public packages dependencies (e.g. Qt, VTK, etc.). #! Package dependencies have the following syntax: #! \verbatim #! [PUBLIC|PRIVATE|INTERFACE] PACKAGE[|COMPONENT1[+COMPONENT2]...] #! \endverbatim #! The default scope for package dependencies is PRIVATE. #! \param ADDITIONAL_LIBS List of additional private libraries linked to this module. #! The folder containing the library will be added to the global list of library search paths. #! \param CPP_FILES List of source files for this module. If the list is non-empty, #! the module does not need to provide a files.cmake file or FILES_CMAKE argument. #! \param H_FILES List of public header files for this module. It is recommended to use #! a files.cmake file instead. #! #! Options (optional) #! #! \param FORCE_STATIC Force building this module as a static library #! \param GCC_DEFAULT_VISIBILITY Do not use gcc visibility flags - all #! symbols will be exported #! \param NO_INIT Do not create CppMicroServices initialization code #! \param NO_FEATURE_INFO Do not create a feature info by calling add_feature_info() #! \param WARNINGS_NO_ERRORS Do not treat compiler warnings as errors # ################################################################## function(mitk_create_module) set(_macro_params VERSION # module version number, e.g. "1.2.0" EXPORT_DEFINE # export macro name for public symbols of this module (DEPRECATED) AUTOLOAD_WITH # a module target name identifying the module which will trigger the # automatic loading of this module FILES_CMAKE # file name of a CMake file setting source list variables # (defaults to files.cmake) DEPRECATED_SINCE # marks this modules as deprecated DESCRIPTION # a description for this module ) set(_macro_multiparams - SUBPROJECTS # list of CDash labels + SUBPROJECTS # list of CDash labels (deprecated) INCLUDE_DIRS # include directories: [PUBLIC|PRIVATE|INTERFACE] INTERNAL_INCLUDE_DIRS # include dirs internal to this module (DEPRECATED) DEPENDS # list of modules this module depends on: [PUBLIC|PRIVATE|INTERFACE] DEPENDS_INTERNAL # list of modules this module internally depends on (DEPRECATED) PACKAGE_DEPENDS # list of "packages this module depends on (e.g. Qt, VTK, etc.): [PUBLIC|PRIVATE|INTERFACE] TARGET_DEPENDS # list of CMake targets this module should depend on ADDITIONAL_LIBS # list of addidtional private libraries linked to this module. CPP_FILES # list of cpp files H_FILES # list of header files: [PUBLIC|PRIVATE] ) set(_macro_options FORCE_STATIC # force building this module as a static library HEADERS_ONLY # this module is a headers-only library GCC_DEFAULT_VISIBILITY # do not use gcc visibility flags - all symbols will be exported NO_DEFAULT_INCLUDE_DIRS # do not add default include directories like "include" or "." NO_INIT # do not create CppMicroServices initialization code NO_FEATURE_INFO # do not create a feature info by calling add_feature_info() WARNINGS_NO_ERRORS # do not treat compiler warnings as errors EXECUTABLE # create an executable; do not use directly, use mitk_create_executable() instead C_MODULE # compile all source files as C sources CXX_MODULE # compile all source files as C++ sources ) cmake_parse_arguments(MODULE "${_macro_options}" "${_macro_params}" "${_macro_multiparams}" ${ARGN}) set(MODULE_NAME ${MODULE_UNPARSED_ARGUMENTS}) # ----------------------------------------------------------------- # Sanity checks if(NOT MODULE_NAME) if(MITK_MODULE_NAME_DEFAULTS_TO_DIRECTORY_NAME) get_filename_component(MODULE_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) else() message(SEND_ERROR "The module name must not be empty") endif() endif() set(_deprecated_args INTERNAL_INCLUDE_DIRS DEPENDS_INTERNAL EXPORT_DEFINE TARGET_DEPENDS HEADERS_ONLY) foreach(_deprecated_arg ${_deprecated_args}) if(MODULE_${_deprecated_arg}) message(WARNING "The ${_deprecated_arg} argument is deprecated") endif() endforeach() set(_module_type module) set(_Module_type Module) if(MODULE_EXECUTABLE) set(_module_type executable) set(_Module_type Executable) endif() if(MITK_MODULE_NAME_REGEX_MATCH) if(NOT ${MODULE_NAME} MATCHES ${MITK_MODULE_NAME_REGEX_MATCH}) message(SEND_ERROR "The ${_module_type} name \"${MODULE_NAME}\" does not match the regular expression \"${MITK_MODULE_NAME_REGEX_MATCH}\".") endif() endif() if(MITK_MODULE_NAME_REGEX_NOT_MATCH) if(${MODULE_NAME} MATCHES ${MITK_MODULE_NAME_REGEX_NOT_MATCH}) message(SEND_ERROR "The ${_module_type} name \"${MODULE_NAME}\" must not match the regular expression \"${MITK_MODULE_NAME_REGEX_NOT_MATCH}\".") endif() endif() if(MITK_MODULE_NAME_PREFIX AND NOT MODULE_NAME MATCHES "^${MITK_MODULE_NAME_PREFIX}.*$") set(MODULE_NAME "${MITK_MODULE_NAME_PREFIX}${MODULE_NAME}") endif() if(NOT MODULE_FILES_CMAKE) set(MODULE_FILES_CMAKE files.cmake) endif() if(NOT IS_ABSOLUTE ${MODULE_FILES_CMAKE}) set(MODULE_FILES_CMAKE ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_FILES_CMAKE}) endif() - if(NOT MODULE_SUBPROJECTS) - if(MITK_DEFAULT_SUBPROJECTS) - set(MODULE_SUBPROJECTS ${MITK_DEFAULT_SUBPROJECTS}) - elseif(TARGET MITK-Modules) - set(MODULE_SUBPROJECTS MITK-Modules) - endif() - endif() - - # check if the subprojects exist as targets - if(MODULE_SUBPROJECTS) - foreach(subproject ${MODULE_SUBPROJECTS}) - if(NOT TARGET ${subproject}) - message(SEND_ERROR "The subproject ${subproject} does not have a corresponding target") - endif() - endforeach() - endif() - # ----------------------------------------------------------------- # Check if module should be build set(MODULE_TARGET ${MODULE_NAME}) # assume worst case set(MODULE_IS_ENABLED 0) # first we check if we have an explicit module build list if(MITK_MODULES_TO_BUILD) list(FIND MITK_MODULES_TO_BUILD ${MODULE_NAME} _MOD_INDEX) if(_MOD_INDEX EQUAL -1) set(MODULE_IS_EXCLUDED 1) endif() endif() if(NOT MODULE_IS_EXCLUDED) # first of all we check for the dependencies _mitk_parse_package_args(${MODULE_PACKAGE_DEPENDS}) mitk_check_module_dependencies(MODULES ${MODULE_DEPENDS} PACKAGES ${PACKAGE_NAMES} MISSING_DEPENDENCIES_VAR _MISSING_DEP PACKAGE_DEPENDENCIES_VAR PACKAGE_NAMES) if(_MISSING_DEP) if(MODULE_NO_FEATURE_INFO) message("${_Module_type} ${MODULE_NAME} won't be built, missing dependency: ${_MISSING_DEP}") endif() set(MODULE_IS_ENABLED 0) else() foreach(dep ${MODULE_DEPENDS}) if(TARGET ${dep}) get_target_property(AUTLOAD_DEP ${dep} MITK_AUTOLOAD_DIRECTORY) if (AUTLOAD_DEP) message(SEND_ERROR "Module \"${MODULE_NAME}\" has an invalid dependency on autoload module \"${dep}\". Check MITK_CREATE_MODULE usage for \"${MODULE_NAME}\".") endif() endif() endforeach(dep) set(MODULE_IS_ENABLED 1) # now check for every package if it is enabled. This overlaps a bit with # MITK_CHECK_MODULE ... foreach(_package ${PACKAGE_NAMES}) if((DEFINED MITK_USE_${_package}) AND NOT (MITK_USE_${_package})) message("${_Module_type} ${MODULE_NAME} won't be built. Turn on MITK_USE_${_package} if you want to use it.") set(MODULE_IS_ENABLED 0) break() endif() endforeach() endif() endif() # ----------------------------------------------------------------- # Start creating the module if(MODULE_IS_ENABLED) # clear variables defined in files.cmake set(RESOURCE_FILES ) set(CPP_FILES ) set(H_FILES ) set(TXX_FILES ) set(DOX_FILES ) set(UI_FILES ) set(MOC_H_FILES ) set(QRC_FILES ) # clear other variables set(Q${KITNAME}_GENERATED_CPP ) set(Q${KITNAME}_GENERATED_MOC_CPP ) set(Q${KITNAME}_GENERATED_QRC_CPP ) set(Q${KITNAME}_GENERATED_UI_CPP ) # check and set-up auto-loading if(MODULE_AUTOLOAD_WITH) if(NOT TARGET "${MODULE_AUTOLOAD_WITH}") message(SEND_ERROR "The module target \"${MODULE_AUTOLOAD_WITH}\" specified as the auto-loading module for \"${MODULE_NAME}\" does not exist") endif() endif() set(_module_autoload_meta_target "${CMAKE_PROJECT_NAME}-autoload") # create a meta-target if it does not already exist if(NOT TARGET ${_module_autoload_meta_target}) add_custom_target(${_module_autoload_meta_target}) set_property(TARGET ${_module_autoload_meta_target} PROPERTY FOLDER "${MITK_ROOT_FOLDER}/Modules/Autoload") endif() if(NOT MODULE_EXPORT_DEFINE) set(MODULE_EXPORT_DEFINE ${MODULE_NAME}_EXPORT) endif() if(MITK_GENERATE_MODULE_DOT) message("MODULEDOTNAME ${MODULE_NAME}") foreach(dep ${MODULE_DEPENDS}) message("MODULEDOT \"${MODULE_NAME}\" -> \"${dep}\" ; ") endforeach(dep) endif(MITK_GENERATE_MODULE_DOT) if (EXISTS ${MODULE_FILES_CMAKE}) include(${MODULE_FILES_CMAKE}) endif() if(MODULE_CPP_FILES) list(APPEND CPP_FILES ${MODULE_CPP_FILES}) endif() if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src") # Preprend the "src" directory to the cpp file list set(_cpp_files ${CPP_FILES}) set(CPP_FILES ) foreach(_cpp_file ${_cpp_files}) list(APPEND CPP_FILES "src/${_cpp_file}") endforeach() endif() if(CPP_FILES OR RESOURCE_FILES OR UI_FILES OR MOC_H_FILES OR QRC_FILES) set(MODULE_HEADERS_ONLY 0) if(MODULE_C_MODULE) set_source_files_properties(${CPP_FILES} PROPERTIES LANGUAGE C) elseif(MODULE_CXX_MODULE) set_source_files_properties(${CPP_FILES} PROPERTIES LANGUAGE CXX) endif() else() set(MODULE_HEADERS_ONLY 1) if(MODULE_AUTOLOAD_WITH) message(SEND_ERROR "A headers only module cannot be auto-loaded") endif() endif() set(module_c_flags ) set(module_c_flags_debug ) set(module_c_flags_release ) set(module_cxx_flags ) set(module_cxx_flags_debug ) set(module_cxx_flags_release ) if(MODULE_GCC_DEFAULT_VISIBILITY OR NOT CMAKE_COMPILER_IS_GNUCXX) # We only support hidden visibility for gcc for now. Clang still has troubles with # correctly marking template declarations and explicit template instantiations as exported. # See http://comments.gmane.org/gmane.comp.compilers.clang.scm/50028 # and http://llvm.org/bugs/show_bug.cgi?id=10113 set(CMAKE_CXX_VISIBILITY_PRESET default) set(CMAKE_VISIBILITY_INLINES_HIDDEN 0) else() set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) endif() if(NOT MODULE_WARNINGS_NO_ERRORS) if(MSVC_VERSION) mitkFunctionCheckCAndCXXCompilerFlags("/WX" module_c_flags module_cxx_flags) # this would turn on unused parameter warnings, but unfortunately MSVC cannot # distinguish yet between internal and external headers so this would be triggered # a lot by external code. There is support for it on the way so this line could be # reactivated after https://gitlab.kitware.com/cmake/cmake/issues/17904 has been fixed. # mitkFunctionCheckCAndCXXCompilerFlags("/w34100" module_c_flags module_cxx_flags) else() mitkFunctionCheckCAndCXXCompilerFlags(-Werror module_c_flags module_cxx_flags) # The flag "c++0x-static-nonintegral-init" has been renamed in newer Clang # versions to "static-member-init", see # http://clang-developers.42468.n3.nabble.com/Wc-0x-static-nonintegral-init-gone-td3999651.html # # Also, older Clang and seemingly all gcc versions do not warn if unknown # "-no-*" flags are used, so CMake will happily append any -Wno-* flag to the # command line. This may get confusing if unrelated compiler errors happen and # the error output then additionally contains errors about unknown flags (which # is not the case if there were no compile errors). # # So instead of using -Wno-* we use -Wno-error=*, which will be properly rejected by # the compiler and if applicable, prints the specific warning as a real warning and # not as an error (although -Werror was given). mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=c++0x-static-nonintegral-init" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=static-member-init" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=unknown-warning" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=gnu" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=class-memaccess" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=inconsistent-missing-override" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=deprecated-copy" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=cast-function-type" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=deprecated-declarations" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=type-limits" module_c_flags module_cxx_flags) endif() endif() if(MODULE_FORCE_STATIC) set(_STATIC STATIC) else() set(_STATIC ) endif(MODULE_FORCE_STATIC) if(NOT MODULE_HEADERS_ONLY) if(NOT MODULE_NO_INIT OR RESOURCE_FILES) find_package(CppMicroServices QUIET NO_MODULE REQUIRED) endif() if(NOT MODULE_NO_INIT) usFunctionGenerateModuleInit(CPP_FILES) endif() set(binary_res_files ) set(source_res_files ) if(RESOURCE_FILES) if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/resource") set(res_dir resource) elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Resources") set(res_dir Resources) else() message(SEND_ERROR "Resources specified but ${CMAKE_CURRENT_SOURCE_DIR}/resource directory not found.") endif() foreach(res_file ${RESOURCE_FILES}) if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${res_dir}/${res_file}) list(APPEND binary_res_files "${res_file}") else() list(APPEND source_res_files "${res_file}") endif() endforeach() # Add a source level dependencies on resource files usFunctionGetResourceSource(TARGET ${MODULE_TARGET} OUT CPP_FILES) endif() endif() if(MITK_USE_Qt5) if(UI_FILES) qt5_wrap_ui(Q${KITNAME}_GENERATED_UI_CPP ${UI_FILES}) endif() if(MOC_H_FILES) qt5_wrap_cpp(Q${KITNAME}_GENERATED_MOC_CPP ${MOC_H_FILES} OPTIONS -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) endif() if(QRC_FILES) qt5_add_resources(Q${KITNAME}_GENERATED_QRC_CPP ${QRC_FILES}) endif() endif() set(Q${KITNAME}_GENERATED_CPP ${Q${KITNAME}_GENERATED_CPP} ${Q${KITNAME}_GENERATED_UI_CPP} ${Q${KITNAME}_GENERATED_MOC_CPP} ${Q${KITNAME}_GENERATED_QRC_CPP}) mitkFunctionOrganizeSources( SOURCE ${CPP_FILES} HEADER ${H_FILES} TXX ${TXX_FILES} DOC ${DOX_FILES} UI ${UI_FILES} QRC ${QRC_FILES} MOC ${Q${KITNAME}_GENERATED_MOC_CPP} GEN_QRC ${Q${KITNAME}_GENERATED_QRC_CPP} GEN_UI ${Q${KITNAME}_GENERATED_UI_CPP} ) set(coverage_sources ${CPP_FILES} ${H_FILES} ${GLOBBED__H_FILES} ${CORRESPONDING__H_FILES} ${TXX_FILES} ${TOOL_CPPS} ${TOOL_GUI_CPPS}) - if(MODULE_SUBPROJECTS) - set_property(SOURCE ${coverage_sources} APPEND PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) - endif() - # --------------------------------------------------------------- # Create the actual module target if(MODULE_HEADERS_ONLY) add_library(${MODULE_TARGET} INTERFACE) # INTERFACE_LIBRARY targets may only have whitelisted properties. The property "FOLDER" is not allowed. # set_property(TARGET ${MODULE_TARGET} PROPERTY FOLDER "${MITK_ROOT_FOLDER}/Modules") else() if(MODULE_EXECUTABLE) add_executable(${MODULE_TARGET} ${MODULE_CPP_FILES} ${coverage_sources} ${CPP_FILES_GENERATED} ${Q${KITNAME}_GENERATED_CPP} ${DOX_FILES} ${UI_FILES} ${QRC_FILES}) set_property(TARGET ${MODULE_TARGET} PROPERTY FOLDER "${MITK_ROOT_FOLDER}/Modules/Executables") set(_us_module_name main) else() add_library(${MODULE_TARGET} ${_STATIC} ${coverage_sources} ${CPP_FILES_GENERATED} ${Q${KITNAME}_GENERATED_CPP} ${DOX_FILES} ${UI_FILES} ${QRC_FILES}) set_property(TARGET ${MODULE_TARGET} PROPERTY FOLDER "${MITK_ROOT_FOLDER}/Modules") set(_us_module_name ${MODULE_TARGET}) endif() # Apply properties to the module target. target_compile_definitions(${MODULE_TARGET} PRIVATE US_MODULE_NAME=${_us_module_name}) if(MODULE_C_MODULE) if(module_c_flags) string(REPLACE " " ";" module_c_flags "${module_c_flags}") target_compile_options(${MODULE_TARGET} PRIVATE ${module_c_flags}) endif() if(module_c_flags_debug) string(REPLACE " " ";" module_c_flags_debug "${module_c_flags_debug}") target_compile_options(${MODULE_TARGET} PRIVATE $<$:${module_c_flags_debug}>) endif() if(module_c_flags_release) string(REPLACE " " ";" module_c_flags_release "${module_c_flags_release}") target_compile_options(${MODULE_TARGET} PRIVATE $<$:${module_c_flags_release}>) endif() else() if(module_cxx_flags) string(REPLACE " " ";" module_cxx_flags "${module_cxx_flags}") target_compile_options(${MODULE_TARGET} PRIVATE ${module_cxx_flags}) endif() if(module_cxx_flags_debug) string(REPLACE " " ";" module_cxx_flags_debug "${module_cxx_flags_debug}") target_compile_options(${MODULE_TARGET} PRIVATE $<$:${module_cxx_flags_debug}>) endif() if(module_cxx_flags_release) string(REPLACE " " ";" module_cxx_flags_release "${module_cxx_flags_release}") target_compile_options(${MODULE_TARGET} PRIVATE $<$:${module_cxx_flags_release}>) endif() endif() set_property(TARGET ${MODULE_TARGET} PROPERTY US_MODULE_NAME ${_us_module_name}) # Add additional library search directories to a global property which # can be evaluated by other CMake macros, e.g. our install scripts. if(MODULE_ADDITIONAL_LIBS) target_link_libraries(${MODULE_TARGET} PRIVATE ${MODULE_ADDITIONAL_LIBS}) get_property(_mitk_additional_library_search_paths GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS) foreach(_lib_filepath ${MODULE_ADDITIONAL_LIBS}) get_filename_component(_search_path "${_lib_filepath}" PATH) if(_search_path) list(APPEND _mitk_additional_library_search_paths "${_search_path}") endif() endforeach() if(_mitk_additional_library_search_paths) list(REMOVE_DUPLICATES _mitk_additional_library_search_paths) set_property(GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS ${_mitk_additional_library_search_paths}) endif() endif() # add the target name to a global property which is used in the top-level # CMakeLists.txt file to export the target set_property(GLOBAL APPEND PROPERTY MITK_MODULE_TARGETS ${MODULE_TARGET}) if(MODULE_AUTOLOAD_WITH) # for auto-loaded modules, adapt the output directory add_dependencies(${_module_autoload_meta_target} ${MODULE_TARGET}) if(WIN32) set(_module_output_prop RUNTIME_OUTPUT_DIRECTORY) else() set(_module_output_prop LIBRARY_OUTPUT_DIRECTORY) endif() set(_module_output_dir ${CMAKE_${_module_output_prop}}/${MODULE_AUTOLOAD_WITH}) get_target_property(_module_is_imported ${MODULE_AUTOLOAD_WITH} IMPORTED) if(NOT _module_is_imported) # if the auto-loading module is not imported, get its location # and put the auto-load module relative to it. get_target_property(_module_output_dir ${MODULE_AUTOLOAD_WITH} ${_module_output_prop}) set_target_properties(${MODULE_TARGET} PROPERTIES ${_module_output_prop} ${_module_output_dir}/${MODULE_AUTOLOAD_WITH}) else() set_target_properties(${MODULE_TARGET} PROPERTIES ${_module_output_prop} ${CMAKE_${_module_output_prop}}/${MODULE_AUTOLOAD_WITH}) endif() set_target_properties(${MODULE_TARGET} PROPERTIES MITK_AUTOLOAD_DIRECTORY ${MODULE_AUTOLOAD_WITH}) # add the auto-load module name as a property set_property(TARGET ${MODULE_AUTOLOAD_WITH} APPEND PROPERTY MITK_AUTOLOAD_TARGETS ${MODULE_TARGET}) endif() if(binary_res_files) usFunctionAddResources(TARGET ${MODULE_TARGET} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${res_dir} FILES ${binary_res_files}) endif() if(source_res_files) usFunctionAddResources(TARGET ${MODULE_TARGET} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${res_dir} FILES ${source_res_files}) endif() if(binary_res_files OR source_res_files) usFunctionEmbedResources(TARGET ${MODULE_TARGET}) endif() if(MODULE_DEPRECATED_SINCE) set_property(TARGET ${MODULE_TARGET} PROPERTY MITK_MODULE_DEPRECATED_SINCE ${MODULE_DEPRECATED_SINCE}) endif() # create export macros if (NOT MODULE_EXECUTABLE) set(_export_macro_name ) if(MITK_LEGACY_EXPORT_MACRO_NAME) set(_export_macro_names EXPORT_MACRO_NAME ${MODULE_EXPORT_DEFINE} NO_EXPORT_MACRO_NAME ${MODULE_NAME}_NO_EXPORT DEPRECATED_MACRO_NAME ${MODULE_NAME}_DEPRECATED NO_DEPRECATED_MACRO_NAME ${MODULE_NAME}_NO_DEPRECATED ) endif() generate_export_header(${MODULE_NAME} ${_export_macro_names} EXPORT_FILE_NAME ${MODULE_NAME}Exports.h ) endif() target_include_directories(${MODULE_TARGET} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) endif() # --------------------------------------------------------------- # Properties for both header-only and compiled modules if(MODULE_HEADERS_ONLY) set(_module_property_type INTERFACE) else() set(_module_property_type PUBLIC) endif() if(MODULE_TARGET_DEPENDS) add_dependencies(${MODULE_TARGET} ${MODULE_TARGET_DEPENDS}) endif() - if(MODULE_SUBPROJECTS AND NOT MODULE_HEADERS_ONLY) - set_property(TARGET ${MODULE_TARGET} PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) - foreach(subproject ${MODULE_SUBPROJECTS}) - add_dependencies(${subproject} ${MODULE_TARGET}) - endforeach() - endif() - set(DEPENDS "${MODULE_DEPENDS}") if(NOT MODULE_NO_INIT AND NOT MODULE_HEADERS_ONLY) # Add a CppMicroServices dependency implicitly, since it is # needed for the generated "module initialization" code. set(DEPENDS "CppMicroServices;${DEPENDS}") endif() if(DEPENDS OR MODULE_PACKAGE_DEPENDS) mitk_use_modules(TARGET ${MODULE_TARGET} MODULES ${DEPENDS} PACKAGES ${MODULE_PACKAGE_DEPENDS} ) endif() if(NOT MODULE_C_MODULE) target_compile_features(${MODULE_TARGET} ${_module_property_type} ${MITK_CXX_FEATURES}) endif() # add include directories if(MODULE_INTERNAL_INCLUDE_DIRS) target_include_directories(${MODULE_TARGET} PRIVATE ${MODULE_INTERNAL_INCLUDE_DIRS}) endif() if(NOT MODULE_NO_DEFAULT_INCLUDE_DIRS) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/include) target_include_directories(${MODULE_TARGET} ${_module_property_type} include) else() target_include_directories(${MODULE_TARGET} ${_module_property_type} .) endif() if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src) target_include_directories(${MODULE_TARGET} PRIVATE src) endif() endif() target_include_directories(${MODULE_TARGET} ${_module_property_type} ${MODULE_INCLUDE_DIRS}) endif() # ----------------------------------------------------------------- # Record missing dependency information if(_MISSING_DEP) if(MODULE_DESCRIPTION) set(MODULE_DESCRIPTION "${MODULE_DESCRIPTION} (missing dependencies: ${_MISSING_DEP})") else() set(MODULE_DESCRIPTION "(missing dependencies: ${_MISSING_DEP})") endif() endif() if(NOT MODULE_NO_FEATURE_INFO) add_feature_info(${MODULE_NAME} MODULE_IS_ENABLED "${MODULE_DESCRIPTION}") endif() set(MODULE_NAME ${MODULE_NAME} PARENT_SCOPE) set(MODULE_TARGET ${MODULE_TARGET} PARENT_SCOPE) set(MODULE_IS_ENABLED ${MODULE_IS_ENABLED} PARENT_SCOPE) - set(MODULE_SUBPROJECTS ${MODULE_SUBPROJECTS} PARENT_SCOPE) endfunction() diff --git a/CMake/mitkFunctionCreatePlugin.cmake b/CMake/mitkFunctionCreatePlugin.cmake index 72fa8012d9..680bc2c38d 100644 --- a/CMake/mitkFunctionCreatePlugin.cmake +++ b/CMake/mitkFunctionCreatePlugin.cmake @@ -1,365 +1,350 @@ #! \brief Creates a MITK CTK plugin. #! #! This function should be called from the plugins CMakeLists.txt file. #! The target name is available after the macro call as ${PLUGIN_TARGET} #! to add additional libraries in your CMakeLists.txt. Include paths and link #! libraries are set depending on the value of the Required-Plugins header #! in your manifest_headers.cmake file. #! #! This function internally calls ctkMacroBuildPlugin() and adds support #! for Qt Help files and installers. #! #! Options: #! \param TEST_PLUGIN Mark this plug-in as a testing plug-in. #! \param NO_INSTALL Don't install this plug-in. #! #! Parameters: #! #! \param EXPORT_DIRECTIVE (required) The export directive to use in the generated #! _Exports.h file. #! #! Multi-value parameters (all optional): #! #! \param EXPORTED_INCLUDE_SUFFIXES A list of sub-directories which should #! be added to the current source directory. The resulting directories #! will be available in the set of include directories of depending plug-ins. #! \param MODULE_DEPENDS (optional) A list of Modules this plug-in depends on. #! \param PACKAGE_DEPENDS (optional) A list of external packages this plug-in depends on. #! \param DOXYGEN_TAGFILES (optional) Which external tag files should be available for the plugin documentation #! \param MOC_OPTIONS (optional) Additional options to pass to the Qt MOC compiler #! \param WARNINGS_NO_ERRORS (optional) Do not handle compiler warnings as errors function(mitk_create_plugin) # options set(arg_options TEST_PLUGIN # Mark this plug-in as a testing plug-in NO_INSTALL # Don't install this plug-in NO_QHP_TRANSFORM WARNINGS_NO_ERRORS ) # single value arguments set(arg_single EXPORT_DIRECTIVE # (required) TODO: could be generated via CMake as it is done for MITK modules already ) # multiple value arguments set(arg_multiple EXPORTED_INCLUDE_SUFFIXES # (optional) additional public include directories MODULE_DEPENDS # (optional) PACKAGE_DEPENDS DOXYGEN_TAGFILES MOC_OPTIONS - SUBPROJECTS + SUBPROJECTS # deprecated ) cmake_parse_arguments(_PLUGIN "${arg_options}" "${arg_single}" "${arg_multiple}" ${ARGN}) if(_PLUGIN_TEST_PLUGIN) set(_PLUGIN_NO_INSTALL 1) set(is_test_plugin "TEST_PLUGIN") else() set(is_test_plugin) endif() set(_PLUGIN_MOC_OPTIONS "-DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED ${_PLUGIN_MOC_OPTIONS}") set(PLUGIN_TARGET ${PROJECT_NAME}) mitk_check_module_dependencies(MODULES ${_PLUGIN_MODULE_DEPENDS} PACKAGES ${_PLUGIN_PACKAGE_DEPENDS} MISSING_DEPENDENCIES_VAR _missing_deps MODULE_DEPENDENCIES_VAR _module_deps PACKAGE_DEPENDENCIES_VAR _package_deps) if(_missing_deps) if(NOT MITK_BUILD_ALL_PLUGINS) message(SEND_ERROR "${PROJECT_NAME} is missing requirements and won't be built. Missing: ${_missing_deps}") else() message(STATUS "${PROJECT_NAME} is missing requirements and won't be built. Missing: ${_missing_deps}") endif() return() endif() foreach(_module_dep ${_PLUGIN_MODULE_DEPENDS}) if(TARGET ${_module_dep}) get_target_property(AUTLOAD_DEP ${_module_dep} MITK_AUTOLOAD_DIRECTORY) if (AUTLOAD_DEP) message(SEND_ERROR "Plugin \"${PROJECT_NAME}\" has an invalid dependency on autoload module \"${_module_dep}\". Check MITK_CREATE_PLUGIN usage for \"${PROJECT_NAME}\".") endif() endif() endforeach() # -------------- All dependencies are resolved ------------------ message(STATUS "Creating CTK plugin ${PROJECT_NAME}") include(files.cmake) set(_PLUGIN_CPP_FILES ${CPP_FILES}) set(_PLUGIN_MOC_H_FILES ${MOC_H_FILES}) set(_PLUGIN_UI_FILES ${UI_FILES}) set(_PLUGIN_CACHED_RESOURCE_FILES ${CACHED_RESOURCE_FILES}) set(_PLUGIN_TRANSLATION_FILES ${TRANSLATION_FILES}) set(_PLUGIN_QRC_FILES ${QRC_FILES}) set(_PLUGIN_H_FILES ${H_FILES}) set(_PLUGIN_TXX_FILES ${TXX_FILES}) set(_PLUGIN_DOX_FILES ${DOX_FILES}) set(_PLUGIN_CMAKE_FILES ${CMAKE_FILES} files.cmake) set(_PLUGIN_FILE_DEPENDENCIES ${FILE_DEPENDENCIES}) if(CTK_PLUGINS_OUTPUT_DIR) set(_output_dir "${CTK_PLUGINS_OUTPUT_DIR}") else() set(_output_dir "") endif() # Compute the plugin dependencies ctkFunctionGetTargetLibraries(_PLUGIN_target_libraries "") #------------------------------------------------------------# #------------------ Qt Help support -------------------------# set(PLUGIN_GENERATED_QCH_FILES ) if(BLUEBERRY_USE_QT_HELP AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/documentation/UserManual") set(PLUGIN_DOXYGEN_INPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/documentation/UserManual") set(PLUGIN_DOXYGEN_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/documentation/UserManual") # Create a list of Doxygen tag files from the plug-in dependencies set(PLUGIN_DOXYGEN_TAGFILES) foreach(_dep_target ${_PLUGIN_target_libraries}) string(REPLACE _ . _dep ${_dep_target}) get_target_property(_is_imported ${_dep_target} IMPORTED) if(_is_imported) get_target_property(_import_loc_debug ${_dep_target} IMPORTED_LOCATION_DEBUG) get_target_property(_import_loc_release ${_dep_target} IMPORTED_LOCATION_RELEASE) # There is not necessarily a debug and release build if(_import_loc_release) set(_import_loc ${_import_loc_release}) else() set(_import_loc ${_import_loc_debug}) endif() get_filename_component(_target_filename "${_import_loc}" NAME) # on windows there might be a Debug or Release subdirectory string(REGEX REPLACE "/bin/plugins/(Debug/|Release/)?${_target_filename}" "/Plugins/${_dep}/documentation/UserManual" plugin_tag_dir "${_import_loc}" ) else() set(plugin_tag_dir "${CMAKE_BINARY_DIR}/Plugins/${_dep}/documentation/UserManual") endif() set(_tag_file "${plugin_tag_dir}/${_dep_target}.tag") if(EXISTS ${_tag_file}) set(PLUGIN_DOXYGEN_TAGFILES "${PLUGIN_DOXYGEN_TAGFILES} \"${_tag_file}=qthelp://${_dep}/bundle/\"") endif() endforeach() if(_PLUGIN_DOXYGEN_TAGFILES) set(PLUGIN_DOXYGEN_TAGFILES "${PLUGIN_DOXYGEN_TAGFILES} ${_PLUGIN_DOXYGEN_TAGFILES}") endif() #message("PLUGIN_DOXYGEN_TAGFILES: ${PLUGIN_DOXYGEN_TAGFILES}") if(_PLUGIN_NO_QHP_TRANSFORM) set(_use_qhp_xsl 0) else() set(_use_qhp_xsl 1) endif() _FUNCTION_CREATE_CTK_QT_COMPRESSED_HELP(PLUGIN_GENERATED_QCH_FILES ${_use_qhp_xsl}) list(APPEND _PLUGIN_CACHED_RESOURCE_FILES ${PLUGIN_GENERATED_QCH_FILES}) endif() #------------------------------------------------------------# #------------------ Create Plug-in --------------------------# mitkFunctionOrganizeSources( SOURCE ${_PLUGIN_CPP_FILES} HEADER ${_PLUGIN_H_FILES} TXX ${_PLUGIN_TXX_FILES} DOC ${_PLUGIN_DOX_FILES} UI ${_PLUGIN_UI_FILES} QRC ${_PLUGIN_QRC_FILES} ${_PLUGIN_CACHED_RESOURCE_FILES} META ${_PLUGIN_META_FILES} MOC ${MY_MOC_CPP} GEN_UI ${MY_UI_CPP} GEN_QRC ${MY_QRC_SRCS} ) ctkMacroBuildPlugin( NAME ${PLUGIN_TARGET} EXPORT_DIRECTIVE ${_PLUGIN_EXPORT_DIRECTIVE} SRCS ${_PLUGIN_CPP_FILES} ${_PLUGIN_H_FILES} ${CORRESPONDING__H_FILES} ${GLOBBED__H_FILES} MOC_SRCS ${_PLUGIN_MOC_H_FILES} MOC_OPTIONS ${_PLUGIN_MOC_OPTIONS} UI_FORMS ${_PLUGIN_UI_FILES} EXPORTED_INCLUDE_SUFFIXES ${_PLUGIN_EXPORTED_INCLUDE_SUFFIXES} RESOURCES ${_PLUGIN_QRC_FILES} TARGET_LIBRARIES ${_PLUGIN_target_libraries} CACHED_RESOURCEFILES ${_PLUGIN_CACHED_RESOURCE_FILES} TRANSLATIONS ${_PLUGIN_TRANSLATION_FILES} OUTPUT_DIR ${_output_dir} NO_INSTALL # we install the plug-in ourselves ${is_test_plugin} ) mitk_use_modules(TARGET ${PLUGIN_TARGET} MODULES ${_PLUGIN_MODULE_DEPENDS} PACKAGES ${_PLUGIN_PACKAGE_DEPENDS} ) set_property(TARGET ${PLUGIN_TARGET} APPEND PROPERTY COMPILE_DEFINITIONS US_MODULE_NAME=${PLUGIN_TARGET}) set_property(TARGET ${PLUGIN_TARGET} PROPERTY US_MODULE_NAME ${PLUGIN_TARGET}) if(NOT CMAKE_CURRENT_SOURCE_DIR MATCHES "^${CMAKE_SOURCE_DIR}.*") foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) if(CMAKE_CURRENT_SOURCE_DIR MATCHES "^${MITK_EXTENSION_DIR}.*") get_filename_component(MITK_EXTENSION_ROOT_FOLDER ${MITK_EXTENSION_DIR} NAME) set_property(TARGET ${PLUGIN_TARGET} PROPERTY FOLDER "${MITK_EXTENSION_ROOT_FOLDER}/Plugins") break() endif() endforeach() else() set_property(TARGET ${PLUGIN_TARGET} PROPERTY FOLDER "${MITK_ROOT_FOLDER}/Plugins") endif() set(plugin_c_flags) set(plugin_cxx_flags) if(NOT _PLUGIN_WARNINGS_NO_ERRORS) if(MSVC_VERSION) mitkFunctionCheckCAndCXXCompilerFlags("/WX" plugin_c_flags plugin_cxx_flags) else() mitkFunctionCheckCAndCXXCompilerFlags(-Werror plugin_c_flags plugin_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=c++0x-static-nonintegral-init" plugin_c_flags plugin_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=static-member-init" plugin_c_flags plugin_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=unknown-warning" plugin_c_flags plugin_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=gnu" plugin_c_flags plugin_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=cast-function-type" plugin_c_flags plugin_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=inconsistent-missing-override" plugin_c_flags plugin_cxx_flags) endif() endif() if(plugin_c_flags) string(REPLACE " " ";" plugin_c_flags "${plugin_c_flags}") target_compile_options(${PLUGIN_TARGET} PRIVATE ${plugin_c_flags}) endif() if(plugin_cxx_flags) string(REPLACE " " ";" plugin_cxx_flags "${plugin_cxx_flags}") target_compile_options(${PLUGIN_TARGET} PRIVATE ${plugin_cxx_flags}) endif() - if(NOT MY_SUBPROJECTS) - if(MITK_DEFAULT_SUBPROJECTS) - set(MY_SUBPROJECTS ${MITK_DEFAULT_SUBPROJECTS}) - elseif(TARGET MITK-Plugins) - set(MY_SUBPROJECTS MITK-Plugins) - endif() - endif() - - if(MY_SUBPROJECTS) - set_property(TARGET ${PLUGIN_TARGET} PROPERTY LABELS ${MY_SUBPROJECTS}) - foreach(subproject ${MY_SUBPROJECTS}) - add_dependencies(${subproject} ${PLUGIN_TARGET}) - endforeach() - endif() - if(_PLUGIN_TEST_PLUGIN) find_package(CppUnit REQUIRED) target_include_directories(${PLUGIN_TARGET} PRIVATE ${CppUnit_INCLUDE_DIRS}) target_link_libraries(${PLUGIN_TARGET} PRIVATE ${CppUnit_LIBRARIES}) endif() if(mbilog_FOUND) target_link_libraries(${PLUGIN_TARGET} PRIVATE mbilog) endif() set(_PLUGIN_META_FILES "${CMAKE_CURRENT_SOURCE_DIR}/manifest_headers.cmake") if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/plugin.xml") list(APPEND _PLUGIN_META_FILES "${CMAKE_CURRENT_SOURCE_DIR}/plugin.xml") endif() set(PLUGIN_TARGET ${PLUGIN_TARGET} PARENT_SCOPE) #------------------------------------------------------------# #------------------ Installer support -----------------------# if(NOT _PLUGIN_NO_INSTALL) set(install_directories "") if(NOT MACOSX_BUNDLE_NAMES) set(install_directories bin/plugins) else(NOT MACOSX_BUNDLE_NAMES) foreach(bundle_name ${MACOSX_BUNDLE_NAMES}) list(APPEND install_directories ${bundle_name}.app/Contents/MacOS/plugins) endforeach(bundle_name) endif(NOT MACOSX_BUNDLE_NAMES) foreach(install_subdir ${install_directories}) mitkFunctionInstallCTKPlugin(TARGETS ${PLUGIN_TARGET} DESTINATION ${install_subdir}) endforeach() set(_autoload_targets ) foreach(_dependency ${_module_deps}) get_target_property(_dep_autoloads ${_dependency} MITK_AUTOLOAD_TARGETS) if (_dep_autoloads) list(APPEND _autoload_targets ${_dep_autoloads}) endif() endforeach() # The MITK_AUTOLOAD_TARGETS property is used in the mitkFunctionInstallAutoLoadModules # macro which expects a list of plug-in targets. if (_autoload_targets) list(REMOVE_DUPLICATES _autoload_targets) set_target_properties(${PLUGIN_TARGET} PROPERTIES MITK_AUTOLOAD_TARGETS "${_autoload_targets}") endif() endif() endfunction() function(_FUNCTION_CREATE_CTK_QT_COMPRESSED_HELP qch_file use_xsl) set(_manifest_path "${CMAKE_CURRENT_SOURCE_DIR}/manifest_headers.cmake") if(NOT EXISTS ${_manifest_path}) message(FATAL_ERROR "${_manifest_path} not found") endif() include(${_manifest_path}) string(REPLACE "_" "." Plugin-SymbolicName "${PLUGIN_TARGET}") configure_file(${MITK_SOURCE_DIR}/Documentation/doxygen_plugin_manual.conf.in ${PLUGIN_DOXYGEN_OUTPUT_DIR}/doxygen.conf ) set(_qhp_xsl_file "${MITK_SOURCE_DIR}/Documentation/qhp_toc.xsl") set(_generated_qhp_file "${PLUGIN_DOXYGEN_OUTPUT_DIR}/html/index.qhp") set(_transformed_qhp_file "${PLUGIN_DOXYGEN_OUTPUT_DIR}/html/${PLUGIN_TARGET}.qhp") set(${qch_file} "${CMAKE_CURRENT_BINARY_DIR}/resources/${PLUGIN_TARGET}.qch") set(_xsl_command ) if(use_xsl) set(_xsl_command COMMAND ${QT_XMLPATTERNS_EXECUTABLE} ${_qhp_xsl_file} ${_generated_qhp_file} -output ${_transformed_qhp_file}) endif() file(GLOB _file_dependencies "${PLUGIN_DOXYGEN_INPUT_DIR}/*") add_custom_command(OUTPUT ${${qch_file}} # Generate a Qt help project (index.qhp) with doxygen COMMAND ${DOXYGEN_EXECUTABLE} ${PLUGIN_DOXYGEN_OUTPUT_DIR}/doxygen.conf # Use a XSL transformation to get rid of the top-level entry ${_xsl_command} # Generate the final Qt compressed help file (.qch) COMMAND ${QT_HELPGENERATOR_EXECUTABLE} ${_transformed_qhp_file} -o ${${qch_file}} DEPENDS ${PLUGIN_DOXYGEN_OUTPUT_DIR}/doxygen.conf ${_file_dependencies} ) #set_source_files_properties(${qch_file} PROPERTIES GENERATED 1) set(${qch_file} ${${qch_file}} PARENT_SCOPE) endfunction() function(MACRO_CREATE_MITK_CTK_PLUGIN) message(SEND_ERROR "The function MACRO_CREATE_MITK_CTK_PLUGIN was renamed to mitk_create_plugin in MITK 2015.05.") endfunction() diff --git a/CMake/mitkFunctionGenerateProjectXml.cmake b/CMake/mitkFunctionGenerateProjectXml.cmake deleted file mode 100644 index 2d3f4c91a5..0000000000 --- a/CMake/mitkFunctionGenerateProjectXml.cmake +++ /dev/null @@ -1,45 +0,0 @@ - - -function(mitkFunctionGenerateProjectXml dir name targets is_superbuild) - if(NOT EXISTS ${dir}) - message(FATAL_ERROR "Directory ${dir} doesn't exist!") - endif() - - set(xml_subprojects ) - - if(${is_superbuild}) - set(xml_subprojects ${xml_subprojects} " \n") - endif() - - foreach(target ${targets}) - - # Remarks: Project.xml should contains all sub-project. That way - # all dashboards should submit a similar file. - - set(xml_subprojects ${xml_subprojects} " \n") - - if(${is_superbuild}) - set(xml_subprojects ${xml_subprojects} " \n") - endif() - - # Generate XML related to the dependencies - #foreach(dependency_name ${dependencies}) - # set(xml_subprojects ${xml_subprojects} " \n") - #endforeach() - - set(xml_subprojects ${xml_subprojects} " \n") - endforeach() - - set(xml_subprojects ${xml_subprojects} " \n") - foreach(subproject ${targets}) - set(xml_subprojects ${xml_subprojects} " \n") - endforeach() - set(xml_subprojects ${xml_subprojects} " \n") - - set(xml_content "\n${xml_subprojects}") - set(filename "${dir}/Project.xml") - - file(WRITE ${filename} ${xml_content}) - message(STATUS "Generated: ${filename}") -endfunction() - diff --git a/CMake/mitkFunctionGetVersionDescription.cmake b/CMake/mitkFunctionGetVersionDescription.cmake index bb52fefe96..80c55c39c7 100644 --- a/CMake/mitkFunctionGetVersionDescription.cmake +++ b/CMake/mitkFunctionGetVersionDescription.cmake @@ -1,68 +1,71 @@ #! \brief Extract the version description from a local working copy #! #! If the given repository is a git repository, the functions runs the #! git rev-parse --exact-match HEAD command #! #! Information provided is stored in ${prefix}_REVISION_DESC an is #! \ul #! \li The exact tag if the HEAD of the source-tree has a tag #! \li the 'git describe' output, which is -<#Commits>-g #! \lu #! In case the working copy contains local changes, the ${prefix}_REVISION_DESC strings will contain #! a suffix [local changes]. #! #! The revision description can be overridden by a ${prefix}_CUSTOM_REVISION_DESC variable. #! #! \param source_dir The directory containing a working copy #! \param prefix A prefix to prepent to the variables containing #! the extracted information #! function(mitkFunctionGetVersionDescription source_dir prefix) if(NOT prefix) message(FATAL_ERROR "prefix argument not specified") endif() if(${prefix}_CUSTOM_REVISION_DESC) set(_wc_description ${${prefix}_CUSTOM_REVISION_DESC}) else() # initialize variable set(_wc_description "unknown_version") set(_dirty_repo_str "-local_changes") find_package(Git) if(GIT_FOUND) GIT_IS_REPO(${source_dir} _is_git_repo) if(_is_git_repo) execute_process(COMMAND ${GIT_EXECUTABLE} describe --exact-match --dirty=${_dirty_repo_str} WORKING_DIRECTORY ${source_dir} OUTPUT_VARIABLE _project_git_tagname - RESULT_VARIABLE _proper_version) + RESULT_VARIABLE _proper_version + ERROR_VARIABLE _error_msg) + if(_proper_version EQUAL 0) set(_wc_description ${_project_git_tagname}) else() # the execution failed, i.e. the HEAD has no tag, # for fallback string: execute again but without the --exact-match execute_process(COMMAND ${GIT_EXECUTABLE} describe --dirty=${_dirty_repo_str} WORKING_DIRECTORY ${source_dir} OUTPUT_VARIABLE _wc_description - RESULT_VARIABLE _proper_version) + RESULT_VARIABLE _proper_version + ERROR_VARIABLE _error_msg) if(NOT _proper_version EQUAL 0) # last fallback, i.e. working copy is a shallow clone, at least use # commit hash execute_process(COMMAND ${GIT_EXECUTABLE} describe --always --dirty=${_dirty_repo_str} WORKING_DIRECTORY ${source_dir} OUTPUT_VARIABLE _wc_description) endif() endif() # remove newline at and of the string string(STRIP "${_wc_description}" _wc_description) endif() endif() endif() set(${prefix}_REVISION_DESC ${_wc_description} PARENT_SCOPE) endfunction() diff --git a/CMake/mitkMacroCreateDefaultTests.cmake b/CMake/mitkMacroCreateDefaultTests.cmake index 5a5f87dd04..0f14e4145c 100644 --- a/CMake/mitkMacroCreateDefaultTests.cmake +++ b/CMake/mitkMacroCreateDefaultTests.cmake @@ -1,70 +1,66 @@ # Create TestDriver and default tests for MITK # # CMake variables used: # # ${${KITNAME}_GUI_TESTS} : filenames of all tests that run without a parameter # ${${KITNAME}_IMAGE_GUI_TESTS : filenames of all tests that run with an image filename as parameter # ${${KITNAME}_TESTS} : filenames of all tests that run without a parameter # ${${KITNAME}_IMAGE_TESTS : filenames of all tests that run with an image filename as parameter # ${${KITNAME}_TESTIMAGES} : list of images passed as parameter for the IMAGE_TESTS # ${${KITNAME}_CUSTOM_TESTS} : filenames of custom tests which are just added to the TestDriver. Execution # of these has to be specified manually with the ADD_TEST CMake command. # macro(MITK_CREATE_DEFAULT_TESTS) # add tests which need a GUI if it is not disabled if(NOT MITK_GUI_TESTS_DISABLED) set( ${KITNAME}_TESTS ${${KITNAME}_TESTS} ${${KITNAME}_GUI_TESTS} ) set( ${KITNAME}_IMAGE_TESTS ${${KITNAME}_IMAGE_TESTS} ${${KITNAME}_IMAGE_GUI_TESTS} ) endif() # # Create the TestDriver binary which contains all the tests. # create_test_sourcelist(MITKTEST_SOURCE ${KITNAME}TestDriver.cpp ${${KITNAME}_TESTS} ${${KITNAME}_IMAGE_TESTS} ${${KITNAME}_CUSTOM_TESTS} ) add_executable(${KITNAME}TestDriver ${MITKTEST_SOURCE}) - set_property(TARGET ${KITNAME}TestDriver PROPERTY LABELS ${PROJECT_NAME}) target_link_libraries(${KITNAME}TestDriver ${${KITNAME}_CORE_LIBRARIES} ${${KITNAME}_LIBRARIES} ${LIBRARIES_FOR_${KITNAME}_CORE}) # # Now tell CMake which tests should be run. This is done automatically # for all tests in ${KITNAME}_TESTS and ${KITNAME}_IMAGE_TESTS. The IMAGE_TESTS # are run for each image in the TESTIMAGES list. # foreach( test ${${KITNAME}_TESTS} ) get_filename_component(TName ${test} NAME_WE) add_test(${TName} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${KITNAME}TestDriver ${TName}) - set_property(TEST ${TName} PROPERTY LABELS ${PROJECT_NAME}) - mitkFunctionGetLibrarySearchPaths(MITK_RUNTIME_PATH_RELEASE release RELEASE) mitkFunctionGetLibrarySearchPaths(MITK_RUNTIME_PATH_DEBUG debug DEBUG) string (REGEX REPLACE "\;" "\\\;" MITK_RUNTIME_PATH_RELEASE "${MITK_RUNTIME_PATH_RELEASE}") string (REGEX REPLACE "\;" "\\\;" MITK_RUNTIME_PATH_DEBUG "${MITK_RUNTIME_PATH_DEBUG}") set_property(TEST ${TName} PROPERTY ENVIRONMENT "PATH=${MITK_RUNTIME_PATH_RELEASE}\;${MITK_RUNTIME_PATH_DEBUG}" APPEND) set_property(TEST ${TName} PROPERTY SKIP_RETURN_CODE 77) endforeach() foreach(image ${${KITNAME}_TESTIMAGES} ${ADDITIONAL_TEST_IMAGES} ) if(EXISTS "${image}") set(IMAGE_FULL_PATH ${image}) else() # todo: maybe search other paths as well # yes, please in mitk/Testing/Data, too set(IMAGE_FULL_PATH ${CMAKE_CURRENT_SOURCE_DIR}/Data/${image}) endif() if(EXISTS "${IMAGE_FULL_PATH}") foreach( test ${${KITNAME}_IMAGE_TESTS} ) get_filename_component(TName ${test} NAME_WE) get_filename_component(ImageName ${IMAGE_FULL_PATH} NAME) add_test(${TName}_${ImageName} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${KITNAME}TestDriver ${TName} ${IMAGE_FULL_PATH}) - set_property(TEST ${TName}_${ImageName} PROPERTY LABELS ${PROJECT_NAME}) set_property(TEST ${TName}_${ImageName} PROPERTY ENVIRONMENT "PATH=${MITK_RUNTIME_PATH_RELEASE}\;${MITK_RUNTIME_PATH_DEBUG}" APPEND) set_property(TEST ${TName}_${ImageName} PROPERTY SKIP_RETURN_CODE 77) endforeach() else() message("!!!!! No such file: ${IMAGE_FULL_PATH} !!!!!") endif() endforeach() endmacro() diff --git a/CMake/mitkMacroCreateExecutable.cmake b/CMake/mitkMacroCreateExecutable.cmake index c9c9d130ed..7ff9f7f7e9 100644 --- a/CMake/mitkMacroCreateExecutable.cmake +++ b/CMake/mitkMacroCreateExecutable.cmake @@ -1,117 +1,116 @@ ################################################################## # # MITK_CREATE_EXECUTABLE # #! Creates an executable with MITK dependencies and batch files #! for proper application start-up. #! #! USAGE: #! #! \code #! MITK_CREATE_EXECUTABLE( [] #! [DEPENDS ] #! [PACKAGE_DEPENDS ] #! [INCLUDE_DIRS ] #! [TARGET_DEPENDS #! [WARNINGS_NO_ERRORS] #! [NO_INSTALL] #! \endcode #! #! \param EXECUTABLE_NAME The name for the new executable target ################################################################## macro(mitk_create_executable) set(_macro_params VERSION # version number, e.g. "1.2.0" FILES_CMAKE # file name of a CMake file setting source list variables # (defaults to files.cmake) DESCRIPTION # a description for the executable ) set(_macro_multiparams - SUBPROJECTS # list of CDash labels + SUBPROJECTS # list of CDash labels (deprecated) INCLUDE_DIRS # additional include dirs DEPENDS # list of modules this module depends on PACKAGE_DEPENDS # list of "packages" this module depends on (e.g. Qt, VTK, etc.) TARGET_DEPENDS # list of CMake targets this executable should depend on ADDITIONAL_LIBS # list of additional libraries linked to this executable CPP_FILES # (optional) list of cpp files ) set(_macro_options NO_INIT # do not create CppMicroServices initialization code NO_FEATURE_INFO # do not create a feature info by calling add_feature_info() NO_BATCH_FILE # do not create batch files on Windows WARNINGS_NO_ERRORS # do not treat compiler warnings as errors NO_INSTALL ) cmake_parse_arguments(EXEC "${_macro_options}" "${_macro_params}" "${_macro_multiparams}" ${ARGN}) set(_EXEC_OPTIONS EXECUTABLE) if(EXEC_NO_INIT) list(APPEND _EXEC_OPTIONS NO_INIT) endif() if(EXEC_WARNINGS_NO_ERRORS) list(APPEND _EXEC_OPTIONS WARNINGS_NO_ERRORS) endif() if(EXEC_NO_FEATURE_INFO) list(APPEND _EXEC_OPTIONS NO_FEATURE_INFO) endif() mitk_create_module(${EXEC_UNPARSED_ARGUMENTS} - SUBPROJECTS ${EXEC_SUBPROJECTS} VERSION ${EXEC_VERSION} INCLUDE_DIRS ${EXEC_INCLUDE_DIRS} DEPENDS ${EXEC_DEPENDS} PACKAGE_DEPENDS ${EXEC_PACKAGE_DEPENDS} TARGET_DEPENDS ${EXEC_TARGET_DEPENDS} ADDITIONAL_LIBS ${EXEC_ADDITIONAL_LIBS} FILES_CMAKE ${EXEC_FILES_CMAKE} CPP_FILES ${EXEC_CPP_FILES} DESCRIPTION "${DESCRIPTION}" ${_EXEC_OPTIONS} ) set(EXECUTABLE_IS_ENABLED ${MODULE_IS_ENABLED}) set(EXECUTABLE_TARGET ${MODULE_TARGET}) if(EXECUTABLE_IS_ENABLED) set_property(GLOBAL APPEND PROPERTY MITK_EXECUTABLE_TARGETS ${EXECUTABLE_TARGET}) if(EXEC_NO_INSTALL) set_target_properties(${EXECUTABLE_TARGET} PROPERTIES NO_INSTALL TRUE) endif() # Add meta dependencies (e.g. on auto-load modules from depending modules) if(TARGET ${CMAKE_PROJECT_NAME}-autoload) add_dependencies(${MODULE_TARGET} ${CMAKE_PROJECT_NAME}-autoload) endif() # Create batch and VS user files for Windows platforms include(mitkFunctionCreateWindowsBatchScript) if(WIN32) set(_batch_file_in "${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_TARGET}.bat.in") if(NOT EXISTS "${_batch_file_in}") set(_batch_file_in "${MITK_CMAKE_DIR}/StartApp.bat.in") endif() if(CMAKE_RUNTIME_OUTPUT_DIRECTORY) set(_batch_file_out_dir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") else() set(_batch_file_out_dir "${CMAKE_CURRENT_BINARY_DIR}") endif() if(NOT EXEC_NO_BATCH_FILE) if(NOT EXEC_NAME) set(EXEC_NAME ${MODULE_TARGET}) endif() foreach(BUILD_TYPE debug release) mitkFunctionCreateWindowsBatchScript( ${_batch_file_in} ${_batch_file_out_dir}/${MODULE_TARGET}_${BUILD_TYPE}.bat ${BUILD_TYPE} ) endforeach() endif() mitkFunctionConfigureVisualStudioUserProjectFile( NAME ${MODULE_TARGET} ) endif() endif() endmacro() diff --git a/CMake/mitkMacroCreateModuleTests.cmake b/CMake/mitkMacroCreateModuleTests.cmake index a60564cac2..1ce68e4558 100644 --- a/CMake/mitkMacroCreateModuleTests.cmake +++ b/CMake/mitkMacroCreateModuleTests.cmake @@ -1,109 +1,100 @@ # # Create tests and testdriver for this module # # Usage: MITK_CREATE_MODULE_TESTS( [EXTRA_DRIVER_INIT init_code] ) # # EXTRA_DRIVER_INIT is inserted as c++ code in the testdriver and will be executed before each test # macro(MITK_CREATE_MODULE_TESTS) cmake_parse_arguments(MODULE_TEST "US_MODULE;NO_INIT" "EXTRA_DRIVER_INIT;EXTRA_DRIVER_INCLUDE" "EXTRA_DEPENDS;DEPENDS;PACKAGE_DEPENDS" ${ARGN}) if(BUILD_TESTING AND MODULE_IS_ENABLED) include(files.cmake) include_directories(.) set(TESTDRIVER ${MODULE_NAME}TestDriver) set(MODULE_TEST_EXTRA_DRIVER_INIT "${MODULE_TEST_EXTRA_DRIVER_INIT}") if(MITK_XVFB_TESTING) set(xvfb_run ${MITK_XVFB_TESTING_COMMAND}) else() set(xvfb_run ) endif() if(MODULE_TEST_US_MODULE) message(WARNING "The US_MODULE argument is deprecated and should be removed") endif() if(MODULE_TEST_US_MODULE AND MODULE_TEST_NO_INIT) message(WARNING "Conflicting arguments US_MODULE and NO_INIT: NO_INIT wins.") endif() set(_no_init) if(MODULE_TEST_NO_INIT) set(_no_init NO_INIT) endif() set(MITK_MODULE_NAME_REGEX_MATCH ) set(MITK_MODULE_NAME_REGEX_NOT_MATCH ) set(_testdriver_file_list ${CMAKE_CURRENT_BINARY_DIR}/testdriver_files.cmake) configure_file(${MITK_CMAKE_DIR}/mitkTestDriverFiles.cmake.in ${_testdriver_file_list} @ONLY) mitk_create_executable(${TESTDRIVER} DEPENDS ${MODULE_NAME} ${MODULE_TEST_DEPENDS} ${MODULE_TEST_EXTRA_DEPENDS} MitkTestingHelper PACKAGE_DEPENDS ${MODULE_TEST_PACKAGE_DEPENDS} - SUBPROJECTS ${MODULE_SUBPROJECTS} FILES_CMAKE ${_testdriver_file_list} NO_FEATURE_INFO NO_BATCH_FILE NO_INSTALL ${_no_init}) set_property(TARGET ${EXECUTABLE_TARGET} PROPERTY FOLDER "${MITK_ROOT_FOLDER}/Modules/Tests") # # Now tell CMake which tests should be run. This is done automatically # for all tests in ${KITNAME}_TESTS and ${KITNAME}_IMAGE_TESTS. The IMAGE_TESTS # are run for each image in the TESTIMAGES list. # include(files.cmake) foreach( test ${MODULE_TESTS} ) get_filename_component(TName ${test} NAME_WE) add_test(NAME ${TName} COMMAND ${xvfb_run} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} ${TName}) - # Add labels for CDash subproject support - if(MODULE_SUBPROJECTS) - set_property(TEST ${TName} PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) - endif() mitkFunctionGetLibrarySearchPaths(MITK_RUNTIME_PATH_RELEASE release RELEASE) mitkFunctionGetLibrarySearchPaths(MITK_RUNTIME_PATH_DEBUG debug DEBUG) set(test_env_path ${MITK_RUNTIME_PATH_RELEASE} ${MITK_RUNTIME_PATH_DEBUG} $ENV{PATH}) list(REMOVE_DUPLICATES test_env_path) string (REGEX REPLACE "\;" "\\\;" test_env_path "${test_env_path}") set_property(TEST ${TName} PROPERTY ENVIRONMENT "PATH=${test_env_path}" APPEND) set_property(TEST ${TName} PROPERTY SKIP_RETURN_CODE 77) endforeach() set(TEST_TYPES IMAGE SURFACE POINTSET) # add other file types here foreach(test_type ${TEST_TYPES}) foreach(test_data ${MODULE_TEST${test_type}} ${ADDITIONAL_TEST_${test_type}}) if(EXISTS ${test_data}) set(TEST_DATA_FULL_PATH ${test_data}) else() # todo: maybe search other paths as well # yes, please in mitk/Testing/Data, too set(TEST_DATA_FULL_PATH ${MITK_DATA_DIR}/${test_data}) endif() if(EXISTS ${TEST_DATA_FULL_PATH}) foreach( test ${MODULE_${test_type}_TESTS}) get_filename_component(TName ${test} NAME_WE) get_filename_component(DName ${TEST_DATA_FULL_PATH} NAME) add_test(NAME ${TName}_${DName} COMMAND ${xvfb_run} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} ${TName} ${TEST_DATA_FULL_PATH}) - # Add labels for CDash subproject support - if(MODULE_SUBPROJECTS) - set_property(TEST ${TName}_${DName} PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) - endif() set_property(TEST ${TName}_${DName} PROPERTY ENVIRONMENT "PATH=${test_env_path}" APPEND) set_property(TEST ${TName}_${DName} PROPERTY SKIP_RETURN_CODE 77) endforeach() else() message("!!!!! No such file: ${TEST_DATA_FULL_PATH} !!!!!") endif() endforeach() endforeach() endif() endmacro() diff --git a/CMake/mitkPackageTest.cmake b/CMake/mitkPackageTest.cmake index 615870dc1f..c263ed8cb8 100644 --- a/CMake/mitkPackageTest.cmake +++ b/CMake/mitkPackageTest.cmake @@ -1,26 +1,21 @@ if(BUILD_TESTING) #package testing if(NOT MITK_FAST_TESTING) # package testing in windows only for release if(WIN32) add_test(NAME mitkPackageTest CONFIGURATIONS Release COMMAND ${CMAKE_COMMAND} --build ${MITK_BINARY_DIR} --config Release --target package) - set_tests_properties( mitkPackageTest PROPERTIES - TIMEOUT 14400 - LABELS "MITK;MITK-Plugins;PACKAGE_TESTS") + set_tests_properties(mitkPackageTest PROPERTIES TIMEOUT 14400) elseif(CMAKE_BUILD_TYPE) add_test( NAME mitkPackageTest COMMAND ${CMAKE_COMMAND} --build ${MITK_BINARY_DIR} --config ${CMAKE_BUILD_TYPE} --target package) - set_tests_properties( mitkPackageTest PROPERTIES - TIMEOUT 14400 - LABELS "MITK;MITK-Plugins;PACKAGE_TESTS" - RUN_SERIAL TRUE) + set_tests_properties(mitkPackageTest PROPERTIES TIMEOUT 14400 RUN_SERIAL TRUE) endif() endif() # NOT MITK_FAST_TESTING endif(BUILD_TESTING) diff --git a/CMake/mitkTestPluginGenerator.cmake b/CMake/mitkTestPluginGenerator.cmake index cf63eeefe3..318a20f120 100644 --- a/CMake/mitkTestPluginGenerator.cmake +++ b/CMake/mitkTestPluginGenerator.cmake @@ -1,113 +1,109 @@ if(BUILD_TESTING) set(proj GP) # Means GenerateProject (use a short name due to Windows limitations) set(test_project_out_dir "${MITK_BINARY_DIR}") set(test_project_source_dir "${MITK_BINARY_DIR}/${proj}") set(test_project_binary_dir "${MITK_BINARY_DIR}/${proj}-bin") add_test(NAME mitkPluginGeneratorCleanTest COMMAND ${CMAKE_COMMAND} -E remove_directory "${test_project_source_dir}" ) - set_tests_properties(mitkPluginGeneratorCleanTest PROPERTIES - LABELS "MITK;BlueBerry") add_test(NAME mitkPluginGeneratorCleanTest2 COMMAND ${CMAKE_COMMAND} -E remove_directory "${test_project_binary_dir}" ) - set_tests_properties(mitkPluginGeneratorCleanTest2 PROPERTIES - LABELS "MITK;BlueBerry") add_test(NAME mitkPluginGeneratorCleanTest3 COMMAND ${CMAKE_COMMAND} -E make_directory "${test_project_binary_dir}" ) set_tests_properties(mitkPluginGeneratorCleanTest3 PROPERTIES - DEPENDS mitkPluginGeneratorCleanTest2 - LABELS "MITK;BlueBerry") + DEPENDS mitkPluginGeneratorCleanTest2) add_test(NAME mitkPluginGeneratorCreateTest COMMAND ${exec_target} --project-name "${proj}" --project-app-name "TestApp" -ps org.test.plugin -pn "Test Plugin" -vn "Test View" -o ${test_project_out_dir} -y ) set_tests_properties(mitkPluginGeneratorCreateTest PROPERTIES - DEPENDS "${exec_target};mitkPluginGeneratorCleanTest;mitkPluginGeneratorCleanTest3" - LABELS "MITK;BlueBerry") + DEPENDS "${exec_target};mitkPluginGeneratorCleanTest;mitkPluginGeneratorCleanTest3") + + mitkFunctionGetLibrarySearchPaths(MITK_RUNTIME_PATH_RELEASE release RELEASE) + mitkFunctionGetLibrarySearchPaths(MITK_RUNTIME_PATH_DEBUG debug DEBUG) + set(test_env_path ${MITK_RUNTIME_PATH_RELEASE} ${MITK_RUNTIME_PATH_DEBUG} $ENV{PATH}) + list(REMOVE_DUPLICATES test_env_path) + string (REGEX REPLACE "\;" "\\\;" test_env_path "${test_env_path}") + set_property(TEST mitkPluginGeneratorCreateTest APPEND PROPERTY ENVIRONMENT "PATH=${test_env_path}") + set_property(TEST mitkPluginGeneratorCreateTest PROPERTY SKIP_RETURN_CODE 77) set(configure_options -DMITK_DIR:PATH=${MITK_BINARY_DIR} -DCMAKE_C_COMPILER:STRING=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER} -DCMAKE_OSX_SYSROOT:PATH=${CMAKE_OSX_SYSROOT} -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET} -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES} -G${CMAKE_GENERATOR} -C "${MITK_BINARY_DIR}/mitkTestInitialCache.txt" ) if(CMAKE_PREFIX_PATH) string (REPLACE ";" "$" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") list(APPEND configure_options -DCMAKE_PREFIX_PATH:PATH=${CMAKE_PREFIX_PATH}) endif() if(CMAKE_CONFIGURATION_TYPES) foreach(config ${CMAKE_CONFIGURATION_TYPES}) add_test(NAME mitkPluginGeneratorConfigureTest-${config} CONFIGURATIONS ${config} WORKING_DIRECTORY "${test_project_binary_dir}" COMMAND ${CMAKE_COMMAND} ${configure_options} "${test_project_source_dir}") set_tests_properties(mitkPluginGeneratorConfigureTest-${config} PROPERTIES - DEPENDS mitkPluginGeneratorCreateTest - LABELS "MITK;BlueBerry") + DEPENDS mitkPluginGeneratorCreateTest) add_test(NAME mitkPluginGeneratorBuildTest-${config} CONFIGURATIONS ${config} COMMAND ${CMAKE_COMMAND} --build ${test_project_binary_dir} --config ${config}) set_tests_properties(mitkPluginGeneratorBuildTest-${config} PROPERTIES - DEPENDS mitkPluginGeneratorConfigureTest-${config} - LABELS "MITK;BlueBerry") + DEPENDS mitkPluginGeneratorConfigureTest-${config}) endforeach() else() add_test(NAME mitkPluginGeneratorConfigureTest-${CMAKE_BUILD_TYPE} WORKING_DIRECTORY "${test_project_binary_dir}" COMMAND ${CMAKE_COMMAND} ${configure_options} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} "${test_project_source_dir}") set_tests_properties(mitkPluginGeneratorConfigureTest-${CMAKE_BUILD_TYPE} PROPERTIES - DEPENDS mitkPluginGeneratorCreateTest - LABELS "MITK;BlueBerry") + DEPENDS mitkPluginGeneratorCreateTest) add_test(NAME mitkPluginGeneratorBuildTest-${CMAKE_BUILD_TYPE} COMMAND ${CMAKE_COMMAND} --build ${test_project_binary_dir} --config ${CMAKE_BUILD_TYPE}) set_tests_properties(mitkPluginGeneratorBuildTest-${CMAKE_BUILD_TYPE} PROPERTIES - DEPENDS mitkPluginGeneratorConfigureTest-${CMAKE_BUILD_TYPE} - LABELS "MITK;BlueBerry") + DEPENDS mitkPluginGeneratorConfigureTest-${CMAKE_BUILD_TYPE}) endif() set(package_test_configurations) if(WIN32) # Only test packaging if build type is "Release" on Windows set(package_test_configurations CONFIGURATIONS Release) endif() if(NOT MITK_FAST_TESTING) if(WIN32) # Only test packaging if build type is "Release" on Windows add_test(NAME mitkPluginGeneratorPackageTest CONFIGURATIONS Release COMMAND ${CMAKE_COMMAND} --build ${test_project_binary_dir}/${proj}-build --config Release --target package) set_tests_properties(mitkPluginGeneratorPackageTest PROPERTIES DEPENDS mitkPluginGeneratorBuildTest-Release - TIMEOUT 6000 - LABELS "MITK;BlueBerry;PACKAGE_TESTS") + TIMEOUT 6000) elseif(CMAKE_BUILD_TYPE) add_test(mitkPluginGeneratorPackageTest ${CMAKE_COMMAND} --build ${test_project_binary_dir}/${proj}-build --config ${CMAKE_BUILD_TYPE} --target package) set_tests_properties(mitkPluginGeneratorPackageTest PROPERTIES DEPENDS mitkPluginGeneratorBuildTest-${CMAKE_BUILD_TYPE} - TIMEOUT 6000 - LABELS "MITK;BlueBerry;PACKAGE_TESTS") + TIMEOUT 6000) endif() endif() endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index e5f75b83e0..7d903a008e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,1477 +1,1412 @@ set(MITK_CMAKE_MINIMUM_REQUIRED_VERSION 3.14.5) cmake_minimum_required(VERSION ${MITK_CMAKE_MINIMUM_REQUIRED_VERSION}) #----------------------------------------------------------------------------- # See https://cmake.org/cmake/help/v3.14/manual/cmake-policies.7.html 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 2018.04.99) include_directories(SYSTEM ${MITK_SUPERBUILD_BINARY_DIR}) endif() #----------------------------------------------------------------------------- # MITK Extension Feature #----------------------------------------------------------------------------- set(MITK_EXTENSION_DIRS "" CACHE STRING "") set(MITK_DIR_PLUS_EXTENSION_DIRS ${MITK_SOURCE_DIR} ${MITK_EXTENSION_DIRS}) #----------------------------------------------------------------------------- # Update CMake module path #----------------------------------------------------------------------------- set(MITK_CMAKE_DIR ${MITK_SOURCE_DIR}/CMake) set(CMAKE_MODULE_PATH ${MITK_CMAKE_DIR}) foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) set(MITK_CMAKE_EXTENSION_DIR ${MITK_EXTENSION_DIR}/CMake) get_filename_component(MITK_CMAKE_EXTENSION_DIR ${MITK_CMAKE_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_CMAKE_EXTENSION_DIR}) list(APPEND CMAKE_MODULE_PATH ${MITK_CMAKE_EXTENSION_DIR}) endif() endforeach() #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- # Standard CMake macros include(FeatureSummary) include(CTest) 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) include(mitkFunctionAddLibrarySearchPaths) 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 macOS version #----------------------------------------------------------------------------- # The minimum supported macOS version is 10.13. If you use a version less than 10.13, there is no guarantee that the build still works. if(APPLE) exec_program(sw_vers ARGS -productVersion OUTPUT_VARIABLE macos_version) if (macos_version VERSION_LESS "10.13") message(WARNING "Detected macOS version \"${macos_version}\" is not supported anymore. Minimum required macOS version is at least 10.13.") endif() if (CMAKE_OSX_DEPLOYMENT_TARGET AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS 10.13) message(WARNING "Detected macOS deployment target \"${CMAKE_OSX_DEPLOYMENT_TARGET}\" is not supported anymore. Minimum required macOS version is at least 10.13.") endif() endif() #----------------------------------------------------------------------------- # Check miminum compiler versions #----------------------------------------------------------------------------- if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # require at least gcc 4.9 as provided by ppa:ubuntu-toolchain-r/test for Ubuntu 14.04 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) message(FATAL_ERROR "GCC version must be at least 4.9 If you are using Ubuntu 14.04, you can easily install gcc and g++ 4.9 (or any later version available) in addition to your version ${CMAKE_CXX_COMPILER_VERSION}: sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install gcc-4.9 g++-4.9 Make sure to explicitly specify these compilers when configuring MITK: CMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-4.9 CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-4.9 For more information on the proposed PPA see the Toolchain Updates section of https://wiki.ubuntu.com/ToolChain.") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # require at least clang 3.4 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4) message(FATAL_ERROR "Clang version must be at least 3.4") 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 2017 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) message(FATAL_ERROR "Microsoft Visual Studio 2017 or newer required") 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 14) set(CMAKE_CXX_EXTENSIONS 0) set(CMAKE_CXX_STANDARD ${MITK_CXX_STANDARD}) set(CMAKE_CXX_STANDARD_REQUIRED 1) # This is necessary to avoid problems with compile feature checks. # CMAKE_CXX_STANDARD seems to only set the -std=c++14 flag for targets. # However, compile flag checks also need to be done with -std=c++14. # The MITK_CXX14_FLAG variable is also used for external projects # build during the MITK super-build. mitkFunctionCheckCompilerFlags("-std=c++14" MITK_CXX14_FLAG) #----------------------------------------------------------------------------- # 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 34) # _src_dir_length_max - strlen(ep/src/ITK-build) 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) #----------------------------------------------------------------------------- # ----------------------------------------- # 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) option(MITK_FAST_TESTING "Disable long-running tests like packaging" OFF) option(MITK_XVFB_TESTING "Execute test drivers through xvfb-run" OFF) option(MITK_BUILD_ALL_APPS "Build all MITK applications" OFF) 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_XVFB_TESTING MITK_FAST_TESTING MITK_BUILD_ALL_APPS MITK_ENABLE_PIC_READER ) #----------------------------------------------------------------------------- # Set UI testing flags #----------------------------------------------------------------------------- if(MITK_XVFB_TESTING) set(MITK_XVFB_TESTING_COMMAND "xvfb-run" "--auto-servernum" CACHE STRING "Command and options to test through Xvfb") mark_as_advanced(MITK_XVFB_TESTING_COMMAND) endif(MITK_XVFB_TESTING) # ----------------------------------------- # Other options set(MITK_CUSTOM_REVISION_DESC "" CACHE STRING "Override MITK revision description") mark_as_advanced(MITK_CUSTOM_REVISION_DESC) set_property(GLOBAL PROPERTY MITK_EXTERNAL_PROJECTS "") include(CMakeExternals/ExternalProjectList.cmake) foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) set(MITK_CMAKE_EXTERNALS_EXTENSION_DIR ${MITK_EXTENSION_DIR}/CMakeExternals) get_filename_component(MITK_CMAKE_EXTERNALS_EXTENSION_DIR ${MITK_CMAKE_EXTERNALS_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_CMAKE_EXTERNALS_EXTENSION_DIR}/ExternalProjectList.cmake) include(${MITK_CMAKE_EXTERNALS_EXTENSION_DIR}/ExternalProjectList.cmake) endif() endforeach() # ----------------------------------------- # Other MITK_USE_* options not related to # external projects build via the # MITK superbuild option(MITK_USE_BLUEBERRY "Build the BlueBerry platform" ON) option(MITK_USE_OpenCL "Use OpenCL GPU-Computing library" OFF) option(MITK_USE_OpenMP "Use OpenMP" OFF) option(MITK_USE_Python3 "Use Python 3" 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() foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) file(GLOB _extBuildConfigFiles ${MITK_EXTENSION_DIR}/CMake/BuildConfigurations/*.cmake) foreach(_extBuildConfigFile ${_extBuildConfigFiles}) get_filename_component(_extBuildConfigFile ${_extBuildConfigFile} NAME_WE) list(APPEND _buildConfigs ${_extBuildConfigFile}) endforeach() list(REMOVE_DUPLICATES _buildConfigs) endforeach() set(MITK_BUILD_CONFIGURATION "Custom" CACHE STRING "Use pre-defined MITK configurations") set_property(CACHE MITK_BUILD_CONFIGURATION PROPERTY STRINGS ${_buildConfigs}) mitkFunctionEnableBuildConfiguration() mitkFunctionCreateWhitelistPaths(MITK) mitkFunctionFindWhitelists(MITK) # ----------------------------------------- # Qt version related variables option(MITK_USE_Qt5 "Use Qt 5 library" ON) if(MITK_USE_Qt5) set(MITK_QT5_MINIMUM_VERSION 5.12) set(MITK_QT5_COMPONENTS Concurrent OpenGL PrintSupport Script Sql Svg Widgets Xml XmlPatterns WebEngineWidgets UiTools Help LinguistTools) if(APPLE) list(APPEND MITK_QT5_COMPONENTS DBus) elseif(UNIX) list(APPEND MITK_QT5_COMPONENTS X11Extras) endif() # Hint at default install locations of Qt if(NOT Qt5_DIR) if(MSVC) set(_dir_candidates "C:/Qt") if(CMAKE_GENERATOR MATCHES "^Visual Studio [0-9]+ ([0-9]+)") set(_compilers "msvc${CMAKE_MATCH_1}") elseif(CMAKE_GENERATOR MATCHES "Ninja") include(mitkFunctionGetMSVCVersion) mitkFunctionGetMSVCVersion() if(VISUAL_STUDIO_PRODUCT_NAME MATCHES "^Visual Studio ([0-9]+)") set(_compilers "msvc${CMAKE_MATCH_1}") endif() endif() if(_compilers MATCHES "[0-9]+") if (CMAKE_MATCH_0 EQUAL 2019) list(APPEND _compilers "msvc2017") # Binary compatible to 2019 endif() endif() else() set(_dir_candidates ~/Qt) if(APPLE) set(_compilers clang) else() list(APPEND _dir_candidates /opt/Qt) set(_compilers gcc) endif() endif() if(CMAKE_SIZEOF_VOID_P EQUAL 8) foreach(_compiler ${_compilers}) list(APPEND _compilers64 "${_compiler}_64") endforeach() set(_compilers ${_compilers64}) endif() foreach(_dir_candidate ${_dir_candidates}) get_filename_component(_dir_candidate ${_dir_candidate} REALPATH) foreach(_compiler ${_compilers}) set(_glob_expression "${_dir_candidate}/5.*/${_compiler}") file(GLOB _hints ${_glob_expression}) list(SORT _hints) list(APPEND MITK_QT5_HINTS ${_hints}) endforeach() endforeach() endif() find_package(Qt5 ${MITK_QT5_MINIMUM_VERSION} COMPONENTS ${MITK_QT5_COMPONENTS} REQUIRED HINTS ${MITK_QT5_HINTS}) if(${Qt5_VERSION} VERSION_GREATER_EQUAL 5.13) message(WARNING "Qt version ${Qt5_VERSION_MAJOR}.${Qt5_VERSION_MINOR} is not yet supported. We recommend using version 5.12.x.") endif() endif() # ----------------------------------------- # Custom dependency logic 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") if(MITK_USE_cpprestsdk) find_package(OpenSSL QUIET) if(NOT OpenSSL_FOUND) set(openssl_message "Could not find OpenSSL (dependency of C++ REST SDK).\n") if(UNIX) if(APPLE) set(openssl_message "${openssl_message}Please install it using your favorite package management " "system (i.e. Homebrew or MacPorts).\n") else() set(openssl_message "${openssl_message}Please install the dev package of OpenSSL (i.e. libssl-dev).\n") endif() else() set(openssl_message "${openssl_message}Please install Win32 OpenSSL:\n" " https://slproweb.com/products/Win32OpenSSL.html\n") endif() set(openssl_message "${openssl_message}If it still cannot be found, you can hint CMake to find OpenSSL by " "adding/setting the OPENSSL_ROOT_DIR variable to the root directory of an " "OpenSSL installation. Make sure to clear variables of partly found " "versions of OpenSSL before, or they will be mixed up.") message(FATAL_ERROR ${openssl_message}) endif() list(APPEND MITK_USE_Boost_LIBRARIES date_time regex system) if(UNIX) list(APPEND MITK_USE_Boost_LIBRARIES atomic chrono filesystem random thread) endif() list(REMOVE_DUPLICATES MITK_USE_Boost_LIBRARIES) set(MITK_USE_Boost_LIBRARIES ${MITK_USE_Boost_LIBRARIES} CACHE STRING "A semi-colon separated list of required Boost libraries" FORCE) endif() if(MITK_USE_Python3) set(MITK_USE_ZLIB ON CACHE BOOL "" FORCE) if(APPLE AND CMAKE_FRAMEWORK_PATH AND CMAKE_FRAMEWORK_PATH MATCHES "python3\\.?([0-9]+)") find_package(Python3 3.${CMAKE_MATCH_1} EXACT REQUIRED COMPONENTS Interpreter Development NumPy) else() find_package(Python3 REQUIRED COMPONENTS Interpreter Development NumPy) endif() if(WIN32) string(REPLACE "\\" "/" Python3_STDARCH "${Python3_STDARCH}") string(REPLACE "\\" "/" Python3_STDLIB "${Python3_STDLIB}") string(REPLACE "\\" "/" Python3_SITELIB "${Python3_SITELIB}") 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() 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) - -list(APPEND CTEST_PROJECT_SUBPROJECTS - MITK-Core - MITK-CoreUI - MITK-IGT - MITK-ToF - 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 - ) - -foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) - set(MITK_CMAKE_EXTENSION_DIR ${MITK_EXTENSION_DIR}/CMake) - get_filename_component(MITK_CMAKE_EXTENSION_DIR ${MITK_CMAKE_EXTENSION_DIR} ABSOLUTE) - if(EXISTS ${MITK_CMAKE_EXTENSION_DIR}/CTestSubprojectList.cmake) - set(MITK_CTEST_SUBPROJECTS "") - include(${MITK_CMAKE_EXTENSION_DIR}/CTestSubprojectList.cmake) - if(MITK_CTEST_SUBPROJECTS) - list(APPEND CTEST_PROJECT_SUBPROJECTS ${MITK_CTEST_SUBPROJECTS}) - endif() - endif() -endforeach() - -# 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 **************************** #***************************************************************************** #----------------------------------------------------------------------------- # Organize MITK targets in folders #----------------------------------------------------------------------------- set_property(GLOBAL PROPERTY USE_FOLDERS ON) set(MITK_ROOT_FOLDER "MITK" CACHE STRING "") mark_as_advanced(MITK_ROOT_FOLDER) #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- include(WriteBasicConfigVersionFile) include(CheckCXXSourceCompiles) include(GenerateExportHeader) include(mitkFunctionAddCustomModuleTest) include(mitkFunctionCheckModuleDependencies) include(mitkFunctionCompileSnippets) include(mitkFunctionConfigureVisualStudioUserProjectFile) include(mitkFunctionConvertXPSchema) include(mitkFunctionCreateBlueBerryApplication) include(mitkFunctionCreateCommandLineApp) include(mitkFunctionCreateModule) include(mitkFunctionCreatePlugin) include(mitkFunctionCreateProvisioningFile) include(mitkFunctionGetLibrarySearchPaths) include(mitkFunctionGetVersion) include(mitkFunctionGetVersionDescription) include(mitkFunctionInstallAutoLoadModules) include(mitkFunctionInstallCTKPlugin) include(mitkFunctionInstallProvisioningFiles) include(mitkFunctionInstallThirdPartyCTKPlugins) include(mitkFunctionOrganizeSources) include(mitkFunctionUseModules) if( ${MITK_USE_MatchPoint} ) include(mitkFunctionCreateMatchPointDeployedAlgorithm) endif() include(mitkMacroConfigureItkPixelTypes) include(mitkMacroCreateExecutable) include(mitkMacroCreateModuleTests) include(mitkMacroGenerateToolsLibrary) include(mitkMacroGetLinuxDistribution) include(mitkMacroGetPMDPlatformString) include(mitkMacroInstall) include(mitkMacroInstallHelperApp) include(mitkMacroInstallTargets) include(mitkMacroMultiplexPicType) # Deprecated include(mitkMacroCreateCTKPlugin) #----------------------------------------------------------------------------- # Global CMake variables #----------------------------------------------------------------------------- # Required and enabled C++14 features for all MITK code. # These are added as PUBLIC compile features to all MITK modules. set(MITK_CXX_FEATURES cxx_auto_type cxx_decltype cxx_enum_forward_declarations cxx_extended_friend_declarations cxx_extern_templates cxx_final cxx_lambdas cxx_local_type_template_args cxx_long_long_type cxx_nullptr cxx_override cxx_range_for cxx_right_angle_brackets cxx_rvalue_references cxx_static_assert cxx_strong_enums cxx_template_template_parameters cxx_trailing_return_types cxx_variadic_macros ) 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) #----------------------------------------------------------------------------- # Look for optional Doxygen package find_package(Doxygen) option(BLUEBERRY_DEBUG_SMARTPOINTER "Enable code for debugging smart pointers" OFF) mark_as_advanced(BLUEBERRY_DEBUG_SMARTPOINTER) # Ask the user to show the console window for applications 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") ) + if(MITK_CTEST_SCRIPT_MODE STREQUAL "Continuous" OR MITK_CTEST_SCRIPT_MODE STREQUAL "Experimental") set(MITK_FAST_TESTING ON) endif() endif() if(NOT UNIX) 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_DEFAULT_MODULE_NAME_PREFIX "Mitk") set(MITK_MODULE_NAME_PREFIX ${MITK_DEFAULT_MODULE_NAME_PREFIX}) set(MITK_MODULE_NAME_DEFAULTS_TO_DIRECTORY_NAME 1) #----------------------------------------------------------------------------- # Get MITK version info #----------------------------------------------------------------------------- mitkFunctionGetVersion(${MITK_SOURCE_DIR} MITK) mitkFunctionGetVersionDescription(${MITK_SOURCE_DIR} MITK) # 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() #----------------------------------------------------------------------------- # Installation preparation # # These should be set before any MITK install macros are used #----------------------------------------------------------------------------- # on macOS all BlueBerry plugins get copied into every # application bundle (.app directory) specified here if(MITK_USE_BLUEBERRY AND APPLE) foreach(MITK_EXTENSION_DIR ${MITK_DIR_PLUS_EXTENSION_DIRS}) set(MITK_APPLICATIONS_EXTENSION_DIR ${MITK_EXTENSION_DIR}/Applications) get_filename_component(MITK_APPLICATIONS_EXTENSION_DIR ${MITK_APPLICATIONS_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_APPLICATIONS_EXTENSION_DIR}/AppList.cmake) set(MITK_APPS "") include(${MITK_APPLICATIONS_EXTENSION_DIR}/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() 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_CXX14_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} -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 mitkFunctionCheckCompilerFlags("/wd4180" MITK_CXX_FLAGS) # warning C4180: qualifier applied to function type has no meaning mitkFunctionCheckCompilerFlags("/wd4251" MITK_CXX_FLAGS) # warning C4251: 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2' endif() if(APPLE) set(MITK_CXX_FLAGS "${MITK_CXX_FLAGS} -DGL_SILENCE_DEPRECATION") # Apple deprecated OpenGL in macOS 10.14 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 -Wno-error=deprecated-copy -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) mitkFunctionCheckCAndCXXCompilerFlags("-fstack-protector-all" MITK_C_FLAGS MITK_CXX_FLAGS) set(MITK_CXX_FLAGS_RELEASE "-U_FORTIFY_SOURCES -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}) foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) set(MITK_PACKAGE_DEPENDS_EXTENSION_DIR ${MITK_EXTENSION_DIR}/CMake/PackageDepends) get_filename_component(MITK_PACKAGE_DEPENDS_EXTENSION_DIR ${MITK_PACKAGE_DEPENDS_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_PACKAGE_DEPENDS_EXTENSION_DIR}) list(APPEND MODULES_PACKAGE_DEPENDS_DIRS ${MITK_PACKAGE_DEPENDS_EXTENSION_DIR}) endif() endforeach() 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) set(Boost_ADDITIONAL_VERSIONS 1.68 1.68.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. if(DEFINED ${_package}_DIR) #we store the information because it will be overwritten by find_package #and would get lost for all EPs that use on Find.cmake instead of config #files. set(_temp_EP_${_package}_dir ${${_package}_DIR}) endif(DEFINED ${_package}_DIR) find_package(${_package} QUIET CONFIG) string(TOUPPER "${_package}" _package_uc) if(NOT (${_package}_FOUND OR ${_package_uc}_FOUND)) if(DEFINED _temp_EP_${_package}_dir) set(${_package}_DIR ${_temp_EP_${_package}_dir} CACHE PATH "externaly set dir of the package ${_package}" FORCE) endif(DEFINED _temp_EP_${_package}_dir) 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_DCMQI) # Due to the preferred CONFIG mode in find_package calls above, # the DCMQIConfig.cmake file is read, which does not provide useful # package information. We explictly need MODULE mode to find DCMQI. # Help our FindDCMQI.cmake script find our super-build DCMQI set(DCMQI_DIR ${MITK_EXTERNAL_PROJECT_PREFIX}) find_package(DCMQI REQUIRED) endif() link_directories(${Boost_LIBRARY_DIRS}) if(MITK_USE_OpenIGTLink) link_directories(${OpenIGTLink_LIBRARY_DIRS}) endif() if(MITK_USE_OpenCL) find_package(OpenCL REQUIRED) endif() if(MITK_USE_OpenMP) find_package(OpenMP REQUIRED COMPONENTS CXX) else() find_package(OpenMP QUIET COMPONENTS CXX) if(OpenMP_FOUND) set(MITK_USE_OpenMP ON CACHE BOOL "" FORCE) elseif(APPLE AND OpenMP_libomp_LIBRARY AND NOT OpenMP_CXX_LIB_NAMES) set(OpenMP_CXX_LIB_NAMES libomp CACHE STRING "" FORCE) get_filename_component(openmp_lib_dir "${OpenMP_libomp_LIBRARY}" DIRECTORY) set(openmp_include_dir "${openmp_lib_dir}/../include") if(EXISTS "${openmp_include_dir}") get_filename_component(openmp_include_dir "${openmp_include_dir}" REALPATH) set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp -I${openmp_include_dir}" CACHE STRING "" FORCE) find_package(OpenMP QUIET COMPONENTS CXX) if(OpenMP_FOUND) set(MITK_USE_OpenMP ON CACHE BOOL "" FORCE) endif() endif() endif() endif() # Qt support if(MITK_USE_Qt5) 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() find_program(QT_HELPGENERATOR_EXECUTABLE NAMES qhelpgenerator qhelpgenerator-qt5 qhelpgenerator5 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) find_program(QT_COLLECTIONGENERATOR_EXECUTABLE NAMES qcollectiongenerator qcollectiongenerator-qt5 qcollectiongenerator5 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) find_program(QT_ASSISTANT_EXECUTABLE NAMES assistant assistant-qt5 assistant5 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) find_program(QT_XMLPATTERNS_EXECUTABLE NAMES xmlpatterns PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) mark_as_advanced(QT_HELPGENERATOR_EXECUTABLE QT_COLLECTIONGENERATOR_EXECUTABLE QT_ASSISTANT_EXECUTABLE QT_XMLPATTERNS_EXECUTABLE ) if(MITK_USE_BLUEBERRY) option(BLUEBERRY_USE_QT_HELP "Enable support for integrating plugin documentation into Qt Help" ${DOXYGEN_FOUND}) mark_as_advanced(BLUEBERRY_USE_QT_HELP) # Sanity checks for in-application BlueBerry plug-in help generation if(BLUEBERRY_USE_QT_HELP) set(_force_blueberry_use_qt_help_to_off 0) if(NOT DOXYGEN_FOUND) message("> Forcing BLUEBERRY_USE_QT_HELP to OFF because Doxygen was not found.") set(_force_blueberry_use_qt_help_to_off 1) endif() if(DOXYGEN_FOUND AND DOXYGEN_VERSION VERSION_LESS 1.8.7) message("> Forcing BLUEBERRY_USE_QT_HELP to OFF because Doxygen version 1.8.7 or newer not found.") set(_force_blueberry_use_qt_help_to_off 1) endif() if(NOT QT_HELPGENERATOR_EXECUTABLE) message("> Forcing BLUEBERRY_USE_QT_HELP to OFF because QT_HELPGENERATOR_EXECUTABLE is empty.") set(_force_blueberry_use_qt_help_to_off 1) endif() if(NOT MITK_USE_Qt5) message("> Forcing BLUEBERRY_USE_QT_HELP to OFF because MITK_USE_Qt5 is OFF.") set(_force_blueberry_use_qt_help_to_off 1) endif() if(NOT QT_XMLPATTERNS_EXECUTABLE) message("You have enabled Qt Help support, but QT_XMLPATTERNS_EXECUTABLE is empty") set(_force_blueberry_use_qt_help_to_off 1) endif() if(_force_blueberry_use_qt_help_to_off) set(BLUEBERRY_USE_QT_HELP OFF CACHE BOOL "Enable support for integrating plugin documentation into Qt Help" FORCE) endif() endif() if(BLUEBERRY_QT_HELP_REQUIRED AND NOT BLUEBERRY_USE_QT_HELP) message(FATAL_ERROR "BLUEBERRY_USE_QT_HELP is required to be set to ON") endif() endif() endif() #----------------------------------------------------------------------------- # Testing #----------------------------------------------------------------------------- if(BUILD_TESTING) - # Setup file for setting custom ctest vars - configure_file( - CMake/CTestCustom.cmake.in - ${MITK_BINARY_DIR}/CTestCustom.cmake - @ONLY - ) - # Initial cache for ProjectTemplate and PluginGenerator tests configure_file( CMake/mitkTestInitialCache.txt.in ${MITK_BINARY_DIR}/mitkTestInitialCache.txt @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 (const std::exception& e) { fprintf(stderr, \"%s\\n\", e.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 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}") -#----------------------------------------------------------------------------- -# Add custom targets representing CDash subprojects -#----------------------------------------------------------------------------- - -foreach(subproject ${CTEST_PROJECT_SUBPROJECTS}) - if(NOT TARGET ${subproject} AND NOT subproject MATCHES "Unlabeled") - add_custom_target(${subproject}) - set_property(TARGET ${subproject} PROPERTY FOLDER "${MITK_ROOT_FOLDER}/CTestSubprojects") - endif() -endforeach() - #----------------------------------------------------------------------------- # Add subdirectories #----------------------------------------------------------------------------- add_subdirectory(Utilities) add_subdirectory(Modules) include("${CMAKE_CURRENT_SOURCE_DIR}/Modules/ModuleList.cmake") mitkFunctionWhitelistModules(MITK MITK_MODULES) set(MITK_ROOT_FOLDER_BACKUP "${MITK_ROOT_FOLDER}") foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) get_filename_component(MITK_ROOT_FOLDER ${MITK_EXTENSION_DIR} NAME) set(MITK_MODULES_EXTENSION_DIR ${MITK_EXTENSION_DIR}/Modules) get_filename_component(MITK_MODULES_EXTENSION_DIR ${MITK_MODULES_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_MODULES_EXTENSION_DIR}/ModuleList.cmake) set(MITK_MODULES "") include(${MITK_MODULES_EXTENSION_DIR}/ModuleList.cmake) foreach(mitk_module ${MITK_MODULES}) add_subdirectory(${MITK_MODULES_EXTENSION_DIR}/${mitk_module} Modules/${mitk_module}) endforeach() endif() set(MITK_MODULE_NAME_PREFIX ${MITK_DEFAULT_MODULE_NAME_PREFIX}) endforeach() set(MITK_ROOT_FOLDER "${MITK_ROOT_FOLDER_BACKUP}") add_subdirectory(Wrapping) set(MITK_DOXYGEN_OUTPUT_DIR "${PROJECT_BINARY_DIR}/Documentation/Doxygen" CACHE PATH "Output directory for doxygen generated documentation.") if(MITK_USE_BLUEBERRY) set(BLUEBERRY_XPDOC_OUTPUT_DIR "${MITK_DOXYGEN_OUTPUT_DIR}/html/extension-points/html/") execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${BLUEBERRY_XPDOC_OUTPUT_DIR}) include("${CMAKE_CURRENT_SOURCE_DIR}/Plugins/PluginList.cmake") mitkFunctionWhitelistPlugins(MITK MITK_PLUGINS) set(mitk_plugins_fullpath "") foreach(mitk_plugin ${MITK_PLUGINS}) list(APPEND mitk_plugins_fullpath Plugins/${mitk_plugin}) endforeach() set(MITK_PLUGIN_REGEX_LIST "") foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) set(MITK_PLUGINS_EXTENSION_DIR ${MITK_EXTENSION_DIR}/Plugins) get_filename_component(MITK_PLUGINS_EXTENSION_DIR ${MITK_PLUGINS_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_PLUGINS_EXTENSION_DIR}/PluginList.cmake) set(MITK_PLUGINS "") include(${MITK_PLUGINS_EXTENSION_DIR}/PluginList.cmake) foreach(mitk_plugin ${MITK_PLUGINS}) list(APPEND mitk_plugins_fullpath ${MITK_PLUGINS_EXTENSION_DIR}/${mitk_plugin}) endforeach() endif() 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 MITK_PLUGIN_REGEX_LIST OUTPUT_VARIABLE ${varname}) endmacro() # Get infos about application directories and build options set(mitk_apps_fullpath "") foreach(MITK_EXTENSION_DIR ${MITK_DIR_PLUS_EXTENSION_DIRS}) set(MITK_APPLICATIONS_EXTENSION_DIR ${MITK_EXTENSION_DIR}/Applications) get_filename_component(MITK_APPLICATIONS_EXTENSION_DIR ${MITK_APPLICATIONS_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_APPLICATIONS_EXTENSION_DIR}/AppList.cmake) set(MITK_APPS "") include(${MITK_APPLICATIONS_EXTENSION_DIR}/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 0 directory_name) list(GET target_info_list 1 option_name) if(${option_name}) list(APPEND mitk_apps_fullpath "${MITK_APPLICATIONS_EXTENSION_DIR}/${directory_name}^^${option_name}") endif() endforeach() 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 #----------------------------------------------------------------------------- if(DOXYGEN_FOUND) add_subdirectory(Documentation) endif() #----------------------------------------------------------------------------- # Installation #----------------------------------------------------------------------------- # set MITK cpack variables # These are the default variables, which can be overwritten ( see below ) include(mitkSetupCPack) set(use_default_config ON) set(ALL_MITK_APPS "") set(activated_apps_no 0) foreach(MITK_EXTENSION_DIR ${MITK_DIR_PLUS_EXTENSION_DIRS}) set(MITK_APPLICATIONS_EXTENSION_DIR ${MITK_EXTENSION_DIR}/Applications) get_filename_component(MITK_APPLICATIONS_EXTENSION_DIR ${MITK_APPLICATIONS_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_APPLICATIONS_EXTENSION_DIR}/AppList.cmake) set(MITK_APPS "") include(${MITK_APPLICATIONS_EXTENSION_DIR}/AppList.cmake) foreach(mitk_app ${MITK_APPS}) string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 0 directory_name) list(GET target_info_list 1 option_name) list(GET target_info_list 2 executable_name) list(APPEND ALL_MITK_APPS "${MITK_EXTENSION_DIR}/Applications/${directory_name}^^${option_name}^^${executable_name}") if(${option_name} OR MITK_BUILD_ALL_APPS) MATH(EXPR activated_apps_no "${activated_apps_no} + 1") endif() endforeach() endif() endforeach() list(LENGTH ALL_MITK_APPS app_count) 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 ${ALL_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) list(GET target_info_list 2 executable_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 "${target_dir}/CPackOptions.cmake") include("${target_dir}/CPackOptions.cmake") endif() if(EXISTS "${target_dir}/CPackConfig.cmake.in") set(CPACK_PROJECT_CONFIG_FILE "${target_dir}/CPackConfig.cmake") configure_file(${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 "${executable_name}") endif() endforeach() # 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) #----------------------------------------------------------------------------- # MITK Applications #----------------------------------------------------------------------------- # This must come after MITKConfig.h was generated, since applications # might do a find_package(MITK REQUIRED). add_subdirectory(Applications) if(MSVC AND TARGET MitkWorkbench) set_directory_properties(PROPERTIES VS_STARTUP_PROJECT MitkWorkbench) endif() foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) set(MITK_APPLICATIONS_EXTENSION_DIR ${MITK_EXTENSION_DIR}/Applications) get_filename_component(MITK_APPLICATIONS_EXTENSION_DIR ${MITK_APPLICATIONS_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_APPLICATIONS_EXTENSION_DIR}/CMakeLists.txt) add_subdirectory(${MITK_APPLICATIONS_EXTENSION_DIR} Applications) endif() endforeach() #----------------------------------------------------------------------------- # 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/CTestConfig.cmake b/CTestConfig.cmake index 81b115e712..3dabcd5f5a 100644 --- a/CTestConfig.cmake +++ b/CTestConfig.cmake @@ -1,5 +1,3 @@ -set(CTEST_PROJECT_NAME_SUPERBUILD "MITK-superbuild") set(CTEST_PROJECT_NAME "MITK") -set(CTEST_NIGHTLY_START_TIME "00:00:00 UTC") - +set(CTEST_NIGHTLY_START_TIME "23:00:00 UTC") set(CTEST_SUBMIT_URL "https://cdash.mitk.org/submit.php?project=MITK") diff --git a/CTestConfigSubProject.cmake.in b/CTestConfigSubProject.cmake.in deleted file mode 100644 index 5bff13cd9b..0000000000 --- a/CTestConfigSubProject.cmake.in +++ /dev/null @@ -1,2 +0,0 @@ -set(CTEST_PROJECT_SUBPROJECTS @CTEST_PROJECT_SUBPROJECTS@) - diff --git a/Documentation/CMakeLists.txt b/Documentation/CMakeLists.txt index 7ab4c59c20..9492b54c1a 100644 --- a/Documentation/CMakeLists.txt +++ b/Documentation/CMakeLists.txt @@ -1,216 +1,213 @@ -# Compile source code snippets -add_subdirectory(Snippets) - # Different doxygen versions produce significantly different behaviour in the MITK documentation # especially in regards to the MITK Qt assistant help files and markdown files. # The HTML documentation is supposed to be build with Doxygen 1.8.7 or newer, the # Qt assistant QCH files are supposed to be generated with Doxygen 1.8.7 or newer. # So we check for 1.8.7 here and QCH generation support is checked in # BlueBerry/CMakeLists.txt set(supported_doxygen_version "1.8.7") if(DOXYGEN_VERSION VERSION_LESS ${supported_doxygen_version}) MESSAGE(WARNING "Unsupported doxygen version ${DOXYGEN_VERSION}. The MITK HTML documentation has been tested to work with doxygen ${supported_doxygen_version} or newer.") endif() option(USE_DOT "Use dot program for generating graphical class diagrams with doxygen, if available" ON) option(MITK_DOXYGEN_BUILD_ALWAYS "Always build the MITK documentation when building the default target" OFF) option(MITK_DOXYGEN_GENERATE_QCH_FILES "Use doxygen to generate Qt compressed help files for MITK docs" OFF) mark_as_advanced(USE_DOT MITK_DOXYGEN_BUILD_ALWAYS MITK_DOXYGEN_GENERATE_QCH_FILES) if (MITK_DOXYGEN_GENERATE_QCH_FILES AND DOXYGEN_VERSION VERSION_LESS "1.8.7") message(WARNING "> Forcing MITK_DOXYGEN_GENERATE_QCH_FILES to OFF because Doxygen version 1.8.7 or newer not found.") set(MITK_DOXYGEN_GENERATE_QCH_FILES OFF CACHE BOOL "Use doxygen to generate Qt compressed help files for MITK docs" FORCE) endif() set(HAVE_DOT "NO") if(DOXYGEN_DOT_EXECUTABLE AND USE_DOT) set(HAVE_DOT "YES") endif() set(MITK_DOXYGEN_TAGFILE_NAME ${MITK_DOXYGEN_OUTPUT_DIR}/MITK.tag CACHE INTERNAL "MITK Doxygen tag file") # This is relative to the working directory of the doxygen command set(MITK_DOXYGEN_STYLESHEET mitk_doxygen_extra.css) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${MITK_DOXYGEN_STYLESHEET} ${CMAKE_CURRENT_BINARY_DIR}/${MITK_DOXYGEN_STYLESHEET} COPYONLY) # Create QCH files for MITK and external projects set(MITK_DOXYGEN_GENERATE_QHP "NO") if(MITK_DOXYGEN_GENERATE_QCH_FILES) find_program(QT_HELPGENERATOR_EXECUTABLE NAMES qhelpgenerator qhelpgenerator-qt5 qhelpgenerator5 PATHS ${QT_BINARY_DIR} DOC "The location of the the Qt help generator executable" NO_DEFAULT_PATH ) mark_as_advanced(QT_HELPGENERATOR_EXECUTABLE) if(NOT QT_HELPGENERATOR_EXECUTABLE) message(SEND_ERROR "The Qt help generator could not be found. Disabling qch generation") else() set(MITK_DOXYGEN_GENERATE_QHP "YES") endif() # The name of the generated MITK qch file, relative to the # Doxygen HTML output folder set(MITK_DOXYGEN_QCH_FILE "${MITK_BINARY_DIR}/MITK-${MITK_REVISION_ID}.qch") # Generating ITK and VTK docs it not done yet #option(MITK_DOXYGEN_GENERATE_VTK_QCH_FILE "Use doxygen to generate a Qt compressed help file for VTK docs" OFF) #option(MITK_DOXYGEN_GENERATE_ITK_QCH_FILE "Use doxygen to generate a Qt compressed help file for ITK docs" OFF) #mark_as_advanced(MITK_DOXYGEN_GENERATE_VTK_QCH_FILE MITK_DOXYGEN_GENERATE_ITK_QCH_FILE) endif() if(MITK_USE_BLUEBERRY) file(RELATIVE_PATH _blueberry_doxygen_path ${MITK_DOXYGEN_OUTPUT_DIR}/html ${BLUEBERRY_DOXYGEN_OUTPUT_DIR}/html) set(BLUEBERRY_DOXYGEN_TAGFILE "${BLUEBERRY_DOXYGEN_TAGFILE_NAME}=${_blueberry_doxygen_path}") set(BLUEBERRY_DOXYGEN_LINK "BlueBerry Documentation") set(MITK_XP_LINK "\\ref mitkExtPointsIndex") configure_file(schema.css ${MITK_DOXYGEN_OUTPUT_DIR}/html/schema.css) set(MITK_DOXYGEN_ENABLED_SECTIONS "${MITK_DOXYGEN_ENABLED_SECTIONS} BLUEBERRY") endif(MITK_USE_BLUEBERRY) # Compile a doxygen input filter for processing CMake scripts include(mitkFunctionCMakeDoxygenFilterCompile) mitkFunctionCMakeDoxygenFilterCompile(NAMESPACE "CMake") # Configure some doxygen options if(NOT MITK_DOXYGEN_INTERNAL_DOCS) set(MITK_DOXYGEN_INTERNAL_DOCS "NO") set(MITK_DOXYGEN_HIDE_FRIEND_COMPOUNDS "YES") set(MITK_DOXYGEN_EXCLUDE_PATTERNS "*_p.* *Private.h */internal/*") else() set(MITK_DOXYGEN_HIDE_FRIEND_COMPOUNDS "NO") set(MITK_DOXYGEN_EXCLUDE_PATTERNS "") endif() if(NOT MITK_DOXYGEN_GENERATE_TODOLIST) set(MITK_DOXYGEN_GENERATE_TODOLIST "NO") endif() if(NOT MITK_DOXYGEN_GENERATE_BUGLIST) set(MITK_DOXYGEN_GENERATE_BUGLIST "NO") endif() if(NOT MITK_DOXYGEN_HTML_DYNAMIC_SECTIONS) set(MITK_DOXYGEN_HTML_DYNAMIC_SECTIONS "NO") endif() if(NOT MITK_DOXYGEN_UML_LOOK) set(MITK_DOXYGEN_UML_LOOK "NO") endif() if(NOT MITK_DOXYGEN_GENERATE_DEPRECATEDLIST) set(MITK_DOXYGEN_GENERATE_DEPRECATEDLIST "YES") endif() if(NOT DEFINED MITK_DOXYGEN_DOT_NUM_THREADS) set(MITK_DOXYGEN_DOT_NUM_THREADS 0) endif() if(NOT DEFINED US_PLATFORM) if(UNIX) if(APPLE) set(US_PLATFORM "US_PLATFORM_APPLE=1") else() set(US_PLATFORM "US_PLATFORM_LINUX=1") endif() set(US_PLATFORM "${US_PLATFORM} \\\nUS_PLATFORM_POSIX=1") else() set(US_PLATFORM "US_PLATFORM_WINDOWS=1") endif() endif() # parse which plug-in documentation to activate set(USERS_GUIDE_INPUT "${MITK_SOURCE_DIR}/Documentation/Doxygen/UserManual/") if(MITK_USE_BLUEBERRY) if(MITK_BUILD_ALL_PLUGINS) set(USERS_GUIDE_INPUT "${USERS_GUIDE_INPUT} \\ ${MITK_SOURCE_DIR}/Plugins/") else() foreach(mitk_plugin ${${CMAKE_PROJECT_NAME}_PLUGIN_LIBRARIES}) # we want each line to end in " \" and each directory be on a separate line set(USERS_GUIDE_INPUT "${USERS_GUIDE_INPUT} \\ ${${mitk_plugin}_SOURCE_DIR}/") endforeach() endif() if(MITK_BUILD_EXAMPLES) set(USERS_GUIDE_INPUT "${USERS_GUIDE_INPUT} \\ ${MITK_SOURCE_DIR}/Examples/Plugins/") endif() endif() # create output directories for the guides file(MAKE_DIRECTORY ${MITK_DOXYGEN_OUTPUT_DIR}/Guides/Users_Guide/) file(MAKE_DIRECTORY ${MITK_DOXYGEN_OUTPUT_DIR}/Guides/Developers_Guide/) configure_file(doxygen.conf.in ${CMAKE_CURRENT_BINARY_DIR}/doxygen.conf) configure_file(doxygen_users_guide.conf.in ${CMAKE_CURRENT_BINARY_DIR}/doxygen_users_guide.conf) configure_file(doxygen_developers_guide.conf.in ${CMAKE_CURRENT_BINARY_DIR}/doxygen_developers_guide.conf) if(MITK_DOXYGEN_BUILD_ALWAYS) set(_doc_in_all "ALL") else() set(_doc_in_all "") endif() add_custom_target(doc ${_doc_in_all} ${DOXYGEN} ${CMAKE_CURRENT_BINARY_DIR}/doxygen.conf WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) add_custom_target(doc_usersguide ${DOXYGEN} ${CMAKE_CURRENT_BINARY_DIR}/doxygen_users_guide.conf WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) add_custom_target(doc_developersguide ${DOXYGEN} ${CMAKE_CURRENT_BINARY_DIR}/doxygen_developers_guide.conf WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) set_property(TARGET doc doc_usersguide doc_developersguide PROPERTY FOLDER "${MITK_ROOT_FOLDER}/Documentation") if(MITK_USE_BLUEBERRY) # convert the extension points schema files into html find_package(Ant) set(BLUEBERRY_DOC_TOOLS_DIR "" CACHE PATH "Directory containing additional tools needed for generating the documentation") if(ANT_FOUND AND BLUEBERRY_DOC_TOOLS_DIR) list(APPEND MITK_XP_GLOB_EXPRESSIONS ${MITK_SOURCE_DIR}/Plugins/plugin.xml) file(GLOB_RECURSE _plugin_xmls ${MITK_XP_GLOB_EXPRESSIONS}) mitkFunctionConvertXPSchema(INPUT ${_plugin_xmls} OUTPUT_DIR "${MITK_DOXYGEN_OUTPUT_DIR}/html/extension-points/html" TARGET_NAME mitkXPDoc ) add_dependencies(doc mitkXPDoc) else() message(STATUS "Extension-point schema documentation generation disabled due to missing Ant and / or missing BlueBerry doc tools.") endif() endif(MITK_USE_BLUEBERRY) #if(MITK_DOXYGEN_GENERATE_ITK_QCH_FILE) # # add the command to generate the ITK documentation # add_custom_target(doc-itk # COMMAND ${DOXYGEN} ${CMAKE_CURRENT_BINARY_DIR}/doxygen.itk.conf) # add_dependencies(doc doc-itk) #endif() #if(MITK_DOXYGEN_GENERATE_VTK_QCH_FILE) # # add the command to generate the VTK documentation # add_custom_target(doc-vtk # COMMAND ${DOXYGEN} ${CMAKE_CURRENT_BINARY_DIR}/doxygen.vtk.conf) # add_dependencies(doc doc-vtk) #endif() diff --git a/Documentation/Doxygen/2-UserManual/MITKPluginGeneralManualsList.dox b/Documentation/Doxygen/2-UserManual/MITKPluginGeneralManualsList.dox index d21900ecc1..78f1b417e2 100644 --- a/Documentation/Doxygen/2-UserManual/MITKPluginGeneralManualsList.dox +++ b/Documentation/Doxygen/2-UserManual/MITKPluginGeneralManualsList.dox @@ -1,32 +1,32 @@ /** \page PluginListGeneralPage List of General Purpose Plugins \li \subpage org_mitk_views_basicimageprocessing \li \subpage org_mitk_views_datamanager \li \subpage org_mitk_views_properties \li \subpage org_mitk_editors_dicombrowser \li \subpage org_mitk_gui_qt_dicominspector \li \subpage org_mitk_views_imagecropper \li \subpage org_mitk_views_imagenavigator \li \subpage org_blueberry_ui_qt_log \li \subpage org_mitk_gui_qt_matchpoint_algorithm_batch - \li \subpage org_mitk_gui_qt_matchpoint_algorithm_browser - \li \subpage org_mitk_gui_qt_matchpoint_algorithm_control - \li \subpage org_mitk_gui_qt_matchpoint_evaluator - \li \subpage org_mitk_gui_qt_matchpoint_framereg - \li \subpage org_mitk_gui_qt_matchpoint_manipulator - \li \subpage org_mitk_gui_qt_matchpoint_mapper - \li \subpage org_mitk_gui_qt_matchpoint_visualizer + \li \subpage org_mitk_views_qt_matchpoint_algorithm_browser + \li \subpage org_mitk_views_qt_matchpoint_algorithm_control + \li \subpage org_mitk_views_matchpoint_evaluator + \li \subpage org_mitk_views_qt_matchpoint_framereg + \li \subpage org_mitk_views_qt_matchpoint_manipulator + \li \subpage org_mitk_views_matchpoint_mapper + \li \subpage org_mitk_views_qt_matchpoint_visualizer \li \subpage org_mitk_gui_qt_measurementtoolbox \li \subpage org_mitk_views_moviemaker \li \subpage org_mitk_views_multilabelsegmentation \li \subpage org_mitk_views_pointsetinteraction \li \subpage org_mitk_gui_qt_python \li \subpage org_mitk_gui_qt_remeshing \li \subpage org_mitk_views_screenshotmaker \li \subpage org_mitk_views_segmentation \li \subpage org_mitk_gui_qt_flow_segmentation \li \subpage org_mitk_gui_qt_viewnavigator \li \subpage org_mitk_views_volumevisualization */ diff --git a/Documentation/Doxygen/2-UserManual/MITKPluginManualsList.dox b/Documentation/Doxygen/2-UserManual/MITKPluginManualsList.dox index e54330dd05..2bf2a11b12 100644 --- a/Documentation/Doxygen/2-UserManual/MITKPluginManualsList.dox +++ b/Documentation/Doxygen/2-UserManual/MITKPluginManualsList.dox @@ -1,84 +1,84 @@ /** \page PluginListPage MITK Plugin Manuals The plugins and bundles provide much of the extended functionality of MITK. Each encapsulates a solution to a problem and associated features. This way one can easily assemble the necessary capabilites for a workflow without adding a lot of bloat, by combining plugins as needed. \subpage PluginListGeneralPage
  • \ref org_mitk_views_basicimageprocessing
  • \ref org_mitk_views_datamanager
  • \ref org_mitk_editors_dicombrowser
  • \ref org_mitk_gui_qt_dicominspector
  • \ref org_mitk_gui_qt_flowapplication
  • \ref org_mitk_views_imagecropper
  • \ref org_mitk_views_imagenavigator
  • \ref org_blueberry_ui_qt_log
  • -
  • \ref org_mitk_gui_qt_matchpoint_algorithm_browser
  • -
  • \ref org_mitk_gui_qt_matchpoint_algorithm_control
  • -
  • \ref org_mitk_gui_qt_matchpoint_evaluator
  • -
  • \ref org_mitk_gui_qt_matchpoint_framereg
  • -
  • \ref org_mitk_gui_qt_matchpoint_manipulator
  • -
  • \ref org_mitk_gui_qt_matchpoint_mapper
  • -
  • \ref org_mitk_gui_qt_matchpoint_visualizer
  • +
  • \ref org_mitk_views_matchpoint_algorithm_browser
  • +
  • \ref org_mitk_views_matchpoint_algorithm_control
  • +
  • \ref org_mitk_views_matchpoint_evaluator
  • +
  • \ref org_mitk_views_matchpoint_framereg
  • +
  • \ref org_mitk_views_matchpoint_manipulator
  • +
  • \ref org_mitk_views_matchpoint_mapper
  • +
  • \ref org_mitk_views_matchpoint_visualizer
  • \ref org_mitk_gui_qt_measurementtoolbox
  • \ref org_mitk_views_moviemaker
  • \ref org_mitk_views_multilabelsegmentation
  • \ref org_mitk_views_pointsetinteraction
  • \ref org_mitk_gui_qt_python
  • \ref org_mitk_gui_qt_remeshing
  • \ref org_mitk_views_screenshotmaker
  • \ref org_mitk_views_segmentation
  • \ref org_mitk_gui_qt_flow_segmentation
  • \ref org_mitk_gui_qt_viewnavigator
  • \ref org_mitk_views_volumevisualization
\subpage PluginListSpecificPage
  • \ref org_mitk_views_properties
  • \ref org_mitk_gui_qt_aicpregistration
  • \ref org_mitk_gui_qt_cest
  • \ref org_mitk_gui_qt_classificationsegmentation
  • \ref org_mitk_views_cmdlinemodules
  • \ref org_mitk_gui_qt_pharmacokinetics_concentration_mri
  • \ref org_mitk_views_pharmacokinetics_mri
  • \ref org_mitk_gui_qt_pharmacokinetics_pet
  • \ref org_mitk_gui_qt_eventrecorder
  • \ref org_mitk_gui_qt_examples
  • \ref org_mitk_gui_qt_geometrytools
  • \ref org_mitk_gui_qt_igtexample
  • \ref org_mitk_gui_qt_igtlplugin
  • \ref org_mitk_gui_qt_igttracking
  • \ref org_mitk_gui_qt_igttrackingsemiautomaticmeasurement
  • \ref org_mitk_views_imagestatistics
  • \ref org_mitk_gui_qt_lasercontrol
  • \ref org_mitk_gui_qt_fit_demo
  • \ref org_mitk_gui_qt_fit_genericfitting
  • \ref org_mitk_gui_qt_fit_inspector
  • \ref org_mitkexamplesopencv
  • \ref org_mitk_gui_qt_overlaymanager
  • \ref org_mitk_gui_qt_mitkphenotyping
  • \ref org_mitk_gui_qt_photoacoustics_pausmotioncompensation
  • \ref org_mitk_example_gui_pcaexample
  • \ref org_mitk_gui_qt_preprocessing_resampling
  • \ref org_mitk_gui_qt_pharmacokinetics_curvedescriptor
  • \ref org_mitk_gui_qt_photoacoustics_imageprocessing
  • \ref org_mitk_gui_qt_pharmacokinetics_simulation
  • \ref org_mitk_gui_qt_pointsetinteractionmultispectrum
  • \ref org_mitk_gui_qt_renderwindowmanager
  • \ref org_mitk_gui_qt_photoacoustics_spectralunmixing
  • \ref org_mitk_gui_qt_spectrocamrecorder
  • \ref org_surfacematerialeditor
  • \ref org_toftutorial
  • \ref org_blueberry_ui_qt_objectinspector
  • \ref org_mitk_gui_qt_ultrasound
  • \ref org_mitk_gui_qt_igt_app_echotrack
  • \ref org_mitk_gui_qt_xnat
*/ diff --git a/Documentation/Snippets/CMakeLists.txt b/Documentation/Snippets/CMakeLists.txt deleted file mode 100644 index 01142e1503..0000000000 --- a/Documentation/Snippets/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -if(BUILD_TESTING) - include(mitkFunctionCompileSnippets) - - include_directories(${CTKPluginFramework_INCLUDE_DIRS}) - - set(_link_libs CTKPluginFramework) - mitkFunctionCompileSnippets("${CMAKE_CURRENT_SOURCE_DIR}" ${_link_libs}) -endif() diff --git a/Documentation/Snippets/org.blueberry.ui.qt.help-config/main.cpp b/Documentation/Snippets/org.blueberry.ui.qt.help-config/main.cpp deleted file mode 100644 index 473ba9d872..0000000000 --- a/Documentation/Snippets/org.blueberry.ui.qt.help-config/main.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#include - -#include -#include -#include -#include -#include - -class MyApplicationPlugin : public QObject, public ctkPluginActivator -{ - Q_OBJECT - Q_INTERFACES(ctkPluginActivator) - -public: - MyApplicationPlugin(); - ~MyApplicationPlugin() override; - - //! [0] - void start(ctkPluginContext *context) override - { - // Get a service reference for the Config Admin service - ctkServiceReference cmRef = context->getServiceReference(); - ctkConfigurationAdmin *configAdmin = nullptr; - if (cmRef) - { - configAdmin = context->getService(cmRef); - } - - // Use the CTK Configuration Admin service to configure the BlueBerry help system. - // This assumes that the plug-in providing the Config Admin implementation is - // already active. - if (configAdmin) - { - // Get a ctkConfiguration object for the PID "org.blueberry.services.help" - // (or create an unbound instance if it does not exist yet). - ctkConfigurationPtr conf = configAdmin->getConfiguration("org.blueberry.services.help", QString()); - - // Configure the help system using a custom home page - ctkDictionary helpProps; - helpProps.insert("homePage", "qthelp://org.company.plugin/bundle/index.html"); - conf->update(helpProps); - - // Unget the service - context->ungetService(cmRef); - } - else - { - // Warn that the Config Admin service is unavailable - } - } - //! [0] - - void stop(ctkPluginContext *context) override; - - //! [1] - void requestHelp(ctkPluginContext *context) - { - if (context == nullptr) - { - // Warn that the plugin context is zero - return; - } - - // Check if the org.blueberry.ui.qt.help plug-in is installed and started - QList> plugins = context->getPlugins(); - foreach (QSharedPointer p, plugins) - { - if (p->getSymbolicName() == "org.blueberry.ui.qt.help" && p->getState() != ctkPlugin::ACTIVE) - { - // The plug-in is in RESOLVED state but is not started yet. - // Try to activate the plug-in explicitly, so that it can react - // to events send via the CTK Event Admin. - try - { - p->start(ctkPlugin::START_TRANSIENT); - } - catch (const ctkPluginException &) - { - // Warn that activating the org.blueberry.ui.qt.help plug-in failed - return; - } - } - } - - ctkServiceReference eventAdminRef = context->getServiceReference(); - ctkEventAdmin *eventAdmin = nullptr; - if (eventAdminRef) - { - eventAdmin = context->getService(eventAdminRef); - } - - if (eventAdmin == nullptr) - { - // Warn that the ctkEventAdmin service was not found - } - else - { - // Create the event and send it asynchronuously - ctkEvent ev("org/blueberry/ui/help/CONTEXTHELP_REQUESTED"); - eventAdmin->postEvent(ev); - } - } - //! [1] - -private: -}; - -int main(int /*argc*/, char * /*argv*/ []) -{ - return 0; -} diff --git a/Examples/BlueBerryExampleLauncher/CMakeLists.txt b/Examples/BlueBerryExampleLauncher/CMakeLists.txt index 06111f4d8c..6890323b01 100644 --- a/Examples/BlueBerryExampleLauncher/CMakeLists.txt +++ b/Examples/BlueBerryExampleLauncher/CMakeLists.txt @@ -1,82 +1,76 @@ project(BlueBerryExampleLauncher) set(_source_files BlueBerryExampleLauncher.cpp BlueBerryExampleLauncherDialog.cpp ) set(_source_moc_h_files BlueBerryExampleLauncherDialog.h ) set(_source_ui_files BlueBerryExampleLauncherDialog.ui ) # this is a workaround for Visual Studio. The relative include paths in the generated # moc files can get very long and can't be resolved by the MSVC compiler. foreach(_moc_src ${_source_moc_h_files}) qt5_wrap_cpp(_source_files ${_moc_src} OPTIONS -f${_moc_src}) endforeach() qt5_wrap_ui(_source_files ${_source_ui_files}) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) #----------------------------------------------------------------------------- # Create provisioning files #----------------------------------------------------------------------------- set(_plugins_for_all_demos ) file(GLOB _demo_configurations Configurations/*.cmake) set(ALL_REQUIRED_PLUGINS ${_plugins_for_all_demos}) foreach(_demo_config_file ${_demo_configurations}) set(REQUIRED_PLUGINS ) set(DESCRIPTION ) include(${_demo_config_file}) get_filename_component(_name ${_demo_config_file} NAME_WE) mitkFunctionCreateProvisioningFile(FILE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}_${_name}.provisioning PLUGINS ${REQUIRED_PLUGINS} ${_plugins_for_all_demos} NO_INSTALL ) if(DESCRIPTION) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/BlueBerryExampleDescription.txt ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}_${_name}.txt @ONLY) endif() list(APPEND ALL_REQUIRED_PLUGINS ${REQUIRED_PLUGINS}) endforeach() list(REMOVE_DUPLICATES ALL_REQUIRED_PLUGINS) set(ALL_REQUIRED_PLUGIN_TARGETS ) foreach(req_plugin ${ALL_REQUIRED_PLUGINS}) string(REPLACE "." "_" _plugin_target ${req_plugin}) if(TARGET ${_plugin_target}) list(APPEND ALL_REQUIRED_PLUGIN_TARGETS ${_plugin_target}) endif() endforeach() #----------------------------------------------------------------------------- # Create the example launcher #----------------------------------------------------------------------------- mitkFunctionCreateBlueBerryApplication( NAME ${PROJECT_NAME} DESCRIPTION "MITK Application Framework Demo" SOURCES ${_source_files} # PLUGINS ${ALL_REQUIRED_PLUGIN_TARGETS} NO_PROVISIONING NO_INSTALL ) add_dependencies(${PROJECT_NAME} ${ALL_REQUIRED_PLUGIN_TARGETS}) - -# subproject support -set_property(TARGET ${PROJECT_NAME} PROPERTY LABELS ${MITK_DEFAULT_SUBPROJECTS}) -foreach(subproject ${MITK_DEFAULT_SUBPROJECTS}) - add_dependencies(${subproject} ${PROJECT_NAME}) -endforeach() diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index e14eb0f581..870475f3a0 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -1,52 +1,49 @@ - -set(MITK_DEFAULT_SUBPROJECTS MITK-Examples) - #----------------------------------------------------------------------------- # Set-up example plugins #----------------------------------------------------------------------------- if(MITK_USE_BLUEBERRY) # Specify which plug-ins belong to this project macro(GetMyTargetLibraries all_target_libraries varname) set(re_ctkplugin_mitk "^org_mitk_example_[a-zA-Z0-9_]+$") set(_tmp_list) list(APPEND _tmp_list ${all_target_libraries}) ctkMacroListFilter(_tmp_list re_ctkplugin_mitk OUTPUT_VARIABLE ${varname}) endmacro() set(MITK_EXAMPLE_PLUGIN_TARGETS ) foreach(mitk_example_plugin ${MITK_EXAMPLE_PLUGINS}) ctkFunctionExtractOptionNameAndValue(${mitk_example_plugin} plugin_name plugin_value) string(REPLACE "." "_" _plugin_target ${plugin_name}) list(APPEND MITK_EXAMPLE_PLUGIN_TARGETS ${_plugin_target}) mark_as_advanced(${${_plugin_target}_option_name}) endforeach() endif() #----------------------------------------------------------------------------- # Add example executables #----------------------------------------------------------------------------- set(MITK_DIR ${PROJECT_BINARY_DIR}) set(MITK_EXPORTS_FILE_INCLUDED 1) set(_example_dirs Dump MbiLog QtFreeRender Tutorial FirstSteps Annotation ) if(MITK_USE_BLUEBERRY) list(APPEND _example_dirs BlueBerryExampleLauncher ) endif() foreach(_example_dir ${_example_dirs}) add_subdirectory(${_example_dir}) endforeach() diff --git a/Examples/FirstSteps/NewModule/CMakeLists.txt b/Examples/FirstSteps/NewModule/CMakeLists.txt index 9fd2803595..12f4c6f71e 100644 --- a/Examples/FirstSteps/NewModule/CMakeLists.txt +++ b/Examples/FirstSteps/NewModule/CMakeLists.txt @@ -1,11 +1,10 @@ MITK_CREATE_MODULE( INCLUDE_DIRS PUBLIC ${MITK_BINARY_DIR} PRIVATE src/DataManagement DEPENDS PUBLIC MitkCore - SUBPROJECTS MITK-Examples ) add_subdirectory(autoload/IO) add_subdirectory(cmdapps) add_subdirectory(test) diff --git a/Examples/FirstSteps/NewModule/autoload/IO/CMakeLists.txt b/Examples/FirstSteps/NewModule/autoload/IO/CMakeLists.txt index c9c1d4d72b..24b2612a99 100644 --- a/Examples/FirstSteps/NewModule/autoload/IO/CMakeLists.txt +++ b/Examples/FirstSteps/NewModule/autoload/IO/CMakeLists.txt @@ -1,9 +1,8 @@ MITK_CREATE_MODULE( NewModuleIO INCLUDE_DIRS PRIVATE src/IO DEPENDS PUBLIC MitkNewModule MitkSceneSerialization PACKAGE_DEPENDS PRIVATE tinyxml AUTOLOAD_WITH MitkCore - SUBPROJECTS MITK-Examples -) \ No newline at end of file +) diff --git a/Modules/CommandLine/CMakeLists.txt b/Modules/CommandLine/CMakeLists.txt index 716f698871..5f101a602e 100644 --- a/Modules/CommandLine/CMakeLists.txt +++ b/Modules/CommandLine/CMakeLists.txt @@ -1,7 +1,6 @@ MITK_CREATE_MODULE( INCLUDE_DIRS PUBLIC include/ PRIVATE src/ - SUBPROJECTS MITK-Modules DEPENDS MitkCore ) diff --git a/Modules/Core/CMakeLists.txt b/Modules/Core/CMakeLists.txt index bae8a92060..9443972b06 100644 --- a/Modules/Core/CMakeLists.txt +++ b/Modules/Core/CMakeLists.txt @@ -1,66 +1,65 @@ set(TOOL_CPPS "") # temporary suppress warnings in the following files until image accessors are fully integrated. set_source_files_properties( src/DataManagement/mitkImage.cpp COMPILE_FLAGS -DMITK_NO_DEPRECATED_WARNINGS ) set_source_files_properties( src/Controllers/mitkSliceNavigationController.cpp COMPILE_FLAGS -DMITK_NO_DEPRECATED_WARNINGS ) MITK_CREATE_MODULE( INCLUDE_DIRS PUBLIC ${MITK_BINARY_DIR} PRIVATE src/Algorithms src/Controllers src/DataManagement src/Interactions src/IO src/Rendering ${OPENGL_INCLUDE_DIR} DEPENDS PUBLIC mbilog CppMicroServices PACKAGE_DEPENDS PRIVATE tinyxml OpenGL PUBLIC ITK|ITKTransform+ITKImageGrid+ITKImageFeature+ITKIOImageBase+ITKIOHDF5+ITKIOLSM+ITKIOMRC+ITKIOBioRad+ITKIOGE+ITKIOStimulate+ITKIOBruker+ITKIOMINC # We privately use/link all ITK modules in order to support all IO, Transform, etc. # factories from ITK which are registered "automatically" via a factory manager. PRIVATE ITK PUBLIC VTK|vtkFiltersTexture+vtkFiltersParallel+vtkImagingStencil+vtkImagingMath+vtkInteractionStyle+vtkRenderingOpenGL2+vtkRenderingContextOpenGL2+vtkRenderingVolumeOpenGL2+vtkRenderingFreeType+vtkRenderingLabel+vtkInteractionWidgets+vtkIOGeometry+vtkIOXML PUBLIC Boost|boost - SUBPROJECTS MITK-Core # Do not automatically create CppMicroServices initialization code. # Because the VTK 6 "auto-init" functionality injects file-local static # initialization code in every cpp file which includes a VTK header, # static initialization order becomes an issue again. For the Mitk # core library, we need to ensure that the VTK static initialization stuff # happens before the CppMicroServices initialization, since the latter # might already use VTK code which needs to access VTK object factories. # Hence, CppMicroServices initialization code is placed manually within # the mitkCoreActivator.cpp file. NO_INIT ) if(NOT TARGET ${MODULE_TARGET}) message(SEND_ERROR "Core target ${MODULE_TARGET} does not exist") endif() function(_itk_create_factory_register_manager) # In MITK_ITK_Config.cmake, we do *not* include ITK_USE_FILE, which # prevents multiple registrations/unregistrations of ITK IO factories # during library loading/unloading (of MITK libraries). However, we need # "one" place where the IO factories are registered at # least once. This could be the application executable, but every executable would # need to take care of that itself. Instead, we allow the auto registration in the # Mitk Core library. set(NO_DIRECTORY_SCOPED_ITK_COMPILE_DEFINITION 1) find_package(ITK) include(${ITK_USE_FILE}) if(NOT ITK_NO_IO_FACTORY_REGISTER_MANAGER) # We manually add the define which will be of target scope. MITK # patches ITK_USE_FILE to remove the directory scoped compile # definition since it would be propagated to other targets in the # same directory scope but these targets might want to *not* # use the ITK factory manager stuff. target_compile_definitions(${MODULE_TARGET} PRIVATE ITK_IO_FACTORY_REGISTER_MANAGER) endif() endfunction() _itk_create_factory_register_manager() if(MSVC_IDE OR MSVC_VERSION) target_link_libraries(${MODULE_TARGET} PRIVATE psapi.lib) endif() if(BUILD_TESTING) add_subdirectory(TestingHelper) add_subdirectory(test) endif() diff --git a/Modules/CppMicroServices/cmake/usFunctionCompileSnippets.cmake b/Modules/CppMicroServices/cmake/usFunctionCompileSnippets.cmake index 2df8c74a4d..1fd333819b 100644 --- a/Modules/CppMicroServices/cmake/usFunctionCompileSnippets.cmake +++ b/Modules/CppMicroServices/cmake/usFunctionCompileSnippets.cmake @@ -1,51 +1,50 @@ function(usFunctionCompileSnippets snippet_path) # get all files called "main.cpp" file(GLOB_RECURSE main_cpp_list "${snippet_path}/main.cpp") foreach(main_cpp_file ${main_cpp_list}) # get the directory containing the main.cpp file get_filename_component(main_cpp_dir "${main_cpp_file}" PATH) set(snippet_src_files ) # If there exists a "files.cmake" file in the snippet directory, # include it and assume it sets the variable "snippet_src_files" # to a list of source files for the snippet. if(EXISTS "${main_cpp_dir}/files.cmake") include("${main_cpp_dir}/files.cmake") set(_tmp_src_files ${snippet_src_files}) set(snippet_src_files ) foreach(_src_file ${_tmp_src_files}) if(IS_ABSOLUTE ${_src_file}) list(APPEND snippet_src_files ${_src_file}) else() list(APPEND snippet_src_files ${main_cpp_dir}/${_src_file}) endif() endforeach() else() # glob all files in the directory and add them to the snippet src list file(GLOB_RECURSE snippet_src_files "${main_cpp_dir}/*") endif() # Uset the top-level directory name as the executable name string(REPLACE "/" ";" main_cpp_dir_tokens "${main_cpp_dir}") list(GET main_cpp_dir_tokens -1 snippet_exec_name) set(snippet_target_name "Snippet-${snippet_exec_name}") add_executable(${snippet_target_name} ${snippet_src_files}) target_link_libraries(${snippet_target_name} ${PROJECT_TARGET} ${snippet_link_libraries}) set_property(TARGET ${snippet_target_name} APPEND PROPERTY COMPILE_DEFINITIONS US_MODULE_NAME=main) set_property(TARGET ${snippet_target_name} PROPERTY US_MODULE_NAME main) set_property(TARGET ${snippet_target_name} PROPERTY FOLDER "${MITK_ROOT_FOLDER}/CppMicroServices/Snippets") set_target_properties(${snippet_target_name} PROPERTIES - LABELS Documentation RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/snippets" ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/snippets" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/snippets" OUTPUT_NAME ${snippet_exec_name} ) endforeach() endfunction() diff --git a/Modules/CppMicroServices/core/doc/snippets/uServices-resources-cmake/CMakeLists.txt b/Modules/CppMicroServices/core/doc/snippets/uServices-resources-cmake/CMakeLists.txt index d1ab01f6f0..9d41b1df2e 100644 --- a/Modules/CppMicroServices/core/doc/snippets/uServices-resources-cmake/CMakeLists.txt +++ b/Modules/CppMicroServices/core/doc/snippets/uServices-resources-cmake/CMakeLists.txt @@ -1,9 +1,8 @@ include(${CMAKE_CURRENT_LIST_DIR}/CMakeLists_example.txt) set_target_properties(mymodule PROPERTIES - LABELS Documentation RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/snippets" ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/snippets" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/snippets" OUTPUT_NAME Snippet-mymodule ) diff --git a/Modules/CppMicroServices/core/examples/CMakeLists.txt b/Modules/CppMicroServices/core/examples/CMakeLists.txt index 1144b939be..96b99784f8 100644 --- a/Modules/CppMicroServices/core/examples/CMakeLists.txt +++ b/Modules/CppMicroServices/core/examples/CMakeLists.txt @@ -1,176 +1,169 @@ project(CoreExamples) cmake_minimum_required(VERSION 2.8) find_package(CppMicroServices NO_MODULE REQUIRED) include_directories(${CppMicroServices_INCLUDE_DIRS}) #----------------------------------------------------------------------------- # Set C/CXX flags #----------------------------------------------------------------------------- #if(${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}) # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CppMicroServices_CXX_FLAGS}") # set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${CppMicroServices_CXX_FLAGS_RELEASE}") # set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${CppMicroServices_CXX_FLAGS_DEBUG}") # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CppMicroServices_C_FLAGS}") # set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${CppMicroServices_C_FLAGS_RELEASE}") # set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${CppMicroServices_C_FLAGS_DEBUG}") #endif() #----------------------------------------------------------------------------- # Init output directories #----------------------------------------------------------------------------- set(CoreExamples_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") set(CoreExamples_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") set(CoreExamples_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin") foreach(_type ARCHIVE LIBRARY RUNTIME) if(NOT CMAKE_${_type}_OUTPUT_DIRECTORY) set(CMAKE_${_type}_OUTPUT_DIRECTORY ${CoreExamples_${_type}_OUTPUT_DIRECTORY}) endif() endforeach() function(CreateExample _name) add_library(Example-${_name} ${ARGN}) set_property(TARGET Example-${_name} APPEND PROPERTY COMPILE_DEFINITIONS US_MODULE_NAME=${_name}) if(NOT US_BUILD_SHARED_LIBS) set_property(TARGET Example-${_name} APPEND PROPERTY COMPILE_DEFINITIONS US_STATIC_MODULE) endif() if(${_name}_DEPENDS) foreach(_dep ${${_name}_DEPENDS}) include_directories(${PROJECT_SOURCE_DIR}/${_dep}) target_link_libraries(Example-${_name} Example-${_dep}) endforeach() endif() target_link_libraries(Example-${_name} ${CppMicroServices_LIBRARIES}) - set_target_properties(Example-${_name} PROPERTIES - LABELS Examples - OUTPUT_NAME ${_name} - ) + set_target_properties(Example-${_name} PROPERTIES OUTPUT_NAME ${_name}) endfunction() add_subdirectory(eventlistener) add_subdirectory(dictionaryservice) add_subdirectory(frenchdictionary) add_subdirectory(dictionaryclient) add_subdirectory(dictionaryclient2) add_subdirectory(dictionaryclient3) add_subdirectory(spellcheckservice) add_subdirectory(spellcheckclient) add_subdirectory(driver) #----------------------------------------------------------------------------- # Test if examples compile against an install tree and if the # Makefile example compiles #----------------------------------------------------------------------------- if(US_BUILD_TESTING) enable_testing() set(_example_tests ) if(WIN32) string(REGEX REPLACE "^.:" "" _install_prefix ${CMAKE_INSTALL_PREFIX}) else() set(_install_prefix ${CMAKE_INSTALL_PREFIX}) endif() set(_install_dir "${CppMicroServices_BINARY_DIR}/install_test/${_install_prefix}") add_test(NAME usInstallCleanTest COMMAND ${CMAKE_COMMAND} -E remove_directory "${_install_dir}") add_test(NAME usInstallTest WORKING_DIRECTORY ${CppMicroServices_BINARY_DIR} COMMAND ${CMAKE_COMMAND} --build ${CppMicroServices_BINARY_DIR} --config $ --target install) set_tests_properties(usInstallTest PROPERTIES ENVIRONMENT "DESTDIR=${CppMicroServices_BINARY_DIR}/install_test" DEPENDS usInstallCleanTest) set(_examples_binary_dir "${CppMicroServices_BINARY_DIR}/examples_build") add_test(NAME usExamplesCleanTest COMMAND ${CMAKE_COMMAND} -E remove_directory "${_examples_binary_dir}") add_test(NAME usExamplesCreateDirTest COMMAND ${CMAKE_COMMAND} -E make_directory "${_examples_binary_dir}") set_tests_properties(usExamplesCreateDirTest PROPERTIES DEPENDS usExamplesCleanTest) list(APPEND _example_tests usInstallCleanTest usInstallTest usExamplesCleanTest usExamplesCreateDirTest) if(CMAKE_CONFIGURATION_TYPES) foreach(config ${CMAKE_CONFIGURATION_TYPES}) add_test(NAME usExamplesConfigureTest-${config} CONFIGURATIONS ${config} WORKING_DIRECTORY ${_examples_binary_dir} COMMAND ${CMAKE_COMMAND} -D CMAKE_C_COMPILER:STRING=${CMAKE_C_COMPILER} -D CMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER} -D BUILD_SHARED_LIBS:BOOL=${US_BUILD_SHARED_LIBS} -G ${CMAKE_GENERATOR} "-DCppMicroServices_DIR:PATH=${_install_dir}/${AUXILIARY_CMAKE_INSTALL_DIR}" "${CMAKE_CURRENT_LIST_DIR}") set_tests_properties(usExamplesConfigureTest-${config} PROPERTIES DEPENDS "usInstallTest;usExamplesCreateDirTest") add_test(NAME usExamplesBuildTest-${config} CONFIGURATIONS ${config} WORKING_DIRECTORY ${_examples_binary_dir} COMMAND ${CMAKE_COMMAND} --build . --config ${config}) set_tests_properties(usExamplesBuildTest-${config} PROPERTIES DEPENDS usExamplesConfigureTest-${config}) list(APPEND _example_tests usExamplesConfigureTest-${config} usExamplesBuildTest-${config}) endforeach() else() add_test(NAME usExamplesConfigureTest-${CMAKE_BUILD_TYPE} WORKING_DIRECTORY ${_examples_binary_dir} COMMAND ${CMAKE_COMMAND} -D CMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -D CMAKE_C_COMPILER:STRING=${CMAKE_C_COMPILER} -D CMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER} -D BUILD_SHARED_LIBS:BOOL=${US_BUILD_SHARED_LIBS} -G ${CMAKE_GENERATOR} "-DCppMicroServices_DIR:PATH=${_install_dir}/${AUXILIARY_CMAKE_INSTALL_DIR}" "${CMAKE_CURRENT_LIST_DIR}") set_tests_properties(usExamplesConfigureTest-${CMAKE_BUILD_TYPE} PROPERTIES DEPENDS "usInstallTest;usExamplesCreateDirTest") add_test(NAME usExamplesBuildTest-${CMAKE_BUILD_TYPE} WORKING_DIRECTORY ${_examples_binary_dir} COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE}) set_tests_properties(usExamplesBuildTest-${CMAKE_BUILD_TYPE} PROPERTIES DEPENDS usExamplesConfigureTest-${CMAKE_BUILD_TYPE}) list(APPEND _example_tests usExamplesConfigureTest-${CMAKE_BUILD_TYPE} usExamplesBuildTest-${CMAKE_BUILD_TYPE}) endif() # The makefile is Linux specific, so only try to build the Makefile example # if we are on a proper system if(UNIX AND NOT APPLE AND US_BUILD_SHARED_LIBS) find_program(MAKE_COMMAND NAMES make gmake) find_program(CXX_COMMAND NAMES g++) mark_as_advanced(MAKE_COMMAND CXX_COMMAND) if(MAKE_COMMAND AND CXX_COMMAND) add_test(NAME usMakefileExampleCleanTest WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/makefile COMMAND ${MAKE_COMMAND} clean) add_test(NAME usMakefileExampleTest WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/makefile COMMAND ${MAKE_COMMAND}) set_tests_properties(usMakefileExampleTest PROPERTIES DEPENDS "usMakefileExampleCleanTest;usInstallTest" ENVIRONMENT "CppMicroServices_ROOT=${CppMicroServices_BINARY_DIR}/install_test${CMAKE_INSTALL_PREFIX};US_CXX_FLAGS=${US_CXX_FLAGS}") list(APPEND _example_tests usMakefileExampleCleanTest usMakefileExampleTest) endif() endif() - if(US_TEST_LABELS) - set_tests_properties(${_example_tests} PROPERTIES LABELS "${US_TEST_LABELS}") - endif() - endif() diff --git a/Modules/CppMicroServices/core/examples/dictionaryservice/CMakeLists.txt b/Modules/CppMicroServices/core/examples/dictionaryservice/CMakeLists.txt index c904b4e9ac..25e76663ff 100644 --- a/Modules/CppMicroServices/core/examples/dictionaryservice/CMakeLists.txt +++ b/Modules/CppMicroServices/core/examples/dictionaryservice/CMakeLists.txt @@ -1,31 +1,28 @@ # The library name for the module set(_lib_name dictionaryservice) # A list of source code files set(_srcs Activator.cpp IDictionaryService.cpp ) # Generate module initialization code usFunctionGenerateModuleInit(_srcs) # Create the library add_library(Example-${_lib_name} ${_srcs}) # Add the required compile definitions set_property(TARGET Example-${_lib_name} APPEND PROPERTY COMPILE_DEFINITIONS US_MODULE_NAME=${_lib_name}) if(NOT US_BUILD_SHARED_LIBS) set_property(TARGET Example-${_lib_name} APPEND PROPERTY COMPILE_DEFINITIONS US_STATIC_MODULE) endif() # Link the CppMicroServices library target_link_libraries(Example-${_lib_name} ${CppMicroServices_LIBRARIES}) -set_target_properties(Example-${_lib_name} PROPERTIES - LABELS Examples - OUTPUT_NAME ${_lib_name} -) +set_target_properties(Example-${_lib_name} PROPERTIES OUTPUT_NAME ${_lib_name}) #CreateExample(dictionaryservice ${_srcs}) diff --git a/Modules/CppMicroServices/core/test/CMakeLists.txt b/Modules/CppMicroServices/core/test/CMakeLists.txt index 612276d86c..6a763a0fa7 100644 --- a/Modules/CppMicroServices/core/test/CMakeLists.txt +++ b/Modules/CppMicroServices/core/test/CMakeLists.txt @@ -1,102 +1,98 @@ #----------------------------------------------------------------------------- # Configure files, include dirs, etc. #----------------------------------------------------------------------------- configure_file("${CMAKE_CURRENT_SOURCE_DIR}/usTestingConfig.h.in" "${PROJECT_BINARY_DIR}/include/usTestingConfig.h") include_directories(${CMAKE_CURRENT_SOURCE_DIR}) #----------------------------------------------------------------------------- # Create test modules #----------------------------------------------------------------------------- include(usFunctionCreateTestModule) set(_us_test_module_libs "" CACHE INTERNAL "" FORCE) add_subdirectory(modules) #----------------------------------------------------------------------------- # Add unit tests #----------------------------------------------------------------------------- set(_tests usAnyTest usLDAPFilterTest usLogTest usModuleHooksTest usModuleManifestTest usModuleTest usModuleResourceTest usServiceFactoryTest usServiceHooksTest usServiceRegistryPerformanceTest usServiceRegistryTest usServiceTemplateTest usServiceTrackerTest usStaticModuleResourceTest usStaticModuleTest ) if(US_BUILD_SHARED_LIBS) list(APPEND _tests usServiceListenerTest usSharedLibraryTest ) if(US_ENABLE_AUTOLOADING_SUPPORT) list(APPEND _tests usModuleAutoLoadTest) endif() endif() set(_additional_srcs usTestDriverActivator.cpp usTestManager.cpp usTestUtilModuleListener.cpp ) set(_test_driver us${PROJECT_NAME}TestDriver) set(_test_sourcelist_extra_args ) create_test_sourcelist(_srcs ${_test_driver}.cpp ${_tests} ${_test_sourcelist_extra_args}) # Generate a custom "module init" file for the test driver executable usFunctionGenerateModuleInit(_srcs) usFunctionGetResourceSource(TARGET ${_test_driver} OUT _srcs) add_executable(${_test_driver} ${_srcs} ${_additional_srcs}) set_property(TARGET ${_test_driver} APPEND PROPERTY COMPILE_DEFINITIONS US_MODULE_NAME=main) set_property(TARGET ${_test_driver} PROPERTY US_MODULE_NAME main) set_property(TARGET ${_test_driver} PROPERTY FOLDER "${MITK_ROOT_FOLDER}/CppMicroServices/Tests") if(NOT US_BUILD_SHARED_LIBS) set_property(TARGET ${_test_driver} APPEND PROPERTY COMPILE_DEFINITIONS US_STATIC_MODULE) target_link_libraries(${_test_driver} ${_us_test_module_libs}) endif() target_link_libraries(${_test_driver} ${Core_TARGET}) if(UNIX AND NOT APPLE) target_link_libraries(${_test_driver} rt) endif() # Add resources usFunctionEmbedResources(TARGET ${_test_driver} FILES usTestResource.txt manifest.json ZIP_ARCHIVES ${Core_TARGET} ${_us_test_module_libs}) # Register tests foreach(_test ${_tests}) add_test(NAME ${_test} COMMAND ${_test_driver} ${_test}) endforeach() -if(US_TEST_LABELS) - set_tests_properties(${_tests} PROPERTIES LABELS "${US_TEST_LABELS}") -endif() - #----------------------------------------------------------------------------- # Add dependencies for shared libraries #----------------------------------------------------------------------------- if(US_BUILD_SHARED_LIBS) foreach(_test_module ${_us_test_module_libs}) add_dependencies(${_test_driver} ${_test_module}) endforeach() endif() diff --git a/Modules/DICOMTesting/test/CMakeLists.txt b/Modules/DICOMTesting/test/CMakeLists.txt index 6bb2f72b2b..5912e42626 100644 --- a/Modules/DICOMTesting/test/CMakeLists.txt +++ b/Modules/DICOMTesting/test/CMakeLists.txt @@ -1,87 +1,89 @@ - -MITK_CREATE_MODULE_TESTS(LABELS) - -include(mitkFunctionAddTestLabel) +MITK_CREATE_MODULE_TESTS() # verify minimum expectations: # files are recognized as DICOM # loading files results in a given number of images mitkAddCustomModuleTest(mitkDICOMTestingSanityTest_NoFiles mitkDICOMTestingSanityTest 0) mitkAddCustomModuleTest(mitkDICOMTestingSanityTest_CTImage mitkDICOMTestingSanityTest 1 ${MITK_DATA_DIR}/spacing-ok-ct.dcm) mitkAddCustomModuleTest(mitkDICOMTestingSanityTest_MRImage mitkDICOMTestingSanityTest 1 ${MITK_DATA_DIR}/spacing-ok-mr.dcm) mitkAddCustomModuleTest(mitkDICOMTestingSanityTest_SCImage mitkDICOMTestingSanityTest 1 ${MITK_DATA_DIR}/spacing-ok-sc.dcm) mitkAddCustomModuleTest(mitkDICOMTestingSanityTest_NoImagePositionPatient mitkDICOMTestingSanityTest 1 ${MITK_DATA_DIR}/spacing-ok-sc-no2032.dcm) # verifies that the loader can also be used to just scan for tags and provide them in mitk::Properties (parameter preLoadedVolume) mitkAddCustomModuleTest(mitkDICOMPreloadedVolumeTest_Slice mitkDICOMPreloadedVolumeTest ${MITK_DATA_DIR}/spacing-ok-ct.dcm) set(VERIFY_DUMP_CMD ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/VerifyDICOMMitkImageDump) set(CT_ABDOMEN_DIR ${MITK_DATA_DIR}/TinyCTAbdomen_DICOMReader) set(MR_HEART_DIR ${MITK_DATA_DIR}/3D+t-Heart) set(CT_TILT_HEAD_DIR ${MITK_DATA_DIR}/TiltHead) set(CT_TILT_DIR ${MITK_DATA_DIR}/TiltedData) set(SOP_CLASSES_DIR ${MITK_DATA_DIR}/DICOMReader) # these variables could be passed as parameters to a generic test creation function set(TESTS_DIR Tests) set(INPUT_LISTNAME input) set(EXPECTED_DUMP expected.dump) function(AddDicomTestsFromDataRepository CURRENT_DATASET_DIR TESTS_DIR INPUT_LISTNAME EXPECTED_DUMP) # find all test input lists file(GLOB_RECURSE allInputs ${CURRENT_DATASET_DIR}/${TESTS_DIR}/*/${INPUT_LISTNAME}) function(expectFileExists filename) if(NOT EXISTS ${filename}) message(SEND_ERROR "Test case expected file ${filename} which does not exist! Please fix your CMake code or file layout.") endif(NOT EXISTS ${filename}) endfunction(expectFileExists) foreach(input ${allInputs}) # extract only the name of the directory of this very test case string(REGEX REPLACE ".*${TESTS_DIR}/([^/]+)/.*" "\\1" input ${input}) set(inputfilelist "${CURRENT_DATASET_DIR}/${TESTS_DIR}/${input}/${INPUT_LISTNAME}") set(expecteddump "${CURRENT_DATASET_DIR}/${TESTS_DIR}/${input}/${EXPECTED_DUMP}") - set(testname "DICOM_Load_${input}") + set(test_name "DICOM_Load_${input}") #message(STATUS "DICOM loading test case '${input}'") expectFileExists(${inputfilelist}) expectFileExists(${expecteddump}) # TODO provide error messages if input not valid set(dicomFiles) # clear list # read list of file names from file "input" file(STRINGS ${inputfilelist} rawDicomFiles) foreach(raw ${rawDicomFiles}) # prepend each file with an abosolute path set(fileWithFullPath ${CURRENT_DATASET_DIR}/${raw}) list(APPEND dicomFiles ${fileWithFullPath}) endforeach(raw ${rawDicomFiles}) #message(STATUS " Load ${dicomFiles}") - add_test(${testname} - ${VERIFY_DUMP_CMD} ${expecteddump} ${dicomFiles}) - mitkFunctionAddTestLabel(${testname}) + add_test(${test_name} ${VERIFY_DUMP_CMD} ${expecteddump} ${dicomFiles}) + mitkFunctionGetLibrarySearchPaths(MITK_RUNTIME_PATH_RELEASE release RELEASE) + mitkFunctionGetLibrarySearchPaths(MITK_RUNTIME_PATH_DEBUG debug DEBUG) + set(test_env_path ${MITK_RUNTIME_PATH_RELEASE} ${MITK_RUNTIME_PATH_DEBUG} $ENV{PATH}) + list(REMOVE_DUPLICATES test_env_path) + string (REGEX REPLACE "\;" "\\\;" test_env_path "${test_env_path}") + set_property(TEST ${test_name} PROPERTY ENVIRONMENT "PATH=${test_env_path}" APPEND) + set_property(TEST ${test_name} PROPERTY SKIP_RETURN_CODE 77) endforeach(input allInputs) endfunction(AddDicomTestsFromDataRepository CURRENT_DATASET_DIR TESTS_DIR INPUT_LISTNAME EXPECTED_DUMP) AddDicomTestsFromDataRepository(${CT_ABDOMEN_DIR} ${TESTS_DIR} ${INPUT_LISTNAME} ${EXPECTED_DUMP}) AddDicomTestsFromDataRepository(${CT_TILT_HEAD_DIR} ${TESTS_DIR} ${INPUT_LISTNAME} ${EXPECTED_DUMP}) AddDicomTestsFromDataRepository(${CT_TILT_DIR} ${TESTS_DIR} ${INPUT_LISTNAME} ${EXPECTED_DUMP}) AddDicomTestsFromDataRepository(${MR_HEART_DIR} ${TESTS_DIR} ${INPUT_LISTNAME} ${EXPECTED_DUMP}) AddDicomTestsFromDataRepository(${SOP_CLASSES_DIR} ${TESTS_DIR} ${INPUT_LISTNAME} ${EXPECTED_DUMP}) # use one more realistic series for testing property lists file(GLOB_RECURSE abdomenImages ${CT_ABDOMEN_DIR}/14?) # this is just one small volume mitkAddCustomModuleTest(mitkDICOMPreloadedVolumeTest_Abdomen mitkDICOMPreloadedVolumeTest ${abdomenImages}) diff --git a/Modules/IGT/CMakeLists.txt b/Modules/IGT/CMakeLists.txt index 79cb9fd186..760efba59f 100644 --- a/Modules/IGT/CMakeLists.txt +++ b/Modules/IGT/CMakeLists.txt @@ -1,64 +1,63 @@ include(MITKIGTHardware.cmake) if(MITK_USE_MICRON_TRACKER) set(ADDITIONAL_INCLUDE_DIRS ${ADDITIONAL_INCLUDE_DIRS} ${MITK_MICRON_TRACKER_INCLUDE_DIR}) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_MICRON_TRACKER_LIB}) endif(MITK_USE_MICRON_TRACKER) if(MITK_USE_OPTITRACK_TRACKER) set(ADDITIONAL_INCLUDE_DIRS ${ADDITIONAL_INCLUDE_DIRS} ${MITK_OPTITRACK_TRACKER_INCLUDE_DIR}) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_OPTITRACK_TRACKER_LIB}) add_definitions( -DMITK_USE_OPTITRACK_TRACKER ) endif(MITK_USE_OPTITRACK_TRACKER) if(MITK_USE_MICROBIRD_TRACKER) set(ADDITIONAL_INCLUDE_DIRS ${ADDITIONAL_INCLUDE_DIRS} ${MITK_USE_MICROBIRD_TRACKER_INCLUDE_DIR}) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_USE_MICROBIRD_TRACKER_LIB}) endif(MITK_USE_MICROBIRD_TRACKER) if(MITK_USE_POLHEMUS_TRACKER) set(ADDITIONAL_INCLUDE_DIRS ${ADDITIONAL_INCLUDE_DIRS} ${MITK_POLHEMUS_TRACKER_INCLUDE_DIR}) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_POLHEMUS_TRACKER_LIB}) endif(MITK_USE_POLHEMUS_TRACKER) MITK_CREATE_MODULE( - SUBPROJECTS MITK-IGT INCLUDE_DIRS PUBLIC Algorithms Common DataManagement ExceptionHandling IO Rendering TrackingDevices TestingHelper PRIVATE ${ADDITIONAL_INCLUDE_DIRS} DEPENDS PUBLIC MitkImageStatistics MitkSceneSerialization MitkIGTBase MitkOpenIGTLink PACKAGE_DEPENDS ITK|ITKRegistrationCommon tinyxml OpenIGTLink ADDITIONAL_LIBS "${ADDITIONAL_LIBS}" ) if(MitkIGT_IS_ENABLED) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/ClaronMicron.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/IntuitiveDaVinci.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAurora.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAurora_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAuroraCompactFG_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAuroraPlanarFG_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAuroraTabletopFG_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAuroraTabletopFG_Prototype_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIPolarisOldModel.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIPolarisSpectra.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIPolarisSpectraExtendedPyramid.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIPolarisVicra.stl ) endif() if(NOT MODULE_IS_ENABLED) message(STATUS "IGTTutorialStep1 won't be built. Missing: ${_RESULT}") else() ## create IGT config configure_file(mitkIGTConfig.h.in ${PROJECT_BINARY_DIR}/mitkIGTConfig.h @ONLY) # add test programm for serial communication classADD_EXECUTABLE(SerialCommunicationTest IGTTrackingDevices/mitkSerialCommunicationTest.cpp)target_link_libraries(SerialCommunicationTest mitkIGT Mitk tinyxml PocoXML) add_subdirectory(autoload/DeviceRegistry) add_subdirectory(Tutorial) add_subdirectory(Testing) endif() diff --git a/Modules/IGTUI/CMakeLists.txt b/Modules/IGTUI/CMakeLists.txt index d37c9b60a3..dc3353f397 100644 --- a/Modules/IGTUI/CMakeLists.txt +++ b/Modules/IGTUI/CMakeLists.txt @@ -1,12 +1,11 @@ MITK_CREATE_MODULE( - SUBPROJECTS MITK-IGT INCLUDE_DIRS Qmitk DEPENDS MitkIGT MitkQtWidgetsExt MitkPersistence ) add_subdirectory(autoload/ConfigurationWidgetRegistry) ## create IGTUI config configure_file(mitkIGTUIConfig.h.in ${PROJECT_BINARY_DIR}/mitkIGTUIConfig.h @ONLY) diff --git a/Modules/IpPicSupportIO/Testing/CMakeLists.txt b/Modules/IpPicSupportIO/Testing/CMakeLists.txt index 930c090bf0..9e874e1ea1 100644 --- a/Modules/IpPicSupportIO/Testing/CMakeLists.txt +++ b/Modules/IpPicSupportIO/Testing/CMakeLists.txt @@ -1,4 +1,4 @@ -MITK_CREATE_MODULE_TESTS(LABELS MITK-Modules) +MITK_CREATE_MODULE_TESTS() mitkAddCustomModuleTest(mitkPicFileReaderTest_emptyFile mitkPicFileReaderTest ${CMAKE_CURRENT_SOURCE_DIR}/Data/emptyFile.pic) mitkAddCustomModuleTest(mitkPicFileReaderTest_emptyGzipFile mitkPicFileReaderTest ${CMAKE_CURRENT_SOURCE_DIR}/Data/emptyFile.pic.gz) diff --git a/Modules/MatchPointRegistration/CMakeLists.txt b/Modules/MatchPointRegistration/CMakeLists.txt index 97bb55792b..acbcd26ff3 100644 --- a/Modules/MatchPointRegistration/CMakeLists.txt +++ b/Modules/MatchPointRegistration/CMakeLists.txt @@ -1,25 +1,28 @@ MITK_CREATE_MODULE( - INCLUDE_DIRS PUBLIC Rendering Helper algorithms + INCLUDE_DIRS + PUBLIC algorithms + PRIVATE src/Helper src/Rendering DEPENDS MitkCore MitkSceneSerializationBase PACKAGE_DEPENDS PUBLIC MatchPoint ) if(TARGET ${MODULE_TARGET}) set(ALG_PROFILE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/algorithms) include(${MatchPoint_SOURCE_DIR}/CMake/mapFunctionCreateAlgorithmProfile.cmake) file(GLOB ALG_PROFILE_FILES LIST_DIRECTORIES false RELATIVE ${ALG_PROFILE_DIR} "${ALG_PROFILE_DIR}/*.profile") foreach(profile_file ${ALG_PROFILE_FILES}) get_filename_component(profile_name ${profile_file} NAME_WE) MESSAGE(STATUS "... generate MDRA profile ${profile_name} (from ${profile_file})...") CREATE_ALGORITHM_PROFILE(${profile_name} ${ALG_PROFILE_DIR}/${profile_file}) endforeach(profile_file) ADD_SUBDIRECTORY(autoload/IO) ADD_SUBDIRECTORY(deployment) if(BUILD_TESTING) ADD_SUBDIRECTORY(Testing) endif(BUILD_TESTING) + ADD_SUBDIRECTORY(cmdapps) endif() diff --git a/Modules/MatchPointRegistration/Testing/files.cmake b/Modules/MatchPointRegistration/Testing/files.cmake index 5efdc15458..b1268f0481 100644 --- a/Modules/MatchPointRegistration/Testing/files.cmake +++ b/Modules/MatchPointRegistration/Testing/files.cmake @@ -1,3 +1,4 @@ SET(MODULE_TESTS mitkTimeFramesRegistrationHelperTest.cpp + itkStitchImageFilterTest.cpp ) \ No newline at end of file diff --git a/Modules/MatchPointRegistration/Testing/itkStitchImageFilterTest.cpp b/Modules/MatchPointRegistration/Testing/itkStitchImageFilterTest.cpp new file mode 100644 index 0000000000..10c37646e5 --- /dev/null +++ b/Modules/MatchPointRegistration/Testing/itkStitchImageFilterTest.cpp @@ -0,0 +1,160 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#include "mitkTestingMacros.h" +#include "mitkTestFixture.h" +#include "mitkTestDynamicImageGenerator.h" + +#include "itkStitchImageFilter.h" +#include "itkTranslationTransform.h" +#include "itkNearestNeighborInterpolateImageFunction.h" + +class itkStitchImageFilterTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(itkStitchImageFilterTestSuite); + // Test the append method + MITK_TEST(StitchWithNoTransformAndNoInterp); + MITK_TEST(StitchWithNoInterp); + MITK_TEST(Stitch); + CPPUNIT_TEST_SUITE_END(); + + using InputImageType = mitk::TestImageType; + using OutputImageType = itk::Image; +private: + using FilterType = itk::StitchImageFilter; + FilterType::Pointer m_Filter; + + InputImageType::Pointer m_Input1; + InputImageType::Pointer m_Input2; + InputImageType::Pointer m_Input3; + +public: + void setUp() override + { + InputImageType::PointType origin; + origin.Fill(0.); + InputImageType::SpacingType spacing; + spacing.Fill(1.); + spacing[1] = 5.; + + m_Filter = FilterType::New(); + m_Input1 = mitk::GenerateTestImage(1); + m_Input1->SetSpacing(spacing); + + m_Input2 = mitk::GenerateTestImage(10); + origin[1] = 10.; + m_Input2->SetOrigin(origin); + m_Input2->SetSpacing(spacing); + + m_Input3 = mitk::GenerateTestImage(100); + origin[1] = 20.; + m_Input3->SetOrigin(origin); + m_Input3->SetSpacing(spacing); + + FilterType::SizeType size = { 3, 9 }; + m_Filter->SetDefaultPixelValue(1000); + m_Filter->SetSize(size); + m_Filter->SetOutputSpacing(spacing); + } + + void tearDown() override + { + } + + bool CheckPixels(const OutputImageType* image, const std::vector& pixels) + { + bool result = true; + + itk::ImageRegionConstIteratorWithIndex iter(image, image->GetLargestPossibleRegion()); + auto refIter = pixels.begin(); + iter.GoToBegin(); + while (!iter.IsAtEnd()) + { + if (refIter == pixels.end()) + { + std::cerr << "Error image to check has a different pixel count then the reference pixel value vector."<SetInput(0, m_Input1); + m_Filter->SetInput(1, m_Input2); + m_Filter->SetInput(2, m_Input3); + + m_Filter->Update(); + auto output = m_Filter->GetOutput(); + + CPPUNIT_ASSERT(CheckPixels(output, {1, 2, 3, 4, 5, 6, 8.5, 14, 19.5, 40, 50, 60, 85, 140, 195, 400, 500, 600, 700, 800, 900, 1000, 1000, 1000, 1000, 1000, 1000})); + } + + void StitchWithNoInterp() + { + m_Filter->SetInput(0, m_Input1); + + using TranslationType = itk::TranslationTransform; + TranslationType::OutputVectorType offset; + offset[0] = 0.; + offset[1] = -5.; + auto translation1 = TranslationType::New(); + translation1->SetOffset(offset); + m_Filter->SetInput(1, m_Input2, translation1); + + offset[1] = -10.; + auto translation2 = TranslationType::New(); + translation2->SetOffset(offset); + m_Filter->SetInput(2, m_Input3, translation2); + + m_Filter->Update(); + auto output = m_Filter->GetOutput(); + + CPPUNIT_ASSERT(CheckPixels(output, { 1,2,3,4,5,6,7,8,9,10,20,30,40,50,60,70,80,90,100,200,300,400,500,600,700,800,900})); + } + + void Stitch() + { + using TranslationType = itk::TranslationTransform; + TranslationType::OutputVectorType offset; + offset[0] = 0; + offset[1] = -7.5; + auto translation1 = TranslationType::New(); + translation1->SetOffset(offset); + + offset[1] = -12.5; + auto translation2 = TranslationType::New(); + translation2->SetOffset(offset); + + m_Filter->SetInput(0, m_Input1); + m_Filter->SetInput(1, m_Input2, translation1, itk::NearestNeighborInterpolateImageFunction::New()); + m_Filter->SetInput(2, m_Input3, translation2); + + m_Filter->Update(); + auto output = m_Filter->GetOutput(); + + CPPUNIT_ASSERT(CheckPixels(output, { 1,2,3,4,5,6,7,8,9,10,20,30,40,50,60,70,80,90,100,200,300,250,350,450,550,650,750 })); + } + +}; + +MITK_TEST_SUITE_REGISTRATION(itkStitchImageFilter) diff --git a/Modules/MatchPointRegistration/cmdapps/CMakeLists.txt b/Modules/MatchPointRegistration/cmdapps/CMakeLists.txt new file mode 100644 index 0000000000..f02ab70bc2 --- /dev/null +++ b/Modules/MatchPointRegistration/cmdapps/CMakeLists.txt @@ -0,0 +1,33 @@ +option(BUILD_MatchPointCmdApps "Build commandline tools for the MatchPoint module" OFF) + +if(BUILD_MatchPointCmdApps OR MITK_BUILD_ALL_APPS) + + # needed include directories + include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ) + # list of CmdApps + # if an app requires additional dependencies + # they are added after a "^^" and separated by "_" + set( cmdapps + StitchImagesMiniApp^^ + ) + + foreach(cmdapp ${cmdapps}) + # extract cmd name and dependencies + string(REPLACE "^^" "\\;" cmdapp_info ${cmdapp}) + set(cmdapp_info_list ${cmdapp_info}) + list(GET cmdapp_info_list 0 appname) + list(GET cmdapp_info_list 1 raw_dependencies) + string(REPLACE "_" "\\;" dependencies "${raw_dependencies}") + set(dependencies_list ${dependencies}) + + mitkFunctionCreateCommandLineApp( + NAME ${appname} + DEPENDS MitkCore MitkMatchPointRegistration ${dependencies_list} + PACKAGE_DEPENDS ITK + ) + endforeach() + +endif(BUILD_MatchPointCmdApps OR MITK_BUILD_ALL_APPS) diff --git a/Modules/MatchPointRegistration/cmdapps/StitchImagesMiniApp.cpp b/Modules/MatchPointRegistration/cmdapps/StitchImagesMiniApp.cpp new file mode 100644 index 0000000000..ef8fc82bd2 --- /dev/null +++ b/Modules/MatchPointRegistration/cmdapps/StitchImagesMiniApp.cpp @@ -0,0 +1,226 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +// std includes +#include +#include + +// itk includes +#include "itksys/SystemTools.hxx" + +// CTK includes +#include "mitkCommandLineParser.h" + +// MITK includes +#include +#include +#include +#include +#include + +mitkCommandLineParser::StringContainerType inFilenames; +mitkCommandLineParser::StringContainerType regFilenames; +std::string outFileName; +std::string refGeometryFileName; + +std::vector images; +std::vector registrations; +mitk::BaseGeometry::Pointer refGeometry; +mitk::ImageMappingInterpolator::Type interpolatorType = mitk::ImageMappingInterpolator::Linear; +double paddingValue = 0; +itk::StitchStrategy stitchStratgy = itk::StitchStrategy::Mean; + +void setupParser(mitkCommandLineParser& parser) +{ + // set general information about your MiniApp + parser.setCategory("Mapping Tools"); + parser.setTitle("Stitch 3D Images"); + parser.setDescription("MiniApp that allows to map and stitch 3D images into a given output geometry."); + parser.setContributor("DKFZ MIC"); + //! [create parser] + + //! [add arguments] + // how should arguments be prefixed + parser.setArgumentPrefix("--", "-"); + // add each argument, unless specified otherwise each argument is optional + // see mitkCommandLineParser::addArgument for more information + parser.beginGroup("Required I/O parameters"); + parser.addArgument( + "inputs", "i", mitkCommandLineParser::StringList, "Input files", "Pathes to the input images that should be mapped and stitched", us::Any(), false, false, false, mitkCommandLineParser::Input); + parser.addArgument("output", + "o", + mitkCommandLineParser::File, + "Output file path", + "Path to the fused 3D+t image.", + us::Any(), + false, false, false, mitkCommandLineParser::Output); + parser.endGroup(); + + parser.beginGroup("Optional parameters"); + parser.addArgument("template", + "t", + mitkCommandLineParser::File, + "Output template image.", + "File path to an image that serves as template for the output geometry.", + us::Any(), + false, false, false, mitkCommandLineParser::Input); + parser.addArgument( + "registrations", "r", mitkCommandLineParser::StringList, "Registration files", "Pathes to the registrations that should be used to map the input images. If this parameter is not set, identity transforms are assumed. If this parameter is set, it must have the same number of entries then the parameter inputs. If you want to use and identity transform for a specific input, specify an empty string. The application assumes that inputs and registrations have the same order, so the n-th input should use thr n-th registration.", us::Any(), true, false, false, mitkCommandLineParser::Input); + parser.addArgument("interpolator", "n", mitkCommandLineParser::Int, "Interpolator type", "Interpolator used for mapping the images. Default: 2; allowed values: 1: Nearest Neighbour, 2: Linear, 3: BSpline 3, 4: WSinc Hamming, 5: WSinc Welch", us::Any(2), true); + parser.addArgument("strategy", "s", mitkCommandLineParser::Int, "Stitch strategy", "Strategy used for stitching the images. 0: Mean -> computes the mean value of all input images that cover an output pixel (default strategy). 1: BorderDistance -> Uses the input pixel that has the largest minimal distance to its image borders", us::Any(2), true); + parser.addArgument("padding", "p", mitkCommandLineParser::Float, "Padding value", "Value used for output voxels that are not covered by any input image.", us::Any(0.), true); + parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text"); + parser.endGroup(); + //! [add arguments] +} + +bool configureApplicationSettings(std::map parsedArgs) +{ + try + { + if (parsedArgs.size() == 0) + return false; + + inFilenames = us::any_cast(parsedArgs["inputs"]); + outFileName = us::any_cast(parsedArgs["output"]); + + if (parsedArgs.count("template")) + { + refGeometryFileName = us::any_cast(parsedArgs["template"]); + } + + if (parsedArgs.count("registrations")) + { + regFilenames = us::any_cast(parsedArgs["registrations"]); + } + else + { + regFilenames.resize(inFilenames.size()); + std::fill(regFilenames.begin(), regFilenames.end(), ""); + } + + if (parsedArgs.count("interpolator")) + { + auto interpolator = us::any_cast(parsedArgs["interpolator"]); + interpolatorType = static_cast(interpolator); + } + + if (parsedArgs.count("padding")) + { + paddingValue = us::any_cast(parsedArgs["padding"]); + } + + if (parsedArgs.count("strategy")) + { + auto temp = us::any_cast(parsedArgs["strategy"]); + stitchStratgy = static_cast(temp); + } + } + catch (...) + { + return false; + } + + return true; +} + +int main(int argc, char* argv[]) +{ + mitkCommandLineParser parser; + setupParser(parser); + + mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (autoselect)" }, { "" }); + + const std::map& parsedArgs = parser.parseArguments(argc, argv); + if (!configureApplicationSettings(parsedArgs)) + { + MITK_ERROR << "Command line arguments are invalid. To see the correct usage please call with -h or --help to show the help information."; + return EXIT_FAILURE; + }; + + // Show a help message + if (parsedArgs.count("help") || parsedArgs.count("h")) + { + std::cout << parser.helpText(); + return EXIT_SUCCESS; + } + + if(regFilenames.size() != inFilenames.size()) + { + MITK_ERROR << "Cannot stitch inputs. The number of specified registrations does not match the number of inputs."; + return EXIT_FAILURE; + } + + //! [do processing] + try + { + std::cout << "Load images:" << std::endl; + + unsigned int index = 0; + for (auto path : inFilenames) + { + std::cout << "#"<(path, &readerFilterFunctor); + images.push_back(image.GetPointer()); + if (regFilenames[index].empty()) + { + std::cout << " associated registration: identity" << std::endl; + registrations.push_back(mitk::GenerateIdentityRegistration3D().GetPointer()); + } + else + { + std::cout << " associated registration: " << regFilenames[index] << std::endl; + auto reg = mitk::IOUtil::Load(regFilenames[index]); + registrations.push_back(reg.GetPointer()); + } + ++index; + } + std::cout << "Reference image: " << refGeometryFileName << std::endl << std::endl; + auto refImage = mitk::IOUtil::Load(refGeometryFileName, &readerFilterFunctor); + if (refImage.IsNotNull()) + { + refGeometry = refImage->GetGeometry(); + } + std::cout << "Padding value: " << paddingValue << std::endl; + std::cout << "Stitch strategy: "; + if (itk::StitchStrategy::Mean == stitchStratgy) + { + std::cout << "Mean " << std::endl; + } + else + { + std::cout << "BorderDistance" << std::endl; + } + + std::cout << "Stitch the images ..." << std::endl; + + auto output = mitk::StitchImages(images, registrations, refGeometry,paddingValue,stitchStratgy,interpolatorType); + + std::cout << "Save output image: " << outFileName << std::endl; + + mitk::IOUtil::Save(output, outFileName); + + std::cout << "Processing finished." << std::endl; + + return EXIT_SUCCESS; + } + catch (const std::exception& e) + { + MITK_ERROR << e.what(); + return EXIT_FAILURE; + } + catch (...) + { + MITK_ERROR << "Unexpected error encountered."; + return EXIT_FAILURE; + } +} diff --git a/Modules/MatchPointRegistration/files.cmake b/Modules/MatchPointRegistration/files.cmake index 1b9c8ff7e1..0bf01d264c 100644 --- a/Modules/MatchPointRegistration/files.cmake +++ b/Modules/MatchPointRegistration/files.cmake @@ -1,65 +1,32 @@ +file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h") +file(GLOB_RECURSE TPP_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*.tpp") + set(CPP_FILES mitkMAPRegistrationWrapper.cpp mitkMAPRegistrationWrapperObjectFactory.cpp mitkRegEvaluationObjectFactory.cpp mitkRegEvaluationObject.cpp Helper/mitkUIDHelper.cpp Helper/mitkMAPAlgorithmHelper.cpp Helper/mitkMaskedAlgorithmHelper.cpp Helper/mitkRegistrationHelper.cpp Helper/mitkImageMappingHelper.cpp + Helper/mitkImageStitchingHelper.cpp Helper/mitkPointSetMappingHelper.cpp Helper/mitkResultNodeGenerationHelper.cpp Helper/mitkTimeFramesRegistrationHelper.cpp Rendering/mitkRegistrationWrapperMapper2D.cpp Rendering/mitkRegistrationWrapperMapper3D.cpp Rendering/mitkRegistrationWrapperMapperBase.cpp Rendering/mitkRegEvaluationMapper2D.cpp Rendering/mitkRegVisStyleProperty.cpp Rendering/mitkRegVisDirectionProperty.cpp Rendering/mitkRegVisColorStyleProperty.cpp Rendering/mitkRegVisPropertyTags.cpp Rendering/mitkRegVisHelper.cpp Rendering/mitkRegEvalStyleProperty.cpp Rendering/mitkRegEvalWipeStyleProperty.cpp ) -set(H_FILES - mitkMatchPointPropertyTags.h - mitkMAPRegistrationWrapper.h - mitkMAPRegistrationWrapperObjectFactory.h - mitkRegEvaluationObjectFactory.h - mitkRegEvaluationObject.h - algorithms/mitkMultiModalAffineDefaultRegistrationAlgorithm.h - algorithms/mitkMultiModalRigidDefaultRegistrationAlgorithm.h - algorithms/mitkMultiModalTransDefaultRegistrationAlgorithm.h - algorithms/mitkFastSymmetricForcesDemonsMultiResDefaultRegistrationAlgorithm.h - algorithms/mitkLevelSetMotionMultiResDefaultRegistrationAlgorithm.h - algorithms/mitkRigidClosedFormPointsDefaultRegistrationAlgorithm.h - algorithms/mitkRigidICPDefaultRegistrationAlgorithm.h - Helper/mitkUIDHelper.h - Helper/mitkMAPAlgorithmHelper.h - Helper/mitkMaskedAlgorithmHelper.h - Helper/mitkRegistrationHelper.h - Helper/mitkImageMappingHelper.h - Helper/mitkPointSetMappingHelper.h - Helper/mitkResultNodeGenerationHelper.h - Helper/mitkTimeFramesRegistrationHelper.h - Rendering/mitkRegistrationWrapperMapper2D.h - Rendering/mitkRegistrationWrapperMapper3D.h - Rendering/mitkRegistrationWrapperMapperBase.h - Rendering/mitkRegVisStyleProperty.h - Rendering/mitkRegVisDirectionProperty.h - Rendering/mitkRegVisColorStyleProperty.h - Rendering/mitkRegVisPropertyTags.h - Rendering/mitkRegVisHelper.h - Rendering/mitkRegEvaluationMapper2D.h - Rendering/mitkRegEvalStyleProperty.h - Rendering/mitkRegEvalWipeStyleProperty.h -) - -set(TPP_FILES -) - set(MOC_H_FILES ) diff --git a/Modules/MatchPointRegistration/Helper/QmitkAlgorithmListModel.h b/Modules/MatchPointRegistration/include/QmitkAlgorithmListModel.h similarity index 100% rename from Modules/MatchPointRegistration/Helper/QmitkAlgorithmListModel.h rename to Modules/MatchPointRegistration/include/QmitkAlgorithmListModel.h diff --git a/Modules/MatchPointRegistration/Helper/QmitkMapPropertyDelegate.h b/Modules/MatchPointRegistration/include/QmitkMapPropertyDelegate.h similarity index 100% rename from Modules/MatchPointRegistration/Helper/QmitkMapPropertyDelegate.h rename to Modules/MatchPointRegistration/include/QmitkMapPropertyDelegate.h diff --git a/Modules/MatchPointRegistration/include/itkStitchImageFilter.h b/Modules/MatchPointRegistration/include/itkStitchImageFilter.h new file mode 100644 index 0000000000..5d5edce5d0 --- /dev/null +++ b/Modules/MatchPointRegistration/include/itkStitchImageFilter.h @@ -0,0 +1,330 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#ifndef itkStitchImageFilter_h +#define itkStitchImageFilter_h + +#include "itkFixedArray.h" +#include "itkTransform.h" +#include "itkImageRegionIterator.h" +#include "itkImageToImageFilter.h" +#include "itkLinearInterpolateImageFunction.h" +#include "itkSize.h" +#include "itkDefaultConvertPixelTraits.h" +#include "itkDataObjectDecorator.h" + + +namespace itk +{ + enum class StitchStrategy + { + Mean = 0, //use the mean value of all inputs that can provide a pixel vaule + BorderDistance = 1 //use the value that is largest minimal distance to its image borders (use e.g. if vaules tend to be not reliable at borders) + }; + + std::ostream& operator<< (std::ostream& os, const itk::StitchStrategy& strategy) + { + if (itk::StitchStrategy::Mean == strategy) + os << "Mean"; + else if (itk::StitchStrategy::BorderDistance == strategy) + os << "BorderDistance"; + else + os << "unkown"; + + return os; + }; + + /** \class StitchImageFilter + * \brief ITK filter that resamples/stitches multiple images into a given reference geometry. + * + * StitchImageFilter is similar to itk's ResampleImageFilter, but in difference to the last + * mentioned StitchImageFilter is able to resample multiple input images at once (with a transform + * for each input image). If multiple input images cover the output region the behavior depends on + * the StitchStragy: + * - Mean: a weighted sum of all voxels mapped input pixel values will be calculated. + * - BorderDistance: the voxels will be choosen that have the largest minimal distance to its own image borders. + * + * All other behaviors are similar to itk::ResampleImageFilter. See the filter's description for + * more details. + */ +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType = double, + typename TTransformPrecisionType = TInterpolatorPrecisionType> +class StitchImageFilter : + public ImageToImageFilter< TInputImage, TOutputImage > +{ +public: + /** Standard class typedefs. */ + typedef StitchImageFilter Self; + typedef ImageToImageFilter< TInputImage, TOutputImage > Superclass; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + + typedef TInputImage InputImageType; + typedef TOutputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename InputImageType::RegionType InputImageRegionType; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(StitchImageFilter, ImageToImageFilter); + + /** Number of dimensions. */ + itkStaticConstMacro(ImageDimension, unsigned int, + TOutputImage::ImageDimension); + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + + /** base type for images of the current ImageDimension */ + typedef ImageBase< itkGetStaticConstMacro(ImageDimension) > ImageBaseType; + + /** + * Transform typedef. + */ + typedef Transform< TTransformPrecisionType, + itkGetStaticConstMacro(ImageDimension), + itkGetStaticConstMacro(ImageDimension) > TransformType; + typedef typename TransformType::ConstPointer TransformPointerType; + typedef DataObjectDecorator DecoratedTransformType; + typedef typename DecoratedTransformType::Pointer DecoratedTransformPointer; + + + /** Interpolator typedef. */ + typedef InterpolateImageFunction< InputImageType, + TInterpolatorPrecisionType > InterpolatorType; + typedef typename InterpolatorType::Pointer InterpolatorPointerType; + + typedef typename InterpolatorType::OutputType InterpolatorOutputType; + + typedef DefaultConvertPixelTraits< InterpolatorOutputType > InterpolatorConvertType; + + typedef typename InterpolatorConvertType::ComponentType ComponentType; + + typedef LinearInterpolateImageFunction< InputImageType, + TInterpolatorPrecisionType > LinearInterpolatorType; + typedef typename LinearInterpolatorType::Pointer + LinearInterpolatorPointerType; + + /** Image size typedef. */ + typedef Size< itkGetStaticConstMacro(ImageDimension) > SizeType; + + /** Image index typedef. */ + typedef typename TOutputImage::IndexType IndexType; + + /** Image point typedef. */ + typedef typename InterpolatorType::PointType PointType; + //typedef typename TOutputImage::PointType PointType; + + /** Image pixel value typedef. */ + typedef typename TOutputImage::PixelType PixelType; + typedef typename TInputImage::PixelType InputPixelType; + + typedef DefaultConvertPixelTraits PixelConvertType; + + typedef typename PixelConvertType::ComponentType PixelComponentType; + + /** Input pixel continuous index typdef */ + typedef ContinuousIndex< TTransformPrecisionType, ImageDimension > + ContinuousInputIndexType; + + /** Typedef to describe the output image region type. */ + typedef typename TOutputImage::RegionType OutputImageRegionType; + + /** Image spacing,origin and direction typedef */ + typedef typename TOutputImage::SpacingType SpacingType; + typedef typename TOutputImage::PointType OriginPointType; + typedef typename TOutputImage::DirectionType DirectionType; + + using Superclass::GetInput; + + /** Typedef the reference image type to be the ImageBase of the OutputImageType */ + typedef ImageBase ReferenceImageBaseType; + + using Superclass::SetInput; + void SetInput(const InputImageType* image) override; + void SetInput(unsigned int index, const InputImageType* image) override; + /** Convinience methods that allows setting of input image and its transform in + one call.*/ + virtual void SetInput(unsigned int index, const InputImageType* image, const TransformType* transform); + virtual void SetInput(unsigned int index, const InputImageType* image, const TransformType* transform, InterpolatorType* interpolator); + + const TransformType* GetTransform(unsigned int index) const; + + const InterpolatorType* GetInterpolator(unsigned int index) const; + + /** Get/Set the size of the output image. */ + itkSetMacro(Size, SizeType); + itkGetConstReferenceMacro(Size, SizeType); + + /** Get/Set the pixel value when a transformed pixel is outside of the + * image. The default default pixel value is 0. */ + itkSetMacro(DefaultPixelValue, PixelType); + itkGetConstReferenceMacro(DefaultPixelValue, PixelType); + + /** Set the output image spacing. */ + itkSetMacro(OutputSpacing, SpacingType); + virtual void SetOutputSpacing(const double *values); + + /** Get the output image spacing. */ + itkGetConstReferenceMacro(OutputSpacing, SpacingType); + + /** Set the output image origin. */ + itkSetMacro(OutputOrigin, OriginPointType); + virtual void SetOutputOrigin(const double *values); + + /** Get the output image origin. */ + itkGetConstReferenceMacro(OutputOrigin, OriginPointType); + + /** Set the output direciton cosine matrix. */ + itkSetMacro(OutputDirection, DirectionType); + itkGetConstReferenceMacro(OutputDirection, DirectionType); + + /** Helper method to set the output parameters based on this image. */ + void SetOutputParametersFromImage(const ImageBaseType *image); + + /** Set the start index of the output largest possible region. + * The default is an index of all zeros. */ + itkSetMacro(OutputStartIndex, IndexType); + + /** Get the start index of the output largest possible region. */ + itkGetConstReferenceMacro(OutputStartIndex, IndexType); + + /** Set a reference image to use to define the output information. + * By default, output information is specificed through the + * SetOutputSpacing, Origin, and Direction methods. Alternatively, + * this method can be used to specify an image from which to + * copy the information. UseReferenceImageOn must be set to utilize the + * reference image. */ + itkSetInputMacro(ReferenceImage, ReferenceImageBaseType); + + /** Get the reference image that is defining the output information. */ + itkGetInputMacro(ReferenceImage, ReferenceImageBaseType); + + /** Turn on/off whether a specified reference image should be used to define + * the output information. */ + itkSetMacro(UseReferenceImage, bool); + itkBooleanMacro(UseReferenceImage); + itkGetConstMacro(UseReferenceImage, bool); + + itkSetMacro(StitchStrategy, StitchStrategy); + itkGetConstMacro(StitchStrategy, StitchStrategy); + + /** StitchImageFilter produces an image which is a different size + * than its input. As such, it needs to provide an implementation + * for GenerateOutputInformation() in order to inform the pipeline + * execution model. The original documentation of this method is + * below. \sa ProcessObject::GenerateOutputInformaton() */ + virtual void GenerateOutputInformation() ITK_OVERRIDE; + + /** StitchImageFilter needs a different input requested region than + * the output requested region. As such, StitchImageFilter needs + * to provide an implementation for GenerateInputRequestedRegion() + * in order to inform the pipeline execution model. + * \sa ProcessObject::GenerateInputRequestedRegion() */ + virtual void GenerateInputRequestedRegion() ITK_OVERRIDE; + + /** Set up state of filter before multi-threading. + * InterpolatorType::SetInputImage is not thread-safe and hence + * has to be set up before ThreadedGenerateData */ + virtual void BeforeThreadedGenerateData() ITK_OVERRIDE; + + /** Set the state of the filter after multi-threading. */ + virtual void AfterThreadedGenerateData() ITK_OVERRIDE; + + /** Compute the Modified Time based on the changed components. */ + ModifiedTimeType GetMTime(void) const ITK_OVERRIDE; + +#ifdef ITK_USE_CONCEPT_CHECKING + // Begin concept checking + itkConceptMacro( OutputHasNumericTraitsCheck, + ( Concept::HasNumericTraits< PixelComponentType > ) ); + // End concept checking +#endif + +protected: + StitchImageFilter(); + ~StitchImageFilter() ITK_OVERRIDE {} + void PrintSelf(std::ostream & os, Indent indent) const ITK_OVERRIDE; + + /** Override VeriyInputInformation() since this filter's inputs do + * not need to occoupy the same physical space. + * + * \sa ProcessObject::VerifyInputInformation + */ + virtual void VerifyInputInformation() ITK_OVERRIDE { } + + /** StitchImageFilter can be implemented as a multithreaded filter. + * Therefore, this implementation provides a ThreadedGenerateData() + * routine which is called for each processing thread. The output + * image data is allocated automatically by the superclass prior + * to calling ThreadedGenerateData(). + * ThreadedGenerateData can only write to the portion of the output image + * specified by the parameter "outputRegionForThread" + * \sa ImageToImageFilter::ThreadedGenerateData(), + * ImageToImageFilter::GenerateData() */ + virtual void ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread, + ThreadIdType threadId) ITK_OVERRIDE; + + /** Cast pixel from interpolator output to PixelType. */ + virtual PixelType CastPixelWithBoundsChecking( const InterpolatorOutputType value, + const ComponentType minComponent, + const ComponentType maxComponent) const; + + void SetTransform(unsigned int index, const TransformType* transform); + + /** Helper that ensures that a transform is specified for every input image. + If a input image has no specified transforms, an identity transform will + be created and set as default.*/ + void EnsureTransforms(); + + /** Helper that ensures that an interpolator is specified for every input image. + If a input image has no specified interpolator, a linear interpolator will + be created and set as default.*/ + void EnsureInterpolators(); + + static std::string GetTransformInputName(unsigned int index); + +private: + ITK_DISALLOW_COPY_AND_ASSIGN(StitchImageFilter); + + typedef std::vector InputImageVectorType; + typedef std::map TransformMapType; + typedef std::map InterpolatorMapType; + + InputImageVectorType GetInputs(); + TransformMapType GetTransforms(); + + InterpolatorMapType m_Interpolators; // Image function for + // interpolation + PixelType m_DefaultPixelValue; // default pixel value + // if the point is + // outside the image + SizeType m_Size; // Size of the output image + SpacingType m_OutputSpacing; // output image spacing + OriginPointType m_OutputOrigin; // output image origin + DirectionType m_OutputDirection; // output image direction cosines + IndexType m_OutputStartIndex; // output image start index + bool m_UseReferenceImage; + StitchStrategy m_StitchStrategy; +}; +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkStitchImageFilter.tpp" +#endif + +#endif diff --git a/Modules/MatchPointRegistration/include/itkStitchImageFilter.tpp b/Modules/MatchPointRegistration/include/itkStitchImageFilter.tpp new file mode 100644 index 0000000000..1ec8334ada --- /dev/null +++ b/Modules/MatchPointRegistration/include/itkStitchImageFilter.tpp @@ -0,0 +1,639 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#ifndef itkStitchImageFilter_hxx +#define itkStitchImageFilter_hxx + +#include "itkStitchImageFilter.h" +#include "itkObjectFactory.h" +#include "itkIdentityTransform.h" +#include "itkProgressReporter.h" +#include "itkImageRegionIteratorWithIndex.h" +#include "itkImageScanlineIterator.h" +#include "itkSpecialCoordinatesImage.h" +#include "itkDefaultConvertPixelTraits.h" +#include "itkSimpleDataObjectDecorator.h" + +#include + +namespace itk +{ + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::StitchImageFilter() : + m_OutputSpacing( 1.0 ), + m_OutputOrigin( 0.0 ), + m_UseReferenceImage( false ), + m_StitchStrategy(StitchStrategy::Mean) +{ + + m_Size.Fill( 0 ); + m_OutputStartIndex.Fill( 0 ); + + m_OutputDirection.SetIdentity(); + + // Pipeline input configuration + + // implicit input index set: + // #1 "ReferenceImage" optional + Self::AddOptionalInputName("ReferenceImage"); + + m_DefaultPixelValue + = NumericTraits::ZeroValue( m_DefaultPixelValue ); +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > + void + StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > + ::SetInput(const InputImageType* image) +{ + this->SetInput(0, image, itk::IdentityTransform< TTransformPrecisionType, ImageDimension>::New().GetPointer(), LinearInterpolatorType::New().GetPointer()); +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +void +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::SetInput(unsigned int index, const InputImageType* image) +{ + this->SetInput(index, image, itk::IdentityTransform< TTransformPrecisionType, ImageDimension>::New().GetPointer(), LinearInterpolatorType::New().GetPointer()); +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +void +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::SetInput(unsigned int index, const InputImageType* image, const TransformType* transform) +{ + this->SetInput(index, image, transform, LinearInterpolatorType::New().GetPointer()); +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +void +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::SetInput(unsigned int index, const InputImageType* image, const TransformType* transform, InterpolatorType* interpolator) +{ + Superclass::SetInput(index, image); + m_Interpolators[image] = interpolator; + + this->SetTransform(index, transform); +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > + void + StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > + ::SetTransform(unsigned int index, const TransformType* transform) +{ + const auto transformName = this->GetTransformInputName(index); + typedef SimpleDataObjectDecorator< TransformPointerType > DecoratorType; + const DecoratorType* oldInput = itkDynamicCastInDebugMode< const DecoratorType* >(this->ProcessObject::GetInput(transformName)); + if (!oldInput || oldInput->Get() != transform) + { + typename DecoratorType::Pointer newInput = DecoratorType::New(); + // Process object is not const-correct so the const_cast is required here + newInput->Set(const_cast(transform)); + this->ProcessObject::SetInput(transformName, newInput); + } +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > + const typename StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >::TransformType* + StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > + ::GetTransform(unsigned int index) const +{ + typedef SimpleDataObjectDecorator< TransformPointerType > DecoratorType; + const DecoratorType* input = itkDynamicCastInDebugMode< const DecoratorType* >(this->ProcessObject::GetInput(this->GetTransformInputName(index))); + + if (nullptr != input) + { + return input->Get(); + } + + return nullptr; +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > + const typename StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >::InterpolatorType* + StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > + ::GetInterpolator(unsigned int index) const +{ + auto input = this->GetInput(index); + if (m_Interpolators.find(input) != std::end(m_Interpolators)) + { + return m_Interpolators[input]; + } + + return nullptr; +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +void +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::SetOutputSpacing(const double *spacing) +{ + SpacingType s; + for(unsigned int i = 0; i < TOutputImage::ImageDimension; ++i) + { + s[i] = static_cast< typename SpacingType::ValueType >(spacing[i]); + } + this->SetOutputSpacing(s); +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +void +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::SetOutputOrigin(const double *origin) +{ + OriginPointType p(origin); + + this->SetOutputOrigin(p); +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +void +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::SetOutputParametersFromImage(const ImageBaseType *image) +{ + this->SetOutputOrigin ( image->GetOrigin() ); + this->SetOutputSpacing ( image->GetSpacing() ); + this->SetOutputDirection ( image->GetDirection() ); + this->SetOutputStartIndex ( image->GetLargestPossibleRegion().GetIndex() ); + this->SetSize ( image->GetLargestPossibleRegion().GetSize() ); +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +void +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::BeforeThreadedGenerateData() +{ + this->EnsureInterpolators(); + this->EnsureTransforms(); + + for (const auto& interpolator : m_Interpolators) + { + interpolator.second->SetInputImage(interpolator.first); + } + + unsigned int nComponents + = DefaultConvertPixelTraits::GetNumberOfComponents( + m_DefaultPixelValue ); + + if (nComponents == 0) + { + PixelComponentType zeroComponent + = NumericTraits::ZeroValue( zeroComponent ); + nComponents = this->GetInput()->GetNumberOfComponentsPerPixel(); + NumericTraits::SetLength(m_DefaultPixelValue, nComponents ); + for (unsigned int n=0; n +void +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::AfterThreadedGenerateData() +{ + // Disconnect input image from the interpolator + for (auto& interpolator : m_Interpolators) + { + interpolator.second->SetInputImage(ITK_NULLPTR); + } +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +void +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread, + ThreadIdType threadId) +{ + + if( outputRegionForThread.GetNumberOfPixels() == 0 ) + { + return; + } + + // Get the output pointers + OutputImageType* outputPtr = this->GetOutput(); + // Get this input pointers + InputImageVectorType inputs = this->GetInputs(); + TransformMapType transforms = this->GetTransforms(); + + std::map lowerIndices; + std::map upperIndices; + for (const auto& input : inputs) + { + const auto largestRegion = input->GetLargestPossibleRegion(); + lowerIndices[input] = largestRegion.GetIndex(); + upperIndices[input] = largestRegion.GetUpperIndex(); + } + + // Create an iterator that will walk the output region for this thread. + typedef ImageRegionIteratorWithIndex< OutputImageType > OutputIterator; + OutputIterator outIt(outputPtr, outputRegionForThread); + + // Define a few indices that will be used to translate from an input pixel + // to an output pixel + PointType outputPoint; // Coordinates of current output pixel + PointType inputPoint; // Coordinates of current input pixel + + ContinuousInputIndexType inputIndex; + + // Support for progress methods/callbacks + ProgressReporter progress(this, + threadId, + outputRegionForThread.GetNumberOfPixels()); + + // Min/max values of the output pixel type AND these values + // represented as the output type of the interpolator + const PixelComponentType minValue = NumericTraits< PixelComponentType >::NonpositiveMin(); + const PixelComponentType maxValue = NumericTraits< PixelComponentType >::max(); + + typedef typename InterpolatorType::OutputType OutputType; + const ComponentType minOutputValue = static_cast(minValue); + const ComponentType maxOutputValue = static_cast(maxValue); + + // Walk the output region + outIt.GoToBegin(); + + while (!outIt.IsAtEnd()) + { + // Determine the index of the current output pixel + outputPtr->TransformIndexToPhysicalPoint(outIt.GetIndex(), outputPoint); + + std::vector pixvals; + std::vector pixDistance; + + for (const auto& input : inputs) + { + // Compute corresponding input pixel position + inputPoint = transforms[input]->TransformPoint(outputPoint); + const bool isInsideInput = input->TransformPhysicalPointToContinuousIndex(inputPoint, inputIndex); + + // Evaluate input at right position and copy to the output + if (m_Interpolators[input]->IsInsideBuffer(inputIndex) && isInsideInput) + { + OutputType value = m_Interpolators[input]->EvaluateAtContinuousIndex(inputIndex); + pixvals.emplace_back(this->CastPixelWithBoundsChecking(value, minOutputValue, maxOutputValue)); + + ContinuousInputIndexType indexDistance; + const auto spacing = input->GetSpacing(); + + double minBorderDistance = std::numeric_limits::max(); + for (unsigned int i = 0; i < ImageDimension; ++i) + { + minBorderDistance = std::min(minBorderDistance, std::min(std::abs(lowerIndices[input][i] - inputIndex[i]) * spacing[i], std::abs(upperIndices[input][i] - inputIndex[i]) * spacing[i])); + } + pixDistance.emplace_back(minBorderDistance); + } + } + + if (!pixvals.empty()) + { //at least one input provided a value + if (StitchStrategy::Mean == m_StitchStrategy) + { + double sum = std::accumulate(pixvals.begin(), pixvals.end(), 0.0); + outIt.Set(sum / pixvals.size()); + } + else + { + auto finding = std::max_element(pixDistance.begin(), pixDistance.end()); + outIt.Set(pixvals[std::distance(pixDistance.begin(), finding)]); + } + } + else + { + outIt.Set(m_DefaultPixelValue); // default background value + } + + progress.CompletedPixel(); + ++outIt; + } +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +typename StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::PixelType +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::CastPixelWithBoundsChecking(const InterpolatorOutputType value, + const ComponentType minComponent, + const ComponentType maxComponent ) const +{ + const unsigned int nComponents = InterpolatorConvertType::GetNumberOfComponents(value); + PixelType outputValue; + + NumericTraits::SetLength( outputValue, nComponents ); + + for (unsigned int n = 0; n < nComponents; n++) + { + ComponentType component = InterpolatorConvertType::GetNthComponent( n, value ); + + if ( component < minComponent ) + { + PixelConvertType::SetNthComponent( n, outputValue, static_cast( minComponent ) ); + } + else if ( component > maxComponent ) + { + PixelConvertType::SetNthComponent( n, outputValue, static_cast( maxComponent ) ); + } + else + { + PixelConvertType::SetNthComponent(n, outputValue, + static_cast( component ) ); + } + } + + return outputValue; +} + +template +typename StitchImageFilter::InputImageVectorType +StitchImageFilter +::GetInputs() +{ + InputImageVectorType inputs; + for (unsigned int i = 0; i < this->GetNumberOfIndexedInputs(); ++i) + { + auto input = this->GetInput(i); + if (nullptr != input) + { + inputs.push_back(input); + } + } + return inputs; +} + +template +typename StitchImageFilter::TransformMapType +StitchImageFilter +::GetTransforms() +{ + TransformMapType transforms; + for (unsigned int i = 0; i < this->GetNumberOfIndexedInputs(); ++i) + { + auto input = this->GetInput(i); + auto transform = this->GetTransform(i); + transforms[input] = transform; + } + return transforms; +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +void +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::GenerateInputRequestedRegion() +{ + // Call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + if ( !this->GetInput() ) + { + return; + } + + // Get pointers to the input + auto inputs = this->GetInputs(); + + for (auto& input : inputs) + { + InputImagePointer inputPtr = + const_cast(input); + // Determining the actual input region is non-trivial, especially + // when we cannot assume anything about the transform being used. + // So we do the easy thing and request the entire input image. + // + inputPtr->SetRequestedRegionToLargestPossibleRegion(); + } +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +void +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::GenerateOutputInformation() +{ + // Call the superclass' implementation of this method + Superclass::GenerateOutputInformation(); + + // Get pointers to the input and output + OutputImageType *outputPtr = this->GetOutput(); + if ( !outputPtr ) + { + return; + } + + const ReferenceImageBaseType *referenceImage = this->GetReferenceImage(); + + // Set the size of the output region + if ( m_UseReferenceImage && referenceImage ) + { + outputPtr->SetLargestPossibleRegion( + referenceImage->GetLargestPossibleRegion() ); + } + else + { + typename TOutputImage::RegionType outputLargestPossibleRegion; + outputLargestPossibleRegion.SetSize(m_Size); + outputLargestPossibleRegion.SetIndex(m_OutputStartIndex); + outputPtr->SetLargestPossibleRegion(outputLargestPossibleRegion); + } + + // Set spacing and origin + if ( m_UseReferenceImage && referenceImage ) + { + outputPtr->SetSpacing( referenceImage->GetSpacing() ); + outputPtr->SetOrigin( referenceImage->GetOrigin() ); + outputPtr->SetDirection( referenceImage->GetDirection() ); + } + else + { + outputPtr->SetSpacing(m_OutputSpacing); + outputPtr->SetOrigin(m_OutputOrigin); + outputPtr->SetDirection(m_OutputDirection); + } +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +ModifiedTimeType +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::GetMTime(void) const +{ + ModifiedTimeType latestTime = Object::GetMTime(); + + for (const auto& interpolator : m_Interpolators) + { + if (interpolator.second.GetPointer()) + { + if (latestTime < interpolator.second->GetMTime()) + { + latestTime = interpolator.second->GetMTime(); + } + } + } + + return latestTime; +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +void +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::PrintSelf(std::ostream & os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "DefaultPixelValue: " + << static_cast< typename NumericTraits< PixelType >::PrintType > + ( m_DefaultPixelValue ) + << std::endl; + os << indent << "Size: " << m_Size << std::endl; + os << indent << "OutputStartIndex: " << m_OutputStartIndex << std::endl; + os << indent << "OutputSpacing: " << m_OutputSpacing << std::endl; + os << indent << "OutputOrigin: " << m_OutputOrigin << std::endl; + os << indent << "OutputDirection: " << m_OutputDirection << std::endl; + for (const auto& interpolator : m_Interpolators) + { + os << indent << "Interpolator: " << interpolator.second.GetPointer() << std::endl; + } + os << indent << "UseReferenceImage: " << ( m_UseReferenceImage ? "On" : "Off" ) + << std::endl; +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +void +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::EnsureTransforms() +{ + const auto inputCount = this->GetNumberOfIndexedInputs(); + for (unsigned int i = 0; i < inputCount; ++i) + { + auto input = this->GetInput(i); + + if (nullptr == input) + { + itkExceptionMacro(<< "Nth input image is not set (n: " << i << ")."); + } + + auto transform = this->GetTransform(i); + if (nullptr == transform) + { + this->SetTransform(i, itk::IdentityTransform< TTransformPrecisionType, ImageDimension>::New().GetPointer()); + } + } +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +void +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::EnsureInterpolators() +{ + const auto inputCount = this->GetNumberOfIndexedInputs(); + InterpolatorMapType newInterpolatorMap; + + for (unsigned int i = 0; i < inputCount; ++i) + { + auto input = this->GetInput(i); + + if (nullptr == input) + { + itkExceptionMacro(<< "Nth input image is not set (n: " << i << ")."); + } + + if (m_Interpolators[input].IsNull()) + { + newInterpolatorMap[input] = LinearInterpolatorType::New().GetPointer(); + } + else + { + newInterpolatorMap[input] = m_Interpolators[input]; + } + } + m_Interpolators = newInterpolatorMap; +} + +template< typename TInputImage, + typename TOutputImage, + typename TInterpolatorPrecisionType, + typename TTransformPrecisionType > +std::string +StitchImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType > +::GetTransformInputName(unsigned int index) +{ + return "transform_" + std::to_string(index); +} + +} // end namespace itk + +#endif diff --git a/Modules/MatchPointRegistration/Helper/mitkImageMappingHelper.h b/Modules/MatchPointRegistration/include/mitkImageMappingHelper.h similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkImageMappingHelper.h rename to Modules/MatchPointRegistration/include/mitkImageMappingHelper.h diff --git a/Modules/MatchPointRegistration/include/mitkImageStitchingHelper.h b/Modules/MatchPointRegistration/include/mitkImageStitchingHelper.h new file mode 100644 index 0000000000..8d4b12f3ec --- /dev/null +++ b/Modules/MatchPointRegistration/include/mitkImageStitchingHelper.h @@ -0,0 +1,67 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + + +#ifndef MITK_IMAGE_STITCHING_HELPER_H +#define MITK_IMAGE_STITCHING_HELPER_H + +#include "mapRegistrationBase.h" +#include "mitkImage.h" +#include "mitkGeometry3D.h" + +#include "mitkMAPRegistrationWrapper.h" +#include "mitkImageMappingHelper.h" + +#include + +#include "MitkMatchPointRegistrationExports.h" + +namespace mitk +{ + /**Helper that stitches a given vector of input images + * @param inputs vector of input images that should be stitched. + * @param registrations vector of registrations that should be used for mapping of the inputs before stitching. + * the method assumes that order of registrations is the same as the order of inputs, thus for the n-th input + * the n-th registration will be used. + * @param resultGeometry Pointer to the Geometry object that specifies the grid of the result image. + * @param paddingValue Indicates the value that should be used if an out of input error occurs (and throwOnOutOfInputAreaError is false). + * @param interpolatorType Indicates the type of interpolation strategy that should be used. + * @param stitchStrategy Strategy used if more than one input can contribute. for more details see the documentation of itk::StitchStrategy. + * @pre inputs must not be empty and contain valid instances + * @pre registration must have same size as inputs and contain valid instances. + * @pre Dimensionality of the registrations must match with the inputs + * @pre resultGeometry must be valid. + * @remark The helper currently only supports 3D images. + * @result Pointer to the resulting mapped image.h*/ + MITKMATCHPOINTREGISTRATION_EXPORT Image::Pointer StitchImages(std::vector inputs, + std::vector<::map::core::RegistrationBase::ConstPointer> registrations, + const BaseGeometry* resultGeometry, + const double& paddingValue = 0, itk::StitchStrategy stitchStrategy = itk::StitchStrategy::Mean, + mitk::ImageMappingInterpolator::Type interpolatorType = mitk::ImageMappingInterpolator::Linear); + + MITKMATCHPOINTREGISTRATION_EXPORT Image::Pointer StitchImages(std::vector inputs, + std::vector registrations, + const BaseGeometry* resultGeometry, + const double& paddingValue = 0, itk::StitchStrategy stitchStrategy = itk::StitchStrategy::Mean, + mitk::ImageMappingInterpolator::Type interpolatorType = mitk::ImageMappingInterpolator::Linear); + + /**@overload + * Convinience version that uses identity transforms form the registrations. + */ + MITKMATCHPOINTREGISTRATION_EXPORT Image::Pointer StitchImages(std::vector inputs, + const BaseGeometry* resultGeometry, + const double& paddingValue = 0, itk::StitchStrategy stitchStrategy = itk::StitchStrategy::Mean, + mitk::ImageMappingInterpolator::Type interpolatorType = mitk::ImageMappingInterpolator::Linear); + +} + +#endif diff --git a/Modules/MatchPointRegistration/Helper/mitkMAPAlgorithmHelper.h b/Modules/MatchPointRegistration/include/mitkMAPAlgorithmHelper.h similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkMAPAlgorithmHelper.h rename to Modules/MatchPointRegistration/include/mitkMAPAlgorithmHelper.h diff --git a/Modules/MatchPointRegistration/mitkMAPRegistrationWrapper.h b/Modules/MatchPointRegistration/include/mitkMAPRegistrationWrapper.h similarity index 100% rename from Modules/MatchPointRegistration/mitkMAPRegistrationWrapper.h rename to Modules/MatchPointRegistration/include/mitkMAPRegistrationWrapper.h diff --git a/Modules/MatchPointRegistration/mitkMAPRegistrationWrapperObjectFactory.h b/Modules/MatchPointRegistration/include/mitkMAPRegistrationWrapperObjectFactory.h similarity index 100% rename from Modules/MatchPointRegistration/mitkMAPRegistrationWrapperObjectFactory.h rename to Modules/MatchPointRegistration/include/mitkMAPRegistrationWrapperObjectFactory.h diff --git a/Modules/MatchPointRegistration/Helper/mitkMaskedAlgorithmHelper.h b/Modules/MatchPointRegistration/include/mitkMaskedAlgorithmHelper.h similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkMaskedAlgorithmHelper.h rename to Modules/MatchPointRegistration/include/mitkMaskedAlgorithmHelper.h diff --git a/Modules/MatchPointRegistration/mitkMatchPointPropertyTags.h b/Modules/MatchPointRegistration/include/mitkMatchPointPropertyTags.h similarity index 100% rename from Modules/MatchPointRegistration/mitkMatchPointPropertyTags.h rename to Modules/MatchPointRegistration/include/mitkMatchPointPropertyTags.h diff --git a/Modules/MatchPointRegistration/Helper/mitkPointSetMappingHelper.h b/Modules/MatchPointRegistration/include/mitkPointSetMappingHelper.h similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkPointSetMappingHelper.h rename to Modules/MatchPointRegistration/include/mitkPointSetMappingHelper.h diff --git a/Modules/MatchPointRegistration/Helper/mitkQMAPAlgorithmModel.h b/Modules/MatchPointRegistration/include/mitkQMAPAlgorithmModel.h similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkQMAPAlgorithmModel.h rename to Modules/MatchPointRegistration/include/mitkQMAPAlgorithmModel.h diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegEvalStyleProperty.h b/Modules/MatchPointRegistration/include/mitkRegEvalStyleProperty.h similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegEvalStyleProperty.h rename to Modules/MatchPointRegistration/include/mitkRegEvalStyleProperty.h diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegEvalWipeStyleProperty.h b/Modules/MatchPointRegistration/include/mitkRegEvalWipeStyleProperty.h similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegEvalWipeStyleProperty.h rename to Modules/MatchPointRegistration/include/mitkRegEvalWipeStyleProperty.h diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegEvaluationMapper2D.h b/Modules/MatchPointRegistration/include/mitkRegEvaluationMapper2D.h similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegEvaluationMapper2D.h rename to Modules/MatchPointRegistration/include/mitkRegEvaluationMapper2D.h diff --git a/Modules/MatchPointRegistration/mitkRegEvaluationObject.h b/Modules/MatchPointRegistration/include/mitkRegEvaluationObject.h similarity index 100% rename from Modules/MatchPointRegistration/mitkRegEvaluationObject.h rename to Modules/MatchPointRegistration/include/mitkRegEvaluationObject.h diff --git a/Modules/MatchPointRegistration/mitkRegEvaluationObjectFactory.h b/Modules/MatchPointRegistration/include/mitkRegEvaluationObjectFactory.h similarity index 100% rename from Modules/MatchPointRegistration/mitkRegEvaluationObjectFactory.h rename to Modules/MatchPointRegistration/include/mitkRegEvaluationObjectFactory.h diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegVisColorStyleProperty.h b/Modules/MatchPointRegistration/include/mitkRegVisColorStyleProperty.h similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegVisColorStyleProperty.h rename to Modules/MatchPointRegistration/include/mitkRegVisColorStyleProperty.h diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegVisDirectionProperty.h b/Modules/MatchPointRegistration/include/mitkRegVisDirectionProperty.h similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegVisDirectionProperty.h rename to Modules/MatchPointRegistration/include/mitkRegVisDirectionProperty.h diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegVisHelper.h b/Modules/MatchPointRegistration/include/mitkRegVisHelper.h similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegVisHelper.h rename to Modules/MatchPointRegistration/include/mitkRegVisHelper.h diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegVisPropertyTags.h b/Modules/MatchPointRegistration/include/mitkRegVisPropertyTags.h similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegVisPropertyTags.h rename to Modules/MatchPointRegistration/include/mitkRegVisPropertyTags.h diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegVisStyleProperty.h b/Modules/MatchPointRegistration/include/mitkRegVisStyleProperty.h similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegVisStyleProperty.h rename to Modules/MatchPointRegistration/include/mitkRegVisStyleProperty.h diff --git a/Modules/MatchPointRegistration/Helper/mitkRegistrationHelper.h b/Modules/MatchPointRegistration/include/mitkRegistrationHelper.h similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkRegistrationHelper.h rename to Modules/MatchPointRegistration/include/mitkRegistrationHelper.h diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegistrationWrapperMapper2D.h b/Modules/MatchPointRegistration/include/mitkRegistrationWrapperMapper2D.h similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegistrationWrapperMapper2D.h rename to Modules/MatchPointRegistration/include/mitkRegistrationWrapperMapper2D.h diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegistrationWrapperMapper3D.h b/Modules/MatchPointRegistration/include/mitkRegistrationWrapperMapper3D.h similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegistrationWrapperMapper3D.h rename to Modules/MatchPointRegistration/include/mitkRegistrationWrapperMapper3D.h diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegistrationWrapperMapperBase.h b/Modules/MatchPointRegistration/include/mitkRegistrationWrapperMapperBase.h similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegistrationWrapperMapperBase.h rename to Modules/MatchPointRegistration/include/mitkRegistrationWrapperMapperBase.h diff --git a/Modules/MatchPointRegistration/Helper/mitkResultNodeGenerationHelper.h b/Modules/MatchPointRegistration/include/mitkResultNodeGenerationHelper.h similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkResultNodeGenerationHelper.h rename to Modules/MatchPointRegistration/include/mitkResultNodeGenerationHelper.h diff --git a/Modules/MatchPointRegistration/Helper/mitkTimeFramesRegistrationHelper.h b/Modules/MatchPointRegistration/include/mitkTimeFramesRegistrationHelper.h similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkTimeFramesRegistrationHelper.h rename to Modules/MatchPointRegistration/include/mitkTimeFramesRegistrationHelper.h diff --git a/Modules/MatchPointRegistration/Helper/mitkUIDHelper.h b/Modules/MatchPointRegistration/include/mitkUIDHelper.h similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkUIDHelper.h rename to Modules/MatchPointRegistration/include/mitkUIDHelper.h diff --git a/Modules/MatchPointRegistration/Helper/QmitkAlgorithmListModel.cpp b/Modules/MatchPointRegistration/src/Helper/QmitkAlgorithmListModel.cpp similarity index 100% rename from Modules/MatchPointRegistration/Helper/QmitkAlgorithmListModel.cpp rename to Modules/MatchPointRegistration/src/Helper/QmitkAlgorithmListModel.cpp diff --git a/Modules/MatchPointRegistration/Helper/QmitkMapPropertyDelegate.cpp b/Modules/MatchPointRegistration/src/Helper/QmitkMapPropertyDelegate.cpp similarity index 100% rename from Modules/MatchPointRegistration/Helper/QmitkMapPropertyDelegate.cpp rename to Modules/MatchPointRegistration/src/Helper/QmitkMapPropertyDelegate.cpp diff --git a/Modules/MatchPointRegistration/Helper/mitkImageMappingHelper.cpp b/Modules/MatchPointRegistration/src/Helper/mitkImageMappingHelper.cpp similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkImageMappingHelper.cpp rename to Modules/MatchPointRegistration/src/Helper/mitkImageMappingHelper.cpp diff --git a/Modules/MatchPointRegistration/src/Helper/mitkImageStitchingHelper.cpp b/Modules/MatchPointRegistration/src/Helper/mitkImageStitchingHelper.cpp new file mode 100644 index 0000000000..e0fcb5f46a --- /dev/null +++ b/Modules/MatchPointRegistration/src/Helper/mitkImageStitchingHelper.cpp @@ -0,0 +1,229 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#include "mitkImageStitchingHelper.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "mapRegistration.h" + +#include "mitkRegistrationHelper.h" + +template +typename ::itk::InterpolateImageFunction< TImage >::Pointer generateInterpolator(mitk::ImageMappingInterpolator::Type interpolatorType) +{ + typedef ::itk::InterpolateImageFunction< TImage > BaseInterpolatorType; + typename BaseInterpolatorType::Pointer result; + + switch (interpolatorType) + { + case mitk::ImageMappingInterpolator::NearestNeighbor: + { + result = ::itk::NearestNeighborInterpolateImageFunction::New(); + break; + } + case mitk::ImageMappingInterpolator::BSpline_3: + { + typename ::itk::BSplineInterpolateImageFunction::Pointer spInterpolator = ::itk::BSplineInterpolateImageFunction::New(); + spInterpolator->SetSplineOrder(3); + result = spInterpolator; + break; + } + case mitk::ImageMappingInterpolator::WSinc_Hamming: + { + result = ::itk::WindowedSincInterpolateImageFunction::New(); + break; + } + case mitk::ImageMappingInterpolator::WSinc_Welch: + { + result = ::itk::WindowedSincInterpolateImageFunction >::New(); + break; + } + default: + { + result = ::itk::LinearInterpolateImageFunction::New(); + break; + } + + } + + return result; +}; + +template +void doMITKStitching(const ::itk::Image* /*input1*/, + mitk::Image::Pointer& result, + std::vector inputs, + std::vector<::map::core::RegistrationBase::ConstPointer> registrations, + const mitk::BaseGeometry* resultGeometry, + const double& paddingValue, itk::StitchStrategy stitchStrategy, mitk::ImageMappingInterpolator::Type interpolatorType) +{ + using ConcreteRegistrationType = ::map::core::Registration; + using ItkImageType = itk::Image; + + using StitchingFilterType = ::itk::StitchImageFilter; + auto stitcher = StitchingFilterType::New(); + + stitcher->SetDefaultPixelValue(paddingValue); + + stitcher->SetOutputOrigin(resultGeometry->GetOrigin()); + + const auto spacing = resultGeometry->GetSpacing(); + stitcher->SetOutputSpacing(spacing); + + typename StitchingFilterType::DirectionType itkDirection; + const auto mitkDirection = resultGeometry->GetIndexToWorldTransform()->GetMatrix(); + for (unsigned int i = 0; i < VImageDimension; ++i) + { + for (unsigned int j = 0; j < VImageDimension; ++j) + { + itkDirection[i][j] = mitkDirection[i][j] / spacing[j]; + } + } + stitcher->SetOutputDirection(itkDirection); + + typename ItkImageType::SizeType size; + size[0] = resultGeometry->GetExtent(0); + size[1] = resultGeometry->GetExtent(1); + size[2] = resultGeometry->GetExtent(2); + stitcher->SetSize(size); + stitcher->SetNumberOfThreads(1); + stitcher->SetStitchStrategy(stitchStrategy); + + auto inputIter = inputs.begin(); + auto regIter = registrations.begin(); + unsigned int index = 0; + + while (inputIter != inputs.end()) + { + auto itkInput = mitk::ImageToItkImage(*inputIter); + + auto castedReg = dynamic_cast(regIter->GetPointer()); + + auto kernel = dynamic_cast* >(&(castedReg->getInverseMapping())); + if (nullptr == kernel) + { + mitkThrow() << "Cannot stitch images. At least passed registration object #"<SetInput(index, itkInput, kernel->getTransformModel(), generateInterpolator< ::itk::Image >(interpolatorType)); + ++inputIter; + ++regIter; + ++index; + } + + stitcher->Update(); + mitk::CastToMitkImage<>(stitcher->GetOutput(),result); +} + +mitk::Image::Pointer +mitk::StitchImages(std::vector inputs, + std::vector<::map::core::RegistrationBase::ConstPointer> registrations, + const BaseGeometry* resultGeometry, + const double& paddingValue, itk::StitchStrategy stitchStrategy, + mitk::ImageMappingInterpolator::Type interpolatorType) +{ + if (inputs.size() != registrations.size()) + { + mitkThrow() << "Cannot stitch images. Passed inputs vector and registrations vector have different sizes."; + } + + if (inputs.empty()) + { + mitkThrow() << "Cannot stitch images. No input images are defined."; + } + + auto inputDim = inputs.front()->GetDimension(); + auto inputPixelType = inputs.front()->GetPixelType(); + + for (const auto& input : inputs) + { + if (input->GetDimension() != inputDim) + { + mitkThrow() << "Cannot stitch images. Images have different dimensions. Dimeonsion of first input: " << inputDim << "; wrong dimension: " << input->GetDimension(); + } + if (input->GetPixelType() != inputPixelType) + { + mitkThrow() << "Cannot stitch images. Input images have different pixeltypes. The current implementation does only support stitching of images with same pixel type. Dimeonsion of first input: " << inputPixelType.GetTypeAsString() << "; wrong dimension: " << input->GetPixelType().GetTypeAsString(); + } + if (input->GetTimeSteps() > 1) + { + mitkThrow() << "Cannot stitch dynamic images. At least one input image has multiple time steps."; + } + } + + for (const auto& reg : registrations) + { + if (reg->getMovingDimensions() != inputDim) + { + mitkThrow() << "Cannot stitch images. At least one registration has a different moving dimension then the inputs. Dimeonsion of inputs: " << inputDim << "; wrong dimension: " << reg->getMovingDimensions(); + } + if (reg->getTargetDimensions() != inputDim) + { + mitkThrow() << "Cannot stitch images. At least one registration has a different target dimension then the inputs. Dimeonsion of inputs: " << inputDim << "; wrong dimension: " << reg->getTargetDimensions(); + } + } + + Image::Pointer result; + + AccessFixedDimensionByItk_n(inputs.front(), doMITKStitching, 3, (result, inputs, registrations, resultGeometry, paddingValue, stitchStrategy, interpolatorType)); + + return result; +} + +mitk::Image::Pointer +mitk::StitchImages(std::vector inputs, + std::vector registrations, + const BaseGeometry* resultGeometry, + const double& paddingValue, itk::StitchStrategy stitchStrategy, + mitk::ImageMappingInterpolator::Type interpolatorType) +{ + + std::vector<::map::core::RegistrationBase::ConstPointer> unwrappedRegs; + for (const auto& reg : registrations) + { + if (!reg) + { + mitkThrow() << "Cannot stitch images. At least one passed registration wrapper pointer is nullptr."; + } + unwrappedRegs.push_back(reg->GetRegistration()); + } + + Image::Pointer result = StitchImages(inputs, unwrappedRegs, resultGeometry, paddingValue, stitchStrategy, interpolatorType); + return result; +} + +mitk::Image::Pointer +mitk::StitchImages(std::vector inputs, + const BaseGeometry* resultGeometry, + const double& paddingValue, itk::StitchStrategy stitchStrategy, + mitk::ImageMappingInterpolator::Type interpolatorType) +{ + auto defaultReg = GenerateIdentityRegistration3D(); + std::vector<::map::core::RegistrationBase::ConstPointer> defaultRegs; + defaultRegs.resize(inputs.size()); + std::fill(defaultRegs.begin(), defaultRegs.end(), defaultReg->GetRegistration()); + + Image::Pointer result = StitchImages(inputs, defaultRegs, resultGeometry, paddingValue, stitchStrategy, interpolatorType); + return result; +} + diff --git a/Modules/MatchPointRegistration/Helper/mitkMAPAlgorithmHelper.cpp b/Modules/MatchPointRegistration/src/Helper/mitkMAPAlgorithmHelper.cpp similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkMAPAlgorithmHelper.cpp rename to Modules/MatchPointRegistration/src/Helper/mitkMAPAlgorithmHelper.cpp diff --git a/Modules/MatchPointRegistration/Helper/mitkMaskedAlgorithmHelper.cpp b/Modules/MatchPointRegistration/src/Helper/mitkMaskedAlgorithmHelper.cpp similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkMaskedAlgorithmHelper.cpp rename to Modules/MatchPointRegistration/src/Helper/mitkMaskedAlgorithmHelper.cpp diff --git a/Modules/MatchPointRegistration/Helper/mitkPointSetMappingHelper.cpp b/Modules/MatchPointRegistration/src/Helper/mitkPointSetMappingHelper.cpp similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkPointSetMappingHelper.cpp rename to Modules/MatchPointRegistration/src/Helper/mitkPointSetMappingHelper.cpp diff --git a/Modules/MatchPointRegistration/Helper/mitkQMAPAlgorithmModel.cpp b/Modules/MatchPointRegistration/src/Helper/mitkQMAPAlgorithmModel.cpp similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkQMAPAlgorithmModel.cpp rename to Modules/MatchPointRegistration/src/Helper/mitkQMAPAlgorithmModel.cpp diff --git a/Modules/MatchPointRegistration/Helper/mitkRegistrationHelper.cpp b/Modules/MatchPointRegistration/src/Helper/mitkRegistrationHelper.cpp similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkRegistrationHelper.cpp rename to Modules/MatchPointRegistration/src/Helper/mitkRegistrationHelper.cpp diff --git a/Modules/MatchPointRegistration/Helper/mitkResultNodeGenerationHelper.cpp b/Modules/MatchPointRegistration/src/Helper/mitkResultNodeGenerationHelper.cpp similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkResultNodeGenerationHelper.cpp rename to Modules/MatchPointRegistration/src/Helper/mitkResultNodeGenerationHelper.cpp diff --git a/Modules/MatchPointRegistration/Helper/mitkTimeFramesRegistrationHelper.cpp b/Modules/MatchPointRegistration/src/Helper/mitkTimeFramesRegistrationHelper.cpp similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkTimeFramesRegistrationHelper.cpp rename to Modules/MatchPointRegistration/src/Helper/mitkTimeFramesRegistrationHelper.cpp diff --git a/Modules/MatchPointRegistration/Helper/mitkUIDHelper.cpp b/Modules/MatchPointRegistration/src/Helper/mitkUIDHelper.cpp similarity index 100% rename from Modules/MatchPointRegistration/Helper/mitkUIDHelper.cpp rename to Modules/MatchPointRegistration/src/Helper/mitkUIDHelper.cpp diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegEvalStyleProperty.cpp b/Modules/MatchPointRegistration/src/Rendering/mitkRegEvalStyleProperty.cpp similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegEvalStyleProperty.cpp rename to Modules/MatchPointRegistration/src/Rendering/mitkRegEvalStyleProperty.cpp diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegEvalWipeStyleProperty.cpp b/Modules/MatchPointRegistration/src/Rendering/mitkRegEvalWipeStyleProperty.cpp similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegEvalWipeStyleProperty.cpp rename to Modules/MatchPointRegistration/src/Rendering/mitkRegEvalWipeStyleProperty.cpp diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegEvaluationMapper2D.cpp b/Modules/MatchPointRegistration/src/Rendering/mitkRegEvaluationMapper2D.cpp similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegEvaluationMapper2D.cpp rename to Modules/MatchPointRegistration/src/Rendering/mitkRegEvaluationMapper2D.cpp diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegVisColorStyleProperty.cpp b/Modules/MatchPointRegistration/src/Rendering/mitkRegVisColorStyleProperty.cpp similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegVisColorStyleProperty.cpp rename to Modules/MatchPointRegistration/src/Rendering/mitkRegVisColorStyleProperty.cpp diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegVisDirectionProperty.cpp b/Modules/MatchPointRegistration/src/Rendering/mitkRegVisDirectionProperty.cpp similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegVisDirectionProperty.cpp rename to Modules/MatchPointRegistration/src/Rendering/mitkRegVisDirectionProperty.cpp diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegVisHelper.cpp b/Modules/MatchPointRegistration/src/Rendering/mitkRegVisHelper.cpp similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegVisHelper.cpp rename to Modules/MatchPointRegistration/src/Rendering/mitkRegVisHelper.cpp diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegVisPropertyTags.cpp b/Modules/MatchPointRegistration/src/Rendering/mitkRegVisPropertyTags.cpp similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegVisPropertyTags.cpp rename to Modules/MatchPointRegistration/src/Rendering/mitkRegVisPropertyTags.cpp diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegVisStyleProperty.cpp b/Modules/MatchPointRegistration/src/Rendering/mitkRegVisStyleProperty.cpp similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegVisStyleProperty.cpp rename to Modules/MatchPointRegistration/src/Rendering/mitkRegVisStyleProperty.cpp diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegistrationWrapperMapper2D.cpp b/Modules/MatchPointRegistration/src/Rendering/mitkRegistrationWrapperMapper2D.cpp similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegistrationWrapperMapper2D.cpp rename to Modules/MatchPointRegistration/src/Rendering/mitkRegistrationWrapperMapper2D.cpp diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegistrationWrapperMapper3D.cpp b/Modules/MatchPointRegistration/src/Rendering/mitkRegistrationWrapperMapper3D.cpp similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegistrationWrapperMapper3D.cpp rename to Modules/MatchPointRegistration/src/Rendering/mitkRegistrationWrapperMapper3D.cpp diff --git a/Modules/MatchPointRegistration/Rendering/mitkRegistrationWrapperMapperBase.cpp b/Modules/MatchPointRegistration/src/Rendering/mitkRegistrationWrapperMapperBase.cpp similarity index 100% rename from Modules/MatchPointRegistration/Rendering/mitkRegistrationWrapperMapperBase.cpp rename to Modules/MatchPointRegistration/src/Rendering/mitkRegistrationWrapperMapperBase.cpp diff --git a/Modules/MatchPointRegistration/mitkMAPRegistrationWrapper.cpp b/Modules/MatchPointRegistration/src/mitkMAPRegistrationWrapper.cpp similarity index 100% rename from Modules/MatchPointRegistration/mitkMAPRegistrationWrapper.cpp rename to Modules/MatchPointRegistration/src/mitkMAPRegistrationWrapper.cpp diff --git a/Modules/MatchPointRegistration/mitkMAPRegistrationWrapperObjectFactory.cpp b/Modules/MatchPointRegistration/src/mitkMAPRegistrationWrapperObjectFactory.cpp similarity index 100% rename from Modules/MatchPointRegistration/mitkMAPRegistrationWrapperObjectFactory.cpp rename to Modules/MatchPointRegistration/src/mitkMAPRegistrationWrapperObjectFactory.cpp diff --git a/Modules/MatchPointRegistration/mitkRegEvaluationObject.cpp b/Modules/MatchPointRegistration/src/mitkRegEvaluationObject.cpp similarity index 100% rename from Modules/MatchPointRegistration/mitkRegEvaluationObject.cpp rename to Modules/MatchPointRegistration/src/mitkRegEvaluationObject.cpp diff --git a/Modules/MatchPointRegistration/mitkRegEvaluationObjectFactory.cpp b/Modules/MatchPointRegistration/src/mitkRegEvaluationObjectFactory.cpp similarity index 100% rename from Modules/MatchPointRegistration/mitkRegEvaluationObjectFactory.cpp rename to Modules/MatchPointRegistration/src/mitkRegEvaluationObjectFactory.cpp diff --git a/Modules/ModelFit/cmdapps/Fuse3Dto4DImageMiniApp.cpp b/Modules/ModelFit/cmdapps/Fuse3Dto4DImageMiniApp.cpp index a2cd40129f..de03cf4055 100644 --- a/Modules/ModelFit/cmdapps/Fuse3Dto4DImageMiniApp.cpp +++ b/Modules/ModelFit/cmdapps/Fuse3Dto4DImageMiniApp.cpp @@ -1,167 +1,167 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // std includes #include #include // itk includes #include "itksys/SystemTools.hxx" // CTK includes #include "mitkCommandLineParser.h" // MITK includes #include #include #include mitkCommandLineParser::StringContainerType inFilenames; std::string outFileName; std::vector images; std::vector timebounds; void setupParser(mitkCommandLineParser& parser) { // set general information about your MiniApp parser.setCategory("Dynamic Data Analysis Tools"); parser.setTitle("Fuse 3D to 4D Image"); parser.setDescription("MiniApp that allows to fuse several 3D images (with same geometry) into a 3D+t (4D) image that can be processed as dynamic data."); parser.setContributor("DKFZ MIC"); //! [create parser] //! [add arguments] // how should arguments be prefixed parser.setArgumentPrefix("--", "-"); // add each argument, unless specified otherwise each argument is optional // see mitkCommandLineParser::addArgument for more information parser.beginGroup("Required I/O parameters"); parser.addArgument( "inputs", "i", mitkCommandLineParser::StringList, "Input files", "Pathes to the input images that should be fused", us::Any(), false, false, false, mitkCommandLineParser::Input); parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file path", "Path to the fused 3D+t image.", us::Any(), false, false, false, mitkCommandLineParser::Output); parser.endGroup(); parser.beginGroup("Optional parameters"); parser.addArgument( "time", "t", mitkCommandLineParser::StringList, "Time bounds", "Defines the time geometry of the resulting dynamic image in [ms]. The first number is the start time point of the first time step. All other numbers are the max bound of a time step. So the structure is [minBound0 maxBound1 [maxBound2 [... maxBoundN]]]; e.g. \"2 3.5 10\" encodes a time geometry with two time steps and that starts at 2 ms and the second time step starts at 3.5 ms and ends at 10 ms. If not set e propertional time geometry with 1 ms duration will be generated!", us::Any(), true, false, false, mitkCommandLineParser::Input); parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text"); parser.endGroup(); //! [add arguments] } bool configureApplicationSettings(std::map parsedArgs) { if (parsedArgs.size() == 0) return false; inFilenames = us::any_cast(parsedArgs["inputs"]); outFileName = us::any_cast(parsedArgs["output"]); if (parsedArgs.count("time")) { auto timeBoundsStr = us::any_cast(parsedArgs["time"]); for (const auto& timeBoundStr : timeBoundsStr) { std::istringstream stream; stream.imbue(std::locale("C")); stream.str(timeBoundStr); mitk::TimePointType time = 0 ; stream >> time; timebounds.emplace_back(time); } } return true; } int main(int argc, char* argv[]) { mitkCommandLineParser parser; setupParser(parser); - mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (classic config)" }, { "MITK DICOM Reader" }); + mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (autoselect)" }, { "" }); const std::map& parsedArgs = parser.parseArguments(argc, argv); if (!configureApplicationSettings(parsedArgs)) { return EXIT_FAILURE; }; // Show a help message if (parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } if (timebounds.empty()) { timebounds.resize(inFilenames.size()+1); std::iota(timebounds.begin(), timebounds.end(), 0.0); } else if (inFilenames.size() + 1 != timebounds.size()) { std::cerr << "Cannot fuse images. Explicitly specified time bounds do not match. Use --help for more information on how to specify time bounds correctly."; return EXIT_FAILURE; }; //! [do processing] try { std::cout << "Load images:" << std::endl; auto filter = mitk::TemporalJoinImagesFilter::New(); unsigned int step = 0; for (auto path : inFilenames) { std::cout << "Time step #"<(path, &readerFilterFunctor); images.push_back(image); filter->SetInput(step, image); ++step; } filter->SetFirstMinTimeBound(timebounds[0]); filter->SetMaxTimeBounds({ timebounds.begin() + 1, timebounds.end() }); std::cout << "Fuse the images ..." << std::endl; filter->Update(); auto output = filter->GetOutput(); std::cout << "Save output image: " << outFileName << std::endl; mitk::IOUtil::Save(output, outFileName); std::cout << "Processing finished." << std::endl; return EXIT_SUCCESS; } catch (const std::exception& e) { MITK_ERROR << e.what(); return EXIT_FAILURE; } catch (...) { MITK_ERROR << "Unexpected error encountered."; return EXIT_FAILURE; } } diff --git a/Modules/ModelFit/cmdapps/GenericFittingMiniApp.cpp b/Modules/ModelFit/cmdapps/GenericFittingMiniApp.cpp index 68984e081d..0e45f362ed 100644 --- a/Modules/ModelFit/cmdapps/GenericFittingMiniApp.cpp +++ b/Modules/ModelFit/cmdapps/GenericFittingMiniApp.cpp @@ -1,360 +1,360 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // std includes #include // itk includes #include "itksys/SystemTools.hxx" // CTK includes #include "mitkCommandLineParser.h" // MITK includes #include #include #include #include #include #include #include #include #include #include #include #include std::string inFilename; std::string outFileName; std::string maskFileName; bool verbose(false); bool roibased(false); std::string functionName; std::string formular; mitk::Image::Pointer image; mitk::Image::Pointer mask; void onFitEvent(::itk::Object* caller, const itk::EventObject & event, void* /*data*/) { itk::ProgressEvent progressEvent; if (progressEvent.CheckEvent(&event)) { mitk::ParameterFitImageGeneratorBase* castedReporter = dynamic_cast(caller); std::cout <GetProgress()*100 << "% "; } } void setupParser(mitkCommandLineParser& parser) { // set general information about your MiniApp parser.setCategory("Dynamic Data Analysis Tools"); parser.setTitle("Generic Fitting"); parser.setDescription("MiniApp that allows to make a pixel based fitting on the intensity signal over time for a given model function."); parser.setContributor("DKFZ MIC"); //! [create parser] //! [add arguments] // how should arguments be prefixed parser.setArgumentPrefix("--", "-"); // add each argument, unless specified otherwise each argument is optional // see mitkCommandLineParser::addArgument for more information parser.beginGroup("Model parameters"); parser.addArgument( "function", "f", mitkCommandLineParser::String, "Model function", "Function that should be used to fit the intensity signals. Options are: \"Linear\" or \"\" (for generic formulas).", us::Any(std::string("Linear"))); parser.addArgument( "formular", "y", mitkCommandLineParser::String, "Generic model function formular", "Formular of a generic model (if selected) that will be parsed and fitted.", us::Any()); parser.endGroup(); parser.beginGroup("Required I/O parameters"); parser.addArgument( "input", "i", mitkCommandLineParser::File, "Input file", "input 3D+t image file", us::Any(), false, false, false, mitkCommandLineParser::Input); parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file template", "where to save the output parameter images. The specified path will be used as template to determine the format (via extension) and the name \"root\". For each parameter a suffix will be added to the name.", us::Any(), false, false, false, mitkCommandLineParser::Output); parser.endGroup(); parser.beginGroup("Optional parameters"); parser.addArgument( "mask", "m", mitkCommandLineParser::File, "Mask file", "Mask that defines the spatial image region that should be fitted. Must have the same geometry as the input image!", us::Any(), true, false, false, mitkCommandLineParser::Input); parser.addArgument( "verbose", "v", mitkCommandLineParser::Bool, "Verbose Output", "Whether to produce verbose output"); parser.addArgument( "roibased", "r", mitkCommandLineParser::Bool, "Roi based fitting", "Will compute a mean intesity signal over the ROI before fitting it. If this mode is used a mask must be specified."); parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text"); parser.endGroup(); //! [add arguments] } bool configureApplicationSettings(std::map parsedArgs) { if (parsedArgs.size() == 0) return false; // parse, cast and set required arguments functionName = "Linear"; if (parsedArgs.count("function")) { functionName = us::any_cast(parsedArgs["function"]); } if (parsedArgs.count("formular")) { formular = us::any_cast(parsedArgs["formular"]); } inFilename = us::any_cast(parsedArgs["input"]); outFileName = us::any_cast(parsedArgs["output"]); verbose = false; if (parsedArgs.count("verbose")) { verbose = us::any_cast(parsedArgs["verbose"]); } roibased = false; if (parsedArgs.count("roibased")) { roibased = us::any_cast(parsedArgs["roibased"]); } if (parsedArgs.count("mask")) { maskFileName = us::any_cast(parsedArgs["mask"]); } return true; } void configureInitialParametersOfParameterizer(mitk::ModelParameterizerBase* parameterizer) { mitk::GenericParamModelParameterizer* genericParameterizer = dynamic_cast(parameterizer); if (genericParameterizer) { genericParameterizer->SetFunctionString(formular); } } mitk::ModelFitFunctorBase::Pointer createDefaultFitFunctor( const mitk::ModelParameterizerBase* parameterizer) { mitk::LevenbergMarquardtModelFitFunctor::Pointer fitFunctor = mitk::LevenbergMarquardtModelFitFunctor::New(); mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::Pointer chi2 = mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::New(); fitFunctor->RegisterEvaluationParameter("Chi^2", chi2); mitk::ModelBase::Pointer refModel = parameterizer->GenerateParameterizedModel(); ::itk::LevenbergMarquardtOptimizer::ScalesType scales; scales.SetSize(refModel->GetNumberOfParameters()); scales.Fill(1.0); fitFunctor->SetScales(scales); fitFunctor->SetDebugParameterMaps(true); return fitFunctor.GetPointer(); } template void generateModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& /*modelFitInfo*/, mitk::ParameterFitImageGeneratorBase::Pointer& generator) { mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = mitk::PixelBasedParameterFitImageGenerator::New(); typename TParameterizer::Pointer modelParameterizer = TParameterizer::New(); configureInitialParametersOfParameterizer(modelParameterizer); //Specify fitting strategy and criterion parameters mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer); //Parametrize fit generator fitGenerator->SetModelParameterizer(modelParameterizer); fitGenerator->SetMask(mask); fitGenerator->SetDynamicImage(image); fitGenerator->SetFitFunctor(fitFunctor); generator = fitGenerator.GetPointer(); } template void generateModelFit_ROIBased( mitk::modelFit::ModelFitInfo::Pointer& /*modelFitInfo*/, mitk::ParameterFitImageGeneratorBase::Pointer& generator) { mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator = mitk::ROIBasedParameterFitImageGenerator::New(); typename TParameterizer::Pointer modelParameterizer = TParameterizer::New(); configureInitialParametersOfParameterizer(modelParameterizer); //Compute ROI signal mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = mitk::MaskedDynamicImageStatisticsGenerator::New(); signalGenerator->SetMask(mask); signalGenerator->SetDynamicImage(image); signalGenerator->Generate(); mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean(); //Specify fitting strategy and criterion parameters mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer); //Parametrize fit generator fitGenerator->SetModelParameterizer(modelParameterizer); fitGenerator->SetMask(mask); fitGenerator->SetFitFunctor(fitFunctor); fitGenerator->SetSignal(roiSignal); fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(image)); generator = fitGenerator.GetPointer(); } void doFitting() { mitk::ParameterFitImageGeneratorBase::Pointer generator = nullptr; mitk::modelFit::ModelFitInfo::Pointer fitSession = nullptr; ::itk::CStyleCommand::Pointer command = ::itk::CStyleCommand::New(); command->SetCallback(onFitEvent); bool isLinearFactory = functionName == "Linear"; if (isLinearFactory) { std::cout << "Model: linear" << std::endl; if (!roibased) { generateModelFit_PixelBased(fitSession, generator); } else { generateModelFit_ROIBased(fitSession, generator); } } else { std::cout << "Model: generic (2 parameter)" << std::endl; if (!roibased) { generateModelFit_PixelBased(fitSession, generator); } else { generateModelFit_ROIBased(fitSession, generator); } } if (generator.IsNotNull() ) { std::cout << "Started fitting process..." << std::endl; generator->AddObserver(::itk::AnyEvent(), command); generator->Generate(); std::cout << std::endl << "Finished fitting process" << std::endl; mitk::storeModelFitGeneratorResults(outFileName, generator, fitSession); } else { mitkThrow() << "Fitting error! Could not initalize fitting job."; } } int main(int argc, char* argv[]) { mitkCommandLineParser parser; setupParser(parser); - mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (classic config)" }, { "MITK DICOM Reader" }); + mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (autoselect)" }, { "" }); const std::map& parsedArgs = parser.parseArguments(argc, argv); if (!configureApplicationSettings(parsedArgs)) { return EXIT_FAILURE; }; // Show a help message if (parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } //! [do processing] try { image = mitk::IOUtil::Load(inFilename, &readerFilterFunctor); std::cout << "Input: " << inFilename << std::endl; if (!maskFileName.empty()) { mask = mitk::IOUtil::Load(maskFileName, &readerFilterFunctor); std::cout << "Mask: " << maskFileName << std::endl; } else { std::cout << "Mask: none" << std::endl; } if (roibased && mask.IsNull()) { mitkThrow() << "Error. Cannot fit. Please specify mask if you select roi based fitting."; } std::cout << "Style: "; if (roibased) { std::cout << "ROI based"; } else { std::cout << "pixel based"; } std::cout << std::endl; doFitting(); std::cout << "Processing finished." << std::endl; return EXIT_SUCCESS; } catch (const itk::ExceptionObject& e) { MITK_ERROR << e.what(); return EXIT_FAILURE; } catch (const std::exception& e) { MITK_ERROR << e.what(); return EXIT_FAILURE; } catch (...) { MITK_ERROR << "Unexpected error encountered."; return EXIT_FAILURE; } } diff --git a/Modules/ModelFit/cmdapps/PixelDumpMiniApp.cpp b/Modules/ModelFit/cmdapps/PixelDumpMiniApp.cpp index 2c50a02d4b..d3323ed319 100644 --- a/Modules/ModelFit/cmdapps/PixelDumpMiniApp.cpp +++ b/Modules/ModelFit/cmdapps/PixelDumpMiniApp.cpp @@ -1,447 +1,447 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // std includes #include // itk includes #include "itksys/SystemTools.hxx" #include "itkImageRegionConstIteratorWithIndex.h" #include "itkCastImageFilter.h" #include "itkExtractImageFilter.h" // CTK includes #include "mitkCommandLineParser.h" // MITK includes #include #include #include #include "mitkImageAccessByItk.h" #include "mitkImageCast.h" mitkCommandLineParser::StringContainerType inFilenames; std::string outFileName; std::string maskFileName; mitkCommandLineParser::StringContainerType captions; using ImageVectorType = std::vector; ImageVectorType images; mitk::Image::Pointer mask; bool verbose(false); typedef itk::Image InternalImageType; typedef std::map InternalImageMapType; InternalImageMapType internalImages; itk::ImageRegion<3> relevantRegion; InternalImageType::PointType relevantOrigin; InternalImageType::SpacingType relevantSpacing; InternalImageType::DirectionType relevantDirection; typedef itk::Index<3> DumpIndexType; typedef std::vector DumpedValuesType; struct DumpIndexCompare { bool operator() (const DumpIndexType& lhs, const DumpIndexType& rhs) const { if (lhs[0] < rhs[0]) { return true; } else if (lhs[0] > rhs[0]) { return false; } if (lhs[1] < rhs[1]) { return true; } else if (lhs[1] > rhs[1]) { return false; } return lhs[2] < rhs[2]; } }; typedef std::map DumpPixelMapType; DumpPixelMapType dumpedPixels; void setupParser(mitkCommandLineParser& parser) { // set general information about your MiniApp parser.setCategory("Generic Analysis Tools"); parser.setTitle("Pixel Dumper"); parser.setDescription("MiniApp that allows to dump the pixel values of all passed files into a csv. The region of dumping can defined by a mask. All images (and mask) must have the same geometrie."); parser.setContributor("DKFZ MIC"); //! [create parser] //! [add arguments] // how should arguments be prefixed parser.setArgumentPrefix("--", "-"); // add each argument, unless specified otherwise each argument is optional // see mitkCommandLineParser::addArgument for more information parser.beginGroup("Required I/O parameters"); parser.addArgument( "inputs", "i", mitkCommandLineParser::StringList, "Input files", "list of the images that should be dumped.", us::Any(), false); parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file", "where to save the csv.", us::Any(), false, false, false, mitkCommandLineParser::Output); parser.endGroup(); parser.beginGroup("Optional parameters"); parser.addArgument( "mask", "m", mitkCommandLineParser::File, "Mask file", "Mask that defines the spatial image region that should be dumped. Must have the same geometry as the input images!", us::Any(), true, false, false, mitkCommandLineParser::Input); parser.addArgument( "captions", "c", mitkCommandLineParser::StringList, "Captions of image columns", "If provided the pixel columns of the csv will be named according to the passed values instead of using the image pathes. Number of images and names must be equal.", us::Any(), false); parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text"); parser.endGroup(); //! [add arguments] } bool configureApplicationSettings(std::map parsedArgs) { if (parsedArgs.size() == 0) return false; // parse, cast and set required arguments inFilenames = us::any_cast(parsedArgs["inputs"]); outFileName = us::any_cast(parsedArgs["output"]); if (parsedArgs.count("mask")) { maskFileName = us::any_cast(parsedArgs["mask"]); } captions = inFilenames; if (parsedArgs.count("captions")) { captions = us::any_cast(parsedArgs["captions"]); } return true; } template < typename TPixel, unsigned int VImageDimension > void ExtractRelevantInformation( const itk::Image< TPixel, VImageDimension > *image) { relevantRegion = image->GetLargestPossibleRegion(); relevantOrigin = image->GetOrigin(); relevantSpacing = image->GetSpacing(); relevantDirection = image->GetDirection(); } template < typename TPixel, unsigned int VImageDimension > void DoInternalImageConversion( const itk::Image< TPixel, VImageDimension > *image, InternalImageType::Pointer& internalImage) { typedef itk::Image< TPixel, VImageDimension > ImageType; //check if image fit to geometry // Make sure that spacing are the same typename ImageType::SpacingType imageSpacing = image->GetSpacing(); typename ImageType::PointType zeroPoint; zeroPoint.Fill(0.0); if ((zeroPoint + imageSpacing).SquaredEuclideanDistanceTo((zeroPoint + relevantSpacing)) > 1e-6) // for the dumper we are not as strict as mitk normally would be (mitk::eps) { mitkThrow() << "Images need to have same spacing! (Image spacing: " << imageSpacing << "; relevant spacing: " << relevantSpacing << ")"; } // Make sure that orientation of mask and image are the same typename ImageType::DirectionType imageDirection = image->GetDirection(); for (unsigned int i = 0; i < imageDirection.RowDimensions; ++i) { for (unsigned int j = 0; j < imageDirection.ColumnDimensions; ++j) { double differenceDirection = imageDirection[i][j] - relevantDirection[i][j]; if (fabs(differenceDirection) > 1e-6) // SD: 1e6 wird hier zum zweiten mal als Magic Number benutzt -> Konstante { // for the dumper we are not as strict as mitk normally would be (mitk::eps) mitkThrow() << "Images need to have same direction! (Image direction: " << imageDirection << "; relevant direction: " << relevantDirection << ")"; } } } // Make sure that origin of mask and image are the same typename ImageType::PointType imageOrigin = image->GetOrigin(); if (imageOrigin.SquaredEuclideanDistanceTo(relevantOrigin) > 1e-6) { // for the dumper we are not as strict as mitk normally would be (mitk::eps) mitkThrow() << "Image need to have same spacing! (Image spacing: " << imageSpacing << "; relevant spacing: " << relevantOrigin << ")"; } typename ImageType::RegionType imageRegion = image->GetLargestPossibleRegion(); if (!imageRegion.IsInside(relevantRegion) && imageRegion != relevantRegion) { mitkThrow() << "Images need to have same region! (Image region: " << imageRegion << "; relevant region: " << relevantRegion << ")"; } //convert to internal image typedef itk::ExtractImageFilter ExtractFilterType; typename ExtractFilterType::Pointer extractFilter = ExtractFilterType::New(); typedef itk::CastImageFilter CastFilterType; typename CastFilterType::Pointer castFilter = CastFilterType::New(); extractFilter->SetInput(image); extractFilter->SetExtractionRegion(relevantRegion); castFilter->SetInput(extractFilter->GetOutput()); castFilter->Update(); internalImage = castFilter->GetOutput(); } template < typename TPixel, unsigned int VImageDimension > void DoMaskedCollecting( const itk::Image< TPixel, VImageDimension > *image) { typedef itk::Image< TPixel, VImageDimension > ImageType; itk::ImageRegionConstIteratorWithIndex it(image, relevantRegion); it.GoToBegin(); while (!it.IsAtEnd()) { if (mask.IsNull() || it.Get() > 0) { DumpedValuesType values; const auto index = it.GetIndex(); for (auto& imagePos : internalImages) { double value = imagePos.second->GetPixel(index); values.push_back(value); } dumpedPixels.insert(std::make_pair(index, values)); } ++it; } } InternalImageMapType ConvertImageTimeSteps(mitk::Image* image) { InternalImageMapType map; InternalImageType::Pointer internalImage; for (unsigned int i = 0; i < image->GetTimeSteps(); ++i) { mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); imageTimeSelector->SetInput(image); imageTimeSelector->SetTimeNr(i); imageTimeSelector->UpdateLargestPossibleRegion(); mitk::Image::Pointer imageTimePoint = imageTimeSelector->GetOutput(); AccessFixedDimensionByItk_1(imageTimePoint, DoInternalImageConversion, 3, internalImage); std::stringstream stream; stream << "[" << i << "]"; map.insert(std::make_pair(stream.str(), internalImage)); } return map; } void doDumping() { if (mask.IsNotNull() && mask->GetTimeSteps() > 1) { std::cout << "Pixel Dumper: Selected mask has multiple timesteps. Only use first timestep to mask the pixel dumping." << std::endl; mitk::ImageTimeSelector::Pointer maskTimeSelector = mitk::ImageTimeSelector::New(); maskTimeSelector->SetInput(mask); maskTimeSelector->SetTimeNr(0); maskTimeSelector->UpdateLargestPossibleRegion(); mask = maskTimeSelector->GetOutput(); } try { if (mask.IsNotNull()) { // if mask exist, we use the mask because it could be a sub region. AccessFixedDimensionByItk(mask, ExtractRelevantInformation, 3); } else { AccessFixedDimensionByItk(images.front(), ExtractRelevantInformation, 3); } } catch (const std::exception& e) { std::cerr << "Error extracting image geometry. Error text: " << e.what(); throw; } for (unsigned int index = 0; index < images.size(); ++index) { try { InternalImageMapType conversionMap = ConvertImageTimeSteps(images[index]); if (conversionMap.size() == 1) { internalImages.insert(std::make_pair(captions[index], conversionMap.begin()->second)); } else if (conversionMap.size() > 1) { for (auto& pos : conversionMap) { std::stringstream namestream; namestream << captions[index] << " " << pos.first; internalImages.insert(std::make_pair(namestream.str(), pos.second)); } } } catch (const std::exception& e) { std::stringstream errorStr; errorStr << "Inconsistent image \"" << captions[index] << "\" will be excluded from the collection. Error: " << e.what(); std::cerr << errorStr.str() << std::endl; } } if (mask.IsNotNull()) { // if mask exist, we use the mask because it could be a sub region. AccessFixedDimensionByItk(mask, DoMaskedCollecting, 3); } else { AccessFixedDimensionByItk(images.front(), DoMaskedCollecting, 3); } } void storeCSV() { std::ofstream resultfile; resultfile.open(outFileName.c_str()); resultfile << "x,y,z"; for (auto aImage : internalImages) { resultfile << "," << aImage.first; } resultfile << std::endl; for (auto dumpPos : dumpedPixels) { resultfile << dumpPos.first[0] << "," << dumpPos.first[1] << "," << dumpPos.first[2]; for(auto d : dumpPos.second) { resultfile << "," << d; } resultfile << std::endl; } } int main(int argc, char* argv[]) { mitkCommandLineParser parser; setupParser(parser); const std::map& parsedArgs = parser.parseArguments(argc, argv); - mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (classic config)" }, { "MITK DICOM Reader" }); + mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (autoselect)" }, { "" }); if (!configureApplicationSettings(parsedArgs)) { return EXIT_FAILURE; }; // Show a help message if (parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } if (!captions.empty() && inFilenames.size() != captions.size()) { std::cerr << "Cannot dump images. Number of given captions does not equal number of given images."; return EXIT_FAILURE; }; //! [do processing] try { std::cout << "Load images:" << std::endl; for (auto path : inFilenames) { std::cout << "Input: " << path << std::endl; auto image = mitk::IOUtil::Load(path, &readerFilterFunctor); images.push_back(image); } if (!maskFileName.empty()) { mask = mitk::IOUtil::Load(maskFileName, &readerFilterFunctor); std::cout << "Mask: " << maskFileName << std::endl; } else { std::cout << "Mask: none" << std::endl; } doDumping(); storeCSV(); std::cout << "Processing finished." << std::endl; return EXIT_SUCCESS; } catch (const itk::ExceptionObject& e) { MITK_ERROR << e.what(); return EXIT_FAILURE; } catch (const std::exception& e) { MITK_ERROR << e.what(); return EXIT_FAILURE; } catch (...) { MITK_ERROR << "Unexpected error encountered."; return EXIT_FAILURE; } } diff --git a/Modules/OpenIGTLink/CMakeLists.txt b/Modules/OpenIGTLink/CMakeLists.txt index ac6c973d10..882e3a92f7 100644 --- a/Modules/OpenIGTLink/CMakeLists.txt +++ b/Modules/OpenIGTLink/CMakeLists.txt @@ -1,9 +1,8 @@ mitk_create_module( - SUBPROJECTS MITK-IGT DEPENDS MitkCore PACKAGE_DEPENDS PUBLIC OpenIGTLink INCLUDE_DIRS Filters DeviceSources ) add_subdirectory(Testing) diff --git a/Modules/Pharmacokinetics/cmdapps/CurveDescriptorMiniApp.cpp b/Modules/Pharmacokinetics/cmdapps/CurveDescriptorMiniApp.cpp index dd52eec7f8..df8257534f 100644 --- a/Modules/Pharmacokinetics/cmdapps/CurveDescriptorMiniApp.cpp +++ b/Modules/Pharmacokinetics/cmdapps/CurveDescriptorMiniApp.cpp @@ -1,242 +1,242 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // std includes #include // itk includes #include "itksys/SystemTools.hxx" // CTK includes #include "mitkCommandLineParser.h" // MITK includes #include #include #include #include #include #include #include #include #include std::string inFilename; std::string outFileName; std::string maskFileName; bool verbose(false); bool preview(false); mitk::Image::Pointer image; mitk::Image::Pointer mask; void onFitEvent(::itk::Object* caller, const itk::EventObject & event, void* /*data*/) { itk::ProgressEvent progressEvent; if (progressEvent.CheckEvent(&event)) { mitk::PixelBasedDescriptionParameterImageGenerator* castedReporter = dynamic_cast(caller); std::cout <GetProgress()*100 << "% "; } } void setupParser(mitkCommandLineParser& parser) { // set general information about your MiniApp parser.setCategory("Dynamic Data Analysis Tools"); parser.setTitle("Curve Descriptor"); parser.setDescription("MiniApp that allows to generate curve descriptor maps for dynamic image."); parser.setContributor("DKFZ MIC"); //! [create parser] //! [add arguments] // how should arguments be prefixed parser.setArgumentPrefix("--", "-"); // add each argument, unless specified otherwise each argument is optional // see mitkCommandLineParser::addArgument for more information parser.beginGroup("Required I/O parameters"); parser.addArgument( "input", "i", mitkCommandLineParser::File, "Input file", "input 3D+t image file", us::Any(), false, false, false, mitkCommandLineParser::Input); parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file template", "where to save the output parameter images. The specified path will be used as template to determine the format (via extension) and the name \"root\". For each parameter a suffix will be added to the name.", us::Any(), false, false, false, mitkCommandLineParser::Output); parser.endGroup(); parser.beginGroup("Optional parameters"); parser.addArgument( "mask", "m", mitkCommandLineParser::File, "Mask file", "Mask that defines the spatial image region that should be fitted. Must have the same geometry as the input image!", us::Any(), true, false, false, mitkCommandLineParser::Input); parser.addArgument( "verbose", "v", mitkCommandLineParser::Bool, "Verbose Output", "Whether to produce verbose output"); parser.addArgument( "preview", "p", mitkCommandLineParser::Bool, "Preview outputs", "The application previews the outputs (filename, type) it would produce with the current settings."); parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text"); parser.endGroup(); //! [add arguments] } bool configureApplicationSettings(std::map parsedArgs) { if (parsedArgs.size() == 0) return false; verbose = false; if (parsedArgs.count("verbose")) { verbose = us::any_cast(parsedArgs["verbose"]); } if (parsedArgs.count("mask")) { maskFileName = us::any_cast(parsedArgs["mask"]); } preview = false; if (parsedArgs.count("preview")) { preview = us::any_cast(parsedArgs["preview"]); } inFilename = us::any_cast(parsedArgs["input"]); outFileName = us::any_cast(parsedArgs["output"]); return true; } void ConfigureFunctor(mitk::CurveParameterFunctor* functor) { mitk::CurveDescriptionParameterBase::Pointer parameterFunction = mitk::AreaUnderTheCurveDescriptionParameter::New().GetPointer(); functor->RegisterDescriptionParameter("AUC", parameterFunction); parameterFunction = mitk::AreaUnderFirstMomentDescriptionParameter::New().GetPointer(); functor->RegisterDescriptionParameter("AUMC", parameterFunction); parameterFunction = mitk::MeanResidenceTimeDescriptionParameter::New().GetPointer(); functor->RegisterDescriptionParameter("MRT", parameterFunction); parameterFunction = mitk::TimeToPeakCurveDescriptionParameter::New().GetPointer(); functor->RegisterDescriptionParameter("TimeToPeak", parameterFunction); }; void doDescription() { mitk::PixelBasedDescriptionParameterImageGenerator::Pointer generator = mitk::PixelBasedDescriptionParameterImageGenerator::New(); mitk::CurveParameterFunctor::Pointer functor = mitk::CurveParameterFunctor::New(); ConfigureFunctor(functor); functor->SetGrid(mitk::ExtractTimeGrid(image)); generator->SetFunctor(functor); generator->SetDynamicImage(image); generator->SetMask(mask); ::itk::CStyleCommand::Pointer command = ::itk::CStyleCommand::New(); command->SetCallback(onFitEvent); std::cout << "Started curve descriptor computation process..." << std::endl; generator->AddObserver(::itk::AnyEvent(), command); generator->Generate(); std::cout << std::endl << "Finished computation process" << std::endl; for (auto imageIterator : generator->GetParameterImages()) { mitk::storeParameterResultImage(outFileName, imageIterator.first, imageIterator.second); } } void doPreview() { mitk::CurveParameterFunctor::Pointer functor = mitk::CurveParameterFunctor::New(); ConfigureFunctor(functor); auto pNames = functor->GetDescriptionParameterNames(); for (auto aName : pNames) { auto fullPath = mitk::generateModelFitResultImagePath(outFileName, aName); std::cout << "Store result parameter: " << aName << " -> " << fullPath << std::endl; } } int main(int argc, char* argv[]) { mitkCommandLineParser parser; setupParser(parser); - mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (classic config)" }, { "MITK DICOM Reader" }); + mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (autoselect)" }, { "" }); const std::map& parsedArgs = parser.parseArguments(argc, argv); if (!configureApplicationSettings(parsedArgs)) { return EXIT_FAILURE; }; // Show a help message if (parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } //! [do processing] try { if (preview) { doPreview(); } else { image = mitk::IOUtil::Load(inFilename, &readerFilterFunctor); std::cout << "Input: " << inFilename << std::endl; if (!maskFileName.empty()) { mask = mitk::IOUtil::Load(maskFileName, &readerFilterFunctor); std::cout << "Mask: " << maskFileName << std::endl; } else { std::cout << "Mask: none" << std::endl; } doDescription(); } std::cout << "Processing finished." << std::endl; return EXIT_SUCCESS; } catch (const itk::ExceptionObject& e) { MITK_ERROR << e.what(); return EXIT_FAILURE; } catch (const std::exception& e) { MITK_ERROR << e.what(); return EXIT_FAILURE; } catch (...) { MITK_ERROR << "Unexpected error encountered."; return EXIT_FAILURE; } } diff --git a/Modules/Pharmacokinetics/cmdapps/MRPerfusionMiniApp.cpp b/Modules/Pharmacokinetics/cmdapps/MRPerfusionMiniApp.cpp index 9fc08615b9..d871108746 100644 --- a/Modules/Pharmacokinetics/cmdapps/MRPerfusionMiniApp.cpp +++ b/Modules/Pharmacokinetics/cmdapps/MRPerfusionMiniApp.cpp @@ -1,890 +1,890 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // std includes #include // itk includes #include "itksys/SystemTools.hxx" // CTK includes #include "mitkCommandLineParser.h" // MITK includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include std::string inFilename; std::string outFileName; std::string maskFileName; std::string aifMaskFileName; std::string aifImageFileName; mitk::Image::Pointer image; mitk::Image::Pointer mask; mitk::Image::Pointer aifImage; mitk::Image::Pointer aifMask; bool useConstraints(false); bool verbose(false); bool roibased(false); bool preview(false); std::string modelName; float aifHematocritLevel(0); float brixInjectionTime(0); const std::string MODEL_NAME_2SL = "2SL"; const std::string MODEL_NAME_3SL = "3SL"; const std::string MODEL_NAME_descriptive = "descriptive"; const std::string MODEL_NAME_tofts = "tofts"; const std::string MODEL_NAME_2CX = "2CX"; void onFitEvent(::itk::Object* caller, const itk::EventObject & event, void* /*data*/) { itk::ProgressEvent progressEvent; if (progressEvent.CheckEvent(&event)) { mitk::ParameterFitImageGeneratorBase* castedReporter = dynamic_cast(caller); std::cout <GetProgress()*100 << "% "; } } void setupParser(mitkCommandLineParser& parser) { // set general information about your MiniApp parser.setCategory("Dynamic Data Analysis Tools"); parser.setTitle("MR Perfusion"); parser.setDescription("MiniApp that allows to fit MRI perfusion models and generates the according parameter maps. IMPORTANT!!!: The app assumes that the input images (signal and AIF) are concentration images. If your images do not hold this assumption, convert the image date before using this app (e.g. by using the signal-to-concentration-converter mini app."); parser.setContributor("DKFZ MIC"); //! [create parser] //! [add arguments] // how should arguments be prefixed parser.setArgumentPrefix("--", "-"); // add each argument, unless specified otherwise each argument is optional // see mitkCommandLineParser::addArgument for more information parser.beginGroup("Model parameters"); parser.addArgument( "model", "l", mitkCommandLineParser::String, "Model function", "Model that should be used to fit the concentration signal. Options are: \""+MODEL_NAME_descriptive+"\" (descriptive pharmacokinetic Brix model),\"" + MODEL_NAME_2SL + "\" (two step linear model),\""+MODEL_NAME_3SL+"\" (three step linear model), \""+MODEL_NAME_tofts+"\" (extended tofts model) or \""+MODEL_NAME_2CX+"\" (two compartment exchange model).", us::Any(std::string(MODEL_NAME_tofts))); parser.addArgument( "injectiontime", "j", mitkCommandLineParser::Float, "Injection time [min]", "Injection time of the bolus. This information is needed for the descriptive pharmacokinetic Brix model.", us::Any()); parser.endGroup(); parser.beginGroup("Required I/O parameters"); parser.addArgument( "input", "i", mitkCommandLineParser::File, "Input file", "input 3D+t image file", us::Any(), false, false, false, mitkCommandLineParser::Input); parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file template", "where to save the output parameter images. The specified path will be used as template to determine the format (via extension) and the name \"root\". For each parameter a suffix will be added to the name.", us::Any(), false, false, false, mitkCommandLineParser::Output); parser.endGroup(); parser.beginGroup("AIF parameters"); parser.addArgument( "aifmask", "n", mitkCommandLineParser::File, "AIF mask file", "Mask that defines the spatial image region that should be used as AIF for models that need one. Must have the same geometry as the AIF input image!", us::Any(), true, false, false, mitkCommandLineParser::Input); parser.addArgument( "aifimage", "a", mitkCommandLineParser::File, "AIF image file", "3D+t image that defines the image that containes the AIF signal. If this flag is not set and the model needs a AIF, the CLI will assume that the AIF is encoded in the normal image. Must have the same geometry as the AIF mask!", us::Any(), true, false, false, mitkCommandLineParser::Input); parser.addArgument( "hematocrit", "h", mitkCommandLineParser::Float, "Hematocrit Level", "Value needed for correct AIF computation. Only needed if model needs an AIF. Default value is 0.45.", us::Any(0.45)); parser.endGroup(); parser.beginGroup("Optional parameters"); parser.addArgument( "mask", "m", mitkCommandLineParser::File, "Mask file", "Mask that defines the spatial image region that should be fitted. Must have the same geometry as the input image!", us::Any(), true, false, false, mitkCommandLineParser::Input); parser.addArgument( "verbose", "v", mitkCommandLineParser::Bool, "Verbose Output", "Whether to produce verbose output"); parser.addArgument( "roibased", "r", mitkCommandLineParser::Bool, "Roi based fitting", "Will compute a mean intesity signal over the ROI before fitting it. If this mode is used a mask must be specified."); parser.addArgument( "constraints", "c", mitkCommandLineParser::Bool, "Constraints", "Indicates if constraints should be used for the fitting (if flag is set the default contraints will be used.).", us::Any(false)); parser.addArgument( "preview", "p", mitkCommandLineParser::Bool, "Preview outputs", "The application previews the outputs (filename, type) it would produce with the current settings."); parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text"); parser.endGroup(); //! [add arguments] } bool configureApplicationSettings(std::map parsedArgs) { if (parsedArgs.size() == 0) return false; // parse, cast and set required arguments modelName = MODEL_NAME_tofts; if (parsedArgs.count("model")) { modelName = us::any_cast(parsedArgs["model"]); } inFilename = us::any_cast(parsedArgs["input"]); outFileName = us::any_cast(parsedArgs["output"]); if (parsedArgs.count("mask")) { maskFileName = us::any_cast(parsedArgs["mask"]); } if (parsedArgs.count("aifimage")) { aifImageFileName = us::any_cast(parsedArgs["aifimage"]); } if (parsedArgs.count("aifmask")) { aifMaskFileName = us::any_cast(parsedArgs["aifmask"]); } verbose = false; if (parsedArgs.count("verbose")) { verbose = us::any_cast(parsedArgs["verbose"]); } preview = false; if (parsedArgs.count("preview")) { preview = us::any_cast(parsedArgs["preview"]); } roibased = false; if (parsedArgs.count("roibased")) { roibased = us::any_cast(parsedArgs["roibased"]); } useConstraints = false; if (parsedArgs.count("constraints")) { useConstraints = us::any_cast(parsedArgs["constraints"]); } aifHematocritLevel = 0.45; if (parsedArgs.count("hematocrit")) { aifHematocritLevel = us::any_cast(parsedArgs["hematocrit"]); } brixInjectionTime = 0.0; if (parsedArgs.count("injectiontime")) { brixInjectionTime = us::any_cast(parsedArgs["injectiontime"]); } return true; } mitk::ModelFitFunctorBase::Pointer createDefaultFitFunctor( const mitk::ModelParameterizerBase* parameterizer, const mitk::ModelFactoryBase* modelFactory) { mitk::LevenbergMarquardtModelFitFunctor::Pointer fitFunctor = mitk::LevenbergMarquardtModelFitFunctor::New(); mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::Pointer chi2 = mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::New(); fitFunctor->RegisterEvaluationParameter("Chi^2", chi2); if (useConstraints) { fitFunctor->SetConstraintChecker(modelFactory->CreateDefaultConstraints().GetPointer()); } mitk::ModelBase::Pointer refModel = parameterizer->GenerateParameterizedModel(); ::itk::LevenbergMarquardtOptimizer::ScalesType scales; scales.SetSize(refModel->GetNumberOfParameters()); scales.Fill(1.0); fitFunctor->SetScales(scales); fitFunctor->SetDebugParameterMaps(true); return fitFunctor.GetPointer(); } /**Helper that ensures that the mask (if it exists) is always 3D image. If the mask is originally an 4D image, the first time step will be used.*/ mitk::Image::Pointer getMask3D() { mitk::Image::Pointer result; if (mask.IsNotNull()) { result = mask; //mask settings if (mask->GetTimeSteps() > 1) { MITK_INFO << "Selected mask has multiple timesteps. Only use first timestep to mask model fit."; mitk::ImageTimeSelector::Pointer maskedImageTimeSelector = mitk::ImageTimeSelector::New(); maskedImageTimeSelector->SetInput(mask); maskedImageTimeSelector->SetTimeNr(0); maskedImageTimeSelector->UpdateLargestPossibleRegion(); result = maskedImageTimeSelector->GetOutput(); } } return result; } void getAIF(mitk::AIFBasedModelBase::AterialInputFunctionType& aif, mitk::AIFBasedModelBase::AterialInputFunctionType& aifTimeGrid) { if (aifMask.IsNotNull()) { aif.clear(); aifTimeGrid.clear(); mitk::AterialInputFunctionGenerator::Pointer aifGenerator = mitk::AterialInputFunctionGenerator::New(); //Hematocrit level aifGenerator->SetHCL(aifHematocritLevel); std::cout << "AIF hematocrit level: " << aifHematocritLevel << std::endl; mitk::Image::Pointer selectedAIFMask = aifMask; //mask settings if (aifMask->GetTimeSteps() > 1) { MITK_INFO << "Selected AIF mask has multiple timesteps. Only use first timestep to mask model fit."; mitk::ImageTimeSelector::Pointer maskedImageTimeSelector = mitk::ImageTimeSelector::New(); maskedImageTimeSelector->SetInput(aifMask); maskedImageTimeSelector->SetTimeNr(0); maskedImageTimeSelector->UpdateLargestPossibleRegion(); aifMask = maskedImageTimeSelector->GetOutput(); } aifGenerator->SetMask(aifMask); mitk::Image::Pointer selectedAIFImage = image; //image settings if (aifImage.IsNotNull()) { selectedAIFImage = aifImage; } aifGenerator->SetDynamicImage(selectedAIFImage); aif = aifGenerator->GetAterialInputFunction(); aifTimeGrid = aifGenerator->GetAterialInputFunctionTimeGrid(); } else { mitkThrow() << "Cannot generate AIF. AIF mask was not specified or correctly loaded."; } } void generateDescriptiveBrixModel_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) { mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = mitk::PixelBasedParameterFitImageGenerator::New(); mitk::DescriptivePharmacokineticBrixModelParameterizer::Pointer modelParameterizer = mitk::DescriptivePharmacokineticBrixModelParameterizer::New(); mitk::Image::Pointer mask3D = getMask3D(); //Model configuration (static parameters) can be done now modelParameterizer->SetTau(brixInjectionTime); std::cout << "Injection time [min]: " << brixInjectionTime << std::endl; mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); imageTimeSelector->SetInput(image); imageTimeSelector->SetTimeNr(0); imageTimeSelector->UpdateLargestPossibleRegion(); mitk::DescriptivePharmacokineticBrixModelParameterizer::BaseImageType::Pointer baseImage; mitk::CastToItkImage(imageTimeSelector->GetOutput(), baseImage); modelParameterizer->SetBaseImage(baseImage); //Specify fitting strategy and criterion parameters mitk::ModelFactoryBase::Pointer factory = mitk::DescriptivePharmacokineticBrixModelFactory::New().GetPointer(); mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory); //Parametrize fit generator fitGenerator->SetModelParameterizer(modelParameterizer); std::string roiUID = ""; if (mask3D.IsNotNull()) { fitGenerator->SetMask(mask3D); roiUID = mask->GetUID(); } fitGenerator->SetDynamicImage(image); fitGenerator->SetFitFunctor(fitFunctor); generator = fitGenerator.GetPointer(); //Create model info modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, image, mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED(), roiUID); } void generateDescriptiveBrixModel_ROIBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) { mitk::Image::Pointer mask3D = getMask3D(); if (mask3D.IsNull()) { return; } mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator = mitk::ROIBasedParameterFitImageGenerator::New(); mitk::DescriptivePharmacokineticBrixModelValueBasedParameterizer::Pointer modelParameterizer = mitk::DescriptivePharmacokineticBrixModelValueBasedParameterizer::New(); //Compute ROI signal mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = mitk::MaskedDynamicImageStatisticsGenerator::New(); signalGenerator->SetMask(mask3D); signalGenerator->SetDynamicImage(image); signalGenerator->Generate(); mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean(); //Model configuration (static parameters) can be done now modelParameterizer->SetTau(brixInjectionTime); std::cout << "Injection time [min]: " << brixInjectionTime << std::endl; modelParameterizer->SetBaseValue(roiSignal[0]); //Specify fitting strategy and criterion parameters mitk::ModelFactoryBase::Pointer factory = mitk::DescriptivePharmacokineticBrixModelFactory::New().GetPointer(); mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory); //Parametrize fit generator fitGenerator->SetModelParameterizer(modelParameterizer); fitGenerator->SetMask(mask3D); fitGenerator->SetFitFunctor(fitFunctor); fitGenerator->SetSignal(roiSignal); fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(image)); generator = fitGenerator.GetPointer(); std::string roiUID = mask->GetUID(); //Create model info modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, image, mitk::ModelFitConstants::FIT_TYPE_VALUE_ROIBASED(), roiUID); mitk::ScalarListLookupTable::ValueType infoSignal; for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos = roiSignal.begin(); pos != roiSignal.end(); ++pos) { infoSignal.push_back(*pos); } modelFitInfo->inputData.SetTableValue("ROI", infoSignal); } template void GenerateLinearModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) { mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = mitk::PixelBasedParameterFitImageGenerator::New(); typename TParameterizer::Pointer modelParameterizer = TParameterizer::New(); mitk::Image::Pointer mask3D = getMask3D(); //Specify fitting strategy and criterion parameters mitk::ModelFactoryBase::Pointer factory = TFactory::New().GetPointer(); mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory); //Parametrize fit generator fitGenerator->SetModelParameterizer(modelParameterizer); std::string roiUID = ""; if (mask3D.IsNotNull()) { fitGenerator->SetMask(mask3D); roiUID = mask->GetUID(); } fitGenerator->SetDynamicImage(image); fitGenerator->SetFitFunctor(fitFunctor); generator = fitGenerator.GetPointer(); //Create model info modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, image, mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED(), roiUID); } template void GenerateLinearModelFit_ROIBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) { mitk::Image::Pointer mask3D = getMask3D(); if (mask3D.IsNull()) { return; } mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator = mitk::ROIBasedParameterFitImageGenerator::New(); typename TParameterizer::Pointer modelParameterizer = TParameterizer::New(); //Compute ROI signal mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = mitk::MaskedDynamicImageStatisticsGenerator::New(); signalGenerator->SetMask(mask3D); signalGenerator->SetDynamicImage(image); signalGenerator->Generate(); mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean(); //Specify fitting strategy and criterion parameters mitk::ModelFactoryBase::Pointer factory = TFactory::New().GetPointer(); mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory); //Parametrize fit generator fitGenerator->SetModelParameterizer(modelParameterizer); fitGenerator->SetMask(mask3D); fitGenerator->SetFitFunctor(fitFunctor); fitGenerator->SetSignal(roiSignal); fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(image)); generator = fitGenerator.GetPointer(); std::string roiUID = mask->GetUID(); //Create model info modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, image, mitk::ModelFitConstants::FIT_TYPE_VALUE_ROIBASED(), roiUID); mitk::ScalarListLookupTable::ValueType infoSignal; for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos = roiSignal.begin(); pos != roiSignal.end(); ++pos) { infoSignal.push_back(*pos); } modelFitInfo->inputData.SetTableValue("ROI", infoSignal); } template void generateAIFbasedModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) { mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = mitk::PixelBasedParameterFitImageGenerator::New(); typename TParameterizer::Pointer modelParameterizer = TParameterizer::New(); mitk::AIFBasedModelBase::AterialInputFunctionType aif; mitk::AIFBasedModelBase::AterialInputFunctionType aifTimeGrid; getAIF(aif, aifTimeGrid); modelParameterizer->SetAIF(aif); modelParameterizer->SetAIFTimeGrid(aifTimeGrid); mitk::Image::Pointer mask3D = getMask3D(); //Specify fitting strategy and criterion parameters mitk::ModelFactoryBase::Pointer factory = TFactory::New().GetPointer(); mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory); //Parametrize fit generator fitGenerator->SetModelParameterizer(modelParameterizer); std::string roiUID = ""; if (mask3D.IsNotNull()) { fitGenerator->SetMask(mask3D); roiUID = mask->GetUID(); } fitGenerator->SetDynamicImage(image); fitGenerator->SetFitFunctor(fitFunctor); generator = fitGenerator.GetPointer(); //Create model info modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, image, mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED(), roiUID); mitk::ScalarListLookupTable::ValueType infoSignal; for (mitk::AIFBasedModelBase::AterialInputFunctionType::const_iterator pos = aif.begin(); pos != aif.end(); ++pos) { infoSignal.push_back(*pos); } modelFitInfo->inputData.SetTableValue("AIF", infoSignal); } template void generateAIFbasedModelFit_ROIBased( mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) { mitk::Image::Pointer mask3D = getMask3D(); if (mask3D.IsNull()) { return; } mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator = mitk::ROIBasedParameterFitImageGenerator::New(); typename TParameterizer::Pointer modelParameterizer = TParameterizer::New(); mitk::AIFBasedModelBase::AterialInputFunctionType aif; mitk::AIFBasedModelBase::AterialInputFunctionType aifTimeGrid; getAIF(aif, aifTimeGrid); modelParameterizer->SetAIF(aif); modelParameterizer->SetAIFTimeGrid(aifTimeGrid); //Compute ROI signal mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = mitk::MaskedDynamicImageStatisticsGenerator::New(); signalGenerator->SetMask(mask3D); signalGenerator->SetDynamicImage(image); signalGenerator->Generate(); mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean(); //Specify fitting strategy and criterion parameters mitk::ModelFactoryBase::Pointer factory = TFactory::New().GetPointer(); mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory); //Parametrize fit generator fitGenerator->SetModelParameterizer(modelParameterizer); fitGenerator->SetMask(mask3D); fitGenerator->SetFitFunctor(fitFunctor); fitGenerator->SetSignal(roiSignal); fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(image)); generator = fitGenerator.GetPointer(); std::string roiUID = mask->GetUID(); //Create model info modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, image, mitk::ModelFitConstants::FIT_TYPE_VALUE_ROIBASED(), roiUID); mitk::ScalarListLookupTable::ValueType infoSignal; for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos = roiSignal.begin(); pos != roiSignal.end(); ++pos) { infoSignal.push_back(*pos); } modelFitInfo->inputData.SetTableValue("ROI", infoSignal); infoSignal.clear(); for (mitk::AIFBasedModelBase::AterialInputFunctionType::const_iterator pos = aif.begin(); pos != aif.end(); ++pos) { infoSignal.push_back(*pos); } modelFitInfo->inputData.SetTableValue("AIF", infoSignal); } void storeResultImage(const std::string& name, mitk::Image* image, mitk::modelFit::Parameter::Type nodeType, const mitk::modelFit::ModelFitInfo* modelFitInfo) { mitk::modelFit::SetModelFitDataProperties(image, name, nodeType, modelFitInfo); std::string ext = ::itksys::SystemTools::GetFilenameLastExtension(outFileName); std::string dir = itksys::SystemTools::GetFilenamePath(outFileName); dir = itksys::SystemTools::ConvertToOutputPath(dir); std::string rootName = itksys::SystemTools::GetFilenameWithoutLastExtension(outFileName); std::string fileName = rootName + "_" + name + ext; std::vector pathElements; pathElements.push_back(dir); pathElements.push_back(fileName); std::string fullOutPath = itksys::SystemTools::ConvertToOutputPath(dir + "/" + fileName); mitk::IOUtil::Save(image, fullOutPath); std::cout << "Store result (parameter: "<(fitSession, generator); } else { GenerateLinearModelFit_ROIBased(fitSession, generator); } } else if (is2SLFactory) { std::cout << "Model: two step linear model" << std::endl; if (!roibased) { GenerateLinearModelFit_PixelBased(fitSession, generator); } else { GenerateLinearModelFit_ROIBased(fitSession, generator); } } else if (isToftsFactory) { std::cout << "Model: extended tofts model" << std::endl; if (!roibased) { generateAIFbasedModelFit_PixelBased(fitSession, generator); } else { generateAIFbasedModelFit_ROIBased(fitSession, generator); } } else if (is2CXMFactory) { std::cout << "Model: two compartment exchange model" << std::endl; if (!roibased) { generateAIFbasedModelFit_PixelBased(fitSession, generator); } else { generateAIFbasedModelFit_ROIBased(fitSession, generator); } } else { std::cerr << "ERROR. Model flag is unknown. Given flag: " << modelName << std::endl; } } void doFitting() { mitk::ParameterFitImageGeneratorBase::Pointer generator = nullptr; mitk::modelFit::ModelFitInfo::Pointer fitSession = nullptr; ::itk::CStyleCommand::Pointer command = ::itk::CStyleCommand::New(); command->SetCallback(onFitEvent); createFitGenerator(fitSession, generator); if (generator.IsNotNull() ) { std::cout << "Started fitting process..." << std::endl; generator->AddObserver(::itk::AnyEvent(), command); generator->Generate(); std::cout << std::endl << "Finished fitting process" << std::endl; mitk::storeModelFitGeneratorResults(outFileName, generator, fitSession); } else { mitkThrow() << "Fitting error! Could not initialize fitting job."; } } void doPreview() { mitk::ParameterFitImageGeneratorBase::Pointer generator = nullptr; mitk::modelFit::ModelFitInfo::Pointer fitSession = nullptr; createFitGenerator(fitSession, generator); if (generator.IsNotNull()) { mitk::previewModelFitGeneratorResults(outFileName, generator); } else { mitkThrow() << "Fitting error! Could not initialize fitting job."; } } int main(int argc, char* argv[]) { mitkCommandLineParser parser; setupParser(parser); const std::map& parsedArgs = parser.parseArguments(argc, argv); - mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (classic config)" }, { "MITK DICOM Reader" }); + mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (autoselect)" }, { "" }); if (!configureApplicationSettings(parsedArgs)) { return EXIT_FAILURE; }; // Show a help message if (parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } //! [do processing] try { image = mitk::IOUtil::Load(inFilename, &readerFilterFunctor); std::cout << "Input: " << inFilename << std::endl; if (!maskFileName.empty()) { mask = mitk::IOUtil::Load(maskFileName, &readerFilterFunctor); std::cout << "Mask: " << maskFileName << std::endl; } else { std::cout << "Mask: none" << std::endl; } if (modelName != MODEL_NAME_descriptive && modelName != MODEL_NAME_3SL && MODEL_NAME_2SL != modelName) { if (!aifMaskFileName.empty()) { aifMask = mitk::IOUtil::Load(aifMaskFileName, &readerFilterFunctor); std::cout << "AIF mask: " << aifMaskFileName << std::endl; } else { mitkThrow() << "Error. Cannot fit. Choosen model needs an AIF. Please specify AIF mask (--aifmask)."; } if (!aifImageFileName.empty()) { aifImage = mitk::IOUtil::Load(aifImageFileName, &readerFilterFunctor); std::cout << "AIF image: " << aifImageFileName << std::endl; } else { std::cout << "AIF image: none (using signal image)" << std::endl; } } if (roibased && mask.IsNull()) { mitkThrow() << "Error. Cannot fit. Please specify mask if you select roi based fitting."; } std::cout << "Style: "; if (roibased) { std::cout << "ROI based"; } else { std::cout << "pixel based"; } std::cout << std::endl; if (preview) { doPreview(); } else { doFitting(); } std::cout << "Processing finished." << std::endl; return EXIT_SUCCESS; } catch (const itk::ExceptionObject& e) { MITK_ERROR << e.what(); return EXIT_FAILURE; } catch (const std::exception& e) { MITK_ERROR << e.what(); return EXIT_FAILURE; } catch (...) { MITK_ERROR << "Unexpected error encountered."; return EXIT_FAILURE; } } diff --git a/Modules/Pharmacokinetics/cmdapps/MRSignal2ConcentrationMiniApp.cpp b/Modules/Pharmacokinetics/cmdapps/MRSignal2ConcentrationMiniApp.cpp index bd517b3abb..c9057a5bc8 100644 --- a/Modules/Pharmacokinetics/cmdapps/MRSignal2ConcentrationMiniApp.cpp +++ b/Modules/Pharmacokinetics/cmdapps/MRSignal2ConcentrationMiniApp.cpp @@ -1,287 +1,287 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // std includes #include // itk includes #include "itksys/SystemTools.hxx" // CTK includes #include "mitkCommandLineParser.h" // MITK includes #include #include #include #include #include std::string inFilename; std::string outFileName; mitk::Image::Pointer image; bool verbose(false); bool t1_absolute(false); bool t1_relative(false); bool t1_flash(false); bool t2(false); float k(1.0); float te(0); float rec_time(0); float relaxivity(0); float rel_time(0); void setupParser(mitkCommandLineParser& parser) { // set general information about your MiniApp parser.setCategory("Dynamic Data Analysis Tools"); parser.setTitle("MR Signal to Concentration Converter"); parser.setDescription("MiniApp that allows to convert a T1 or T2 signal image into a concentration image for perfusion analysis."); parser.setContributor("DKFZ MIC"); //! [create parser] //! [add arguments] // how should arguments be prefixed parser.setArgumentPrefix("--", "-"); // add each argument, unless specified otherwise each argument is optional // see mitkCommandLineParser::addArgument for more information parser.beginGroup("Required I/O parameters"); parser.addArgument( "input", "i", mitkCommandLineParser::File, "Input file", "input 3D+t image file", us::Any(), false, false, false, mitkCommandLineParser::Input); parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file", "where to save the output concentration image.", us::Any(), false, false, false, mitkCommandLineParser::Output); parser.endGroup(); parser.beginGroup("Conversion parameters"); parser.addArgument( "t1-absolute", "", mitkCommandLineParser::Bool, "T1 absolute signal enhancement", "Activate conversion for T1 absolute signal enhancement."); parser.addArgument( "t1-relative", "", mitkCommandLineParser::Bool, "T1 relative signal enhancement", "Activate conversion for T1 relative signal enhancement."); parser.addArgument( "t1-flash", "", mitkCommandLineParser::Bool, "T1 turbo flash", "Activate specific conversion for T1 turbo flash sequences."); parser.addArgument( "t2", "", mitkCommandLineParser::Bool, "T2 signal conversion", "Activate conversion for T2 signal enhancement to concentration."); parser.addArgument( "k", "k", mitkCommandLineParser::Float, "Conversion factor k", "Needed for the following conversion modes: T1-absolute, T1-relative, T2. Default value is 1.", us::Any(1)); parser.addArgument( "recovery-time", "", mitkCommandLineParser::Float, "Recovery time", "Needed for the following conversion modes: T1-flash."); parser.addArgument( "relaxivity", "", mitkCommandLineParser::Float, "Relaxivity", "Needed for the following conversion modes: T1-flash."); parser.addArgument( "relaxation-time", "", mitkCommandLineParser::Float, "Relaxation time", "Needed for the following conversion modes: T1-flash."); parser.addArgument( "te", "", mitkCommandLineParser::Float, "Echo time TE", "Needed for the following conversion modes: T2.", us::Any(1)); parser.beginGroup("Optional parameters"); parser.addArgument( "verbose", "v", mitkCommandLineParser::Bool, "Verbose Output", "Whether to produce verbose output"); parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text"); parser.endGroup(); //! [add arguments] } bool configureApplicationSettings(std::map parsedArgs) { if (parsedArgs.size() == 0) return false; inFilename = us::any_cast(parsedArgs["input"]); outFileName = us::any_cast(parsedArgs["output"]); verbose = false; if (parsedArgs.count("verbose")) { verbose = us::any_cast(parsedArgs["verbose"]); } t1_absolute = false; if (parsedArgs.count("t1-absolute")) { t1_absolute = us::any_cast(parsedArgs["t1-absolute"]); } t1_relative = false; if (parsedArgs.count("t1-relative")) { t1_relative = us::any_cast(parsedArgs["t1-relative"]); } t1_flash = false; if (parsedArgs.count("t1-flash")) { t1_flash = us::any_cast(parsedArgs["t1-flash"]); } t2 = false; if (parsedArgs.count("t2")) { t2 = us::any_cast(parsedArgs["t2"]); } k = 0.0; if (parsedArgs.count("k")) { k = us::any_cast(parsedArgs["k"]); } relaxivity = 0.0; if (parsedArgs.count("relaxivity")) { relaxivity = us::any_cast(parsedArgs["relaxivity"]); } rec_time = 0.0; if (parsedArgs.count("recovery-time")) { rec_time = us::any_cast(parsedArgs["recovery-time"]); } rel_time = 0.0; if (parsedArgs.count("relaxation-time")) { rel_time = us::any_cast(parsedArgs["relaxation-time"]); } te = 0.0; if (parsedArgs.count("te")) { te = us::any_cast(parsedArgs["te"]); } //consistency checks int modeCount = 0; if (t1_absolute) ++modeCount; if (t1_flash) ++modeCount; if (t1_relative) ++modeCount; if (t2) ++modeCount; if (modeCount==0) { mitkThrow() << "Invalid program call. Please select the type of conversion."; } if (modeCount >1) { mitkThrow() << "Invalid program call. Please select only ONE type of conversion."; } if (!k && (t2 || t1_absolute || t1_relative)) { mitkThrow() << "Invalid program call. Please set 'k', if you use t1-absolute, t1-relative or t2."; } if (!te && t2) { mitkThrow() << "Invalid program call. Please set 'te', if you use t2 mode."; } if ((!rec_time||!rel_time||!relaxivity) && t1_flash) { mitkThrow() << "Invalid program call. Please set 'recovery-time', 'relaxation-time' and 'relaxivity', if you use t1-flash mode."; } return true; } void doConversion() { mitk::ConcentrationCurveGenerator::Pointer concentrationGen = mitk::ConcentrationCurveGenerator::New(); concentrationGen->SetDynamicImage(image); concentrationGen->SetisTurboFlashSequence(t1_flash); concentrationGen->SetAbsoluteSignalEnhancement(t1_absolute); concentrationGen->SetRelativeSignalEnhancement(t1_relative); concentrationGen->SetisT2weightedImage(t2); if (t1_flash) { concentrationGen->SetRecoveryTime(rec_time); concentrationGen->SetRelaxationTime(rel_time); concentrationGen->SetRelaxivity(relaxivity); } else if (t2) { concentrationGen->SetT2Factor(k); concentrationGen->SetT2EchoTime(te); } else { concentrationGen->SetFactor(k); } mitk::Image::Pointer concentrationImage = concentrationGen->GetConvertedImage(); mitk::IOUtil::Save(concentrationImage, outFileName); std::cout << "Store result: " << outFileName << std::endl; } int main(int argc, char* argv[]) { mitkCommandLineParser parser; setupParser(parser); const std::map& parsedArgs = parser.parseArguments(argc, argv); if (!configureApplicationSettings(parsedArgs)) { return EXIT_FAILURE; }; - mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (classic config)" }, { "MITK DICOM Reader" }); + mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (autoselect)" }, { "" }); // Show a help message if (parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } //! [do processing] try { image = mitk::IOUtil::Load(inFilename, &readerFilterFunctor); std::cout << "Input: " << inFilename << std::endl; doConversion(); std::cout << "Processing finished." << std::endl; return EXIT_SUCCESS; } catch (const itk::ExceptionObject& e) { MITK_ERROR << e.what(); return EXIT_FAILURE; } catch (const std::exception& e) { MITK_ERROR << e.what(); return EXIT_FAILURE; } catch (...) { MITK_ERROR << "Unexpected error encountered."; return EXIT_FAILURE; } } diff --git a/Modules/QtWidgets/CMakeLists.txt b/Modules/QtWidgets/CMakeLists.txt index 08c2333393..1938494ee8 100644 --- a/Modules/QtWidgets/CMakeLists.txt +++ b/Modules/QtWidgets/CMakeLists.txt @@ -1,9 +1,8 @@ MITK_CREATE_MODULE( INCLUDE_DIRS PRIVATE resource # for xpm includes DEPENDS MitkPlanarFigure MitkAnnotation PACKAGE_DEPENDS PUBLIC ITK|ITKIOImageBase VTK|vtkGUISupportQt+vtkRenderingQt Qt5|Widgets+OpenGL+Core - SUBPROJECTS MITK-CoreUI ) add_subdirectory(test) diff --git a/Modules/SceneSerialization/test/CMakeLists.txt b/Modules/SceneSerialization/test/CMakeLists.txt index 07a93f524e..62a7032a54 100644 --- a/Modules/SceneSerialization/test/CMakeLists.txt +++ b/Modules/SceneSerialization/test/CMakeLists.txt @@ -1,25 +1,32 @@ -MITK_CREATE_MODULE_TESTS(LABELS MITK-Modules) +MITK_CREATE_MODULE_TESTS() if(TARGET ${TESTDRIVER}) if(BUILD_TESTING AND MODULE_IS_ENABLED) add_test(mitkSceneIOTest_Pic3D.nrrd_binary.stl ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} mitkSceneIOTest ${MITK_DATA_DIR}/Pic3D.nrrd ${MITK_DATA_DIR}/binary.stl ) - set_property(TEST mitkSceneIOTest_Pic3D.nrrd_binary.stl PROPERTY LABELS MITK-Modules) + + mitkFunctionGetLibrarySearchPaths(MITK_RUNTIME_PATH_RELEASE release RELEASE) + mitkFunctionGetLibrarySearchPaths(MITK_RUNTIME_PATH_DEBUG debug DEBUG) + set(test_env_path ${MITK_RUNTIME_PATH_RELEASE} ${MITK_RUNTIME_PATH_DEBUG} $ENV{PATH}) + list(REMOVE_DUPLICATES test_env_path) + string (REGEX REPLACE "\;" "\\\;" test_env_path "${test_env_path}") + set_property(TEST mitkSceneIOTest_Pic3D.nrrd_binary.stl APPEND PROPERTY ENVIRONMENT "PATH=${test_env_path}") + set_property(TEST mitkSceneIOTest_Pic3D.nrrd_binary.stl PROPERTY SKIP_RETURN_CODE 77) mitkAddCustomModuleTest(mitkSceneIOCompatibility_NoRainbowCT mitkSceneIOCompatibilityTest ${MITK_DATA_DIR}/RenderingTestData/SceneFiles/rainbows-post-17547.mitk # scene to load -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/rainbows-post-17547.png) # reference rendering if (FALSE) # fix not yet integrated mitkAddCustomModuleTest(mitkSceneIOCompatibility_SurfaceIntLineWidth mitkSceneIOCompatibilityTest ${MITK_DATA_DIR}/RenderingTestData/SceneFiles/surface-pre-18528.mitk # scene to load -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/surface-pre-18528.png) # reference rendering endif() endif() endif() diff --git a/Modules/Segmentation/Interactions/mitkSegmentationInteractor.cpp b/Modules/Segmentation/Interactions/mitkSegmentationInteractor.cpp index bdb6497405..4aec82aba5 100644 --- a/Modules/Segmentation/Interactions/mitkSegmentationInteractor.cpp +++ b/Modules/Segmentation/Interactions/mitkSegmentationInteractor.cpp @@ -1,61 +1,63 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkSegmentationInteractor.h" #include "mitkInteractionPositionEvent.h" #include "mitkLabelSetImage.h" #include "mitkToolManager.h" #include "mitkToolManagerProvider.h" #include #include void mitk::SegmentationInteractor::ConnectActionsAndFunctions() { Superclass::ConnectActionsAndFunctions(); // CONNECT_FUNCTION("change_active_label", ChangeActiveLabel); } bool mitk::SegmentationInteractor::ChangeActiveLabel(StateMachineAction *, InteractionEvent *interactionEvent) { BaseRenderer::Pointer sender = interactionEvent->GetSender(); auto *positionEvent = static_cast(interactionEvent); // MLI TODO // m_LastDisplayCoordinate = m_CurrentDisplayCoordinate; // m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); - mitk::ToolManager *toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); + auto *toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager( + mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION); + assert(toolManager); DataNode *workingNode(toolManager->GetWorkingData(0)); if (workingNode) { auto *workingImage = dynamic_cast(workingNode->GetData()); assert(workingImage); int timestep = positionEvent->GetSender()->GetTimeStep(); int pixelValue = static_cast(workingImage->GetPixelValueByWorldCoordinate(positionEvent->GetPositionInWorld(), timestep)); workingImage->GetActiveLabelSet()->SetActiveLabel(pixelValue); // can be the background // Call Events // workingImage->ActiveLabelEvent.Send(pixelValue); // MLI TODO // toolManager->WorkingDataModified.Send(); } RenderingManager::GetInstance()->RequestUpdateAll(); return true; } diff --git a/Modules/Segmentation/Interactions/mitkSegmentationInteractor.h b/Modules/Segmentation/Interactions/mitkSegmentationInteractor.h index 700f51751a..b5fcb1f559 100644 --- a/Modules/Segmentation/Interactions/mitkSegmentationInteractor.h +++ b/Modules/Segmentation/Interactions/mitkSegmentationInteractor.h @@ -1,51 +1,51 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkSegmentationInteractor_h #define mitkSegmentationInteractor_h #include "MitkSegmentationExports.h" #include "mitkDisplayInteractor.h" namespace mitk { /** *\class SegmentationInteractor - *@brief Observer that adds interaction with a segmentation session to the default display interaction. + *@brief Observer that adds interaction with a multi-label segmentation session to the default display interaction. * * At the moment, this includes changing the active label. * * @ingroup Interaction **/ class MITKSEGMENTATION_EXPORT SegmentationInteractor : public DisplayInteractor { public: mitkClassMacro(SegmentationInteractor, DisplayInteractor); itkNewMacro(Self); protected : SegmentationInteractor(){}; ~SegmentationInteractor() override{}; /** * Derived function. * Connects the action names used in the state machine pattern with functions implemented within * this InteractionEventObserver. This is only necessary here because the events are processed by the state machine. */ void ConnectActionsAndFunctions() override; /** * Changes the active label. */ bool ChangeActiveLabel(StateMachineAction *, InteractionEvent *); }; } #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitkMaskStampWidget.h b/Modules/SegmentationUI/Qmitk/QmitkMaskStampWidget.h index 456a6f1cc4..e75f8c8adf 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkMaskStampWidget.h +++ b/Modules/SegmentationUI/Qmitk/QmitkMaskStampWidget.h @@ -1,59 +1,61 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef QmitkMaskStampWidget_h_Included #define QmitkMaskStampWidget_h_Included #include "MitkSegmentationUIExports.h" #include "mitkDataNode.h" #include #include "ui_QmitkMaskStampWidgetGUIControls.h" namespace mitk { class ToolManager; } /** \brief GUI for mask stamp functionality + This class uses the mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION context. + \ingroup ToolManagerEtAl \ingroup Widgets */ class MITKSEGMENTATIONUI_EXPORT QmitkMaskStampWidget : public QWidget { Q_OBJECT public: QmitkMaskStampWidget(QWidget *parent = nullptr, const char *name = nullptr); ~QmitkMaskStampWidget() override; void SetDataStorage(mitk::DataStorage *storage); protected slots: void OnShowInformation(bool); void OnStamp(); private: mitk::ToolManager *m_ToolManager; mitk::DataStorage *m_DataStorage; Ui::QmitkMaskStampWidgetGUIControls m_Controls; }; #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitkSliceBasedInterpolatorWidget.h b/Modules/SegmentationUI/Qmitk/QmitkSliceBasedInterpolatorWidget.h index c23db6bcf3..f33ab64114 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkSliceBasedInterpolatorWidget.h +++ b/Modules/SegmentationUI/Qmitk/QmitkSliceBasedInterpolatorWidget.h @@ -1,195 +1,197 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef QmitkSliceBasedInterpolatorWidget_h_Included #define QmitkSliceBasedInterpolatorWidget_h_Included #include "MitkSegmentationUIExports.h" #include "mitkDataStorage.h" #include "mitkSliceBasedInterpolationController.h" #include #include #include "ui_QmitkSliceBasedInterpolatorWidgetGUIControls.h" namespace mitk { class PlaneGeometry; class SliceNavigationController; class LabelSetImage; class ToolManager; class DiffSliceOperation; } /** \brief GUI for slices interpolation. \ingroup ToolManagerEtAl \ingroup Widgets \sa QmitkInteractiveSegmentation \sa mitk::SegmentationInterpolation While mitk::SegmentationInterpolation does the bookkeeping of interpolation (keeping track of which slices contain how much segmentation) and the algorithmic work, QmitkSliceBasedInterpolatorWidget is responsible to watch the GUI, to notice, which slice is currently visible. It triggers generation of interpolation suggestions and also triggers acception of suggestions. + This class uses the mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION context. + \todo show/hide feedback on demand Last contributor: $Author: maleike $ */ class MITKSEGMENTATIONUI_EXPORT QmitkSliceBasedInterpolatorWidget : public QWidget { Q_OBJECT public: QmitkSliceBasedInterpolatorWidget(QWidget *parent = nullptr, const char *name = nullptr); ~QmitkSliceBasedInterpolatorWidget() override; void SetDataStorage(mitk::DataStorage &storage); /** Sets the slice navigation controllers for getting slice changed events from the views. */ void SetSliceNavigationControllers(const QList &controllers); void OnToolManagerWorkingDataModified(); void OnTimeChanged(itk::Object *sender, const itk::EventObject &); void OnSliceChanged(itk::Object *sender, const itk::EventObject &); void OnSliceNavigationControllerDeleted(const itk::Object *sender, const itk::EventObject &); /** Just public because it is called by itk::Commands. You should not need to call this. */ void OnSliceInterpolationInfoChanged(const itk::EventObject &); Ui::QmitkSliceBasedInterpolatorWidgetGUIControls m_Controls; signals: void signalSliceBasedInterpolationEnabled(bool); public slots: /** \brief Reaction to "Start/Stop" button click */ void OnToggleWidgetActivation(bool); protected slots: /** \brief Reaction to "Accept Current Slice" button click. */ void OnAcceptInterpolationClicked(); /* \brief Reaction to "Accept All Slices" button click. Opens popup to ask about which orientation should be interpolated */ void OnAcceptAllInterpolationsClicked(); /* \brief Called from popup menu of OnAcceptAllInterpolationsClicked() Will trigger interpolation for all slices in given orientation */ void OnAcceptAllPopupActivated(QAction *action); protected: typedef std::map ActionToSliceDimensionMapType; const ActionToSliceDimensionMapType CreateActionToSliceDimension(); ActionToSliceDimensionMapType m_ActionToSliceDimensionMap; void AcceptAllInterpolations(mitk::SliceNavigationController *slicer); void WaitCursorOn(); void WaitCursorOff(); void RestoreOverrideCursor(); /** Gets the working slice based on the given plane geometry and last saved interaction \param planeGeometry a plane geometry */ mitk::Image::Pointer GetWorkingSlice(const mitk::PlaneGeometry *planeGeometry); /** Retrieves the currently selected PlaneGeometry from a SlicedGeometry3D that is generated by a SliceNavigationController and calls Interpolate to further process this PlaneGeometry into an interpolation. \param e is a actually a mitk::SliceNavigationController::GeometrySliceEvent, sent by a SliceNavigationController \param slice the SliceNavigationController */ void TranslateAndInterpolateChangedSlice(const itk::EventObject &e, mitk::SliceNavigationController *slicer); /** Given a PlaneGeometry, this method figures out which slice of the first working image (of the associated ToolManager) should be interpolated. The actual work is then done by our SegmentationInterpolation object. */ void Interpolate(mitk::PlaneGeometry *plane, mitk::TimePointType timePoint, mitk::SliceNavigationController *slicer); /** Called internally to update the interpolation suggestion. Finds out about the focused render window and requests an interpolation. */ void UpdateVisibleSuggestion(); private: mitk::SliceBasedInterpolationController::Pointer m_SliceInterpolatorController; mitk::ToolManager *m_ToolManager; bool m_Activated; template void WritePreviewOnWorkingImage(itk::Image *target, const mitk::Image *source, int overwritevalue); QHash m_ControllerToTimeObserverTag; QHash m_ControllerToSliceObserverTag; QHash m_ControllerToDeleteObserverTag; unsigned int m_InterpolationInfoChangedObserverTag; mitk::DiffSliceOperation *m_doOperation; mitk::DiffSliceOperation *m_undoOperation; mitk::DataNode::Pointer m_PreviewNode; mitk::Image::Pointer m_PreviewImage; mitk::LabelSetImage::Pointer m_WorkingImage; QHash m_TimePoints; mitk::DataStorage::Pointer m_DataStorage; mitk::SliceNavigationController *m_LastSNC; unsigned int m_LastSliceIndex; }; #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitkSurfaceBasedInterpolatorWidget.h b/Modules/SegmentationUI/Qmitk/QmitkSurfaceBasedInterpolatorWidget.h index a4582310dc..fb16e7f7b0 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkSurfaceBasedInterpolatorWidget.h +++ b/Modules/SegmentationUI/Qmitk/QmitkSurfaceBasedInterpolatorWidget.h @@ -1,119 +1,121 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef QmitkSurfaceBasedInterpolatorWidgetWidget_h_Included #define QmitkSurfaceBasedInterpolatorWidgetWidget_h_Included #include "MitkSegmentationUIExports.h" #include "mitkDataNode.h" #include "mitkDataStorage.h" #include "mitkLabelSetImage.h" #include "mitkSurfaceBasedInterpolationController.h" #include #include // For running 3D interpolation in background #include #include #include #include #include "ui_QmitkSurfaceBasedInterpolatorWidgetGUIControls.h" namespace mitk { class ToolManager; } /** \brief GUI for surface-based interpolation. \ingroup ToolManagerEtAl \ingroup Widgets \sa QmitkInteractiveSegmentation \sa mitk::SurfaceBasedInterpolationController QmitkSurfaceBasedInterpolatorWidgetController is responsible to watch the GUI, to notice, which slice is currently visible. It triggers generation of interpolation suggestions and also triggers acception of suggestions. + + This class uses the mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION context. */ class MITKSEGMENTATIONUI_EXPORT QmitkSurfaceBasedInterpolatorWidget : public QWidget { Q_OBJECT public: QmitkSurfaceBasedInterpolatorWidget(QWidget *parent = nullptr, const char *name = nullptr); ~QmitkSurfaceBasedInterpolatorWidget() override; void SetDataStorage(mitk::DataStorage &storage); void OnToolManagerWorkingDataModified(); /** Just public because it is called by itk::Commands. You should not need to call this. */ void OnSurfaceInterpolationInfoChanged(const itk::EventObject &); /** * @brief Set the visibility of the interpolation */ void ShowInterpolationResult(bool); Ui::QmitkSurfaceBasedInterpolatorWidgetGUIControls m_Controls; public slots: /** \brief Reaction to "Start/Stop" button click */ void OnToggleWidgetActivation(bool); protected slots: void OnAcceptInterpolationClicked(); void OnSurfaceInterpolationFinished(); void OnRunInterpolation(); void OnShowMarkers(bool); void StartUpdateInterpolationTimer(); void StopUpdateInterpolationTimer(); void ChangeSurfaceColor(); private: mitk::SurfaceBasedInterpolationController::Pointer m_SurfaceBasedInterpolatorController; mitk::ToolManager *m_ToolManager; bool m_Activated; unsigned int m_SurfaceInterpolationInfoChangedObserverTag; mitk::DataNode::Pointer m_InterpolatedSurfaceNode; mitk::DataNode::Pointer m_3DContourNode; mitk::DataStorage::Pointer m_DataStorage; mitk::LabelSetImage::Pointer m_WorkingImage; QFuture m_Future; QFutureWatcher m_Watcher; QTimer *m_Timer; }; #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitkSurfaceStampWidget.cpp b/Modules/SegmentationUI/Qmitk/QmitkSurfaceStampWidget.cpp index 05be2aa182..ad9a9a0f92 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkSurfaceStampWidget.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkSurfaceStampWidget.cpp @@ -1,117 +1,117 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkSurfaceStampWidget.h" #include #include #include #include #include QmitkSurfaceStampWidget::QmitkSurfaceStampWidget(QWidget *parent, const char * /*name*/) : QWidget(parent), m_ToolManager(nullptr), m_DataStorage(nullptr) { m_Controls.setupUi(this); m_Controls.m_InformationWidget->hide(); m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION); m_ToolManager->ActivateTool(-1); mitk::NodePredicateAnd::Pointer m_SurfacePredicate = mitk::NodePredicateAnd::New(); m_SurfacePredicate->AddPredicate(mitk::NodePredicateDataType::New("Surface")); m_SurfacePredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))); m_Controls.m_cbSurfaceNodeSelector->SetPredicate(m_SurfacePredicate); connect(m_Controls.m_pbStamp, SIGNAL(clicked()), this, SLOT(OnStamp())); connect(m_Controls.m_cbShowInformation, SIGNAL(toggled(bool)), this, SLOT(OnShowInformation(bool))); m_Controls.m_InformationWidget->hide(); } QmitkSurfaceStampWidget::~QmitkSurfaceStampWidget() { } void QmitkSurfaceStampWidget::SetDataStorage(mitk::DataStorage *storage) { m_DataStorage = storage; m_Controls.m_cbSurfaceNodeSelector->SetDataStorage(m_DataStorage); } void QmitkSurfaceStampWidget::OnStamp() { mitk::DataNode *surfaceNode = m_Controls.m_cbSurfaceNodeSelector->GetSelectedNode(); if (!surfaceNode) { QMessageBox::information(this, "Surface Stamp", "Please load and select a surface before starting some action."); return; } - m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); + m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION); assert(m_ToolManager); m_ToolManager->ActivateTool(-1); mitk::Surface *surface = dynamic_cast(surfaceNode->GetData()); if (!surface) { QMessageBox::information(this, "Surface Stamp", "Please load and select a surface before starting some action."); return; } mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0); if (!workingNode) { QMessageBox::information( this, "Surface Stamp", "Please load and select a segmentation before starting some action."); return; } mitk::LabelSetImage *workingImage = dynamic_cast(workingNode->GetData()); if (!workingImage) { QMessageBox::information( this, "Surface Stamp", "Please load and select a segmentation before starting some action."); return; } QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); try { // workingImage->SurfaceStamp( surface, m_Controls.m_chkOverwrite->isChecked() ); } catch (mitk::Exception &e) { QApplication::restoreOverrideCursor(); MITK_ERROR << "Exception caught: " << e.GetDescription(); QMessageBox::information( this, "Surface Stamp", "Could not stamp the selected surface.\n See error log for details.\n"); return; } QApplication::restoreOverrideCursor(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSurfaceStampWidget::OnShowInformation(bool on) { if (on) m_Controls.m_InformationWidget->show(); else m_Controls.m_InformationWidget->hide(); } diff --git a/Modules/SegmentationUI/Qmitk/QmitkSurfaceStampWidget.h b/Modules/SegmentationUI/Qmitk/QmitkSurfaceStampWidget.h index 6320838ba2..852eced247 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkSurfaceStampWidget.h +++ b/Modules/SegmentationUI/Qmitk/QmitkSurfaceStampWidget.h @@ -1,58 +1,60 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef QmitkSurfaceStampWidget_h_Included #define QmitkSurfaceStampWidget_h_Included #include "MitkSegmentationUIExports.h" #include #include "ui_QmitkSurfaceStampWidgetGUIControls.h" namespace mitk { class ToolManager; } /** \brief GUI for surface-based interpolation. + This class uses the mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION context. + \ingroup ToolManagerEtAl \ingroup Widgets */ class MITKSEGMENTATIONUI_EXPORT QmitkSurfaceStampWidget : public QWidget { Q_OBJECT public: QmitkSurfaceStampWidget(QWidget *parent = nullptr, const char *name = nullptr); ~QmitkSurfaceStampWidget() override; void SetDataStorage(mitk::DataStorage *storage); protected slots: void OnShowInformation(bool); void OnStamp(); private: mitk::ToolManager *m_ToolManager; mitk::DataStorage *m_DataStorage; Ui::QmitkSurfaceStampWidgetGUIControls m_Controls; }; #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitkToolSelectionBox.cpp b/Modules/SegmentationUI/Qmitk/QmitkToolSelectionBox.cpp index 43ca2e2c15..2036ea6b67 100755 --- a/Modules/SegmentationUI/Qmitk/QmitkToolSelectionBox.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkToolSelectionBox.cpp @@ -1,722 +1,683 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ //#define MBILOG_ENABLE_DEBUG 1 #include #include "QmitkToolSelectionBox.h" #include "QmitkToolGUI.h" #include "mitkBaseRenderer.h" #include #include #include #include #include #include #include #include "usModuleResource.h" #include "usModuleResourceStream.h" #include "mitkToolManagerProvider.h" QmitkToolSelectionBox::QmitkToolSelectionBox(QWidget *parent, mitk::DataStorage *) : QWidget(parent), m_SelfCall(false), m_DisplayedGroups("default"), m_LayoutColumns(2), m_ShowNames(true), m_GenerateAccelerators(false), m_ToolGUIWidget(nullptr), m_LastToolGUI(nullptr), m_ToolButtonGroup(nullptr), m_ButtonLayout(nullptr), m_EnabledMode(EnabledWithReferenceAndWorkingDataVisible) { QFont currentFont = QWidget::font(); currentFont.setBold(true); QWidget::setFont(currentFont); m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); - // muellerm // QButtonGroup m_ToolButtonGroup = new QButtonGroup(this); // some features of QButtonGroup m_ToolButtonGroup->setExclusive(false); // mutually exclusive toggle buttons RecreateButtons(); QWidget::setContentsMargins(0, 0, 0, 0); if (layout() != nullptr) { layout()->setContentsMargins(0, 0, 0, 0); } // reactions to signals connect(m_ToolButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(toolButtonClicked(int))); // reactions to ToolManager events m_ToolManager->ActiveToolChanged += mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerToolModified); m_ToolManager->ReferenceDataChanged += mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerReferenceDataModified); m_ToolManager->WorkingDataChanged += mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerWorkingDataModified); // show active tool SetOrUnsetButtonForActiveTool(); QWidget::setEnabled(false); } QmitkToolSelectionBox::~QmitkToolSelectionBox() { m_ToolManager->ActiveToolChanged -= mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerToolModified); m_ToolManager->ReferenceDataChanged -= mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerReferenceDataModified); m_ToolManager->WorkingDataChanged -= mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerWorkingDataModified); } void QmitkToolSelectionBox::SetEnabledMode(EnabledMode mode) { m_EnabledMode = mode; SetGUIEnabledAccordingToToolManagerState(); } mitk::ToolManager *QmitkToolSelectionBox::GetToolManager() { return m_ToolManager; } void QmitkToolSelectionBox::SetToolManager( mitk::ToolManager &newManager) // no nullptr pointer allowed here, a manager is required { // say bye to the old manager m_ToolManager->ActiveToolChanged -= mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerToolModified); m_ToolManager->ReferenceDataChanged -= mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerReferenceDataModified); m_ToolManager->WorkingDataChanged -= mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerWorkingDataModified); if (QWidget::isEnabled()) { m_ToolManager->UnregisterClient(); } m_ToolManager = &newManager; RecreateButtons(); // greet the new one m_ToolManager->ActiveToolChanged += mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerToolModified); m_ToolManager->ReferenceDataChanged += mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerReferenceDataModified); m_ToolManager->WorkingDataChanged += mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerWorkingDataModified); if (QWidget::isEnabled()) { m_ToolManager->RegisterClient(); } // ask the new one what the situation is like SetOrUnsetButtonForActiveTool(); } void QmitkToolSelectionBox::toolButtonClicked(int id) { if (!QWidget::isEnabled()) return; // this method could be triggered from the constructor, when we are still disabled MITK_DEBUG << "toolButtonClicked(" << id << "): id translates to tool ID " << m_ToolIDForButtonID[id]; - // QToolButton* toolButton = dynamic_cast( Q3ButtonGroup::find(id) ); QToolButton *toolButton = dynamic_cast(m_ToolButtonGroup->buttons().at(id)); if (toolButton) { if ((m_ButtonIDForToolID.find(m_ToolManager->GetActiveToolID()) != m_ButtonIDForToolID.end()) // if we have this tool in our box && (m_ButtonIDForToolID[m_ToolManager->GetActiveToolID()] == id)) // the tool corresponding to this button is already active { // disable this button, disable all tools - // mmueller toolButton->setChecked(false); m_ToolManager->ActivateTool(-1); // disable everything } else { // enable the corresponding tool m_SelfCall = true; m_ToolManager->ActivateTool(m_ToolIDForButtonID[id]); m_SelfCall = false; } } } void QmitkToolSelectionBox::OnToolManagerToolModified() { SetOrUnsetButtonForActiveTool(); } void QmitkToolSelectionBox::SetOrUnsetButtonForActiveTool() { // we want to emit a signal in any case, whether we selected ourselves or somebody else changes "our" tool manager. // --> emit before check on m_SelfCall int id = m_ToolManager->GetActiveToolID(); // don't emit signal for shape model tools bool emitSignal = true; mitk::Tool *tool = m_ToolManager->GetActiveTool(); if (tool && std::string(tool->GetGroup()) == "organ_segmentation") emitSignal = false; if (emitSignal) emit ToolSelected(id); // delete old GUI (if any) if (m_LastToolGUI && m_ToolGUIWidget) { if (m_ToolGUIWidget->layout()) { m_ToolGUIWidget->layout()->removeWidget(m_LastToolGUI); } - // m_LastToolGUI->reparent(nullptr, QPoint(0,0)); - // TODO: reparent <-> setParent, Daniel fragen m_LastToolGUI->setParent(nullptr); delete m_LastToolGUI; // will hopefully notify parent and layouts m_LastToolGUI = nullptr; QLayout *layout = m_ToolGUIWidget->layout(); if (layout) { layout->activate(); } } QToolButton *toolButton(nullptr); - // mitk::Tool* tool = m_ToolManager->GetActiveTool(); if (m_ButtonIDForToolID.find(id) != m_ButtonIDForToolID.end()) // if this tool is in our box { - // toolButton = dynamic_cast( Q3ButtonGroup::find( m_ButtonIDForToolID[id] ) ); toolButton = dynamic_cast(m_ToolButtonGroup->buttons().at(m_ButtonIDForToolID[id])); } if (toolButton) { // mmueller // uncheck all other buttons QAbstractButton *tmpBtn = nullptr; QList::iterator it; for (int i = 0; i < m_ToolButtonGroup->buttons().size(); ++i) { tmpBtn = m_ToolButtonGroup->buttons().at(i); if (tmpBtn != toolButton) dynamic_cast(tmpBtn)->setChecked(false); } toolButton->setChecked(true); if (m_ToolGUIWidget && tool) { // create and reparent new GUI (if any) itk::Object::Pointer possibleGUI = tool->GetGUI("Qmitk", "GUI").GetPointer(); // prefix and postfix if (possibleGUI.IsNull()) possibleGUI = tool->GetGUI("", "GUI").GetPointer(); QmitkToolGUI *gui = dynamic_cast(possibleGUI.GetPointer()); //! m_LastToolGUI = gui; if (gui) { gui->SetTool(tool); - // mmueller - // gui->reparent(m_ToolGUIWidget, gui->geometry().topLeft(), true ); gui->setParent(m_ToolGUIWidget); gui->move(gui->geometry().topLeft()); gui->show(); QLayout *layout = m_ToolGUIWidget->layout(); if (!layout) { layout = new QVBoxLayout(m_ToolGUIWidget); } if (layout) { - // mmueller layout->addWidget(gui); - // layout->add( gui ); layout->activate(); } } } } else { // disable all buttons QToolButton *selectedToolButton = dynamic_cast(m_ToolButtonGroup->checkedButton()); - // QToolButton* selectedToolButton = dynamic_cast( Q3ButtonGroup::find( Q3ButtonGroup::selectedId() ) - // ); if (selectedToolButton) { - // mmueller selectedToolButton->setChecked(false); - // selectedToolButton->setOn(false); } } } void QmitkToolSelectionBox::OnToolManagerReferenceDataModified() { if (m_SelfCall) return; MITK_DEBUG << "OnToolManagerReferenceDataModified()"; - SetGUIEnabledAccordingToToolManagerState(); + this->UpdateButtonsEnabledState(); + this->SetGUIEnabledAccordingToToolManagerState(); } void QmitkToolSelectionBox::OnToolManagerWorkingDataModified() { if (m_SelfCall) return; MITK_DEBUG << "OnToolManagerWorkingDataModified()"; - SetGUIEnabledAccordingToToolManagerState(); + this->UpdateButtonsEnabledState(); + this->SetGUIEnabledAccordingToToolManagerState(); } /** Implementes the logic, which decides, when tools are activated/deactivated. */ void QmitkToolSelectionBox::SetGUIEnabledAccordingToToolManagerState() { mitk::DataNode *referenceNode = m_ToolManager->GetReferenceData(0); mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0); - // MITK_DEBUG << this->name() << ": SetGUIEnabledAccordingToToolManagerState: referenceNode " << (void*)referenceNode - // << " workingNode " << (void*)workingNode << " isVisible() " << isVisible(); - bool enabled = true; switch (m_EnabledMode) { default: case EnabledWithReferenceAndWorkingDataVisible: enabled = referenceNode && workingNode && referenceNode->IsVisible( mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget0"))) && workingNode->IsVisible( mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget0"))) && isVisible(); break; case EnabledWithReferenceData: enabled = referenceNode && isVisible(); break; case EnabledWithWorkingData: enabled = workingNode && isVisible(); break; case AlwaysEnabled: enabled = isVisible(); break; } if (QWidget::isEnabled() == enabled) return; // nothing to change QWidget::setEnabled(enabled); if (enabled) { m_ToolManager->RegisterClient(); int id = m_ToolManager->GetActiveToolID(); emit ToolSelected(id); } else { m_ToolManager->ActivateTool(-1); m_ToolManager->UnregisterClient(); emit ToolSelected(-1); } } /** External enableization... */ void QmitkToolSelectionBox::setEnabled(bool /*enable*/) { SetGUIEnabledAccordingToToolManagerState(); } -void QmitkToolSelectionBox::RecreateButtons() +void QmitkToolSelectionBox::UpdateButtonsEnabledState() { - if (m_ToolManager.IsNull()) - return; + auto buttons = m_ToolButtonGroup->buttons(); - /* - // remove all buttons that are there - QObjectList *l = Q3ButtonGroup::queryList( "QButton" ); - QObjectListIt it( *l ); // iterate over all buttons - QObject *obj; + const auto refDataNode = m_ToolManager->GetReferenceData(0); + const mitk::BaseData* refData = nullptr; + if (nullptr != refDataNode) + { + refData = refDataNode->GetData(); + } - while ( (obj = it.current()) != 0 ) + const auto workingDataNode = m_ToolManager->GetWorkingData(0); + const mitk::BaseData* workingData = nullptr; + if (nullptr != workingDataNode) { - ++it; - QButton* button = dynamic_cast(obj); - if (button) - { - Q3ButtonGroup::remove(button); - delete button; - } + workingData = workingDataNode->GetData(); + } + + for (const auto& button : buttons) + { + const auto buttonID = m_ToolButtonGroup->id(button); + const auto toolID = m_ToolIDForButtonID[buttonID]; + const auto tool = m_ToolManager->GetToolById(toolID); + + button->setEnabled(tool->CanHandle(refData, workingData)); } - delete l; // delete the list, not the objects - */ +} + +void QmitkToolSelectionBox::RecreateButtons() +{ + if (m_ToolManager.IsNull()) + return; - // mmueller Qt impl QList l = m_ToolButtonGroup->buttons(); // remove all buttons that are there QList::iterator it; QAbstractButton *btn; for (it = l.begin(); it != l.end(); ++it) { btn = *it; m_ToolButtonGroup->removeButton(btn); - // this->removeChild(btn); delete btn; } - // end mmueller Qt impl mitk::ToolManager::ToolVectorTypeConst allPossibleTools = m_ToolManager->GetTools(); mitk::ToolManager::ToolVectorTypeConst allTools; typedef std::pair SortPairType; typedef std::priority_queue SortedToolQueueType; SortedToolQueueType toolPositions; // clear and sort all tools // step one: find name/group of all tools in m_DisplayedGroups string. remember these positions for all tools. for (mitk::ToolManager::ToolVectorTypeConst::const_iterator iter = allPossibleTools.begin(); iter != allPossibleTools.end(); ++iter) { const mitk::Tool *tool = *iter; std::string::size_type namePos = m_DisplayedGroups.find(std::string("'") + tool->GetName() + "'"); std::string::size_type groupPos = m_DisplayedGroups.find(std::string("'") + tool->GetGroup() + "'"); if (!m_DisplayedGroups.empty() && namePos == std::string::npos && groupPos == std::string::npos) continue; // skip if (m_DisplayedGroups.empty() && std::string(tool->GetName()).length() > 0) { namePos = static_cast(tool->GetName()[0]); } SortPairType thisPair = std::make_pair(namePos < groupPos ? namePos : groupPos, *iter); toolPositions.push(thisPair); } // step two: sort tools according to previously found positions in m_DisplayedGroups MITK_DEBUG << "Sorting order of tools (lower number --> earlier in button group)"; while (!toolPositions.empty()) { SortPairType thisPair = toolPositions.top(); MITK_DEBUG << "Position " << thisPair.first << " : " << thisPair.second->GetName(); allTools.push_back(thisPair.second); toolPositions.pop(); } std::reverse(allTools.begin(), allTools.end()); MITK_DEBUG << "Sorted tools:"; for (mitk::ToolManager::ToolVectorTypeConst::const_iterator iter = allTools.begin(); iter != allTools.end(); ++iter) { MITK_DEBUG << (*iter)->GetName(); } - // try to change layout... bad? - // Q3GroupBox::setColumnLayout ( m_LayoutColumns, Qt::Horizontal ); - // mmueller using gridlayout instead of Q3GroupBox - // this->setLayout(0); if (m_ButtonLayout == nullptr) m_ButtonLayout = new QGridLayout; - /*else - delete m_ButtonLayout;*/ int row(0); int column(-1); int currentButtonID(0); m_ButtonIDForToolID.clear(); m_ToolIDForButtonID.clear(); QToolButton *button = nullptr; MITK_DEBUG << "Creating buttons for tools"; // fill group box with buttons for (mitk::ToolManager::ToolVectorTypeConst::const_iterator iter = allTools.begin(); iter != allTools.end(); ++iter) { const mitk::Tool *tool = *iter; int currentToolID(m_ToolManager->GetToolID(tool)); ++column; // new line if we are at the maximum columns if (column == m_LayoutColumns) { ++row; column = 0; } button = new QToolButton; button->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); // add new button to the group MITK_DEBUG << "Adding button with ID " << currentToolID; m_ToolButtonGroup->addButton(button, currentButtonID); // ... and to the layout MITK_DEBUG << "Adding button in row/column " << row << "/" << column; m_ButtonLayout->addWidget(button, row, column); if (m_LayoutColumns == 1) { - // button->setTextPosition( QToolButton::BesideIcon ); - // mmueller button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); } else { - // button->setTextPosition( QToolButton::BelowIcon ); - // mmueller button->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); } - // button->setToggleButton( true ); - // mmueller button->setCheckable(true); if (currentToolID == m_ToolManager->GetActiveToolID()) button->setChecked(true); QString label; if (m_GenerateAccelerators) { label += "&"; } label += tool->GetName(); QString tooltip = tool->GetName(); MITK_DEBUG << tool->GetName() << ", " << label.toLocal8Bit().constData() << ", '" << tooltip.toLocal8Bit().constData(); if (m_ShowNames) { - /* - button->setUsesTextLabel(true); - button->setTextLabel( label ); // a label - QToolTip::add( button, tooltip ); - */ - // mmueller Qt button->setText(label); // a label button->setToolTip(tooltip); - // mmueller QFont currentFont = button->font(); currentFont.setBold(false); button->setFont(currentFont); } us::ModuleResource iconResource = tool->GetIconResource(); if (!iconResource.IsValid()) { button->setIcon(QIcon(QPixmap(tool->GetXPM()))); } else { auto isSVG = "svg" == iconResource.GetSuffix(); auto openmode = isSVG ? std::ios_base::in : std::ios_base::binary; us::ModuleResourceStream resourceStream(iconResource, openmode); resourceStream.seekg(0, std::ios::end); std::ios::pos_type length = resourceStream.tellg(); resourceStream.seekg(0, std::ios::beg); char *data = new char[length]; resourceStream.read(data, length); if (isSVG) { button->setIcon(QmitkStyleManager::ThemeIcon(QByteArray::fromRawData(data, length))); } else { QPixmap pixmap; pixmap.loadFromData(QByteArray::fromRawData(data, length)); button->setIcon(QIcon(pixmap)); } delete[] data; if (m_ShowNames) { if (m_LayoutColumns == 1) button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); else button->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); button->setIconSize(QSize(24, 24)); } else { button->setToolButtonStyle(Qt::ToolButtonIconOnly); button->setIconSize(QSize(32, 32)); button->setToolTip(tooltip); } } if (m_GenerateAccelerators) { QString firstLetter = QString(tool->GetName()); firstLetter.truncate(1); button->setShortcut( firstLetter); // a keyboard shortcut (just the first letter of the given name w/o any CTRL or something) } - mitk::DataNode *dataNode = m_ToolManager->GetReferenceData(0); - const auto workingDataNode = m_ToolManager->GetWorkingData(0); - const mitk::BaseData* workingData = nullptr; - if (nullptr != workingDataNode) - { - workingData = workingDataNode->GetData(); - } - - if (nullptr == dataNode || !tool->CanHandle(dataNode->GetData(), workingData)) - button->setEnabled(false); - m_ButtonIDForToolID[currentToolID] = currentButtonID; m_ToolIDForButtonID[currentButtonID] = currentToolID; MITK_DEBUG << "m_ButtonIDForToolID[" << currentToolID << "] == " << currentButtonID; MITK_DEBUG << "m_ToolIDForButtonID[" << currentButtonID << "] == " << currentToolID; tool->GUIProcessEventsMessage += mitk::MessageDelegate( this, &QmitkToolSelectionBox::OnToolGUIProcessEventsMessage); // will never add a listener twice, so we don't have // to check here tool->ErrorMessage += mitk::MessageDelegate1( this, &QmitkToolSelectionBox::OnToolErrorMessage); // will never add a listener twice, so we don't have to check here tool->GeneralMessage += mitk::MessageDelegate1(this, &QmitkToolSelectionBox::OnGeneralToolMessage); ++currentButtonID; } // setting grid layout for this groupbox this->setLayout(m_ButtonLayout); + this->UpdateButtonsEnabledState(); // this->update(); } void QmitkToolSelectionBox::OnToolGUIProcessEventsMessage() { qApp->processEvents(); } void QmitkToolSelectionBox::OnToolErrorMessage(std::string s) { QMessageBox::critical( this, "MITK", QString(s.c_str()), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); } void QmitkToolSelectionBox::OnGeneralToolMessage(std::string s) { QMessageBox::information( this, "MITK", QString(s.c_str()), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); } void QmitkToolSelectionBox::SetDisplayedToolGroups(const std::string &toolGroups) { if (m_DisplayedGroups != toolGroups) { QString q_DisplayedGroups = toolGroups.c_str(); // quote all unquoted single words q_DisplayedGroups = q_DisplayedGroups.replace(QRegExp("\\b(\\w+)\\b|'([^']+)'"), "'\\1\\2'"); MITK_DEBUG << "m_DisplayedGroups was \"" << toolGroups << "\""; m_DisplayedGroups = q_DisplayedGroups.toLocal8Bit().constData(); MITK_DEBUG << "m_DisplayedGroups is \"" << m_DisplayedGroups << "\""; RecreateButtons(); SetOrUnsetButtonForActiveTool(); } } void QmitkToolSelectionBox::SetLayoutColumns(int columns) { if (columns > 0 && columns != m_LayoutColumns) { m_LayoutColumns = columns; RecreateButtons(); } } void QmitkToolSelectionBox::SetShowNames(bool show) { if (show != m_ShowNames) { m_ShowNames = show; RecreateButtons(); } } void QmitkToolSelectionBox::SetGenerateAccelerators(bool accel) { if (accel != m_GenerateAccelerators) { m_GenerateAccelerators = accel; RecreateButtons(); } } void QmitkToolSelectionBox::SetToolGUIArea(QWidget *parentWidget) { m_ToolGUIWidget = parentWidget; } void QmitkToolSelectionBox::setTitle(const QString & /*title*/) { } void QmitkToolSelectionBox::showEvent(QShowEvent *e) { QWidget::showEvent(e); SetGUIEnabledAccordingToToolManagerState(); } void QmitkToolSelectionBox::hideEvent(QHideEvent *e) { QWidget::hideEvent(e); SetGUIEnabledAccordingToToolManagerState(); } diff --git a/Modules/SegmentationUI/Qmitk/QmitkToolSelectionBox.h b/Modules/SegmentationUI/Qmitk/QmitkToolSelectionBox.h index 643e32bd71..2afc06ce0f 100755 --- a/Modules/SegmentationUI/Qmitk/QmitkToolSelectionBox.h +++ b/Modules/SegmentationUI/Qmitk/QmitkToolSelectionBox.h @@ -1,147 +1,148 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef QmitkToolSelectionBox_h_Included #define QmitkToolSelectionBox_h_Included #include "QmitkToolGUIArea.h" #include #include "mitkToolManager.h" #include #include #include #include class QmitkToolGUI; /** \brief Display the tool selection state of a mitk::ToolManager \sa mitk::ToolManager \ingroup org_mitk_gui_qt_interactivesegmentation \ingroup ToolManagerEtAl This widget graphically displays the active tool of a mitk::ToolManager as a set of toggle buttons. Each button show the identification of a Tool (icon and name). When a button's toggle state is "down", the tool is activated. When a different button is clicked, the active tool is switched. When you click an already active button, the associated tool is deactivated with no replacement, which means that no tool is active then. When this widget is enabled/disabled it (normally) also enables/disables the tools. There could be cases where two QmitkToolSelectionBox widgets are associated to the same ToolManager, but if this happens, please look deeply into the code. Last contributor: $Author: maleike $ */ class MITKSEGMENTATIONUI_EXPORT QmitkToolSelectionBox : public QWidget //! { Q_OBJECT public: enum EnabledMode { EnabledWithReferenceAndWorkingDataVisible, EnabledWithReferenceData, EnabledWithWorkingData, AlwaysEnabled }; QmitkToolSelectionBox(QWidget *parent = nullptr, mitk::DataStorage *storage = nullptr); ~QmitkToolSelectionBox() override; mitk::ToolManager *GetToolManager(); void SetToolManager(mitk::ToolManager &); // no nullptr pointer allowed here, a manager is required void setTitle(const QString &title); /** You may specify a list of tool "groups" that should be displayed in this widget. Every Tool can report its group as a string. This method will try to find the tool's group inside the supplied string \param toolGroups. If there is a match, the tool is displayed. Effectively, you can provide a human readable list like "default, lymphnodevolumetry, oldERISstuff". */ void SetDisplayedToolGroups(const std::string &toolGroups = nullptr); void OnToolManagerToolModified(); void OnToolManagerReferenceDataModified(); void OnToolManagerWorkingDataModified(); void OnToolGUIProcessEventsMessage(); void OnToolErrorMessage(std::string s); void OnGeneralToolMessage(std::string s); void RecreateButtons(); signals: /// Whenever a tool is activated. id is the index of the active tool. Counting starts at 0, -1 indicates "no tool /// selected" /// This signal is also emitted, when the whole QmitkToolSelectionBox get disabled. Then it will claim /// ToolSelected(-1) /// When it is enabled again, there will be another ToolSelected event with the tool that is currently selected void ToolSelected(int id); public slots: virtual void setEnabled(bool); virtual void SetEnabledMode(EnabledMode mode); virtual void SetLayoutColumns(int); virtual void SetShowNames(bool); virtual void SetGenerateAccelerators(bool); virtual void SetToolGUIArea(QWidget *parentWidget); protected slots: void toolButtonClicked(int id); void SetGUIEnabledAccordingToToolManagerState(); + void UpdateButtonsEnabledState(); protected: void showEvent(QShowEvent *) override; void hideEvent(QHideEvent *) override; void SetOrUnsetButtonForActiveTool(); mitk::ToolManager::Pointer m_ToolManager; bool m_SelfCall; std::string m_DisplayedGroups; /// stores relationship between button IDs of the Qt widget and tool IDs of ToolManager std::map m_ButtonIDForToolID; /// stores relationship between button IDs of the Qt widget and tool IDs of ToolManager std::map m_ToolIDForButtonID; int m_LayoutColumns; bool m_ShowNames; bool m_GenerateAccelerators; QWidget *m_ToolGUIWidget; QmitkToolGUI *m_LastToolGUI; // store buttons in this group QButtonGroup *m_ToolButtonGroup; QGridLayout *m_ButtonLayout; EnabledMode m_EnabledMode; }; #endif diff --git a/Modules/ToFHardware/CMakeLists.txt b/Modules/ToFHardware/CMakeLists.txt index 45414ffffe..3c591fa061 100644 --- a/Modules/ToFHardware/CMakeLists.txt +++ b/Modules/ToFHardware/CMakeLists.txt @@ -1,33 +1,32 @@ #Define the platform string mitkMacroGetPMDPlatformString(_PLATFORM_STRING) MITK_CREATE_MODULE( - SUBPROJECTS MITK-ToF DEPENDS MitkOpenCVVideoSupport MitkIGTBase MitkCameraCalibration MitkIpPic PACKAGE_DEPENDS ITK|ITKIONRRD ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ) # set(tofHardware_srcs ) # usFunctionEmbedResources(tofHardware_srcs # LIBRARY_NAME mitkToFHardware # ROOT_DIR ${MITK_DATA_DIR}/ToF-Data/CalibrationFiles # FILES Default_Parameters.xml Kinect_IR_camera.xml Kinect_RGB_camera.xml Mesa-SR4000_Camera.xml PMDCamBoard_camera.xml PMDCamCube2_camera.xml PMDCamCube3_camera.xml # ) add_subdirectory(Testing) add_subdirectory(Kinect) add_subdirectory(KinectV2) add_subdirectory(PMD) add_subdirectory(MesaSR4000) # Install external libraries which are not directly linked to a MITK module include(${CMAKE_CURRENT_SOURCE_DIR}/mitkToFHardwareInstallRules.cmake) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/mitkToFHardwareInstallRules.cmake ${PROJECT_BINARY_DIR}/mitkToFHardwareInstallRules.cmake COPYONLY) CONFIGURE_FILE(mitkToFConfig.h.in ${PROJECT_BINARY_DIR}/mitkToFConfig.h @ONLY) #foreach(tofhardwaresubfolder_dir ${tofhardwaresubfolder_dirs}) # add_subdirectory(${tofhardwaresubfolder_dirs}) #endforeach() diff --git a/Modules/ToFHardware/Kinect/CMakeLists.txt b/Modules/ToFHardware/Kinect/CMakeLists.txt index e4342230e2..a7c5376a0c 100644 --- a/Modules/ToFHardware/Kinect/CMakeLists.txt +++ b/Modules/ToFHardware/Kinect/CMakeLists.txt @@ -1,26 +1,25 @@ #Begin Kinect hardware OPTION(MITK_USE_TOF_KINECT "Enable support for Kinect camera" OFF) IF(MITK_USE_TOF_KINECT) mitkFunctionCheckCompilerFlags("-Wno-error=unknown-pragmas" CMAKE_CXX_FLAGS) mitkFunctionCheckCompilerFlags("-Wno-error=reorder" CMAKE_CXX_FLAGS) FIND_LIBRARY(MITK_KINECT_LIB libOpenNI DOC "Kinect access library.") FIND_PATH(MITK_KINECT_INCLUDE_DIR XnCppWrapper.h DOC "Include directory of Kinect camera.") SET(MITK_TOF_AVAILABLE_CAMERAS ${MITK_TOF_AVAILABLE_CAMERAS},Microsoft Kinect) SET(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_KINECT_INCLUDE_DIR}) SET(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_KINECT_LIB}) MITK_CREATE_MODULE( - SUBPROJECTS MITK-ToF INCLUDE_DIRS PUBLIC ${MITK_BIN_DIR} PRIVATE ${INCLUDE_DIRS_INTERNAL} DEPENDS MitkToFHardware ADDITIONAL_LIBS ${ADDITIONAL_LIBS} AUTOLOAD_WITH MitkToFHardware ) Message("Kinect Module generated") add_subdirectory(Testing) ENDIF(MITK_USE_TOF_KINECT) #End Kinect Hardware diff --git a/Modules/ToFHardware/KinectV2/CMakeLists.txt b/Modules/ToFHardware/KinectV2/CMakeLists.txt index e1b35b9d9f..fcfab10ee9 100644 --- a/Modules/ToFHardware/KinectV2/CMakeLists.txt +++ b/Modules/ToFHardware/KinectV2/CMakeLists.txt @@ -1,21 +1,20 @@ OPTION(MITK_USE_TOF_KINECTV2 "Enable support for Kinect V2 camera" OFF) IF(MITK_USE_TOF_KINECTV2) FIND_LIBRARY(MITK_KINECTV2_LIB KinectV20.lib DOC "Kinect V2 access library.") FIND_PATH(MITK_KINECTV2_INCLUDE_DIR Kinect.h DOC "Include directory of Kinect V2 camera.") SET(MITK_TOF_AVAILABLE_CAMERAS ${MITK_TOF_AVAILABLE_CAMERAS},Microsoft Kinect V2) SET(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_KINECTV2_INCLUDE_DIR}) SET(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_KINECTV2_LIB}) MITK_CREATE_MODULE( - SUBPROJECTS MITK-ToF INCLUDE_DIRS ${MITK_BIN_DIR} INTERNAL_INCLUDE_DIRS ${INCLUDE_DIRS_INTERNAL} DEPENDS MitkToFHardware MitkOpenCVVideoSupport ADDITIONAL_LIBS ${ADDITIONAL_LIBS} AUTOLOAD_WITH MitkToFHardware ) Message("Kinect V2 Module generated") add_subdirectory(Testing) ENDIF(MITK_USE_TOF_KINECTV2) diff --git a/Modules/ToFHardware/MesaSR4000/CMakeLists.txt b/Modules/ToFHardware/MesaSR4000/CMakeLists.txt index fb5efc890c..80575d9ddd 100644 --- a/Modules/ToFHardware/MesaSR4000/CMakeLists.txt +++ b/Modules/ToFHardware/MesaSR4000/CMakeLists.txt @@ -1,28 +1,27 @@ #Begin MESA SR4000 hardware OPTION(MITK_USE_TOF_MESASR4000 "Enable support for MESA SR4000" OFF) IF(MITK_USE_TOF_MESASR4000) FIND_LIBRARY(MITK_MESA_LIB libMesaSR DOC "MESA access library.") GET_FILENAME_COMPONENT(MITK_MESA_SDK_DIR ${MITK_MESA_LIB} PATH) SET(MITK_MESA_SDK_DIR ${MITK_MESA_SDK_DIR}/..) FIND_PATH(MITK_MESA_INCLUDE_DIR libMesaSR.h ${MITK_MESA_SDK_DIR}/include DOC "Include directory of MESA-SDK.") SET(MITK_TOF_AVAILABLE_CAMERAS ${MITK_TOF_AVAILABLE_CAMERAS},MESA Swissranger 4000) IF(WIN32) INSTALL(FILES ${MITK_MESA_SDK_DIR}/bin/libMesaSR.dll DESTINATION bin CONFIGURATIONS Release) ENDIf(WIN32) set(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_MESA_SDK_DIR}/include) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_MESA_LIB}) MITK_CREATE_MODULE( - SUBPROJECTS MITK-ToF INCLUDE_DIRS ${MITK_BIN_DIR} INTERNAL_INCLUDE_DIRS ${INCLUDE_DIRS_INTERNAL} DEPENDS MitkToFHardware ADDITIONAL_LIBS ${ADDITIONAL_LIBS} AUTOLOAD_WITH MitkToFHardware ) Message("MESASR4000 Module generated") add_subdirectory(Testing) ENDIF(MITK_USE_TOF_MESASR4000) #End MESA SR4000 Hardware diff --git a/Modules/ToFHardware/PMD/CMakeLists.txt b/Modules/ToFHardware/PMD/CMakeLists.txt index 0e2aaca2cd..baddf03e07 100644 --- a/Modules/ToFHardware/PMD/CMakeLists.txt +++ b/Modules/ToFHardware/PMD/CMakeLists.txt @@ -1,102 +1,101 @@ #Begin PMD Module OPTION(MITK_USE_TOF_PMDCAMCUBE "Enable support for Cam Cube camera" OFF) IF(WIN32) IF(_PLATFORM_STRING MATCHES "W32") OPTION(MITK_USE_TOF_PMDCAMBOARD "Enable support for PMD camboard" OFF) ENDIF(_PLATFORM_STRING MATCHES "W32") ElSE(WIN32) OPTION(MITK_USE_TOF_PMDCAMBOARD "Enable support for PMD camboard" OFF) ENDIF(WIN32) IF(WIN32) IF(_PLATFORM_STRING MATCHES "W32") OPTION(MITK_USE_TOF_PMDO3 "Enable support for PMD O3" OFF) ENDIF(_PLATFORM_STRING MATCHES "W32") ENDIF(WIN32) SET(MITK_USE_PMD OFF) IF(MITK_USE_TOF_PMDO3 OR MITK_USE_TOF_PMDCAMCUBE OR MITK_USE_TOF_PMDCAMBOARD) SET(MITK_USE_PMD ON) ENDIF(MITK_USE_TOF_PMDO3 OR MITK_USE_TOF_PMDCAMCUBE OR MITK_USE_TOF_PMDCAMBOARD) #Creating Basics for all PMD devices IF(MITK_USE_PMD) #-----Setting generall Path----- FIND_LIBRARY(MITK_PMD_LIB pmdaccess2 DOC "PMD access library.") GET_FILENAME_COMPONENT(MITK_PMD_SDK_DIR ${MITK_PMD_LIB} PATH) SET(MITK_PMD_SDK_DIR ${MITK_PMD_SDK_DIR}/.. CACHE INTERNAL "PMD SDK directory") FIND_PATH(MITK_PMD_INCLUDE_DIR pmdsdk2.h ${MITK_PMD_SDK_DIR}/include DOC "Include directory of PMD-SDK.") Set(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_PMD_SDK_DIR}/include) Set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_PMD_LIB}) #-----Creating the PMD-Module itself----- MITK_CREATE_MODULE( - SUBPROJECTS MITK-ToF INCLUDE_DIRS ${MITK_BINARY_DIR} INTERNAL_INCLUDE_DIRS ${INCLUDE_DIRS_INTERNAL} DEPENDS MitkToFHardware ADDITIONAL_LIBS ${ADDITIONAL_LIBS} AUTOLOAD_WITH MitkToFHardware ) Message("PMD Module generated") add_subdirectory(Testing) ENDIF(MITK_USE_PMD) #Only for CamCube IF(MITK_USE_TOF_PMDCAMCUBE) # message(${MITK_BINARY_DIR}) # message(${MITK_PMD_SDK_DIR}) # message(${_PLATFORM_STRING}) configure_file(${MITK_PMD_SDK_DIR}/plugins/camcube3.${_PLATFORM_STRING}.pap ${MITK_BINARY_DIR}/bin/camcube3.${_PLATFORM_STRING}.pap COPYONLY) configure_file(${MITK_PMD_SDK_DIR}/plugins/camcubeproc.${_PLATFORM_STRING}.ppp ${MITK_BINARY_DIR}/bin/camcubeproc.${_PLATFORM_STRING}.ppp COPYONLY) IF(_PLATFORM_STRING MATCHES "W32") configure_file(${MITK_PMD_SDK_DIR}/plugins/pmdfile.${_PLATFORM_STRING}.pcp ${MITK_BINARY_DIR}/bin/pmdfile.${_PLATFORM_STRING}.pap COPYONLY) ENDIF() SET(MITK_TOF_PMD_CAMCUBE_SOURCE camcube3.${_PLATFORM_STRING}.pap) SET(MITK_TOF_PMD_CAMCUBE_PROC camcubeproc.${_PLATFORM_STRING}.ppp) IF(_PLATFORM_STRING MATCHES "W32") SET(MITK_TOF_PMD_FILE_SOURCE pmdfile.${_PLATFORM_STRING}.pcp) ENDIF() SET(MITK_TOF_AVAILABLE_CAMERAS ${MITK_TOF_AVAILABLE_CAMERAS},PMD CamCube 2.0/3.0,PMD CamCubeRaw 2.0/3.0,PMD Player,PMD Raw Data Player) Message("PMDCamCube activated") ENDIF(MITK_USE_TOF_PMDCAMCUBE) #-------------------------------Begin CamBoard hardware------------------------------------------- IF(MITK_USE_TOF_PMDCAMBOARD) IF(_PLATFORM_STRING MATCHES "W32") configure_file(${MITK_PMD_SDK_DIR}/plugins/camboard.${_PLATFORM_STRING}.pap ${MITK_BINARY_DIR}/bin/camboard.${_PLATFORM_STRING}.pap COPYONLY) configure_file(${MITK_PMD_SDK_DIR}/plugins/camboardproc.${_PLATFORM_STRING}.ppp ${MITK_BINARY_DIR}/bin/camboardproc.${_PLATFORM_STRING}.ppp COPYONLY) ENDIF() SET(MITK_TOF_PMD_CAMBOARD_SOURCE camboard.${_PLATFORM_STRING}.pap) SET(MITK_TOF_PMD_CAMBOARD_PROC camboardproc.${_PLATFORM_STRING}.ppp) SET(MITK_TOF_AVAILABLE_CAMERAS ${MITK_TOF_AVAILABLE_CAMERAS},PMD CamBoard,PMD CamBoardRaw) # FILE(GLOB MITK_TOF_PMD_CAMBOARD_SOURCE camboard.${_PLATFORM_STRING}.pap) # FILE(GLOB MITK_TOF_PMD_CAMBOARD_PROC camboardproc.${_PLATFORM_STRING}.ppp) # FILE(GLOB MITK_TOF_PMD_FILE_SOURCE ${MITK_PMD_SDK_DIR}/plugins/pmdfile.${_PLATFORM_STRING}.pcp) Message("PMDCamBoard activated") ENDIF(MITK_USE_TOF_PMDCAMBOARD) #----------------------------------------Begin PMD O3 hardware-------------------------------------------- # only if PMD O3 is enabled IF(WIN32 AND MITK_USE_TOF_PMDO3) Message("PMDO3 is activated") configure_file(${MITK_PMD_SDK_DIR}/plugins/o3d.${_PLATFORM_STRING}.pcp ${MITK_BINARY_DIR}/bin/o3d.${_PLATFORM_STRING}.pcp COPYONLY) configure_file(${MITK_PMD_SDK_DIR}/plugins/o3d.${_PLATFORM_STRING}.pcp ${MITK_BINARY_DIR}/bin/o3d.${_PLATFORM_STRING}.pcp COPYONLY) SET(MITK_TOF_PMD_O3D_SOURCE o3d.${_PLATFORM_STRING}.pcp) SET(MITK_TOF_PMD_O3D_PROC o3d.${_PLATFORM_STRING}.pcp) SET(MITK_TOF_AVAILABLE_CAMERAS ${MITK_TOF_AVAILABLE_CAMERAS},PMD O3D) ENDIF() #Generate the mitkToFPMDConfig.h file which is used internally CONFIGURE_FILE(mitkToFPMDConfig.h.in ${PROJECT_BINARY_DIR}/mitkToFPMDConfig.h @ONLY) diff --git a/Modules/ToFProcessing/CMakeLists.txt b/Modules/ToFProcessing/CMakeLists.txt index 51c57e409b..5e2e9cc973 100644 --- a/Modules/ToFProcessing/CMakeLists.txt +++ b/Modules/ToFProcessing/CMakeLists.txt @@ -1,13 +1,12 @@ MITK_CREATE_MODULE( - SUBPROJECTS MITK-ToF DEPENDS MitkCameraCalibration PACKAGE_DEPENDS OpenCV WARNINGS_NO_ERRORS ) if(BUILD_TESTING) add_subdirectory(Testing) endif(BUILD_TESTING) diff --git a/Modules/ToFUI/CMakeLists.txt b/Modules/ToFUI/CMakeLists.txt index 2eaf906d34..c625537b6a 100644 --- a/Modules/ToFUI/CMakeLists.txt +++ b/Modules/ToFUI/CMakeLists.txt @@ -1,7 +1,6 @@ MITK_CREATE_MODULE( - SUBPROJECTS MITK-ToF INCLUDE_DIRS Qmitk DEPENDS MitkToFHardware MitkToFProcessing MitkQtWidgetsExt PACKAGE_DEPENDS CTK|CTKWidgets ) diff --git a/Plugins/org.mitk.core.services/CMakeLists.txt b/Plugins/org.mitk.core.services/CMakeLists.txt index ab0342e947..b490a1a9cb 100644 --- a/Plugins/org.mitk.core.services/CMakeLists.txt +++ b/Plugins/org.mitk.core.services/CMakeLists.txt @@ -1,8 +1,7 @@ project(org_mitk_core_services) mitk_create_plugin( EXPORT_DIRECTIVE MITK_CORE_SERVICES_PLUGIN EXPORTED_INCLUDE_SUFFIXES src - SUBPROJECTS MITK-CoreUI MODULE_DEPENDS PUBLIC MitkCore ) diff --git a/Plugins/org.mitk.gui.common/CMakeLists.txt b/Plugins/org.mitk.gui.common/CMakeLists.txt index 4708013faa..3c3fcd88a7 100644 --- a/Plugins/org.mitk.gui.common/CMakeLists.txt +++ b/Plugins/org.mitk.gui.common/CMakeLists.txt @@ -1,9 +1,8 @@ project(org_mitk_gui_common) mitk_create_plugin( EXPORT_DIRECTIVE MITK_GUI_COMMON_PLUGIN EXPORTED_INCLUDE_SUFFIXES src MODULE_DEPENDS MitkQtWidgets - SUBPROJECTS MITK-CoreUI ) diff --git a/Plugins/org.mitk.gui.qt.application/CMakeLists.txt b/Plugins/org.mitk.gui.qt.application/CMakeLists.txt index 04efa26bd0..5790187d9c 100644 --- a/Plugins/org.mitk.gui.qt.application/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.application/CMakeLists.txt @@ -1,9 +1,8 @@ project(org_mitk_gui_qt_application) mitk_create_plugin( EXPORT_DIRECTIVE MITK_QT_APP EXPORTED_INCLUDE_SUFFIXES src MODULE_DEPENDS MitkQtWidgets MitkQtWidgetsExt PACKAGE_DEPENDS Qt5|OpenGL+Xml - SUBPROJECTS MITK-CoreUI ) diff --git a/Plugins/org.mitk.gui.qt.common.legacy/CMakeLists.txt b/Plugins/org.mitk.gui.qt.common.legacy/CMakeLists.txt index 720f7b98a3..50b2016664 100755 --- a/Plugins/org.mitk.gui.qt.common.legacy/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.common.legacy/CMakeLists.txt @@ -1,8 +1,7 @@ project(org_mitk_gui_qt_common_legacy) mitk_create_plugin( EXPORT_DIRECTIVE MITK_QT_COMMON_LEGACY EXPORTED_INCLUDE_SUFFIXES src MODULE_DEPENDS MitkQtWidgets - SUBPROJECTS MITK-CoreUI ) diff --git a/Plugins/org.mitk.gui.qt.common/CMakeLists.txt b/Plugins/org.mitk.gui.qt.common/CMakeLists.txt index d30d57f00e..7211d902fb 100755 --- a/Plugins/org.mitk.gui.qt.common/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.common/CMakeLists.txt @@ -1,8 +1,7 @@ project(org_mitk_gui_qt_common) mitk_create_plugin( EXPORT_DIRECTIVE MITK_QT_COMMON EXPORTED_INCLUDE_SUFFIXES src MODULE_DEPENDS MitkQtWidgets - SUBPROJECTS MITK-CoreUI ) diff --git a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/Manual.dox index 93f1b219bb..2e852eeafa 100644 --- a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/Manual.dox +++ b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/Manual.dox @@ -1,50 +1,56 @@ /** -\page org_mitk_gui_qt_matchpoint_evaluator The MatchPoint Registration Evaluation View +\page org_mitk_views_matchpoint_evaluator The MatchPoint Registration Evaluation View \imageMacro{map_evaluator_doc.svg, "Icon of the MatchPoint Registration Evaluator", 3} \tableofcontents \section MAP_REGEVAL_Introduction Introduction This view offers the possibility to evaluate the quality of the registration/mapping of two given images by visual inspection. -One may select no registration. Then the images will be displayed in evaluation mode assuming an identity transform (so no mapping). +This can either by used to assess the visual quality of a registration or to assess how well the image contents are already aligned +by default. To achieve the latter, one may select no registration. Then the images will be displayed in evaluation mode assuming an identity transform (so no mapping). It is one of several MatchPoint registration plug-ins.\n -\section MAP_REGEVAL_Contact Contact information -This plug-in is being developed by the SIDT group (Software development for Integrated Diagnostics -and Therapy) at the German Cancer Research Center (DKFZ). If you have any questions, need support, -find a bug or have a feature request, feel free to contact us at www.mitk.org. - \section MAP_REGEVAL_Usage Usage -\imageMacro{map_view_example.png, "Example screenshot showing the plug-in in use.", 14} -To use the evaluation view you must have selected at least the moving and the target image you want to use to evaluate. -If you select a registration with referenced target and moving image (the normal state if you generate registrations with the MatchPoint plugins) -these images will be auto selected by just clicking on the registration. -If you select no registration the view will assume that an identity transform should be used.\n -As long as no valid set of data is selected the "Start evaluation" button will be disabled. If its enabled you may start the evaluation mode with it. - -\imageMacro{map_no_data_selected.png, "Example screenshot showing the state if no data is selected", 5} +\imageMacro{map_view_evaluator_example.png, "Example screenshot showing the main elements of the view.", 14} +(1) The currently selected registration that should be used to map the moving image for evaluation. Click to change. If no registration is selected, a direct evaluation will be performed.\n +(2) Reset button will remove the currently selected registration.\n +(3) Auto select option. If active the view will try to deduce and automatically select (if loaded in the application) the moving and target image when the registration changes. The view assumes that the moving and target images used to determine the registration should be used.\n +(4) The currently selected moving data. Click to change.\n +(5) The currently selected target data. Click to change.\n +(6) Start/Stop button used to activate/deactivate the evaluation. This button become active when at least the moving and the target image are selected.\n +(7) Selection of the visualization style. (only visible if evaluation is active)\n +(8) Style specific settings. (only visible if evaluation is active)\n If the evaluation view is active you can choose between different modes of visualization. For more details see \ref MAP_REGEVAL_Styles.\n To stop the evaluation mode, you may use the "Stop evaluation" button or just close the evaluation view. -\remark The evaluation view will use the level window settings of the used images. So to changes the level windowing of the evaluation view, you must change the -level windowing of the respective images. +\remark The evaluation view will use the level window settings of the used images. So to change the level windowing of the evaluation view, you must change the +level windowing of the respective input images (moving image and target image). + +\section MAP_REGEVAL_Accuracy Evaluating accuracy +Important note: Please be aware, that a visual inspection of registration quality is only a weak surrogate for a thorough accuracy analysis based on representative and suitable ground truth data. From a visually good mapping you can not deduce a correct registration. This is especially true if the degrees of freedom of the registration increases. For a rigid registration it might by feasible to discern correct and incorrect registration. But for none rigid registrations you definitely you should use this view only for first visual inspection (to check if it SEEMS to do the right thing and is worth further exploration) or illustrating the registration effect for registration you have assessed in a sound way. \section MAP_REGEVAL_Styles Visualization styles You can choose from the following visualization styles to evaluate the registration/mapping quality:\n \li "Blend": Blends the images with a user defined weight. Default is 50:50. -\imageMacro{map_style_blend.png, "Example for mode: Blend", 5} -\li "Checkerboard": Checkerboard style that composes both images. You may define the resolution of the checkerboard. +\imageMacro{map_view_blend_settings.png, "Settings of the Blend style", 8} +(1) Click to set the weights to 100% target image.\n +(2) Click to set the weights to 50:50 (equal blend).\n +(3) Slider to adjust the weights between target image and the mapped input image. The spin box shows the weight of the mapped input image.\n +(4) Click to set the weights to 100% mapped input image.\n +(5) Click to toggle the weight between both images.\n +\imageMacro{map_style_blend.png, "Example for mode: Blend (50:50)", 5} +\li "Checkerboard": Checkerboard style that composes both images by showing image 1 in all light squares and image 2 in all dark squares. You can define the resolution/number of squares of the checkerboard. \imageMacro{map_style_checkerboard.png, "Example for mode: Checkerboard", 5} \li "Color blend": Color blend of the images (blue: target image; yellow: moving). Areas where you see no color implies good intensity matchings. \imageMacro{map_style_color_blend.png, "Example for mode: Color blend", 5} -\li "Contour": Blend mode that display one image as blue "background" and the other image in yellow contours. You may choose the role of the images. +\li "Contour": Blend mode that displays one image as blue "background" and the other image in yellow contours. You can choose the role of the images. \imageMacro{map_style_contour.png, "Example for mode: Contour", 5} \li "Difference": Displays the absolute difference of both images. \li "Wipe": Blend mode that makes a rectilinear combination of the images. You can choose the mode how the images are splitted. The split is synchronized with the current selection. So you may interact with the split border to position it on interesting areas. \imageMacro{map_style_wipe_cross.png, "Example for mode: Wipe cross", 5} \imageMacro{map_style_wipe_horizontal.png, "Example for mode: Wipe horizontal", 5} */ diff --git a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_no_data_selected.png b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_no_data_selected.png deleted file mode 100644 index 2a72cfa281..0000000000 Binary files a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_no_data_selected.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_blend_settings.png b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_blend_settings.png new file mode 100644 index 0000000000..ff4c1c314a Binary files /dev/null and b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_blend_settings.png differ diff --git a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_blend_settings.svg b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_blend_settings.svg new file mode 100644 index 0000000000..91573fb6d3 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_blend_settings.svg @@ -0,0 +1,398 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (3) Slider to adjust weighting + (4) Set to 100% mapped visibility + (5) Toggle weighting + + (2) Set to 50:50 visibility + + (1) Set to 100% target visibility + diff --git a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_evaluator_example.png b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_evaluator_example.png new file mode 100644 index 0000000000..e29f63b0d9 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_evaluator_example.png differ diff --git a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_evaluator_example.svg b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_evaluator_example.svg new file mode 100644 index 0000000000..ae70bf0a5b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_evaluator_example.svg @@ -0,0 +1,409 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (1) Registration slot + (7) Evaluation styles + (2) Registration reset + (4) Moving image slot + (5) Target image slot + (6) Start/Stop button + (8) Style specific settings + + (3) Auto select option + diff --git a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_evaluator_example_raw.png b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_evaluator_example_raw.png new file mode 100644 index 0000000000..ce373edb1b Binary files /dev/null and b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_evaluator_example_raw.png differ diff --git a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_example.png b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_example.png deleted file mode 100644 index 496925adee..0000000000 Binary files a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/documentation/UserManual/map_view_example.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/plugin.xml b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/plugin.xml index 015b7372b2..ab99f800b2 100644 --- a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/plugin.xml +++ b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/plugin.xml @@ -1,12 +1,12 @@ - diff --git a/Plugins/org.mitk.gui.qt.matchpoint.manipulator/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.matchpoint.manipulator/documentation/UserManual/Manual.dox index d4af889568..c00ab5da9b 100644 --- a/Plugins/org.mitk.gui.qt.matchpoint.manipulator/documentation/UserManual/Manual.dox +++ b/Plugins/org.mitk.gui.qt.matchpoint.manipulator/documentation/UserManual/Manual.dox @@ -1,69 +1,69 @@ /** \page org_mitk_gui_qt_matchpoint_manipulator The MatchPoint Registration Manipulator View \imageMacro{map_manipulator_icon_doc.svg, "Icon of the MatchPoint Registration Manipulator", 3} \tableofcontents \section MAP_REGMANIP_Introduction Introduction This view offers the possibility to manually manipulate a registration to establish a good mapping between data. The effect of manipulation is visualized with to user defined images to allow visual inspection.\n It is one of several MatchPoint registration plug-ins.\n \imageMacro{map_view_example.png, "Example screenshot showing the plug-in in use", 10} \section MAP_REGMANIP_Contact Contact information This plug-in is being developed by the SIDT group (Software development for Integrated Diagnostics and Therapy) at the German Cancer Research Center (DKFZ). If you have any questions, need support, find a bug or have a feature request, feel free to contact us at www.mitk.org. \section MAP_REGMANIP_Usage Usage \imageMacro{map_view_steps.png, "Illustration of the workflow steps.", 7} The typical workflow with the manipulator has following steps/sections: 1. Source selection: You can choose between starting a new registration and using a selected registration. For later option, the registration must be selected in the data manager. \remark If you choose a new registration, the manipulator will automatically pre initialize this new transform to align the centers of the used images and therefore starts with sensible settings. \remark If you choose an existing registration, the registration will *not* be altered. It serves as template/baseline for the manipulation, which will be "on top" of the existing registration. 2. Image selection: To allow visual inspection of the manipulation to images are needed. If you have selected a registration (independent from the source selection mode) the manipulator will use the moving and target images used to determine the selected registration as images for the manipulation. You can also explicitly select images in the data manager (press shift while selecting for multi select). 3. Start manual registration: If all settings are valid, you can start the manipulation. The render windows will automatically switch to the visual inspection mode. The views will be reinitialized to the field of view of the target image. 4. Generation settings: You may choose to give the resulting registration a special name. Additionally you can choose the convenience option to map the moving image with the confirmed registration automatically. 5. Settings: You can alter the settings of the transform (\ref MAP_REGMANIP_TransSettings) and the rendering settings (\ref MAP_REGMANIP_EvalSettings) for the visual inspection. 6. Cancel or confirmation: You may cancel the manipulation process (Closing the view equals cancelation) or confirm the determined registration and store it in the data storage with the given name.\n \section MAP_REGMANIP_TransSettings Transformation settings You can alter the translation and the rotation of the transform. In addition you may choose the center of rotation type. You have the following options:\n - Moving image center: Rotate around the center of the moving image. - World origin: Rotate around (0.0,0.0,0.0), the world origin. - Current navigator position: Rotate around the current navigator position in the render views. \remark FAQ: Why are the translation values "jumping" when I change the center mode or when I am rotating?\n The reason is the relation between center, rotation, and translation.\n A transformation is defined as x' = R (x - C) + C + T\n where x': transformed point; x: point to transform; R: rotation matrix; C: center point; T: translation vector.\n The offset of a transform is defined as O = -RC + C + T\n The offset as well as the rotation matrix stay constant if the center point changes, therefore the translation has to be altered. \note To ease the orientation, the edit fields have background colours which resemble the colours of the plane the changes will "happen".\n For translation, the translation vector will be perpendicular to the indicated plane (The image moves "through" the plane). For rotation, the rotation axis will be perpendicular to the indicated plane. \section MAP_REGMANIP_EvalSettings Evaluation settings -The settings you can choose are equal to the settings of the evaluation view (\ref org_mitk_gui_qt_matchpoint_evaluator). +The settings you can choose are equal to the settings of the evaluation view (\ref org_mitk_views_matchpoint_evaluator). Please see the documentation of the MatchPoint Registration Evaluator view for more details. */ diff --git a/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/Manual.dox index 76b20f6419..c3f3652037 100644 --- a/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/Manual.dox +++ b/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/Manual.dox @@ -1,85 +1,79 @@ /** -\page org_mitk_gui_qt_matchpoint_mapper The MatchPoint Image Mapper View +\page org_mitk_views_matchpoint_mapper The MatchPoint Image Mapper View \imageMacro{map_mapper_icon_doc.svg, "Icon of the MatchPoint Image Mapper",3} \tableofcontents \section MAP_MAPPER_Introduction Introduction -This view offers the possibility to map any image or point set in the data manager using a user selected registration object. -Using the Mapper to map images the user can control the field of view (image geometry) the image should be mapped into, as well as -interpolation strategy that should be used.\n -It is one of several MatchPoint registration plugins.\n -Typical usage scenarios\n -\li You have registered image I1 onto image I2. Now you want to transfer the segmentation of I1 to I2 in order to evaluate I2 within this mapped segmentation using \ref org_mitk_views_imagestatistics . -\li You have registered image I1 onto image I2. Now you want to map I3 (e.g. an other MRI sequence of the same session) also onto I2 with the same registration. -\li You have registered image I1 onto image I2. Now you want to map a segmentation done on I1 also onto I2 with the same registration. -\li You have registered image I1 onto image I2. Now you want to map a point set of image I1 also onto I2 with the same registration. +This view offers the possibility to map any loaded image or point set using a user selected registration object. +When mapping images the user can control the field of view (image geometry) the image should be mapped into, as well as the interpolation strategy and padding values that should be used. + +It is one of several MatchPoint registration plugins. -\section MAP_MAPPER_Contact Contact information -This plug-in is being developed by the SIDT group (Software development for Integrated Diagnostics -and Therapy) at the German Cancer Research Center (DKFZ). If you have any questions, need support, -find a bug or have a feature request, feel free to contact us at www.mitk.org. +Typical usage scenarios\n +You have registered image I1 onto image I2. Now you want to +\li (Most obvious) map I1 onto I2 with the registration, e.g. to make a joint statistical analysis. +\li map image I3 (e.g. an other MRI sequence of the same session) also onto I2 with the same registration. +\li map a segmentation created on I1 also onto I2 with the same registration. +\li map a point set of image I1 also onto I2 with the same registration. \section MAP_MAPPER_Usage Usage -\imageMacro{map_mapper-examplescreen.png, "Example screenshot showing the Mapper plugin in use.", 14} -To use the mapper at least an input data (image or point set) must be selected. Additionally you may select a registration object and a reference image. -Registration objects are marked with a small blue icon (e.g. the data "Registration" in the data manager of the screen shot above). -The Reference image defines the geometry (field of view, orientation, spacing) that should be used for the result image. -By default the view will try to automatically determine the reference image (by default it is the target image of the selected registration). -If auto selection cannot determine the reference it will choose the input image as reference. -The reference image can be also defined by the user explicitly by activating manual selection.\n -REMARK: If you map point sets you can ignore the reference image slot. It has no affect.\n -You can multi select registration and data (press the CTRL-key while selecting the nodes in the data manager). -The Mapper will automatically sort the selections in the correct "slots" of the view.\n -REMARK: The mapping results will be added as child nodes to the used input node.\n +To use the mapper at least the input (image or point set) must be selected. Additionally, you may select a registration object and, in case the input is an image, an optional reference image. + +The reference image defines the geometry (field of view, orientation, spacing) that should be used for the result image. +The view will try to automatically determine the reference image. By default it is the target image that was used to determine the selected registration. +If auto selection cannot determine the reference (e.g. because it was not specified or it is currently not loaded), the input image will be selected as reference. +The reference image can be also defined by the user explicitly by activating manual selection. + +REMARK: If you map point sets you can ignore the reference image slot. It has no effect. + +REMARK: The mapping results will be added as child nodes to the used input node. + REMARK: If you do not select an registration the view will assume that you make an identity transform. This is a convenient way if you just want to resample an image into the geometry of an other image (when no registration is needed). Also in this use case you can take advantage of the different interpolation and sub/super sampling strategies. -\imageMacro{map_mapper.png, "Details of the mapper view.", 8} -(1) The currently selected registration, that will be used for mapping.\n -(2) The currently selected input data, that will be mapped.\n -(3) The currently (automatically or by user) selected reference image, that defines the geometry of the result.\n -(4) The name of the result data in the data manger.\n -(5) The start button(s) to commence the mapping process. For details regarding the two options see \ref MAP_MAPPER_Refine.\n -(6) Log windows with messages regarding the mapping process.\n\n +\imageMacro{map_mapper_instructions.png, "Main elements of the mapper view.", 7} +(1) The currently selected registration that will be used for mapping. Click to change.\n +(2) Reset button that will remove the current selected registration and switch back to an identity transform.\n +(3) The currently selected input data, that will be mapped. Click to change.\n +(4) The currently (automatically or by user) selected reference image, that defines the geometry of the result. Click to change.\n +(5) The name of the result data in the data manager.\n +(6) The start button(s) to commence the mapping process. For details regarding the two options see \ref MAP_MAPPER_Refine.\n +(7) Log windows with messages regarding the mapping process.\n -Every "slot" has the ability to be locked. If locked the last selection will be kept, regardless the current selection in the data manager. -You can use this for example to lock the registration, if you want to map multiple images. Doing so it is enough to just select the next image -in the data manager. To lock a slot, click at the "lock" button at the right side (see example images below). -\imageMacro{map_node-unlocked.png, "Unlocked slot/node (default state). Changes with the selections in the data manager.",6} -\imageMacro{map_node-locked.png, "Locked slot/node. Stays, regardless the selections in the data manager.",6} \section MAP_MAPPER_Refine Mapping or geometry refinement The mapper view offers two options to map images:\n \li "Map" (default) \li "Refine geometry" -For images "Map" fills the pixels of the output image by interpolating input image pixels using the registration object. This option always works. -But may take longer and introduces interpolation errors, because a new image is resampled.\n -The second option "Refine geometry" is only offered, if the registration (more precise its inverse kernel) is matrix based and the selected data is an image. +For images "Map" fills the pixels of the output image by interpolating input image pixels using the registration object. This option always works, +but may take longer and introduces interpolation errors, because a new image is resampled.\n +The second option "Refine geometry" is only offered, if the registration (more precisely its inverse kernel) is matrix based and the selected data is an image. In this case it just clones the image and refines its image geometry (origin and orientation) to project it to the position indicated by the registration; thus no interpolation artefacts are introduced. -\remark If you want to use a mapped image in conjunction with the statistic plugin and an mask of the reference image (or you want to proceed any other computation that expects the voxel to be in the same grid for direct numeric comparison), you must use "Map" to ensure the same geometry -(including the same image grid; including same spacing and resolution). Otherwise operations like the statistic plugin will fail. +\remark If you want to use a mapped image in conjunction with the image statistics plugin and a mask of the reference image (or you want to proceed any other computation that expects the voxel to be in the same grid for direct numeric comparison), you must use "Map" to ensure the same geometry +(including the same image grid; including same spacing and resolution). Otherwise operations like the images statistics plugin will fail. \section MAP_MAPPER_Settings Settings +\imageMacro{map_mapper-settings.png, "Available settings for mapping images.", 7} If you map the image (and not just refine the geometry), you have several settings available:\n -\li "Allow undefined pixels": Activate to handle pixels of the result image that are not in the field of view of the input image. This pixel will get the "padding value". -\li "Allow error pixels": Activate to handle pixels of the result image that can not be mapped because the registration does not support this part of the output image. This pixel will get the "error value". +\li "Allow undefined pixels": Activate to handle pixels of the result image that are not in the field of view of the input image. These pixels will get the "padding value". +\li "Allow unregistered pixels": Activate to handle pixels of the result image that can not be mapped because the registration does not support this part of the output image. These pixels will get the "error value". \li "Interpolator": Set to choose the interpolation strategy that should be used for mapping. \li "Activate super/sub sampling": Activate if you want to use origin and orientation of the reference image but want to alter the spacing. \section MAP_MAPPER_Interpolation Interpolation You can choose from the following interpolation strategies:\n -\li "nearest neighbor": Use the value of the nearest pixel. Fastest, but high interpolation errors for gray value images. Right choice for label images or masks. +\li "Nearest Neighbor": Use the value of the nearest pixel. Fastest, but high interpolation errors for gray value images. Right choice for label images or masks. \li "Linear": Fast linear interpolation with often sufficient quality. Tends to blur edges. \li "BSpline (3rd order)": Good trade off between time and quality. \li "Windowed Sinc (Hamming)": Good interpolation quality but very time consuming. \li "Windowed Sinc (Welch)": Good interpolation quality but very time consuming. \section MAP_MAPPER_Masks Handling of masks/segmentations If you select an mask as input image, the plugin will be automatically reconfigured to settings that are suitable for the task of mapping masks. -Most importantly the interpolator will be set to "nearest neighbor". +Most importantly the interpolator will be set to "Nearest Neighbor". */ diff --git a/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper-examplescreen.png b/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper-examplescreen.png deleted file mode 100644 index 438d48fc90..0000000000 Binary files a/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper-examplescreen.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper-settings.png b/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper-settings.png index fb7ba5f47b..5e1e2d5d6f 100644 Binary files a/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper-settings.png and b/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper-settings.png differ diff --git a/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper.png b/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper.png index 2ddec78f8f..bbb2054937 100644 Binary files a/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper.png and b/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper.png differ diff --git a/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper_instructions.png b/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper_instructions.png new file mode 100644 index 0000000000..9c83eb21f1 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper_instructions.png differ diff --git a/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper_instructionsassets.svg b/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper_instructionsassets.svg new file mode 100644 index 0000000000..10fa218739 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_mapper_instructionsassets.svg @@ -0,0 +1,365 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (1) Registration slot + (6) Start buttons + (2) Registration reset + (3) Input slot + (4) Reference slot + (5) Result name + (7) Log + diff --git a/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_node-locked.png b/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_node-locked.png deleted file mode 100644 index abc66c27c4..0000000000 Binary files a/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_node-locked.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_node-unlocked.png b/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_node-unlocked.png deleted file mode 100644 index 4ec502eec3..0000000000 Binary files a/Plugins/org.mitk.gui.qt.matchpoint.mapper/documentation/UserManual/map_node-unlocked.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.matchpoint.mapper/src/internal/QmitkMatchPointMapper.ui b/Plugins/org.mitk.gui.qt.matchpoint.mapper/src/internal/QmitkMatchPointMapper.ui index fe48fae142..a1da741298 100644 --- a/Plugins/org.mitk.gui.qt.matchpoint.mapper/src/internal/QmitkMatchPointMapper.ui +++ b/Plugins/org.mitk.gui.qt.matchpoint.mapper/src/internal/QmitkMatchPointMapper.ui @@ -1,565 +1,565 @@ MatchPointMapperControls 0 0 392 816 5 5 5 5 5 Selected registration: 3 0 40 Input data (images or point sets): 3 0 40 Select reference manually instat of determined by registration... Select reference image manually: 3 0 40 true 0 false false false Execution 5 5 5 5 5 Mapped data name: Name of the resulting mapped image mappedImage <html><head/><body><p>Starts the mapping of the input image with the current settings.</p></body></html> Map false <html><head/><body><p>Applys the registration by refining the geometry of the data and not by resampling it. This option can only be selected if the chosen registration is 3D and can be decomposed in a rotation matrix and offset.</p></body></html> Refine geometry Log: 9 true QTextEdit::NoWrap true Clear log on mapping start Settings 5 5 5 5 5 0 0 50 false <html><head/><body><p>Allows that pixels may not be defined in the mapped image because they are outside of the field of view of the used input image.</p><p>The pixels will be marked with the given padding value.</p><p>If unchecked the mapping will be aborted in a case of undefined pixels.</p></body></html> Allow undefined pixels false true 5 9 5 9 5 Padding value: 0 0 Pixel value that indicates pixels that are outside of the input image -5000 5000 0 0 50 false <html><head/><body><p>Allows that pixels may not be registred because they are outside of the field of view of the used registration. The location in the correlated input image pixel(s) are therefore unkown. The pixels will be marked witrh the given error value.</p><p>If unchecked the mapping will be aborted in a case of unregistered pixels.</p></body></html> - Allow unregistred pixels + Allow unregistered pixels false true 5 5 5 Error value: 0 0 <html><head/><body><p>Value of pixels that cannot be registered because of an unsufficient field of view of the selected registration instance.</p></body></html> -5000 5000 0 0 Interpolator: true <html><head/><body><p>Interpolation function that should be used to map the pixel values from the input image into the result image.</p></body></html> 1 Nearest Neighbor Linear BSpline (3rd order) Windowed Sinc (Hamming) Windowed Sinc (Welch) 0 0 Activate super/sub sampling true false 5 <html><head/><body><p>Check to ensure that x, y and z dimension use the same sampling factor.</p></body></html> linked factors true 0 0 x: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter <html><head/><body><p>Indicate the sampling factor to change the resolution.</p><p>2.0: doubled resolution; e.g. 100 pixels -&gt; 200 pixels and spacing 1 -&gt; spacing 0.5</p><p>0.5: half resolution; e.g. 100 pixels -&gt; 50 pixels and spacing 1 -&gt; spacing 2</p></body></html> y: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter z: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Vertical QSizePolicy::Preferred 20 700 QmitkSingleNodeSelectionWidget QWidget
QmitkSingleNodeSelectionWidget.h
1
5 5 true true true
diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/documentation/UserManual/QmitkImageStatistics.dox b/Plugins/org.mitk.gui.qt.measurementtoolbox/documentation/UserManual/QmitkImageStatistics.dox index bf9108b366..f371747b7c 100644 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/documentation/UserManual/QmitkImageStatistics.dox +++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/documentation/UserManual/QmitkImageStatistics.dox @@ -1,55 +1,63 @@ /** \page org_mitk_views_imagestatistics The Image Statistics View \imageMacro{bar-chart2.svg,"Icon of the Image Statistics View",2.00} \section QmitkImageStatisticsUserManualSummary Summary This view provides an easy interface to quickly compute some features of a whole image or a region of interest. This document will tell you how to use this view, but it is assumed that you already know how to use MITK in general. Please see \ref QmitkImageStatisticsUserManualDetails for more detailed information on usage and supported filters. \section QmitkImageStatisticsUserManualDetails Details Manual sections: - \ref QmitkImageStatisticsUserManualOverview - \ref QmitkImageStatisticsUserManualUsage \section QmitkImageStatisticsUserManualOverview Overview This view provides an easy interface to quickly compute some features of a whole image or a region of interest. \imageMacro{QmitkMeasurementToolbox_Interface.png,"The interface",9.10} \section QmitkImageStatisticsUserManualUsage Usage To select the input data, either use the quick selection button (labeled "+"), or select the input data via the "Input Data" tab. \imageMacro{QmitkImageStatistics_InputData.png,"Select the input data via the \"Input data\" tab (marked red) or via the quick selection button (marked yellow)",10} +\subsection QmitkImageStatisticStatistics Statistics After selection of an image or a binary mask as input data, the image statistics are calculated and displayed in the "Statistics" section. If masks (ROIs: segmentations, planarfigures, ...) are selected, the statistics for these masks are shown. For time data the statistics for each time step are calculated correspondingly. An example of parts of the calculated statistical features (Mean, Median, StandardDeviation, RMS, Max, MaxPosition, Min, MinPosition, Voxel, Volume [mm^3], Skewness, Kurtosis, Uniformity, Entropy, MPP, UPP and Variance) for different timesteps and different masks is pictured below. \imageMacro{QmitkImageStatistics_statistics.png, "Example of parts of the statistics for different masks and timestamps", 1.00} Check "Ignore zero-valued voxels" to hide voxels with grayvalue zero. -Beneath the statistics window is the histogram window, which shows the histogram of the current selection. The histogram window is currently only available for a single image and/or mask: When selection multiple images and/or multiple masks, the histogram window is deactivated. +\subsection QmitkImageStatisticHistogram Histogram + +Beneath the statistics window is the histogram window, which shows the histogram of the current selection. + +The histogram window is currently only available for a single image and no or one ROI: When selection multiple images and/or multiple masks, the histogram window is deactivated! Draw a rectangular window with a pressed left button to zoom in on the histogram. With a double click in the view area you can zoom out to the default viewport. You can also pan the view in horizontal or vertical direction by dragging with the left mouse button in the respective direction. Additionally, different options like "Custom Zoom", to set the maximum and minimum value, or by adjusting the number of bins, can be used to modify the view. If the mask is not a closed planar figure or a segmentation an intensity profile is created instead of the histogram. A tooltip is available by hovering over one of the bins. +\subsection QmitkImageStatisticsUserManualCopytoClipboard Copy to Clipboard + At the bottom of each view is a "Copy to Clipboard" button, allowing to copy the respective data in csv format to the clipboard. +Be aware of the following information regarding this functionality: +\li The values are separated by tabulator. +\li Numeric values will be converted using the system language (e.g. with German as system language the decimal separator will be ",", with English it will be '.'). +\li One can directly copy'n'paste into Excel (and alike) as long as Excel supports/is configured to the system language -All other problems.
-Please report to the MITK mailing list. -See http://www.mitk.org/wiki/Mailinglist on how to do this. */ diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkMeasurementView.cpp b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkMeasurementView.cpp index 2954c3715c..1007251dc0 100644 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkMeasurementView.cpp +++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkMeasurementView.cpp @@ -1,872 +1,874 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkMeasurementView.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ctkDoubleSpinBox.h" #include "mitkPluginActivator.h" #include "usModuleRegistry.h" #include "mitkInteractionEventObserver.h" #include "mitkDisplayInteractor.h" #include "usGetModuleContext.h" #include "usModuleContext.h" #include US_INITIALIZE_MODULE struct QmitkPlanarFigureData { QmitkPlanarFigureData() : m_EndPlacementObserverTag(0), m_SelectObserverTag(0), m_StartInteractionObserverTag(0), m_EndInteractionObserverTag(0) { } mitk::PlanarFigure::Pointer m_Figure; unsigned int m_EndPlacementObserverTag; unsigned int m_SelectObserverTag; unsigned int m_StartInteractionObserverTag; unsigned int m_EndInteractionObserverTag; }; struct QmitkMeasurementViewData { QmitkMeasurementViewData() : m_LineCounter(0), m_PathCounter(0), m_AngleCounter(0), m_FourPointAngleCounter(0), m_CircleCounter(0), m_EllipseCounter(0), m_DoubleEllipseCounter(0), m_RectangleCounter(0), m_PolygonCounter(0), m_BezierCurveCounter(0), m_SubdivisionPolygonCounter(0), m_UnintializedPlanarFigure(false), m_ScrollEnabled(true), m_Parent(nullptr), m_SingleNodeSelectionWidget(nullptr), m_DrawLine(nullptr), m_DrawPath(nullptr), m_DrawAngle(nullptr), m_DrawFourPointAngle(nullptr), m_DrawRectangle(nullptr), m_DrawPolygon(nullptr), m_DrawCircle(nullptr), m_DrawEllipse(nullptr), m_DrawDoubleEllipse(nullptr), m_DrawBezierCurve(nullptr), m_DrawSubdivisionPolygon(nullptr), m_DrawActionsToolBar(nullptr), m_DrawActionsGroup(nullptr), m_SelectedPlanarFiguresText(nullptr), m_CopyToClipboard(nullptr), m_Layout(nullptr), m_Radius(nullptr), m_Thickness(nullptr), m_FixedParameterBox(nullptr) { } unsigned int m_LineCounter; unsigned int m_PathCounter; unsigned int m_AngleCounter; unsigned int m_FourPointAngleCounter; unsigned int m_CircleCounter; unsigned int m_EllipseCounter; unsigned int m_DoubleEllipseCounter; unsigned int m_RectangleCounter; unsigned int m_PolygonCounter; unsigned int m_BezierCurveCounter; unsigned int m_SubdivisionPolygonCounter; QList m_CurrentSelection; std::map m_DataNodeToPlanarFigureData; mitk::DataNode::Pointer m_SelectedImageNode; bool m_UnintializedPlanarFigure; bool m_ScrollEnabled; QWidget* m_Parent; QmitkSingleNodeSelectionWidget* m_SingleNodeSelectionWidget; QAction* m_DrawLine; QAction* m_DrawPath; QAction* m_DrawAngle; QAction* m_DrawFourPointAngle; QAction* m_DrawRectangle; QAction* m_DrawPolygon; QAction* m_DrawCircle; QAction* m_DrawEllipse; QAction* m_DrawDoubleEllipse; QAction* m_DrawBezierCurve; QAction* m_DrawSubdivisionPolygon; QToolBar* m_DrawActionsToolBar; QActionGroup* m_DrawActionsGroup; QTextBrowser* m_SelectedPlanarFiguresText; QPushButton* m_CopyToClipboard; QGridLayout* m_Layout; ctkDoubleSpinBox* m_Radius; ctkDoubleSpinBox* m_Thickness; QGroupBox* m_FixedParameterBox; }; const std::string QmitkMeasurementView::VIEW_ID = "org.mitk.views.measurement"; QmitkMeasurementView::QmitkMeasurementView() : d(new QmitkMeasurementViewData) { } QmitkMeasurementView::~QmitkMeasurementView() { auto planarFigures = this->GetAllPlanarFigures(); for (auto it = planarFigures->Begin(); it != planarFigures->End(); ++it) this->NodeRemoved(it.Value()); delete d; } void QmitkMeasurementView::CreateQtPartControl(QWidget* parent) { d->m_Parent = parent; d->m_SingleNodeSelectionWidget = new QmitkSingleNodeSelectionWidget(); d->m_SingleNodeSelectionWidget->SetDataStorage(GetDataStorage()); d->m_SingleNodeSelectionWidget->SetNodePredicate(mitk::NodePredicateAnd::New( mitk::TNodePredicateDataType::New(), mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object")))); d->m_SingleNodeSelectionWidget->SetSelectionIsOptional(true); - d->m_SingleNodeSelectionWidget->SetAutoSelectNewNodes(true); d->m_SingleNodeSelectionWidget->SetEmptyInfo(QStringLiteral("Please select a reference image")); d->m_SingleNodeSelectionWidget->SetPopUpTitel(QStringLiteral("Select a reference image")); d->m_DrawActionsToolBar = new QToolBar; d->m_DrawActionsGroup = new QActionGroup(this); d->m_DrawActionsGroup->setExclusive(true); auto* currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/line.png"), tr("Draw Line")); currentAction->setCheckable(true); d->m_DrawLine = currentAction; currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/path.png"), tr("Draw Path")); currentAction->setCheckable(true); d->m_DrawPath = currentAction; currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/angle.png"), tr("Draw Angle")); currentAction->setCheckable(true); d->m_DrawAngle = currentAction; currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/four-point-angle.png"), tr("Draw Four Point Angle")); currentAction->setCheckable(true); d->m_DrawFourPointAngle = currentAction; currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/circle.png"), tr("Draw Circle")); currentAction->setCheckable(true); d->m_DrawCircle = currentAction; currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/ellipse.png"), tr("Draw Ellipse")); currentAction->setCheckable(true); d->m_DrawEllipse = currentAction; currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/doubleellipse.png"), tr("Draw Double Ellipse")); currentAction->setCheckable(true); d->m_DrawDoubleEllipse = currentAction; currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/rectangle.png"), tr("Draw Rectangle")); currentAction->setCheckable(true); d->m_DrawRectangle = currentAction; currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/polygon.png"), tr("Draw Polygon")); currentAction->setCheckable(true); d->m_DrawPolygon = currentAction; currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/beziercurve.png"), tr("Draw Bezier Curve")); currentAction->setCheckable(true); d->m_DrawBezierCurve = currentAction; currentAction = d->m_DrawActionsToolBar->addAction(QIcon(":/measurement/subdivisionpolygon.png"), tr("Draw Subdivision Polygon")); currentAction->setCheckable(true); d->m_DrawSubdivisionPolygon = currentAction; d->m_DrawActionsToolBar->setEnabled(false); // fixed parameter section auto fixedLayout = new QGridLayout(); d->m_FixedParameterBox = new QGroupBox(); d->m_FixedParameterBox->setCheckable(true); d->m_FixedParameterBox->setChecked(false); d->m_FixedParameterBox->setTitle("Fixed sized circle/double ellipse"); d->m_FixedParameterBox->setToolTip("If activated, circles and double ellipses (as rings) figures will always be created with the set parameters as fixed size."); d->m_FixedParameterBox->setAlignment(Qt::AlignLeft); auto labelRadius1 = new QLabel(QString("Radius")); d->m_Radius = new ctkDoubleSpinBox(); d->m_Radius->setMinimum(0); d->m_Radius->setValue(10); d->m_Radius->setSuffix(" mm"); d->m_Radius->setAlignment(Qt::AlignLeft); d->m_Radius->setToolTip("Sets the radius for following planar figures: circle, double ellipse (as ring)."); auto labelThickness = new QLabel(QString("Thickness")); d->m_Thickness = new ctkDoubleSpinBox(); d->m_Thickness->setMinimum(0); d->m_Thickness->setMaximum(10); d->m_Thickness->setValue(5); d->m_Thickness->setSuffix(" mm"); d->m_Thickness->setAlignment(Qt::AlignLeft); d->m_Thickness->setToolTip("Sets the thickness for following planar figures: double ellipse (as ring)."); fixedLayout->addWidget(labelRadius1,0,0); fixedLayout->addWidget(d->m_Radius,0,1); fixedLayout->addWidget(labelThickness,1,0); fixedLayout->addWidget(d->m_Thickness,1,1); d->m_FixedParameterBox->setLayout(fixedLayout); // planar figure details text d->m_SelectedPlanarFiguresText = new QTextBrowser; // copy to clipboard button d->m_CopyToClipboard = new QPushButton(tr("Copy to Clipboard")); d->m_Layout = new QGridLayout; d->m_Layout->addWidget(d->m_SingleNodeSelectionWidget, 0, 0, 1, 2); d->m_Layout->addWidget(d->m_DrawActionsToolBar, 1, 0, 1, 2); d->m_Layout->addWidget(d->m_FixedParameterBox, 2, 0, 1, 2); d->m_Layout->addWidget(d->m_SelectedPlanarFiguresText, 3, 0, 1, 2); d->m_Layout->addWidget(d->m_CopyToClipboard, 4, 0, 1, 2); d->m_Parent->setLayout(d->m_Layout); this->CreateConnections(); this->AddAllInteractors(); + + // placed after CreateConnections to trigger update of the current selection + d->m_SingleNodeSelectionWidget->SetAutoSelectNewNodes(true); } void QmitkMeasurementView::CreateConnections() { connect(d->m_SingleNodeSelectionWidget, &QmitkSingleNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkMeasurementView::OnCurrentSelectionChanged); connect(d->m_DrawLine, SIGNAL(triggered(bool)), this, SLOT(OnDrawLineTriggered(bool))); connect(d->m_DrawPath, SIGNAL(triggered(bool)), this, SLOT(OnDrawPathTriggered(bool))); connect(d->m_DrawAngle, SIGNAL(triggered(bool)), this, SLOT(OnDrawAngleTriggered(bool))); connect(d->m_DrawFourPointAngle, SIGNAL(triggered(bool)), this, SLOT(OnDrawFourPointAngleTriggered(bool))); connect(d->m_DrawCircle, SIGNAL(triggered(bool)), this, SLOT(OnDrawCircleTriggered(bool))); connect(d->m_DrawEllipse, SIGNAL(triggered(bool)), this, SLOT(OnDrawEllipseTriggered(bool))); connect(d->m_DrawDoubleEllipse, SIGNAL(triggered(bool)), this, SLOT(OnDrawDoubleEllipseTriggered(bool))); connect(d->m_DrawRectangle, SIGNAL(triggered(bool)), this, SLOT(OnDrawRectangleTriggered(bool))); connect(d->m_DrawPolygon, SIGNAL(triggered(bool)), this, SLOT(OnDrawPolygonTriggered(bool))); connect(d->m_DrawBezierCurve, SIGNAL(triggered(bool)), this, SLOT(OnDrawBezierCurveTriggered(bool))); connect(d->m_DrawSubdivisionPolygon, SIGNAL(triggered(bool)), this, SLOT(OnDrawSubdivisionPolygonTriggered(bool))); connect(d->m_CopyToClipboard, SIGNAL(clicked(bool)), this, SLOT(OnCopyToClipboard(bool))); connect(d->m_Radius, QOverload::of(&ctkDoubleSpinBox::valueChanged), d->m_Thickness, &ctkDoubleSpinBox::setMaximum); } void QmitkMeasurementView::OnCurrentSelectionChanged(QList nodes) { if (nodes.empty() || nodes.front().IsNull()) { d->m_SelectedImageNode = nullptr; d->m_DrawActionsToolBar->setEnabled(false); } else { d->m_SelectedImageNode = nodes.front(); d->m_DrawActionsToolBar->setEnabled(true); } } void QmitkMeasurementView::NodeAdded(const mitk::DataNode* node) { // add observer for selection in renderwindow mitk::PlanarFigure::Pointer planarFigure = dynamic_cast(node->GetData()); auto isPositionMarker = false; node->GetBoolProperty("isContourMarker", isPositionMarker); if (planarFigure.IsNotNull() && !isPositionMarker) { auto nonConstNode = const_cast(node); mitk::PlanarFigureInteractor::Pointer interactor = dynamic_cast(node->GetDataInteractor().GetPointer()); if (interactor.IsNull()) { interactor = mitk::PlanarFigureInteractor::New(); auto planarFigureModule = us::ModuleRegistry::GetModule("MitkPlanarFigure"); interactor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule); interactor->SetEventConfig("PlanarFigureConfig.xml", planarFigureModule); } interactor->SetDataNode(nonConstNode); QmitkPlanarFigureData data; data.m_Figure = planarFigure; typedef itk::SimpleMemberCommand SimpleCommandType; typedef itk::MemberCommand MemberCommandType; // add observer for event when figure has been placed auto initializationCommand = SimpleCommandType::New(); initializationCommand->SetCallbackFunction(this, &QmitkMeasurementView::PlanarFigureInitialized); data.m_EndPlacementObserverTag = planarFigure->AddObserver(mitk::EndPlacementPlanarFigureEvent(), initializationCommand); // add observer for event when figure is picked (selected) auto selectCommand = MemberCommandType::New(); selectCommand->SetCallbackFunction(this, &QmitkMeasurementView::PlanarFigureSelected); data.m_SelectObserverTag = planarFigure->AddObserver(mitk::SelectPlanarFigureEvent(), selectCommand); // add observer for event when interaction with figure starts auto startInteractionCommand = SimpleCommandType::New(); startInteractionCommand->SetCallbackFunction(this, &QmitkMeasurementView::DisableCrosshairNavigation); data.m_StartInteractionObserverTag = planarFigure->AddObserver(mitk::StartInteractionPlanarFigureEvent(), startInteractionCommand); // add observer for event when interaction with figure starts auto endInteractionCommand = SimpleCommandType::New(); endInteractionCommand->SetCallbackFunction(this, &QmitkMeasurementView::EnableCrosshairNavigation); data.m_EndInteractionObserverTag = planarFigure->AddObserver(mitk::EndInteractionPlanarFigureEvent(), endInteractionCommand); // adding to the map of tracked planarfigures d->m_DataNodeToPlanarFigureData[nonConstNode] = data; } } void QmitkMeasurementView::NodeChanged(const mitk::DataNode* node) { auto it = std::find(d->m_CurrentSelection.begin(), d->m_CurrentSelection.end(), node); if (it != d->m_CurrentSelection.end()) { this->UpdateMeasurementText(); } } void QmitkMeasurementView::NodeRemoved(const mitk::DataNode* node) { auto nonConstNode = const_cast(node); auto it = d->m_DataNodeToPlanarFigureData.find(nonConstNode); auto isFigureFinished = false; auto isPlaced = false; if (it != d->m_DataNodeToPlanarFigureData.end()) { QmitkPlanarFigureData& data = it->second; data.m_Figure->RemoveObserver(data.m_EndPlacementObserverTag); data.m_Figure->RemoveObserver(data.m_SelectObserverTag); data.m_Figure->RemoveObserver(data.m_StartInteractionObserverTag); data.m_Figure->RemoveObserver(data.m_EndInteractionObserverTag); isFigureFinished = data.m_Figure->GetPropertyList()->GetBoolProperty("initiallyplaced", isPlaced); if (!isFigureFinished) // if the property does not yet exist or is false, drop the datanode this->PlanarFigureInitialized(); // normally called when a figure is finished, to reset all buttons d->m_DataNodeToPlanarFigureData.erase( it ); } if (nonConstNode != nullptr) nonConstNode->SetDataInteractor(nullptr); auto isPlanarFigure = mitk::TNodePredicateDataType::New(); auto nodes = this->GetDataStorage()->GetDerivations(node, isPlanarFigure); for (unsigned int x = 0; x < nodes->size(); ++x) { mitk::PlanarFigure::Pointer planarFigure = dynamic_cast(nodes->at(x)->GetData()); if (planarFigure.IsNotNull()) { isFigureFinished = planarFigure->GetPropertyList()->GetBoolProperty("initiallyplaced",isPlaced); if (!isFigureFinished) // if the property does not yet exist or is false, drop the datanode { this->GetDataStorage()->Remove(nodes->at(x)); if (!d->m_DataNodeToPlanarFigureData.empty()) { it = d->m_DataNodeToPlanarFigureData.find(nodes->at(x)); if (it != d->m_DataNodeToPlanarFigureData.end()) { d->m_DataNodeToPlanarFigureData.erase(it); this->PlanarFigureInitialized(); // normally called when a figure is finished, to reset all buttons this->EnableCrosshairNavigation(); } } } } } } void QmitkMeasurementView::PlanarFigureSelected(itk::Object* object, const itk::EventObject&) { d->m_CurrentSelection.clear(); auto lambda = [&object](const std::pair& element) { return element.second.m_Figure == object; }; auto it = std::find_if(d->m_DataNodeToPlanarFigureData.begin(), d->m_DataNodeToPlanarFigureData.end(), lambda); if (it != d->m_DataNodeToPlanarFigureData.end()) { d->m_CurrentSelection.push_back(it->first); } this->UpdateMeasurementText(); this->RequestRenderWindowUpdate(); } void QmitkMeasurementView::PlanarFigureInitialized() { d->m_UnintializedPlanarFigure = false; d->m_DrawActionsToolBar->setEnabled(true); d->m_DrawLine->setChecked(false); d->m_DrawPath->setChecked(false); d->m_DrawAngle->setChecked(false); d->m_DrawFourPointAngle->setChecked(false); d->m_DrawCircle->setChecked(false); d->m_DrawEllipse->setChecked(false); d->m_DrawDoubleEllipse->setChecked(false); d->m_DrawRectangle->setChecked(false); d->m_DrawPolygon->setChecked(false); d->m_DrawBezierCurve->setChecked(false); d->m_DrawSubdivisionPolygon->setChecked(false); } void QmitkMeasurementView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& nodes) { d->m_CurrentSelection = nodes; this->UpdateMeasurementText(); // bug 16600: deselecting all planarfigures by clicking on datamanager when no node is selected if (d->m_CurrentSelection.size() == 0) { auto isPlanarFigure = mitk::TNodePredicateDataType::New(); auto planarFigures = this->GetDataStorage()->GetSubset(isPlanarFigure); // setting all planar figures which are not helper objects not selected for (mitk::DataStorage::SetOfObjects::ConstIterator it = planarFigures->Begin(); it != planarFigures->End(); ++it) { auto node = it.Value(); auto isHelperObject = false; node->GetBoolProperty("helper object", isHelperObject); if (!isHelperObject) node->SetSelected(false); } } for (int i = d->m_CurrentSelection.size() - 1; i >= 0; --i) { auto node = d->m_CurrentSelection[i]; mitk::PlanarFigure::Pointer planarFigure = dynamic_cast(node->GetData()); // the last selected planar figure if (planarFigure.IsNotNull() && planarFigure->GetPlaneGeometry()) { auto planarFigureInitializedWindow = false; auto linkedRenderWindow = dynamic_cast(this->GetRenderWindowPart()); QmitkRenderWindow* selectedRenderWindow; if (!linkedRenderWindow) return; auto axialRenderWindow = linkedRenderWindow->GetQmitkRenderWindow("axial"); auto sagittalRenderWindow = linkedRenderWindow->GetQmitkRenderWindow("sagittal"); auto coronalRenderWindow = linkedRenderWindow->GetQmitkRenderWindow("coronal"); auto threeDimRenderWindow = linkedRenderWindow->GetQmitkRenderWindow("3d"); if (node->GetBoolProperty("planarFigureInitializedWindow", planarFigureInitializedWindow, axialRenderWindow->GetRenderer())) { selectedRenderWindow = axialRenderWindow; } else if (node->GetBoolProperty("planarFigureInitializedWindow", planarFigureInitializedWindow, sagittalRenderWindow->GetRenderer())) { selectedRenderWindow = sagittalRenderWindow; } else if (node->GetBoolProperty("planarFigureInitializedWindow", planarFigureInitializedWindow, coronalRenderWindow->GetRenderer())) { selectedRenderWindow = coronalRenderWindow; } else if (node->GetBoolProperty("planarFigureInitializedWindow", planarFigureInitializedWindow, threeDimRenderWindow->GetRenderer())) { selectedRenderWindow = threeDimRenderWindow; } else { selectedRenderWindow = nullptr; } auto planeGeometry = dynamic_cast(planarFigure->GetPlaneGeometry()); auto normal = planeGeometry->GetNormalVnl(); mitk::PlaneGeometry::ConstPointer axialPlane = axialRenderWindow->GetRenderer()->GetCurrentWorldPlaneGeometry(); auto axialNormal = axialPlane->GetNormalVnl(); mitk::PlaneGeometry::ConstPointer sagittalPlane = sagittalRenderWindow->GetRenderer()->GetCurrentWorldPlaneGeometry(); auto sagittalNormal = sagittalPlane->GetNormalVnl(); mitk::PlaneGeometry::ConstPointer coronalPlane = coronalRenderWindow->GetRenderer()->GetCurrentWorldPlaneGeometry(); auto coronalNormal = coronalPlane->GetNormalVnl(); normal[0] = fabs(normal[0]); normal[1] = fabs(normal[1]); normal[2] = fabs(normal[2]); axialNormal[0] = fabs(axialNormal[0]); axialNormal[1] = fabs(axialNormal[1]); axialNormal[2] = fabs(axialNormal[2]); sagittalNormal[0] = fabs(sagittalNormal[0]); sagittalNormal[1] = fabs(sagittalNormal[1]); sagittalNormal[2] = fabs(sagittalNormal[2]); coronalNormal[0] = fabs(coronalNormal[0]); coronalNormal[1] = fabs(coronalNormal[1]); coronalNormal[2] = fabs(coronalNormal[2]); auto ang1 = angle(normal, axialNormal); auto ang2 = angle(normal, sagittalNormal); auto ang3 = angle(normal, coronalNormal); if (ang1 < ang2 && ang1 < ang3) { selectedRenderWindow = axialRenderWindow; } else { if (ang2 < ang3) { selectedRenderWindow = sagittalRenderWindow; } else { selectedRenderWindow = coronalRenderWindow; } } // re-orient view if (selectedRenderWindow) selectedRenderWindow->GetSliceNavigationController()->ReorientSlices(planeGeometry->GetOrigin(), planeGeometry->GetNormal()); } break; } this->RequestRenderWindowUpdate(); } void QmitkMeasurementView::OnDrawLineTriggered(bool) { this->AddFigureToDataStorage( mitk::PlanarLine::New(), QString("Line%1").arg(++d->m_LineCounter)); } void QmitkMeasurementView::OnDrawPathTriggered(bool) { mitk::CoreServicePointer propertyFilters(mitk::CoreServices::GetPropertyFilters()); mitk::PropertyFilter filter; filter.AddEntry("ClosedPlanarPolygon", mitk::PropertyFilter::Blacklist); propertyFilters->AddFilter(filter, "PlanarPolygon"); mitk::PlanarPolygon::Pointer planarFigure = mitk::PlanarPolygon::New(); planarFigure->ClosedOff(); auto node = this->AddFigureToDataStorage( planarFigure, QString("Path%1").arg(++d->m_PathCounter)); node->SetProperty("ClosedPlanarPolygon", mitk::BoolProperty::New(false)); node->SetProperty("planarfigure.isextendable", mitk::BoolProperty::New(true)); } void QmitkMeasurementView::OnDrawAngleTriggered(bool) { this->AddFigureToDataStorage( mitk::PlanarAngle::New(), QString("Angle%1").arg(++d->m_AngleCounter)); } void QmitkMeasurementView::OnDrawFourPointAngleTriggered(bool) { this->AddFigureToDataStorage( mitk::PlanarFourPointAngle::New(), QString("Four Point Angle%1").arg(++d->m_FourPointAngleCounter)); } void QmitkMeasurementView::OnDrawCircleTriggered(bool) { auto circle = (d->m_FixedParameterBox->isChecked()) ? mitk::PlanarCircle::New(d->m_Radius->value()) : mitk::PlanarCircle::New(); this->AddFigureToDataStorage(circle, QString("Circle%1").arg(++d->m_CircleCounter)); } void QmitkMeasurementView::OnDrawEllipseTriggered(bool) { this->AddFigureToDataStorage( mitk::PlanarEllipse::New(), QString("Ellipse%1").arg(++d->m_EllipseCounter)); } void QmitkMeasurementView::OnDrawDoubleEllipseTriggered(bool) { auto ellipse = (d->m_FixedParameterBox->isChecked()) ? mitk::PlanarDoubleEllipse::New(d->m_Radius->value(),d->m_Thickness->value()) : mitk::PlanarDoubleEllipse::New(); this->AddFigureToDataStorage(ellipse, QString("DoubleEllipse%1").arg(++d->m_DoubleEllipseCounter)); } void QmitkMeasurementView::OnDrawBezierCurveTriggered(bool) { this->AddFigureToDataStorage( mitk::PlanarBezierCurve::New(), QString("BezierCurve%1").arg(++d->m_BezierCurveCounter)); } void QmitkMeasurementView::OnDrawSubdivisionPolygonTriggered(bool) { this->AddFigureToDataStorage( mitk::PlanarSubdivisionPolygon::New(), QString("SubdivisionPolygon%1").arg(++d->m_SubdivisionPolygonCounter)); } void QmitkMeasurementView::OnDrawRectangleTriggered(bool) { this->AddFigureToDataStorage( mitk::PlanarRectangle::New(), QString("Rectangle%1").arg(++d->m_RectangleCounter)); } void QmitkMeasurementView::OnDrawPolygonTriggered(bool) { auto planarFigure = mitk::PlanarPolygon::New(); planarFigure->ClosedOn(); auto node = this->AddFigureToDataStorage( planarFigure, QString("Polygon%1").arg(++d->m_PolygonCounter)); node->SetProperty("planarfigure.isextendable", mitk::BoolProperty::New(true)); } void QmitkMeasurementView::OnCopyToClipboard(bool) { QApplication::clipboard()->setText(d->m_SelectedPlanarFiguresText->toPlainText(), QClipboard::Clipboard); } mitk::DataNode::Pointer QmitkMeasurementView::AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name) { auto newNode = mitk::DataNode::New(); newNode->SetName(name.toStdString()); newNode->SetData(figure); newNode->SetSelected(true); if (d->m_SelectedImageNode.IsNotNull()) { this->GetDataStorage()->Add(newNode, d->m_SelectedImageNode); } else { this->GetDataStorage()->Add(newNode); } for (auto &node : d->m_CurrentSelection) node->SetSelected(false); d->m_CurrentSelection.clear(); d->m_CurrentSelection.push_back(newNode); this->UpdateMeasurementText(); this->DisableCrosshairNavigation(); d->m_DrawActionsToolBar->setEnabled(false); d->m_UnintializedPlanarFigure = true; return newNode; } void QmitkMeasurementView::UpdateMeasurementText() { d->m_SelectedPlanarFiguresText->clear(); QString infoText; QString plainInfoText; int j = 1; mitk::PlanarFigure::Pointer planarFigure; mitk::PlanarAngle::Pointer planarAngle; mitk::PlanarFourPointAngle::Pointer planarFourPointAngle; mitk::DataNode::Pointer node; for (int i = 0; i < d->m_CurrentSelection.size(); ++i, ++j) { plainInfoText.clear(); node = d->m_CurrentSelection[i]; planarFigure = dynamic_cast(node->GetData()); if (planarFigure.IsNull()) continue; if (j > 1) infoText.append("
"); infoText.append(QString("%1
").arg(QString::fromStdString(node->GetName()))); plainInfoText.append(QString("%1").arg(QString::fromStdString(node->GetName()))); planarAngle = dynamic_cast (planarFigure.GetPointer()); if (planarAngle.IsNull()) planarFourPointAngle = dynamic_cast (planarFigure.GetPointer()); double featureQuantity = 0.0; for (unsigned int k = 0; k < planarFigure->GetNumberOfFeatures(); ++k) { if (!planarFigure->IsFeatureActive(k)) continue; featureQuantity = planarFigure->GetQuantity(k); if ((planarAngle.IsNotNull() && k == planarAngle->FEATURE_ID_ANGLE) || (planarFourPointAngle.IsNotNull() && k == planarFourPointAngle->FEATURE_ID_ANGLE)) featureQuantity = featureQuantity * 180 / vnl_math::pi; infoText.append(QString("%1: %2 %3") .arg(QString(planarFigure->GetFeatureName(k))) .arg(featureQuantity, 0, 'f', 2) .arg(QString(planarFigure->GetFeatureUnit(k)))); plainInfoText.append(QString("\n%1: %2 %3") .arg(QString(planarFigure->GetFeatureName(k))) .arg(featureQuantity, 0, 'f', 2) .arg(QString(planarFigure->GetFeatureUnit(k)))); if (k + 1 != planarFigure->GetNumberOfFeatures()) infoText.append("
"); } if (j != d->m_CurrentSelection.size()) infoText.append("
"); } d->m_SelectedPlanarFiguresText->setHtml(infoText); } void QmitkMeasurementView::AddAllInteractors() { auto planarFigures = this->GetAllPlanarFigures(); for (auto it = planarFigures->Begin(); it != planarFigures->End(); ++it) this->NodeAdded(it.Value()); } void QmitkMeasurementView::EnableCrosshairNavigation() { // enable the crosshair navigation // Re-enabling InteractionEventObservers that have been previously disabled for legacy handling of Tools // in new interaction framework for (const auto& displayInteractorConfig : m_DisplayInteractorConfigs) { if (displayInteractorConfig.first) { auto displayInteractor = static_cast(us::GetModuleContext()->GetService(displayInteractorConfig.first)); if (displayInteractor != nullptr) { // here the regular configuration is loaded again displayInteractor->SetEventConfig(displayInteractorConfig.second); } } } m_DisplayInteractorConfigs.clear(); d->m_ScrollEnabled = true; } void QmitkMeasurementView::DisableCrosshairNavigation() { // dont deactivate twice, else we will clutter the config list ... if (d->m_ScrollEnabled == false) return; // As a legacy solution the display interaction of the new interaction framework is disabled here to avoid conflicts with tools // Note: this only affects InteractionEventObservers (formerly known as Listeners) all DataNode specific interaction will still be enabled m_DisplayInteractorConfigs.clear(); auto eventObservers = us::GetModuleContext()->GetServiceReferences(); for (const auto& eventObserver : eventObservers) { auto displayInteractor = dynamic_cast(us::GetModuleContext()->GetService(eventObserver)); if (displayInteractor != nullptr) { // remember the original configuration m_DisplayInteractorConfigs.insert(std::make_pair(eventObserver, displayInteractor->GetEventConfig())); // here the alternative configuration is loaded displayInteractor->SetEventConfig("DisplayConfigMITKLimited.xml"); } } d->m_ScrollEnabled = false; } mitk::DataStorage::SetOfObjects::ConstPointer QmitkMeasurementView::GetAllPlanarFigures() const { auto isPlanarFigure = mitk::TNodePredicateDataType::New(); auto isNotHelperObject = mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(false)); auto isNotHelperButPlanarFigure = mitk::NodePredicateAnd::New( isPlanarFigure, isNotHelperObject ); return this->GetDataStorage()->GetSubset(isPlanarFigure); } diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionView.cpp b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionView.cpp index b225533dc8..9ee2b5e3f5 100644 --- a/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionView.cpp +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionView.cpp @@ -1,1487 +1,1485 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "MRPerfusionView.h" #include "boost/tokenizer.hpp" #include "boost/math/constants/constants.hpp" #include #include "mitkWorkbenchUtil.h" #include "mitkAterialInputFunctionGenerator.h" #include "mitkConcentrationCurveGenerator.h" #include #include #include #include "mitkThreeStepLinearModelFactory.h" #include "mitkThreeStepLinearModelParameterizer.h" #include "mitkTwoStepLinearModelFactory.h" #include "mitkTwoStepLinearModelParameterizer.h" #include #include #include #include #include "mitkTwoCompartmentExchangeModelFactory.h" #include "mitkTwoCompartmentExchangeModelParameterizer.h" #include "mitkNumericTwoCompartmentExchangeModelFactory.h" #include "mitkNumericTwoCompartmentExchangeModelParameterizer.h" #include #include #include #include #include #include #include #include "mitkNodePredicateFunction.h" #include #include #include #include #include #include #include #include #include #include +#include #include #include #include // Includes for image casting between ITK and MITK #include #include "mitkImageCast.h" #include "mitkITKImageImport.h" #include #include const std::string MRPerfusionView::VIEW_ID = "org.mitk.gui.qt.pharmacokinetics.mri"; inline double convertToDouble(const std::string& data) { std::istringstream stepStream(data); stepStream.imbue(std::locale("C")); double value = 0.0; if (!(stepStream >> value) || !(stepStream.eof())) { mitkThrow() << "Cannot convert string to double. String: " << data; } return value; } void MRPerfusionView::SetFocus() { m_Controls.btnModelling->setFocus(); } void MRPerfusionView::CreateQtPartControl(QWidget* parent) { m_Controls.setupUi(parent); m_Controls.btnModelling->setEnabled(false); this->InitModelComboBox(); m_Controls.timeSeriesNodeSelector->SetNodePredicate(this->m_isValidTimeSeriesImagePredicate); m_Controls.timeSeriesNodeSelector->SetDataStorage(this->GetDataStorage()); m_Controls.timeSeriesNodeSelector->SetSelectionIsOptional(false); m_Controls.timeSeriesNodeSelector->SetInvalidInfo("Please select time series."); m_Controls.timeSeriesNodeSelector->SetAutoSelectNewNodes(true); m_Controls.maskNodeSelector->SetNodePredicate(this->m_IsMaskPredicate); m_Controls.maskNodeSelector->SetDataStorage(this->GetDataStorage()); m_Controls.maskNodeSelector->SetSelectionIsOptional(true); m_Controls.maskNodeSelector->SetEmptyInfo("Please select (optional) mask."); connect(m_Controls.btnModelling, SIGNAL(clicked()), this, SLOT(OnModellingButtonClicked())); connect(m_Controls.comboModel, SIGNAL(currentIndexChanged(int)), this, SLOT(OnModellSet(int))); connect(m_Controls.radioPixelBased, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); connect(m_Controls.timeSeriesNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &MRPerfusionView::OnNodeSelectionChanged); connect(m_Controls.maskNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &MRPerfusionView::OnNodeSelectionChanged); connect(m_Controls.AIFMaskNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &MRPerfusionView::UpdateGUIControls); connect(m_Controls.AIFImageNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &MRPerfusionView::UpdateGUIControls); //AIF setting m_Controls.groupAIF->hide(); m_Controls.btnAIFFile->setEnabled(false); m_Controls.btnAIFFile->setEnabled(false); m_Controls.radioAIFImage->setChecked(true); m_Controls.AIFMaskNodeSelector->SetDataStorage(this->GetDataStorage()); m_Controls.AIFMaskNodeSelector->SetNodePredicate(m_IsMaskPredicate); m_Controls.AIFMaskNodeSelector->setVisible(true); m_Controls.AIFMaskNodeSelector->setEnabled(true); m_Controls.AIFMaskNodeSelector->SetAutoSelectNewNodes(true); m_Controls.AIFImageNodeSelector->SetDataStorage(this->GetDataStorage()); m_Controls.AIFImageNodeSelector->SetNodePredicate(this->m_isValidTimeSeriesImagePredicate); m_Controls.AIFImageNodeSelector->setEnabled(false); m_Controls.checkDedicatedAIFImage->setEnabled(true); m_Controls.HCLSpinBox->setValue(mitk::AterialInputFunctionGenerator::DEFAULT_HEMATOCRIT_LEVEL); m_Controls.spinBox_baselineEndTimeStep->setMinimum(0); m_Controls.spinBox_baselineStartTimeStep->setMinimum(0); connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.AIFMaskNodeSelector, SLOT(setVisible(bool))); connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.labelAIFMask, SLOT(setVisible(bool))); connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.checkDedicatedAIFImage, SLOT(setVisible(bool))); connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.AIFMaskNodeSelector, SLOT(setEnabled(bool))); connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.checkDedicatedAIFImage, SLOT(setEnabled(bool))); connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.checkDedicatedAIFImage, SLOT(setVisible(bool))); connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.AIFImageNodeSelector, SLOT(setVisible(bool))); connect(m_Controls.checkDedicatedAIFImage, SIGNAL(toggled(bool)), m_Controls.AIFImageNodeSelector, SLOT(setEnabled(bool))); connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); connect(m_Controls.radioAIFFile, SIGNAL(toggled(bool)), m_Controls.btnAIFFile, SLOT(setEnabled(bool))); connect(m_Controls.radioAIFFile, SIGNAL(toggled(bool)), m_Controls.aifFilePath, SLOT(setEnabled(bool))); connect(m_Controls.radioAIFFile, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); connect(m_Controls.btnAIFFile, SIGNAL(clicked()), this, SLOT(LoadAIFfromFile())); //Brix setting m_Controls.groupDescBrix->hide(); connect(m_Controls.injectiontime, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); //Num2CX setting m_Controls.groupNum2CXM->hide(); connect(m_Controls.odeStepSize, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); //Model fit configuration m_Controls.groupBox_FitConfiguration->hide(); m_Controls.checkBox_Constraints->setEnabled(false); m_Controls.constraintManager->setEnabled(false); m_Controls.initialValuesManager->setEnabled(false); m_Controls.initialValuesManager->setDataStorage(this->GetDataStorage()); connect(m_Controls.radioButton_StartParameters, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); connect(m_Controls.checkBox_Constraints, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); connect(m_Controls.initialValuesManager, SIGNAL(initialValuesChanged(void)), this, SLOT(UpdateGUIControls())); connect(m_Controls.radioButton_StartParameters, SIGNAL(toggled(bool)), m_Controls.initialValuesManager, SLOT(setEnabled(bool))); connect(m_Controls.checkBox_Constraints, SIGNAL(toggled(bool)), m_Controls.constraintManager, SLOT(setEnabled(bool))); connect(m_Controls.checkBox_Constraints, SIGNAL(toggled(bool)), m_Controls.constraintManager, SLOT(setVisible(bool))); //Concentration m_Controls.groupConcentration->hide(); m_Controls.groupBoxEnhancement->hide(); m_Controls.groupBoxTurboFlash->hide(); m_Controls.radioButtonNoConversion->setChecked(true); m_Controls.groupBox_T1MapviaVFA->hide(); m_Controls.spinBox_baselineStartTimeStep->setValue(0); m_Controls.spinBox_baselineEndTimeStep->setValue(0); connect(m_Controls.radioButtonTurboFlash, SIGNAL(toggled(bool)), m_Controls.groupBoxTurboFlash, SLOT(setVisible(bool))); connect(m_Controls.radioButtonTurboFlash, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); connect(m_Controls.relaxationtime, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); connect(m_Controls.recoverytime, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); connect(m_Controls.relaxivity, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); connect(m_Controls.radioButton_absoluteEnhancement, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); connect(m_Controls.radioButton_relativeEnchancement, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); connect(m_Controls.radioButton_absoluteEnhancement, SIGNAL(toggled(bool)), m_Controls.groupBoxEnhancement, SLOT(setVisible(bool))); connect(m_Controls.radioButton_relativeEnchancement, SIGNAL(toggled(bool)), m_Controls.groupBoxEnhancement, SLOT(setVisible(bool))); connect(m_Controls.factorSpinBox, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); connect(m_Controls.spinBox_baselineStartTimeStep, SIGNAL(valueChanged(int)), this, SLOT(UpdateGUIControls())); connect(m_Controls.spinBox_baselineEndTimeStep, SIGNAL(valueChanged(int)), this, SLOT(UpdateGUIControls())); connect(m_Controls.radioButtonUsingT1viaVFA, SIGNAL(toggled(bool)), m_Controls.groupBox_T1MapviaVFA, SLOT(setVisible(bool))); connect(m_Controls.radioButtonUsingT1viaVFA, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); connect(m_Controls.FlipangleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); connect(m_Controls.RelaxivitySpinBox, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); connect(m_Controls.TRSpinBox, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); m_Controls.PDWImageNodeSelector->SetNodePredicate(m_isValidPDWImagePredicate); m_Controls.PDWImageNodeSelector->SetDataStorage(this->GetDataStorage()); m_Controls.PDWImageNodeSelector->SetInvalidInfo("Please select PDW Image."); m_Controls.PDWImageNodeSelector->setEnabled(false); connect(m_Controls.radioButtonUsingT1viaVFA, SIGNAL(toggled(bool)), m_Controls.PDWImageNodeSelector, SLOT(setEnabled(bool))); UpdateGUIControls(); } bool MRPerfusionView::IsTurboFlashSequenceFlag() const { return this->m_Controls.radioButtonTurboFlash->isChecked(); }; void MRPerfusionView::UpdateGUIControls() { m_Controls.lineFitName->setPlaceholderText(QString::fromStdString(this->GetDefaultFitName())); m_Controls.lineFitName->setEnabled(!m_FittingInProgress); m_Controls.checkBox_Constraints->setEnabled(m_modelConstraints.IsNotNull()); bool isDescBrixFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; bool isToftsFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr || dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; bool is2CXMFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr || dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; bool isNum2CXMFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; bool isSLFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr || dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; m_Controls.groupAIF->setVisible(isToftsFactory || is2CXMFactory); m_Controls.groupDescBrix->setVisible(isDescBrixFactory); m_Controls.groupNum2CXM->setVisible(isNum2CXMFactory); m_Controls.groupConcentration->setVisible(isToftsFactory || is2CXMFactory || isSLFactory); m_Controls.groupBox_FitConfiguration->setVisible(m_selectedModelFactory); m_Controls.groupBox->setEnabled(!m_FittingInProgress); m_Controls.comboModel->setEnabled(!m_FittingInProgress); m_Controls.groupAIF->setEnabled(!m_FittingInProgress); m_Controls.groupDescBrix->setEnabled(!m_FittingInProgress); m_Controls.groupNum2CXM->setEnabled(!m_FittingInProgress); m_Controls.groupConcentration->setEnabled(!m_FittingInProgress); m_Controls.groupBox_FitConfiguration->setEnabled(!m_FittingInProgress); m_Controls.radioROIbased->setEnabled(m_selectedMask.IsNotNull()); m_Controls.btnModelling->setEnabled(m_selectedImage.IsNotNull() && m_selectedModelFactory.IsNotNull() && !m_FittingInProgress && CheckModelSettings()); m_Controls.spinBox_baselineStartTimeStep->setEnabled(m_Controls.radioButtonTurboFlash->isChecked() || m_Controls.radioButton_absoluteEnhancement->isChecked() || m_Controls.radioButton_relativeEnchancement->isChecked() || m_Controls.radioButtonUsingT1viaVFA->isChecked()); m_Controls.spinBox_baselineEndTimeStep->setEnabled(m_Controls.radioButton_absoluteEnhancement->isChecked() || m_Controls.radioButton_relativeEnchancement->isChecked() || m_Controls.radioButtonUsingT1viaVFA->isChecked() || m_Controls.radioButtonTurboFlash->isChecked()); } void MRPerfusionView::OnModellSet(int index) { m_selectedModelFactory = nullptr; if (index > 0) { if (static_cast(index) <= m_FactoryStack.size() ) { m_selectedModelFactory = m_FactoryStack[index - 1]; } else { MITK_WARN << "Invalid model index. Index outside of the factory stack. Factory stack size: "<< m_FactoryStack.size() << "; invalid index: "<< index; } } if (m_selectedModelFactory) { this->m_modelConstraints = dynamic_cast (m_selectedModelFactory->CreateDefaultConstraints().GetPointer()); m_Controls.initialValuesManager->setInitialValues(m_selectedModelFactory->GetParameterNames(), m_selectedModelFactory->GetDefaultInitialParameterization()); if (this->m_modelConstraints.IsNull()) { this->m_modelConstraints = mitk::SimpleBarrierConstraintChecker::New(); } m_Controls.constraintManager->setChecker(this->m_modelConstraints, this->m_selectedModelFactory->GetParameterNames()); } UpdateGUIControls(); } std::string MRPerfusionView::GetFitName() const { std::string fitName = m_Controls.lineFitName->text().toStdString(); if (fitName.empty()) { fitName = m_Controls.lineFitName->placeholderText().toStdString(); } return fitName; } std::string MRPerfusionView::GetDefaultFitName() const { std::string defaultName = "undefined model"; if (this->m_selectedModelFactory.IsNotNull()) { defaultName = this->m_selectedModelFactory->GetClassID(); } if (this->m_Controls.radioPixelBased->isChecked()) { defaultName += "_pixel"; } else { defaultName += "_roi"; } return defaultName; } void MRPerfusionView::OnModellingButtonClicked() { //check if all static parameters set if (m_selectedModelFactory.IsNotNull() && CheckModelSettings()) { m_HasGeneratedNewInput = false; m_HasGeneratedNewInputAIF = false; mitk::ParameterFitImageGeneratorBase::Pointer generator = nullptr; mitk::modelFit::ModelFitInfo::Pointer fitSession = nullptr; bool isDescBrixFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; bool is3LinearFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; bool is2LinearFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; bool isExtToftsFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; bool isStanToftsFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; bool is2CXMFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; bool isNum2CXMFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; if (isDescBrixFactory) { if (this->m_Controls.radioPixelBased->isChecked()) { GenerateDescriptiveBrixModel_PixelBased(fitSession, generator); } else { GenerateDescriptiveBrixModel_ROIBased(fitSession, generator); } } else if (is2LinearFactory) { if (this->m_Controls.radioPixelBased->isChecked()) { GenerateLinearModelFit_PixelBased(fitSession, generator); } else { GenerateLinearModelFit_ROIBased(fitSession, generator); } } else if (is3LinearFactory) { if (this->m_Controls.radioPixelBased->isChecked()) { GenerateLinearModelFit_PixelBased(fitSession, generator); } else { GenerateLinearModelFit_ROIBased(fitSession, generator); } } else if (isStanToftsFactory) { if (this->m_Controls.radioPixelBased->isChecked()) { GenerateAIFbasedModelFit_PixelBased(fitSession, generator); } else { GenerateAIFbasedModelFit_ROIBased(fitSession, generator); } } else if (isExtToftsFactory) { if (this->m_Controls.radioPixelBased->isChecked()) { GenerateAIFbasedModelFit_PixelBased(fitSession, generator); } else { GenerateAIFbasedModelFit_ROIBased(fitSession, generator); } } else if (is2CXMFactory) { if (this->m_Controls.radioPixelBased->isChecked()) { GenerateAIFbasedModelFit_PixelBased(fitSession, generator); } else { GenerateAIFbasedModelFit_ROIBased(fitSession, generator); } } else if (isNum2CXMFactory) { if (this->m_Controls.radioPixelBased->isChecked()) { GenerateAIFbasedModelFit_PixelBased(fitSession, generator); } else { GenerateAIFbasedModelFit_ROIBased(fitSession, generator); } } //add other models with else if if (generator.IsNotNull() && fitSession.IsNotNull()) { m_FittingInProgress = true; UpdateGUIControls(); DoFit(fitSession, generator); } else { QMessageBox box; box.setText("Fitting error!"); box.setInformativeText("Could not establish fitting job. Error when setting ab generator, model parameterizer or session info."); box.setStandardButtons(QMessageBox::Ok); box.setDefaultButton(QMessageBox::Ok); box.setIcon(QMessageBox::Warning); box.exec(); } } else { QMessageBox box; box.setText("Static parameters for model are not set!"); box.setInformativeText("Some static parameters, that are needed for calculation are not set and equal to zero. Modeling not possible"); box.setStandardButtons(QMessageBox::Ok); box.setDefaultButton(QMessageBox::Ok); box.setIcon(QMessageBox::Warning); box.exec(); } } void MRPerfusionView::OnNodeSelectionChanged(QList/*nodes*/) { m_selectedMaskNode = nullptr; m_selectedMask = nullptr; if (m_Controls.timeSeriesNodeSelector->GetSelectedNode().IsNotNull()) { this->m_selectedNode = m_Controls.timeSeriesNodeSelector->GetSelectedNode(); m_selectedImage = dynamic_cast(m_selectedNode->GetData()); if (m_selectedImage) { this->m_Controls.initialValuesManager->setReferenceImageGeometry(m_selectedImage->GetGeometry()); } else { this->m_Controls.initialValuesManager->setReferenceImageGeometry(nullptr); } } else { this->m_selectedNode = nullptr; this->m_selectedImage = nullptr; this->m_Controls.initialValuesManager->setReferenceImageGeometry(nullptr); } if (m_Controls.maskNodeSelector->GetSelectedNode().IsNotNull()) { this->m_selectedMaskNode = m_Controls.maskNodeSelector->GetSelectedNode(); this->m_selectedMask = dynamic_cast(m_selectedMaskNode->GetData()); if (this->m_selectedMask.IsNotNull() && this->m_selectedMask->GetTimeSteps() > 1) { MITK_INFO << "Selected mask has multiple timesteps. Only use first timestep to mask model fit. Mask name: " << m_Controls.maskNodeSelector->GetSelectedNode()->GetName(); mitk::ImageTimeSelector::Pointer maskedImageTimeSelector = mitk::ImageTimeSelector::New(); maskedImageTimeSelector->SetInput(this->m_selectedMask); maskedImageTimeSelector->SetTimeNr(0); maskedImageTimeSelector->UpdateLargestPossibleRegion(); this->m_selectedMask = maskedImageTimeSelector->GetOutput(); } } if (m_selectedMask.IsNull()) { this->m_Controls.radioPixelBased->setChecked(true); } if (this->m_selectedImage.IsNotNull()) { m_Controls.spinBox_baselineStartTimeStep->setMaximum((this->m_selectedImage->GetDimension(3))-1); m_Controls.spinBox_baselineEndTimeStep->setMaximum((this->m_selectedImage->GetDimension(3)) - 1); } UpdateGUIControls(); } bool MRPerfusionView::CheckModelSettings() const { bool ok = true; //check wether any model is set at all. Otherwise exit with false if (m_selectedModelFactory.IsNotNull()) { bool isDescBrixFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; bool is3LinearFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; bool is2LinearFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; bool isToftsFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr|| dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; bool is2CXMFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; bool isNum2CXMFactory = dynamic_cast (m_selectedModelFactory.GetPointer()) != nullptr; if (isDescBrixFactory) { //if all static parameters for this model are set, exit with true, Otherwise exit with false ok = m_Controls.injectiontime->value() > 0; } else if (is3LinearFactory || is2LinearFactory) { if (this->m_Controls.radioButtonTurboFlash->isChecked() ) { ok = ok && (m_Controls.recoverytime->value() > 0); ok = ok && (m_Controls.relaxationtime->value() > 0); ok = ok && (m_Controls.relaxivity->value() > 0); ok = ok && (m_Controls.AifRecoverytime->value() > 0); ok = ok && CheckBaselineSelectionSettings(); } else if (this->m_Controls.radioButton_absoluteEnhancement->isChecked() || this->m_Controls.radioButton_relativeEnchancement->isChecked() ) { ok = ok && (m_Controls.factorSpinBox->value() > 0); ok = ok && CheckBaselineSelectionSettings(); } else if (this->m_Controls.radioButtonUsingT1viaVFA->isChecked() ) { ok = ok && (m_Controls.FlipangleSpinBox->value() > 0); ok = ok && (m_Controls.TRSpinBox->value() > 0); ok = ok && (m_Controls.RelaxivitySpinBox->value() > 0); ok = ok && (m_Controls.PDWImageNodeSelector->GetSelectedNode().IsNotNull()); ok = ok && CheckBaselineSelectionSettings(); } else if (this->m_Controls.radioButtonNoConversion->isChecked()) { ok = true; } else { ok = false; } } else if (isToftsFactory || is2CXMFactory || isNum2CXMFactory) { if (this->m_Controls.radioAIFImage->isChecked()) { ok = ok && m_Controls.AIFMaskNodeSelector->GetSelectedNode().IsNotNull(); if (this->m_Controls.checkDedicatedAIFImage->isChecked()) { ok = ok && m_Controls.AIFImageNodeSelector->GetSelectedNode().IsNotNull(); } } else if (this->m_Controls.radioAIFFile->isChecked()) { ok = ok && (this->AIFinputGrid.size() != 0) && (this->AIFinputFunction.size() != 0); } else { ok = false; } if (this->m_Controls.radioButtonTurboFlash->isChecked() ) { ok = ok && (m_Controls.recoverytime->value() > 0); ok = ok && (m_Controls.relaxationtime->value() > 0); ok = ok && (m_Controls.relaxivity->value() > 0); ok = ok && (m_Controls.AifRecoverytime->value() > 0); ok = ok && CheckBaselineSelectionSettings(); } else if (this->m_Controls.radioButton_absoluteEnhancement->isChecked() || this->m_Controls.radioButton_relativeEnchancement->isChecked() ) { ok = ok && (m_Controls.factorSpinBox->value() > 0); ok = ok && CheckBaselineSelectionSettings(); } else if (this->m_Controls.radioButtonUsingT1viaVFA->isChecked() ) { ok = ok && (m_Controls.FlipangleSpinBox->value() > 0); ok = ok && (m_Controls.TRSpinBox->value() > 0); ok = ok && (m_Controls.RelaxivitySpinBox->value() > 0); ok = ok && (m_Controls.PDWImageNodeSelector->GetSelectedNode().IsNotNull()); ok = ok && CheckBaselineSelectionSettings(); } else if (this->m_Controls.radioButtonNoConversion->isChecked()) { ok = ok && true; } else { ok = false; } if (isNum2CXMFactory) { ok = ok && (this->m_Controls.odeStepSize->value() > 0); } } //add other models as else if and check wether all needed static parameters are set else { ok = false; } if (this->m_Controls.radioButton_StartParameters->isChecked() && !this->m_Controls.initialValuesManager->hasValidInitialValues()) { std::string warning = "Warning. Invalid start parameters. At least one parameter as an invalid image setting as source."; MITK_ERROR << warning; m_Controls.infoBox->append(QString("") + QString::fromStdString(warning) + QString("")); ok = false; }; } else { ok = false; } return ok; } bool MRPerfusionView::CheckBaselineSelectionSettings() const { return m_Controls.spinBox_baselineStartTimeStep->value() <= m_Controls.spinBox_baselineEndTimeStep->value(); } void MRPerfusionView::ConfigureInitialParametersOfParameterizer(mitk::ModelParameterizerBase* parameterizer) const { if (m_Controls.radioButton_StartParameters->isChecked()) { //use user defined initial parameters mitk::InitialParameterizationDelegateBase::Pointer paramDelegate = m_Controls.initialValuesManager->getInitialParametrizationDelegate(); parameterizer->SetInitialParameterizationDelegate(paramDelegate); } } void MRPerfusionView::GenerateDescriptiveBrixModel_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) { mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = mitk::PixelBasedParameterFitImageGenerator::New(); mitk::DescriptivePharmacokineticBrixModelParameterizer::Pointer modelParameterizer = mitk::DescriptivePharmacokineticBrixModelParameterizer::New(); //Model configuration (static parameters) can be done now modelParameterizer->SetTau(m_Controls.injectiontime->value()); mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); imageTimeSelector->SetInput(this->m_selectedImage); imageTimeSelector->SetTimeNr(0); imageTimeSelector->UpdateLargestPossibleRegion(); mitk::DescriptivePharmacokineticBrixModelParameterizer::BaseImageType::Pointer baseImage; mitk::CastToItkImage(imageTimeSelector->GetOutput(), baseImage); modelParameterizer->SetBaseImage(baseImage); this->ConfigureInitialParametersOfParameterizer(modelParameterizer); //Specify fitting strategy and criterion parameters mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer); //Parametrize fit generator fitGenerator->SetModelParameterizer(modelParameterizer); std::string roiUID = ""; if (m_selectedMask.IsNotNull()) { fitGenerator->SetMask(m_selectedMask); roiUID = m_selectedMask->GetUID(); } fitGenerator->SetDynamicImage(m_selectedImage); fitGenerator->SetFitFunctor(fitFunctor); generator = fitGenerator.GetPointer(); //Create model info modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, m_selectedNode->GetData(), mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED(), this->GetFitName(), roiUID); } void MRPerfusionView::GenerateDescriptiveBrixModel_ROIBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) { if (m_selectedMask.IsNull()) { return; } mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator = mitk::ROIBasedParameterFitImageGenerator::New(); mitk::DescriptivePharmacokineticBrixModelValueBasedParameterizer::Pointer modelParameterizer = mitk::DescriptivePharmacokineticBrixModelValueBasedParameterizer::New(); //Compute ROI signal mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = mitk::MaskedDynamicImageStatisticsGenerator::New(); signalGenerator->SetMask(m_selectedMask); signalGenerator->SetDynamicImage(m_selectedImage); signalGenerator->Generate(); mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean(); //Model configuration (static parameters) can be done now modelParameterizer->SetTau(m_Controls.injectiontime->value()); modelParameterizer->SetBaseValue(roiSignal[0]); this->ConfigureInitialParametersOfParameterizer(modelParameterizer); //Specify fitting strategy and criterion parameters mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer); //Parametrize fit generator fitGenerator->SetModelParameterizer(modelParameterizer); fitGenerator->SetMask(m_selectedMask); fitGenerator->SetFitFunctor(fitFunctor); fitGenerator->SetSignal(roiSignal); fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(m_selectedImage)); generator = fitGenerator.GetPointer(); std::string roiUID = this->m_selectedMask->GetUID(); //Create model info modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, m_selectedNode->GetData(), mitk::ModelFitConstants::FIT_TYPE_VALUE_ROIBASED(), this->GetFitName(), roiUID); mitk::ScalarListLookupTable::ValueType infoSignal; for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos = roiSignal.begin(); pos != roiSignal.end(); ++pos) { infoSignal.push_back(*pos); } modelFitInfo->inputData.SetTableValue("ROI", infoSignal); } template void MRPerfusionView::GenerateLinearModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) { mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = mitk::PixelBasedParameterFitImageGenerator::New(); typename TParameterizer::Pointer modelParameterizer = TParameterizer::New(); this->ConfigureInitialParametersOfParameterizer(modelParameterizer); //Specify fitting strategy and criterion parameters mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer); //Parametrize fit generator fitGenerator->SetModelParameterizer(modelParameterizer); std::string roiUID = ""; if (m_selectedMask.IsNotNull()) { fitGenerator->SetMask(m_selectedMask); roiUID = this->m_selectedMask->GetUID(); } fitGenerator->SetDynamicImage(m_selectedImage); fitGenerator->SetFitFunctor(fitFunctor); generator = fitGenerator.GetPointer(); //Create model info modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, m_selectedNode->GetData(), mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED(), this->GetFitName(), roiUID); } template void MRPerfusionView::GenerateLinearModelFit_ROIBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) { if (m_selectedMask.IsNull()) { return; } mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator = mitk::ROIBasedParameterFitImageGenerator::New(); typename TParameterizer::Pointer modelParameterizer = TParameterizer::New(); //Compute ROI signal mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = mitk::MaskedDynamicImageStatisticsGenerator::New(); signalGenerator->SetMask(m_selectedMask); signalGenerator->SetDynamicImage(m_selectedImage); signalGenerator->Generate(); mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean(); //Model configuration (static parameters) can be done now this->ConfigureInitialParametersOfParameterizer(modelParameterizer); //Specify fitting strategy and criterion parameters mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer); //Parametrize fit generator fitGenerator->SetModelParameterizer(modelParameterizer); fitGenerator->SetMask(m_selectedMask); fitGenerator->SetFitFunctor(fitFunctor); fitGenerator->SetSignal(roiSignal); fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(m_selectedImage)); generator = fitGenerator.GetPointer(); std::string roiUID = this->m_selectedMask->GetUID(); //Create model info modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, m_selectedNode->GetData(), mitk::ModelFitConstants::FIT_TYPE_VALUE_ROIBASED(), this->GetFitName(), roiUID); mitk::ScalarListLookupTable::ValueType infoSignal; for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos = roiSignal.begin(); pos != roiSignal.end(); ++pos) { infoSignal.push_back(*pos); } modelFitInfo->inputData.SetTableValue("ROI", infoSignal); } template void MRPerfusionView::GenerateAIFbasedModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) { mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = mitk::PixelBasedParameterFitImageGenerator::New(); typename TParameterizer::Pointer modelParameterizer = TParameterizer::New(); PrepareConcentrationImage(); mitk::AIFBasedModelBase::AterialInputFunctionType aif; mitk::AIFBasedModelBase::AterialInputFunctionType aifTimeGrid; GetAIF(aif, aifTimeGrid); modelParameterizer->SetAIF(aif); modelParameterizer->SetAIFTimeGrid(aifTimeGrid); this->ConfigureInitialParametersOfParameterizer(modelParameterizer); mitk::NumericTwoCompartmentExchangeModelParameterizer* numTCXParametrizer = dynamic_cast (modelParameterizer.GetPointer()); if (numTCXParametrizer) { numTCXParametrizer->SetODEINTStepSize(this->m_Controls.odeStepSize->value()); } //Specify fitting strategy and criterion parameters mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer); //Parametrize fit generator fitGenerator->SetModelParameterizer(modelParameterizer); std::string roiUID = ""; if (m_selectedMask.IsNotNull()) { fitGenerator->SetMask(m_selectedMask); roiUID = this->m_selectedMask->GetUID(); } fitGenerator->SetDynamicImage(this->m_inputImage); fitGenerator->SetFitFunctor(fitFunctor); generator = fitGenerator.GetPointer(); //Create model info modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, this->m_inputImage, mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED(), this->GetFitName(), roiUID); mitk::ScalarListLookupTable::ValueType infoSignal; for (mitk::AIFBasedModelBase::AterialInputFunctionType::const_iterator pos = aif.begin(); pos != aif.end(); ++pos) { infoSignal.push_back(*pos); } modelFitInfo->inputData.SetTableValue("AIF", infoSignal); } template void MRPerfusionView::GenerateAIFbasedModelFit_ROIBased( mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) { if (m_selectedMask.IsNull()) { return; } mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator = mitk::ROIBasedParameterFitImageGenerator::New(); typename TParameterizer::Pointer modelParameterizer = TParameterizer::New(); PrepareConcentrationImage(); mitk::AIFBasedModelBase::AterialInputFunctionType aif; mitk::AIFBasedModelBase::AterialInputFunctionType aifTimeGrid; GetAIF(aif, aifTimeGrid); modelParameterizer->SetAIF(aif); modelParameterizer->SetAIFTimeGrid(aifTimeGrid); this->ConfigureInitialParametersOfParameterizer(modelParameterizer); mitk::NumericTwoCompartmentExchangeModelParameterizer* numTCXParametrizer = dynamic_cast (modelParameterizer.GetPointer()); if (numTCXParametrizer) { numTCXParametrizer->SetODEINTStepSize(this->m_Controls.odeStepSize->value()); } //Compute ROI signal mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = mitk::MaskedDynamicImageStatisticsGenerator::New(); signalGenerator->SetMask(m_selectedMask); signalGenerator->SetDynamicImage(this->m_inputImage); signalGenerator->Generate(); mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean(); //Specify fitting strategy and criterion parameters mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer); //Parametrize fit generator fitGenerator->SetModelParameterizer(modelParameterizer); fitGenerator->SetMask(m_selectedMask); fitGenerator->SetFitFunctor(fitFunctor); fitGenerator->SetSignal(roiSignal); fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(this->m_inputImage)); generator = fitGenerator.GetPointer(); std::string roiUID = this->m_selectedMask->GetUID(); //Create model info modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, this->m_inputImage, mitk::ModelFitConstants::FIT_TYPE_VALUE_ROIBASED(), this->GetFitName(), roiUID); mitk::ScalarListLookupTable::ValueType infoSignal; for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos = roiSignal.begin(); pos != roiSignal.end(); ++pos) { infoSignal.push_back(*pos); } modelFitInfo->inputData.SetTableValue("ROI", infoSignal); infoSignal.clear(); for (mitk::AIFBasedModelBase::AterialInputFunctionType::const_iterator pos = aif.begin(); pos != aif.end(); ++pos) { infoSignal.push_back(*pos); } modelFitInfo->inputData.SetTableValue("AIF", infoSignal); } void MRPerfusionView::DoFit(const mitk::modelFit::ModelFitInfo* fitSession, mitk::ParameterFitImageGeneratorBase* generator) { this->m_Controls.infoBox->append(QString("" + QString("Fitting Data Set . . .") + QString (""))); ///////////////////////// //create job and put it into the thread pool mitk::modelFit::ModelFitResultNodeVectorType additionalNodes; if (m_HasGeneratedNewInput) { additionalNodes.push_back(m_inputNode); } if (m_HasGeneratedNewInputAIF) { additionalNodes.push_back(m_inputAIFNode); } ParameterFitBackgroundJob* pJob = new ParameterFitBackgroundJob(generator, fitSession, this->m_selectedNode, additionalNodes); pJob->setAutoDelete(true); connect(pJob, SIGNAL(Error(QString)), this, SLOT(OnJobError(QString))); connect(pJob, SIGNAL(Finished()), this, SLOT(OnJobFinished())); connect(pJob, SIGNAL(ResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType, const ParameterFitBackgroundJob*)), this, SLOT(OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType, const ParameterFitBackgroundJob*)), Qt::BlockingQueuedConnection); connect(pJob, SIGNAL(JobProgress(double)), this, SLOT(OnJobProgress(double))); connect(pJob, SIGNAL(JobStatusChanged(QString)), this, SLOT(OnJobStatusChanged(QString))); QThreadPool* threadPool = QThreadPool::globalInstance(); threadPool->start(pJob); } MRPerfusionView::MRPerfusionView() : m_FittingInProgress(false), m_HasGeneratedNewInput(false), m_HasGeneratedNewInputAIF(false) { m_selectedImage = nullptr; m_selectedMask = nullptr; mitk::ModelFactoryBase::Pointer factory = mitk::DescriptivePharmacokineticBrixModelFactory::New().GetPointer(); m_FactoryStack.push_back(factory); factory = mitk::TwoStepLinearModelFactory::New().GetPointer(); m_FactoryStack.push_back(factory); factory = mitk::ThreeStepLinearModelFactory::New().GetPointer(); m_FactoryStack.push_back(factory); factory = mitk::StandardToftsModelFactory::New().GetPointer(); m_FactoryStack.push_back(factory); factory = mitk::ExtendedToftsModelFactory::New().GetPointer(); m_FactoryStack.push_back(factory); factory = mitk::TwoCompartmentExchangeModelFactory::New().GetPointer(); m_FactoryStack.push_back(factory); factory = mitk::NumericTwoCompartmentExchangeModelFactory::New().GetPointer(); m_FactoryStack.push_back(factory); mitk::NodePredicateDataType::Pointer isLabelSet = mitk::NodePredicateDataType::New("LabelSetImage"); mitk::NodePredicateDataType::Pointer isImage = mitk::NodePredicateDataType::New("Image"); mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateAnd::Pointer isLegacyMask = mitk::NodePredicateAnd::New(isImage, isBinary); mitk::NodePredicateDimension::Pointer is3D = mitk::NodePredicateDimension::New(3); mitk::NodePredicateOr::Pointer isMask = mitk::NodePredicateOr::New(isLegacyMask, isLabelSet); mitk::NodePredicateAnd::Pointer isNoMask = mitk::NodePredicateAnd::New(isImage, mitk::NodePredicateNot::New(isMask)); mitk::NodePredicateAnd::Pointer is3DImage = mitk::NodePredicateAnd::New(isImage, is3D, isNoMask); this->m_IsMaskPredicate = mitk::NodePredicateAnd::New(isMask, mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))).GetPointer(); this->m_IsNoMaskImagePredicate = mitk::NodePredicateAnd::New(isNoMask, mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))).GetPointer(); auto isDynamicData = mitk::NodePredicateFunction::New([](const mitk::DataNode* node) { return (node && node->GetData() && node->GetData()->GetTimeSteps() > 1); }); - auto isNoModelFitNodePredicate = mitk::NodePredicateFunction::New([](const mitk::DataNode* node) { - bool isNoModelFitNode = node->GetData()->GetProperty(mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME().c_str()).IsNull(); - return isNoModelFitNode; - }); - + auto modelFitResultRelationRule = mitk::ModelFitResultRelationRule::New(); + auto isNoModelFitNodePredicate = mitk::NodePredicateNot::New(modelFitResultRelationRule->GetConnectedSourcesDetector()); this->m_isValidPDWImagePredicate = mitk::NodePredicateAnd::New(is3DImage, isNoModelFitNodePredicate); this->m_isValidTimeSeriesImagePredicate = mitk::NodePredicateAnd::New(isDynamicData, isImage, isNoMask); } void MRPerfusionView::OnJobFinished() { this->m_Controls.infoBox->append(QString("Fitting finished.")); this->m_FittingInProgress = false; this->UpdateGUIControls(); }; void MRPerfusionView::OnJobError(QString err) { MITK_ERROR << err.toStdString().c_str(); m_Controls.infoBox->append(QString("") + err + QString("")); }; void MRPerfusionView::OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType results, const ParameterFitBackgroundJob* pJob) { //Store the resulting parameter fit image via convenience helper function in data storage //(handles the correct generation of the nodes and their properties) mitk::modelFit::StoreResultsInDataStorage(this->GetDataStorage(), results, pJob->GetParentNode()); //this stores the concentration image and AIF concentration image, if generated for this fit in the storage. //if not generated for this fit, relevant nodes are empty. mitk::modelFit::StoreResultsInDataStorage(this->GetDataStorage(), pJob->GetAdditionalRelevantNodes(), pJob->GetParentNode()); }; void MRPerfusionView::OnJobProgress(double progress) { QString report = QString("Progress. ") + QString::number(progress); this->m_Controls.infoBox->append(report); }; void MRPerfusionView::OnJobStatusChanged(QString info) { this->m_Controls.infoBox->append(info); } void MRPerfusionView::InitModelComboBox() const { this->m_Controls.comboModel->clear(); this->m_Controls.comboModel->addItem(tr("No model selected")); for (ModelFactoryStackType::const_iterator pos = m_FactoryStack.begin(); pos != m_FactoryStack.end(); ++pos) { this->m_Controls.comboModel->addItem(QString::fromStdString((*pos)->GetClassID())); } this->m_Controls.comboModel->setCurrentIndex(0); }; mitk::DataNode::Pointer MRPerfusionView::GenerateConcentrationNode(mitk::Image* image, const std::string& nodeName) const { if (!image) { mitkThrow() << "Cannot generate concentration node. Passed image is null. parameter name: "; } mitk::DataNode::Pointer result = mitk::DataNode::New(); result->SetData(image); result->SetName(nodeName); result->SetVisibility(true); return result; }; mitk::Image::Pointer MRPerfusionView::ConvertConcentrationImage(bool AIFMode) { //Compute Concentration image mitk::ConcentrationCurveGenerator::Pointer concentrationGen = mitk::ConcentrationCurveGenerator::New(); if (m_Controls.checkDedicatedAIFImage->isChecked() && AIFMode) { concentrationGen->SetDynamicImage(this->m_selectedAIFImage); } else { concentrationGen->SetDynamicImage(this->m_selectedImage); } concentrationGen->SetisTurboFlashSequence(IsTurboFlashSequenceFlag()); concentrationGen->SetAbsoluteSignalEnhancement(m_Controls.radioButton_absoluteEnhancement->isChecked()); concentrationGen->SetRelativeSignalEnhancement(m_Controls.radioButton_relativeEnchancement->isChecked()); concentrationGen->SetUsingT1Map(m_Controls.radioButtonUsingT1viaVFA->isChecked()); if (IsTurboFlashSequenceFlag()) { if (AIFMode) { concentrationGen->SetRecoveryTime(m_Controls.AifRecoverytime->value()); } else { concentrationGen->SetRecoveryTime(m_Controls.recoverytime->value()); } concentrationGen->SetRelaxationTime(m_Controls.relaxationtime->value()); concentrationGen->SetRelaxivity(m_Controls.relaxivity->value()); concentrationGen->SetBaselineStartTimeStep(m_Controls.spinBox_baselineStartTimeStep->value()); concentrationGen->SetBaselineEndTimeStep(m_Controls.spinBox_baselineEndTimeStep->value()); } else if (this->m_Controls.radioButtonUsingT1viaVFA->isChecked()) { concentrationGen->SetRecoveryTime(m_Controls.TRSpinBox->value()); concentrationGen->SetRelaxivity(m_Controls.RelaxivitySpinBox->value()); concentrationGen->SetT10Image(dynamic_cast(m_Controls.PDWImageNodeSelector->GetSelectedNode()->GetData())); concentrationGen->SetBaselineStartTimeStep(m_Controls.spinBox_baselineStartTimeStep->value()); concentrationGen->SetBaselineEndTimeStep(m_Controls.spinBox_baselineEndTimeStep->value()); //Convert Flipangle from degree to radiant double alpha = m_Controls.FlipangleSpinBox->value()/360*2* boost::math::constants::pi(); concentrationGen->SetFlipAngle(alpha); } else { concentrationGen->SetFactor(m_Controls.factorSpinBox->value()); concentrationGen->SetBaselineStartTimeStep(m_Controls.spinBox_baselineStartTimeStep->value()); concentrationGen->SetBaselineEndTimeStep(m_Controls.spinBox_baselineEndTimeStep->value()); } mitk::Image::Pointer concentrationImage = concentrationGen->GetConvertedImage(); return concentrationImage; } void MRPerfusionView::GetAIF(mitk::AIFBasedModelBase::AterialInputFunctionType& aif, mitk::AIFBasedModelBase::AterialInputFunctionType& aifTimeGrid) { if (this->m_Controls.radioAIFFile->isChecked()) { aif.clear(); aifTimeGrid.clear(); aif.SetSize(AIFinputFunction.size()); aifTimeGrid.SetSize(AIFinputGrid.size()); aif.fill(0.0); aifTimeGrid.fill(0.0); itk::Array::iterator aifPos = aif.begin(); for (std::vector::const_iterator pos = AIFinputFunction.begin(); pos != AIFinputFunction.end(); ++pos, ++aifPos) { *aifPos = *pos; } itk::Array::iterator gridPos = aifTimeGrid.begin(); for (std::vector::const_iterator pos = AIFinputGrid.begin(); pos != AIFinputGrid.end(); ++pos, ++gridPos) { *gridPos = *pos; } } else if (this->m_Controls.radioAIFImage->isChecked()) { aif.clear(); aifTimeGrid.clear(); mitk::AterialInputFunctionGenerator::Pointer aifGenerator = mitk::AterialInputFunctionGenerator::New(); //Hematocrit level aifGenerator->SetHCL(this->m_Controls.HCLSpinBox->value()); //mask settings this->m_selectedAIFMaskNode = m_Controls.AIFMaskNodeSelector->GetSelectedNode(); this->m_selectedAIFMask = dynamic_cast(this->m_selectedAIFMaskNode->GetData()); if (this->m_selectedAIFMask->GetTimeSteps() > 1) { MITK_INFO << "Selected AIF mask has multiple timesteps. Only use first timestep to mask model fit. AIF Mask name: " << m_selectedAIFMaskNode->GetName() ; mitk::ImageTimeSelector::Pointer maskedImageTimeSelector = mitk::ImageTimeSelector::New(); maskedImageTimeSelector->SetInput(this->m_selectedAIFMask); maskedImageTimeSelector->SetTimeNr(0); maskedImageTimeSelector->UpdateLargestPossibleRegion(); this->m_selectedAIFMask = maskedImageTimeSelector->GetOutput(); } if (this->m_selectedAIFMask.IsNotNull()) { aifGenerator->SetMask(this->m_selectedAIFMask); } //image settings if (this->m_Controls.checkDedicatedAIFImage->isChecked()) { this->m_selectedAIFImageNode = m_Controls.AIFImageNodeSelector->GetSelectedNode(); this->m_selectedAIFImage = dynamic_cast(this->m_selectedAIFImageNode->GetData()); } else { this->m_selectedAIFImageNode = m_selectedNode; this->m_selectedAIFImage = m_selectedImage; } this->PrepareAIFConcentrationImage(); aifGenerator->SetDynamicImage(this->m_inputAIFImage); aif = aifGenerator->GetAterialInputFunction(); aifTimeGrid = aifGenerator->GetAterialInputFunctionTimeGrid(); } else { mitkThrow() << "Cannot generate AIF. View is in a invalide state. No AIF mode selected."; } } void MRPerfusionView::LoadAIFfromFile() { QFileDialog dialog; dialog.setNameFilter(tr("Images (*.csv")); QString fileName = dialog.getOpenFileName(); m_Controls.aifFilePath->setText(fileName); std::string m_aifFilePath = fileName.toStdString(); //Read Input typedef boost::tokenizer< boost::escaped_list_separator > Tokenizer; ///////////////////////////////////////////////////////////////////////////////////////////////// //AIF Data std::ifstream in1(m_aifFilePath.c_str()); if (!in1.is_open()) { this->m_Controls.infoBox->append(QString("Could not open AIF File!")); } std::vector< std::string > vec1; std::string line1; while (getline(in1, line1)) { Tokenizer tok(line1); vec1.assign(tok.begin(), tok.end()); this->AIFinputGrid.push_back(convertToDouble(vec1[0])); this->AIFinputFunction.push_back(convertToDouble(vec1[1])); } } void MRPerfusionView::PrepareConcentrationImage() { mitk::Image::Pointer concentrationImage = this->m_selectedImage; mitk::DataNode::Pointer concentrationNode = this->m_selectedNode; m_HasGeneratedNewInput = false; if (!this->m_Controls.radioButtonNoConversion->isChecked()) { concentrationImage = this->ConvertConcentrationImage(false); concentrationNode = GenerateConcentrationNode(concentrationImage, "Concentration"); m_HasGeneratedNewInput = true; } m_inputImage = concentrationImage; m_inputNode = concentrationNode; } void MRPerfusionView::PrepareAIFConcentrationImage() { mitk::Image::Pointer concentrationImage = this->m_selectedImage; mitk::DataNode::Pointer concentrationNode = this->m_selectedNode; m_HasGeneratedNewInputAIF = false; if (this->m_Controls.checkDedicatedAIFImage->isChecked()) { concentrationImage = this->m_selectedAIFImage; concentrationNode = this->m_selectedAIFImageNode; } if (!this->m_Controls.radioButtonNoConversion->isChecked()) { if (!IsTurboFlashSequenceFlag() && !this->m_Controls.checkDedicatedAIFImage->isChecked()) { if (m_inputImage.IsNull()) { mitkThrow() << "Cannot get AIF concentration image. Invalid view state. Input image is not defined yet, but should be."; } //we can directly use the concentration input image/node (generated by GetConcentrationImage) also for the AIF concentrationImage = this->m_inputImage; concentrationNode = this->m_inputNode; } else { concentrationImage = this->ConvertConcentrationImage(true); concentrationNode = GenerateConcentrationNode(concentrationImage, "AIF Concentration"); m_HasGeneratedNewInputAIF = true; } } m_inputAIFImage = concentrationImage; m_inputAIFNode = concentrationNode; } mitk::ModelFitFunctorBase::Pointer MRPerfusionView::CreateDefaultFitFunctor( const mitk::ModelParameterizerBase* parameterizer) const { mitk::LevenbergMarquardtModelFitFunctor::Pointer fitFunctor = mitk::LevenbergMarquardtModelFitFunctor::New(); mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::Pointer chi2 = mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::New(); fitFunctor->RegisterEvaluationParameter("Chi^2", chi2); if (m_Controls.checkBox_Constraints->isChecked()) { fitFunctor->SetConstraintChecker(m_modelConstraints); } mitk::ModelBase::Pointer refModel = parameterizer->GenerateParameterizedModel(); ::itk::LevenbergMarquardtOptimizer::ScalesType scales; scales.SetSize(refModel->GetNumberOfParameters()); scales.Fill(1.0); fitFunctor->SetScales(scales); fitFunctor->SetDebugParameterMaps(m_Controls.checkDebug->isChecked()); return fitFunctor.GetPointer(); } diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/UserManual/QmitkPhenotypingPortalPage.dox b/Plugins/org.mitk.gui.qt.radiomics/documentation/UserManual/QmitkPhenotypingPortalPage.dox index a2cc0e7284..69c9dce5b6 100644 --- a/Plugins/org.mitk.gui.qt.radiomics/documentation/UserManual/QmitkPhenotypingPortalPage.dox +++ b/Plugins/org.mitk.gui.qt.radiomics/documentation/UserManual/QmitkPhenotypingPortalPage.dox @@ -1,41 +1,41 @@ /** \page org_mitk_gui_qt_mitkphenotyping The Phenotyping \tableofcontents MITK Phenotyping is a selection of algorithms that can be used to extract image-based phenotypes, for example using a radiomics approach. The software is part of the research of the Division of Medical Image Computing of the German Cancer Research Center (DKFZ). MITK Phenotyping is not intended to be a single application, it is rather a collection of the necessary plugins within the offical MITK releases. The functionality of MITK Phenotyping can be accessed in different ways: Using the graphical interface using the Plugins listed below, using command line applications, or using one of the programming interfaces. \section org_mitk_gui_qt_mitkphenotyping_Tutorials Tutorials \li \subpage org_mitk_views_radiomicstutorial_gui_portal A tutorial on how to use the grapical interface of MITK Phenotying \section org_mitk_gui_qt_mitkphenotyping_Views Views \subsection sub2 Specific Views: Views that were developed with the main focus on Radiomics. They still might be used in other use-cases as well: \li \subpage org_mitk_views_radiomicstransformationview : Image transformations like Resampling, Laplacian of Gaussian, and Wavelet Transformations \li \subpage org_mitk_views_radiomicsmaskprocessingview : Processing and Cleaning of Masks \li \subpage org_mitk_views_radiomicsarithmetricview : Processing images using mathematical operations \li \subpage org_mitk_views_radiomicsstatisticview : Calculate Radiomics Features \subsection sub1 Non-Specific Views: This section contains views that are included within MITK Phenotyping, but were developed with a broader application in mind. \li \subpage org_mitk_views_basicimageprocessing : Deprecated plugin for performing different image-related tasks like subtraction, mutliplaction, filtering etc. -\li \subpage org_mitk_gui_qt_matchpoint_algorithm_browser : Selection of MatchPoint (Registration) Algorithm -\li \subpage org_mitk_gui_qt_matchpoint_algorithm_control : Configuring and Controlling MatchPoint (Registration) Algorithm -\li \subpage org_mitk_gui_qt_matchpoint_evaluator : Evaluate the Registration performance using MatchPoint -\li \subpage org_mitk_gui_qt_matchpoint_manipulator : Adapt a registration calculated using MatchPoint -\li \subpage org_mitk_gui_qt_matchpoint_mapper : Apply a MatchPoint Registration to a specific image -\li \subpage org_mitk_gui_qt_matchpoint_visualizer : Visualize a Registration obtained with MatchPoint -\li \subpage org_mitk_gui_qt_matchpoint_algorithm_batch : Running MatchPoint over multiple images (BatchMode) +\li \subpage org_mitk_views_matchpoint_algorithm_browser : Selection of MatchPoint (Registration) Algorithm +\li \subpage org_mitk_views_matchpoint_algorithm_control : Configuring and Controlling MatchPoint (Registration) Algorithm +\li \subpage org_mitk_views_matchpoint_evaluator : Evaluate the Registration performance using MatchPoint +\li \subpage org_mitk_views_matchpoint_manipulator : Adapt a registration calculated using MatchPoint +\li \subpage org_mitk_views_matchpoint_mapper : Apply a MatchPoint Registration to a specific image +\li \subpage org_mitk_views_matchpoint_visualizer : Visualize a Registration obtained with MatchPoint +\li \subpage org_mitk_views_matchpoint_algorithm_batch : Running MatchPoint over multiple images (BatchMode) \li \subpage org_mitk_views_multilabelsegmentation : Create and editing of Multilabel-Segmentations. \li \subpage org_mitk_views_segmentation : Create simple segmentations \li \subpage org_mitk_views_segmentationutilities : Utilities for the processing of simple segmentations. \section radiomics_miniapps MiniApps (Command line Tools) \li \subpage MiniAppExplainPage Explanation of the Command Line App concept in MITK \li \subpage mitkBasicImageProcessingMiniAppsPortalPage : List of common preprocessing MiniApps \li \subpage mitkClassificationMiniAppsPortalPage : (Incomplete) list of MITK Classification MiniApps */ diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_03_Preprocessing.dox b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_03_Preprocessing.dox index 52194c1bcd..33b6af06c5 100644 --- a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_03_Preprocessing.dox +++ b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_03_Preprocessing.dox @@ -1,23 +1,23 @@ /** \page org_mitk_views_radiomicstutorial_gui_03_preprocessing GUI based Radiomics Tutorial - Preprocessing the data \subsection Preprocessing the data The first step we take is to resample the data. To do so, we open the "Radiomics Transformation" View and select the "Resample Image" panel. We start by resampling the original image and therefore select the original picture (for us, Pic3D). Right-clicking on the image in the "Data Manager" and selecting the option "Details" gives us more information on the image. As we can see, our image has a spacing of [1, 1, 3], with an inplane resolution of 1x1mm and a out-of-plane resolution of 3 mm. We therefore decide to resample the image to an isotropic resolution of 1x1x1 mm. \imageMacro{RadiomicsTutorial_GUI_Step3_01_DetailView.png,"Details showing the spacing of the original image.",1} -To resample the image, we de-select "Dimension X" and "Dimension Y" option and set the "Dimension Z" option to 1, as indiciated by the image above. This tells the resampling algorithm to change only the last dimension to the value we specified. We further select to have the output image as double and chose B-Spline as resampling algorithm. This is a fast and still accurate option for resampling. To learn more about the other interpolation modes, refer to \ref org_mitk_gui_qt_matchpoint_mapper . +To resample the image, we de-select "Dimension X" and "Dimension Y" option and set the "Dimension Z" option to 1, as indiciated by the image above. This tells the resampling algorithm to change only the last dimension to the value we specified. We further select to have the output image as double and chose B-Spline as resampling algorithm. This is a fast and still accurate option for resampling. To learn more about the other interpolation modes, refer to \ref org_mitk_views_matchpoint_mapper . After resampling the original image, we also need to resample the segmentation. For this, we select the segmentation, leave the dimensions unchanged. Remove the "Output as double" option, as segmentations are not double values and choose a linear interpolation, which seems to be a better solution for resampling masks. We also check the option that we are resampling a mask. After performing those two steps, there should be two additional, resampled images in the "Data Manager". As a second step, we calculate some Laplacian of Gaussian images of the resampled image that allow us to capture more detailed information. For this, we select the panel "Laplacian of Gaussian" of the "Radiomics Transformation"-view and perform the algorithm three times with different sigma values (we chose 1,2, and 4). Make sure that you selected the right image to calculate the image, i.e. the resampled image. Finally, we clear the mask to obtain a clear segmentation of the target structure and remove possible resampling artifacts. To do so, we open the "Radiomics Mask Processing" View and select the resampled image and the resampled mask. We then select a lower limit only and set it to 160. Since we are working with MR, this is not a fixed value but something we manually determined. With this set, we perform the mask reducing by cklicking "Clean Mask based on Intervall". After this, we have the resampled image, three LoG images and a resampled and cleaned mask. The result should look similar to the next picture. You can also see the final image structure we obtained from our processing. It might help you to compare your results, although it is not necessary to obtain the same structure as long as you have all necessary images. \imageMacro{RadiomicsTutorial_GUI_Step3_02_FinishedPreprocessing.png,"Final results with a completed resampling",1} */ \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/CMakeLists.txt b/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/CMakeLists.txt index 2976e1079d..d8535984e4 100755 --- a/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/CMakeLists.txt @@ -1,8 +1,7 @@ project(org_mitk_gui_qt_stdmultiwidgeteditor) mitk_create_plugin( EXPORT_DIRECTIVE ORG_MITK_GUI_QT_STDMULTIWIDGETEDITOR EXPORTED_INCLUDE_SUFFIXES src MODULE_DEPENDS MitkQtWidgets - SUBPROJECTS MITK-CoreUI ) diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization.dox b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization.dox index 49360ff183..c1c47212a6 100644 --- a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization.dox +++ b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization.dox @@ -1,154 +1,140 @@ /** \page org_mitk_views_volumevisualization The Volume Visualization Plugin \imageMacro{volume_visualization.svg,"Icon of the Volume Visualization Plugin",2.00} \tableofcontents \section QVV_Overview Overview -The Volume Visualization Plugin is a basic tool for visualizing three dimensional medical images. -MITK provides generic transfer function presets for medical CT data. -These functions, that map the gray-value to color and opacity, can be interactively edited. -Additionally, there are controls to quickly generate common used transfer function shapes -like the threshold and bell curve to help identify a range of grey-values. +The Volume Visualization Plugin is a basic tool for volume rendering of three dimensional medical images. +MITK provides generic transfer function presets for medical CT and MRT data. +These functions that map the gray-value to color and opacity can be interactively edited. +Additionally, there are controls to quickly generate commonly used transfer function shapes like the threshold and bell curve to help identify a range of grey-values. \imageMacro{QmitkVolumeVisualization_Overview.png,"",16.00} -\section QVV_EnableVRPage Enable Volume Rendering +\section QVV_EnableVRPage Volume Rendering -\subsection QVV_LoadingImage Loading an image into the application +\subsection QVV_LoadingImage Select an image and enable volume rendering -Load an image into the application by +\imageMacro{QmitkVolumeVisualization_Checkboxen.png,"",8.21} -
    -
  • dragging a file into the application window. -
  • selecting file / load from the menu. -
+Select an image on top of the view and click on the checkbox left of 'Volumerendering'. Please be patient, while the image is prepared for rendering, which can take up to a half minute. +\note Volume Visualization imposes following restrictions on images: -
    -
  • It has to be a 3D-Image Scalar image, that means a normal CT or MRT. -
  • 3D+T are supported for rendering, but the histograms are not computed. -
  • Also be aware that volume visualization requires a huge amount of memory. - Very large images may not work, unless you use the 64bit version. +
  • It has to be a 3D scalar image, that means e.g. a CT or MRT image. +
  • 3D+t images are supported for rendering, but the histograms are not computed. +
  • Also be aware that volume visualization requires a huge amount of memory. Very large images may not work unless you use the 64bit version.
-\subsection QVV_EnableVR Enable Volumerendering - -\imageMacro{QmitkVolumeVisualization_Checkboxen.png,"",8.21} - -Select an image in datamanager and click on the checkbox left of "Volumerendering". -Please be patient, while the image is prepared for rendering, which can take up to a half minute. \subsection QVV_LODGPU Dropdown menus for the rendering and blend modes -Two dropdown menus allow selection of rendering mode (Default, RayCast, GPU) and the blend mode (Composite, Max, Min, Avg, Add). +Two dropdown menus are located right next to the 'Volumerendering' checkbox. They allow you to select a rendering mode (Default, RayCast, GPU) and the blend mode (Composite, Max, Min, Avg, Add). -Any Volume Rendering mode requires a lot of computing resources including processor, memory and often also graphics card. -The Default selection usually finds the best rendering mode for the available hardware. -Alternatively, it is possible to manually specify the selections RayCast and GPU. -The RayCast selection is based on CPU computation and therefore typically slow, but allows to render without hardware acceleration. -The GPU selection uses computing resources on the graphics card to accelerate volume rendering. -It requires a powerful graphics card and OpenGL hardware support for shaders, but achieves much higher frame rates than software-rendering. +Any rendering mode requires a lot of computing resources including processor, memory and often also graphics card. +The 'Default' selection usually finds the best 'rendering' mode for the available hardware. +Alternatively, it is possible to manually specify the selections 'RayCast' and 'GPU'. +The 'RayCast' selection is based on CPU computation and therefore typically slow, but allows to render without hardware acceleration. +The 'GPU' selection uses computing resources on the graphics card to accelerate volume rendering. +It requires a powerful graphics card and OpenGL hardware support for shaders but achieves much higher frame rates than software-rendering. -Blend modes define how the volume voxels intersected by the rendering rays are pooled. The composite mode specifies standard volume rendering, -for which each voxel contributes equally with opacity and color. Other blend modes simply visualize the voxel of maximum / -minimum intensity and average / add the intentities along the rendering ray. +Blend modes define how the volume voxels, intersected by the rendering rays, are pooled. The 'Composite' mode specifies standard volume rendering, +for which each voxel contributes equally with opacity and color. Other 'blend' modes simply visualize the voxel of the maximum / +minimum intensity and average / add the intensities along the rendering ray. \section QVV_PresetPage Applying premade presets \subsection QVV_Preset Internal presets -There are some internal presets given, that can be used with normal CT data (given in Houndsfield units). -A large set of medical data has been tested with that presets, but it may not suit on some special cases. +There are some internal presets given that can be used with normal CT data (given in Houndsfield units). +A large set of medical data has been tested with those presets, but they may not suit some special cases. -Click on the "Preset" tab for using internal or custom presets. +Click on the 'Preset' tab for using internal or custom presets. \imageMacro{QmitkVolumeVisualization_InternalPresets.png,"",8.30}
    -
  • "CT Generic" is the default transferfunction that is first applied. -
  • "CT Black&White" does not use any colors, as it may be distracting on some data. -
  • "CT Cardiac" tries to increase detail on CTs from the heart. -
  • "CT Bone" emphasizes bones and shows other areas more transparent. -
  • "CT Bone (Gradient)" is like "CT Bone", but shows from other organs only the surface by using the gradient. -
  • "MR Generic" is the default transferfunction that we use on MRT data (which is not normalized like CT data). -
  • "CT Thorax small" tries to increase detail. -
  • "CT Thorax large" tries to increase detail. +
  • 'CT Generic' is the default transfer function that is first applied. +
  • 'CT Black&White' does not use any colors for the volume visualization as it may be distracting on some data. +
  • 'CT Cardiac' is well-suited for CT images containing the heart. +
  • 'CT Bone' emphasizes bones and shows other areas more transparent. +
  • 'CT Bone (Gradient)' is like 'CT Bone' but shows only the surface from other organs by using the gradient. +
  • 'MR Generic' is the default transfer function that can be used on MRT data (which is not normalized like CT data). +
  • 'CT Thorax small' is useful if only a proportion of the thorax is selected to emphasize details. +
  • 'CT Thorax large' is useful if a large proportion or the entire thorax is selected to emphasize details.
\subsection QVV_CustomPreset Saving and loading custom presets -After creating or editing a transferfunction (see \ref QVV_Editing or \ref QVV_ThresholdBell), -the custom transferfunction can be stored and later retrieved on the filesystem. -Click "Save" (respectively "Load") button to save (load) the threshold-, color- and gradient function combined in a single .xml file. - -\section QVV_ThresholdBell Interactively create transferfunctions +After creating or editing a transfer function (see \ref QVV_Editing or \ref QVV_ThresholdBell), +the custom transfer function can be stored and later retrieved on the filesystem. +Click 'Save' (respectively 'Load') button below the preset selection to save (load) the threshold-, color- and gradient function combined in a single .xml file. -Beside the possibility to directly edit the transferfunctions (\ref QVV_Editing), -a one-click generation of two commonly known shapes is given. +\section QVV_ThresholdBell Interactively create transfer functions -Both generators have two parameters, that can be modified by first clicking on the cross and then moving the mouse up/down and left/right. +Besides the possibility to directly edit the transfer functions (\ref QVV_Editing), the plugin provides two commonly known shapes to quickly generate transfer functions with a few clicks. Both generators have two parameters that can be modified by first clicking on the cross and then moving the mouse up/down and left/right. -The first parameter "center" (controlled by horizontal movement of the mouse) specifies the gravalue where the center of the shape will be located. +The first parameter 'center' (controlled by horizontal movement of the mouse) specifies the gray value where the center of the shape will be located. -The second parameter "width" (controlled by vertical movement of the mouse) specifies the width (or steepness) of the shape. +The second parameter 'width' (controlled by vertical movement of the mouse) specifies the width (or steepness) of the shape. \subsection Threshold -Click on the "Threshold" tab to active the threshold function generator. +Click on the 'Threshold' tab to activate the threshold function generator. \imageMacro{QmitkVolumeVisualization_Threshold.png,"",8.21} -A threshold shape begins with zero and raises to one across the "center" parameter. Lower widths results in steeper threshold functions. +A threshold shape begins with zero and raises to one across the 'center' parameter. Lower widths result in steeper threshold functions. \subsection Bell -Click on the "Bell" tab to active the threshold function generator. +Click on the 'Bell' tab to activate the bell-shaped threshold function generator. \imageMacro{QmitkVolumeVisualization_Bell.png,"",8.23} -A threshold shape begins with zero and raises to one at the "center" parameter and the lowers agains to zero. The "width" parameter correspondens to the width of the bell. +A threshold shape begins with zero and raises to one at the 'center' parameter and then lowers again to zero. The 'width' parameter corresponds to the width of the bell. -\section QVV_Editing Customize transferfunctions in detail +\section QVV_Editing Customize transfer functions in detail -\subsection QVV_Navigate Choosing grayvalue interval to edit +\subsection QVV_Navigate Choosing gray value interval to edit \imageMacro{QmitkVolumeVisualization_Slider.png,"",8.23} -To navigate across the grayvalue range or to zoom in some ranges use the "range"-slider. +To navigate across the gray value range or to zoom in some ranges use the 'range'-slider. All three function editors have in common following:
  • By left-clicking a new point is added.
  • By right-clicking a point is deleted.
  • By left-clicking and holding, an exisiting point can be dragged.
  • By pressing arrow keys, the currently selected point is moved. -
  • By pressing the "DELETE" key, the currently selected point is deleted. +
  • By pressing the 'DELETE' key, the currently selected point is deleted.
  • Between points the transferfunctions are linear interpolated.
-There are three transferfunctions to customize: +There are three transfer functions to customize: \subsection QVV_GO Grayvalue -> Opacity -\imageMacro{QmitkVolumeVisualization_Opacity.png,"grayvalues will be mapped to opacity.",8.04} +\imageMacro{QmitkVolumeVisualization_Opacity.png,"Gray values will be mapped to opacity.",8.04} + +An opacity of 0 means total transparent, an opacity of 1 means total opaque. The opacity editor allows changing the opacity for all gray values independently. You can alter the position of control points using your mouse. You can add control points by left-clicking on the graph. To remove a control point again you can right-click on the respective point. -An opacity of 0 means total transparent, an opacity of 1 means total opaque. \subsection QVV_GC Grayvalue -> Color -\imageMacro{QmitkVolumeVisualization_Color.png,"grayvalues will be mapped to color.",8.81} +\imageMacro{QmitkVolumeVisualization_Color.png,"Gray values will be mapped to color.",8.81} -The color transferfunction editor also allows by double-clicking a point to change its color. +The color transfer function editor also allows you to change its color by double-clicking a point. You can add color control points by left-clicking on the color bar. To remove a control point again right-click on the respective point. \subsection QVV_GGO Grayvalue and Gradient -> Opacity \imageMacro{QmitkVolumeVisualization_Gradient.png,"",8.85} -Here the influence of the gradient is controllable at specific grayvalues. - +The gradient editor allows you to change the gradient influence for all gray values independently. You can move the existing control points using your mouse. Additionally, you can add control points by left-clicking on the graph. To remove a control point again, right-click on the respective point. */ diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Bell.png b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Bell.png index 7cf0b2eed9..a4df90bd88 100644 Binary files a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Bell.png and b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Bell.png differ diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Checkboxen.png b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Checkboxen.png index f395d4cb7d..dac50d7795 100644 Binary files a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Checkboxen.png and b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Checkboxen.png differ diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Color.png b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Color.png index befafba215..4b346432fe 100644 Binary files a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Color.png and b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Color.png differ diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Gradient.png b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Gradient.png index c9bf5ef70f..d4ba5b74f9 100644 Binary files a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Gradient.png and b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Gradient.png differ diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_InternalPresets.png b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_InternalPresets.png index a769755e2a..78bd1e14c1 100644 Binary files a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_InternalPresets.png and b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_InternalPresets.png differ diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Opacity.png b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Opacity.png index c31fbc8aca..79f549f869 100644 Binary files a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Opacity.png and b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Opacity.png differ diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Overview.png b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Overview.png index 2c190a8ce2..555de51a10 100644 Binary files a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Overview.png and b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Overview.png differ diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Slider.png b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Slider.png index f65e9d6da5..c1237a7f12 100644 Binary files a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Slider.png and b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Slider.png differ diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Threshold.png b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Threshold.png index fe6fc3b653..a12fcf586f 100644 Binary files a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Threshold.png and b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Threshold.png differ diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp index 51d291a500..7ab3ab1e54 100755 --- a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp +++ b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp @@ -1,291 +1,292 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkVolumeVisualizationView.h" #include #include #include #include #include #include #include #include #include #include #include #include const std::string QmitkVolumeVisualizationView::VIEW_ID = "org.mitk.views.volumevisualization"; enum { DEFAULT_RENDERMODE = 0, RAYCAST_RENDERMODE = 1, GPU_RENDERMODE = 2 }; QmitkVolumeVisualizationView::QmitkVolumeVisualizationView() : QmitkAbstractView() , m_Controls(nullptr) { } void QmitkVolumeVisualizationView::SetFocus() { } void QmitkVolumeVisualizationView::CreateQtPartControl(QWidget* parent) { m_Controls = new Ui::QmitkVolumeVisualizationViewControls; m_Controls->setupUi(parent); m_Controls->volumeSelectionWidget->SetDataStorage(GetDataStorage()); m_Controls->volumeSelectionWidget->SetNodePredicate(mitk::NodePredicateAnd::New( mitk::TNodePredicateDataType::New(), mitk::NodePredicateOr::New(mitk::NodePredicateDimension::New(3), mitk::NodePredicateDimension::New(4)), mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object")))); - m_Controls->volumeSelectionWidget->SetSelectionIsOptional(true); m_Controls->volumeSelectionWidget->SetEmptyInfo(QString("Please select a 3D / 4D image volume")); m_Controls->volumeSelectionWidget->SetPopUpTitel(QString("Select image volume")); // Fill the transfer function presets in the generator widget std::vector names; mitk::TransferFunctionInitializer::GetPresetNames(names); for (const auto& name : names) { m_Controls->transferFunctionGeneratorWidget->AddPreset(QString::fromStdString(name)); } // see enum in vtkSmartVolumeMapper m_Controls->renderMode->addItem("Default"); m_Controls->renderMode->addItem("RayCast"); m_Controls->renderMode->addItem("GPU"); // see vtkVolumeMapper::BlendModes m_Controls->blendMode->addItem("Comp"); m_Controls->blendMode->addItem("Max"); m_Controls->blendMode->addItem("Min"); m_Controls->blendMode->addItem("Avg"); m_Controls->blendMode->addItem("Add"); connect(m_Controls->volumeSelectionWidget, &QmitkSingleNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkVolumeVisualizationView::OnCurrentSelectionChanged); connect(m_Controls->enableRenderingCB, SIGNAL(toggled(bool)), this, SLOT(OnEnableRendering(bool))); connect(m_Controls->renderMode, SIGNAL(activated(int)), this, SLOT(OnRenderMode(int))); connect(m_Controls->blendMode, SIGNAL(activated(int)), this, SLOT(OnBlendMode(int))); connect(m_Controls->transferFunctionGeneratorWidget, SIGNAL(SignalUpdateCanvas()), m_Controls->transferFunctionWidget, SLOT(OnUpdateCanvas())); connect(m_Controls->transferFunctionGeneratorWidget, SIGNAL(SignalTransferFunctionModeChanged(int)), SLOT(OnMitkInternalPreset(int))); m_Controls->enableRenderingCB->setEnabled(false); m_Controls->blendMode->setEnabled(false); m_Controls->renderMode->setEnabled(false); m_Controls->transferFunctionWidget->setEnabled(false); m_Controls->transferFunctionGeneratorWidget->setEnabled(false); + + m_Controls->volumeSelectionWidget->SetAutoSelectNewNodes(true); } void QmitkVolumeVisualizationView::OnMitkInternalPreset(int mode) { if (m_SelectedNode.IsExpired()) { return; } auto node = m_SelectedNode.Lock(); mitk::TransferFunctionProperty::Pointer transferFuncProp; if (node->GetProperty(transferFuncProp, "TransferFunction")) { // first item is only information if (--mode == -1) return; // -- Creat new TransferFunction mitk::TransferFunctionInitializer::Pointer tfInit = mitk::TransferFunctionInitializer::New(transferFuncProp->GetValue()); tfInit->SetTransferFunctionMode(mode); RequestRenderWindowUpdate(); m_Controls->transferFunctionWidget->OnUpdateCanvas(); } } void QmitkVolumeVisualizationView::OnCurrentSelectionChanged(QList nodes) { m_SelectedNode = nullptr; if (nodes.empty() || nodes.front().IsNull()) { UpdateInterface(); return; } auto selectedNode = nodes.front(); auto image = dynamic_cast(selectedNode->GetData()); if (nullptr != image) { m_SelectedNode = selectedNode; } UpdateInterface(); } void QmitkVolumeVisualizationView::OnEnableRendering(bool state) { if (m_SelectedNode.IsExpired()) { return; } m_SelectedNode.Lock()->SetProperty("volumerendering", mitk::BoolProperty::New(state)); UpdateInterface(); RequestRenderWindowUpdate(); } void QmitkVolumeVisualizationView::OnRenderMode(int mode) { if (m_SelectedNode.IsExpired()) { return; } auto selectedNode = m_SelectedNode.Lock(); bool usegpu = false; bool useray = false; if (DEFAULT_RENDERMODE == mode) { useray = true; usegpu = true; } else if (GPU_RENDERMODE == mode) { usegpu = true; } else if (RAYCAST_RENDERMODE == mode) { useray = true; } selectedNode->SetProperty("volumerendering.usegpu", mitk::BoolProperty::New(usegpu)); selectedNode->SetProperty("volumerendering.useray", mitk::BoolProperty::New(useray)); RequestRenderWindowUpdate(); } void QmitkVolumeVisualizationView::OnBlendMode(int mode) { if (m_SelectedNode.IsExpired()) { return; } auto selectedNode = m_SelectedNode.Lock(); bool usemip = false; if (vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND == mode) { usemip = true; } selectedNode->SetProperty("volumerendering.usemip", mitk::BoolProperty::New(usemip)); selectedNode->SetProperty("volumerendering.blendmode", mitk::IntProperty::New(mode)); RequestRenderWindowUpdate(); } void QmitkVolumeVisualizationView::UpdateInterface() { if (m_SelectedNode.IsExpired()) { // turnoff all m_Controls->enableRenderingCB->setChecked(false); m_Controls->enableRenderingCB->setEnabled(false); m_Controls->blendMode->setCurrentIndex(0); m_Controls->blendMode->setEnabled(false); m_Controls->renderMode->setCurrentIndex(0); m_Controls->renderMode->setEnabled(false); m_Controls->transferFunctionWidget->SetDataNode(nullptr); m_Controls->transferFunctionWidget->setEnabled(false); m_Controls->transferFunctionGeneratorWidget->SetDataNode(nullptr); m_Controls->transferFunctionGeneratorWidget->setEnabled(false); return; } bool enabled = false; auto selectedNode = m_SelectedNode.Lock(); selectedNode->GetBoolProperty("volumerendering", enabled); m_Controls->enableRenderingCB->setEnabled(true); m_Controls->enableRenderingCB->setChecked(enabled); if (!enabled) { // turnoff all except volumerendering checkbox m_Controls->blendMode->setCurrentIndex(0); m_Controls->blendMode->setEnabled(false); m_Controls->renderMode->setCurrentIndex(0); m_Controls->renderMode->setEnabled(false); m_Controls->transferFunctionWidget->SetDataNode(nullptr); m_Controls->transferFunctionWidget->setEnabled(false); m_Controls->transferFunctionGeneratorWidget->SetDataNode(nullptr); m_Controls->transferFunctionGeneratorWidget->setEnabled(false); return; } // otherwise we can activate em all m_Controls->blendMode->setEnabled(true); m_Controls->renderMode->setEnabled(true); // Determine Combo Box mode { bool usegpu = false; bool useray = false; bool usemip = false; selectedNode->GetBoolProperty("volumerendering.usegpu", usegpu); selectedNode->GetBoolProperty("volumerendering.useray", useray); selectedNode->GetBoolProperty("volumerendering.usemip", usemip); int blendMode; if (selectedNode->GetIntProperty("volumerendering.blendmode", blendMode)) m_Controls->blendMode->setCurrentIndex(blendMode); if (usemip) m_Controls->blendMode->setCurrentIndex(vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND); int mode = DEFAULT_RENDERMODE; if (useray) mode = RAYCAST_RENDERMODE; else if (usegpu) mode = GPU_RENDERMODE; m_Controls->renderMode->setCurrentIndex(mode); } m_Controls->transferFunctionWidget->SetDataNode(selectedNode); m_Controls->transferFunctionWidget->setEnabled(true); m_Controls->transferFunctionGeneratorWidget->SetDataNode(selectedNode); m_Controls->transferFunctionGeneratorWidget->setEnabled(true); } diff --git a/SuperBuild.cmake b/SuperBuild.cmake index cfe9d86ca3..683b5634cf 100644 --- a/SuperBuild.cmake +++ b/SuperBuild.cmake @@ -1,505 +1,510 @@ #----------------------------------------------------------------------------- # Convenient macro allowing to download a file #----------------------------------------------------------------------------- if(NOT MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL) set(MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL http://mitk.org/download/thirdparty) endif() macro(downloadFile url dest) file(DOWNLOAD ${url} ${dest} STATUS status) list(GET status 0 error_code) list(GET status 1 error_msg) if(error_code) message(FATAL_ERROR "error: Failed to download ${url} - ${error_msg}") endif() endmacro() #----------------------------------------------------------------------------- # MITK Prerequisites #----------------------------------------------------------------------------- if(UNIX AND NOT APPLE) include(mitkFunctionCheckPackageHeader) # Check for libxt-dev mitkFunctionCheckPackageHeader(StringDefs.h libxt-dev /usr/include/X11/) # Check for libtiff4-dev mitkFunctionCheckPackageHeader(tiff.h libtiff4-dev) endif() # We need a proper patch program. On Linux and MacOS, we assume # that "patch" is available. On Windows, we download patch.exe # if not patch program is found. find_program(PATCH_COMMAND patch) if((NOT PATCH_COMMAND OR NOT EXISTS ${PATCH_COMMAND}) AND WIN32) downloadFile(${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/patch.exe ${CMAKE_CURRENT_BINARY_DIR}/patch.exe) find_program(PATCH_COMMAND patch ${CMAKE_CURRENT_BINARY_DIR}) endif() if(NOT PATCH_COMMAND) message(FATAL_ERROR "No patch program found.") endif() #----------------------------------------------------------------------------- # ExternalProjects #----------------------------------------------------------------------------- get_property(external_projects GLOBAL PROPERTY MITK_EXTERNAL_PROJECTS) if(MITK_CTEST_SCRIPT_MODE) # Write a file containing the list of enabled external project targets. # This file can be read by a ctest script to separately build projects. set(SUPERBUILD_TARGETS ) foreach(proj ${external_projects}) if(MITK_USE_${proj}) list(APPEND SUPERBUILD_TARGETS ${proj}) endif() endforeach() file(WRITE "${CMAKE_BINARY_DIR}/SuperBuildTargets.cmake" "set(SUPERBUILD_TARGETS ${SUPERBUILD_TARGETS})") endif() # A list of "nice" external projects, playing well together with CMake set(nice_external_projects ${external_projects}) list(REMOVE_ITEM nice_external_projects Boost) foreach(proj ${nice_external_projects}) if(MITK_USE_${proj}) set(EXTERNAL_${proj}_DIR "${${proj}_DIR}" CACHE PATH "Path to ${proj} build directory") mark_as_advanced(EXTERNAL_${proj}_DIR) if(EXTERNAL_${proj}_DIR) set(${proj}_DIR ${EXTERNAL_${proj}_DIR}) endif() endif() endforeach() set(EXTERNAL_BOOST_ROOT "${BOOST_ROOT}" CACHE PATH "Path to Boost directory") mark_as_advanced(EXTERNAL_BOOST_ROOT) if(EXTERNAL_BOOST_ROOT) set(BOOST_ROOT ${EXTERNAL_BOOST_ROOT}) endif() -# Setup file for setting custom ctest vars -configure_file( - CMake/SuperbuildCTestCustom.cmake.in - ${MITK_BINARY_DIR}/CTestCustom.cmake - @ONLY -) - if(BUILD_TESTING) set(EXTERNAL_MITK_DATA_DIR "${MITK_DATA_DIR}" CACHE PATH "Path to the MITK data directory") mark_as_advanced(EXTERNAL_MITK_DATA_DIR) if(EXTERNAL_MITK_DATA_DIR) set(MITK_DATA_DIR ${EXTERNAL_MITK_DATA_DIR}) endif() endif() #----------------------------------------------------------------------------- # External project settings #----------------------------------------------------------------------------- include(ExternalProject) include(mitkMacroQueryCustomEPVars) include(mitkFunctionInstallExternalCMakeProject) include(mitkFunctionCleanExternalProject) option(MITK_AUTOCLEAN_EXTERNAL_PROJECTS "Experimental: Clean external project builds if updated" OFF) mark_as_advanced(MITK_AUTOCLEAN_EXTERNAL_PROJECTS) set(ep_prefix "${CMAKE_BINARY_DIR}/ep") set_property(DIRECTORY PROPERTY EP_PREFIX ${ep_prefix}) # Compute -G arg for configuring external projects with the same CMake generator: if(CMAKE_EXTRA_GENERATOR) set(gen "${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}") else() set(gen "${CMAKE_GENERATOR}") endif() set(gen_platform ${CMAKE_GENERATOR_PLATFORM}) # Use this value where semi-colons are needed in ep_add args: set(sep "^^") ## if(MSVC_VERSION) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /bigobj /MP") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj /MP") endif() if(MITK_USE_Boost_LIBRARIES) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBOOST_ALL_DYN_LINK") endif() # This is a workaround for passing linker flags # actually down to the linker invocation set(_cmake_required_flags_orig ${CMAKE_REQUIRED_FLAGS}) set(CMAKE_REQUIRED_FLAGS "-Wl,-rpath") mitkFunctionCheckCompilerFlags(${CMAKE_REQUIRED_FLAGS} _has_rpath_flag) set(CMAKE_REQUIRED_FLAGS ${_cmake_required_flags_orig}) set(_install_rpath_linkflag ) if(_has_rpath_flag) if(APPLE) set(_install_rpath_linkflag "-Wl,-rpath,@loader_path/../lib") else() set(_install_rpath_linkflag "-Wl,-rpath='$ORIGIN/../lib'") endif() endif() set(_install_rpath) if(APPLE) set(_install_rpath "@loader_path/../lib") elseif(UNIX) # this work for libraries as well as executables set(_install_rpath "\$ORIGIN/../lib") endif() set(ep_common_args -DCMAKE_CXX_EXTENSIONS:STRING=${CMAKE_CXX_EXTENSIONS} -DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD} -DCMAKE_CXX_STANDARD_REQUIRED:BOOL=${CMAKE_CXX_STANDARD_REQUIRED} -DCMAKE_MACOSX_RPATH:BOOL=TRUE "-DCMAKE_INSTALL_RPATH:STRING=${_install_rpath}" -DBUILD_TESTING:BOOL=OFF -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} -DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS} "-DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS} ${MITK_CXX14_FLAG}" #debug flags -DCMAKE_CXX_FLAGS_DEBUG:STRING=${CMAKE_CXX_FLAGS_DEBUG} -DCMAKE_C_FLAGS_DEBUG:STRING=${CMAKE_C_FLAGS_DEBUG} #release flags -DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE} -DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE} #relwithdebinfo -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DCMAKE_C_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_C_FLAGS_RELWITHDEBINFO} #link flags -DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_SHARED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_MODULE_LINKER_FLAGS} ) if(MSVC_VERSION) list(APPEND ep_common_args -DCMAKE_DEBUG_POSTFIX:STRING=d ) set(DCMTK_CMAKE_DEBUG_POSTFIX d) endif() set(ep_common_cache_args ) set(ep_common_cache_default_args "-DCMAKE_PREFIX_PATH:PATH=;${CMAKE_PREFIX_PATH}" "-DCMAKE_INCLUDE_PATH:PATH=${CMAKE_INCLUDE_PATH}" "-DCMAKE_LIBRARY_PATH:PATH=${CMAKE_LIBRARY_PATH}" ) # Pass the CMAKE_OSX variables to external projects if(APPLE) set(MAC_OSX_ARCHITECTURE_ARGS -DCMAKE_OSX_ARCHITECTURES:PATH=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET:PATH=${CMAKE_OSX_DEPLOYMENT_TARGET} -DCMAKE_OSX_SYSROOT:PATH=${CMAKE_OSX_SYSROOT} ) set(ep_common_args ${MAC_OSX_ARCHITECTURE_ARGS} ${ep_common_args} ) endif() set(mitk_superbuild_ep_args) set(mitk_depends ) # Include external projects include(CMakeExternals/MITKData.cmake) foreach(p ${external_projects}) set(p_hash "") set(p_file "${CMAKE_SOURCE_DIR}/CMakeExternals/${p}.cmake") if(EXISTS ${p_file}) file(MD5 ${p_file} p_hash) else() foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) get_filename_component(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIR} ABSOLUTE) set(MITK_CMAKE_EXTERNALS_EXTENSION_DIR ${MITK_EXTENSION_DIR}/CMakeExternals) set(p_file "${MITK_CMAKE_EXTERNALS_EXTENSION_DIR}/${p}.cmake") if(EXISTS ${p_file}) file(MD5 ${p_file} p_hash) break() endif() endforeach() endif() if(p_hash) set(p_hash_file "${ep_prefix}/tmp/${p}-hash.txt") if(MITK_AUTOCLEAN_EXTERNAL_PROJECTS) if(EXISTS ${p_hash_file}) file(READ ${p_hash_file} p_prev_hash) if(NOT p_hash STREQUAL p_prev_hash) mitkCleanExternalProject(${p}) endif() endif() endif() file(WRITE ${p_hash_file} ${p_hash}) endif() include(${p_file} OPTIONAL) list(APPEND mitk_superbuild_ep_args -DMITK_USE_${p}:BOOL=${MITK_USE_${p}} ) get_property(_package GLOBAL PROPERTY MITK_${p}_PACKAGE) if(_package) list(APPEND mitk_superbuild_ep_args -D${p}_DIR:PATH=${${p}_DIR}) endif() list(APPEND mitk_depends ${${p}_DEPENDS}) endforeach() if (SWIG_EXECUTABLE) list(APPEND mitk_superbuild_ep_args -DSWIG_EXECUTABLE=${SWIG_EXECUTABLE}) endif() #----------------------------------------------------------------------------- # Set superbuild boolean args #----------------------------------------------------------------------------- set(mitk_cmake_boolean_args BUILD_SHARED_LIBS WITH_COVERAGE BUILD_TESTING MITK_BUILD_ALL_PLUGINS MITK_BUILD_ALL_APPS MITK_BUILD_EXAMPLES MITK_USE_Qt5 MITK_USE_SYSTEM_Boost MITK_USE_BLUEBERRY MITK_USE_OpenCL MITK_USE_OpenMP MITK_ENABLE_PIC_READER ) #----------------------------------------------------------------------------- # Create the final variable containing superbuild boolean args #----------------------------------------------------------------------------- set(mitk_superbuild_boolean_args) foreach(mitk_cmake_arg ${mitk_cmake_boolean_args}) list(APPEND mitk_superbuild_boolean_args -D${mitk_cmake_arg}:BOOL=${${mitk_cmake_arg}}) endforeach() if(MITK_BUILD_ALL_PLUGINS) list(APPEND mitk_superbuild_boolean_args -DBLUEBERRY_BUILD_ALL_PLUGINS:BOOL=ON) endif() #----------------------------------------------------------------------------- # MITK Utilities #----------------------------------------------------------------------------- set(proj MITK-Utilities) ExternalProject_Add(${proj} DOWNLOAD_COMMAND "" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" DEPENDS ${mitk_depends} ) #----------------------------------------------------------------------------- # Additional MITK CXX/C Flags #----------------------------------------------------------------------------- set(MITK_ADDITIONAL_C_FLAGS "" CACHE STRING "Additional C Flags for MITK") set(MITK_ADDITIONAL_C_FLAGS_RELEASE "" CACHE STRING "Additional Release C Flags for MITK") set(MITK_ADDITIONAL_C_FLAGS_DEBUG "" CACHE STRING "Additional Debug C Flags for MITK") mark_as_advanced(MITK_ADDITIONAL_C_FLAGS MITK_ADDITIONAL_C_FLAGS_DEBUG MITK_ADDITIONAL_C_FLAGS_RELEASE) set(MITK_ADDITIONAL_CXX_FLAGS "" CACHE STRING "Additional CXX Flags for MITK") set(MITK_ADDITIONAL_CXX_FLAGS_RELEASE "" CACHE STRING "Additional Release CXX Flags for MITK") set(MITK_ADDITIONAL_CXX_FLAGS_DEBUG "" CACHE STRING "Additional Debug CXX Flags for MITK") mark_as_advanced(MITK_ADDITIONAL_CXX_FLAGS MITK_ADDITIONAL_CXX_FLAGS_DEBUG MITK_ADDITIONAL_CXX_FLAGS_RELEASE) set(MITK_ADDITIONAL_EXE_LINKER_FLAGS "" CACHE STRING "Additional exe linker flags for MITK") set(MITK_ADDITIONAL_SHARED_LINKER_FLAGS "" CACHE STRING "Additional shared linker flags for MITK") set(MITK_ADDITIONAL_MODULE_LINKER_FLAGS "" CACHE STRING "Additional module linker flags for MITK") mark_as_advanced(MITK_ADDITIONAL_EXE_LINKER_FLAGS MITK_ADDITIONAL_SHARED_LINKER_FLAGS MITK_ADDITIONAL_MODULE_LINKER_FLAGS) #----------------------------------------------------------------------------- # MITK Configure #----------------------------------------------------------------------------- if(MITK_INITIAL_CACHE_FILE) set(mitk_initial_cache_arg -C "${MITK_INITIAL_CACHE_FILE}") endif() set(mitk_optional_cache_args ) foreach(type RUNTIME ARCHIVE LIBRARY) if(DEFINED CTK_PLUGIN_${type}_OUTPUT_DIRECTORY) list(APPEND mitk_optional_cache_args -DCTK_PLUGIN_${type}_OUTPUT_DIRECTORY:PATH=${CTK_PLUGIN_${type}_OUTPUT_DIRECTORY}) endif() endforeach() # Optional python variables if(MITK_USE_Python3) list(APPEND mitk_optional_cache_args -DMITK_USE_Python3:BOOL=${MITK_USE_Python3} "-DPython3_EXECUTABLE:FILEPATH=${Python3_EXECUTABLE}" "-DPython3_INCLUDE_DIR:PATH=${Python3_INCLUDE_DIRS}" "-DPython3_LIBRARY:FILEPATH=${Python3_LIBRARY}" "-DPython3_STDLIB:FILEPATH=${Python3_STDLIB}" "-DPython3_SITELIB:FILEPATH=${Python3_SITELIB}" ) endif() if(OPENSSL_ROOT_DIR) list(APPEND mitk_optional_cache_args "-DOPENSSL_ROOT_DIR:PATH=${OPENSSL_ROOT_DIR}" ) endif() if(CMAKE_FRAMEWORK_PATH) list(APPEND mitk_optional_cache_args "-DCMAKE_FRAMEWORK_PATH:PATH=${CMAKE_FRAMEWORK_PATH}" ) endif() if(Eigen_INCLUDE_DIR) list(APPEND mitk_optional_cache_args -DEigen_INCLUDE_DIR:PATH=${Eigen_INCLUDE_DIR} ) endif() # Optional pass through of Doxygen if(DOXYGEN_EXECUTABLE) list(APPEND mitk_optional_cache_args -DDOXYGEN_EXECUTABLE:FILEPATH=${DOXYGEN_EXECUTABLE} ) endif() +if(MITK_DOXYGEN_BUILD_ALWAYS) + list(APPEND mitk_optional_cache_args + -DMITK_DOXYGEN_BUILD_ALWAYS:BOOL=${MITK_DOXYGEN_BUILD_ALWAYS} + ) +endif() + +if(BLUEBERRY_DOC_TOOLS_DIR) + list(APPEND mitk_optional_cache_args + "-DBLUEBERRY_DOC_TOOLS_DIR:PATH=${BLUEBERRY_DOC_TOOLS_DIR}" + ) +endif() + set(proj MITK-Configure) ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} DOWNLOAD_COMMAND "" CMAKE_GENERATOR ${gen} CMAKE_GENERATOR_PLATFORM ${gen_platform} CMAKE_CACHE_ARGS # --------------- Build options ---------------- -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} "-DCMAKE_PREFIX_PATH:PATH=${ep_prefix};${CMAKE_PREFIX_PATH}" "-DCMAKE_LIBRARY_PATH:PATH=${CMAKE_LIBRARY_PATH}" "-DCMAKE_INCLUDE_PATH:PATH=${CMAKE_INCLUDE_PATH}" # --------------- Compile options ---------------- -DCMAKE_CXX_EXTENSIONS:STRING=${CMAKE_CXX_EXTENSIONS} -DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD} -DCMAKE_CXX_STANDARD_REQUIRED:BOOL=${CMAKE_CXX_STANDARD_REQUIRED} -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS} ${MITK_ADDITIONAL_C_FLAGS}" "-DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS} ${MITK_ADDITIONAL_CXX_FLAGS}" # debug flags "-DCMAKE_CXX_FLAGS_DEBUG:STRING=${CMAKE_CXX_FLAGS_DEBUG} ${MITK_ADDITIONAL_CXX_FLAGS_DEBUG}" "-DCMAKE_C_FLAGS_DEBUG:STRING=${CMAKE_C_FLAGS_DEBUG} ${MITK_ADDITIONAL_C_FLAGS_DEBUG}" # release flags "-DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE} ${MITK_ADDITIONAL_CXX_FLAGS_RELEASE}" "-DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE} ${MITK_ADDITIONAL_C_FLAGS_RELEASE}" # relwithdebinfo -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DCMAKE_C_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_C_FLAGS_RELWITHDEBINFO} # link flags "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS} ${MITK_ADDITIONAL_EXE_LINKER_FLAGS}" "-DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_SHARED_LINKER_FLAGS} ${MITK_ADDITIONAL_SHARED_LINKER_FLAGS}" "-DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_MODULE_LINKER_FLAGS} ${MITK_ADDITIONAL_MODULE_LINKER_FLAGS}" # Output directories -DMITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY:PATH=${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY} -DMITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY:PATH=${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY} -DMITK_CMAKE_ARCHIVE_OUTPUT_DIRECTORY:PATH=${MITK_CMAKE_ARCHIVE_OUTPUT_DIRECTORY} # ------------- Boolean build options -------------- ${mitk_superbuild_boolean_args} ${mitk_optional_cache_args} -DMITK_USE_SUPERBUILD:BOOL=OFF -DMITK_BUILD_CONFIGURATION:STRING=${MITK_BUILD_CONFIGURATION} -DMITK_FAST_TESTING:BOOL=${MITK_FAST_TESTING} -DMITK_XVFB_TESTING:BOOL=${MITK_XVFB_TESTING} -DMITK_XVFB_TESTING_COMMAND:STRING=${MITK_XVFB_TESTING_COMMAND} -DCTEST_USE_LAUNCHERS:BOOL=${CTEST_USE_LAUNCHERS} # ----------------- Miscellaneous --------------- -DCMAKE_LIBRARY_PATH:PATH=${CMAKE_LIBRARY_PATH} -DCMAKE_INCLUDE_PATH:PATH=${CMAKE_INCLUDE_PATH} -DMITK_CTEST_SCRIPT_MODE:STRING=${MITK_CTEST_SCRIPT_MODE} -DMITK_SUPERBUILD_BINARY_DIR:PATH=${MITK_BINARY_DIR} -DMITK_MODULES_TO_BUILD:INTERNAL=${MITK_MODULES_TO_BUILD} -DMITK_WHITELIST:STRING=${MITK_WHITELIST} -DMITK_WHITELISTS_EXTERNAL_PATH:STRING=${MITK_WHITELISTS_EXTERNAL_PATH} -DMITK_WHITELISTS_INTERNAL_PATH:STRING=${MITK_WHITELISTS_INTERNAL_PATH} -DMITK_EXTENSION_DIRS:STRING=${MITK_EXTENSION_DIRS} -DMITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES} -DMITK_ACCESSBYITK_FLOATING_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES} -DMITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES} -DMITK_ACCESSBYITK_VECTOR_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES} -DMITK_ACCESSBYITK_DIMENSIONS:STRING=${MITK_ACCESSBYITK_DIMENSIONS} -DMITK_CUSTOM_REVISION_DESC:STRING=${MITK_CUSTOM_REVISION_DESC} # --------------- External project options --------------- -DMITK_DATA_DIR:PATH=${MITK_DATA_DIR} -DMITK_EXTERNAL_PROJECT_PREFIX:PATH=${ep_prefix} -DCppMicroServices_DIR:PATH=${CppMicroServices_DIR} -DDCMTK_CMAKE_DEBUG_POSTFIX:STRING=${DCMTK_CMAKE_DEBUG_POSTFIX} -DBOOST_ROOT:PATH=${BOOST_ROOT} -DBOOST_LIBRARYDIR:PATH=${BOOST_LIBRARYDIR} -DMITK_USE_Boost_LIBRARIES:STRING=${MITK_USE_Boost_LIBRARIES} -DQt5_DIR:PATH=${Qt5_DIR} CMAKE_ARGS ${mitk_initial_cache_arg} ${MAC_OSX_ARCHITECTURE_ARGS} ${mitk_superbuild_ep_args} SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} BINARY_DIR ${CMAKE_BINARY_DIR}/MITK-build BUILD_COMMAND "" INSTALL_COMMAND "" DEPENDS MITK-Utilities ) mitkFunctionInstallExternalCMakeProject(${proj}) #----------------------------------------------------------------------------- # MITK #----------------------------------------------------------------------------- if(CMAKE_GENERATOR MATCHES ".*Makefiles.*") set(mitk_build_cmd "$(MAKE)") else() set(mitk_build_cmd ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/MITK-build --config ${CMAKE_CFG_INTDIR}) endif() if(NOT DEFINED SUPERBUILD_EXCLUDE_MITKBUILD_TARGET OR NOT SUPERBUILD_EXCLUDE_MITKBUILD_TARGET) set(MITKBUILD_TARGET_ALL_OPTION "ALL") else() set(MITKBUILD_TARGET_ALL_OPTION "") endif() add_custom_target(MITK-build ${MITKBUILD_TARGET_ALL_OPTION} COMMAND ${mitk_build_cmd} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/MITK-build DEPENDS MITK-Configure ) #----------------------------------------------------------------------------- # Custom target allowing to drive the build of the MITK project itself #----------------------------------------------------------------------------- add_custom_target(MITK COMMAND ${mitk_build_cmd} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/MITK-build )